activiti与spring集成

 

摘要: 一、集成配置 <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">     <property name="driverClass" value="org.

一、集成配置
<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
    <property name="driverClass" value="org.h2.Driver" />
    <property name="url" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000" />
    <property name="username" value="sa" />
    <property name="password" value="" />
  </bean>

  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
  </bean>

  <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
    <property name="dataSource" ref="dataSource" />
    <property name="transactionManager" ref="transactionManager" />
    <property name="databaseSchemaUpdate" value="true" />
    <property name="jobExecutorActivate" value="false" />
  </bean>

  <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
    <property name="processEngineConfiguration" ref="processEngineConfiguration" />
  </bean>

  <bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService" />
  <bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService" />
  <bean id="taskService" factory-bean="processEngine" factory-method="getTaskService" />
  <bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService" />
  <bean id="managementService" factory-bean="processEngine" factory-method="getManagementService" />
二、资源自动部署
为了定制发布方式,你可以为SpringProcessEngineConfiguration指定一个额外的参数deploymentMode。 
这个参数指定了匹配多个资源时的发布处理方式。默认下这个参数支持设置三个值:
  • default: 把所有资源放在一个单独的发布包中,对这个发布包进行重复检测。 这是默认值,如果你没有指定参数值,就会使用它。

  • single-resource: 为每个单独的资源创建一个发布包,并对这些发布包进行重复检测。 你可以单独发布每个流程定义,并在修改流程定义后只创建一个新的流程定义版本。

  • resource-parent-folder: 把放在同一个上级目录下的资源发布在一个单独的发布包中,并对发布包进行重复检测。 当需要多资源需要创建发布包,但是需要根据共同的文件夹来组合一些资源时,可以使用它。

<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
  ...
  
  
</bean>

 ===============================================================================================

Spring和Activiti的整合:

在Spring和Activiti的整合中ProcessEngineFactoryBean成为了两者的整合点。ProcessEngineFactoryBeanorg.activiti.spring.ProcessEngineFactoryBean。提供了ProcessEngine的配置和创建的功能。

 

<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">

    ...

</bean>

  

<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">

  <property name="processEngineConfiguration" ref="processEngineConfiguration" />

</bean>

如果在包含事物的activiti配置如下:
<beans xmlns="http://www.springframework.org/schema/beans" 

       xmlns:context="http://www.springframework.org/schema/context"

       xmlns:tx="http://www.springframework.org/schema/tx"

       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

                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd

                           http://www.springframework.org/schema/tx      http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

 <!-- 采用spring的数据源类创建一个数据源 -->

  <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">

    <property name="driverClass" value="org.h2.Driver" />

    <property name="url" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000" />

    <property name="username" value="sa" />

    <property name="password" value="" />

  </bean>

 <!-- 创建一个事物管理器 -->

  <bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

    <property name="dataSource" ref="dataSource" />

  </bean>

  <!-- 创建一个流程引擎的配置对象 -->

  <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">

    <property name="dataSource" ref="dataSource" />

    <property name="transactionManager" ref="transactionManager" />

    <!-- 设置数据库schema的更新方式 -->

    <property name="databaseSchemaUpdate" value="true" />

    <!-- 是否启动jobExecutor -->

    <property name="jobExecutorActivate" value="false" />

  </bean>

   <!-- 创建一个流程引擎bean -->

  <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">

    <property name="processEngineConfiguration" ref="processEngineConfiguration" />

  </bean>

  <!-- 创建activiti提供的各种服务 -->

  <!-- 工作流仓储服务 -->

  <bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService" />

  <!-- 工作流运行服务 -->

  <bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService" />

  <!--  工作流任务服务-->

  <bean id="taskService" factory-bean="processEngine" factory-method="getTaskService" />

  <!--  工作流历史数据服务-->

  <bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService" />

  <!--  工作流管理服务-->

  <bean id="managementService" factory-bean="processEngine" factory-method="getManagementService" />

  <!-- 工作流唯一服务 -->

  <bean id="IdentityService" factory-bean="processEngine" factory-method="getIdentityService" />

