栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

springBoot2.0集成Activiti6.0.0工作流

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

springBoot2.0集成Activiti6.0.0工作流

那么首先我们应该知道工作流是干什么的
简单来说工作流就是多个参与者,按照某种预定义的规则,传递业务信息,进行审核的功能一个框架
Activiti就是通过流程引擎processEngine,调用Service,从而操作activiti提供的数据库的23表

数据表分类
ACT_GE_* 通用数据表(GE表示General)
ACT_RE_* 流程定义存储表(RE表示repository)
ACT_ID_* 身份信息表(ID表示IDentity)
ACT_RU_* 运行是数据库表(RU表示runtime)
ACT_HI_* 历史数据库表(HI表示history)

processEnigne 流程引擎
我们可以通过流程引擎来获取一些service

ReopsitoryService :
负责对流程文件的管理,主要操作一些静态文件,比如流程文件中的xml,流程图.bpmn文件等
我们通过repositoryService部署流程对象, 会涉及到两个实体对象,一个是部署对象,一个是资源对象,部署对象和资源对象是一个一对多的关系,那么就可以说明, 一次部署可以包含多个资源文件,最常见的流程部署就是把流程图的xml或者.bpmn图片部署到数据库里面,

RuntimeService :主要是对流程进行控制的API,可以用于启动一个流程实例,针对制定的流程实例,进行暂停,挂起,和继续执行,也可以查询正在运行中的流程实例和执行对象,也可以对流程中的上下文数据进行设置和获取

通过RuntimeService启动流程,processDefinitionKey就是设置的整个流程的Id,businessKey因为整个流程为完成的时候都会存在,那么就可以设置成自己的业务数据表的Id,这样可以和activiti的数据表有一个交互的作用,也可以在自己的业务表中存放processInstanceId或者taskId,这样也可以直接通过业务数据命中该流程的实例,
variables也可以存放一些业务数据,这些都是需要在启动流程的时候的才能存放的

TaskService 主要管理userTask, 也就是人工任务, 可以对人工任务进行增删改查,也可以对用户任务设置指定的操作权限,指定的用户或用户主,同时也可以对用户任务上下文的变量设置或获取

	    // 通过流程实例Id获取当前任务
 Task task = taskService.createTaskQuery()
  .processInstanceId(processInstance.getProcessInstanceId())
  .singleResult();
   // 通过businessKey获取当前任务实例
   Task task2 = taskService.createTaskQuery()
  .processInstanceBusinessKey("业务表Id")
  .singleResult();      
		// 执行任务
 taskService.complete(task.getId());
		// 也可以携带参数执行,比如排他网关需要的参数等
 taskService.complete(task.getId(), map);

IdentityService 是对用户或者用户主管理,我们可以创建用户或用户主,并维护用户之间的关系

FormService 可以解析出流程定义中的设计表单,对表单的输入类型和格式做数据渲染

HistoryService 主要提供了对运行结束的流程实例的查询功能,也提供了基于流程维度和用户维度的删除操作,方便我们统计流程执行过程的变化,

ManagementService 主要是对流程引擎基础的管理, 一般用的比较少,还提供了对定时任务的管理

DynamicBPMService 动态,侵入性比较高的功能, 他可以动态的对流程定义的模型做修改, 一般不推荐使用

BPMN2.0(Buisness Process Model and Notation)

是一套业务流程模型与符号建模标准
精准的执行语义来描述元素的操作
以XML为载体,以符号可视化业务
BPMN2.0元素
FlowObjects 流对象 包括了事件,活动和网关,这些流对象通过连接对象连接起来,表示数据流转,过程中的数据流转主要通过连接对象来描述的,
ConnectingObjects 连接对象
Swimlanes 泳道 适用于对业务做一个范围维度的区分, 一般通过不同的职能做区分,比如角色和部门来区分不同的范围
Data 数据
Artifacs 描述对象

idea+actiBPM画图工具+jdk8+springBoot2.0+activiti6.0.0+jpa
pom.xml需要的依赖

