前回の記事で Digester の基本的な使い方を説明しました。次に、この記事では主に次の内容を学習していきます。 binding を使用して、RulesModule インターフェース実装クラスを定義してルールの事前バインドを完了し、実行時にそれを再利用します
xml を非同期的に解析します
${sys.user} などの XML 内の変数を解析します
パラメーターのコンストラクター メソッドでオブジェクトが作成され、パラメーターは XML ノード データから取得されます
Rules モジュールは事前にバインドされています - RulesModule インターフェイス
これは少し曖昧かもしれませんが、次の Web アプリケーション シナリオを参照すると、より深く理解できるはずです。
サーブレット シナリオの例
Web 開発に精通している人はサーブレットについて知っているはずなので、ここでは詳しく説明しません。以下に示すように、
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 ルール セット実装を定義します。
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" ) ) ); ... } }
オブジェクトはクライアントと高度に結合されており、クライアントによって直接作成されます
各解析呼び出しの前に、ルールを繰り返しバインドする必要があります
バインドされているため、セマンティクスが非常に貧弱で、可読性も良くありません。
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") ) );
...
}
}
RulesModule
ルール バインディングの API は非常にセマンティックで、使いやすく、可読性が高くなります。 ルール バインディングの設定は完了するために起動フェーズに移行します。DigesterLoader
によって作成されましたExcept クラスはRulesModuleを実装しますインターフェースに加えて、ダイジェスター自体がを提供します
XmlRulesModule クラス: 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 と RulesModule を使用します。実装クラス; クライアントクラス:
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(); } } }
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(); } } }
结果打印:
以上がApache Commons Digesterの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。