Acticiti7工作流引擎

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.imooc</groupId>
    <artifactId>activitiweb</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>activitiweb</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter</artifactId>
            <version>7.1.0.M4</version>
        </dependency>
        <dependency>
            <groupId>org.activiti.dependencies</groupId>
            <artifactId>activiti-dependencies</artifactId>
            <version>7.1.0.M4</version>
            <type>pom</type>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.2</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.2</version>
                <configuration>
                    <verbose>true</verbose>
                    <overwrite>true</overwrite>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.1</version>
                <configuration>
                    <skipTests>true</skipTests>
                </configuration>
            </plugin>

        </plugins>
    </build>

</project>

 

ymal

server:
  port: 8080
  servlet:
    context-path: /
    session:
      timeout: 9000
spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/activiti?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC&nullCatalogMeansCurrent=true
    driver-class-name: com.mysql.cj.jdbc.Driver
    #日志的相关配置
logging:
  level:
    root: info
#日志的相关配置
spring.activiti.history-level: full
spring.activiti.db-history-used: true
# spring-activiti
# 自动部署验证设置:true-开启(默认)、false-关闭
spring.activiti.check-process-definitions: false

 

user.sql

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- 创建用户表
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) DEFAULT NULL COMMENT '姓名',
  `address` varchar(64) DEFAULT NULL COMMENT '联系地址',
  `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '账号',
  `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '密码',
  `roles` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '角色',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

-- ----------------------------
-- 填充用户表
-- ----------------------------
INSERT INTO `user` VALUES ('1', 'admincn', 'beijing', 'admin', '$2a$10$gw46pmsOVYO.smHYQ2jH.OoXoe.lGP8OStDkHNs/E74GqZDL5K7ki', 'ROLE_ACTIVITI_ADMIN');
INSERT INTO `user` VALUES ('2', 'bajiecn', 'shanghang', 'bajie', '$2a$10$gw46pmsOVYO.smHYQ2jH.OoXoe.lGP8OStDkHNs/E74GqZDL5K7ki', 'ROLE_ACTIVITI_USER,GROUP_activitiTeam,g_bajiewukong');
INSERT INTO `user` VALUES ('3', 'wukongcn', 'beijing', 'wukong', '$2a$10$gw46pmsOVYO.smHYQ2jH.OoXoe.lGP8OStDkHNs/E74GqZDL5K7ki', 'ROLE_ACTIVITI_USER,GROUP_activitiTeam');
INSERT INTO `user` VALUES ('4', 'salaboycn', 'beijing', 'salaboy', '$2a$10$gw46pmsOVYO.smHYQ2jH.OoXoe.lGP8OStDkHNs/E74GqZDL5K7ki', 'ROLE_ACTIVITI_USER,GROUP_activitiTeam');

-- ----------------------------
-- 修复Activiti7的M4版本缺失字段Bug
-- ----------------------------
alter table ACT_RE_DEPLOYMENT add column PROJECT_RELEASE_VERSION_ varchar(255) DEFAULT NULL;
alter table ACT_RE_DEPLOYMENT add column VERSION_ varchar(255) DEFAULT NULL;

