Spring集成使用工作流框架Activiti!事务配置,注解配置以及流程资源自动化部署

简介: 本文详尽地说明了如何在Spring项目中集成使用工作流Activiti框架。介绍了在Spring框架的项目中使用工作流Activti框架时事务的配置,表达式的使用,资源的自动化部署,单元测试以及基于注解的配置。通过这篇文章介绍的工作流框架Activiti集成到Spring项目中的使用,可以让我们更加能够熟练的在项目中使用工作流Activti框架。

Spring使用Activiti提供了一些非常不错的集成特性,只在Activiti与Spring集成时使用

ProcessEngineFactoryBean

  • 可以把流程引擎(ProcessEngine)作为一个普通的Spring bean进行配置
  • org.activiti.spring.ProcessEngineFactoryBean是集成的切入点,这个bean需要一个流程引擎配置来创建流程引擎
  • Spring集成的配置和流程引擎bean,使用的processEngineConfiguration beanorg.activiti.spring.SpringProcessEngineConfiguration类:
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
    ...
</bean>

<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
  <property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>
AI 代码解读

事务

  • 使用这个例子的Spring配置文件SpringTransactionIntegrationTest-context.xml:

    • dataSource: 数据源
    • transactionManager: 事务管理器
    • processEngine: 流程引擎
    • Activiti引擎服务
  • 当把数据源(DataSource)传递给SpringProcessEngineConfiguration(使用"dataSource"属性)之后,Activiti内部使用了一个org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy代理来封装传递进来的数据源(DataSource).这样做是为了确保从数据源(DataSource)获取的SQL连接能够与Spring的事物结合在一起发挥得更出色.这意味不需要在Spring配置中代理数据源(dataSource). 但是仍然允许传递一个TransactionAwareDataSourceProxySpringProcessEngineConfiguration
  • 为了确保在Spring配置中声明的一个TransactionAwareDataSourceProxy,不能把使用它的应用交给Spring事物控制的资源(例如DataSourceTransactionManagerJPATransactionManager需要非代理的数据源)
<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">

  <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" />

...
AI 代码解读
  • Spring配置文件的其余部分包含beans和在特有的例子中的配置:
<beans>
  ...
  <tx:annotation-driven transaction-manager="transactionManager"/>

  <bean id="userBean" class="org.activiti.spring.test.UserBean">
    <property name="runtimeService" ref="runtimeService" />
  </bean>

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

</beans>
AI 代码解读
  • 首先使用任意的一种Spring创建应用上下文的方式创建其Spring应用上下文.可以使用类路径下面的XML资源来配置我们的Spring应用上下文:
ClassPathXmlApplicationContext applicationContext =
    new ClassPathXmlApplicationContext("org/activiti/examples/spring/SpringTransactionIntegrationTest-context.xml");
AI 代码解读

或者

@ContextConfiguration("classpath:org/activiti/spring/test/transaction/SpringTransactionIntegrationTest-context.xml")
AI 代码解读
  • 然后我们就可以得到Activiti的服务beans并且调用该服务上面的方法,ProcessEngineFactoryBean将会对该服务添加一些额外的拦截器,在Activiti服务上面的方法使用的是Propagation.REQUIRED事物语义. 可以使用repositoryService去部署一个流程:
RepositoryService repositoryService = (RepositoryService) applicationContext.getBean("repositoryService");
String deploymentId = repositoryService
  .createDeployment()
  .addClasspathResource("org/activiti/spring/test/hello.bpmn20.xml")
  .deploy()
  .getId();   
AI 代码解读
  • 其他相同的服务也是同样可以这么使用.在这个例子中,Spring的事务将会围绕在userBean.hello()上,并且调用Activiti服务的方法也会加入到这个事务中
UserBean userBean = (UserBean) applicationContext.getBean("userBean");
userBean.hello();
AI 代码解读
  • 在上面Spring bean的配置中把repositoryService注入到userBean中
