>  기사  >  Java  >  아파치 커먼즈 다이제스터

아파치 커먼즈 다이제스터

巴扎黑
巴扎黑원래의
2017-06-26 09:17:071517검색

머리말

이전 글에서는 Digester에 대한 기본적인 소개를 했고, Digester의 기본 사용법을 이미 이해했습니다. 다음으로, 이 글에서는 주로 다음 내용을 다루겠습니다.

  1. Rule 모듈. 바인딩, RulesModule 인터페이스 구현 클래스를 정의하여 규칙의 사전 바인딩을 완료하고 런타임에 이를 재사용합니다.

  2. xml을 비동기식으로 구문 분석

  3. ${sys.user}

  4. 과 같은 XML의 변수를 구문 분석합니다. 매개변수의 생성자 메소드와 함께 사용하면 객체가 생성되고 매개변수는 xml 노드 데이터에서 나옵니다

Rules 모듈이 미리 바인딩되어 있습니다 - RulesModule 인터페이스

이전에 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 메소드를 직접 작성하고 규칙을 추가하는 것이 더 낫다고 생각합니다. ㅎㅎ) 하지만 다음과 같은 단점이 있습니다.

  1. RuleSet은 실제로 구성이 아니며 규칙을

    digester에 바인딩할 뿐입니다.

  2. digester객체는 클라이언트와 긴밀하게 결합되어 있으며 클라이언트에 의해 직접 생성됩니다.

  3. 각 구문 분석 호출 전에 규칙을 반복적으로 바인딩해야 합니다

  4. 규칙이 바인딩되어 있고 의미가 매우 열악하며 가독성이 좋지 않습니다.

  5. 그렇다면 모범 사례가 무엇입니까? 답은 RulesModule 인터페이스를 사용하여 시작할 때 규칙을 미리 바인딩한 다음 재사용하는 것입니다.

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") ) );
        ...
    }

}
이점은 분명합니다.

  1. RulesModule

    규칙 바인딩의 API는 매우 의미 있고 사용하기 쉽고 읽기 쉽습니다.

  2. 규칙 바인딩 구성 완료를 위해 시작 단계로 이동했습니다.
  3. digester 개체는 클라이언트에 의해 생성되지 않습니다. 하지만 DigesterLoader에 의해 생성됨

FromXmlRulesModule

제외

직접 작성 클래스는 RulesModule을 구현합니다.

인터페이스 외에도 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>

결과 인쇄:
Pi Chen, CITY , HangZhou, 2

XML의 비동기 구문 분석

For 비동기 구문 분석의 경우 asyncParse 메서드를 직접 호출할 수 있지만
digester

개체는 스레드로부터 안전하지 않기 때문에 특별한 주의가 필요합니다. 다음은 간단한 API 사용 예입니다.
이전 예를 따르고 동일한 xml을 사용합니다. 및 RulesModule 구현 클래스;

클라이언트 클래스:
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();
        }
    }
}

结果打印:

9.99
false

参考资料


代码参考


위 내용은 아파치 커먼즈 다이제스터의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.