-- ----------------------------
-- 动态表单数据存储
-- ----------------------------
DROP TABLE IF EXISTS `formdata`;
CREATE TABLE `formdata` (
  `PROC_DEF_ID_` varchar(64) DEFAULT NULL,
  `PROC_INST_ID_` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `FORM_KEY_` varchar(255) DEFAULT NULL,
  `Control_ID_` varchar(100) DEFAULT NULL,
  `Control_VALUE_` varchar(2000) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 

 

 

----------------------------------------------------------------------------------
Activiti7工作流引擎
activiti bpmn visualizer最终这个插件可用(idea插件)。

Activiti7经典类
流程部署deployment
流程定义processDefinition
流程实例processInstance
任务处理Task
历史任务historicTaskInstance

流程部署deploymen:指定流程key,指定流程名称,任务指定执行人,上传bpmn,增删改查,查询列表和查询xml。


    //通过bpmn部署流程
    @Test
    public void initDeploymentBPMN(){
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

        try {
            Resource[] resources = resolver.getResources("classpath*:**/process/Part1_Deployment.bpmn");
            for (Resource resource : resources) {
                Deployment deployment=repositoryService.createDeployment()
                        .addInputStream(resource.getFilename(),
                                resource.getInputStream())
                        .name("流程部署测试bpmn")
                        .deploy();
                System.out.println(deployment.getName());
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

//act_re_deployment表增加了记录
//act_ge_bytearray表增加了记录

    //通过png部署流程
    @Test
    public void initDeploymentPNG(){
        
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        try {
            Resource[] resources = resolver.getResources("classpath*:**/process/Part1_Deployment.png");
            for (Resource resource : resources) {
                Deployment deployment=repositoryService.createDeployment()
                        .addInputStream(resource.getFilename(),
                                resource.getInputStream())
                        .name("流程部署测试png")
                        .deploy();
                System.out.println(deployment.getName());
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

//act_re_deployment表增加了记录
//act_ge_bytearray表增加了记录



    //通过ZIP部署流程
    @Test
    public void initDeploymentZIP() {
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        try {
            Resource[] resources = resolver.getResources("classpath*:**/process/Part1_DeploymentV2.zip");
            for (Resource resource : resources) {
                ZipInputStream zip=new ZipInputStream(resource.getInputStream());
                Deployment deployment=repositoryService.createDeployment()
                        .addZipInputStream(zip)
                        .name("流程部署测试zip")
                        .deploy();
                System.out.println(deployment.getName());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

//act_re_deployment表增加了记录
//act_ge_bytearray表增加了记录



    //查询流程部署
    @Test
    public void getDeployments() {
        List<Deployment> list = repositoryService.createDeploymentQuery().list();
        for(Deployment dep : list){
            System.out.println("Id:"+dep.getId());
            System.out.println("Name:"+dep.getName());
            System.out.println("DeploymentTime:"+dep.getDeploymentTime());
            System.out.println("Key:"+dep.getKey());
        }

    }

-----------------------------------------------------------------------------------------------------------
流程定义processDefinition

Deployment:添加资源文件,获取部署信息,部署时间
ProcessDefinition: 获取版本号,key,资源名称,部署ID等。


act_re_procdef表

    //查询流程定义
    @Test
    public void getDefinitions(){
        List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery()
                .list();
        for(ProcessDefinition pd : list){
            System.out.println("------流程定义--------");
            System.out.println("Name:"+pd.getName());
            System.out.println("Key:"+pd.getKey());
            System.out.println("ResourceName:"+pd.getResourceName());
            System.out.println("DeploymentId:"+pd.getDeploymentId());
            System.out.println("Version:"+pd.getVersion());

        }

    }


    //删除流程定义
    @Test
    public void delDefinition(){

        String pdID="1a8bcf80-e132-11f0-9d85-0a0027000006";
        repositoryService.deleteDeployment(pdID,true);
        System.out.println("删除流程定义成功");
    }

-----------------------------------------------------------------------------------------------------------
流程实例processInstance


    //初始化流程实例
    @Test
    public void initProcessInstance(){
        //1、获取页面表单填报的内容,请假时间,请假事由,String fromData
        //2、fromData 写入业务表,返回业务表主键ID==businessKey
        //3、把业务数据与Activiti7流程数据关联
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("Part1_Deployment","bKey001");
        System.out.println("流程实例ID:"+processInstance.getProcessDefinitionId());

    }


//act_ru_execution表
//act_ru_identitylink表


    //获取流程实例列表
    @Test
    public void getProcessInstances(){
        List<ProcessInstance> list = runtimeService.createProcessInstanceQuery().list();
        for(ProcessInstance pi : list){
            System.out.println("--------流程实例------");
            System.out.println("ProcessInstanceId:"+pi.getProcessInstanceId());
            System.out.println("ProcessDefinitionId:"+pi.getProcessDefinitionId());
            System.out.println("isEnded:"+pi.isEnded());
            System.out.println("isSuspended:"+pi.isSuspended());
            System.out.println("Name:"+pi.getName());
        }

    }


    //挂起与激活流程实例
    @Test
    public void activitieProcessInstance(){
//         runtimeService.suspendProcessInstanceById("5dc1d19a-e158-11f0-8ad9-0a0027000006");
//        System.out.println("挂起流程实例");

        runtimeService.activateProcessInstanceById("5dc1d19a-e158-11f0-8ad9-0a0027000006");
        System.out.println("激活流程实例");
    }


    //删除流程实例
    @Test
    public void delProcessInstance(){
        runtimeService.deleteProcessInstance("5dc1d19a-e158-11f0-8ad9-0a0027000006","测试");
        System.out.println("删除流程实例");
    }


-----------------------------------------------------------------------------------------------------------
任务处理Task
用户任务:Assignee:执行人、代理人。
用户任务:Candidate Users: 候选人。
用户任务:Candidate Groups: 候选组。
用户任务:Due Date: 任务到期时间。

新建 Part4_Task.bpmn
运行 initDeploymentBPMN
运行 getDefinitions
运行 initProcessInstance



    //任务查询
    @Test
    public void getTasks(){
        List<Task> list = taskService.createTaskQuery().list();
        for(Task tk : list){
            System.out.println("Id:"+tk.getId());
            System.out.println("Name:"+tk.getName());
            System.out.println("Assignee:"+tk.getAssignee());
        }
    }


    //查询我的代办任务
    @Test
    public void getTasksByAssignee(){
        List<Task> list = taskService.createTaskQuery()
                .taskAssignee("bajie")
                .list();
        for(Task tk : list){
            System.out.println("Id:"+tk.getId());
            System.out.println("Name:"+tk.getName());
            System.out.println("Assignee:"+tk.getAssignee());
        }

    }

//act_ru_task表


新建 Part4_Task_claim.bpmn
运行 initDeploymentBPMN
运行 getDefinitions
运行 initProcessInstance


    //拾取任务
    @Test
    public void claimTask(){
        Task task = taskService.createTaskQuery().taskId("210a762b-e167-11f0-b62e-0a0027000006").singleResult();
        taskService.claim("210a762b-e167-11f0-b62e-0a0027000006","bajie");
        System.out.println("拾取任务");
    }

-----------------------------------------------------------------------------------------------------------
查询历史记录
历史综合信息:HistoricTaskInstance
历史变量:HistoricVariableInstance

//act_hi_actinst表
//act_hi_identitylink表
//act_hi_procinst表
//act_hi_taskinst表


    //根据用户名查询历史记录
    @Test
    public void HistoricTaskInstanceByUser(){
        List<HistoricTaskInstance> list = historyService
                .createHistoricTaskInstanceQuery()
                .orderByHistoricTaskInstanceEndTime().asc()
                .taskAssignee("bajie")
                .list();
        for(HistoricTaskInstance hi : list){
            System.out.println("Id:"+ hi.getId());
            System.out.println("ProcessInstanceId:"+ hi.getProcessInstanceId());
            System.out.println("Name:"+ hi.getName());

        }

    }

    //根据流程实例ID查询历史
    @Test
    public void HistoricTaskInstanceByPiID(){
        List<HistoricTaskInstance> list = historyService
                .createHistoricTaskInstanceQuery()
                .orderByHistoricTaskInstanceEndTime().asc()
                .processInstanceId("33c69ef1-e160-11f0-b1e2-0a0027000006")
                .list();
        for(HistoricTaskInstance hi : list){
            System.out.println("Id:"+ hi.getId());
            System.out.println("ProcessInstanceId:"+ hi.getProcessInstanceId());
            System.out.println("Name:"+ hi.getName());

        }
    }


-----------------------------------------------------------------------------------------------------------
UEL表达式
EL为表达式语言(Expression Language)
UEL统一表达式语言(Unified Expression Language)

表达式描述
表达式以 "${"开始",以"}"结束,例如${day > 100}
支持逻辑运算${userName == "bajie" and pwd== "123"}
支持变量与实体类赋值

对应activiti数据表
act_ru_variable运行时参数表
act_hi_varinst历史参数表

UEL表达式的保留字
and,eq,gt,
instanceof,div,or,
le,false,empty,
not,Lt,ge,

UEL表达式的运算符
+-*/或div 除
%或 mod 求余



新建 Part6_UEL_V1.bpmn
运行 initDeploymentBPMN
运行 getDefinitions
//运行 initProcessInstance


    //启动流程实例带参数,执行执行人
    @Test
    public void initProcessInstanceWithArgs() {
        //流程变量//${ZhiXingRen}
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("ZhiXingRen", "wukong");

        ProcessInstance processInstance = runtimeService
                .startProcessInstanceByKey("myProcess_UEL_V1"
                        , "bKey004"
                        , variables);
        System.out.println("流程实例ID:" + processInstance.getProcessDefinitionId());

    }

运行getTasksByAssignee


新建 Part6_UEL_V2.bpmn
运行 initDeploymentBPMN
运行 getDefinitions
运行 initProcessInstance



    //完成任务带参数
    @Test
    public void completeTaskWithArgs() {
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("ZhiXingRen", "wukong");
        taskService.complete("210a762b-e167-11f0-b62e-0a0027000006",null);
        System.out.println("完成任务");
    }

    //完成任务带参数,指定流程变量
    @Test
    public void completeTaskWithArgs2() {
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("pay", "101");
        taskService.complete("6e7e1179-e17e-11f0-ae29-0a0027000006",variables);
        System.out.println("完成任务");
    }


新建 Part6_UEL_V3.bpmn
运行 initDeploymentBPMN
//运行 getDefinitions

    //启动流程实例带参数,使用实体类
    @Test
    public void initProcessInstanceWithClassArgs() {

        UEL_POJO uelPojo = new UEL_POJO();
        uelPojo.setZhixingren("bajie");

        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("uelpojo", uelPojo);

        ProcessInstance processInstance = runtimeService
                .startProcessInstanceByKey("myProcess_UEL_V3"
                        , "bKey005"
                        , variables);
        System.out.println("流程实例ID:" + processInstance.getProcessDefinitionId());
    }

    //任务完成环节带参数,指定多个候选人
    @Test
    public void initProcessInstanceWithCandiDateArgs() {
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("houxuanren", "wukong,tangseng");
        taskService.complete("e0f16f7c-e18e-11f0-bcbb-0a0027000006",variables);
        System.out.println("完成任务");
    }


-------------------------------------------------------------------------------------------------
BPMN2.0网关
并行网关
排他网关
包容网关
事件网关



新建 Part7_Parallel.bpmn
运行 initDeploymentBPMN
运行 initProcessInstance

运行 completeTask

新建 Part7_Exclusive.bpmn
运行 initDeploymentBPMN


//        Map<String, Object> variables = new HashMap<String, Object>();
//        variables.put("day", "1");
//        taskService.complete("c9506c43-e24f-11f0-9c08-0a0027000006",variables);
//        System.out.println("完成任务");
        //沙僧  3c8dc419-e250-11f0-89f9-0a0027000006
        //悟空  3c8dc417-e250-11f0-89f9-0a0027000006
        taskService.complete("3c8dc419-e250-11f0-89f9-0a0027000006");
        taskService.complete("3c8dc417-e250-11f0-89f9-0a0027000006");
        System.out.println("完成任务");
-------------------------------------------------------------------------------------------------
ProcessRuntime
TaskRuntime

从github.com下载activiti
https://github.com/Activiti/Activiti
打开项目,复制子项目activiti-examples/activiti-api-basic-full-example-bean/下的
DemoApplicationConfiguration.java和SecurityUtil.java到Activiti7SpringbootApplication同级目录


    //获取流程实例
    @Test
    public void getProcessInstance(){
        securityUtil.logInAs("bajie");
        Page<ProcessInstance> processInstancePage = processRuntime
                .processInstances(Pageable.of(0,100));
        System.out.println("流程实例数量:" + processInstancePage.getTotalItems());
        List<ProcessInstance> list = processInstancePage.getContent();
        for(ProcessInstance pi : list){
            System.out.println("===================>");
            System.out.println("id:" + pi.getId());
            System.out.println("name:" + pi.getName());
            System.out.println("StartDate:" + pi.getStartDate());
            System.out.println("Status:" + pi.getStatus());
            System.out.println("ProcessDefinitionId:" + pi.getProcessDefinitionId());
            System.out.println("ProcessDefinitionKey:" + pi.getProcessDefinitionKey());
        }
    }


新建 Part8_ProcessRunTime.bpmn
运行 initDeploymentBPMN
运行 startProcessInstance


    //启动流程实例
    @Test
    public void startProcessInstance(){
        securityUtil.logInAs("bajie");
        ProcessInstance processInstance = processRuntime.start(
                ProcessPayloadBuilder.start()
                        .withProcessDefinitionKey("myProcess_ProcessRunTime")
                        .withName("第一个流程实例名称")
//                        .withVariable()
                        .withBusinessKey("buskey001")
                        .build()
        );
        System.out.println("流程实例ID:"+processInstance.getProcessDefinitionId());
    }


    //挂起流程实例
    @Test
    public void suspendProcessInstance(){
        securityUtil.logInAs("bajie");
        ProcessInstance processInstance = processRuntime.suspend(
                ProcessPayloadBuilder.suspend()
                        .withProcessInstanceId("170c3c11-e54f-11f0-a51e-0a0027000006")
                        .build()
        );
        System.out.println("挂起流程实例" + processInstance.getId());
    }


TaskRuntime


    //获取当前登录用户任务
    @Test
    public void getTasks(){
        securityUtil.logInAs("bajie");
        Page<Task> tasks = taskRuntime.tasks(Pageable.of(0, 100));
        System.out.println("任务数量:" + tasks.getTotalItems());
        List<Task> list = tasks.getContent();
        for(Task task: list){
            System.out.println("++++++++++++++++");
            System.out.println("Id: " + task.getId());
            System.out.println("name: " + task.getName());
            System.out.println("status: " + task.getStatus());
            System.out.println("createDate: " + task.getCreatedDate());
            System.out.println("assignee: " + task.getAssignee());
        }
    }

    //完成任务
    @Test
    public void completeTask(){
        securityUtil.logInAs("bajie");
        Task task = taskRuntime.task("eddbd9a9-e229-11f0-9645-0a0027000006");
        if(task.getAssignee() == null){
            taskRuntime.claim(TaskPayloadBuilder.claim()
                    .withTaskId(task.getId())
                    .build());

        }
        taskRuntime.complete(TaskPayloadBuilder
                .complete()
                .withTaskId(task.getId())
                .build());
        System.out.println("任务执行完成");
    }

-------------------------------------------------------------------------------------------------
SpringSecurity
认证
鉴权/授权

导入
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-security</artifactId>
    </dependency>


@Component
public class UserInfoBean implements UserDetails {
    private Long id;
    private String name;
    private String address;
    private String username;
    private String password;
    private String roles;



    public String getAddress(){
        return address;
    }
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {

        return Arrays.stream(roles.split(","))
                .map(s -> new SimpleGrantedAuthority(s))
                .collect(Collectors.toList());
    }

    @Override
    public String getPassword() {
        return password;
    }

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

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

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

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

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


@Mapper
@Component
public interface UserInfoBeanMapper {

    @Select("select * from user where username=#{username}")
    UserInfoBean selectByUsername(@Param("username") String username);
}



@Component
public class MyUserDetailsService implements UserDetailsService {

    @Resource
    UserInfoBeanMapper userInfoBeanMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

/*
        String passWorld = passwordEncoder().encode("111");
//        String passWorld = new BCryptPasswordEncoder().encode("111");

        return new User(username
        ,passWorld
        , AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ACTIVITI_USER"));
*/
        UserInfoBean userInfoBean = userInfoBeanMapper.selectByUsername(username);
        if(userInfoBean == null){
            throw new UsernameNotFoundException("数据库中无此用户");
        }
        return userInfoBean;

    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}




@Component("loginSuccessHandler")
public class LoginSuccessHandler implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) throws IOException, ServletException {
        AuthenticationSuccessHandler.super.onAuthenticationSuccess(request, response, chain, authentication);
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
        httpServletResponse.setContentType("application/json;charset=UTF-8");
        httpServletResponse.getWriter().write("登录成功LoginSuccessHandler," + authentication.getName());
    }
}



@Configuration
public class ActivitiSecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private LoginSuccessHandler loginSuccessHandler;

    @Resource
    private LoginFailureHandler loginFailureHandler;

    @Override
    protected void configure(HttpSecurity http)throws Exception{
        http.formLogin()
                .loginPage("/login")
                .loginProcessingUrl("/login")
                .successHandler(loginSuccessHandler)
                .failureHandler(loginFailureHandler)
                .and()
                .authorizeRequests()
                .anyRequest().permitAll()
                .and()
                .logout().permitAll()
                .and()
                .csrf().disable()
                .headers().frameOptions().disable();

    }
}

@Component("loginFailureHandler")
public class LoginFailureHandler implements AuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
        httpServletResponse.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        httpServletResponse.setContentType("application/json;charset=UTF-8");
        httpServletResponse.getWriter().write("登录失败: " + e.getMessage());
    }
}


@Controller
public class ActivitiSecurityController {

    @RequestMapping("/login")
    @ResponseStatus(code = HttpStatus.UNAUTHORIZED)
    public String requireAuthentication(HttpServletRequest request, HttpServletResponse response){
        return new String("需要登录,请使用login.html或者发起POST登录请求");
    }
}


-------------------------------------------------------------------------------------------------
bpmnjs整合
下载bpmnjs地址如下
https://github.com/bpmn-io/bpmn-js-examples
resources下再建resources目录
复制properties-panel到resources/resources目录下
在cmd窗口中cd到resources\resources\bpmnjs目录下,运行 npm install
再运行npm run dev

https://git.imooc.com/coding-454/activiti7_workflow

复制customControls文件夹
复制customTranslate文件夹
复制properties-panel文件夹
复制activiti.json
复制newDiagram.bpmn
到resources\resources\bpmnjs\resources下


打开resources\resources\bpmnjs\app\index.js
注释以下内容
import propertiesProviderModule from 'bpmn-js-properties-panel/lib/provider/camunda';
import camundaModdleDescriptor from 'camunda-bpmn-moddle/resources/camunda.json';

注释以下内容
var bpmnModeler = new BpmnModeler({
    container: canvas,
    propertiesPanel:{
        parent: '#js-properties-panel'
    },
    additionalModules:[
       propertiesPanelModule,
       propertiesProviderModule
       ],
       moddleExtensions:{
            camunda: camundaModdleDescriptor
        }
});

添加以下内容
import propertiesProviderModule from '../resources/properties-panel/provider/activiti';
import activitiModdleDescriptor from '../resources/activiti.json';
import customTranslate from '../resources/customTranslate/customTranslate';
import customControlsModule from '../resources/customControls';

添加组件
var customTranslateModule = {
     translate: ['value',customTranslate]
};

var bpmnModeler = new BpmnModeler({
    container: canvas,
    propertiesPanel:{
        parent: '#js-properties-panel'
    },
    additionalModules: [
        propertiesPanelModule,
        propertiesProviderModule,
        customControlsModule,
        customTranslateModule
    ],
    moddleExtensions:{
        activiti:activitiModdleDescriptor
   }
});

增加bpmn可执行选项默认勾选,打开resources/newDiagram.bpmn
属性修改isExecutable="true"
<bpmn2:process id="Process_1" isExecutable="true">



---------------------------------------------------------------------------
流程定义--------


    //添加流程定义通过上传bpmn
    @PostMapping("/uploadStreamAndDeployment")
    public AjaxResponse uploadStreamAndDeployment(@RequestParam("processFile") MultipartFile multipartFile
    ,@RequestParam("deploymentName") String deploymentName){
        try {
            String fileName = multipartFile.getOriginalFilename();
            //文件扩展名
            String extension = FilenameUtils.getExtension(fileName);
            InputStream fileInputStream = multipartFile.getInputStream();
            Deployment deployment = null;
            if(extension.equals("zip")){
                ZipInputStream zip = new ZipInputStream(fileInputStream);
                deployment = repositoryService.createDeployment()//初始化部署
                        .addZipInputStream(zip)
                        .name(deploymentName)
                        .deploy();
            }else{
                deployment = repositoryService.createDeployment()
                        .addInputStream(fileName,fileInputStream)
                        .name(deploymentName)
                        .deploy();
            }
            System.out.println("添加流程定义通过上传bpmn");
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(),
                    deployment.getId() +";" + fileName );
        }catch (Exception e){
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(), "流程部署失败",e.getMessage());
        }

    }


   //添加流程定义通过在线提交bpmn的xml
    @PostMapping("/addDeploymentByString")
    public AjaxResponse addDeploymentByString(@RequestParam("stringBPMN") String stringBPMN
            ,@RequestParam("deploymentName") String deploymentName){

        System.out.println("111111111111111111");
        try {
            Deployment deployment = repositoryService.createDeployment()
                            .addString("CreateWithBPMNJS.bpmn", stringBPMN)
                                    .name(deploymentName)
                                            .deploy();
            System.out.println("添加流程定义通过在线提交bpmn的xml");
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(),
                    deployment.getId() );
        }catch (Exception e){
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(), "string流程部署失败",e.getMessage());
        }

    }

    //获取流程定义列表
    @GetMapping("/getDefinitions")
    public AjaxResponse getDefinitions(){
        try {
            List<HashMap<String,Object>> listMap = new ArrayList<HashMap<String,Object>>();

                List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery()
                        .list();
                for (ProcessDefinition pd : list) {
                    HashMap<String,Object> hashMap = new HashMap<>();
                    hashMap.put("Name" , pd.getName());
                    hashMap.put("Key" , pd.getKey());
                    hashMap.put("ResourceName" , pd.getResourceName());
                    hashMap.put("DeploymentId" , pd.getDeploymentId());
                    hashMap.put("Version" , pd.getVersion());
                    System.out.println("------流程定义--------");
                    System.out.println("Name:" + pd.getName());
                    System.out.println("Key:" + pd.getKey());
                    System.out.println("ResourceName:" + pd.getResourceName());
                    System.out.println("DeploymentId:" + pd.getDeploymentId());
                    System.out.println("Version:" + pd.getVersion());
                    listMap.add(hashMap);
                }
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(),
                    listMap);
        }catch (Exception e){
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(), "获取流程定义失败",e.getMessage());
        }

    }


    //获取流程定义XML
    @GetMapping("/getDefinitionXML")
    public void getDefinitionXML(HttpServletResponse response, @RequestParam("deploymentID") String deploymentID
            , @RequestParam("resourceName") String resourceName){
        try {
            InputStream inputStream = repositoryService.getResourceAsStream(deploymentID,resourceName);
            int count = inputStream.available();
            byte[] bytes = new byte[count];
            response.setContentType("text/xml");
            OutputStream outputStream = response.getOutputStream();
            while (inputStream.read(bytes) != -1){
                outputStream.write(bytes);
            }
            inputStream.close();


        }catch (Exception e){
            e.getMessage();
        }

    }

    //获取流程部署列表
    @GetMapping("/getDeployments")
    public AjaxResponse getDeployments(){
        try {
            List<HashMap<String,Object>> listMap = new ArrayList<HashMap<String,Object>>();

            List<Deployment> list = repositoryService.createDeploymentQuery()
                    .list();
            for (Deployment dep : list) {
                HashMap<String,Object> hashMap = new HashMap<>();
                hashMap.put("Id" , dep.getId());
                hashMap.put("Name" , dep.getName());
                hashMap.put("DeploymentTime" , dep.getDeploymentTime());

                System.out.println("------流程定义--------");
                System.out.println("Id:" + dep.getId());
                System.out.println("Name:" + dep.getName());
                System.out.println("DeploymentTime:" + dep.getDeploymentTime());
                listMap.add(hashMap);
            }
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(),
                    listMap);
        }catch (Exception e){
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(), "获取流程部署列表失败",e.getMessage());
        }

    }


    //删除流程定义
    @GetMapping("/delDefinition")
    public AjaxResponse delDefinition(@RequestParam("pdID") String pdID){


        try {
            repositoryService.deleteDeployment(pdID,true);

            System.out.println("添加流程定义通过在线提交bpmn的xml");
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(),
                    null );
        }catch (Exception e){
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(), "删除流程定义失败",e.getMessage());
        }

    }

