一:项目结构

spring boot activiti7 spring boot activiti7 项目代码_spring


二:application.yml配置

server:
  port: 9999
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/springboot_activiti?useUnicode=true&characterEncoding=UTF-8&nullCatalogMeansCurrent=true&useOldAliasMetadataBehavior=true&autoReconnect=true&serverTimezone=UTC
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
  activiti:
    #1.flase: 默认值。activiti在启动时,会对比数据库表中保存的版本,如果没有表或者版本不匹配,将抛出异常
    #2.true: activiti会对数据库中所有表进行更新操作。如果表不存在,则自动创建
    #3.create_drop: 在activiti启动时创建表,在关闭时删除表(必须手动关闭引擎,才能删除表)
    #4.drop-create: 在activiti启动时删除原来的旧表,然后在创建新表(不需要手动关闭引擎)
    database-schema-update: true
    #检测历史表是否存在 activiti7默认没有开启数据库历史记录 启动数据库历史记录
    db-history-used: true
    #记录历史等级 可配置的历史级别有none, activity, audit, full
    history-level: full
    #校验流程文件,默认校验resources下的processes文件夹里的流程文件
    check-process-definitions: true

三:pom文件中的依赖引入

</dependency>
<!--        工作流activiti相关依赖-->
                <dependency>
                    <groupId>org.activiti</groupId>
                    <artifactId>activiti-spring-boot-starter</artifactId>
                    <version>7.0.0.Beta2</version>
        <!--            <version>7.1.0.M1</version>-->
                    <exclusions>
                        <exclusion>
                            <artifactId>mybatis</artifactId>
                            <groupId>org.mybatis</groupId>
                        </exclusion>
                    </exclusions>
                </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter-basic</artifactId>
            <version>6.0.0</version>
        </dependency>

四:流程管理文件配置
bpmn文件默认放在resource下的processes文件夹下,项目启动时,会自动部署此文件夹下的所有bpmn文件,即部署流程

五:利用工具Camunda Modeler生成bpmn文件

1)下载Camunda Modeler,下载地址https://camunda.com/download/modeler/

lz下载的是camunda-modeler-4.6.0-win-x64

spring boot activiti7 spring boot activiti7 项目代码_spring_02


2)IDEA整合Camunda Modeler

spring boot activiti7 spring boot activiti7 项目代码_ide_03


参考文档:https://www.jianshu.com/p/5942c4ee513c

3)利用Camunda Modeler画流程图,并生成bpmn文件流程图总览:

spring boot activiti7 spring boot activiti7 项目代码_java_04

流程组件详解:

任务组件:

spring boot activiti7 spring boot activiti7 项目代码_spring_05


网关组件:

spring boot activiti7 spring boot activiti7 项目代码_ide_06


开始组件:

spring boot activiti7 spring boot activiti7 项目代码_activiti_07


结束组件:

spring boot activiti7 spring boot activiti7 项目代码_spring_08


设置流程主体信息:

spring boot activiti7 spring boot activiti7 项目代码_spring_09


设置任务详请

spring boot activiti7 spring boot activiti7 项目代码_spring_10


设置流程变量

流程变量即流程控制条件,引导流程的走向

spring boot activiti7 spring boot activiti7 项目代码_activiti_11


保存文件,并复制到IDEA中的processes文件夹下

spring boot activiti7 spring boot activiti7 项目代码_java_12


修改bpmn文件中的属性,使其在IDEA中能够正确部署

1、将camunda全部替换为activiti

spring boot activiti7 spring boot activiti7 项目代码_activiti_13


2、如果没有xmlns:activiti="http://activiti.org/bpmn"则新增,如果报红,则alt+enter,选择ignore(注:xmlns:activiti="http://activiti.org/bpmn"配置必须和这个一样,其他的xmlns:activiti配置需要覆盖掉)3、流程变量的设置:需满足El表达式的语法

spring boot activiti7 spring boot activiti7 项目代码_ide_14


ex: <![CDATA[${evection.num < 3}]]>4、设置listener

spring boot activiti7 spring boot activiti7 项目代码_ide_15

import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.ExecutionListener;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class MyExecutionListener implements ExecutionListener {

    @Override
    public void notify(DelegateExecution delegateExecution) {
        log.info("delegateExecution is {}",delegateExecution);
    }
}

4、bpmn文件中executionListener的class属性不能为空,设置listener

spring boot activiti7 spring boot activiti7 项目代码_java_16

配置SpringSecurity权限

由于activiti7内嵌了SpringSecurity,作为权限管理,所以需要配置权限信息

1、配置Security的工具类,用于验证权限

spring boot activiti7 spring boot activiti7 项目代码_ide_17

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 {

    @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);
    }
}

2、配置权限用户

spring boot activiti7 spring boot activiti7 项目代码_java_18

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
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 //配置的是SpringSecurity的权限信息
public class DemoApplicationConfiguration extends WebSecurityConfigurerAdapter {

    private Logger logger = LoggerFactory.getLogger(DemoApplicationConfiguration.class);

    @Override
    @Autowired
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(myUserDetailsService());
    }

    @Bean
    public UserDetailsService myUserDetailsService() {

        InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
        //todo 由于本项目为demo,这里的用户信息临时添加,正式项目,这里需要从数据库中查询处用户
        String[][] usersGroupsAndRoles = {
                //用户名,密码,角色(前缀带ROLE),组信息(前缀带GROUP)
                {"salaboy", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
                {"jack", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
                {"jerry", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
                {"tom", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
                {"rose", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
                {"miki", "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();
    }
}

3、取消SpringSecurity的自动配置

spring boot activiti7 spring boot activiti7 项目代码_ide_19

启动SpringBoot项目,完成流程自动部署

spring boot activiti7 spring boot activiti7 项目代码_java_20

验证流程部署是否完成

1、新建测试类

spring boot activiti7 spring boot activiti7 项目代码_spring_21

import com.activiti.demo.utils.SecurityUtil;
import org.activiti.api.process.model.ProcessDefinition;
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.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
public class ActivitiTest {

    @Autowired
    private ProcessRuntime processRuntime;
    @Autowired
    private TaskRuntime taskRuntime;
    @Autowired
    private SecurityUtil securityUtil;

    //流程定义的查看
    @Test
    public void testDefinition() {

        securityUtil.logInAs("tom");
        Page<ProcessDefinition> processDefinitionPage = processRuntime.processDefinitions(Pageable.of(0, 10));
        int totalItems = processDefinitionPage.getTotalItems();
        System.out.println("可用的流程定义数量:" + totalItems);
        List<ProcessDefinition> content = processDefinitionPage.getContent();
        if (content != null && content.size() > 0) {
            for (ProcessDefinition processDefinition : content) {
                System.out.println("流程定义:" + processDefinition);
            }
        }
    }

}

2、查看控制台

spring boot activiti7 spring boot activiti7 项目代码_spring_22