Maison >Java >javaDidacticiel >Digesteur Apache Commons
L'article précédent a donné une introduction de base à Digester, et nous avons déjà compris l'utilisation de base de Digester. Ensuite, nous continuerons à apprendre ses fonctionnalités associées. Cet article couvre principalement le contenu suivant :
Liaison du module de règles, complétez la pré-liaison des règles en définissant une classe d'implémentation d'interface RulesModule et réutilisez-la au moment de l'exécution
Analyse asynchrone xml
Analyser les variables en XML, telles que ${sys.user}
Utiliser le constructeur avec des paramètres pour créer des objets, et les paramètres proviennent des données du nœud XML
Avant cela, notre processus de base d'utilisation de Digester consistait à lier les règles à chaque fois que le programme est en cours d'exécution puis les analyse ;
En fait, nous pouvons modifier le processus d'analyse de Digester, prédéfinir l'ensemble de règles au démarrage, puis réutiliser les règles prédéfinies au moment de l'exécution
Peut-être ; c'est un peu vague, vous pouvez jeter un œil au scénario d'application Web suivant et vous devriez avoir une compréhension plus approfondie
Ceux qui sont familiers avec le développement Web devraient déjà le faire ; Je connais le servlet, donc je n'entrerai pas dans les détails ici. Maintenant, supposons qu'il y ait un EmployeeServlet, comme indiqué ci-dessous :
Puisque le servlet est un singleton et que le Digester n'est pas un thread-. sûr, nous en émettrons un nouveau à chaque fois qu'il sera demandé. Un objet Dgester pour assurer la sécurité des threads, écrit comme suit :
public class EmployeeServlet extends HttpServlet {public void doGet(HttpServletRequest req, HttpServletResponse res)throws ServletException, IOException { Digester digester = new Digester(); digester.setNamespaceAware( true ); digester.setXIncludeAware( true ); digester.addObjectCreate( "employee", Employee.class ); digester.addCallMethod( "employee/firstName", "setFirstName", 0 ); digester.addCallMethod( "employee/lastName", "setLastName", 0 ); digester.addObjectCreate( "employee/address", Address.class ); digester.addCallMethod( "employee/address/type", "setType", 0 ); digester.addCallMethod( "employee/address/city", "setCity", 0 ); digester.addCallMethod( "employee/address/state", "setState", 0 ); digester.addSetNext( "employee/address", "addAddress" ); Employee employee = digester.parse( openStream( req.getParameter( "employeeId" ) ) ); ... }
On peut facilement trouver le inconvénients du programme ci-dessus : le code n'est pas réutilisé à chaque fois. Chaque requête doit être liée à la règle à plusieurs reprises
Cependant, nous pouvons utiliser RuleSet pour résoudre le problème de l'absence de réutilisation de code ; illustré ci-dessous, définissez une EmployeeRuleSet implémentation d'un ensemble de règlesRuleSetInterface :
public class EmployeeRuleSet implements RuleSet {public void addRuleInstances( Digester digester ) { digester.addObjectCreate( "employee", Employee.class ); digester.addCallMethod( "employee/firstName", "setFirstName", 0 ); digester.addCallMethod( "employee/lastName", "setLastName", 0 ); digester.addObjectCreate( "employee/address", Address.class ); digester.addCallMethod( "employee/address/type", "setType", 0 ); digester.addCallMethod( "employee/address/city", "setCity", 0 ); digester.addCallMethod( "employee/address/state", "setState", 0 ); digester.addSetNext( "employee/address", "addAddress" ); } }
Ensuite, utilisez-la comme ceci dans le servlet :
public class EmployeeServlet extends HttpServlet {private final RuleSet employeeRuleSet = new EmployeeRuleSet();public void doGet(HttpServletRequest req, HttpServletResponse res)throws ServletException, IOException { Digester digester = new Digester(); digester.setNamespaceAware( true ); digester.setXIncludeAware( true ); employeeRuleSet.addRuleInstances( digester ); Employee employee = digester.parse( openStream( req.getParameter( "employeeId" ) ) ); ... } }
Évidemment, il n'y a aucun moyen de faire cela. Mauvais (en fait, je pense personnellement qu'il vaut mieux écrire une méthode privée et ajouter des règles directement, haha), mais elle a ce qui suit inconvénients :
RuleSet n'est pas réellement une configuration, c'est juste pour Le digesteur est simplement lié aux règles
digesteurL'objet est fortement couplé au client et est créé directement par le client ;
Avant chaque appel d'analyse , les règles contraignantes doivent être répétées
Lors de la liaison des règles, mauvaise sémantique et mauvaise lisibilité
class EmployeeModuleextends AbstractRulesModule { @Overrideprotected void configure() { forPattern( "employee" ).createObject().ofType( Employee.class ); forPattern( "employee/firstName" ).setBeanProperty(); forPattern( "employee/lastName" ).setBeanProperty(); forPattern( "employee/address" ).createObject().ofType( Address.class ).then().setNext( "addAddress"); forPattern( "employee/address/type" ).setBeanProperty(); forPattern( "employee/address/city" ).setBeanProperty(); forPattern( "employee/address/state" ).setBeanProperty(); } }
public class EmployeeServletextends HttpServlet {private final DigesterLoader loader = newLoader( new EmployeeModule() ) .setNamespaceAware( true ) .setXIncludeAware( true );public void doGet(HttpServletRequest req, HttpServletResponse res)throws ServletException, IOException { Digester digester = loader.newDigester() Employee employee = digester.parse( openStream( req.getParameter("employeeId") ) ); ... } }
RulesModuleL'API pour la liaison de règles est très sémantique, facile à utiliser et très lisible ; La configuration de la liaison des règles est déplacée vers la phase de démarrage
DigesterLoader; FromXmlRulesModule
classe FromXmlRulesModule a déjà implémenté le RulesModule Nous pouvons utiliser comme ceci : Exemple complet
DigesterLoader loader = DigesterLoader.newLoader( .getResource( "myrule.xml"
Démarrez l'encodage, commencez par définir la classe d'implémentation d'interface A RulesModule :
<employee> <firstName>Pi</firstName> <lastName>Chen</lastName> <address> <type>CITY</type> <city>HangZhou</city> <state>2</state> </address> </employee>
Écrire la classe client :
package apache.commons.digester3.example.rulesbinder.module;import org.apache.commons.digester3.binder.AbstractRulesModule;import apache.commons.digester3.example.rulesbinder.pojo.Address;import apache.commons.digester3.example.rulesbinder.pojo.Employee;/** * * * @author * @version 2017年6月5日 */public class EmployeeModule extends AbstractRulesModule { @Overrideprotected void configure() { forPattern("employee").createObject().ofType(Employee.class); forPattern("employee/firstName").setBeanProperty(); forPattern("employee/lastName").setBeanProperty(); forPattern("employee/address").createObject().ofType(Address.class).then().setNext("addAddress"); forPattern("employee/address/type").setBeanProperty(); forPattern("employee/address/city").setBeanProperty(); forPattern("employee/address/state").setBeanProperty(); } }
Impression des résultats :
package apache.commons.digester3.example.rulesbinder;import java.io.IOException;import org.apache.commons.digester3.Digester;import org.apache.commons.digester3.binder.DigesterLoader;import org.xml.sax.SAXException;import apache.commons.digester3.example.rulesbinder.module.EmployeeModule;import apache.commons.digester3.example.rulesbinder.pojo.Address;import apache.commons.digester3.example.rulesbinder.pojo.Employee;import apache.commons.digester3.example.simpletest.ExampleMain;/** * * * @author * @version 2017年6月5日 */public class DigesterLoaderMain {private static DigesterLoader dl = DigesterLoader.newLoader(new EmployeeModule()) .setNamespaceAware(false);public static void main(String[] args) {try { Digester digester = dl.newDigester(); Employee employee = digester.parse(ExampleMain.class.getClassLoader().getResourceAsStream("employee.xml")); System.out.print(employee.getFirstName() + " "); System.out.print(employee.getLastName() + ", ");for (Address a : employee.getAddressList()) { System.out.print(a.getType() + ", "); System.out.print(a.getCity() + ", "); System.out.println(a.getState()); } } catch (IOException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } } }
Suivez l'exemple précédent et utilisez le même XML et le même RulesModule pour implémenter la classe Classe client :
.
Classe abstraite d'analyse de variables XML-Substitutor
package apache.commons.digester3.example.rulesbinder;import java.util.concurrent.ExecutionException;import java.util.concurrent.Executors;import java.util.concurrent.Future;import org.apache.commons.digester3.Digester;import org.apache.commons.digester3.binder.DigesterLoader;import apache.commons.digester3.example.rulesbinder.module.EmployeeModule;import apache.commons.digester3.example.rulesbinder.pojo.Address;import apache.commons.digester3.example.rulesbinder.pojo.Employee;import apache.commons.digester3.example.simpletest.ExampleMain;/** * * @author * @version 2017年6月5日 */public class AsyncParseMain {private static DigesterLoader dl = DigesterLoader.newLoader(new EmployeeModule()) .setNamespaceAware(false).setExecutorService(Executors.newSingleThreadExecutor());public static void main(String[] args) {try { Digester digester = dl.newDigester(); Future<Employee> future = digester.asyncParse(ExampleMain.class.getClassLoader().getResourceAsStream("employee.xml")); Employee employee = future.get(); System.out.print(employee.getFirstName() + " "); System.out.print(employee.getLastName() + ", ");for (Address a : employee.getAddressList()) { System.out.print(a.getType() + ", "); System.out.print(a.getCity() + ", "); System.out.println(a.getState()); } } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }
那么可以这样解析如上xml:
package apache.commons.digester3.example.rulesbinder;import java.io.IOException;import java.util.HashMap;import java.util.Map;import org.apache.commons.digester3.Digester;import org.apache.commons.digester3.Substitutor;import org.apache.commons.digester3.binder.DigesterLoader;import org.apache.commons.digester3.substitution.MultiVariableExpander;import org.apache.commons.digester3.substitution.VariableSubstitutor;import org.xml.sax.SAXException;import apache.commons.digester3.example.rulesbinder.module.EmployeeModule;import apache.commons.digester3.example.rulesbinder.pojo.Address;import apache.commons.digester3.example.rulesbinder.pojo.Employee;import apache.commons.digester3.example.simpletest.ExampleMain;/** * * * @author * @version 2017年6月5日 */public class SubstitutionMain {private static DigesterLoader dl = DigesterLoader.newLoader(new EmployeeModule()) .setNamespaceAware(false);public static void main(String[] args) {try{// set up the variables the input xml can referenceMap<String, Object> vars = new HashMap<String, Object>(); vars.put("user.name", "me"); vars.put("type", "boss");// map ${varname} to the entries in the var mapMultiVariableExpander expander = new MultiVariableExpander(); expander.addSource("$", vars);// allow expansion in both xml attributes and element textSubstitutor substitutor = new VariableSubstitutor(expander); Digester digester = dl.newDigester(); digester.setSubstitutor(substitutor); Employee employee = digester .parse(ExampleMain.class.getClassLoader().getResourceAsStream("employee$.xml")); System.out.print(employee.getFirstName() + " "); System.out.print(employee.getLastName() + ", ");for (Address a : employee.getAddressList()) { System.out.print(a.getType() + ", "); System.out.print(a.getCity() + ", "); System.out.println(a.getState()); } }catch (IOException e) { e.printStackTrace(); }catch (SAXException e) { e.printStackTrace(); } } }
简单地说,就是在使用ObjectCreateRule规则的时候,能够传递xml中的值(属性值、body值)给构造方法使用;
如下是一个待解析的xml:
<root> <bean super="false"><rate>9.99</rate> </bean></root>
那么可以这样解析:
package apache.commons.digester3.example.rulesbinder;import java.io.IOException;import org.apache.commons.digester3.Digester;import org.apache.commons.digester3.ObjectCreateRule;import org.apache.commons.digester3.binder.DigesterLoader;import org.xml.sax.SAXException;import apache.commons.digester3.example.rulesbinder.module.EmployeeModule;import apache.commons.digester3.example.rulesbinder.pojo.Address;import apache.commons.digester3.example.rulesbinder.pojo.Employee;import apache.commons.digester3.example.rulesbinder.pojo.MyBean;import apache.commons.digester3.example.simpletest.ExampleMain;/** * * * @author * @version 2017年6月5日 */public class ConstructorParamsMain {public static void main(String[] args) {try{ ObjectCreateRule createRule = new ObjectCreateRule(MyBean.class); createRule.setConstructorArgumentTypes(Double.class, Boolean.class); Digester digester = new Digester(); digester.addRule("root/bean", createRule); digester.addCallParam("root/bean", 1, "super"); digester.addCallParam("root/bean/rate", 0); MyBean myBean = digester.parse(ConstructorParamsMain.class.getClassLoader() .getResourceAsStream("constructor-params.xml")); System.out.println(myBean.getRate()); System.out.println(myBean.isSuper_()); }catch (IOException e) { e.printStackTrace(); }catch (SAXException e) { e.printStackTrace(); } } }
结果打印:
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!