이전 글에서는 Digester에 대한 기본적인 소개를 했고, Digester의 기본 사용법을 이미 이해했습니다. 다음으로, 이 글에서는 주로 다음 내용을 다루겠습니다.
Rule 모듈. 바인딩, RulesModule 인터페이스 구현 클래스를 정의하여 규칙의 사전 바인딩을 완료하고 런타임에 이를 재사용합니다.
xml을 비동기식으로 구문 분석
${sys.user}
과 같은 XML의 변수를 구문 분석합니다. 매개변수의 생성자 메소드와 함께 사용하면 객체가 생성되고 매개변수는 xml 노드 데이터에서 나옵니다
이전에 Digester를 사용하는 기본 프로세스는 규칙을 바인딩할 때마다 규칙을 바인딩하는 것이었습니다. 프로그램을 실행한 후 파싱합니다 ;
실제로 Digester의 파싱 프로세스를 변경하고 시작 시 규칙 세트를 미리 정의한 다음 작업 중에 미리 정의된 규칙을 재사용할 수 있습니다.
이것은 약간의 시간이 걸릴 수 있습니다. 막연하게, 다음 웹 애플리케이션 시나리오를 보면 더 깊은 이해가 있을 것입니다.
웹 개발에 익숙한 사람들은 서블릿을 알아야 하므로 여기서는 자세히 설명하지 않겠습니다. 아래와 같이 EmployeeServlet이 있습니다.
서블릿은 싱글톤이고 Digester는 스레드로부터 안전하지 않기 때문에 스레드 안전을 보장하기 위해 요청할 때마다 새로운 Digester 객체를 생성합니다.
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을 사용하여 해결할 수 있습니다. 코드 재사용이 없다는 문제는 아래와 같이 EmployeeRuleSet 규칙 집합 구현을 정의합니다. RuleSetInterface:
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" ); } }그런 다음 서블릿에서 다음과 같이 사용합니다.
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" ) ) ); ... } }분명히 이것에는 아무런 문제가 없습니다. (사실 개인적으로 private 메소드를 직접 작성하고 규칙을 추가하는 것이 더 낫다고 생각합니다. ㅎㅎ) 하지만 다음과 같은 단점이 있습니다.
digester에 바인딩할 뿐입니다.
digester객체는 클라이언트와 긴밀하게 결합되어 있으며 클라이언트에 의해 직접 생성됩니다.
RulesModule 인터페이스 구현 클래스 정의:
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") ) ); ... } }
규칙 바인딩의 API는 매우 의미 있고 사용하기 쉽고 읽기 쉽습니다.
digester 개체는 클라이언트에 의해 생성되지 않습니다. 하지만 DigesterLoader에 의해 생성됨
인터페이스 외에도 digester 자체는 FromXmlRulesModule 클래스 이미 RulesModule인터페이스를 구현했습니다. 다음과 같이 사용할 수 있습니다. 먼저 코딩을 시작합니다. RulesModule 인터페이스 구현 클래스를 정의합니다. DigesterLoader loader = DigesterLoader.newLoader( .getResource( "myrule.xml"
클라이언트 클래스 작성: <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(); } }xml 변수 구문 분석-대체 추상 클래스이것은 비교적 간단합니다. VariableSubstitutor 구현 클래스, 사용자 변환 속성 및 본문을 정의합니다. 는 아래와 같은 xml입니다(${type}은 변수임).
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(); } } }
那么可以这样解析如上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(); } } }
结果打印:
위 내용은 아파치 커먼즈 다이제스터의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!