dedecms织梦内容管理系统    
首页 | java | C/C++ | PHP | 操作系统 | ajax | 脚本编程 | 安全技术 | 本站下载页 | flex | CRM | 专题 | QQ群 | 测试中心 | 会员中心 | 积分规则
  当前位置:主页>java>开源框架>文章内容
Apache Commons Chain简明手册
来源: 作者:

基本对象

 

1.  Command接口。它是Commons Chain中最重要的接口,表示在Chain中的具体某一步要执行的命令。它只有一个方法:boolean execute(Context context)。如果返回true,那么表示Chain的处理结束,Chain中的其他命令不会被调用;返回false,则Chain会继续调用下一个Command,直到:

-          Command返回true

-          Command抛出异常;

-          Chain的末尾;

2.  Context接口。它表示命令执行的上下文,在命令间实现共享信息的传递。Context接口的父接口是MapContextBase实现了Context。对于web环境,可以使用WebContext类及其子类(FacesWebContextPortletWebContextServletWebContext)。

3.  Chain接口。它表示“命令链”,要在其中执行的命令,需要先添加到Chain中。Chain的父接口是CommandChainBase实现了它。

 

4.  Filter接口。它的父接口是Command,它是一种特殊的Command。除了Commandexecute,它还包括一个方法:boolean postprocess(Context context, Exception exception)Commons Chain会在执行了Filterexecute方法之后,执行postprocess(不论Chain以何种方式结束)。Filter的执行execute的顺序与Filter出现在Chain中出现的位置一致,但是执行postprocess顺序与之相反。如:如果连续定义了filter1filter2,那么execute的执行顺序是:filter1 -> filter2;而postprocess的执行顺序是:filter2 -> filter1

5.  Catalog接口。它是逻辑命名的ChainCommand集合。通过使用它,Command的调用者不需要了解具体实现Command的类名,只需要通过名字就可以获取所需要的Command实例。

基本使用

 

1.         执行由顺序的命令组成的流程,假设这条流程包含123步。

þ        实现要执行的命令步骤:

public class Command1 implements Command {

    public boolean execute(Context arg0) throws Exception {

        System.out.println("Command1 is done!");

        return false;

    }

}

public class Command2 implements Command {

    public boolean execute(Context arg0) throws Exception {

        System.out.println("Command2 is done!");    

        return false;

    }

}

public class Command3 implements Command {

    public boolean execute(Context arg0) throws Exception {

        System.out.println("Command3 is done!");

        return true;

    }

}

 

þ        注册命令,创建执行的Chain

public class CommandChain extends ChainBase {

    //增加命令的顺序也决定了执行命令的顺序

    public CommandChain(){

        addCommand( new Command1());

        addCommand( new Command2());

        addCommand( new Command3());

    }

   

    public static void main(String[] args) throws Exception{

        Command process = new CommandChain();

        Context ctx= new ContextBase();

        process.execute( ctx);

    }

}

 

2.         使用配置文件加载Command。除了在程序中注册命令之外,还可以使用配置文件来完成。

þ        对于例1,配置文件可以写成:

<?xml version="1.0" encoding="gb2312"?>

<catalog>

       <chain name="CommandChain">

        <!-- 定义的顺序决定执行的顺序 -->

              <command id="command1" className= "chain.Command1"/>

              <command id="command2" className= "chain.Command2"/>

              <command id="command3" className= "chain.Command3"/>

       </chain>

    <command name="command4" className="chain.Command1"/>

 

</catalog>

 

þ        装入配置文件的代码如下:

public class CatalogLoader {

    static final String cfgFile= "/chain/chain-cfg.xml";   

    public static void main(String[] args) throws Exception{

        CatalogLoader loader= new CatalogLoader();

        ConfigParser parser= new ConfigParser();

       

        parser.parse( loader.getClass().getResource( cfgFile));

        Catalog catalog= CatalogFactoryBase.getInstance().getCatalog();

        //加载Chain

        Command cmd= catalog.getCommand("CommandChain");

        Context ctx= new ContextBase();

        cmd.execute( ctx);

//加载Command

cmd= catalog.getCommand( "command4");

        cmd.execute( ctx);

    }

}

注意:使用配置文件的话,需要使用Commons Digester。而Digester则依赖:Commons  CollectionsCommons LoggingCommons BeanUtils

 

3.         加载Catalogweb应用。为了在web应用中加载Catalog,需要在对应的web.xml中添加:

<context-param>

 

  <param-name>org.apache.commons.chain.CONFIG_CLASS_RESOURCE</param-name>

 

  <param-value>resources/catalog.xml</param-value>

 

</context-param>

 

<listener>

 

  <listener-class>org.apache.commons.chain.web.ChainListener</listener-class>

 

</listener>

 

 

 

 

 

 

缺省情况下,Catalog会被加载到Servlet Context中,对应的属性名字是“catalog”。因此获取Catalog

Catalog catalog = (Catalog) request.getSession()

                            .getServletContext().getAttribute("catalog");

 

4.         Filter的使用。Filter是一种特殊的Command,它除了execute方法会被执行之外,同时还会在Chain执行完毕之后(不论是正常结束还是异常结束)执行postprocess。因此,可以将它和Servlet中的Filter做类比:execute相当于处理前操作(相对下一个Command来说),postprocess相当于处理后操作。Filter的使用以及配置和Command完全一样,为了在Command1之前添加一个Filter

