上一篇博客中在末尾提到了自定义属于自己的引擎配置,然后自定义一个类,直接继承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>
效果如下
再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.youkuaiyun.com/jiangjunshow