Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

密码丢失?请输入您的电子邮件地址。您将收到一个重设密码链接。

Error message here!

返回登录

Close

Activiti7之整合spring和spring boot

wishsaber 2020-04-09 22:06:00 阅读数:59 评论数:0 点赞数:0 收藏数:0

整合spring

通过 org.activiti.spring.SpringProcessEngineConfiguration Spring 整合方式来创建ProcessEngine 对象。

1.导入依赖

jdk的版本是1.8

junit的版本必须是4.12以上

 <dependencies>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>7.0.0.Beta1</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-bpmn-model</artifactId>
<version>7.0.0.Beta1</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-bpmn-converter</artifactId>
<version>7.0.0.Beta1</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-json-converter</artifactId>
<version>7.0.0.Beta1</version>
</dependency>
<!-- <dependency>
  <groupId>org.activiti</groupId>
  <artifactId>activiti-bpmn-layout</artifactId>
  <version>7.0.0.Beta1</version>
  </dependency>-->
<dependency>
<groupId>org.activiti.cloud</groupId>
<artifactId>activiti-cloud-services-api</artifactId>
<version>7.0.0.Beta1</version>
</dependency>
<!--activiti和Spring整合依赖-->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring</artifactId>
<version>7.0.0.Beta1</version>
</dependency>
<!--数据库依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<!--单测依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
<!-- log start -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--数据源-->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>alfresco</id>
<name>Activiti Releases</name>
<url>https://artifacts.alfresco.com/nexus/content/repositories/activiti-releases/</url>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
依赖

 

2.配置Activiti

 配置内容:1.数据源 2.配置processEngine对象 3.配置XXXXService
 <!--数据源-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/activiti-y2170"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!--配置ProcessEngineConfiguration-->
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<!--数据源-->
<property name="dataSource" ref="dataSource"/>
<!--配置事务-->
<property name="transactionManager" ref="transactionManager"/>
<!--数据生成策略 true false create drop-create -->
<property name="databaseSchemaUpdate" value="true"/>
</bean>
<!--配置ProcessEngine-->
<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
<property name="processEngineConfiguration" ref="processEngineConfiguration"/>
</bean>
<!--配置RepositoryService-->
<bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService"/>
<!--配置RuntimeService-->
<bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService"/>
<!--配置TaskService-->
<bean id="taskService" factory-bean="processEngine" factory-method="getTaskService"/>
<!--配置HistoryService-->
<bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService"/>
<!--配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
配置

 

3.测试

 package com.wish;

import static org.junit.Assert.assertTrue;

import org.activiti.engine.RepositoryService;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;

/**
 * Unit test for simple App.
 */
@RunWith(SpringJUnit4ClassRunner.class) //测试方式 junit4.12+
@ContextConfiguration("classpath:springActibiti.xml") //配置
public class AppTest
 {
  @Resource
 private RepositoryService repositoryService;
  @Test
 public void shouldAnswerWithTrue()
  {
 System.out.println("部署对象:"+repositoryService);
  }
 }
测试

 

运行结果:接下来就可以部署了

 

 

 

使用RepositoryService 进行部署

 /**
 * 测试流程部署
 */
 @Test
 public void deployment(){
  repositoryService.createDeployment()
 .addClasspathResource("flowchart/process.bpmn")
 .name("测试Spring流程部署")
  .deploy();
 }
repositoryService部署

 

运行结果

 

 

 

 

 

 

执行流程分析

下面我们一起来分析Activiti 与Spring 整合加载的过程。如下图所示:

从图中我们可以看出,首先我们加载 activiti-spring.xml 配置文件,而该配置文件中又会加载SpringProcessEngineConfiguration 对 象 ,

这 个 对 象 它 需 要 依 赖 注 入 dataSource 对 象 和transactionManager 对象。

其次会加载ProcessEngineFactoryBean 工厂来创建ProcessEngine 对象,而ProcessEngineFactoryBean 工厂又需要 依赖注 入 processEngineConfiguration 对 象。

最后 由processEngine 对象来负责创建我们的 Service 对象,从而简化 Activiti 的开发过程。在程序代码中我们可以根据实际需求来决定使用的Service 对象。

 

