若依cloud微服务集成activiti7或activiti8

前言

   想要在自己的代码中集成activiti这是一个复杂而长期的工作。集成是很容易的但是能和自己的权限管理和业务结合起来,就是一个不断扩展不断提炼的过程。若是一篇文章能全部讲解完毕这是一个困难的事情,这里我只能讲解一些必要的集成过程。

第一步、需要有一个流程图设计器集成到系统中(activiti-designer)。

在这里插入图片描述

第二步、需要集成activiti到自己的模块中

说明:中央仓库最后的版本只有7.1.0.M6若是需要集成activiti题最新的版本需要到activiti自己的仓库中下载:
https://artifacts.alfresco.com/nexus/content/repositories/activiti-releases/

尤其是springboot升级到3.x的版本后需要下载高版本的activiti8.x
在这里插入图片描述
nacos中的配置

spring:
  activiti:
    # 数据库的更新策略drop-create
    database-schema-update: true
    #检查历史表是否存在
    db-history-used: true
    #校验流程文件,默认校验resources下的processes文件夹里的流程文件
    check-process-definitions: false
    # 记录历史等级 可配置的历史级别有none, acitivity, audit, full
    history-level: full 
    #default  never-fail(关闭springboot自动部署流程)
    deployment-mode: never-fail

第三步、接入自己的权限管理系统

说明主要有两个类:UserDetailsService SecurityUtil.java

package com.cxbank.act.service.impl;

import com.cxbank.common.core.constant.SecurityConstants;
import com.cxbank.common.core.domain.R;
import com.cxbank.common.core.exception.ServiceException;
import com.cxbank.common.core.utils.StringUtils;
import com.cxbank.system.api.RemoteUserService;
import com.cxbank.system.api.domain.SysUser;
import com.cxbank.system.api.model.LoginUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

public class MyUserDetailsService implements UserDetailsService {
    @Autowired
    RemoteUserService remoteUserService;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        R<LoginUser> userResult= remoteUserService.getUserInfo(username, SecurityConstants.INNER);
        if (R.FAIL == userResult.getCode())
        {
            throw new ServiceException(userResult.getMsg());
        }
        if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData()))
        {
            throw new ServiceException("用户:" + username + " 不存在");
        }
        LoginUser userInfo = userResult.getData();
        SysUser user = userResult.getData().getSysUser();
        return new User(user.getUserName(),user.getPassword(),
                AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ACTIVITI_USER"));

    }
}

package com.cxbank.act.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;

import java.util.Collection;

@Component
public class SecurityUtil {
    // 模拟调用了SpringSecurity 登录鉴权
    private Logger logger = LoggerFactory.getLogger(SecurityUtil.class);

    @Autowired
    private UserDetailsService userDetailsService;

    public void logInAs(String username) {

        UserDetails user = userDetailsService.loadUserByUsername(username);
        if (user == null) {
            throw new IllegalStateException("User " + username + " doesn't exist, please provide a valid user");
        }
        logger.info("> Logged in as: " + username);
        SecurityContextHolder.setContext(new SecurityContextImpl(new Authentication() {
            @Override
            public Collection<? extends GrantedAuthority> getAuthorities() {
                return user.getAuthorities();
            }

            @Override
            public Object getCredentials() {
                return user.getPassword();
            }

            @Override
            public Object getDetails() {
                return user;
            }

            @Override
            public Object getPrincipal() {
                return user;
            }

            @Override
            public boolean isAuthenticated() {
                return true;
            }

            @Override
            public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {

            }
            @Override
            public String getName() {
                return user.getUsername();
            }
        }));
        org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(username);
    }
}

第四步、实现流程节点的Listener

这里面的listener一般有根绝角色找人、根据机构和角色找人、根据用户编号找人这三种,此处我列出其中一种根据角色获取参与者,当然这里面有自己的业务逻辑的代码比如代理、代办、交接的一些逻辑这些可以不用看。

package com.cxbank.act.listener;

import com.cxbank.act.domain.ActExtendAgent;
import com.cxbank.act.domain.ActExtendAgentFlow;
import com.cxbank.act.domain.ActExtendHandover;
import com.cxbank.act.domain.ActExtendHandoverFlow;
import com.cxbank.act.mapper.ActExtendAgentMapper;
import com.cxbank.act.mapper.ActExtendHandoverMapper;
import com.cxbank.act.service.IWorkFlowParticipant;
import com.cxbank.act.utils.ActConstants;
import com.cxbank.common.core.exception.act.NoParticipantException;
import com.cxbank.system.api.domain.WFParticipant;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.TaskListener;
import org.activiti.engine.impl.el.FixedValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

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

/**
 * 功能描述:
 *
 * @author zhangbo
 * @created 2020年11月21日
 * @version 1.0.0
 */
@Component(value = "taskSetUserByRoleListener")
public class TaskSetUserByRoleListener implements TaskListener {
	@Autowired
	IWorkFlowParticipant workFlowParticipant;
	@Autowired
	private ActExtendAgentMapper actExtendAgentMapper;
	@Autowired
	private ActExtendHandoverMapper actExtendHandoverMapper;
	private static final Logger log = LoggerFactory.getLogger(TaskSetUserByRoleListener.class);
	String EVENTNAME_CREATE = "create";
	String EVENTNAME_ASSIGNMENT = "assignment";
	String EVENTNAME_COMPLETE = "complete";
	String EVENTNAME_DELETE = "delete";

	private FixedValue roleCode;


	public FixedValue getRoleCode() {
		return roleCode;
	}

	public void setRoleCode(FixedValue roleCode) {
		this.roleCode = roleCode;
	}



