自制审批流框架记录

Posted Pursuer丶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自制审批流框架记录相关的知识,希望对你有一定的参考价值。

一、使用步骤

下载:https://gitee.com/gs_work/process-spring-boot-starter.git

通过Maven打包

安装到本地Maven仓库:

#jar包方式安装(安装安装记得用resource下的pom文件覆盖本地仓库的)
mvn install:install-file -Dfile=jar包路径 -DgroupId=com.shallowUniverse -DartifactId=process-spring-boot-starter -Dversion=0.0.1-SNAPSHOT -Dpackaging=jar
#在文件夹中安装
mvn clean install

导入启动器中的flowdesign.sql文件到自己的数据库

创建SpringBoot工程引入依赖

<dependency>
    <groupId>com.qianyu</groupId>
    <artifactId>process-spring-boot-starter</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

配置文件(application.yml)配置流程引擎需要的环境

#配置流程引擎数据库对象参数、处理器扫描路径
process:
  database: flowdesign
  user-table: system_user
  user-id: id
  user-name: realName
  role-table: system_role
  role-id: id
  role-name: rname
  dept-table: dept
  dept-id: id
  dept-name: name
  handler-packages: com.example.testflow.handler

启动类开启流程引擎自动配置(@EnableProcess)

@SpringBootApplication
@EnableProcess
@MapperScan(basePackages = {"com.example.process.mapper"})
public class TestFlowApplication {

    public static void main(String[] args) {
        SpringApplication.run(TestFlowApplication.class, args);
    }
}

自定义拦截器(实现ProcessInterceptor接口)

@Component
public class ProcessUserInterceptor implements ProcessInterceptor {

    @Resource
    private ProcessUserManager processUserManager;

    @Override
    public void beforeExecuteProcessor(HttpServletRequest httpServletRequest) {
        //这里正常情况是从request解析token或者session拿到用户信息,此处为测试
        ProcessUser processUser = new ProcessUser();
        processUser.setId(1L);
        processUser.setRealName("gs");
        processUser.setUsername("gs");
        processUser.setUserRoles("1");
        processUser.setDeptId(1L);
        processUserManager.setSysUser(processUser);
    }

    @Override
    public void postExecuteProcessor(Method method, Object returnValue) {
        if ("findByRole".equals(method.getName())) {
            System.out.println("转换之前=========>");
            System.out.println(returnValue);
            System.out.println("转换之后=========>");
            List<Approval> approvals = (List<Approval>) returnValue;
            approvals.clear();
            returnValue = approvals;
        }
    }
}

拦截器放入流程引擎

@Configuration
public class ProcessConfig implements ProcessInterceptorConfigurer {

    @Resource
    private ProcessUserInterceptor processUserInterceptor;

    @Override
    public void configurer(ProcessEngine processEngine) {
        //增加用户校验拦截器
        processEngine.addInterceptor(processUserInterceptor);
    }
}

自己的数据库用户表对应的实体实现SysUser接口(可以不实现直接使用ProcessUser对象封装数据)

public class SystemUser implements SysUser {

    private Long id;
    private String username;
    private Long dept;
    private String realName;
    private String userRoles;

    @Override
    public Long getId() {
        return id;
    }

    @Override
    public Long getDept() {
        return dept;
    }

    @Override
    public String getUsername() {
        return username;
    }

    @Override
    public String getUserRoles() {
        return userRoles;
    }

    @Override
    public String getRealName() {
        return realName;
    }
}

在需要开启审批的方法上加上注解

@Service
public class LeavesService extends ServiceImpl<LeavesMapper, Leaves> {

    @Resource
    private LeavesMapper leavesMapper;

    @ProcessBegin(value = "leaves")
    @Override
    public boolean save(@ProcessEntry(primaryKey = "leavesId", processField = "flowId",underscoreToCamelCase = true) Leaves leaves) {
        return leavesMapper.insert(leaves) > 0;
    }
}

编写后置处理器

//实现FlowFinishedHandler接口
//要加上component注解,因为处理器是全部放在spring容器中,后续加载也会从spring容器加载
@ProcessHandler("leaves")
@Component
public class LeavesFlowHandler implements ProcessFinishedHandler {
​
    //审批同意后的自动回调
    @Override
    public void postAllowHandle(String jsonApproval, ApprovalDetails approvalDetails) {
        System.out.println(JSON.parseObject(jsonApproval, Leaves.class));
    }
 
