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

Springboot整合Flowable并进行一个通用审批流程应用实践

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

Springboot整合Flowable并进行一个通用审批流程应用实践

Springboot整合Flowable并进行一个通用审批流程应用实践
  • 一、Flowable介绍
  • 二、springboot整合Flowable6.7.2
    • 1.springboot和flowable的版本
    • 2.pom.xml引入
    • 3.application.yml中配置flowable的参数
    • 4.建好数据库flowabletest,然后启动
    • 5.定义流程文件
    • 6.代理类准备
    • 6.启动springboot工程让springboot帮我们部署好流程
    • 7.接下来写controller类进行测试
    • 8.接下来可以进行演示了
  • 三、Spring Boot 整合 Flowable-ui-modeler 6.7.2
    • 1.下载前端文件
    • 2.添加Flowable-ui-modeler依赖
    • 3.先启动测试一波
    • 4.配置idm
    • 5.绕过Flowable授权
    • 6.配置账号信息
    • 7. Flowable Modeler匿名账号的处理
    • 8.重启测试
    • 9.在线流程进行发布
  • 四、通用审批流程的应用实践
    • 1.通用审批流程设计
    • 2.业务扩展数据库设计
    • 3.流转说明图
    • 4. 测试说明
  • 五、flowable和mybatis同时存在时问题解决
  • 六、源码下载及说明


一、Flowable介绍
##官方文档
https://www.flowable.org/docs/userguide/index.html

Flowable是一个使用Java编写的轻量级业务流程引擎
Flowable是Activiti的fork

二、springboot整合Flowable6.7.2

基本的整合是参考这篇文章的,CSDN博主「水中加点糖」这位大神的采用springboot+flowable快速实现工作流,阅读量达20万以上,太厉害了,按照这篇文章做下来,结合我的实际情况,很顺利完成基本的整合

1.springboot和flowable的版本

springboot的2.6.2版本和的flowable的6.7.2比较搭配,因此使用这2个版本配对

springBoot版本:2.6.2
flowable版本:6.7.2
2.pom.xml引入

引入flowable-spring-boot-starter和mybatis相关

	
		6.7.2
	
		
		
			org.flowable
			flowable-spring-boot-starter
			${flowable.version}
		
		

		
		
		
			com.github.pagehelper
			pagehelper-spring-boot-starter
			${pagehelper.starter.version}
		
		
		
			com.alibaba
			druid
			1.1.10
		
		
		
			mysql
			mysql-connector-java
			
		
		
3.application.yml中配置flowable的参数

关闭定时任务JOB及启动检查数据库创建参数database-schema-update

flowable:
#关闭定时任务JOB
  async-executor-activate: false
  database-schema-update: true
4.建好数据库flowabletest,然后启动

启动时有个注意的:我的springboot和flowable版本的搭配如果配的是mysql8.0的驱动,会报表不存在的错误,因此先改成5.1.45的驱动,会成功创建表

CREATE DATABASE `flowabletest` 

我这边测试时用mysql8.0驱动时,会报表不存在,然后将以下注解开放,即mysql驱动改成5.1.45,application.yml中也相应修改驱动名为com.mysql.jdbc.Driver,然后重启,可以新建表成功。如果你没有这个问题,可以不用管这一个,建表成功后,可以将flowable.database-schema-update参数改成false,这个生产环境下建议还是改成false,另外建表成功后,可以把mysql的驱动恢复成8.0的(用8.0驱动建表不成功原因不明)。



	mysql
	mysql-connector-java
	

5.定义流程文件

