struts-menu散谈(一)

       今天在测试struts-menu的功能,打算用在项目中,在网上看了蓝色天空的struts-menu的源代码研究,总体来讲是没看懂,不知道别人什么感觉。所以自己打开源码看了下,只看了menu这个包就不得不赞叹大师级的人物写出来的东东,仅仅6个文件就用了composite,adapter两种模式。
       读代码最大的迷惑来自与 digester,由于之前没有用过,所以就在网上抓来了一片文章学习一下,具体内容如下:
 xml解析简介

  总的来说,xml文件解析有2种基本方法。一种是dom(document object model)方法。采用dom方法进行解析时,xml解析器读取整个xml文件并生成一个树状表达方式。另一个是使用sax,它的特点是不需要遍历整个文 件而是用事件驱动来解析文件。虽然dom方法有时实现起来比较容易,但是与sax方法相比速度更慢而且更耗资源。digester构件通过为sax事件提 供高级的接口大大简化了sax方法的解析过程。该接口隐含了大量xml文件处理的复杂的技术细节。使开发人员得以集中精力处理xml数据而不是花太多的时 间在如何解析文件本身上。

digester的几个重要概念

  digester引入了3个重要概念:元素匹配模式,处理规则以及对象栈。 

  元素匹配模式将处理规则与xml元素联系起来。以下是一个xml层次结构的元素匹配模式的例子。 

<datasources> 'datasources'
      <datasource> 'datasources/datasource'
           <name/> 'datasources/datasource/name'
           <driver/> 'datasources/datasource/driver' 
      </datasource>
      <datasource> 'datasources/datasource'
           <name/> 'datasources/datasource/name'
           <driver/> 'datasources/datasource/driver' 
      </datasource>
</datasources>
 


  每当发现一个匹配的模式(也可称层次),对应的处理规则就被激活。在上面的示例中,与'datasource/datasource'相关联的规则将会运行2次。

  处理规则定义了发现匹配的模式时产生的行为。digester模块已经预定了不少处理规则,自定义的处理规则可以通过扩展 org.apache.commons.digester.rule类来实现。

  对象栈用来保存处理规则所要处理的对象。对象可以由人为或处理规则压入和弹出对象栈。

 使用digester
  digester 时常用于解析xml配置文件,下面例子中的xml文件包含了用于创建datasource池的配置信息。 其中datasource是抽象类,拥有一个空的构造函数,多个get,set方法来存取字符串。

<?xml version="1.0"?>
<datasources>
    <datasource>
        <name>hsqldatasource</name>
        <driver>org.hsqldb.jdbcdriver</driver>
        <url>jdbc:hsqldb:hsql://localhost</url>
        <username>sa</username>
        <password></password>
    </datasource>

    <datasource>
        <name>oracledatasource</name>
        <driver>oracle.jdbc.driver.oracledriver</driver>
        <url>jdbc:oracle:thin:@localhost:1521:orcl</url>
        <username>scott</username>
        <password>tiger</password>
    </datasource>
</datasources>
 
  

 
  要使用digester对之进行解析,首先我们要创建一个digester类的实例,然后把所需的对象都压入到digester对象栈中,设置一系列处理规则,最后,对文件进行解析。下面是一个例子: 

digester digester = new digester();
/**

*addobjectcreate()创建一个新的datasource类的实例并把它压入digester的对象栈中。

*/
digester.addobjectcreate("datasources/datasource", "datasource");

/**
addcallmethod()调用位于对象栈顶部的对象的特定的方法,addcallmethod()的最后一个参数指定了传入*该方法的参数数目,如果 数目为0则匹配上的数据项内容将作为参数传入。
*下面这句代码实际就是调用datasource对象中的setname方法,传入的参数就是xml文件中
*"datasources/datasource/name"对应的值
*/
digester.addcallmethod("datasources/datasource/name","setname",0);
digester.addcallmethod("datasources/datasource/driver","setdriver", 0);
/**解析随后的内容*/
digester.parse("datasource.xml");

 (注:类objectcreaterule,callmethodrule 都是digester模块已定义的处理规则)
  假如应用这个代码段来处理在前面提到的xml文件,将会发生以下结果:
  · 一个新的datasource类的实例将被创建并压入堆栈;
  · 调用该实例的setname(string name)方法,参数值为'hsqldatasource';
  · 调用该实例的setdriver(string driver)方法,参数值为'oracledatasource'。
  在对'datasource'元素的处理结束后,对象从堆栈中弹出,文件剩余部分的解析重复以上过程。上面的例子存在一个问题,在对相关元素的处理结 束后,objectcreaterule会弹出它创建的对象。因此,当digester完成解析文件后,只有最后一次创建的对象被保留下来。解决这个问题 也很容易,只要把对象在解析开始之前压入堆栈,随后调用该对象的某个方法来创建所需的任意对象。下面的类就是这个办法的一个演示: 

public class sampledigester {
    public void run() throws ioexception, saxexception