public class UserBean {

  /** 由Spring注入 */
  private RuntimeService runtimeService;

  @Transactional
  public void hello() {
        //这里,你可以在你们的领域模型中做一些事物处理。
        //当在调用Activiti RuntimeService的startProcessInstanceByKey方法时,
        //它将会结合到同一个事物中。
    runtimeService.startProcessInstanceByKey("helloProcess");
  }

  public void setRuntimeService(RuntimeService runtimeService) {
    this.runtimeService = runtimeService;
  }
}
AI 代码解读

表达式

  • 当使用ProcessEngineFactoryBean时候,默认情况下,在BPMN流程中的所有表达式都将会"看见"所有的Spring beans. 可以限制在表达式中暴露出的beans或者甚至可以在配置中使用一个Map不暴露任何beans
  • 想要不暴露任何beans,只需要在SpringProcessEngineConfiguration中传递一个空的list作为'beans'的属性. 当不设置'beans'的属性时,在应用上下文中Spring beans都是可以使用的
  • 下面的例子暴露了一个单例bean(printer),可以把"printer"当作关键字使用:
<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" />
AI 代码解读
  • 现在暴露出来的beans就可以在表达式中使用:例如,在SpringTransactionIntegrationTest中的hello.bpmn20.xml展示的是如何使用UEL方法表达式去调用Spring bean的方法
<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>
AI 代码解读
  • 这里的Printer类似这样:
public class Printer {

  public void printMessage() {
    System.out.println("hello world");
  }
}
AI 代码解读
  • Spring bean的配置类似这样:
<beans ...>
  ...

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

</beans>
AI 代码解读

资源自动部署

  • Spring的集成有专门针对对资源部署的特性
  • 在流程引擎的配置中,可以指定一组资源,当流程引擎被创建的时候,所有在这里的资源都将会被自动扫描与部署
  • 在这里有过滤以防止资源重新部署,只有当这个资源真正发生改变的时候,它才会向Activiti使用的数据库创建新的部署.
  • 这对于很多用例来说,当Spring容器经常重启的情况下,使用是非常不错的选择
<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>
AI 代码解读

默认情况下,上面的配置会把所有匹配的资源发布到Activiti引擎的一个单独发布包下.用来检测防止未修改资源重复发布的机制会作用到整个发布包中
有时候,这可能不是想要的.比如,如果你发布了很多流程资源,但是只修改里其中某一个单独的流程定义,整个发布包都会被认为变更了,导致整个发布包下的所有流程定义都会被重新发布,结果就是每个流程定义都生成了新版本,虽然其中只有一个流程发生了改变

  • 为了定制发布方式, 可以为SpringProcessEngineConfiguration指定一个额外的参数deploymentMode. 这个参数指定了匹配多个资源时的发布处理方式. 默认下这个参数支持设置三个值:

    • default: 把所有资源放在一个单独的发布包中,对这个发布包进行重复检测.这是默认值,如果你没有指定参数值,就会使用它
    • single-resource: 为每个单独的资源创建一个发布包,并对这些发布包进行重复检测.你可以单独发布每个流程定义,并在修改流程定义后只创建一个新的流程定义版本
    • resource-parent-folder: 把放在同一个上级目录下的资源发布在一个单独的发布包中,并对发布包进行重复检测.当需要多资源时需要创建发布包;但是需要根据共同的文件夹来组合一些资源时,可以使用
  • deploymentMode参数配置为single-resource的情况:
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
  ...
  <property name="deploymentResources" value="classpath*:/activiti/*.bpmn" />
  <property name="deploymentMode" value="single-resource" />
</bean>
AI 代码解读
  • 如果想使用上面三个值之外的参数值,你需要自定义处理发布包的行为.可以创建一个SpringProcessEngineConfiguration的子类,重写getAutoDeploymentStrategy(String deploymentMode)方法. 这个方法中处理了对应deploymentMode的发布策略