-----------------------------------------------------------------------------------------------------------
流程实例processInstance


    //获取流程实例列表
    @GetMapping("/getInstances")
    public AjaxResponse getInstances(@AuthenticationPrincipal UserInfoBean userInfoBean){
        try {
            if(GlobalConfig.Test){
                securityUtil.logInAs("bajie");
            }
            //else {
            //  securityUtil.logInAs(userInfoBean.getUsername());//这句不需要
            // }
            Page<ProcessInstance> processInstancePage = processRuntime.processInstances(Pageable.of(0,100));
            System.out.println("流程实例数量:" + processInstancePage.getTotalItems());
            List<ProcessInstance> list = processInstancePage.getContent();
            list.sort((y,x)->x.getStartDate().toString().compareTo(y.getStartDate().toString()));

            List<HashMap<String,Object>> listMap = new ArrayList<HashMap<String,Object>>();
            for(ProcessInstance pi: list){
                HashMap<String,Object> hashMap = new HashMap<>();
                hashMap.put("id",pi.getId());
                hashMap.put("name",pi.getName());
                hashMap.put("status",pi.getStatus());
                hashMap.put("processDefinitionId",pi.getProcessDefinitionId());
                hashMap.put("processDefinitionKey",pi.getProcessDefinitionKey());
                hashMap.put("startDate",pi.getStartDate());
                hashMap.put("processDefinitionVersion",pi.getProcessDefinitionVersion());
                //因为processRuntime.processDefinition("流程部署ID")查询的结果没有部署流程与部署ID,所以用repositoryService查询
                ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
                        .processDefinitionId(pi.getProcessDefinitionId())
                        .singleResult();

                hashMap.put("resourceName", pd.getResourceName());
                hashMap.put("deploymentId", pd.getDeploymentId());

                listMap.add(hashMap);
            }

            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(),
                    listMap);
        }catch (Exception e){
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(), "获取流程实例列表失败",e.getMessage());
        }

    }

    //启动流程实例
    @GetMapping(value = "/startProcess")
    public AjaxResponse startProcess(@RequestParam("processDefinitionKey") String processDefinitionKey,
                                     @RequestParam("instanceName") String instanceName
//            ,@RequestParam("instanceVariable") String instanceVariable
    ) {
        try {
            if (GlobalConfig.Test) {
                securityUtil.logInAs("bajie");
            }
//            else{
//                securityUtil.logInAs(SecurityContextHolder.getContext().getAuthentication().getName());
//            }
            ProcessInstance processInstance = processRuntime.start(ProcessPayloadBuilder
                    .start()
                    .withProcessDefinitionKey(processDefinitionKey)
                    .withName(instanceName)
                    //.withVariable("content", instanceVariable)
                    //.withVariable("参数2", "参数2的值")
                    .withBusinessKey("自定义BusinessKey")
                    .build());
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), processInstance.getName()+""+processInstance.getId());
        } catch (Exception e) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "启动流程实例失败", e.toString());
        }
    }

    //挂起流程实例
    @GetMapping(value = "/suspendInstance")
    public AjaxResponse suspendInstance(@RequestParam("instanceID") String instanceID) {

        try {
            if (GlobalConfig.Test) {
                securityUtil.logInAs("bajie");
            }

            ProcessInstance processInstance = processRuntime.suspend(ProcessPayloadBuilder
                    .suspend()
                    .withProcessInstanceId(instanceID)
                    .build()
            );
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), processInstance.getName());
        }
        catch(Exception e)
        {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "挂起流程实例失败", e.toString());
        }
    }


    //激活、重启流程实例
    @GetMapping(value = "/resumeInstance")
    public AjaxResponse resumeInstance(@RequestParam("instanceID") String instanceID) {

        try {
            if (GlobalConfig.Test) {
                securityUtil.logInAs("bajie");
            }

            ProcessInstance processInstance = processRuntime.resume(ProcessPayloadBuilder
                    .resume()
                    .withProcessInstanceId(instanceID)
                    .build()
            );
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), processInstance.getName());
        }
        catch(Exception e)
        {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "激活流程实例失败", e.toString());
        }
    }


    //删除流程实例
    @GetMapping(value = "/deleteInstance")
    public AjaxResponse deleteInstance(@RequestParam("instanceID") String instanceID) {
        try {
            if (GlobalConfig.Test) {
                securityUtil.logInAs("bajie");
            }

            ProcessInstance processInstance = processRuntime.delete(ProcessPayloadBuilder
                    .delete()
                    .withProcessInstanceId(instanceID)
                    .build()
            );
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), processInstance.getName());
        }
        catch(Exception e)
        {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "删除流程实例失败", e.toString());
        }

    }


    //查询流程参数
    @GetMapping(value = "/getVariables")
    public AjaxResponse getVariables(@RequestParam("instanceID") String instanceID) {
        try {
            if (GlobalConfig.Test) {
                securityUtil.logInAs("bajie");
            }
            List<VariableInstance> variableInstance = processRuntime.variables(ProcessPayloadBuilder
                    .variables()
                    .withProcessInstanceId(instanceID)
                    .build());

            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), variableInstance);
        }
        catch(Exception e)
        {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "获取流程参数失败", e.toString());
        }
    }