org.springframework.boot
spring-boot-starter-parent
2.0.2.RELEASE


    UTF-8
    UTF-8
    1.8


    
 
     org.activiti
     activiti-dmn-model
     6.0.0
 
    


    
 org.springframework.boot
 spring-boot-starter-actuator
 
     
  log4j-api
  org.apache.logging.log4j
     
 
    
    
 org.springframework.boot
 spring-boot-starter-data-jpa
    
    
 org.springframework.boot
 spring-boot-starter-hateoas
    
    
 org.springframework.boot
 spring-boot-starter-jdbc
    
    
 org.springframework.boot
 spring-boot-starter-web
    
    
 org.springframework.boot
 spring-boot-starter-tomcat
 provided
    
    
 org.apache.tomcat.embed
 tomcat-embed-el
    
    
 org.activiti
 activiti-spring-boot-starter-basic
 6.0.0
 
     
  slf4j-log4j12
  org.slf4j
     
 
    
    
 org.activiti
 activiti-app-conf
 6.0.0
 
     
  slf4j-log4j12
  org.slf4j
     
 
    
    
 com.h2database
 h2
 runtime
    
    
 mysql
 mysql-connector-java
 runtime
    
    
 com.alibaba
 druid-spring-boot-starter
 1.1.8
    
    
 org.springframework.boot
 spring-boot-starter-test
 test
    



    
 
     org.springframework.boot
     spring-boot-maven-plugin
 
    

自己的业务数据表
package com.ActivitiDemo.domain;

import com.ActivitiDemo.dto.TaskDto;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.util.StringUtils;

import javax.persistence.*;
import java.util.Date;

@Entity
@Table(name = “t_leave_task”)
public class LeaveTask {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "user_id", columnDefinition = "int(10) COMMENT '请假人ID'")
private Integer userId;
@Column(name = "user_name", columnDefinition = "varchar(20) COMMENT '请假人性名'")
private String userName;
@Column(name = "start_date", columnDefinition = "timestamp COMMENT '请假开始时间'")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date startDate;
@Column(name = "end_date",columnDefinition = "timestamp COMMENT '请假结束时间'")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date endDate;

@Column(name = "leave_type", columnDefinition = "int(10) COMMENT '流程: 0.已提交, 1.主管审批, 2.人事审批, 3.已取消, 4.已完成'")
private LeaveType type;
@Column(name = "leave_cause",columnDefinition = "varchar(50) COMMENT '请假原因'")
private String leaveCause;

@Column(name = "create_date",columnDefinition = "timestamp COMMENT '任务创建时间'")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date createDate;
@Column(name = "review_status",columnDefinition = "int(1) COMMENT '审批结果'")
private Boolean reviewStatus;
@Column(name = "review_date", columnDefinition = "timestamp COMMENT '审批时间'")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date reviewDate;

@Column(name = "review_by", columnDefinition = "varchar(50) COMMENT '审批人'")
private String reviewBy;
@Column(name = "review_in", columnDefinition = "varchar(50) COMMENT '审批原因'")
private String reviewIn;

public LeaveTask() {
}

public LeaveTask(TaskDto dto) {
    this.userId = dto.getUserId();
    this.userName = dto.getUserName();
    this.startDate = dto.getStartDate();
    this.endDate = dto.getEndDate();
    this.leaveCause = StringUtils.isEmpty(dto.getLeaveCause()) ? null : dto.getLeaveCause();
    this.type = LeaveType.tl_approve;
    this.createDate = new Date();
    this.reviewBy = dto.getUserName();
    this.reviewIn = StringUtils.isEmpty(dto.getLeaveCause()) ? null : dto.getLeaveCause();
    this.reviewDate = new Date();
    this.reviewStatus = dto.getDecision();

// setter和getter方法省略。。。
}

spring-jpa可以根据映射表自动在数据库建立表,有兴趣的可以去看一下相关的API

package com.ActivitiDemo.domain;

public enum LeaveType {

submit_leave("已提交"),
tl_approve("主管审批"),
hr_approve("人事审批"),
error_leave("已取消"),
end_leave("已完成");

private final String desc;

LeaveType(String desc) {
    this.desc = desc;
}

public String getDesc() {
    return desc;
}

}

package com.ActivitiDemo.domain;

import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

import java.util.Date;
import java.util.Optional;

@Repository
public interface LeaveTaskRepository extends CrudRepository {

@Query(value = "update LeaveTask set reviewStatus = ?1, reviewBy = ?2, reviewIn = ?3, reviewDate = ?4, type = ?5 where id = ?6")
@Modifying
void updateReviewById(boolean reviewStatus, String reviewBy, String reviewIn, Date reviewDate, LeaveType type, Long id);


Optional findByUserIdAndTypeNotAndTypeNot(Integer userId, LeaveType type0, LeaveType type1);

}