...工作流中Expressions的使用
   在使用springSpringProcessEngineConfiguration时,如果没有beans属性表示所有bean都可以暴露给activiti的流程文件xml访问。如果配置beans但是没有配置mapbean信息,则没有暴露的bean。如果map中配置部分bean表示只是暴露部分beanactiviti使用。

<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">

  ...

  <property name="beans">

    <map>

      <entry key="printer" value-ref="printer" />

    </map>

  </property>

</bean>

  

  <bean id="printer" class="org.activiti.examples.spring.Printer" />

暴露的bean可以在activiti的流程xml中使用。如下调用bean的方法
<bean id="printer" class="org.activiti.examples.spring.Printer" />
<definitions id="definitions" ...>

  

  <process id="helloProcess">

  

    <startEvent id="start" />

    <sequenceFlow id="flow1" sourceRef="start" targetRef="print" />

    

    <serviceTask id="print" activiti:expression="#{printer.printMessage()}" />

    <sequenceFlow id="flow2" sourceRef="print" targetRef="end" />

    

    <endEvent id="end" />

    

  </process>

 

</definitions>
public class Printer {

 

  public void printMessage() {

    System.out.println("hello world");

  }

}

自动资源部署(Automatic resource deploy)

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration("classpath:org/activiti/spring/test/junit4/springTypicalUsageTest-context.xml")

public class MyBusinessProcessTest {

  

  @Autowired

  private RuntimeService runtimeService;

  

  @Autowired

  private TaskService taskService;

  

  @Autowired

  @Rule

  public ActivitiRule activitiSpringRule;

  

  @Test

  @Deployment

  public void simpleProcessTest() {

    runtimeService.startProcessInstanceByKey("simpleProcess");

    Task task = taskService.createTaskQuery().singleResult();

    assertEquals("My Task", task.getName());

  

    taskService.complete(task.getId());

    assertEquals(0, runtimeService.createProcessInstanceQuery().count());

   

  }

}      
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">

  ...

  <property name="deploymentResources"value="classpath*:/org/activiti/spring/test/autodeployment/autodeploy.*.bpmn20.xml" />

</bean>

  

<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">

  <property name="processEngineConfiguration" ref="processEngineConfiguration" />

</bean>

Spring和activit的整合测试

当在spring的配置中配置ActivitiRule时候,测试bean将自动被注入:
<bean id="activitiRule" class="org.activiti.engine.test.ActivitiRule">

  <property name="processEngine" ref="processEngine" />

</bean>   

 

======================================自动部署所有流程=========================================

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd">
	<!--druid数据源-->
	<!--    <bean id ="dataSourceActiviti" class="com.alibaba.druid.pool.DruidDataSource">-->
	<!--采用内存数据库-->
	<!-- <property name="url" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000;MVCC=TRUE" />
     <property name="driverClassName" value="org.h2.Driver" />
     <property name="username" value="sa" />
     <property name="password" value="" />-->

	<!--自己本地的数据库-->
	<!--    <property name="url" value="jdbc:mysql://localhost:3306/activiti8unit?useUnicode=true&amp;characterEncoding=utf-8&amp;usessl=false" />
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="username" value="root" />
        <property name="password" value="root" />
        <property name="initialSize" value="1"/>
        <property name="maxActive" value="10"/>
        <property name="filters" value="stat,slf4j"/>
    </bean>-->


	<!--=====================================================================-->
	<!-- 配置数据源 -->
	<!--<bean id="dataSourceActiviti" class="org.apache.commons.dbcp.BasicDataSource"
		  destroy-method="close">
		<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
		<property name="url" value="jdbc:mysql://localhost:3306/activiti10unit?useUnicode=true&amp;characterEncoding=utf-8&amp;usessl=false"/>
		<property name="username" value="root"/>
		<property name="password" value="root"/>
		&lt;!&ndash; 初始化连接大小 &ndash;&gt;
		<property name="initialSize" value="1"></property>
		&lt;!&ndash; 连接池最大数量 &ndash;&gt;
		<property name="maxActive" value="10"></property>
		&lt;!&ndash; 连接池最大空闲 &ndash;&gt;
		<property name="maxIdle" value="10"></property>
		&lt;!&ndash; 连接池最小空闲 &ndash;&gt;
		<property name="minIdle" value="2"></property>
		&lt;!&ndash; 获取连接最大等待时间 &ndash;&gt;
		<property name="maxWait" value="10000"></property>
	</bean>-->