    digester digester = new digester();

    // this method pushes this (sampledigester) class to the digesters
    // object stack making its method s available to processing rules.
    digester.push(this);

    // this set of rules calls the adddatasource method and passes
    // in five parameters to the method.
    digester.addcallmethod ("datasources/datasource", "adddatasource", 5);
    digester.addcallparam("datasources/datasource/name", 0);
    digester.addcallparam("datasources/datasource/driver", 1);
    digester.addcallparam("datasources/datasource/url", 2);
    digester.addcallparam("datasources/datasource/username", 3);
    digester.addcallparam("datasources/datasource/password", 4);
    // this method starts the parsing of the document.
    digester.parse("datasource.xml");
}
// example method called by digester.
public void adddatasource(string name,
string driver,
string url,
string username,
string password)
{
// create datasource and add to collection...
}
}
 
 


  在上面的sampledigester类中,每当匹配到 'datasources/datasource'时都会自动调用adddatasource()方法。addcallparam()方法将匹配到的数据 项内容作为传入adddatasource()方法的参数。在adddatasource()方法中,你就可以创建具体的datasouce并把它添加入 你的datasource集合中去。

看完着些我们该进入正题了,看看MenuRepository.java中的代码:

    protected Digester initDigester() {
        Digester digester = new Digester();
        digester.setClassLoader(Thread.currentThread().getContextClassLoader());
        digester.push(this);
        digester.addObjectCreate("MenuConfig/Menus/Menu",
                                 "com.fgm.web.menu.MenuComponent",
                                 "type");
        digester.addSetProperties("MenuConfig/Menus/Menu");
        digester.addSetNext("MenuConfig/Menus/Menu", "addMenu");
        // 2
        digester.addObjectCreate("MenuConfig/Menus/Menu/Item",
                                 "com.fgm.web.menu.MenuComponent",
                                 "type");
        digester.addSetProperties("MenuConfig/Menus/Menu/Item");
        digester.addSetNext("MenuConfig/Menus/Menu/Item", "addMenuComponent",
                            "com.fgm.web.menu.MenuComponent");
        // 3       
        digester.addObjectCreate("MenuConfig/Menus/Menu/Item/Item",
                                 "com.fgm.web.menu.MenuComponent",
                                 "type");
        digester.addSetProperties("MenuConfig/Menus/Menu/Item/Item");
        digester.addSetNext("MenuConfig/Menus/Menu/Item/Item", "addMenuComponent",
                            "com.fgm.web.menu.MenuComponent");
        // 4
        digester.addObjectCreate("MenuConfig/Menus/Menu/Item/Item/Item",
                                 "com.fgm.web.menu.MenuComponent",
                                 "type");
        digester.addSetProperties("MenuConfig/Menus/Menu/Item/Item/Item");
        digester.addSetNext("MenuConfig/Menus/Menu/Item/Item/Item", "addMenuComponent",
                            "com.fgm.web.menu.MenuComponent");
        // 5
        digester.addObjectCreate("MenuConfig/Menus/Menu/Item/Item/Item/Item",
                                 "com.fgm.web.menu.MenuComponent",
                                 "type");
        digester.addSetProperties("MenuConfig/Menus/Menu/Item/Item/Item/Item");
        digester.addSetNext("MenuConfig/Menus/Menu/Item/Item/Item/Item", "addMenuComponent",
                            "com.fgm.web.menu.MenuComponent");
        // 6
        digester.addObjectCreate("MenuConfig/Menus/Menu/Item/Item/Item/Item",
                                 "com.fgm.web.menu.MenuComponent",
                                 "type");
        digester.addSetProperties("MenuConfig/Menus/Menu/Item/Item/Item/Item");
        digester.addSetNext("MenuConfig/Menus/Menu/Item/Item/Item/Item", "addMenuComponent",
                            "com.fgm.web.menu.MenuComponent");
        // 7
        digester.addObjectCreate("MenuConfig/Menus/Menu/Item/Item/Item/Item",
                                 "com.fgm.web.menu.MenuComponent",
                                 "type");
        digester.addSetProperties("MenuConfig/Menus/Menu/Item/Item/Item/Item");
        digester.addSetNext("MenuConfig/Menus/Menu/Item/Item/Item/Item", "addMenuComponent",
                            "com.fgm.web.menu.MenuComponent");
        digester.addObjectCreate("MenuConfig/Displayers/Displayer",
                                 "com.fgm.web.menu.displayer.MenuDisplayerMapping",
                                 "mapping");
        digester.addSetProperties("MenuConfig/Displayers/Displayer");
        digester.addSetNext("MenuConfig/Displayers/Displayer", "addMenuDisplayerMapping",
                            "com.fgm.web.menu.displayer.MenuDisplayerMapping");
        digester.addSetProperty("MenuConfig/Displayers/Displayer/SetProperty",
                                "property", "value");
        return digester;
    } 

太晚了,明天接着写。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值