Digester简介及JRXmlLoader分析

Digester提供一种事件驱动的xml格式数据的处理方式,它根据xml的路径模式生成不同的对象并调用指定的方法设置对象的参数。Digester提供了比SAX更高级更友好的接口,更多的实现细节都被封装了,开发人员可以更专注于语义上的处理过程。

 

使用Digester需要加载commons-digester-*.*.jar

使用Digester的基本步骤:

1、  创建一个org.apache.commons.digester.Digester类的实例

2、  设置初始化参数参数 如:

3、  (可选的)将需要初始化的对象放到Digester的对象栈中

4、  注册你希望触发事件的路径模式,如果一个路径模式注册了多个事件则事件按注册的列表顺序执行。

5、  调用digester.parse()方法解析指定的xml文件。   

Digester的属性及意义

classLoader 类加载器,当使用ObjectCreateRule FactoryCreateRule规则时使用classLoader加载规则需要的类。如果不设置程序会调用线程类加载器或者使用加载Digester时所使用的加载器。

 

errorHandler 定义自己的SAX ErrorHandler,默认的把所有解析错误输出到日志,但是Digester会继续进行解析。

 

namespaceAware 是否使用xml命名空间

 

ruleNamespaceURI 命名空间位置

 

rules 匹配规则

 

useContextClassLoader 是否使用上下文类加载器

 

validating 是否进行特点规则校验,默认执行格式良好校验

 

对象堆栈

 

通过xml文档结构,Digester会动态创建一个对象树。Digester最初开发的主要目的就是通过struts-config.xml文件让struts实现自我配置。

Digester公开一个堆栈当xml元素满足某个模式是,就会调用注册的方法去创建一个对象,并放入对象堆栈中。常用的堆栈操作方法有:

clear()  清理堆栈

peek()  获取栈顶的对象

pop()  栈顶的对象出栈

push() 对象入栈

 

一般当遇到一个元素的起始标签是创建对应的对象,当处理元素的子元素时对象呆在栈中,直到遇见元素的结束元素将对象出栈。

 

在栈中每创建一个元素,就会用一个top-1位置的对象(对象的父对象)的方法将top对象赋给top-1对象,这样就可以明确各对象之间的从属关系。

 

一个简单的办法应用根元素对应的对象就是预先见将对象的持有者入栈,然后添加addSetNext方法将跟对象赋给持有对象。

 

 

JasperReport编译jrxml加载器的分析:

 

public class JRXmlLoader

    

private Digester digester = null; 

private JasperDesign jasperDesign = null;

 

    public JRXmlLoader(Digester digester)

    {

       this.digester = digester;

    }

 

    public void setJasperDesign(JasperDesign jasperDesign)

    {

       this.jasperDesign = jasperDesign;

    }

 

    public JasperDesign loadXML(InputSource is) throws JRException

    {

           //将当前对象入栈,以便存储根元素生成的对象

           digester.push(this); 

           /*  

            * 解析输入的xml文件流 

            * */

           digester.parse(is);

             ......

    

           return this.jasperDesign;

    }

}

 

  

 

 

JRXmlDigesterFactory配置Digester匹配模式

public final class JRXmlDigesterFactory

{

/**

     * Configures the given digester for parsing jasperreport xml report definition files.

     */

    public static void configureDigester(Digester digester) throws SAXException, ParserConfigurationException

    {

       // set a composite classloader that includes both the JR classloader

       // and the context classloader

       CompositeClassloader digesterClassLoader = new CompositeClassloader(

              JRXmlDigesterFactory.class.getClassLoader(), 

              Thread.currentThread().getContextClassLoader());

       digester.setClassLoader(digesterClassLoader);

       

       digester.setErrorHandler(new ErrorHandlerImpl());

       

       digester.setNamespaceAware(true);

       

       digester.setRuleNamespaceURI(JRXmlConstants.JASPERREPORTS_NAMESPACE);

 

       /*

        * 注册创建jasperDesign的工厂

          */

       digester.addFactoryCreate("jasperReport", 

JasperDesignFactory.class.getName());

       /*

          将栈顶对象调用setJasperDesign方法放入紧邻的对象中

           即之前的JRXmlLoader digester.push(this);    

        */

       digester.addSetNext("jasperReport", "setJasperDesign", JasperDesign.class.getName());

       /*   

         将属性元素入栈     

        * */

       digester.addRule("*/property", new JRPropertyDigesterRule());

       

       /*  

         创建reportFont的对象通过 addFont将该对象赋给紧邻的对象

*/

       digester.addFactoryCreate("jasperReport/reportFont", JRReportFontFactory.class.getName());

       digester.addSetNext("jasperReport/reportFont", "addFont", JRReportFont.class.getName());

        ......

}

}

 

 

 

JasperDesignFactory创建JasperDesign对象

 

public class JasperDesignFactory extends JRBaseFactory

{

 

    

    /**

     * ObjectCreationFactory 定义的接口用于通过xml element创建对象

     */

    public Object createObject(Attributes atts)

    {

        /*

         * 创建jasperDesign对象,并取得对应的属性

         */

       JasperDesign jasperDesign = new JasperDesign();

       //获取并设置属性name    

jasperDesign.setName(

atts.getValue(JRXmlConstants.ATTRIBUTE_name));

        jasperDesign.setLanguage(

atts.getValue(JRXmlConstants.ATTRIBUTE_language));

        ......

     }

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值