package com.ActivitiDemo.service;

import com.ActivitiDemo.domain.LeaveTask;
import com.ActivitiDemo.domain.LeaveTaskRepository;
import com.ActivitiDemo.domain.LeaveType;
import com.ActivitiDemo.dto.ApprovalDto;
import com.ActivitiDemo.dto.TaskDto;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.HttpServerErrorException;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

@Service
@Transactional
public class ActivitiService {

@Resource
private LeaveTaskRepository leaveTaskRepository;

@Resource
private RuntimeService runtimeService;

@Resource
private TaskService taskService;

@Resource
private RepositoryService repositoryService;


public void postLeaveTask(TaskDto dto) {

    // 判断是否已有流程在走
    Optional optionalLeaveTask = leaveTaskRepository.findByUserIdAndTypeNotAndTypeNot(dto.getUserId(), LeaveType.end_leave, LeaveType.error_leave);

    // 流程已存在
    if(optionalLeaveTask.isPresent()) {

 Task task = taskService.createTaskQuery()
  .processInstanceBusinessKey(optionalLeaveTask.get().getId().toString())
  .singleResult();

 if (!ObjectUtils.isEmpty(task) && "ask_for_leave".equals(task.getTaskDefinitionKey())) {

     Map map = new HashMap<>();
     map.put("tlApprove", dto.getDecision() ? "Y" : "N");
     taskService.complete(task.getId(), map);

     // 修改请假单表的审批信息
     leaveTaskRepository.updateReviewById(dto.getDecision()
      , dto.getUserName()
      , StringUtils.isEmpty(dto.getLeaveCause()) ? null : dto.getLeaveCause()
      , new Date()
      , dto.getDecision() ? LeaveType.tl_approve : LeaveType.error_leave
      , optionalLeaveTask.get().getId());

 }else {
     throw new HttpServerErrorException(HttpStatus.BAD_REQUEST, "错误!");
 }
    }else {
 // 没有流程, 新建
 LeaveTask leaveTask = new LeaveTask(dto);
 LeaveTask result = leaveTaskRepository.save(leaveTask);

 String processDefinitionKey = "LeaveTheProcess";
 // 启动流程
 ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("LeaveTheProcess", result.getId().toString());

 // 获取当前任务
 Task task = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).singleResult();

 Map map = new HashMap<>();
 map.put("submitType", dto.getDecision() ? "Y" : "N");

 taskService.complete(task.getId(), map);
    }
}



public void approveProcess(ApprovalDto dto) {

    Task task = taskService.createTaskQuery()
     .processInstanceBusinessKey(dto.getLeaveId().toString())
     .singleResult();

    if (!ObjectUtils.isEmpty(task) && "tl_approve".equals(task.getTaskDefinitionKey())) {
 this.completeTlApproveTask(dto, task.getId());
    } else if (!ObjectUtils.isEmpty(task) && "hr_approve".equals(task.getTaskDefinitionKey())) {
 this.completeHrApproveTask(dto, task.getId());
    }

}



public void completeTlApproveTask(ApprovalDto dto, String taskId) {

    Map map = new HashMap<>();
    map.put("tlApprove", dto.getReviewStatus() ? "Y" : "N");
    taskService.complete(taskId, map);

    // 修改请假但表的审批信息
    leaveTaskRepository.updateReviewById(dto.getReviewStatus(), dto.getReviewBy(), dto.getReviewIn(), new Date(), dto.getReviewStatus() ? LeaveType.hr_approve : LeaveType.submit_leave, dto.getLeaveId());

}



public void completeHrApproveTask(ApprovalDto dto, String taskId) {

    Map map = new HashMap<>();
    map.put("hrApprove", dto.getReviewStatus() ? "Y" : "N");
    taskService.complete(taskId, map);

    // 修改请假但表的审批信息
    leaveTaskRepository.updateReviewById(dto.getReviewStatus(), dto.getReviewBy(), dto.getReviewIn(), new Date(), dto.getReviewStatus() ? LeaveType.end_leave : LeaveType.submit_leave, dto.getLeaveId());
}



public void deploy() {
    repositoryService.createDeployment()
     .addClasspathResource("processes/leave_the_process.bpmn")
     .name("请假审批流程")
     .category("请假")
     .deploy();

}

}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/236189.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号