JBPM与设计模式之职责链模式

    上篇我们了解并学习了JBPM的长事务实现,其中用到了设计模式中的职责链模式和命令模式;这块还是很有厚重感的,我们可以从中学到很多的东西;今天我们先来学习一下职责链模式。

       职责链模式定义

       使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系;将这些对象连成一条链,并沿这条链传递该请求,直到有一个对象处理该请求。

       职责链模式的优点

       1.客户提交一个请求,其沿着这条链传递直到得到处理;

       2. 发送者和接受者都没有对方的明确信息信息;

       3. 链中对象也不知道链的结构,简化了链中对象的链接关系,它仅需要维持其后继者的引

用,而不用持有它所有的候选者;

    职责链模式UML图

   

        

      JBPM职责链模式UML

       下面结合JBPM的拦截器代码简单介绍一下这个模式

     Client:

客户端定制拦截器装配策略通过jbpm.tx.*.cfg.xml(本文结合hibernate讲解)中定义

       解析配置策略形成职责链是在流程引擎初始化时完成,JBPM中定义了两种拦截器装配策略

       同一个线程的命令嵌套调用的命令共用环境资源

    

View Code
 1 <command-service name="txRequiredCommandService">
 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>

   客户端的请求就是完成一定业务功能的脚本命令

  

View Code
 1 public interface Command<T> extends Serializable {
 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实现如下
   执行处理请求

 

View Code
 1 public interface CommandService {
 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 }

    职责链流传控制

   

View Code
 1 public abstract class Interceptor implements CommandService {
 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职责链执行流程



--

posted @ 2011-06-26 15:51  无风听海  阅读(949)  评论(0编辑  收藏  举报