<!--	<bean id="dataSourceActiviti" class="org.apache.commons.dbcp.BasicDataSource"
		  destroy-method="close">
		<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
		<property name="url" value="jdbc:mysql://localhost:3306/activiti10unit?useUnicode=true&amp;characterEncoding=utf-8&amp;usessl=false"/>
		<property name="username" value="root"/>
		<property name="password" value="root"/>
		&lt;!&ndash; 初始化连接大小 &ndash;&gt;
		<property name="initialSize" value="1"></property>
		&lt;!&ndash; 连接池最大数量 &ndash;&gt;
		<property name="maxActive" value="10"></property>
		&lt;!&ndash; 连接池最大空闲 &ndash;&gt;
		<property name="maxIdle" value="10"></property>
		&lt;!&ndash; 连接池最小空闲 &ndash;&gt;
		<property name="minIdle" value="2"></property>
		&lt;!&ndash; 获取连接最大等待时间 &ndash;&gt;
		<property name="maxWait" value="10000"></property>
	</bean>-->


	<!-- 单独创建事物管理器-->
	<!--<bean id="transactionManager1" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		&lt;!&ndash;<property name="dataSource" ref="dataSourceActiviti"/> 数据源分开&ndash;&gt;
		<property name="dataSource" ref="dataSource"/> &lt;!&ndash;用同一个数据源&ndash;&gt;
	</bean>-->
	<!--Spring集成-->
	<!--要单独创建数据库,因为speing要单独对我们的事物做处理 事物是基于数据库的事物-->
	<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
		<!--<property name="dataSource" ref="dataSourceActiviti"/> 数据源分开-->
		<property name="dataSource" ref="dataSource"/> <!--用同一个数据源-->
		<!--数据库策略-->

		<property name="databaseSchemaUpdate" value="true" />
		<!--注入事物管理器-->
		<property name="transactionManager" ref="transactionManager"/>
		<!--<property name="jobExecutorActivate" value="false" />-->
            <!--如果配自动部署会导致每次启动都会部署一次,需要注意解决方法:具体见文章下面-->
		<property name="deploymentResources" value="classpath:/activitit-bpmn20/*.*.xml"/>

		<!--是否使用历史数据-->
		<property name="dbHistoryUsed" value="true"/>
		<!--是否使用身份数据-->
		<property name="dbIdentityUsed" value="true"/>
        <!--所有表结构加前缀 开头-->
		<!--<property name="databaseTablePrefix" value="t_"/>-->

		<!--默认属性,流程引擎可以根据传进去数据库的url 驱动等自动判断数据库,所以这个配置可以省略-->
		<!--<property name="databaseType" value="mysql"/>-->

		<!--记录历史详情的级别 共4个级别 -->
		<!--<property name="history" value="none" /> -->      <!-- 不记录历史流程,性能高,流程结束后不可读-->
		<!--<property name="history" value="activity" />-->   <!-- 归档流程实例和活动实例,流程变量不同步-->
		<!--<property name="history" value="audit" />-->      <!-- 默认值,在activiti基础上同步变量值,保持表单属性-->
		<property name="history" value="full" />              <!--全部记录,性能较差,记录所有实例和变量的细节变化-->

		<!--是否开启我们的事件日志 true开启 act_evt_log -->
		<property name="enableDatabaseEventLogging" value="true"/>

		<!--事件处理及监听器配置:1 list -->
		<!--<property name="eventListeners">
			<list>
				&lt;!&ndash;自定义监听类&ndash;&gt;
				<bean class="su.activiti.event.ProcessEventListener"/>
			</list>
		</property>-->

		<!--事件处理及监听器配置:2 map -->
	<!--	<property name="typedEventListeners">
		<map>
			<entry key="PROCESS_STARTED"> &lt;!&ndash; 配置key以后只打印PROCESS_STARTED 对应的流程启动日志&ndash;&gt;
				<list>
					<bean class="su.activiti.event.ProcessEventListener"/>
				</list>
			</entry>
		</map>
		</property>-->

		<!-- 配置自定义MDCComandInvoder 拦截器 引入自己定义的bean -->
		<!--<property name="commandInvoker" ref="comandInvoder" />-->

		<!--命令拦截器-->
	<!--	<property name="customPreCommandInterceptors">
			<list>   &lt;!&ndash;这个配置好像有问题配置后 test 测试 流程启动报错   java.lang.IllegalStateException: Failed to load ApplicationContext&ndash;&gt;
				&lt;!&ndash;定义一个拦截器统计这个命令执行的时间是多少&ndash;&gt;
				<bean class="su.activiti.interceptor.DurationCommandInterceptor" />
			</list>
		</property>-->


	</bean>


	<!--	<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
                <property name="dataSource" ref="dataSourceActiviti"/>
                <property name="databaseSchemaUpdate" value="true"/>
            </bean>-->

	<bean id="comandInvoder" class="su.activiti.interceptor.MDCComandInvoder" />

	<!--构造流程引擎对象-->
	<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
		<!--指定流程引擎配置对象-->
		<property name="processEngineConfiguration" ref="processEngineConfiguration"/>
	</bean>

	<!--把服务暴露给Spring-->
	<!-- 创建activiti提供的各种服务 -->
	<!-- 工作流仓储服务 --> <!--部署流程定义文件-->
	<bean id="repositoryService" factory-bean="processEngine"
		  factory-method="getRepositoryService" />
	<!-- 工作流运行服务 -->
	<bean id="runtimeService" factory-bean="processEngine"
		  factory-method="getRuntimeService" />
	<!-- 工作流任务服务 -->
	<bean id="taskService" factory-bean="processEngine"
		  factory-method="getTaskService" />
	<!-- 工作流历史数据服务 -->
	<bean id="historyService" factory-bean="processEngine"
		  factory-method="getHistoryService" />
	<!-- 工作流管理服务 -->
	<bean id="managementService" factory-bean="processEngine"
		  factory-method="getManagementService" />
	<!-- 工作流唯一服务(用户服务) -->
	<bean id="identityService" factory-bean="processEngine" factory-method="getIdentityService"/>

	<!-- 表单服务 -->
	<bean id="formService" factory-bean="processEngine" factory-method="getFormService"/>
	<bean id="dynamicBpmnService" factory-bean="processEngine" factory-method="getDynamicBpmnService"/>


	<!--配置测试 Rule-->
	<!--
        <bean id="activitiRule" class="org.activiti.engine.test.ActivitiRule">
            <property name="processEngine"  ref="processEngine"/>
        </bean>
    -->
	<!-- <bean id="helloBean" class="com.su.test.HelloBean"></bean>-->
	<!--=====================================================================-->
