工作流 Flowable 发起流程 相关实现

This commit is contained in:
jason 2022-02-12 23:31:55 +08:00
parent c761f5258a
commit 073d860a78
17 changed files with 246 additions and 2 deletions

View File

@ -399,6 +399,11 @@
<version>${revision}</version>
</dependency>
<!-- 工作流相关 flowable -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-flowable</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter-basic</artifactId>

View File

@ -35,6 +35,7 @@
<module>yudao-spring-boot-starter-biz-social</module>
<module>yudao-spring-boot-starter-biz-tenant</module>
<module>yudao-spring-boot-starter-biz-data-permission</module>
<module>yudao-spring-boot-starter-flowable</module>
</modules>
<artifactId>yudao-framework</artifactId>

View File

@ -29,6 +29,8 @@ public interface WebFilterOrderEnum {
int ACTIVITI_FILTER = -98; // 需要保证在 Spring Security 过滤后面
int FLOWABLE_FILTER = -98; // 需要保证在 Spring Security 过滤后面
int DEMO_FILTER = Integer.MAX_VALUE;
}

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>yudao-framework</artifactId>
<groupId>cn.iocoder.boot</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yudao-spring-boot-starter-flowable</artifactId>
<dependencies>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-common</artifactId>
</dependency>
<!-- Web 相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-security</artifactId>
</dependency>
<!-- flowable 工作流相关 -->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter-basic</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,22 @@
package cn.iocoder.yudao.framework.flowable.config;
import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
import cn.iocoder.yudao.framework.flowable.core.web.FlowableWebFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class YudaoFlowableConfiguration {
/**
* 配置 flowable Web 过滤器
*/
@Bean
public FilterRegistrationBean<FlowableWebFilter> flowableWebFilter() {
FilterRegistrationBean<FlowableWebFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new FlowableWebFilter());
registrationBean.setOrder(WebFilterOrderEnum.FLOWABLE_FILTER);
return registrationBean;
}
}

View File

@ -0,0 +1 @@
package cn.iocoder.yudao.framework.flowable.core;

View File

@ -0,0 +1,14 @@
package cn.iocoder.yudao.framework.flowable.core.util;
import org.flowable.common.engine.impl.identity.Authentication;
public class FlowableUtils {
public static void setAuthenticatedUserId(Long userId) {
Authentication.setAuthenticatedUserId(String.valueOf(userId));
}
public static void clearAuthenticatedUserId() {
Authentication.setAuthenticatedUserId(null);
}
}

View File

@ -0,0 +1,35 @@
package cn.iocoder.yudao.framework.flowable.core.web;
import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* flowable Web 过滤器 userId 设置到 {@link org.flowable.common.engine.impl.identity.Authentication}
*
* @author jason
*/
public class FlowableWebFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
try {
// 设置工作流的用户
Long userId = SecurityFrameworkUtils.getLoginUserId();
if (userId != null) {
FlowableUtils.setAuthenticatedUserId(userId);
}
// 过滤
chain.doFilter(request, response);
} finally {
// 清理
FlowableUtils.clearAuthenticatedUserId();
}
}
}

View File

@ -0,0 +1 @@
package cn.iocoder.yudao.framework.flowable;

View File

@ -0,0 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.iocoder.yudao.framework.flowable.config.YudaoFlowableConfiguration

View File

@ -23,8 +23,8 @@
</dependency>
<!-- 工作流相关 -->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter-basic</artifactId>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-flowable</artifactId>
</dependency>
<dependency>
<groupId>org.flowable</groupId>

View File

@ -0,0 +1,33 @@
package cn.iocoder.yudao.module.bpm.framework.flowable.config;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.listener.BpmProcessInstanceEventListener;
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.spring.SpringProcessEngineConfiguration;
import org.flowable.spring.boot.EngineConfigurationConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.List;
/**
* BPM 模块的 Flowable 配置类
*
* @author jason
*/
@Configuration
public class BpmFlowableConfiguration {
/**
*将自定义 listener 加入全局listener
* @param processInstanceListener 自定义监听 {@link ProcessInstance}
*/
@Bean
public EngineConfigurationConfigurer<SpringProcessEngineConfiguration> addCustomerListenerConfigurer (BpmProcessInstanceEventListener processInstanceListener) {
return engineConfiguration -> {
List<FlowableEventListener> eventListeners = new ArrayList<>();
eventListeners.add(processInstanceListener);
engineConfiguration.setEventListeners(eventListeners);
};
}
}