	/**
	 */
	private static final long serialVersionUID = 1L;

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.activiti.engine.delegate.TaskListener#notify(org.activiti.engine.delegate
	 * .DelegateTask)
	 */
	@Override
	public void notify(DelegateTask delegateTask) {
		String eventName = delegateTask.getEventName();

		Object role = roleCode.getValue(delegateTask);
		if (null==role || "".equals(role.toString().trim()) ){
			log.error("流程:"+delegateTask.getProcessInstanceId()+"的"+delegateTask.getTaskDefinitionKey()+"节点参与角色流程图中未配置");
			throw  new NoParticipantException("下一节点的参与者未配置,请联系系统管理员!");
		}
		//获取当前节点的参与者
		List<WFParticipant> userCodes = workFlowParticipant.getParticipantByRole(role.toString().trim());
		if(userCodes.size()==0){
			log.error("流程:"+delegateTask.getProcessInstanceId()+"的"+delegateTask.getTaskDefinitionKey()+"节点参与角色{}下未配置人员",role.toString().trim());
			throw  new NoParticipantException("下一节点的参与人员未获取到,请联系系统管理员!");
		}

		ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
		String tenantId=delegateTask.getTenantId();
		String key=engine.getRepositoryService().createProcessDefinitionQuery().processDefinitionId(delegateTask.getProcessDefinitionId()).singleResult().getKey();
		//流程是否为回退
		Object isBackVarValue=delegateTask.getVariable(ActConstants.OPERATE_IS_BACK_VAR_NAME);
		boolean isBack= (null != isBackVarValue && Boolean.parseBoolean(isBackVarValue.toString()));
		List<String> wFParticipants =new ArrayList<String>();

		String userId="";
		ActExtendHandoverFlow actExtendHandoverFlow=null;
		ActExtendAgentFlow actExtendAgentFlow=null;
		List<ActExtendHandover> actExtendHandovers=null;
		List<ActExtendAgent> actExtendAgents=null;
		for (WFParticipant wfp:userCodes){
			userId=wfp.getUserCode();
			actExtendHandoverFlow =new ActExtendHandoverFlow();
			actExtendHandoverFlow.setCreateBy(userId);
			actExtendHandoverFlow.setTenantId(tenantId);
			actExtendHandoverFlow.setActKey(key);
			actExtendHandoverFlow.setProcessInstanceId(delegateTask.getProcessInstanceId());
			actExtendHandovers = actExtendHandoverMapper.selectFlowNodeHandoverUsers(actExtendHandoverFlow);
            //当有交接用户 且当前节点是退回的节点  直接进行交接
			if(null!=actExtendHandovers && actExtendHandovers.size()>0 && isBack){
				for (ActExtendHandover actExtendHandover:actExtendHandovers){
					wFParticipants.add(actExtendHandover.getReceiverId());
				}
			}else {
				/**
				 * 当没有交接时候  或 不是回退节点  此时处理代理、代办人员
				 */
				actExtendAgentFlow = new ActExtendAgentFlow();
				actExtendAgentFlow.setCreateBy(userId);
				actExtendAgentFlow.setTenantId(tenantId);
				actExtendAgentFlow.setActKey(key);
				actExtendAgents = actExtendAgentMapper.selectFlowNodeEntrustUsers(actExtendAgentFlow);
				if (null == actExtendAgents || actExtendAgents.size() == 0) {
					wFParticipants.add(wfp.getUserCode());
					continue;
				}
				boolean b=true;
				for (ActExtendAgent actExtendAgent : actExtendAgents) {
					if (ActConstants.entrustType.DO_STH_FOR_SB.getInfo().equals(actExtendAgent.getEntrustType())) {
						 b=false;
						break;
					}
				}
				List<String> wFParticipants2 = new ArrayList<String>();
				//没有代办就添加此用户
				if(b) {
					wFParticipants.add(wfp.getUserCode());
				}
				//添加代理代办用户
				for (ActExtendAgent actExtendAgent : actExtendAgents) {
					wFParticipants.add(actExtendAgent.getAgentId());
				}
			}
		}
		if (EVENTNAME_CREATE.endsWith(eventName)) {
			if(wFParticipants.size()>0) {
				log.info("开始为任务id为:"+delegateTask.getId()+"的任务设置参与者。");
				delegateTask.addCandidateUsers(wFParticipants);
			}else{
              //log.error("任务id为:"+delegateTask.getId()+"的参与者未获取到");
				 throw  new NoParticipantException("下一步的参与者未获取到,请联系系统管理员!");
			}
		} else if (EVENTNAME_ASSIGNMENT.endsWith(eventName))
			System.out.println("assignment===任务分配");
		else if (EVENTNAME_COMPLETE.endsWith(eventName))
			System.out.println("complete===任务完成");
		else if (EVENTNAME_DELETE.endsWith(eventName))
			System.out.println("delete===任务删除");
	}

}

第五步、前端整合

   前端整合,我这边儿是把流程统一发起、统一审核,这里面真核起来需要和流程图结合起来当然这需要许多扩展表和后台java代码的支撑。
   我认为你只需要把握流程图中节点中配置的formkey这个关键属性以此和自己的前端代码结合使用就可整合。

在这里插入图片描述
在这里插入图片描述

基础支撑和扩展

在这里插入图片描述
下边儿是我集成的一些截图片段:
流程部署:主要是在线绘制流程发布后再设置相关配置。
在这里插入图片描述
设置流程图属性、或选中流程节点设置相关数据、操作等等
在这里插入图片描述
实例管理:针对所有的流程实例管理,可以再此处对流程进行前进后退等操作方便管理人员管理所有流程实例。
在这里插入图片描述
在这里插入图片描述
流程统一发起
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

流程统一审核:
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值