Heim >Java >javaLernprogramm >Apache Commons Digester
Der vorherige Artikel gab eine grundlegende Einführung in Digester, und wir haben die grundlegende Verwendung von Digester bereits verstanden. Als Nächstes werden wir die damit verbundenen Funktionen weiter erlernen.
Regelmodulbindung, Vervollständigen Sie die Vorbindung von Regeln durch Definieren einer RulesModule-Schnittstellenimplementierungsklasse und verwenden Sie sie zur Laufzeit wieder
Asynchrone Analyse xml
Variablen in XML analysieren, z. B. ${sys.user}
Verwenden Sie den Konstruktor mit Parametern, um Objekte und Parameter zu erstellen stammen aus XML-Knotendaten
Zuvor bestand unser grundlegender Prozess bei der Verwendung von Digester darin, die Regeln bei jedem Programmstart zu binden läuft und analysiert sie dann ;
Tatsächlich können wir den Parsing-Prozess von Digester ändern, den Regelsatz beim Start vordefinieren und die vordefinierten Regeln dann zur Laufzeit wiederverwenden
Vielleicht Das ist etwas vage. Sie können sich das folgende Webanwendungsszenario ansehen und sollten ein tieferes Verständnis haben.
Wer mit der Webentwicklung vertraut ist, sollte dies bereits tun Ich kenne das Servlet, daher werde ich hier nicht auf Details eingehen. Angenommen, es gibt ein EmployeeServlet, wie unten gezeigt:
Da das Servlet ein Singleton und der Digester kein Thread ist. sicher, wir werden bei jeder Anforderung ein neues Dgester-Objekt ausgeben, um die Thread-Sicherheit zu gewährleisten, das wie folgt geschrieben ist:
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" ) ) ); ... }
RuleSet
verwenden, um das Problem der Nicht-Wiederverwendung zu lösen Wie unten gezeigt, definieren Sie eine EmployeeRuleSet-RegelsatzimplementierungRuleSetSchnittstelle:
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" ); } }Dann verwenden Sie es wie folgt im 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" ) ) ); ... } }Natürlich gibt es keine Möglichkeit, dies falsch zu machen (tatsächlich denke ich persönlich, dass es besser ist, direkt eine private Methode zu schreiben und Regeln hinzuzufügen, haha), aber es hat Folgendes Nachteile:
digesterDas Objekt ist stark mit dem Client gekoppelt und wird direkt vom Client erstellt;
Vor jedem Parsing-Aufruf , die verbindlichen Regeln müssen wiederholt werden
Bei der Bindung der Regeln ist die Semantik schlecht und die Lesbarkeit schlecht; 🎜>Was ist also die beste Vorgehensweise? Verwenden Sie die RulesModule-Schnittstelle, um beim Start Regeln vorab zu binden, und verwenden Sie dann beim Ausführen einfach die vorgebundenen Regeln wieder, wie unten gezeigt: Definieren Sie eine RulesModule-Schnittstellenimplementierungsklasse:
Dann wird das Servlet wie folgt verwendet:
Die Vorteile sind offensichtlich:
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(); } }RulesModule
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") ) ); ... } }
Das Digester-Objekt wird nicht vom Client erstellt, sondern
DigesterLoader;
Zusätzlich zum Schreiben Ihrer eigenen Klasse Implementieren Sie die RulesModule-Schnittstelle, digester selbst stellt eine FromXmlRulesModule-Klasse
Vollständiges BeispielAngenommen, es gibt eine XML-Datei wie folgt, die analysiert werden sollStarten Sie die Codierung. Definieren Sie zunächst eine RulesModule-Schnittstellenimplementierungsklasse: Client-Klasse schreiben:
DigesterLoader loader = DigesterLoader.newLoader( .getResource( "myrule.xml"
Pi Chen, CITY, HangZhou, 2
<employee> <firstName>Pi</firstName> <lastName>Chen</lastName> <address> <type>CITY</type> <city>HangZhou</city> <state>2</state> </address> </employee>
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(); } }Objekte nicht threadsicher sind . Das Folgende ist ein einfaches API-Verwendungsbeispiel:
Folgen Sie dem vorherigen Beispiel und verwenden Sie dasselbe XML und RulesModule, um die Klasse zu implementieren;
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(); } } }
Angenommen, es gibt eine XML-Datei wie unten gezeigt (wobei ${type} eine Variable ist):
那么可以这样解析如上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(); } } }
结果打印:
Das obige ist der detaillierte Inhalt vonApache Commons Digester. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!