View File

@ -0,0 +1,54 @@
package cn.iocoder.yudao.module.bpm.framework.flowable.core.listener;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
import com.google.common.collect.ImmutableSet;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener;
import org.flowable.engine.delegate.event.FlowableCancelledEvent;
import org.flowable.engine.delegate.event.FlowableProcessStartedEvent;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Set;
/**
* 监听 {@link ProcessInstance} 的开始与完成创建与更新对应的 {@link BpmProcessInstanceExtDO} 记录
*
* @author jason
*/
@Component
public class BpmProcessInstanceEventListener extends AbstractFlowableEngineEventListener {
@Resource
@Lazy
private BpmProcessInstanceService processInstanceService;
public static final Set<FlowableEngineEventType> PROCESS_INSTANCE_EVENTS = ImmutableSet.<FlowableEngineEventType>builder()
.add(FlowableEngineEventType.PROCESS_CREATED)
.add(FlowableEngineEventType.PROCESS_STARTED)
.add(FlowableEngineEventType.PROCESS_CANCELLED)
.build();
public BpmProcessInstanceEventListener(){
super(PROCESS_INSTANCE_EVENTS);
}
@Override
protected void processCreated(FlowableEngineEntityEvent event) {
processInstanceService.createProcessInstanceExt((ProcessInstance)event.getEntity());
}
@Override
protected void processStarted(FlowableProcessStartedEvent event) {
super.processStarted(event);
}
@Override
protected void processCancelled(FlowableCancelledEvent event) {
super.processCancelled(event);
}
}

View File

@ -89,6 +89,16 @@ public interface BpmProcessDefinitionService {
*/
ProcessDefinition getProcessDefinition(String id);
/**
* 获得编号对应的 ProcessDefinition
*
* 相比 {@link #getProcessDefinition(String)} 方法category 的取值是正确
*
* @param id 编号
* @return 流程定义
*/
ProcessDefinition getProcessDefinition2(String id);
/**
* 获得 deploymentId 对应的 ProcessDefinition
*

View File

@ -66,6 +66,11 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
return repositoryService.getProcessDefinition(id);
}
@Override
public ProcessDefinition getProcessDefinition2(String id) {
return repositoryService.createProcessDefinitionQuery().processDefinitionId(id).singleResult();
}
@Override
public ProcessDefinition getProcessDefinitionByDeploymentId(String deploymentId) {
if (StrUtil.isEmpty(deploymentId)) {

View File

@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessI
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceMyPageReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstancePageItemRespVO;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceRespVO;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
@ -73,4 +74,11 @@ public interface BpmProcessInstanceService {
* @return 历史的流程实例
*/
HistoricProcessInstance getHistoricProcessInstance(String id);
/**
* 创建 ProcessInstance 拓展记录
*
* @param instance 流程任务
*/
void createProcessInstanceExt(ProcessInstance instance);
}

View File

@ -12,6 +12,8 @@ import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
@ -32,6 +34,7 @@ import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@ -142,6 +145,23 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult();
}
@Override
public void createProcessInstanceExt(ProcessInstance instance) {
// 获得流程定义
ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId());
// 插入 BpmProcessInstanceExtDO 对象
BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO()
.setProcessInstanceId(instance.getId())
.setProcessDefinitionId(definition.getId())
.setName(instance.getProcessDefinitionName())
.setStartUserId(Long.valueOf(instance.getStartUserId()))
.setCategory(definition.getCategory())
.setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus())
.setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
processInstanceExtMapper.insert(instanceExtDO);
}
private String createProcessInstance0(Long userId, ProcessDefinition definition,
Map<String, Object> variables, String businessKey) {
// 校验流程定义