þ        定义Filter

public class Filter1 implements Filter {

    public boolean postprocess(Context arg0, Exception arg1) {

        System.out.println("Filter1 is after done!");

        return false;

    }

    public boolean execute(Context arg0) throws Exception {

        System.out.println("Filter1 is done!");

        return false;

    }

}

 

þ        修改配置文件,在上述的配置文件中的command1之前添加:

<command id="filter1" className= "chain.Filter1"/>

       Filter的还有一个常用的用法:对于异常的过滤。当Command抛出异常时,最终中会返回到最开始的调用处。有时期望不抛出这些异常,而在内部消化掉,那么就可以利用Filter。因为Commons Chain确保会调用已经执行了execute方法的Filterpostprocess方法,即使在出现异常时也是如此。因此,对应的postprocess方法可以写为:

       public boolean postprocess(Context arg0, Exception arg1) {

        //返回true,表示非空异常已被处理,无需再抛出。

        //否则,异常会被抛出

        if( null!= arg1) return true;

        else return false;

    }

5.         对于复杂的Chain,可能需要使用内嵌的Chain,内嵌Chain可以类比一个子过程。此时,可以使用LookupCommand。以例1为例,假设其中的command2需要扩展成为一个子过程,那么配置文件修改如下:

<?xml version="1.0" encoding="UTF-8"?>

<catalog>

       <chain name="CommandChain">

              <command id="command1" className= "chain.Command1"/>

              <command id="filter1" className= "chain.Filter1"/>

              <command

 

className="org.apache.commons.chain.generic.LookupCommand"

 

                     name="chain_command3"

 

                     optional="true"/>

              <command id="command2" className= "chain.Command2"/>

       </chain>

       <chain name="chain_command3">

 

              <command id="command3" className= "chain.Command3"/>

 

       </chain>

</catalog>

 

 

 

 

 

其中,optional如果设为true,那么如果没有找到对应的类时,程序不会抛出异常。此时,仿佛命令不存在一样。如果为false,那么在找不到对应的类时,会抛出异常。

6.         <define>的使用。配置文件的引入,使得Commons Chain的灵活性大大的提高。在实际的使用过程中,存在着同一个Command被多个Chain使用的情形。如果每次都书写Command的类名,尤其是前面的包名特别长的情况下,是非常枯燥的。而<define>的作用就是为了解决这样的麻烦。通过定义CommandChain的别名,来简化书写。例5的配置文件,可以书写成:

<?xml version="1.0" encoding="gb2312"?>

<catalog>

    <!-- Command的别名,以后直接使用即可 -->

       <define name="command1" className="chain.Command1"/>

       <define name="command2" className="chain.Command2"/>

       <define name="command3" className="chain.Command3"/>

       <define name="filter1" className="chain.Filter1"/>

       <define name="lookupCommand"

                  className="org.apache.commons.chain.generic.LookupCommand"/>

      

       <chain name="CommandChain">

              <command1 id="1"/>

              <filter1 id="2"/>

              <lookupCommand name="chain_command3" optional="true"/>

              <command2 id="3"/>

       </chain>

      

       <chain name="chain_command3">

              <command3 id="3"/>

       </chain>

      

       <command1 name="command4"/>

</catalog>

 

总结

 

       Commons Chain实现了Chain of ResponsebilityCommand模式,其中的Catalog + 配置文件的方式使得调用方和Command的实现方的耦合度大大的降低,提高了灵活性。对于配置文件,通常可以:

-          作为Command的索引表,需要时按名字索引创建实例。

-          利用Chain以及内嵌Chain,完成一组连续任务和Command的复用,引入Filter可以获得与Servlet Filter一样的好处。

-          使用<define>定义别名,简化书写。

 

 

 

 

 

 

 

 


上一篇:fckeditor的官方例子(翻译)   下一篇:PowerDesigner教程系列(一)概念数据模型
[收藏] [推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
用户名: 新注册) 密码: 匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论
  热点文章
·关于JSF和Struts的讨论
·Struts教程-Struts模块化编程教
·Struts入门经验
·用科学的思维方法指导软件的设计
·Hibernate配置文件中映射元素详
·Spring中事件处理的小技巧
·struts2.0pring2.0 hibernate3.2
·struts2.0 spring2.0 hibernate3
·浅谈hibernate lazy fetch
·Hibernate的Fetch
·优化hibernate性能的几点建议
·Hibernate中的取策略延迟加载
  相关文章
·Common Dbutils组件用法详解(含
·翻译 commons dbutils例子exampl
·利用JAVA的动态属性之反射原理实
·利用Jakarta Commons组件beanuti
·Common Dbutils组件的使用
·Apache DBUtils实践
·使用 Spring 2.5 TestContext 测
·Spring 2.5架构图
·Spring 2.5 标注开发的简单例子
·JBPM工作流引擎内核设计思想及构
·JBPM工作流引擎内核设计思想及构
·JBPM工作流引擎内核设计思想及构
  相关信息
copy right @ 百家拳软件项目研究室 2007 辽ICP备07011763