这里我也就直接复制上面引用文章中的流程文件,有不少的人是直接复制这个流程文件的,但自己建的包名又不一样,因此会报包不存在的问题,因此,我们拿到这个流程文件内容后,将里面的类全名路径,可以改成你自己的包名里面去,然后将其命令为ExpenseProcess.bpmn20.xml并将其放于项目中的resource目录下的processes(如此目录不存在自行创建)目录下



    
        报销流程
        
        
            
                
                    
            
        
        
        
            
                
            
        
        
            
                
            
        
        
        
            outcome=='驳回'}]]>
        
        
            outcome=='驳回'}]]>
        
        
        
        
            money > 500}]]>
        
        
            outcome=='通过'}]]>
        
        
            outcome=='通过'}]]>
        
        
            money <= 500}]]>
        
    
    
        
            
                
            
            
                
            
            
                
            
            
                
            
            
                
            
            
                
            
            
                
                
            
            
                
                
            
            
                
                
            
            
                
                
                
                
            
            
                
                
            
            
                
                
            
            
                
                
            
            
                
                
                
            
        
    

6.代理类准备

ManagerTaskHandler

package cn.gzsendi.flowable.listeners;

import org.flowable.engine.delegate.TaskListener;
import org.flowable.task.service.delegate.DelegateTask;
 
public class ManagerTaskHandler implements TaskListener {
	private static final long serialVersionUID = -326245510542194886L;
	@Override
    public void notify(DelegateTask delegateTask) {
        delegateTask.setAssignee("经理");
    }
}

BossTaskHandler

package cn.gzsendi.flowable.listeners;

import org.flowable.engine.delegate.TaskListener;
import org.flowable.task.service.delegate.DelegateTask;

public class BossTaskHandler implements TaskListener {
	private static final long serialVersionUID = 1L;

	@Override
    public void notify(DelegateTask delegateTask) {
        delegateTask.setAssignee("老板");
    }
 
}
6.启动springboot工程让springboot帮我们部署好流程

到这直接启动springboot工程,如果不报错就会将processes下的我们刚准备的流程部署至数据库中,也可以通过检查数据库的表中是否存在部署记录,比如

7.接下来写controller类进行测试

这里我还是直接引用文章开头的引用文章里面的内容,复制出来定义成我的。
写一个TestController类

package cn.gzsendi.flowable.controller;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.ProcessEngine;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/test")
public class TestController {
	
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private ProcessEngine processEngine;

    
    @GetMapping("/add")
    public String addExpense(String userId, Integer money, String descption) {
        //启动流程
        HashMap map = new HashMap<>();
        map.put("taskUser", userId);
        map.put("money", money);
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("Expense", map);
        return "提交成功.流程Id为:" + processInstance.getId();
    }
    
    
    @GetMapping("/list")
    public Object list(String userId) {
        List tasks = taskService.createTaskQuery().taskAssignee(userId).orderByTaskCreateTime().desc().list();
        for (Task task : tasks) {
            System.out.println(task.toString());
        }
        return "task size: " +tasks.size() + " , 第一个:" + tasks.get(0).toString() ;
    }
    
    
    @GetMapping("/apply")
    public String apply(String taskId) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null) {
            throw new RuntimeException("流程不存在");
        }
        //通过审核
        HashMap map = new HashMap<>();
        map.put("outcome", "通过");
        taskService.complete(taskId, map);
        return "processed ok!";
    }
    
    
    @GetMapping("/reject")
    public String reject(String taskId) {
        HashMap map = new HashMap<>();
        map.put("outcome", "驳回");
        taskService.complete(taskId, map);
        return "reject";
    }
    
    
    @GetMapping("/processDiagram")
    public void genProcessDiagram(HttpServletResponse httpServletResponse, String processId) throws Exception {
        ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
 
        //流程走完的不显示图
        if (pi == null) {
            return;
        }
        Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).singleResult();
        //使用流程实例ID,查询正在执行的执行对象表,返回流程实例对象
        String InstanceId = task.getProcessInstanceId();
        List executions = runtimeService
                .createExecutionQuery()
                .processInstanceId(InstanceId)
                .list();
 
        //得到正在执行的Activity的Id
        List activityIds = new ArrayList<>();
        List flows = new ArrayList<>();
        for (Execution exe : executions) {
            List ids = runtimeService.getActiveActivityIds(exe.getId());
            activityIds.addAll(ids);
        }
        
        //图片输出要加上这个不会显示二进制数据,有些浏览器正常,有些浏览器是直接显示二进制数据,因此修改
        httpServletResponse.setContentType("image/png".concat(";charset=UTF-8"));
 
        //获取流程图
        BpmnModel bpmnModel = repositoryService.getBpmnModel(pi.getProcessDefinitionId());
        ProcessEngineConfiguration engconf = processEngine.getProcessEngineConfiguration();
        ProcessDiagramGenerator diagramGenerator = engconf.getProcessDiagramGenerator();
        InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", activityIds, flows, engconf.getActivityFontName(), engconf.getLabelFontName(), engconf.getAnnotationFontName(), engconf.getClassLoader(), 1.0,true);
        OutputStream out = null;
        byte[] buf = new byte[1024];
        int legth = 0;
        try {
            out = httpServletResponse.getOutputStream();
            while ((legth = in.read(buf)) != -1) {
                out.write(buf, 0, legth);
            }
        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
    } 
	
}
8.接下来可以进行演示了
1.创建一个流程:
访问:http://localhost:8080/test/add?userId=testuser&money=1234
返回:提交成功.流程Id为:cd8b3025-c6c9-11ec-b88b-02004c4f4f50