Activiti7的新特性

Activiti7的GitHub官方网站:https://github.com/Activiti/activiti-7-developers-guide/blob/51a1681c0e4bb5e2f96a6dea73516c9fd53 d8521/getting-started/getting-started-activiti-core.md

 

下载 Activiti-Core 的Example 示例:https://github.com/Activiti/activiti-examples

 

Activiti7 为了简化对工作流的操作,特别在原有 API 的基础上再次进行封闭,这样我们原来所学习的Activiti 基本API 就被封闭起来了。

具体要学习的包括:

ProcessRuntime 接口TaskRuntime 接口

ProcessRuntime 接口

 

通过上面的分析,我们发现使用 Activiti7 开发时,只要注入ProcessRuntime 的实现对象,就可以实现流程定义信息的操作。

当然这个过程中因为 Activiti7 与SpringSecurity 的强耦合,引导我们也必须将SpringSecurity 加入进来。

 

TaskRuntime 接口

 

 

 

 

上面部分给我们介绍了如何引入Activiti Core 所需的坐标,同时介绍了如何添加 TaskRuntime 实现对象,源码介绍等。我们会发现TaskRuntime 本身就是对于TaskService 的一个封装。

SpringBoot整合Activiti7

 导入依赖

 <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.activiti/activiti-spring-boot-starter -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
<version>7.0.0.Beta2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
依赖

 

配置application.yml

 spring:
  datasource:
 url: jdbc:mysql://localhost:3306/activiti-wn?useUnicode=true&characterEncoding=utf8&serverT imezone=GMT
  username : root
  password : 123456
  driver-class-name: com.mysql.jdbc.Driver
  activiti:
 db-history-used: true #开启历史信息
配置application.yml

 

将SpringSecurity配置添加到项目当中

SecurityUtil关于权限登陆

 package com.wish.activiti;

import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.core.context.SecurityContextImpl;
 import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.security.core.userdetails.UserDetailsService;
 import org.springframework.stereotype.Component;

import java.util.Collection;

@Component
 public class SecurityUtil {

 @Autowired
 private UserDetailsService userDetailsService;

public void logInAs(String username) {

UserDetails user = userDetailsService.loadUserByUsername(username);
 if (user == null) {
 throw new IllegalStateException("User " + username + " doesn't exist, please provide a valid user");
  }

SecurityContextHolder.setContext(new SecurityContextImpl(new Authentication() {
  @Override
 public Collection<? extends GrantedAuthority> getAuthorities() {
 return user.getAuthorities();
  }

 @Override
 public Object getCredentials() {
 return user.getPassword();
  }

 @Override
 public Object getDetails() {
 return user;
  }

 @Override
 public Object getPrincipal() {
 return user;
  }

 @Override
 public boolean isAuthenticated() {
 return true;
  }

 @Override
 public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {

 }

 @Override
 public String getName() {
 return user.getUsername();
  }
  }));
  org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(username);
  }
 }
SecurityUtil

 

DemoApplicationConfiguration 关于权限配置

 /*
 * Copyright 2018 Alfresco, Inc. and/or its affiliates.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
 *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
 */
package com.wish.activiti;

import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
 import org.springframework.security.core.userdetails.User;
 import org.springframework.security.core.userdetails.UserDetailsService;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.security.provisioning.InMemoryUserDetailsManager;
 import java.util.Arrays;
 import java.util.List;
 import java.util.stream.Collectors;

