diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 9f555b02a7..0e92b32d00 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -399,6 +399,11 @@ ${revision} + + cn.iocoder.boot + yudao-spring-boot-starter-flowable + ${revision} + org.flowable flowable-spring-boot-starter-basic diff --git a/yudao-framework/pom.xml b/yudao-framework/pom.xml index 85533c9a28..21452b4d13 100644 --- a/yudao-framework/pom.xml +++ b/yudao-framework/pom.xml @@ -35,6 +35,7 @@ yudao-spring-boot-starter-biz-social yudao-spring-boot-starter-biz-tenant yudao-spring-boot-starter-biz-data-permission + yudao-spring-boot-starter-flowable yudao-framework diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java index 6cfbba177f..93bd20fa48 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java @@ -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; } diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/pom.xml b/yudao-framework/yudao-spring-boot-starter-flowable/pom.xml new file mode 100644 index 0000000000..f778e2a542 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-flowable/pom.xml @@ -0,0 +1,31 @@ + + + + yudao-framework + cn.iocoder.boot + ${revision} + + 4.0.0 + + yudao-spring-boot-starter-flowable + + + + cn.iocoder.boot + yudao-common + + + + cn.iocoder.boot + yudao-spring-boot-starter-security + + + + org.flowable + flowable-spring-boot-starter-basic + + + + \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/config/YudaoFlowableConfiguration.java b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/config/YudaoFlowableConfiguration.java new file mode 100644 index 0000000000..4061339d69 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/config/YudaoFlowableConfiguration.java @@ -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() { + FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); + registrationBean.setFilter(new FlowableWebFilter()); + registrationBean.setOrder(WebFilterOrderEnum.FLOWABLE_FILTER); + return registrationBean; + } +} diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/package-info.java b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/package-info.java new file mode 100644 index 0000000000..de8d6279d7 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.framework.flowable.core; diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/util/FlowableUtils.java b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/util/FlowableUtils.java new file mode 100644 index 0000000000..641c699c9c --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/util/FlowableUtils.java @@ -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); + } +} diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/web/FlowableWebFilter.java b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/web/FlowableWebFilter.java new file mode 100644 index 0000000000..d9845a394c --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/web/FlowableWebFilter.java @@ -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(); + } + } +} diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/package-info.java b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/package-info.java new file mode 100644 index 0000000000..324d3de0ec --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.framework.flowable; diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000000..c667d5e553 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + cn.iocoder.yudao.framework.flowable.config.YudaoFlowableConfiguration diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/pom.xml b/yudao-module-bpm/yudao-module-bpm-impl-flowable/pom.xml index 09822771da..ea48aaf908 100644 --- a/yudao-module-bpm/yudao-module-bpm-impl-flowable/pom.xml +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/pom.xml @@ -23,8 +23,8 @@ - org.flowable - flowable-spring-boot-starter-basic + cn.iocoder.boot + yudao-spring-boot-starter-flowable org.flowable diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/config/BpmFlowableConfiguration.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/config/BpmFlowableConfiguration.java new file mode 100644 index 0000000000..d7009a5c69 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/config/BpmFlowableConfiguration.java @@ -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 addCustomerListenerConfigurer (BpmProcessInstanceEventListener processInstanceListener) { + return engineConfiguration -> { + List eventListeners = new ArrayList<>(); + eventListeners.add(processInstanceListener); + engineConfiguration.setEventListeners(eventListeners); + }; + } +} diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmProcessInstanceEventListener.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmProcessInstanceEventListener.java new file mode 100644 index 0000000000..1b5d1c6e53 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmProcessInstanceEventListener.java @@ -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 PROCESS_INSTANCE_EVENTS = ImmutableSet.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); + } +} diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java index 96a0bc1a71..7c26b644e4 100644 --- a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java @@ -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 * diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java index f56a18fffa..d75a1bd68a 100644 --- a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java @@ -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)) { diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java index f1d25f1e2c..7b6e3638d3 100644 --- a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java @@ -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); } diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index 77f14f3d15..f9295e0f7d 100644 --- a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -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 variables, String businessKey) { // 校验流程定义