</beans>

 

========================注意:===============================

下面方法是转载过来的没经过验证;

转自: https://lucky16.iteye.com/blog/1740239

Activiti 整合spring的时候,提供了一个自动部署的特性: 

 这样当每次启动web容器的时候就会把指定路径的流程资源文件部署到Activiti DB上。不过这样会产生一个问题,资源文件在没经过任何改动的情况下,特别是我们在做Testing的时候,还是会重新部署一个新的版本到DB上,这样会造成不别要的重复部署。我们在部署之前,应该先判断资源文件是否有改动过,如果有,才部署新版本到DB上。 

实现这个功能很简单,只需要建立一个实现了 InitializingBean 接口的 spring bean,在afterPropertiesSet()方法里面进行判断和部署就可以了。 

Java代码:

/** 
 *  
 */  
package com.highcolu.dms.workflow;  
  
import java.io.File;  
import java.io.FileOutputStream;  
import java.io.InputStream;  
import java.io.OutputStream;  
import java.util.List;  
  
import org.activiti.engine.ActivitiException;  
import org.activiti.engine.RepositoryService;  
import org.activiti.engine.repository.Deployment;  
import org.apache.commons.io.FileUtils;  
import org.apache.commons.io.IOUtils;  
import org.apache.commons.logging.Log;  
import org.apache.commons.logging.LogFactory;  
import org.springframework.beans.BeansException;  
import org.springframework.beans.FatalBeanException;  
import org.springframework.beans.factory.InitializingBean;  
import org.springframework.context.ApplicationContext;  
import org.springframework.context.ApplicationContextAware;  
import org.springframework.core.io.Resource;  
  
