jeecgboot3.6.1集成activiti7工作流引擎

Activiti作为老牌工作流引擎,目前在国内市面上存在广泛的使用。JeecgBoot是国内普及率最高的低代码业务开发平台。 本文将以保姆级喂养式带您从0到1完成集成,开发的工作。

访问JeecgFlow在线体验集成后效果

环境介绍

项目版本
JeecgBoot3.6.1
Activiti7.0.0.Beat2
jdk1.8

JeecgBoot新增activiti模块

首先,我们要新建一个模块,命名成:jeecg-module-activiti, 与现有的命名方式保持一致。在这个模块去做activiti工作流相关的业务。

在项目中,点击右键,选择module

在这里插入图片描述

直接进入创建模块,不要选择任何依赖。

在这里插入图片描述

完成模块命令,写入jeecg-module-activiti
<dependency>
    <groupId>org.jeecgframework.boot</groupId>
    <artifactId>jeecg-boot-base-core</artifactId>
</dependency>

并在该模块下加入上述依赖。 这个是jeecg的核心模块,也是一个公共模块。

在jeecg-boot-module-system的start模块的pom.xml引入新增的activit模块
    <dependency>
            <groupId>org.jeecgframework.boot</groupId>
            <artifactId>jeecg-module-activiti</artifactId>
            <version>${jeecgboot.version}</version>
        </dependency>
swagger配置

在swagger配置新模块的swagger扫描bean.找到Swagger2Config。追加如下Bean配置。

@Bean
public Docket loanApi() {
    return new Docket(DocumentationType.SWAGGER_2)
            .apiInfo(apiInfo()).groupName("会员模块")
            .select()
            //此包路径下的类,才生成接口文档
            .apis(RequestHandlerSelectors.basePackage("org.jeecg.crm"))
            //加了ApiOperation注解的类,才生成接口文档
            .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
            .paths(PathSelectors.any())
            .build()
            .securitySchemes(Collections.singletonList(securityScheme()));
    //.globalOperationParameters(setHeaderToken());
}

mybatis-plus配置

