聚合项目集成flwoable modeler

使用springboot聚合项目,搭建了一套框架,领导说需要把工作流给集成进来。自己以前没做过工作流相关,网上搜索了一下,activiti现在逐渐被flowable给替代,那怎么说呢,那就使用flwoable呗。花了几天时间,搭建起来,简单总结一下,以后便于翻阅。

1. 集成 

    先在网上搜索了一些资料,搜索到了一篇https://blog.csdn.net/puhaiyang/article/details/79845248采用springboot+flowable快速实现工作流。按照内容把项目搭建起来了,然后运行,没什么问题。唯一的就是展示流程图的时候,出现了乱码,配置了config为宋体,或者直接写死为宋体,依然是乱码,后面在网上继续搜索了,设置响应头为图片,这才终于解决了问题。

 

 

 // 设置响应的类型格式为图片格式
        httpServletResponse.setContentType("image/png");
        //禁止图像缓存。
        httpServletResponse.setHeader("Pragma", "no-cache");
        httpServletResponse.setHeader("Cache-Control", "no-cache");
        httpServletResponse.setDateHeader("Expires", 0);
  out = httpServletResponse.getOutputStream();

2. 新建

     集成好了以后,自己测试着新建一个流程,看着上面的博客,看着好像是需要把创建好的保存为bpmn20.xml然后放入processse,重新启动后,就能使用。  自己感觉这个就有点坑了吧,我发布出去的程序,如果新建了一个流程,居然需要拷贝文件并重新启动才能生效?这个不能忍,明明都存到数据库了,为什么还要使用文件呢,后面慢慢继续摸索,终于了解了,需要部署,部署是有API的,哈,这不就能解决这个问题了吗?以后我不需要processse文件夹了,可以直接部署自己想要的,想要部署哪一个就部署哪一个。

public Map addModle(String modelId){
        Map res=new HashMap<>();
        Model modelData =modelService.getModel(modelId);
        byte[] bytes = modelService.getBpmnXML(modelData);
        if(bytes==null){
            res.put("error","模型数据为空,请先设计流程并成功保存,再进行发布。");
            return res;
        }

        BpmnModel model = modelService.getBpmnModel(modelData);
        if(model.getProcesses().size()==0){
            res.put("error","数据模型不符要求,请至少设计一条主线流程。");
            return res;
        }
        byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model);
        String processName = modelData.getName()+".bpmn20.xml";
        Deployment deployment = repositoryService.createDeployment()
                .name(modelData.getName())
                .addBytes(processName,bpmnBytes)
                .deploy();
        return res;
    }

3. 权限

      新增流程,处理流程,都可以了以后,考虑到,这个是一套单独的系统,但是这样以后肯定不行啊,不可能让用户在自己本身的业务系统里操作得好好的,来画一个流程还得再次登录,网上有的人说直接这里不适用权限@SpringBootApplication(exclude = SecurityAutoConfiguration.class),但是我个人觉得这个肯定不行啊,这不就脱离了初衷了嘛,于是自己准备把项目迁移到本身的聚合项目里来,我本身的项目是有一套权限管理的,使用的也是security,那就集成进来呗。首先把项目里涉及到权限的包给屏蔽了

        <!--security -->
        <!--<dependency>-->
            <!--<groupId>org.springframework.security</groupId>-->
            <!--<artifactId>spring-security-core</artifactId>-->
        <!--</dependency>-->
        <!--<dependency>-->
            <!--<groupId>org.springframework.security</groupId>-->
            <!--<artifactId>spring-security-config</artifactId>-->
        <!--</dependency>-->
        <!--<dependency>-->
            <!--<groupId>org.springframework.security</groupId>-->
            <!--<artifactId>spring-security-crypto</artifactId>-->
        <!--</dependency>-->
        <!--<dependency>-->
            <!--<groupId>org.springframework.security</groupId>-->
            <!--<artifactId>spring-security-web</artifactId>-->
        <!--</dependency>-->
        <!-- Servlet -->

然后继续屏蔽IDM应用,因为flowable IDM应用就主要是用户权限啥的,我们既然有,保留这个也没什么用。

        <!--security -->
        <!--<dependency>-->
            <!--<groupId>org.springframework.security</groupId>-->
            <!--<artifactId>spring-security-core</artifactId>-->
        <!--</dependency>-->
        <!--<dependency>-->
            <!--<groupId>org.springframework.security</groupId>-->
            <!--<artifactId>spring-security-config</artifactId>-->
        <!--</dependency>-->
        <!--<dependency>-->
            <!--<groupId>org.springframework.security</groupId>-->
            <!--<artifactId>spring-security-crypto</artifactId>-->
        <!--</dependency>-->
        <!--<dependency>-->
            <!--<groupId>org.springframework.security</groupId>-->
            <!--<artifactId>spring-security-web</artifactId>-->
        <!--</dependency>-->
        <!-- Servlet -->

然后加入了自己的安全校验的包

<dependency>
    <groupId>com.tofly</groupId>
    <artifactId>common-oauth</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

我自身的系统使用的是token校验方式,这里可能还得研究一下,暂时处理方式就是把调用接口的地方都加上我这的token。