-----------------------------------------------------------------------------------------------------------
任务处理Task



    //获取我的待办任务
    @GetMapping(value = "/getTasks")
    public AjaxResponse getTasks() {
        try {
            if (GlobalConfig.Test) {
                securityUtil.logInAs("bajie");
            }
            Page<Task> tasks = taskRuntime.tasks(Pageable.of(0, 100));
            List<HashMap<String, Object>> listMap = new ArrayList<HashMap<String, Object>>();
            for (Task tk : tasks.getContent()) {
                HashMap<String, Object> hashMap = new HashMap<>();
                hashMap.put("id", tk.getId());
                hashMap.put("name", tk.getName());
                hashMap.put("status", tk.getStatus());
                hashMap.put("createdDate", tk.getCreatedDate());
                if (tk.getAssignee() == null) {//执行人,null时前台显示未拾取
                    hashMap.put("assignee", "待拾取任务");
                } else {
                    hashMap.put("assignee", tk.getAssignee());//
                }
                ProcessInstance processInstance = processRuntime.processInstance(tk.getProcessInstanceId());
                hashMap.put("instanceName", processInstance.getName());
                listMap.add(hashMap);
            }

            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), listMap);
        } catch (Exception e) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "获取我的待办任务失败", e.toString());
        }
    }

    //完成待办任务
    @GetMapping(value = "/completeTask")
    public AjaxResponse completeTask(@RequestParam("taskID") String taskID) {
        try {
            if (GlobalConfig.Test) {
                securityUtil.logInAs("bajie");
            }

            Task task = taskRuntime.task(taskID);


            if (task.getAssignee() == null) {
                taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(task.getId()).build());
            }
            taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(task.getId())
                    //.withVariable("num", "2")//执行环节设置变量
                    .build());


            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), null);
        } catch (Exception e) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "完成失败", e.toString());
        }
    }