在application.yml中的配置.
mybatis-plus:
  mapper-locations: classpath*:classpath*:org/jeecg/activiti/**/xml/*Mapper.

mybatis-plus配置类的配置.MybatisPlusSaasConfig配置mapper文件扫描路径


@Configuration
@MapperScan(value={"org.jeecg.modules.**.mapper*","org.jeecg.loan.**.mapper*","org.jeecg.camunda.**.mapper*","org.jeecg.story.**.mapper*"})
public class MybatisPlusSaasConfig {
}

完成以上配置, 你可以往这个模块建表。到这也就完成第一步。模块建立。 接下来说明下如何完善activiti模块的依赖和配置。

Activiti模块的安装和配置

项目父pom.xml中新增activiti的依赖

<dependencyManagement>
    <dependencies>
        <!--以下是所需的依赖文件-->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter</artifactId>
            <version>7.0.0.Beta2</version>
            <exclusions>
                <exclusion>
                    <!-- 重点坑,不排除mybatis的话,在启动项目时会报错mybatisplus缺少类   -->
                    <artifactId>mybatis</artifactId>
                    <groupId>org.mybatis</groupId>
                </exclusion>
            </exclusions>
        </dependency>

    </dependencies>
</dependencyManagement>

jeecg-module-activit模块的依赖

<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-spring-boot-starter</artifactId>
    <exclusions>
        <exclusion>
            <!-- 重点坑,不排除mybatis的话,在启动项目时会报错mybatisplus缺少类   -->
            <artifactId>mybatis</artifactId>
            <groupId>org.mybatis</groupId>
        </exclusion>
    </exclusions>
</dependency>
application.yml配置
spring:
    activiti:
        #1.flase:默认值。activiti在启动时,对比数据库表中保存的版本,如果没有表或者版本不匹配,将抛出异常
        #2.true: activiti会对数据库中所有表进行更新操作。如果表不存在,则自动创建
        #3.create_drop: 在activiti启动时创建表,在关闭时删除表(必须手动关闭引擎,才能删除表)
        #4.drop-create: 在activiti启动时删除原来的旧表,然后在创建新表(不需要手动关闭引擎)
        database-schema-update: true
        # 检测历史信息表是否存在,activiti7默认不生成历史信息表,开启历史表
        db-history-used: true
        # 历史记录存储等级
        history-level: full
        check-process-definitions: true
mysql配置->nullCatalogMeansCurrent=true
url: jdbc:mysql://rxxx/jeecg-camunda?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
//需要在尾部追加nullCatalogMeansCurrent=true
//如果不追加, 可能会出现cause: java.sql.SQLSyntaxErrorException: 
Table 'jeecg-camunda.act_ge_property' doesn't exist

Activiti7 中自带的 Security 安全框架排除掉(因为我这里使用的是 Shiro 安全框架,Security 就没什么用处了)

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, SecurityAutoConfiguration.class,
        SecurityAutoConfiguration.class,
        ManagementWebSecurityAutoConfiguration.class})
public class OAApplication
{
    public static void main(String[] args)
    {
        SpringApplication.run(OAApplication.class, args);
        System.out.println("启动成功~");
    }
}

上面排除 Security 安全框架的操作对于 Activiti 7.1.0.M6 这个版本是没用的,
因为这个版本的代码强引用了 SpringSecurity 里的内容,
比如在 Activiti 的 SpringBoot 配置类中,强引用 UserDetailsService,
没有这个就会报错,所以我们还需要把版本降到7.1.0.M4及以下。

异常情况解决

caused by: java.lang.illegalargumentexception: property ‘sqlsessionfactory’ or ‘sqlsessiontemplate’ are required
the bean ‘methodsecurityinterceptor’, defined in class path resource
[org/activiti/spring/boot/methodsecurityconfig.class],
could not be registered. a bean with that name has already been defined in class path resource
[org/springframework/security/config/annotation/method/configuration/globalmethodsecurityconfiguration.class]
and overriding is disabled.

  • 解决办法在application.yml中,添加如下配置文件.

spring:
main:
allow-bean-definition-overriding: true

入门需求

完成上述配置后, 接下来,我们来完成一个简单的审批入门需求。 帮助大家快速了解如何使用工作流。
需求描述
我们以三国为背景, 假设系统中拥有将军,军师,主公三种角色。
现在作为将军的关羽需要发动一个出征流程。在填写好出兵人数和攻占城市后。
流程流转到军事诸葛亮进行评审, 此时军事可以给出锦囊妙计。
军事同意后,
由主公角色刘备进行最后裁断,并赐予战甲等物资。
这个就是系统中多角色协同的经典业务场景。

在这里插入图片描述

这个就是一个简单的审批的流程,可以类比公司的职员-直属领导-部门经理
完成上述流程建模, 可以在模型建设的菜单下进行操作。
在这里插入图片描述

模块新建的页面,提供在线建模的功能

流程模型分析

  • 1.设置将军角色的用户任务节点的属性配置
    在这里插入图片描述
    将军角色用户任务节点属性配置
  • 2.设置军师角色的用户任务节点的属性配置
    在这里插入图片描述

军师角色用户任务节点属性配置
3.设置主公角色的用户任务节点的属性配置
在这里插入图片描述

主公角色用户任务节点属性配置

接下来,开始角色扮演的过程

  • 将军角色-关羽登录系统,并且点击发起流程。
    在这里插入图片描述

这两个参数值与用户任务节点设置的字段是对应关系

 @ApiOperation(value = "启动流程", notes = "启动流程")
    @PostMapping("/startDemo")
    public Result<?> startDemo(@RequestBody ProcessStartReq processStartReq) {
        //设置用户任务节点assignee流程变量的值
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        Map<String, Object> variables = new HashMap<>(4);
        variables.put("general", sysUser.getUsername());
        variables.put("guide", "诸葛亮");
        variables.put("leader", "刘备");
        //启动流程&&并设置启动人
        Authentication.setAuthenticatedUserId(sysUser.getUsername());
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processStartReq.getModelKey(), variables);
        //查询出征申请用户任务节点,并且设置参数
        Map<String, Object> params = new HashMap<>(12);
        params.put("number", processStartReq.getNumber());
        params.put("city", processStartReq.getCity());
        Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskAssignee(sysUser.getUsername()).singleResult();
        if (task != null) {
            taskService.complete(task.getId(), params);
        }
        return Result.OK("操作成功", processInstance.getId());
    }

  • 军师角色登录系统-完成审批动作
    在这里插入图片描述

待办任务点击任务详情,重点关注同意,驳回,终止三个按钮的操作
同意操作,流程就会流转到下一个节点。

Map<String, Object> map = new HashMap<>(12);
        map.put("comment", userTaskApproveReq.getComment());
        map.put("imageUrl", userTaskApproveReq.getImageUrl());
        //创建评论
        CommentHistoryRes.CommentDTO commentDTO = new CommentHistoryRes.CommentDTO();
        commentDTO.setComment(userTaskApproveReq.getComment());
        commentDTO.setImageUrl(userTaskApproveReq.getImageUrl());
        commentDTO.setTaskStatus("<font color='#67C23A'>通过</font>");
        taskService.addComment(userTaskApproveReq.getTaskId(), userTaskApproveReq.getProcessInstanceId(), JSON.toJSONString(commentDTO));

        taskService.complete(userTaskApproveReq.getTaskId(), map);
驳回操作,可以指定驳回的节点,当前系统默认驳回到发起任务的用户任务节点
public void jump(UserTaskJumpReq userTaskRejectReq) {
        Task t = taskService.createTaskQuery().taskId(userTaskRejectReq.getTaskId()).singleResult();
        String processDefinitionId = runtimeService.createProcessInstanceQuery().processInstanceId(t.getProcessInstanceId()).singleResult().getProcessDefinitionId();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        // 寻找流程实例当前任务的activeId
        Execution execution = runtimeService.createExecutionQuery().executionId(t.getExecutionId()).singleResult();
        String activityId = execution.getActivityId();
        FlowNode currentNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityId);
        FlowNode targetNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(userTaskRejectReq.getTargetActivityId());
        // 创建连接线
        List<SequenceFlow> newSequenceFlowList = new ArrayList<SequenceFlow>();
        SequenceFlow newSequenceFlow = new SequenceFlow();
        newSequenceFlow.setId("newFlow");
        newSequenceFlow.setSourceFlowElement(currentNode);
        newSequenceFlow.setTargetFlowElement(targetNode);
        newSequenceFlowList.add(newSequenceFlow);
        // 备份原有方向
        List<SequenceFlow> dataFlows = currentNode.getOutgoingFlows();
        List<SequenceFlow> oriSequenceFlows = new ArrayList<SequenceFlow>();
        oriSequenceFlows.addAll(dataFlows);
        // 清空原有方向
        currentNode.getOutgoingFlows().clear();
        // 设置新方向
        currentNode.setOutgoingFlows(newSequenceFlowList);
        //创建评论
        CommentHistoryRes.CommentDTO commentDTO = new CommentHistoryRes.CommentDTO();
        commentDTO.setComment(userTaskRejectReq.getComment());
        commentDTO.setImageUrl(userTaskRejectReq.getImageUrl());
        commentDTO.setTaskStatus("<font color='#E6A23C'>驳回</font>");
        taskService.addComment(userTaskRejectReq.getTaskId(), userTaskRejectReq.getProcessInstanceId(), JSON.toJSONString(commentDTO));
        taskService.complete(userTaskRejectReq.getTaskId());
        // 恢复原有方向
        currentNode.setOutgoingFlows(oriSequenceFlows);
        //会签任务不可以驳回 TODO
    }

  • 终止操作,是强行将流程结束。
public void forceEnd(UserTaskForceEndReq userTaskForceEndReq) {
       Task t = taskService.createTaskQuery().taskId(userTaskForceEndReq.getTaskId()).singleResult();
       String processDefinitionId = runtimeService.createProcessInstanceQuery().processInstanceId(t.getProcessInstanceId()).singleResult().getProcessDefinitionId();
       BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
       // 寻找流程实例当前任务的activeId
       Execution execution = runtimeService.createExecutionQuery().executionId(t.getExecutionId()).singleResult();
       String activityId = execution.getActivityId();
       FlowNode currentNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityId);
       // 创建结束节点和连接线
       EndEvent end = new EndEvent();
       end.setName("强制结束");
       end.setId("forceEnd");
       List<SequenceFlow> newSequenceFlowList = new ArrayList<SequenceFlow>();
       SequenceFlow newSequenceFlow = new SequenceFlow();
       newSequenceFlow.setId("newFlow");
       newSequenceFlow.setSourceFlowElement(currentNode);
       newSequenceFlow.setTargetFlowElement(end);
       newSequenceFlowList.add(newSequenceFlow);

       // 备份原有方向
       List<SequenceFlow> dataFlows = currentNode.getOutgoingFlows();
       List<SequenceFlow> oriSequenceFlows = new ArrayList<SequenceFlow>();
       oriSequenceFlows.addAll(dataFlows);

       // 清空原有方向
       currentNode.getOutgoingFlows().clear();
       // 设置新方向
       currentNode.setOutgoingFlows(newSequenceFlowList);
       // 完成当前任务
       CommentHistoryRes.CommentDTO commentDTO = new CommentHistoryRes.CommentDTO();
       commentDTO.setComment(userTaskForceEndReq.getComment());
       commentDTO.setImageUrl(userTaskForceEndReq.getImageUrl());
       commentDTO.setTaskStatus("<font color='#F56C6C'>终止</font>");
       taskService.addComment(userTaskForceEndReq.getTaskId(), t.getProcessInstanceId(), "comment", JSON.toJSONString(commentDTO));
       taskService.complete(userTaskForceEndReq.getTaskId());
       // 恢复原有方向
       currentNode.setOutgoingFlows(oriSequenceFlows);
   }

具体的如何操作,可以登录www.jeecgflow.com系统去体验。
主公角色也是同样的操作。 就不再描述。

  • 11
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: batchplot3.6.1是一款CAD软件的批处理工具。它可以帮助CAD用户快速、高效地批量打印、发布、导出、转换图形文件,大大减轻了用户的工作负担,并提高了工作效率。 该软件支持多种输出格式,包括图像、PDF、DWF、DWFx等。用户可根据需要灵活选择输出方式,以便于更好地与相关部门或人员共享设计图纸。 此外,batchplot3.6.1还可以设置打印、发布等参数,如打印纸张尺寸、图层设置等,使得输出的设计文件更加符合用户的要求。 总之,batchplot3.6.1是一款非常有用的批处理工具,可以帮助CAD设计师在日常工作中更好地完成任务,并提高工作效率。 ### 回答2: Batchplot3.6.1是一款专业的CAD图纸批量打印软件,适用于AutoCAD、MicroStation、ZWCAD等多种CAD软件,可以大幅提高CAD图纸打印的效率和质量。 该软件可以轻松地将大量的CAD图纸进行自动排版和批量打印,同时支持多种打印机类型和打印纸型号,用户可以根据需要快速选择合适的打印机和纸张。 此外,Batchplot3.6.1还具有强大的图纸管理功能,可以对图纸进行分类、排序和筛选,以保证打印的顺序和效果。 在使用Batchplot3.6.1时,用户还可以自定义打印设置,包括打印样式、旋转角度、线宽等,以满足不同打印需求。 总的来说,Batchplot3.6.1是一款功能强大、易于使用的CAD图纸批量打印软件,可以极大地提高CAD绘图和工程设计人员的工作效率,是一款不容错过的优秀软件。 ### 回答3: BatchPlot3.6.1是一款专业的CAD图纸批量打印软件,它为用户提供了一种快捷高效的批量打印解决方案。 使用BatchPlot3.6.1,用户可以轻松地管理和打印各种类型的CAD图纸,包括平面布局、图纸图块、模型空间和纸张空间。该软件支持多种文件格式,如DWG、DXF、DWF、PDF等,并能够按照用户的需求进行自动排版和打印。 除此之外,BatchPlot3.6.1还提供了多种打印设置选项,包括纸张大小、打印质量、线宽、颜色、图层等,并能够将这些设置应用于所有图纸。此外,该软件还支持打印预览和多线程打印功能,大大提高了打印效率。 总的来说,BatchPlot3.6.1是一款功能丰富、易于使用的CAD图纸批量打印软件,它可以帮助用户快速高效地完成CAD图纸的批量打印任务。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值