zoukankan      html  css  js  c++  java
  • Activiti7新特性和整合开发

    1 Activiti和Spring整合开发

    1.1 Activiti和Spring整合的配置

    • 导入相关jar包的Maven坐标:
    <properties>
        <activiti.version>7.0.0.GA</activiti.version>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-engine</artifactId>
            <version>7.0.0.GA</version>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.1.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-model</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-converter</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-json-converter</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-layout</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <dependency>
            <groupId>org.activiti.cloud</groupId>
            <artifactId>activiti-cloud-services-api</artifactId>
            <version>7-201802-EA</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.19</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <!-- log start -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.13.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.13.3</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.30</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.13.3</version>
        </dependency>
        <!-- log end -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>
    </dependencies>
    
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.activiti.cloud.dependencies</groupId>
                <artifactId>activiti-cloud-dependencies</artifactId>
                <version>7.0.0.GA</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>
        </dependencies>
    </dependencyManagement>
    
    • 创建Spring和Activiti的整合配置文件activiti-spring.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns="http://www.springframework.org/schema/beans"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
    
        <!--  配置数据源 -->
        <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
            <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
            <property name="username" value="root"/>
            <property name="url"
                      value="jdbc:mysql://192.168.1.146:3306/activiti?useUnicode=true&amp;characterEncoding=UTF-8&amp;autoReconnect=true&amp;useSSL=false&amp;serverTimezone=GMT%2B8&amp;allowPublicKeyRetrieval=true"/>
            <property name="password" value="123456"/>
            <property name="maxActive" value="3"/>
            <property name="maxIdle" value="1"/>
        </bean>
    
        <!-- 配置事务管理器 -->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"/>
        </bean>
    
        <!-- 工作流引擎配置Bean -->
        <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
            <!-- 数据源 -->
            <property name="dataSource" ref="dataSource"/>
            <!-- 使用Spring的事务管理器 -->
            <property name="transactionManager" ref="transactionManager"/>
            <!-- 数据库的策略 -->
            <property name="databaseSchemaUpdate" value="true"/>
        </bean>
    
        <!-- 流程引擎 -->
        <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
            <property name="processEngineConfiguration" ref="processEngineConfiguration"/>
        </bean>
        <!-- 资源服务service -->
        <bean id="repositoryService" factory-bean="processEngine"
              factory-method="getRepositoryService"/>
        <!-- 流程运行service -->
        <bean id="runtimeService" factory-bean="processEngine"
              factory-method="getRuntimeService"/>
        <!-- 任务管理service -->
        <bean id="taskService" factory-bean="processEngine"
              factory-method="getTaskService"/>
        <!-- 历史管理service -->
        <bean id="historyService" factory-bean="processEngine"
              factory-method="getHistoryService"/>
    
    </beans>
    
    • 创建日志文件log4j2.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
    <!--Configuration后面的status用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,可以看到log4j2内部各种详细输出-->
    <configuration status="INFO">
        <!--先定义所有的appender-->
        <appenders>
            <!--输出日志信息到控制台-->
            <console name="Console" target="SYSTEM_OUT">
                <!--控制日志输出的格式-->
                <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
            </console>
        </appenders>
        <!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
        <!--root:用于指定项目的根日志,如果没有单独指定Logger,则会使用root作为默认的日志输出-->
        <loggers>
            <root level="INFO">
                <appender-ref ref="Console"/>
            </root>
        </loggers>
    </configuration>
    

    1.2 测试Activiti和Spring的整合

    • 测试:
    package com.sunxiaping.test;
    
    import org.activiti.engine.RepositoryService;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    /**
     * @author <a href="mailto:1900919313@qq.com">weiwei.xu</a>
     * @version 1.0
     * 2020-08-12 09:23
     */
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations={"classpath:activiti-spring.xml"})
    public class Activiti7Test {
    
        @Autowired
        private RepositoryService repositoryService;
    
        @Test
        public void test(){
            System.out.println("repositoryService = " + repositoryService);
        }
    }
    

    2 Activiti7和SpringBoot的整合开发

    2.1 概述

    • Activiti7发布正式版以后,它可以和SpringBoot2.x完全整合。我们可以将Activiti7和SpringBoot整合开发的坐标引入到工程中,从而达到SpringBoot支持Activiti7。
    • SpringBoot整合Activiti7的具体步骤如下:
      • 1️⃣添加SpringBoot整合Activiti7的jar包的坐标。
      • 2️⃣添加SpringSecurity安全框架的整合配置信息。
      • 3️⃣使用Activiti7新支持的接口(ProcessRuntime接口和TaskRuntime接口)来实现工作流开发。
      • 4️⃣使用新的API实现工作流的开发,主要包括:流程定义查询,启动流程实例,任务的查询,任务的完成。

    2.2 Activiti和SpringBoot整合的配置

    • 导入相关jar包的坐标:
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.9.RELEASE</version>
        <relativePath/>
    </parent>
    
    <dependencies>
        <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.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter</artifactId>
            <version>7.0.0.GA</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.3</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.2.9.RELEASE</version>
            </plugin>
        </plugins>
    </build>
    
    • application.yml
    spring:
      datasource:
        url: jdbc:mysql://192.168.134.100:3306/activiti?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
        username : root
        password : 123456
        driver-class-name: com.mysql.cj.jdbc.Driver
      activiti:
        database-schema-update: true
        db-history-used: true
        history-level: full
        check-process-definitions: false
        async-executor-activate: true
    
    • 流程定义文件team01.bpmn

    team01.bpmn

    • SpringSecurity的配置
    /*
     * Copyright 2018 Alfresco, Inc. and/or its affiliates.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *       http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package com.sunxiaping.activiti7.config;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.core.authority.SimpleGrantedAuthority;
    import org.springframework.security.core.userdetails.User;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    import org.springframework.security.crypto.password.PasswordEncoder;
    import org.springframework.security.provisioning.InMemoryUserDetailsManager;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.stream.Collectors;
    
    /**
     * SpringSecurity的配置类
     */
    @Configuration
    @EnableWebSecurity
    public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
    
        private Logger logger = LoggerFactory.getLogger(SpringSecurityConfig.class);
    
        @Override
        public void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
        }
    
        @Bean
        public UserDetailsService userDetailsService() {
    
            InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
    
            String[][] usersGroupsAndRoles = {
                    {"salaboy", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
                    {"ryandawsonuk", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
                    {"erdemedeiros", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
                    {"other", "password", "ROLE_ACTIVITI_USER", "GROUP_otherTeam"},
                    {"admin", "password", "ROLE_ACTIVITI_ADMIN"},
            };
    
            for (String[] user : usersGroupsAndRoles) {
                List<String> authoritiesStrings = Arrays.asList(Arrays.copyOfRange(user, 2, user.length));
                logger.info("> Registering new user: " + user[0] + " with the following Authorities[" + authoritiesStrings + "]");
                inMemoryUserDetailsManager.createUser(new User(user[0], passwordEncoder().encode(user[1]),
                        authoritiesStrings.stream().map(s -> new SimpleGrantedAuthority(s)).collect(Collectors.toList())));
            }
    
            return inMemoryUserDetailsManager;
        }
    
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable()
                    .authorizeRequests()
                    .anyRequest()
                    .authenticated()
                    .and()
                    .httpBasic();
        }
    
        @Bean
        public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }
    }
    
    • UserService.java
    package com.sunxiaping.activiti7.service;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    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 UserService {
    
        @Qualifier("userDetailsService")
        @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");
            }
    
            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);
        }
    }
    
    • SpringBoot的启动类:
    package com.sunxiaping.activiti7;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class Activiti7SpringBootApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(Activiti7SpringBootApplication.class, args);
        }
    }
    

    2.3 测试Activiti和SpringBoot的整合

    • 测试:
    package com.sunxiaping.activiti7;
    
    import com.sunxiaping.activiti7.service.UserService;
    import org.activiti.api.process.model.ProcessDefinition;
    import org.activiti.api.process.model.ProcessInstance;
    import org.activiti.api.process.model.builders.ProcessPayloadBuilder;
    import org.activiti.api.process.runtime.ProcessRuntime;
    import org.activiti.api.runtime.shared.query.Page;
    import org.activiti.api.runtime.shared.query.Pageable;
    import org.activiti.api.task.model.Task;
    import org.activiti.api.task.model.builders.TaskPayloadBuilder;
    import org.activiti.api.task.runtime.TaskRuntime;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    
    import java.util.List;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = Activiti7SpringBootApplication.class)
    public class Activiti7Test {
    
        /**
         * 流程定义相关操作
         */
        @Autowired
        private ProcessRuntime processRuntime;
    
        /**
         * 任务相关操作
         */
        @Autowired
        private TaskRuntime taskRuntime;
    
        @Autowired
        private UserService userService;
    
    
        /**
         * 查看流程定义
         */
        @Test
        public void testQueryProcessDefinition() {
    
            userService.logInAs("salaboy");
    
            //分页查询流程定义信息
            Page<ProcessDefinition> page = processRuntime.processDefinitions(Pageable.of(0, 10));
            int totalItems = page.getTotalItems();
            System.out.println("查看部署流程的个数 = " + totalItems);
    
            List<ProcessDefinition> content = page.getContent();
            for (ProcessDefinition processDefinition : content) {
                String id = processDefinition.getId();
                System.out.println("当前部署的流程定义的id = " + id);
            }
        }
    
        /**
         * 启动流程实例
         */
        @Test
        public void testStartProcessInstance() {
            userService.logInAs("salaboy");
            ProcessInstance processInstance = processRuntime.start(ProcessPayloadBuilder.start().withProcessDefinitionKey("team01").build());
            System.out.println("流程实例的id = " + processInstance.getId());
        }
    
        /**
         * 任务分页查询
         */
        @Test
        public void testQueryTask() {
            userService.logInAs("salaboy");
    
            Page<Task> page = taskRuntime.tasks(Pageable.of(0, 10));
    
            int totalItems = page.getTotalItems();
            System.out.println("任务的总数 = " + totalItems);
            for (Task task : page.getContent()) {
                String id = task.getId();
                System.out.println("任务的id = " + id);
                String name = task.getName();
                System.out.println("任务名称 = " + name);
            }
        }
    
        /**
         * 测试查询任务并完成任务
         */
        @Test
        public void testQueryTaskAndCompleteTask(){
            userService.logInAs("salaboy");
    
            Page<Task> page = taskRuntime.tasks(Pageable.of(0, 10));
    
            int totalItems = page.getTotalItems();
            System.out.println("任务的总数 = " + totalItems);
            for (Task task : page.getContent()) {
                String id = task.getId();
                System.out.println("任务的id = " + id);
                String name = task.getName();
                System.out.println("任务名称 = " + name);
    
                //拾取任务
                taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(id).build());
    
                //完成任务
                taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(id).build());
    
            }
        }
    }
    
  • 相关阅读:
    FastCgi与PHP-fpm之间是个什么样的关系
    MySql的like语句中的通配符:百分号、下划线和escape
    mysql将int 时间类型格式化
    navicat 结合快捷键
    MySQL中concat函数
    case when then else end 用法
    PhpStorm主题
    Having与Where的区别
    无需图形界面环境下的浏览器
    Socket常见错误
  • 原文地址:https://www.cnblogs.com/xuweiweiwoaini/p/13660412.html
Copyright © 2011-2022 走看看