-----------------------------------------------------------------------------------------------------------
查询历史记录


    //用户历史任务
    @GetMapping(value = "/getInstancesByUserName")
    public AjaxResponse InstancesByUser() {//@AuthenticationPrincipal UserInfoBean userInfoBean
        try {
            if (GlobalConfig.Test) {
                securityUtil.logInAs("bajie");
            }
//            else{
//                securityUtil.logInAs(SecurityContextHolder.getContext().getAuthentication().getName());
//            }
            List<HistoricTaskInstance> historicTaskInstances = historyService.createHistoricTaskInstanceQuery()
                    .orderByHistoricTaskInstanceEndTime().asc()
                    .taskAssignee(SecurityContextHolder.getContext().getAuthentication().getName())//userInfoBean.getUsername()//"bajie"
                    .list();

            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), historicTaskInstances);
        } catch (Exception e) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "获取用户历史任务失败", e.toString());
        }

    }

    //根据流程实例ID查询任务
    @GetMapping(value = "/getInstancesByPiID")
    public AjaxResponse getInstancesByPiID(@RequestParam("piID") String piID) {
        try {
            if (GlobalConfig.Test) {
                securityUtil.logInAs("bajie");
            }
//            else{
//                securityUtil.logInAs(SecurityContextHolder.getContext().getAuthentication().getName());
//            }
            //--------------------------------------------另一种写法-------------------------
            List<HistoricTaskInstance> historicTaskInstances = historyService.createHistoricTaskInstanceQuery()
                    .orderByHistoricTaskInstanceEndTime().asc()
                    .processInstanceId(piID)
                    .list();

            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), historicTaskInstances);
        } catch (Exception e) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "获取历史任务失败", e.toString());
        }

    }