2.查询待办列表:
访问:http://localhost:8080/test/list?userId=testuser
输出:task size: 1 , 第一个:Task[id=cd93949c-c6c9-11ec-b88b-02004c4f4f50, name=出差报销]

3.同意:
访问:http://localhost:8080/test/apply?taskId=cd93949c-c6c9-11ec-b88b-02004c4f4f50
返回:processed ok!

4.生成流程图:
访问:http://localhost:8080/test/processDiagram?processId=cd8b3025-c6c9-11ec-b88b-02004c4f4f50

发现流程乱码

进一步处理,在工程中加上类FlowableConfig,内容如下:

package cn.gzsendi.config;

import org.flowable.spring.SpringProcessEngineConfiguration;
import org.flowable.spring.boot.EngineConfigurationConfigurer;
import org.springframework.context.annotation.Configuration;


@Configuration
public class FlowableConfig implements EngineConfigurationConfigurer {
    @Override
    public void configure(SpringProcessEngineConfiguration engineConfiguration) {
        engineConfiguration.setActivityFontName("宋体");
        engineConfiguration.setLabelFontName("宋体");
        engineConfiguration.setAnnotationFontName("宋体");
    }
}

重新启动工程测试,至此,图片也正常了,如图

到这里基本的flowable初探过程结束。

三、Spring Boot 整合 Flowable-ui-modeler 6.7.2

初探完成,接着就需要整合Flowable-ui-modeler这个在线设计流程器了,这个也同样的借鉴了另一个大神的文章,CSDN博主「wangdaoyin2010」的Spring Boot 整合 Flowable-ui-modeler 6.7.2,顺利的完成了整合modeler过程,其间也有一些自己的调整。

1.下载前端文件
  1. 下载flowable-engine-main源码文件
    https://github.com/flowable/flowable-engine/releases/tag/flowable-6.7.2
    注:下源码不是编绎后的
    wget https://github.com/flowable/flowable-engine/archive/refs/tags/flowable-6.7.2.tar.gz
  2. 找到前端文件
    解压下载后的文件,找到“flowable-engine-mainmodulesflowable-uiflowable-ui-modeler-frontendsrcmainresourcesstatic”文件夹。将整个”static”文件夹拷贝到自己项目下“resources”目录中
  3. 启动测试下
    http://localhost:8080/modeler/index.html
2.添加Flowable-ui-modeler依赖

在前面工程的依赖基础之上继续添加依赖

		
		
			org.flowable
			flowable-ui-modeler-rest
			${flowable.version}
		
		
		
			org.flowable
			flowable-ui-modeler-conf
			${flowable.version}
		
flowable-ui-modeler-rest: 包含flowableUI对模型的增删查改等所有模型维护接口
flowable-ui-modeler-conf: 包含了一些ui-modeler的自动化配置项
3.先启动测试一波

