开始使用Commons Chain 运用讲解(3)

分类: J2EE   出处:iocblog整理  更新时间:2008-10-24   添加到收藏  


清单10

 

package com.jadecove.chain.sample;

import org.apache.commons.chain.catalog;
import org.apache.commons.chain.command;
import org.apache.commons.chain.context;
import org.apache.commons.chain.config.configparser;
import org.apache.commons.chain.impl.catalogfactorybase;

public class catalogloader {
private static final string config_file =
"/com/jadecove/chain/sample/chain-config.xml";
private configparser parser;
private catalog catalog;

public catalogloader() {
parser = new configparser();
}
public catalog getcatalog() throws exception {
if (catalog == null) {

parser.parse(this.getclass().getresource(config_file));

}
catalog = catalogfactorybase.getinstance().getcatalog();
return catalog;
}
public static void main(string[] args) throws exception {
catalogloader loader = new catalogloader();
catalog samplecatalog = loader.getcatalog();
command command = samplecatalog.getcommand("sell-vehicle");
context ctx = new sellvehiclecontext();
command.execute(ctx);
}
}

 

 

chain使用commons digester来读取和解析配置文件。因此你需要将commons digester.jar加入classpath中。我使用了1.6版本并且工作得很好。digester使用了commons collectios(我使用的版本是3.1),commons logging(版本


1.0.4),commons beanutils(1.7.0),因此你也需要将它们的jar文件加入classpath中。在加入这些jar后,catalogloader就可以被编译和运行,它的输出和另外两个测试完全相同。


现在你可以在xml文件中定义链,并可以在程序中得到这个链(别忘了链也是命令),这样扩展的可能性和程序的灵活性可以说是无限的。假设过程"安排财务"实际上由一个完全分离的商业部门处理。这个部门希望为这种销售建立自己的工作流程。chain提供了嵌套链来实现这个要求。因为链本身就是命令,因此你可以用指向另一个链的引用替换一个单一用途的命令。下面是增加了新流程的链的定义:

清单11

 

<catalog name="auto-sales">
 <chain name="sell-vehicle">
 <command id="getcustomerinfo"
 classname="com.jadecove.chain.sample.getcustomerinfo"/>
 <command id="testdrivevehicle"
 classname="com.jadecove.chain.sample.testdrivevehicle"/>
 <command id="negotiatesale"
 classname="com.jadecove.chain.sample.negotiatesale"/>
 <command
 classname="org.apache.commons.chain.generic.lookupcommand"
 catalogname="auto-sales"
name="arrange-financing"
optional="true"/>
 <command id="closesale"
 classname="com.jadecove.chain.sample.closesale"/>
 </chain>
 <chain name="arrange-financing">
 <command id="arrangefinancing"
 classname="com.jadecove.chain.sample.arrangefinancing"/>
 </chain>
</catalog>

commons chain提供了一个常用的命令lookupcommand来查找和执行另一个链。属性optional用于控制当指定的嵌套链没有找到时如何处理。optional=true时,即使链没找到,处理也会继续。反之,lookupcommand将抛出illegalargumentexception,告知指定的命令未找到。


在下面三种情况下,命令链将结束:


1.命令的execute方法返回true

 

2.运行到了链的尽头


3.命令抛出异常

当链完全处理完一个过程后,命令就返回true。这是责任链模式(chain of responsibility)的基本概念。处理从一个命令传递到另一个命令,直到某个命令(command)处理了这个命令。如果在到达命令序列尽头时仍没有处理返回true,也假设链已经正常结束。

 

当有命令抛出错误时链就会非正常结束。在commons chain中,如果有命令抛出错误,链的执行就会中断。不论是运行时错误(runtime exception)还是应用错误(application exception),都会抛出给链的调用者。但是许多应用都需要对在命令之外定义的错误做明确的处理。commons chain提供了filter接口来满足这个要求。filter继承了command,添加了一个名为postprocess的方法。

 

public boolean postprocess(context context, exception exception);


只要filter的execute方法被调用,不论链的执行过程中是否抛出错误,commons chain都将保证filter的postprocess方法被调用。和servlet的过滤器(filter)相同,commons chain的filter按它们在链中的顺序依次执行。同样,filter的postprocess方法按倒序执行。你可以使用这个特性实现自己的错误处理。下面是一个用于处理我们例子中的错误的filter:


清单12

 

package com.jadecove.chain.sample;

import org.apache.commons.chain.context;
import org.apache.commons.chain.filter;

public class sellvehicleexceptionhandler implements filter {

public boolean execute(context context) throws exception {
system.out.println("filter.execute() called.");
return false;
}

public boolean postprocess(context context,
 exception exception) {
if (exception == null) return false;
system.out.println("exception "
+ exception.getmessage()
+ " occurred.");
return true;
}
}

 

filter在配置文件中的定义就和普通的命令(command)定义相同:


清单13

 

<chain name="sell-vehicle">
<command id="exceptionhandler"
 classname =
 "com.jadecove.chain.sample.sellvehicleexceptionhandler"/>
<command id="getcustomerinfo"
classname="com.jadecove.chain.sample.getcustomerinfo"/>


filter的execute方法按定义的序列调用。然而,它的postprocess方法将在链执行完毕或抛出错误后执行。当一个错误被抛出时,postprocess方法处理完后会返回true,表示错误处理已经完成。链的执行并不会就此结束,但是本质上来说这个错误被捕捉而且不会再向外抛出。如果postprocess方法返回false,那错误会继续向外抛出,然后链就会非正常结束。

让我们假设arrangefinancing因为用户信用卡损坏抛出错误。sellvehic


leexceptionhandler就能捕捉到这个错误,程序输出如下:


filter.execute() called.

get customer info

test drive the vehicle

negotiate sale

exception bad credit occurred.

 

结合了过滤器(filter)和子链技术后,你就可以造型很复杂的工作流程。

 [来源 www.iocblog.net]

commons chain是一个很有前途的框架,现在仍在开发,新的功能被频繁地添加到其中。在下一篇关于commons chain的文章中,我们将研究struts 1.3中是如何使用commons chain的。


struts 1.3中用完全使用commons chain的类替换了原来的处理http请求的类。如果你以前自己定制过struts的请求处理(request processor),你将发现处理这个问题时commons chain为程序带来了很好的灵活性。
 

上一页 [1] [2] [3]


Tag: jakarta



文章整理:iocblog
版权申明:本站文章均来自网络,如有侵权,请联系我们,我们收到后立即删除,谢谢!
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。