-----------------------------------------------------------------------------------------------------------
任务

//获取我的待办任务

    @GetMapping(value = "/getTasks")
    public AjaxResponse getTasks() {
        try {
            if (GlobalConfig.Test) {
                securityUtil.logInAs("bajie");
            }
//            else{
//                securityUtil.logInAs(SecurityContextHolder.getContext().getAuthentication().getName());
//            }
            Page<Task> tasks = taskRuntime.tasks(Pageable.of(0, 100));
            List<HashMap<String, Object>> listMap = new ArrayList<HashMap<String, Object>>();
            for (Task tk : tasks.getContent()) {
                HashMap<String, Object> hashMap = new HashMap<>();
                hashMap.put("id", tk.getId());
                hashMap.put("name", tk.getName());
                hashMap.put("status", tk.getStatus());
                hashMap.put("createdDate", tk.getCreatedDate());
                if (tk.getAssignee() == null) {//执行人,null时前台显示未拾取
                    hashMap.put("assignee", "待拾取任务");
                } else {
                    hashMap.put("assignee", tk.getAssignee());//
                }
                ProcessInstance processInstance = processRuntime.processInstance(tk.getProcessInstanceId());
                hashMap.put("instanceName", processInstance.getName());
                listMap.add(hashMap);
            }

            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), listMap);
        } catch (Exception e) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "获取我的待办任务失败", e.toString());
        }
    }


    //完成待办任务
    @GetMapping(value = "/completeTask")
    public AjaxResponse completeTask(@RequestParam("taskID") String taskID) {
        try {
            if (GlobalConfig.Test) {
                securityUtil.logInAs("bajie");
            }
//            else{
//                securityUtil.logInAs(SecurityContextHolder.getContext().getAuthentication().getName());
//            }

            Task task = taskRuntime.task(taskID);


            if (task.getAssignee() == null) {
                taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(task.getId()).build());
            }
            taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(task.getId())
                    //.withVariable("num", "2")//执行环节设置变量
                    .build());


            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), null);
        } catch (Exception e) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "完成失败", e.toString());
        }
    }

 

 

<meta charset="utf-8" />

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted on 2025-12-24 20:42  yebinghuai-qq-com  阅读(11)  评论(0)    收藏  举报

导航