报错,Caused by: java.lang.IllegalArgumentException: flowable.common.app.idm-url must be set

4.配置idm

继续摘录大神文章中的内容,没有进行Flowable默认使用idm授权,需要对idm授权信息进行配置,添加对应idm配置,继续在application.yml中加入配置如下,然后重启工程。

flowable:
#关闭定时任务JOB
  async-executor-activate: false
  database-schema-update: true
  common:
    app:
#     目前先设置一个正确但是不一定可用的url地址
      idm-url: http://localhost:8080/flowable-idm1
      idm-admin:
#       需要设置一个密码,目前先设置,后期不使用
        password: test
#       默认user为admin,这个地方可设置可不设置
        user: admin1
5.绕过Flowable授权

再次启动成功,然后访问http://localhost:8080/modeler
会跳转到http://localhost:8080/flowable-idm1/idm/#/login?redirectOnAuthSuccess=true&redirectUrl=http://localhost:8080/modeler/
该地址中http://localhost:8080/flowable-idm1就是前面配置idm认证授权地址。说明要访问页面需要进行授权,这里我们不进行授权,直接配置绕过Flowable中的授权。

CSDN博主「wangdaoyin2010」大神的Spring Boot 整合 Flowable-ui-modeler 6.7.2里面写得比较细,我这里就直接使用过程不纠原理了,继续。

  1. 创建一个授权配置类SecurityConfiguration,可以放在任何包下。
package cn.gzsendi.config;

