使用简介:本技术点主要是针对类审批的业务流程的建模,可以有:任务发布(即流程开始)到一级一级的审批到最终结束(即流程结束)一整套完备的模型
1、idea下载activiti插件
- ider以前版本下载actiBPM,但是新版ider这个插件已经被淘汰,已经被下面这个替代
2、单独起一个activiti服务
3、添加依赖在activiti服务中:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
<version>7.0.0.Beta2</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
4、添加配置
我这里的服务结构:
a、activiti.cfg.xml的配置(直接粘,需要修改为自己的数据库):
<?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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/contex
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 默认id对应的值 为processEngineConfiguration -->
<!-- processEngine Activiti的流程引擎 -->
<bean id="processEngineConfiguration"
class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<property name="jdbcDriver" value="***.mysql.cj.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://*****:3306/activiti"/>
<property name="jdbcUsername" value="root"/>
<property name="jdbcPassword" value="*****"/>
<!-- activiti数据库表处理策略 不存在就创建表-->
<property name="databaseSchemaUpdate" value="true"/>
</bean>
</beans>
配置讲解:
b、添加log4j的配置(无需修改,直接粘):
# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE debug info warn error fatal
log4j.rootCategory=debug, CONSOLE, LOGFILE
# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r[%15.15t] %-5p %30.30c %x - %m\n
# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:\XX\activiti.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r[%15.15t] %-5p %30.30c %x - %m\n
- 创建流程图文件:
在创建好的文件中任意位置右键,选择 View BPMN Diagram,打开可视化界面(流程定义的界面
任意右键选择定义流程:
解决图片乱码问题
1.打开 IDEA 安装路径,找到如下的安装目录
追加一条命令: -Dfile.encoding=UTF-8
如下所示
至此activiti的准备工作结束,一下是代码部分:
一、demo代码示例:
public class TestCreateTable {
/**
* 生成 activiti的数据库表
*/
@Test
public void testCreateDbTable() {
//使用classpath下的activiti.cfg.xml中的配置创建processEngine
//如果使用默认则需要上面activiti.cfg.xml配置
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
System.out.println(processEngine);
}
//部署
@Test
public void test01() {
//1、创建ProcessEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2、得到RepositoryService实例
RepositoryService repositoryService = processEngine.getRepositoryService();
//3、使用RepositoryService进行部署
Deployment deploy = repositoryService.createDeployment().addClasspathResource("bpmn/chuchai.bpmn20.xml")
.addClasspathResource("bpmn/diagram.png")
.name("团购申请v1.0")
.deploy();
//4、输出部署信息
System.out.println("部署id:"+deploy.getId());
System.out.println("部署的任务名称:"+deploy.getName());
}
//启动流程
@Test
public void testDeploy() {
//1.创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//创建TaskService
TaskService taskService = processEngine.getTaskService();
Map<String, Object> variables = new HashMap<>();
//张三就是在bpmn中Assignee配置的参数
variables.put("张三", "aaa");
//3.创建流程实例 流程定义的key需要知道 holiday
ProcessInstance processInstance = ProcessEngines.getDefaultProcessEngine()
.getRuntimeService()
.startProcessInstanceByKey("chuchai", variables);
Task tmp = taskService.createTaskQuery()
.processInstanceId(processInstance.getProcessInstanceId()).singleResult();
tmp.setAssignee("张三");
//完成此节点。由下一节点审批。完成后act_ru_task会创建一条由下节点审批的数据
taskService.***plete(tmp.getId(),variables);
//4.输出实例的相关信息
System.out.println( "流程部署ID:" + processInstance.getDeploymentId() );
System.out.println( "流程定义ID:" + processInstance.getProcessDefinitionId());
System.out.println( "流程实例ID:" + processInstance.getId() );
System.out.println( "活动ID:" + processInstance.getActivityId() );
}
@Test
//查询任务
public void test(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//创建TaskService
TaskService taskService = processEngine.getTaskService();
//根据流程key 和 任务负责人 查询任务
List<Task> list = taskService.createTaskQuery()
.processDefinitionKey("chuchai") //流程Key
.taskAssignee("张三")//只查询该任务负责人的任务
.list();
for (Task task : list) {
System.out.println("流程实例id:" + task.getProcessInstanceId());
System.out.println("任务id:" + task.getId());
System.out.println("任务负责人:" + task.getAssignee());
System.out.println("任务名称:" + task.getName());
}
}
//审批流程
@Test
public void test1(){
//1.创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//创建TaskService
TaskService taskService = processEngine.getTaskService();
//根据角色信息获取自己的待办
List<Task> T = taskService.createTaskQuery().taskAssignee("zs").list();
if(!ObjectUtils.isEmpty(T)) {
for (Task item : T) {
Map<String, Object> variables = new HashMap<>();
variables.put("张三", "zs");
variables.put("isSu***ess", true);
item.setAssignee("李四");
//增加审批备注
taskService.add***ment(item.getId(),item.getProcessInstanceId(),"部门经理同意");
//完成此次审批。由下节点审批
taskService.***plete(item.getId(), variables);
}
}
}
// 结束流程
@Test
public void test02() {
//1.创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 创建TaskService
TaskService taskService = processEngine.getTaskService();
//act_re_execution id
String taskId = "42503";
// 任务负责人
String assingee = "李四";
Task task = taskService.createTaskQuery()
.taskId(taskId)
.taskAssignee(assingee)
.singleResult();
if (task != null) {
HashMap<String, Object> map = new HashMap<>();
map.put("agree", 1);
taskService.***plete(taskId, map);
System.out.println("完成任务");
}
}
}
二、项目代码示例:controller层代码(这里是运用到项目中的代码)
@RestController
@RequestMapping("/activiti")
@Slf4j
public class ActivitiController {
@Autowired
private IActivitiService iActivitiService;
//生成25张表
@GetMapping
public Result getTables(){
log.info("开始生成表................................................................");
Result result = iActivitiService.getTable();
return result;
}
//流程部署
@GetMapping("/bushu")
public Result bushu(){
log.info("部署 ");
return Result.su***ess("ok");
}
//查询个人待执行的任务
@GetMapping("/list")
public Result list(){
log.info("查询个人待执行的任务");
Result result = iActivitiService.list();
return result;
}
//结束
@GetMapping("/***plete")
public Result ***plete(){
log.info("结束");
Result result = iActivitiService.***plete();
return result;
}
}
Service层代码:
@Service
@Repository
@Slf4j
public class ActivitiServiceImpl implements IActivitiService {
@Autowired
public IActivitiMapper iActivitiMapper;
@Override
public Result getTable() {
//使用classpath下的activiti.cfg.xml中的配置创建processEngine
//如果使用默认则需要上面activiti.cfg.xml配置
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
return Result.su***ess("生成表成功");
}
@Override
public Result bushu() {
//1、创建ProcessEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2、得到RepositoryService实例
RepositoryService repositoryService = processEngine.getRepositoryService();
//3、使用RepositoryService进行部署
Deployment deploy = repositoryService.createDeployment().addClasspathResource("activiti/groupactiviti.bpmn20.xml")
.addClasspathResource("activiti/groupactiviti.png")
.name("团购申请审批")
.deploy();
//4、输出部署信息
log.info("部署id:"+deploy.getId());
log.info("部署的任务名称:"+deploy.getName());
//5、启动流程定义 根据流程定义的id启动流程 key:act_re_procdef中的KEY
//创建TaskService
TaskService taskService = processEngine.getTaskService();
Map<String, Object> variables = new HashMap<>();
String username = SecurityUtils.getLoginUser().getSysUser().getUserName();
// String username = "admin";
//user就是在bpmn中Assignee配置的参数
variables.put("admin", username);
//3.创建流程实例 流程定义的key需要知道 holiday
ProcessInstance processInstance = ProcessEngines.getDefaultProcessEngine()
.getRuntimeService()
.startProcessInstanceByKey("groupactiviti", variables);
System.out.println(processInstance+"=============================================");
Task tmp = taskService.createTaskQuery()
.processInstanceId(processInstance.getProcessInstanceId()).singleResult();
tmp.setAssignee("ry");
//完成此节点。由下一节点审批。完成后act_ru_task会创建一条由下节点审批的数据
taskService.***plete(tmp.getId(),variables);
//4.输出实例的相关信息
log.info("流程部署ID:" + processInstance.getDeploymentId() );
log.info("流程定义ID:" + processInstance.getProcessDefinitionId());
log.info("流程实例ID:" + processInstance.getId());
log.info("活动ID:" + processInstance.getActivityId());
return Result.su***ess(true,"申请已提交");
}
//个人待执行任务
@Override
public Result list() {
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = defaultProcessEngine.getTaskService();
// 查询当前登录人的任务 进行完成
String username= SecurityUtils.getLoginUser().getSysUser().getUserName();
System.out.println("当前登录人"+username);
if (username == null){
throw new CheckedException("当前登录人为空");
}
List<Task> task = taskService.createTaskQuery()
.processDefinitionKey("groupactiviti")
.taskAssignee(username)
.list();
System.out.println("==================="+task);
if(!ObjectUtils.isEmpty(task)) {
for (Task item : task) {
Map<String, Object> variables = new HashMap<>();
if (username.equals("ry")){
variables.put("ry", username);
variables.put("isSu***ess", true);
item.setAssignee("aaa");
//增加审批备注
taskService.add***ment(item.getId(),item.getProcessInstanceId(),"部门经理已同意");
//完成此次审批。由下节点审批 act_hi_taskinst会修改时间
taskService.***plete(item.getId(), variables);
}
if (username.equals("aaa")){
variables.put("aaa", username);
variables.put("isSu***ess", true);
item.setAssignee("aaa");
//增加审批备注
taskService.add***ment(item.getId(),item.getProcessInstanceId(),"财务已同意");
//完成此次审批。由下节点审批 act_hi_taskinst会修改时间
taskService.***plete(item.getId(), variables);
}
}
}
return Result.su***ess(true,"审核成功");
}
// 结束
@Override
public Result ***plete() {
//1.创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//创建TaskService
TaskService taskService = processEngine.getTaskService();
// 获取当前登录人 判断是admin才结束任务
String username = SecurityUtils.getLoginUser().getSysUser().getUserName();
// String username = "aaa";
if (username == null) {
throw new CheckedException("当前登录人为空");
}
if (username.equals("aaa")) {
//act_re_execution 任务id
Task task = taskService.createTaskQuery()
.processDefinitionKey("groupactiviti")
.taskAssignee(username)
.singleResult();
if (task != null) {
HashMap<String, Object> map = new HashMap<>();
map.put("agree", 1);
taskService.***plete(task.getId(), map);
System.out.println("完成任务");
}
}
return Result.su***ess(true,"审核成功");
}
}
定义远程调用remote供别的服务调用
结构:
- ActivitiRemoteFallback代码:
/**
* activiti服务降级处理
*
* @author
*/
@***ponent
public class ActivitiRemoteFallback implements FallbackFactory<ActivitiRemoteService>
{
private static final Logger log = LoggerFactory.getLogger(ActivitiRemoteFallback.class);
@Override
public ActivitiRemoteService create(Throwable cause) {
log.error("工作流调用失败:{}", cause.getMessage());
return new ActivitiRemoteService(){
@Override
public Result getTables() {
return null;
}
@Override
public Result bushu() {
return Result.error("远程调用工作流部署失败");
}
@Override
public Result list() {
return Result.error("远程调用工作流审核失败");
}
@Override
public Result ***plete() {
return Result.error("远程调用工作流结束审核失败");
}
};
}
}
- ActivitiRemoteService代码:
/**
* 用户服务
*
* @author bawei
*/
@FeignClient(contextId = "rctivitiRemoteService",
value = ServiceNameConstants.****自己的文件名,
fallbackFactory = ActivitiRemoteFallback.class,path = "/activiti")
public interface ActivitiRemoteService {
//生成25张表
@GetMapping
public Result getTables();
//流程部署
@GetMapping("/bushu")
public Result bushu();
//查询个人待执行的任务
@GetMapping("/list")
public Result list();
//结束
@GetMapping("/***plete")
public Result ***plete();
}
- org.springframework.boot.autoconfigure.AutoConfiguration.imports配置的代码
最后:在需要使用Activiti的地方直接注入该服务即可