struts 的digester类解析xml文件

学习struts 的digester类解析xml文件

1、digester的简介

    digester是struts的一个工具,用来解析struts的配置文件struts-config.xml,将xml的元素转换成java的对象。Digester是通过调用预定义的规则来操作xml元素,将xml的元素转换为java对象。

   Digester底层采用SAX解析xml文件。首先识别出特定xml元素(实际细分为begin,body,end,finish四个步骤)后,执行特 定的动作。digester通过匹配模式(matching pattern)识别特定的元素,而相关的操作由rule来执行。

2、degister的创建过程。

xml文档如下:

<web-app>

<servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
   </servlet-mapping>
   <servlet-mapping>
    <servlet-name>ajax</servlet-name>
    <url-pattern>/ajax</url-pattern>
</servlet-mapping>

</web-app>


(1)创建一个digester的实例,一个解析(digester.parse())请求完了以后,digster还可以被后面的解析请求服用。

         Digester digester = new Digester();

   (2)设置一些配置属性(configuration properties),用于设置解析操作。

        digester.setNamespaceAware(true);
        digester.setValidating(false);

   (3)将一个或几个对象塞入Digester对象栈顶,便于解析调用。

        digester.push(this);//this是actionservlet对象。

   (4)注册xml的匹配模板(matching pattern),当一个匹配模板被输入的xml文档中识别出来,其相应的规则就被激活。当识别出该模板后,这些规则依序依次执行。

//    protected String registrations[] = {
        "-//Apache Software Foundation//DTD Struts Configuration 1.0//EN",
        "/org/apache/struts/resources/struts-config_1_0.dtd",
        "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN",
        "/org/apache/struts/resources/struts-config_1_1.dtd",
        "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN",
        "/org/apache/struts/resources/web-app_2_2.dtd",
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN",
        "/org/apache/struts/resources/web-app_2_3.dtd"
    };

//前面已经设置了registrations的值

        for (int i = 0; i < registrations.length; i += 2) {
            URL url = this.getClass().getResource(registrations[i+1]);
            if (url != null) {
                digester.register(registrations[i], url.toString());
            }
        }

(5)digeter先制定相应的rule规则,这些rule保存在digester对象里面,只有等到解析的时候,才会真正去执行。

        digester.addCallMethod("web-app/servlet-mapping",
                               "addServletMapping", 2);

        //表示xml文档碰到web-app元素下的servlet-mapping,就调用当前栈顶的对象(即actionservlet)的 addServletMapping方法,并传递两个参数给该方法。当此处只是声明一个new CallMethodRule(addServletMapping, 2)的对象。

        digester.addCallParam("web-app/servlet-mapping/servlet-name", 0);

      //表示xml文档碰到web-app/servlet-mapping的servlet-name元素,就将servlet-name设的值作为 addServletMapping方法的第一个参数。当此处只是声明一个new CallParamRule(0)的对象。

        digester.addCallParam("web-app/servlet-mapping/url-pattern", 1);

      //表示xml文档碰到web-app/servlet-mapping的url-pattern元素,就将url-pattern设的值作为addServletMapping方法的第二个参数