import org.flowable.ui.common.security.SecurityConstants;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class SecurityConfiguration {
    @Configuration(proxyBeanMethods = false)
    //Order配置说明
    // 这个地方相同会报错
    //这个地方如果大于则该配置在FlowableUiSecurityAutoConfiguratio中对应项后加载,不能起到绕过授权作用
    //所以这个地方-1让该配置项在FlowableUiSecurityAutoConfiguratio中对应配置项前加载,以跳过授权
    @Order(SecurityConstants.FORM_LOGIN_SECURITY_ORDER - 1)
    public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    //必须要将csrf设置为disable,不然后面发送POST请求时会报403错误
                    .csrf().disable()
                    //为了简单起见,简单粗暴方式直接放行modeler下面所有请求
                    .authorizeRequests().antMatchers("/modeler
   @RequestMapping(value = "/rest/account", method = RequestMethod.GET, produces = "application/json")
   public UserRepresentation getAccount() {
       UserRepresentation userRepresentation = new UserRepresentation();
       userRepresentation.setFirstName("admin");
       userRepresentation.setLastName("admin");
       userRepresentation.setFullName("admin");
       userRepresentation.setId("admin");
       List pris = new ArrayList<>();
       pris.add(DefaultPrivileges.ACCESS_MODELER);
       pris.add(DefaultPrivileges.ACCESS_IDM);
       pris.add(DefaultPrivileges.ACCESS_ADMIN);
       pris.add(DefaultPrivileges.ACCESS_TASK);
       pris.add(DefaultPrivileges.ACCESS_REST_API);
       userRepresentation.setPrivileges(pris);

       if (userRepresentation != null) {
           return userRepresentation;
       } else {
           throw new NotFoundException();
       }
   }
}
  1. 重启测试还是会报错的,路径不对,找到url-config.js配置文件中的请求地址进行修改
    共两个url-config.js,找到路径为srcmainresourcesstaticmodelerscriptsconfigurationurl-config.js的这个进行改即可。
    修改前:
    getAccountUrl: function () {
        return FLOWABLE.CONFIG.contextModelerRestRoot + '/rest/account';
    },

修改后

    getAccountUrl: function () {
        return FLOWABLE.CONFIG.contextRoot +  '/app/rest/account';
    },

刷新看效果如图:

7. Flowable Modeler匿名账号的处理

现在,基本上能进行在线流程设计了,我简单设计一下如下:


保存后显示匿名用户创建的:
网上找了一波,要改org.flowable.ui.common.security.SecurityUtils的类,进行重写覆盖到工程里面(包名路径等不能修改)

package org.flowable.ui.common.security;
 
import java.util.ArrayList;
import java.util.List;

import org.flowable.common.engine.api.FlowableIllegalStateException;
import org.flowable.idm.api.User;
import org.flowable.ui.common.model.RemoteUser;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
 

public class SecurityUtils {
 
  private static User assumeUser;
  
  private static SecurityScopeProvider securityScopeProvider = new FlowableSecurityScopeProvider();
 
  private SecurityUtils() {
  }
 
  
  public static String getCurrentUserId() {
    User user = getCurrentUserObject();
    if (user != null) {
      return user.getId();
    }
    return null;
  }
 
  
  public static User getCurrentUserObject() {
    if (assumeUser != null) {
      return assumeUser;
    }
 
    RemoteUser user = new RemoteUser();
    user.setId("admin");
    user.setDisplayName("admin");
    user.setFirstName("admin");
    user.setLastName("admin");
    user.setEmail("admin@flowable.com");
    user.setPassword("123456");
    List pris = new ArrayList<>();
    pris.add(DefaultPrivileges.ACCESS_MODELER);
    pris.add(DefaultPrivileges.ACCESS_IDM);
    pris.add(DefaultPrivileges.ACCESS_ADMIN);
    pris.add(DefaultPrivileges.ACCESS_TASK);
    pris.add(DefaultPrivileges.ACCESS_REST_API);
    user.setPrivileges(pris);
    return user;
  }
  
    public static void setSecurityScopeProvider(SecurityScopeProvider securityScopeProvider) {
        SecurityUtils.securityScopeProvider = securityScopeProvider;
    }
 
    public static SecurityScope getCurrentSecurityScope() {
        SecurityContext securityContext = SecurityContextHolder.getContext();
        if (securityContext != null && securityContext.getAuthentication() != null) {
            return getSecurityScope(securityContext.getAuthentication());
        }
        return null;
    }
 
    public static SecurityScope getSecurityScope(Authentication authentication) {
        return securityScopeProvider.getSecurityScope(authentication);
    }
 
    public static SecurityScope getAuthenticatedSecurityScope() {
        SecurityScope currentSecurityScope = getCurrentSecurityScope();
        if (currentSecurityScope != null) {
            return currentSecurityScope;
        }
        throw new FlowableIllegalStateException("User is not authenticated");
    }
 
  public static void assumeUser(User user) {
    assumeUser = user;
  }
 
  public static void clearAssumeUser() {
    assumeUser = null;
  }
}

如图:

8.重启测试

重启测试后,重新加一个流程,匿名账号的问题也解决了,一切正常。

9.在线流程进行发布

设计了在线流程后,通过flowable moderler怎么在线发布流程,新的flowable-ui,可通过应用程序进行发布。

  1. 新加一个应用程序

    然后进行创建好的应用程序进行编辑


    应用程序进行编辑过程,可以选中想发布的流程,然后在点发布即可。

    发布后数据库就会有记录

    至此,整合Modeler完成。
四、通用审批流程的应用实践

前面的flowable整合完后,已经基本上能按业务需求进行使用了,但每个流程要设计一次,还是觉得有点麻烦,对于我们一些简单的业务,就只设计配置一个通用的流程,系统中的流程都转化成这个通用的流程来进行审批流转

1.通用审批流程设计

通过flowable modeler进行设计一个通用流程如下,系统中的流程会转化成这个流程来进行审批流转

附上对应的通用审批流程.bpmn20.xml(只是参考用,因为可以通过在线Modeler进行修改):



  
    
      
        
      
    
    
      
        
        
        
      
    
    
      
        
        
        
      
    
    
    
    
    
      
        
      
    
    
      
        
      
    
    
    
      result>0}]]>
    
    
      result==0}]]>
    
    
      result<0}]]>
    
    
      result!=-999}]]>
    
    
    
      result==-999}]]>
    
    
      result!=-999}]]>
    
    
    
      result==-999}]]>
    
    
      只要审批没有通过,不管当前流程进行到哪个任务节点,申请人都可以取消审批(撤单)
    
    
  
  
    
      
        
      
      
        
      
      
        
      
      
        
      
      
        
      
      
        
      
      
        
      
      
        
      
      
        
      
      
        
        
      
      
        
        
        
        
      
      
        
        
      
      
        
        
      
      
        
        
      
      
        
        
      
      
        
        
      
      
        
        
      
      
        
        
      
      
        
        
      
      
        
        
        
        
      
    
  

