基本对象
1.
接
口。它是Commons Chain中最重要的接口,表示在Chain中的具体某一步要执行的命令。它只有一个方法:boolean
execute(Context
context)。如果返回true,那么表示Chain的处理结束,Chain中的其他命令不会被调用;返回false,则Chain会继续调用下一个
Command,直到:
Command
-
返回true;
Command
-
抛出异常;
Command
-
的末尾;
Chain
2.
接
口。它表示命令执行的上下文,在命令间实现共享信息的传递。Context接口的父接口是Map,ContextBase实现了Context。对于
web环境,可以使用WebContext类及其子类(FacesWebContext、PortletWebContext和
ServletWebContext)。
Context
3.
接口。它表示“命令链”,要在其中执行的命令,需要先添加到Chain中。Chain的父接口是Command,
ChainBase
实现了它。
Chain
4.
接
口。它的父接口是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。
Filter
5.
接口。它是逻辑命名的Chain和Command集合。通过使用它,Command的调用者不需要了解具体实现Command的类名,只需要通过名字就可以获取所需要的Command实例。
Catalog
基本使用
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);
//加载Command
cmd= 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是一种特殊的Command,它除了execute方法会被执行之外,同时还会在Chain执行完毕之后(不论是正常结束还是异常结
束)执行postprocess。因此,可以将它和Servlet中的Filter做类比:execute相当于处理前操作(相对下一个Command来
说),postprocess相当于处理后操作。Filter的使用以及配置和Command完全一样,为了在Command1之前添加一个
Filter:
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方法的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.
的
使用。配置文件的引入,使得Commons
Chain的灵活性大大的提高。在实际的使用过程中,存在着同一个Command被多个Chain使用的情形。如果每次都书写Command的类名,尤其
是前面的包名特别长的情况下,是非常枯燥的。而<define>的作用就是为了解决这样的麻烦。通过定义Command和Chain的别名,
来简化书写。例5的配置文件,可以书写成:
<define>
<?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>定义别名,简化书写。
相关推荐
apache commons all 中文api合集
apache commons jar(commons所有的jar包... apache-sanselan-incubating-0.97-bin bcel-5.2 commons-beanutils-1.9.2-bin commons-chain-1.2-bin commons-cli-1.3.1-bin commons-codec-1.10-bin commons-collections4-4
commons-lang3.3.1.jar、Apache Commons包中的一个,包含了一些数据类型工具类,是java.lang.*的扩展。必须使用的jar包。为JRE5.0+的更好的版本所提供 Jar文件包含的类: META-INF/MANIFEST.MFMETA-INF/LICENSE....
apache Commons Lang 2.4 API apache Commons Lang 2.4 API
commons-lang3.3.1.jar、Apache Commons包中的一个,包含了一些数据类型工具类,是java.lang.*的扩展。必须使用的jar包。为JRE5.0+的更好的版本所提供 Jar文件包含的类: META-INF/MANIFEST.MFMETA-INF/LICENSE....
Apache-commons源码其中包括(commons-email-1.5-src、commons-fileupload-1.4-src、commons-io-2.8.0-src、commons-jelly-1.0.1-src、commons-lang3-3.11-src...)
天天都有人导入Apache的包,但是里面那么多工具类又有多少人使用过,这里面有一些使用介绍
Apache_Commons_Net_2_API.chm
介绍了Apache Jakarta Commons 项目下Java组件,如FileUpload, HttpClient, DBCP,BeanUtils,Logging,Lang, 以及 Collections,Codec等,是学习和使用Apache Jakarta Commons良好的参考使用手册。
主要介绍了Apache Commons Math3探索之多项式曲线拟合实现代码,小编觉得挺不错的,这里分享给大家,供需要的朋友参考。
Apache Commons Collections,commons-collections-3.2.1和commons-collections4-4.0,含jar包及源码和api文档。
Apache Commons API简介,主要介绍Apache Commons API所包含的包,后续更新补充各类的简介和使用方法
Commons-beanutils-API Commons-collections-API Commons-configuration-API Commons-lang-API Commons-logging-API Dom4j_API java api javascript Struts API J2EE API
apache-commons下全部官方源码和官方API文档,其中有: commons-beanutils-1.8.0 commons-codec commons-collections commons-dbcp commons-dbutils commons-fileupload commons-io commons-lang commons-lang3 ...
apache commons 工具包中提供的一个针对配置文件动态修改的工具类
Apache Commons IO 2.5 (要求 JDK 1.6),IOUtils,FileUtils,jar包下载
Apache Commons是一个非常有用的工具包,解决各种实际的通用问题。(附件中提供了该工具包的jar包,及源文件以供研究) BeanUtils Commons-BeanUtils 提供对 Java 反射和自省API的包装 Betwixt Betwixt提供将 ...
Apache Commons Logging 1.2
Apache Commons官网jar包,包含io,cli,codec,net,lang,email等等等等
apache commons apiapache commons apiapache commons apiapache commons apiapache commons apiapache commons apiapache commons apiapache commons api