本站首页    管理页面    写新日志    退出


«August 2025»
12
3456789
10111213141516
17181920212223
24252627282930
31


公告
 本博客在此声明所有文章均为转摘,只做资料收集使用。

我的分类(专题)

日志更新

最新评论

留言板

链接

Blog信息
blog名称:
日志总数:1304
评论数量:2242
留言数量:5
访问次数:7585339
建立时间:2006年5月29日




[Apache(jakarta)]Apache Commons Chain简明手册
软件技术,  电脑与网络

lhwork 发表于 2006/6/20 11:40:32

基本对象1.  Command接口。它是Commons Chain中最重要的接口,表示在Chain中的具体某一步要执行的命令。它只有一个方法:boolean execute(Context context)。如果返回true,那么表示Chain的处理结束,Chain中的其他命令不会被调用;返回false,则Chain会继续调用下一个Command,直到:-          Command返回true;-          Command抛出异常;-          Chain的末尾;2.  Context接口。它表示命令执行的上下文,在命令间实现共享信息的传递。Context接口的父接口是Map,ContextBase实现了Context。对于web环境,可以使用WebContext类及其子类(FacesWebContext、PortletWebContext和ServletWebContext)。3.  Chain接口。它表示“命令链”,要在其中执行的命令,需要先添加到Chain中。Chain的父接口是Command,ChainBase实现了它。4.  Filter接口。它的父接口是Command,它是一种特殊的Command。除了Command的execute,它还包括一个方法:boolean postprocess(Context context, Exception exception)。Commons Chain会在执行了Filter的execute方法之后,执行postprocess(不论Chain以何种方式结束)。Filter的执行execute的顺序与Filter出现在Chain中出现的位置一致,但是执行postprocess顺序与之相反。如:如果连续定义了filter1和filter2,那么execute的执行顺序是:filter1 -> filter2;而postprocess的执行顺序是:filter2 -> filter1。5.  Catalog接口。它是逻辑命名的Chain和Command集合。通过使用它,Command的调用者不需要了解具体实现Command的类名,只需要通过名字就可以获取所需要的Command实例。基本使用1.         执行由顺序的命令组成的流程,假设这条流程包含1、2和3步。þ        实现要执行的命令步骤: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);//加载Commandcmd= catalog.getCommand( "command4");        cmd.execute( ctx);    }}注意:使用配置文件的话,需要使用Commons Digester。而Digester则依赖:Commons  Collections、Commons Logging和Commons BeanUtils。3.         加载Catalog到web应用。为了在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:þ        定义Filterpublic 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方法的Filter的postprocess方法,即使在出现异常时也是如此。因此,对应的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>的作用就是为了解决这样的麻烦。通过定义Command和Chain的别名,来简化书写。例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 Responsebility和Command模式,其中的Catalog + 配置文件的方式使得调用方和Command的实现方的耦合度大大的降低,提高了灵活性。对于配置文件,通常可以:-          作为Command的索引表,需要时按名字索引创建实例。-          利用Chain以及内嵌Chain,完成一组连续任务和Command的复用,引入Filter可以获得与Servlet Filter一样的好处。-          使用<define>定义别名,简化书写。


阅读全文(1968) | 回复(-1) | 编辑 | 精华
 



发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.063 second(s), page refreshed 144753304 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号