/** 
 * @Description:结合Spring自动部署Activit流程定义文件 
 * @version:2012-12-20 
 * @author: <a href="mailto:zhouwentao16@gmail.com">周文滔</a> 
 */  
public class WorkflowDeployer implements InitializingBean,  
        ApplicationContextAware {  
  
    private static final Log LOGGER = LogFactory.getLog(WorkflowDeployer.class);  
    private Resource[] deploymentResources;  
    private String category;  
    ApplicationContext appCtx;  
  
    public void setDeploymentResources(Resource[] resources) {  
        this.deploymentResources = resources;  
    }  
  
    public void setCategory(String category) {  
        this.category = category;  
    }  
  
    @Override  
    public void setApplicationContext(ApplicationContext applicationContext)  
            throws BeansException {  
        this.appCtx = applicationContext;  
    }  
  
    @Override  
    public void afterPropertiesSet() throws Exception {  
        if (category == null) {  
            throw new FatalBeanException("缺失属性 : category");  
        }  
        if (deploymentResources != null) {  
            RepositoryService repositoryService = appCtx  
                    .getBean(RepositoryService.class);  
            for (Resource r : deploymentResources) {  
                String deploymentName = category + "_" + r.getFilename();  
                String resourceName = r.getFilename();  
                boolean doDeploy = true;  
                List<Deployment> deployments = repositoryService  
                        .createDeploymentQuery().deploymentName(deploymentName)  
                        .orderByDeploymenTime().desc().list();  
                if (!deployments.isEmpty()) {  
                    Deployment existing = deployments.get(0);  
                    try {  
                        InputStream in = repositoryService.getResourceAsStream(  
                                existing.getId(), resourceName);  
                        if (in != null) {  
                            File f = File.createTempFile(  
                                    "deployment",  
                                    "xml",  
                                    new File(System  
                                            .getProperty("java.io.tmpdir")));  
                            f.deleteOnExit();  
                            OutputStream out = new FileOutputStream(f);  
                            IOUtils.copy(in, out);  
                            in.close();  
                            out.close();  
                            doDeploy = (FileUtils.checksumCRC32(f) != FileUtils  
                                    .checksumCRC32(r.getFile()));  
                        } else  
                            throw new ActivitiException("不能读取资源 "  
                                    + resourceName + ", 输入流为空");  
                    } catch (ActivitiException ex) {  
                        LOGGER.error("Unable to read " + resourceName  
                                + " of deployment " + existing.getName()  
                                + ", id: " + existing.getId()  
                                + ", will re-deploy");  
                    }  
                }  
                if (doDeploy) {  
                    repositoryService.createDeployment().name(deploymentName)  
                            .addInputStream(resourceName, r.getInputStream())  
                            .deploy();  
                    LOGGER.warn("文件部署成功 : " + r.getFilename());  
                }  
            }  
        }  
    }  
  
}  

然后在spring的配置文件里面配置好这个bean就可以了.

<bean id="workflowDeployer"  
    class="com.jeemis.workflow.deployer.WorkflowDeployer">  
    <property name="category" value="TEST" />  
    <property name="deploymentResources" value="classpath*:process/TEST.bpmn20.xml" />  
</bean>  

 

=====================================================================================

 

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_无往而不胜_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值