@Configuration
 @EnableWebSecurity
 public class DemoApplicationConfiguration extends WebSecurityConfigurerAdapter {

private Logger logger = LoggerFactory.getLogger(DemoApplicationConfiguration.class);

 @Override
  @Autowired
 public void configure(AuthenticationManagerBuilder auth) throws Exception {
  auth.userDetailsService(myUserDetailsService());
  }

 @Bean
 public UserDetailsService myUserDetailsService() {

InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();

String[][] usersGroupsAndRoles = {
 {"salaboy", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
 {"ryandawsonuk", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
 {"erdemedeiros", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
 {"other", "password", "ROLE_ACTIVITI_USER", "GROUP_otherTeam"},
 {"admin", "password", "ROLE_ACTIVITI_ADMIN"},
  };

for (String[] user : usersGroupsAndRoles) {
 List<String> authoritiesStrings = Arrays.asList(Arrays.copyOfRange(user, 2, user.length));
 logger.info("> Registering new user: " + user[0] + " with the following Authorities[" + authoritiesStrings + "]");
 inMemoryUserDetailsManager.createUser(new User(user[0], passwordEncoder().encode(user[1]),
 authoritiesStrings.stream().map(s -> new SimpleGrantedAuthority(s)).collect(Collectors.toList())));
  }

return inMemoryUserDetailsManager;
  }

 @Override
 protected void configure(HttpSecurity http) throws Exception {
  http
  .csrf().disable()
  .authorizeRequests()
  .anyRequest()
  .authenticated()
  .and()
  .httpBasic();

 }

 @Bean
 public PasswordEncoder passwordEncoder() {
 return new BCryptPasswordEncoder();
  }
 }
DemoApplicationConfiguration

 

启动工程

 package com.wish;

import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
 public class StartActiviti {
 public static void main(String[] args) {
 SpringApplication.run(StartActiviti.class,args);
  }
 }
启动项目

 

运行成功,数据库创建表

 

 

注意问题:
1.Activiti7和SpringSecurity耦合,需要加入SpringSecurity的依赖和配置,我们可以使用Security中的用户角色组定义流程执行的组
2.流程默认可自动部署,但是需要再resources/processes文件夹,将流程文件放入当中
3.默认历史表不会生成,需要手动开启配置

 

执行流程

 package com.wish.controller;

import com.wish.activiti.SecurityUtil;
 import org.activiti.api.process.model.ProcessDefinition;
 import org.activiti.api.process.model.ProcessInstance;
 import org.activiti.api.process.model.builders.ProcessPayloadBuilder;
 import org.activiti.api.process.runtime.ProcessRuntime;
 import org.activiti.api.runtime.shared.query.Page;
 import org.activiti.api.runtime.shared.query.Pageable;
 import org.activiti.api.task.model.Task;
 import org.activiti.api.task.model.builders.TaskPayloadBuilder;
 import org.activiti.api.task.runtime.TaskRuntime;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
 @RequestMapping("/activiti")
 public class ActivitiController {
  @Resource
 private ProcessRuntime processRuntime;
  @Resource
 private TaskRuntime taskRuntime;
  @Resource
 private SecurityUtil securityUtil;
 /**
 * 查询流程定义
 */
@RequestMapping("/getProcess")
 public void getProcess(){
 //查询所有流程定义信息
Page<ProcessDefinition> processDefinitionPage = processRuntime.processDefinitions(Pageable.of(0, 10));
 System.out.println("当前流程定义的数量:"+processDefinitionPage.getTotalItems());
 //获取流程信息
for (ProcessDefinition processDefinition:processDefinitionPage.getContent()) {
 System.out.println("流程定义信息"+processDefinition);
  }
  }

/**
 * 启动流程示例
 */
@RequestMapping("/startInstance")
 public void startInstance(){
 ProcessInstance instance = processRuntime.start(ProcessPayloadBuilder.start().withProcessDefinitionKey("demo").build());
  System.out.println(instance.getId());
  }

/**
 * 获取任务,拾取任务,并且执行
 */
@RequestMapping("/getTask")
 public void getTask(){
 securityUtil.logInAs("salaboy"); //指定组内任务人
Page<Task> tasks = taskRuntime.tasks(Pageable.of(0, 10));
 if(tasks.getTotalItems()>0){
 for (Task task:tasks.getContent()) {
 System.out.println("任务名称:"+task.getName());
 //拾取任务
 taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(task.getId()).build());
 //执行任务
 taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(task.getId()).build());
  }
  }
  }
 }
执行流程

 

执行查询流程定义操作

 

 

 

 

执行启动流程示例

 

 

 

 

 

 

执行获取任务,拾取任务,并且执行操作

 

 

 

 

 

版权声明
本文为[wishsaber]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/wishsaber/p/12669702.html