加上以后,发现modeler获取用户时都是从org.flowable.ui.common.security.SecurityUtils里去获取的用户信息,而org.flowable.ui.common.security.SecurityUtils里面使用的是org.flowable.ui.common.security.FlowableAppUser对象,我们自身的系统肯定不是使用的这个,那怎么办,替换调呗,于是新建org.flowable.ui.common.security.SecurityUtils直接把已经存在的给替代掉。将自己系统使用的对象转换为FlowableAppUser对象

package org.flowable.ui.common.security;

import com.tofly.common.oauth.auth.ToflyUser;
import org.flowable.idm.api.User;
import org.flowable.ui.common.model.RemoteUser;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;

import java.util.Iterator;

public class SecurityUtils {
    private static User assumeUser;

    private SecurityUtils() {
    }

    public static String getCurrentUserId() {
        User user = getCurrentUserObject();
        return user != null ? user.getId() : null;
    }

    public static User getCurrentUserObject() {
        if (assumeUser != null) {
            return assumeUser;
        } else {
            User user = null;
            FlowableAppUser appUser = getCurrentFlowableAppUser();
            if (appUser != null) {
                user = appUser.getUserObject();
            }

            return user;
        }
    }

    public static FlowableAppUser getCurrentFlowableAppUser() {
        FlowableAppUser user = null;
        SecurityContext securityContext = SecurityContextHolder.getContext();
        if (securityContext != null && securityContext.getAuthentication() != null) {
            Object principal = securityContext.getAuthentication().getPrincipal();
            if (principal instanceof ToflyUser) {
                ToflyUser toflyUser=(ToflyUser)principal;
                RemoteUser remoteUser=new RemoteUser();
                remoteUser.setId(toflyUser.getUsername());
                remoteUser.setFullName(toflyUser.getRealName());
                remoteUser.setFirstName(toflyUser.getRealName());
                remoteUser.setPassword(toflyUser.getPassword());
                user=new FlowableAppUser(remoteUser,toflyUser.getUsername(),toflyUser.getAuthorities());
            }

        }

        return user;
    }

    public static boolean currentUserHasCapability(String capability) {
        FlowableAppUser user = getCurrentFlowableAppUser();
        Iterator var2 = user.getAuthorities().iterator();

        GrantedAuthority grantedAuthority;
        do {
            if (!var2.hasNext()) {
                return false;
            }

            grantedAuthority = (GrantedAuthority)var2.next();
        } while(!capability.equals(grantedAuthority.getAuthority()));

        return true;
    }

    public static void assumeUser(User user) {
        assumeUser = user;
    }

    public static void clearAssumeUser() {
        assumeUser = null;
    }
}

这里获取就可以了,当然还要进入modeler系统时,顶部还有一个获取,但是这里面调用了idm的一些,而我们不适用idm,肯定获取不到了,所以把这个接口也给替换掉把,

package com.tofly.flowable.controller;

import com.tofly.common.oauth.auth.ToflyUser;
import com.tofly.common.oauth.util.SecurityUtils;
import org.flowable.ui.common.model.UserRepresentation;
import org.flowable.ui.common.security.DefaultPrivileges;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

/**
 * @author tuonbed
 * @date 2019/11/16  9:42
 */
@RestController
@RequestMapping("/app")
public class UserInfoController {

    public UserInfoController() {
    }
    @RequestMapping(value = "/rest/account", method = RequestMethod.GET, produces = "application/json")
    public UserRepresentation getAccount() {
        UserRepresentation userRepresentation = new UserRepresentation();
        ToflyUser toflyUser= SecurityUtils.getUser();
        userRepresentation.setId(toflyUser.getUsername());
        userRepresentation.setLastName(toflyUser.getRealName());
        userRepresentation.setFirstName(toflyUser.getUsername());
        List<String> privileges = new ArrayList<>();
        privileges.add(DefaultPrivileges.ACCESS_MODELER);
        privileges.add(DefaultPrivileges.ACCESS_IDM);
        privileges.add(DefaultPrivileges.ACCESS_ADMIN);
        privileges.add(DefaultPrivileges.ACCESS_TASK);
        privileges.add(DefaultPrivileges.ACCESS_REST_API);
        userRepresentation.setPrivileges(privileges);
        return userRepresentation;
    }
}

别忘了 移除已经存在的

  excludeFilters = {
                @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = RemoteAccountResource.class)

至此,权限系统已经使用自己的了。

至于用户的同步,用户组的同步问题,这个很好解决,在自己的系统里使用消息队列,消息推送,异步调用等等都可以实现。

4. 使用

这个就得看如何规划的了,查询模板,部署模板。任务启动,任务处理,任务结束。使用org.flowable.engine.RuntimeService,org.flowable.engine.TaskService,org.flowable.engine.RepositoryService 这些API就行了,上面发的博客地址也有个专门的ExpenseController,依据葫芦画瓢就可以了。

 

第一次写博客,自己记录一下吧,希望自己以后养成写博客的好习惯。源码还未看的,书非借不能读也,希望遇见更多的问题,就能更多的了解相关知识。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值