    //审批拒绝后的自动回调
    @Override
    public void postRefuseHandle(String jsonApproval,ApprovalDetails approvalDetails) {
        System.out.println("拒绝");
    }
}

在需要使用的地方引入FlowEngine对象

    @Autowired
    private FlowEngine flowEngine;
​
    //此处为测试代码,实际场景由客户端发送请求controller处理
    @Test
    public void contextLoads() throws FormNotExistException {
        Emp emp = new Emp();
        emp.setEid(1);
        flowEngine.login(emp);
        Leaves leaves = new Leaves();
        leaves.setContent("请假");
        leaves.setIsvalid(1);
        leavesService.save(leaves);
    }

二、注解以接口介绍

@ProcessBegin

  • value:要做流程的表名,和数据库对应

@ProcessEntry

  • primaryKey:实体主键字段名
  • underscoreToCamelCase:主键是否驼峰
  • processField:实体流程字段名

@ProcessHandler

  • value:做流程的表名,和@ProcessBegin填写的对应

SysUser

  • Long getId();
    当前用户id
  • Long getDept();
    当前用户部门id
  • String getUsername();
    当前用户用户名
  • String getUserRoles();
    当前用户角色id字符串,格式1,2,3
  • String getRealName();
    当前用户真实姓名

ProcessInterceptor

  • void beforeExecuteProcessor(HttpServletRequest httpServletRequest);
    这里主要用于解析token或者session拿到用户信息
  • void postExecuteProcessor(Method method, Object returnValue);
    可以对拿到的返回值进行过滤

ProcessInterceptorConfigurer

  • void configurer(ProcessEngine processEngine)
    可以在加载时拿到ProcessEngine对象,添加拦截器或进行改造扩展

ProcessFinishedHandler

  • void postAllowHandle(String jsonForm, ApprovalDetails formAudit)
    审批全部同意以后的回调方法,第一个参数为目标表数据json串,可自行转回对象
  • void postRefuseHandle(String jsonForm, ApprovalDetails formAudit)
    审批中途拒绝以后的回调方法,第一个参数为目标表数据json串,可自行转回对象

ProcessUserManager

  • SysUser getSysUser();
    拿到当前用户
  • void setSysUser(SysUser sysUser);
    设置当前用户

三、执行流程原理

  1. 应用程序启动扫描配置文件配置的处理器包路径从Spring容器中加载所有@ProcessHandler对应的类存入ProcessHandlerManager容器
  2. 自定义拦截器在流程引擎方法被调用前将用户信息存入ProcessUserManager
  3. 执行加了@ProcessBegin的方法时通过SpringAOP环绕通知解析@ProcessEntry的实体并将其封装为审批单对象存入数据库
  4. ProcessEngine的executeApproval()方法执行过程中发现审批流程结束从ProcessHandlerManager中通过源表名获取处理器
  5. 获取到处理器后调用postAllowHandle或postRefuseHandle,至此流程结束

四、注意事项

至少要编写一个自定义拦截器解析token或者session拿到用户信息并放入ProcessUserManager,否则无法正常做审批流,启动类上要加上@EnableProcess注解,否则不会加载ProcessEngine对象,配置文件的dept相关的字段可不配置,不配置的情况下不会根据部门进行节点匹配,可根据需求自行配置,用户管理器ProcessUserManager的默认作用域为审批流框架内部方法,如需增加作用域请编写切面,参考如下:

@Aspect
@Component
public class MyAspect {

    @Resource
    private ProcessEngine processEngine;

    @Pointcut("execution(* com.example.process.service.*.*(..))")
    public void pointCut() {

    }

    @Before("pointCut()")
    public void before() throws AuthenticationException {
        processEngine.autoWriedUser();
    }
}

以上是关于自制审批流框架记录的主要内容,如果未能解决你的问题,请参考以下文章

salesforce零基础学习(八十二)审批邮件获取最终审批人和审批意见

Salesforce 配置教程- 如何添加多个审批人

工作流和审批流的区别?

钉钉审批流回调

ERP-U9 调入单审批流按子行存储地点自动审批设置

钉钉调用审批流