单元测试

  • 当集成Spring时,使用标准的Activiti测试工具类是非常容易地对业务流程进行测试:
@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());

  }
}
AI 代码解读
  • 对于这种方式,需要在Spring配置中定义一个org.activiti.engine.test.ActivitiRulebean
<bean id="activitiRule" class="org.activiti.engine.test.ActivitiRule">
  <property name="processEngine" ref="processEngine" />
</bean>
AI 代码解读

基于注解的配置

除了基于XML的配置以外,还可以选择基于注解的方式来配置Spring环境.这与使用XML的方法非常相似,除了要使用@Bean注解.而且配置是使用java编写的, 可以直接用于Activiti-Spring的集成

  • @EnableActiviti: 会创建一个Spring环境,并对Activiti流程引擎进行配置

    • 默认的内存H2数据库,启用数据库自动升级
    • 一个简单的DataSourceTransactionManager
    • 一个默认的SpringJobExecutor
    • 自动扫描processes/ 目录下的bpmn20.xml文件
  @Configuration
  @EnableActiviti
  public static class SimplestConfiguration {

  }
AI 代码解读
  • 可以直接通过注入操作Activiti引擎:
 @Autowired
  private ProcessEngine processEngine;

  @Autowired
  private RuntimeService runtimeService;

  @Autowired
  private TaskService taskService;

  @Autowired
  private HistoryService historyService;

  @Autowired
  private RepositoryService repositoryService;

  @Autowired
  private ManagementService managementService;

  @Autowired
  private FormService formService;
AI 代码解读
  • 默认值都可以自定义:

    • 如果配置了DataSource,就会代替默认创建的数据库配置
    • 事务管理器,ob执行器和其他组件都与之相同
@Configuration
  @EnableActiviti
  public static class Config {

    @Bean
    public DataSource dataSource() {
        BasicDataSource basicDataSource = new BasicDataSource();
        basicDataSource.setUsername("sa");
        basicDataSource.setUrl("jdbc:h2:mem:anotherDatabase");
        basicDataSource.setDefaultAutoCommit(false);
        basicDataSource.setDriverClassName(org.h2.Driver.class.getName());
        basicDataSource.setPassword("");
        return basicDataSource;
    }

  }
AI 代码解读

其他数据库会代替默认的

  • 注意AbstractActivitiConfigurer用法,它暴露了流程引擎的配置,可以用来对它的细节进行详细的配置:
@Configuration
@EnableActiviti
@EnableTransactionManagement(proxyTargetClass = true)
class JPAConfiguration {

    @Bean
    public OpenJpaVendorAdapter openJpaVendorAdapter() {
        OpenJpaVendorAdapter openJpaVendorAdapter = new OpenJpaVendorAdapter();
        openJpaVendorAdapter.setDatabasePlatform(H2Dictionary.class.getName());
        return openJpaVendorAdapter;
    }

    @Bean
    public DataSource dataSource() {
        BasicDataSource basicDataSource = new BasicDataSource();
        basicDataSource.setUsername("sa");
        basicDataSource.setUrl("jdbc:h2:mem:activiti");
        basicDataSource.setDefaultAutoCommit(false);
        basicDataSource.setDriverClassName(org.h2.Driver.class.getName());
        basicDataSource.setPassword("");
        return basicDataSource;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(
        OpenJpaVendorAdapter openJpaVendorAdapter, DataSource ds) {
        LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
        emf.setPersistenceXmlLocation("classpath:/org/activiti/spring/test/jpa/custom-persistence.xml");
        emf.setJpaVendorAdapter(openJpaVendorAdapter);
        emf.setDataSource(ds);
        return emf;
    }

    @Bean
    public PlatformTransactionManager jpaTransactionManager(
        EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }

    @Bean
    public AbstractActivitiConfigurer abstractActivitiConfigurer(
        final EntityManagerFactory emf,
        final PlatformTransactionManager transactionManager) {

        return new AbstractActivitiConfigurer() {

            @Override
            public void postProcessSpringProcessEngineConfiguration(SpringProcessEngineConfiguration engine) {
                engine.setTransactionManager(transactionManager);
                engine.setJpaEntityManagerFactory(emf);
                engine.setJpaHandleTransaction(false);
                engine.setJobExecutorActivate(false);
                engine.setJpaCloseEntityManager(false);
                engine.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
            }
        };
    }

    // A random bean
    @Bean
    public LoanRequestBean loanRequestBean() {
        return new LoanRequestBean();
    }
}
AI 代码解读

JPA和Hibernate