2.业务扩展数据库设计
  1. 增加work_flow_def表,用来存我们自己的流程名称
  2. 增加work_flow_form_field表,用来存我们定义的表单字段(不使用flowable的)
  3. 增加work_order表,用于存放发起流程关联的工单数据(一个流程实例对应一条work_order数据记录)
  4. 增加wo_assignee表,用来存放审批人设置的信息。
wo_assignee(工单处理人表,即流程模板和流程实例数据表)**
用来将业务流程转化为"通用审批流程",
其中字段**assignee(审批人)**可能是**具体的用户ID**,也可能是**变量**;
当一个流程中的某一个节点的assignee(审批人)是**变量时**,
那就需要在**创建流程实例前赋值**成具体的用户ID,
创建流程实例前会生成**工单ID(work_order表的order_id)**,
我们就用**(order_id和具体的用户ID)**来再存入wo_assignee表,
得到新的工单处理人数据,流程流转时就用这些数据,因此,这些数据就是流程实例数据




3.流转说明图

4. 测试说明

因代码有点多,因此这里只是展示下效果,详见可以下载文章最后提供的源码,使用springboot工程,只需要将工程下的dbscriptsflowabletest.sql导入数据库,然后启动工程开箱即用,就可以进行测试

 

首页

流程表单设计和审批人设置

开启流程

审批

五、flowable和mybatis同时存在时问题解决

同时存在时不能正常启动,报存在2个session如类下以下错误

Description:

file [xxxxcomcarshowflowablemapperIFlowableCommentMapper.class] required a single bean, but 2 were found:
	- sqlSessionFactory: defined by method 'sqlSessionFactory' in class path resource [com/baomidou/mybatisplus/autoconfigure/MybatisPlusAutoConfiguration.class]
	- modelerSqlSessionFactory: defined by method 'modelerSqlSessionFactory' in class path resource [org/flowable/ui/modeler/conf/ModelerDatabaseConfiguration.class]
Action:
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

有博主的文章解决方法如https://blog.csdn.net/forever_xw_/article/details/122377609,我没有试过,觉得挺麻烦的,我这边直接采用手工配置多数据源,然后在写mybatis的mapper时指定使用的数据库来解决的,比如:

为数据库指定一个mybatis相关的config,如DefaultDbConfig,指定此库相关的表的mapper使用的注解为UsingDefalutDB,然后在mapper的编写时也同时指定注解。

package cn.gzsendi.config.mybatis;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface UsingDefaultDB {
}

写mapper时指定注解,使用哪个数据库

详细可以看我的源码里面的代码

六、源码下载及说明

最后提供源码如下及说明:

总的代码地址

github: https://github.com/jxlhljh/flowabletest
gitee: https://gitee.com/jxlhljh/flowabletest.git

springboot整合Flowable6.7.2

https://github.com/jxlhljh/flowabletest/tree/master/v1/flowabletest
https://gitee.com/jxlhljh/flowabletest/tree/master/v1/flowabletest

Spring Boot 整合 Flowable-ui-modeler 6.7.2

https://github.com/jxlhljh/flowabletest/tree/master/v2/flowabletest
https://gitee.com/jxlhljh/flowabletest/tree/master/v2/flowabletest

整合完成后的通用审批流程的应用实践的代码

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

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

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