Activiti入门教程4(自定义Activiti命令拦截器)
Activiti入门教程四(自定义Activiti命令拦截器)
上一篇博客中在末尾提到了自定义属于自己的引擎配置,然后自定义一个类,直接继承ProcessEngineConfigurationImpl类即可,但必须要实现两个抽象的方法,如下
protected abstract Collection< ? extends CommandInterceptor> getDefaultCommandInterceptorsTxRequired();
protected abstract Collection< ? extends CommandInterceptor> getDefaultCommandInterceptorsTxRequiresNew();
如果英文好的人,应该就看出来了,这就是Activiti中的拦截器,其实拦截器的原理采用了设计模式中的命令模式和责任链模式,关于设计模式请参考职责链模式。
下面就先来通过源码分析,来谈一下Activiti中拦截器的执行过程。
当初始化流程引擎的时候,会执行下面的方法
<span style="font-family:Comic Sans MS;font-size:18px;"><span style="font-family:Comic Sans MS;font-size:18px;"> public ProcessEngine buildProcessEngine() { init(); return new ProcessEngineImpl(this); }</span></span>
下面我们再通过源码来看一下Init()方法
<span style="font-family:Comic Sans MS;font-size:18px;"><span style="font-family:Comic Sans MS;font-size:18px;">protected void init() { initHistoryLevel(); initExpressionManager(); initVariableTypes(); initBeans(); initFormEngines(); initFormTypes(); initScriptingEngines(); initBusinessCalendarManager(); initCommandContextFactory(); initTransactionContextFactory(); initCommandExecutors(); initServices(); initIdGenerator(); initDeployers(); initJobExecutor(); initDataSource(); initTransactionFactory(); initSqlSessionFactory(); initSessionFactories(); initJpa(); initDelegateInterceptor(); initEventHandlers(); initFailedJobCommandFactory(); initConfigurators(); } </span></span>
<span style="font-family:Comic Sans MS;font-size:18px;"><span style="font-family:Comic Sans MS;font-size:18px;"> public ProcessEngineImpl(ProcessEngineConfigurationImpl processEngineConfiguration) { this.processEngineConfiguration = processEngineConfiguration; this.name = processEngineConfiguration.getProcessEngineName(); this.repositoryService = processEngineConfiguration.getRepositoryService(); this.runtimeService = processEngineConfiguration.getRuntimeService(); this.historicDataService = processEngineConfiguration.getHistoryService(); this.identityService = processEngineConfiguration.getIdentityService(); this.taskService = processEngineConfiguration.getTaskService(); this.formService = processEngineConfiguration.getFormService(); this.managementService = processEngineConfiguration.getManagementService(); this.databaseSchemaUpdate = processEngineConfiguration.getDatabaseSchemaUpdate(); this.jobExecutor = processEngineConfiguration.getJobExecutor(); this.commandExecutor = processEngineConfiguration.getCommandExecutorTxRequired(); this.sessionFactories = processEngineConfiguration.getSessionFactories(); this.transactionContextFactory = processEngineConfiguration.getTransactionContextFactory(); commandExecutor.execute(new SchemaOperationsProcessEngineBuild()); if (name == null) { log.info("default activiti ProcessEngine created"); } else { log.info("ProcessEngine {} created", name); } ProcessEngines.registerProcessEngine(this); if ((jobExecutor != null) && (jobExecutor.isAutoActivate())) { jobExecutor.start(); } if(processEngineConfiguration.getProcessEngineLifecycleListener() != null) { processEngineConfiguration.getProcessEngineLifecycleListener().onProcessEngineBuilt(this); } }</span></span>
上面讲述了拦截器的执行时机,下面就来自定义一个拦截器
拦截器A
<span style="font-family:Comic Sans MS;font-size:18px;"><span style="font-family:Comic Sans MS;font-size:18px;">package org.crazyit.activiti; import org.activiti.engine.impl.interceptor.Command; import org.activiti.engine.impl.interceptor.CommandInterceptor; /** * 拦截器实现A * */ public class InterceptorA extends CommandInterceptor { public <T> T execute(Command<T> command) { // 输出字符串和命令 System.out.println("this is interceptor A " + command.getClass().getName()); // 然后让责任链中的下一请求处理者处理命令 return next.execute(command); } } </span></span>
<span style="font-family:Comic Sans MS;font-size:18px;"><span style="font-family:Comic Sans MS;font-size:18px;">package org.crazyit.activiti; import org.activiti.engine.impl.interceptor.Command; import org.activiti.engine.impl.interceptor.CommandInterceptor; public class InterceptorB extends CommandInterceptor { @Override public <T> T execute(Command<T> command) { // 输出字符串和命令 System.out.println("this is interceptor B " + command.getClass().getName()); // 然后让责任链中的下一请求处理者处理命令 return next.execute(command); } } </span></span>
然后自定义流程引擎配置,并在其中添加我们的拦截器即可
<span style="font-family:Comic Sans MS;font-size:18px;"><span style="font-family:Comic Sans MS;font-size:18px;">package org.crazyit.activiti; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.activiti.engine.ProcessEngine; import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl; import org.activiti.engine.impl.context.Context; import org.activiti.engine.impl.interceptor.CommandContextInterceptor; import org.activiti.engine.impl.interceptor.CommandInterceptor; import org.activiti.engine.impl.interceptor.LogInterceptor; /** * 自定义配置类 */ public class TestConfiguration extends ProcessEngineConfigurationImpl { protected Collection<? extends CommandInterceptor> getDefaultCommandInterceptorsTxRequired() { // 创建一个拦截器集合 List<CommandInterceptor> defaultCommandInterceptorsTxRequired = new ArrayList<CommandInterceptor>(); // 添加自定义拦截器A defaultCommandInterceptorsTxRequired.add(new InterceptorA()); // 添加系统的拦截器 defaultCommandInterceptorsTxRequired.add(new CommandContextInterceptor( commandContextFactory, this)); return defaultCommandInterceptorsTxRequired; } protected Collection<? extends CommandInterceptor> getDefaultCommandInterceptorsTxRequiresNew() { // 创建一个拦截器集合 List<CommandInterceptor> defaultCommandInterceptorsTxRequired = new ArrayList<CommandInterceptor>(); // 添加自定义拦截器 defaultCommandInterceptorsTxRequired.add(new InterceptorB()); return defaultCommandInterceptorsTxRequired; } } </span></span>
这样就完成了我们的自定义拦截器的操作,下面来通过XML文件配置相关的数据库信息
<span style="font-family:Comic Sans MS;font-size:18px;"><?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 配置自定义属性 --> <bean id="processEngineConfiguration" class="org.crazyit.activiti.TestConfiguration"> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/activiti" /> <property name="jdbcDriver" value="com.mysql.jdbc.Driver" /> <property name="jdbcUsername" value="root" /> <property name="jdbcPassword" value="" /> <property name="databaseSchemaUpdate" value="true"></property> </bean> </beans> </span>
最后看一下测试类
<span style="font-family:Comic Sans MS;font-size:18px;">package org.crazyit.activiti; import java.util.HashMap; import java.util.Map; import org.activiti.engine.ProcessEngine; import org.activiti.engine.ProcessEngineConfiguration; import org.activiti.engine.ProcessEngines; public class MyConfig { /** * @param args */ public static void main(String[] args) { ProcessEngines.getDefaultProcessEngine(); // 创建Activiti配置对象 ProcessEngineConfiguration config = ProcessEngineConfiguration .createProcessEngineConfigurationFromResource("my-config.xml"); // 初始化流程引擎 ProcessEngine engine = config.buildProcessEngine(); // 部署一个最简单的流程 engine.getRepositoryService().createDeployment() .addClasspathResource("bpmn/config.bpmn20.xml").deploy(); // 构建流程参数 Map<String, Object> vars = new HashMap<String, Object>(); vars.put("day", 10); // 开始流程 engine.getRuntimeService().startProcessInstanceByKey("vacationProcess", vars); } }</span>
效果如下
版权声明:本文为博主原创文章,未经博主允许不得转载。