  • 在Activiti引擎的serviceTasklistener中使用Hibernate 4.2.x JPA时,需要添加Spring ORM依赖,Hibernate 4.1.x及以下版本是不需要的:
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-orm</artifactId>
  <version>${org.springframework.version}</version>
</dependency>
AI 代码解读
目录
打赏
0
0
0
0
1278
分享
相关文章
|
1月前
|
微服务——SpringBoot使用归纳——Spring Boot中集成 Shiro——Shiro 身份和权限认证
本文介绍了 Apache Shiro 的身份认证与权限认证机制。在身份认证部分,分析了 Shiro 的认证流程,包括应用程序调用 `Subject.login(token)` 方法、SecurityManager 接管认证以及通过 Realm 进行具体的安全验证。权限认证部分阐述了权限(permission)、角色(role)和用户(user)三者的关系,其中用户可拥有多个角色,角色则对应不同的权限组合,例如普通用户仅能查看或添加信息,而管理员可执行所有操作。
77 0
微服务——SpringBoot使用归纳——Spring Boot 中集成Redis——Redis 介绍
本文介绍在 Spring Boot 中集成 Redis 的方法。Redis 是一种支持多种数据结构的非关系型数据库(NoSQL),具备高并发、高性能和灵活扩展的特点,适用于缓存、实时数据分析等场景。其数据以键值对形式存储,支持字符串、哈希、列表、集合等类型。通过将 Redis 与 Mysql 集群结合使用,可实现数据同步,提升系统稳定性。例如,在网站架构中优先从 Redis 获取数据,故障时回退至 Mysql,确保服务不中断。
104 0
微服务——SpringBoot使用归纳——Spring Boot 中集成Redis——Redis 介绍
|
1月前
|
微服务——SpringBoot使用归纳——Spring Boot集成 Swagger2 展现在线接口文档——Swagger2 的使用
本文详细介绍了Swagger2的使用方法,包括在Spring Boot项目中的配置与应用。重点讲解了Swagger2中常用的注解,如实体类上的`@ApiModel`和`@ApiModelProperty`,Controller类上的`@Api`、`@ApiOperation`以及参数上的`@ApiParam`等。通过示例代码展示了如何为实体类和接口添加注解,并在页面上生成在线接口文档,实现接口测试。最后总结了Swagger的优势及其在项目开发中的重要性,提供了课程源代码下载链接供学习参考。
71 0
微服务——SpringBoot使用归纳——Spring Boot集成 Swagger2 展现在线接口文档——Swagger2 的使用
微服务——SpringBoot使用归纳——Spring Boot中集成 Shiro——Shiro 三大核心组件
本课程介绍如何在Spring Boot中集成Shiro框架,主要讲解Shiro的认证与授权功能。Shiro是一个简单易用的Java安全框架,用于认证、授权、加密和会话管理等。其核心组件包括Subject(认证主体)、SecurityManager(安全管理员)和Realm(域)。Subject负责身份认证,包含Principals(身份)和Credentials(凭证);SecurityManager是架构核心,协调内部组件运作;Realm则是连接Shiro与应用数据的桥梁,用于访问用户账户及权限信息。通过学习,您将掌握Shiro的基本原理及其在项目中的应用。
85 0
微服务——SpringBoot使用归纳——Spring Boot集成MyBatis——基于 xml 的整合
本教程介绍了基于XML的MyBatis整合方式。首先在`application.yml`中配置XML路径,如`classpath:mapper/*.xml`,然后创建`UserMapper.xml`文件定义SQL映射,包括`resultMap`和查询语句。通过设置`namespace`关联Mapper接口,实现如`getUserByName`的方法。Controller层调用Service完成测试,访问`/getUserByName/{name}`即可返回用户信息。为简化Mapper扫描,推荐在Spring Boot启动类用`@MapperScan`注解指定包路径避免逐个添加`@Mapper`
61 0
微服务——SpringBoot使用归纳——Spring Boot集成Thymeleaf模板引擎——Thymeleaf 介绍
本课介绍Spring Boot集成Thymeleaf模板引擎。Thymeleaf是一款现代服务器端Java模板引擎,支持Web和独立环境,可实现自然模板开发,便于团队协作。与传统JSP不同,Thymeleaf模板可以直接在浏览器中打开,方便前端人员查看静态原型。通过在HTML标签中添加扩展属性(如`th:text`),Thymeleaf能够在服务运行时动态替换内容,展示数据库中的数据,同时兼容静态页面展示,为开发带来灵活性和便利性。
63 0
GitHub官方开源MCP服务!GitHub MCP Server:无缝集成GitHub API,实现Git流程完全自动化
GitHub MCP Server是基于Model Context Protocol的服务器工具,提供与GitHub API的无缝集成,支持自动化处理问题、Pull Request和仓库管理等功能。
257 2
GitHub官方开源MCP服务!GitHub MCP Server:无缝集成GitHub API,实现Git流程完全自动化
微服务——SpringBoot使用归纳——Spring Boot中集成ActiveMQ——ActiveMQ安装
本教程介绍ActiveMQ的安装与基本使用。首先从官网下载apache-activemq-5.15.3版本,解压后即可完成安装,非常便捷。启动时进入解压目录下的bin文件夹,根据系统选择win32或win64,运行activemq.bat启动服务。通过浏览器访问`http://127.0.0.1:8161/admin/`可进入管理界面,默认用户名密码为admin/admin。ActiveMQ支持两种消息模式:点对点(Queue)和发布/订阅(Topic)。前者确保每条消息仅被一个消费者消费,后者允许多个消费者同时接收相同消息。
67 0
微服务——SpringBoot使用归纳——Spring Boot中集成ActiveMQ——ActiveMQ安装
微服务——SpringBoot使用归纳——Spring Boot集成Thymeleaf模板引擎——Thymeleaf 的使用
本文介绍了 Thymeleaf 在 Spring Boot 项目中的使用方法,包括访问静态页面、处理对象和 List 数据、常用标签操作等内容。通过示例代码展示了如何配置 404 和 500 错误页面,以及如何在模板中渲染对象属性和列表数据。同时总结了常用的 Thymeleaf 标签,如 `th:value`、`th:if`、`th:each` 等,并提供了官方文档链接以供进一步学习。
90 0
微服务——SpringBoot使用归纳——Spring Boot集成Thymeleaf模板引擎——Thymeleaf 的使用
微服务——SpringBoot使用归纳——Spring Boot中集成ActiveMQ——发布/订阅消息的生产和消费
本文详细讲解了Spring Boot中ActiveMQ的发布/订阅消息机制,包括消息生产和消费的具体实现方式。生产端通过`sendMessage`方法发送订阅消息,消费端则需配置`application.yml`或自定义工厂以支持topic消息监听。为解决点对点与发布/订阅消息兼容问题,可通过设置`containerFactory`实现两者共存。最后,文章还提供了测试方法及总结,帮助读者掌握ActiveMQ在异步消息处理中的应用。
85 0

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等