其 中解析的时候会去调用begin(Attributes attributes),end(String namespace, String name)等方法,其中attributes中保存的是配置文件的内容,该类里面有个data变量是string[] 数组,存放配置的属性和配置的属性值。[, path, path, CDATA, /logon, , name, name, CDATA, logonForm, , input, input, CDATA, /WEB-INF/jsp/bas/logon.jsp, , scope, scope, (request|session), request, , type, type, CDATA, com.longtop.bas.web.LogonAction, , validate, validate, (true|false|yes|no), false]

   (6)解析xml文件,当必须传给parse()一个参数(文件引用)。

        InputStream input =
            getServletContext().getResourceAsStream("/WEB-INF/web.xml");//xml文档的引用

        try {
            digester.parse(input);//传递xml文档的引用,并且一定要捕捉并处理IOException和SAXException

        } catch (IOException e) {
            log.error(internal.getMessage("configWebXml"), e);
            throw new ServletException(e);
           
        } catch (SAXException e) {
            log.error(internal.getMessage("configWebXml"), e);
            throw new ServletException(e);

   调用parse(input)的时候,digester才真正解析xml文档,规则和相关的操作才被执行(即actionservlet的 addServletMapping()才真正被执行)。如上xml文档所示的有两个action-mapping的节点,所以 actionservlet类的addServletMapping方法会被调用两次。

3、对象栈的理解

     当识别出xml元素的开始,就将该元素对应的对象压入栈顶。当识别出该元素的子节点,则又生成一个对象压入栈顶,并将该元素对应的对象作为一个参数,传递 给子节点对应的对象。这样就可以建立1:1或1:N的父子关系。当解析器遇到一个xml元素的“开始”,就将该元素对应的对象压入栈顶,当解析完该元素的 所有子元素,解析器遇到该元素的“结束”,就弹出该对象,并进行相关的处理。

4、digester的所有操作(规则)

   (1)首先引用一个比较完整的xml文档

<struts-config><!-- 配置数据源 -->
<data-sources >
    <data-source key="mysql" className="org.apache.struts.config.DataSourceConfig2">
      <set-property property="driverClass" value="org.gjt.mm.mysql.Driver" />
      <set-property property="url" value="jdbc:mysql://localhost:3306/manage" />
      <set-property property="user" value="root" />
      <set-property property="password" value="root" />
      <set-property property="minCount" value="5" />
      <set-property property="maxCount" value="10" />     
      <set-property property="description" value="" />     
      <set-property property="readOnly" value="false" />
      <set-property property="autoCommit" value="false" />
      <set-property property="loginTimeout" value="" />
    </data-source>   
</data-sources>

<!-- 配置ActionForm -->
<form-beans >
    <form-bean name="loginForm" type="com.wind.struts.form.LoginForm" />
</form-beans>

<!-- 配置全局异常处理 -->
<global-exceptions>
<exception type="" key=""/>
</global-exceptions>

<!-- 配置全局跳转 -->
<global-forwards>
     <forward name="professor" path="/professor.jsp" />
</global-forwards>


<!-- 配置映射关系 -->
<action-mappings >
    <action
      attribute="loginForm"
      input="/form/login.jsp"
      name="loginForm"
      path="/login"
      scope="request"
   validate="true"
      type="com.wind.struts.action.LoginAction" >
     
      <!-- 配置局部异常处理 -->
      <exception type="" key=""/>
     
      <!-- 配置局部跳转 -->
      <forward name="student" path="/student.jsp" />
      <forward name="teacher" path="/teacher.jsp" />     
     
    </action>
</action-mappings>

<!-- 配置RequestProcessor插件 -->
<controller processorClass="com.wind.MyRequestProcessor"></controller>

<!-- 配置国际化资源文件 -->  
<message-resources parameter="com.wind.struts.ApplicationResources" />

<!-- 配置Plugin插件 -->
<plug-in className="com.wind.MyPlugin">
<!-- 配置validate验证文件 -->
    <set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
</plug-in></struts-config>

(2)ConfigRuleSet类addRuleInstances()方法设置中对xml解析的操作(规则)

public void addRuleInstances(Digester digester) {

        digester.addObjectCreate
            ("struts-config/data-sources/data-source",
             "org.apache.struts.config.DataSourceConfig",
             "className");

      //表示遇到data-source节点的“开始”,就可以缺省创建一个 org.apache.struts.config.DataSourceConfig的实例。如果xml文件设置了className的属性,就生成一 个className指定类(org.apache.struts.config.DataSourceConfig2)的实例,而不是 org.apache.struts.config.DataSourceConfig的实例。并将该对象压入栈顶。详细的看 ObjectCreatRule类。

        digester.addSetProperties
            ("struts-config/data-sources/data-source");

   //遇到struts-config/data-sources/data-source的attributevs的“开始”,根据web-xml的根据 属性列表中(attributes)的属性值对 ,<form-bean name="basMapForm" type="com.longtop.bas.web.BasMapForm"/>,则从栈顶取回该对象Object top = digester.peek();,并设置object的 name=basMapForm,type="com.longtop.bas.web.BasMapForm"。该节点被解析 时,SetPropertiesRule的begin()方法会被调用,并且name="basMapForm" type="com.longtop.bas.web.BasMapForm"会被封装到Attributes attributes的对象里。详细的看SetPropertiesRule类。

/***解析时相当运行的代码***/

HashMap values = new HashMap();

String name = attributes.getLocalName(0);name="name"

String value = attributes.getValue(0);value=="basMapForm"

String name = attributes.getLocalName(0);name="type"

String value = attributes.getValue(0);value=="com.longtop.bas.web.BasMapForm"

values.put(name, value);

Object top = digester.peek();//top是org.apache.struts.action.ActionFormBean的实例。

BeanUtils.populate(top, values);//是指org.apache.struts.action.ActionFormBean的实例的name和type属性值。

/***解析时相当运行的代码***/

        digester.addSetProperty
            ("struts-config/data-sources/data-source/set-property",
             "property", "value");

// 遇到struts-config/data-sources/data-source/set-property的“开始”,根据web-xml的根据属 性中(property)的属性值对 ,      <set-property property="user" value="root" />
      <set-property property="password" value="root" />,则从栈顶取回该对象Object top = digester.peek();,并设置object的password=root,user=root。详细的看SetPropertyRule类。


        digester.addSetNext
            ("struts-config/form-beans/form-bean",
             "addFormBeanConfig",
             "org.apache.struts.config.FormBeanConfig");

   //表示调用栈顶org.apache.struts.config.DataSourceConfig的父节点 (org.apache.struts.config.ModuleConfig)相对应的对象的addDataSourceConfig的方法将该对象 (DataSourceConfig,当前的栈顶对象)加入到父节点对象(ModuleConfig)。详细的看SetNextRule类。

<form-bean name="basMapForm" type="com.longtop.bas.web.BasMapForm"/>

        Object child = digester.peek(0);子节点FormBeanConfig
        Object parent = digester.peek(1);父节点org.apache.struts.config.impl.ModuleConfig

        if (paramType != null) {
            paramTypes[0] =
                    digester.getClassLoader().loadClass(paramType);//paramType是实例化rule时,已经设置 成“FormBeanConfig”,加载FormBeanConfig的类。
        } else {
            paramTypes[0] = child.getClass();

     }

 

Come fromhttp://dev.firnow.com/course/3_program/java/javajs/20100719/461328.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值