JBPM与设计模式之职责链模式
上篇我们了解并学习了JBPM的长事务实现,其中用到了设计模式中的职责链模式和命令模式;这块还是很有厚重感的,我们可以从中学到很多的东西;今天我们先来学习一下职责链模式。
职责链模式定义
使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系;将这些对象连成一条链,并沿这条链传递该请求,直到有一个对象处理该请求。
职责链模式的优点
1.客户提交一个请求,其沿着这条链传递直到得到处理;
2. 发送者和接受者都没有对方的明确信息信息;
3. 链中对象也不知道链的结构,简化了链中对象的链接关系,它仅需要维持其后继者的引
用,而不用持有它所有的候选者;
职责链模式UML图
JBPM职责链模式UML图
下面结合JBPM的拦截器代码简单介绍一下这个模式
Client:
客户端定制拦截器装配策略通过jbpm.tx.*.cfg.xml(本文结合hibernate讲解)中定义
解析配置策略形成职责链是在流程引擎初始化时完成,JBPM中定义了两种拦截器装配策略
同一个线程的命令嵌套调用的命令共用环境资源
2 <skip-interceptor />
3 <retry-interceptor />
4 <environment-interceptor />
5 <standard-transaction-interceptor />
6 </command-service>
7 每个命令调用都新建环境资源
8 <command-service name="newTxRequiredCommandService">
9 <retry-interceptor />
10 <environment-interceptor policy="requiresNew" />
11 <standard-transaction-interceptor />
12 </command-service>
客户端的请求就是完成一定业务功能的脚本命令
2
3 T execute(Environment environment) throws Exception;
4 }
5
6 public class SaveTaskCmd extends AbstractCommand<String> {
7
8 private static final long serialVersionUID = 1L;
9
10 protected TaskImpl task;
11
12 public SaveTaskCmd(TaskImpl task) {
13 this.task = task;
14 }
15
16 public String execute(Environment environment) throws Exception {
17 DbSession dbSession = environment.get(DbSession.class);
18
19 if (task.isNew()) {
20 if (task.getSuperTaskDbid()!=null) {
21 TaskImpl parentTask = dbSession.get(TaskImpl.class, task.getSuperTaskDbid());
22 parentTask.addSubTask(task);
23 task.setSuperTaskDbid(null);
24 }
25
26 dbSession.save(task);
27
28 HistoryEvent.fire(new TaskCreated(task));
29
30 } else {
31 dbSession.update(task);
32
33 HistoryEvent.fire(new TaskUpdated(task));
34 }
35
36 return task.getId();
37 }
38 }
客户端调用
taskService. assignTask(task.getId(),userId);
ChainHandle:
JBPM并没用完全照搬职责链的定义, 虽然在每个拦截器中都可以处理请求,但是JBPM设计的只能在DefaultCommandService里处理请求,然后再拦截器中处理环境资源初始化和长事务的管理等。
根据以上分析,职责链ChainHandler实现如下
执行处理请求
2
3 String NAME_TX_REQUIRED_COMMAND_SERVICE = "txRequiredCommandService";
4 String NAME_NEW_TX_REQUIRED_COMMAND_SERVICE = "newTxRequiredCommandService";
5
6 /**
7 * @throws JbpmException if command throws an exception.
8 */
9 <T> T execute(Command<T> command);
10 }
11
12 public class DefaultCommandService implements CommandService {
13
14 private static final Log log = Log.getLog(DefaultCommandService.class.getName());
15
16 public <T> T execute(Command<T> command) {
17 EnvironmentImpl environment = EnvironmentImpl.getCurrent();
18
19 try {
20 return command.execute(environment);
21
22 } catch (RuntimeException e) {
23 log.info("exception while executing command "+command, e);
24 throw e;
25
26 } catch (Exception e) {
27 log.info("exception while executing command "+command, e);
28 throw new JbpmException("exception while executing command "+command, e);
29 }
30 }
31 }
职责链流传控制
2
3 protected CommandService next;
4
5 public CommandService getNext() {
6 return next;
7 }
8 public void setNext(CommandService next) {
9 this.next = next;
10 }
11 }
12
13 public class SkipInterceptor extends Interceptor {
14
15 static DefaultCommandService defaultCommandService = new DefaultCommandService();
16
17 public <T> T execute(Command<T> command) {
18 EnvironmentImpl environment = EnvironmentImpl.getCurrent();
19 // if there is an environment active
20 if (environment!=null) {
21 // skip the rest of the interceptor stack and just execute the command
22 return defaultCommandService.execute(command);
23 }
24
25 return next.execute(command);
26 }
27
28 }
JBPM职责链执行流程
-- |