Activiti7+SpringBoot2.1.4+Jpa+Mysql---环境搭建

1. 准备环境

IDEA+MySql
pom文件

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.yb</groupId>
    <artifactId>Study_Activiti7_Jpa</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!--1 确定spring boot的版本-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
    </parent>
    <dependencies>
        <!--test测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>

        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.20</version>
        </dependency>
        <!--web起步依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--MySQL数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <!--jpa-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <version>2.1.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>persistence-api</artifactId>
            <version>1.0</version>
        </dependency>
        <!--activiti7-->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter</artifactId>
            <version>7.0.0.Beta4</version>
        </dependency>
    </dependencies>
</project>

2. yml

#端口号
server:
  port: 9090
#服务名和数据源(连接池)
spring:
  application:
    name: activitiservice
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/activiti7_db?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&nullCatalogMeansCurrent=true
    username: root
    password: 1234
  jpa:
    show-sql: true
  activiti:
    database-schema-update: true
    check-process-definitions: false
    history-level: audit
    #开启历史库
    db-history-used: true

yml参数说明:

databaseSchemaUpdate配置项可以设置流程引擎启动和关闭时数据库执行的策略。 databaseSchemaUpdate有以下四个值:

 1. false:false为默认值,设置为该值后,Activiti在启动时,会对比数据库表中保存的版本,如果没有表或者版本不匹配时,将在启动时抛出异常。
 2. true:设置为该值后,Activiti会对数据库中所有的表进行更新,如果表不存在,则Activiti会自动创建。
 3. create-drop:Activiti启动时,会执行数据库表的创建操作,在Activiti关闭时,执行数据库表的删除操作。
 4. drop-create:Activiti启动时,执行数据库表的删除操作在Activiti关闭时,会执行数据库表的创建操作。

history-level对于历史数据,保存到何种粒度,Activiti提供了history-level属性对其进行配置。history-level属性有点像log4j的日志输出级别,该属性有以下四个值:

 1. none:不保存任何的历史数据,因此,在流程执行过程中,这是最高效的。
 2. activity:级别高于none,保存流程实例与流程行为,其他数据不保存。
 3. audit:除activity级别会保存的数据外,还会保存全部的流程任务及其属性。audit为history的默认值。
 4. full:保存历史数据的最高级别,除了会保存audit级别的数据外,还会保存其他全部流程相关的细节数据,包括一些流程参数等。

db-history-used为true表示使用历史表,如果不配置,则工程启动后可以检查数据库,只建立了17张表,历史表没有建立,则流程图及运行节点无法展示。

3. 初始项目结构

在这里插入图片描述

4. SecurityUtil类

添加 SecurityUtil 类。
为了能够快速实现 SpringSecurity 安全框架的配置,所添加的一个组件。

package com.yb.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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 javax.annotation.Resource;
import java.util.Collection;

/**
 * @author [email protected]
 * @version 1.0
 * @date 2020/8/21
 */
@Component
public class SecurityUtil {
    
    

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


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

5. DemoApplicationConfig 类

在 Activiti7 官方下载的 Example 中找到 DemoApplicationConfig 类,它的作用是为了实现
SpringSecurity 框架的用户权限的配置,这样我们就可以在系统中使用用户权限信息。本次项目中基
本是在文件中定义出来的用户信息,当然也可以是数据库中查询的用户权限信息。

package com.yb.config;

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;

/**
 * @author [email protected]
 * @version 1.0
 * @date 2020/8/21
 */
@Configuration
@EnableWebSecurity
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();

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

说明:上面所有的配置完毕,直接运行项目即可在数据库创建25张表,无需网上其他人说的那种需要配置创建数据库的脚本
数据库:
在这里插入图片描述

6. 测试

流程图:
在这里插入图片描述
Bpmn文件

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1597976389680" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema">
  <process id="test" isClosed="false" isExecutable="true" processType="None">
    <startEvent id="_2" name="开始"/>
    <userTask activiti:assignee="user1" activiti:exclusive="true" id="_3" name="项目经理审批"/>
    <userTask activiti:assignee="user2" activiti:exclusive="true" id="_4" name="总经理审批"/>
    <endEvent id="_5" name="结束"/>
    <sequenceFlow id="_6" sourceRef="_2" targetRef="_3"/>
    <sequenceFlow id="_7" sourceRef="_3" targetRef="_4"/>
    <sequenceFlow id="_8" sourceRef="_4" targetRef="_5"/>
  </process>
  <bpmndi:BPMNDiagram documentation="background=#000000;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram">
    <bpmndi:BPMNPlane bpmnElement="test">
      <bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2">
        <omgdc:Bounds height="32.0" width="32.0" x="215.0" y="40.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3">
        <omgdc:Bounds height="55.0" width="85.0" x="190.0" y="150.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4">
        <omgdc:Bounds height="55.0" width="85.0" x="190.0" y="265.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5">
        <omgdc:Bounds height="32.0" width="32.0" x="215.0" y="395.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="_6" id="BPMNEdge__6" sourceElement="_2" targetElement="_3">
        <omgdi:waypoint x="231.0" y="72.0"/>
        <omgdi:waypoint x="231.0" y="150.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_7" id="BPMNEdge__7" sourceElement="_3" targetElement="_4">
        <omgdi:waypoint x="232.5" y="205.0"/>
        <omgdi:waypoint x="232.5" y="265.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_8" id="BPMNEdge__8" sourceElement="_4" targetElement="_5">
        <omgdi:waypoint x="231.0" y="320.0"/>
        <omgdi:waypoint x="231.0" y="395.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

测试类

package com.yb;

import com.yb.config.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.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;

/**
 * @author [email protected]
 * @version 1.0
 * @date 2020/8/21
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class TextActiviti {
    
    

    @Resource
    private ProcessRuntime processRuntime;
    @Resource
    private TaskRuntime taskRuntime;
    @Resource
    private RepositoryService repositoryService;
    @Resource
    private SecurityUtil securityUtil;
    @Resource
    private RuntimeService runtimeService;
    @Resource
    private TaskService taskService;
    /**
     * 查询流程定义
     */
    @Test
    public void testQueryProcessDefinition() {
    
    
        securityUtil.logInAs("salaboy");
        Page<ProcessDefinition> pfp = processRuntime.processDefinitions(Pageable.of(0, 10));
        System.out.println("可用的流程定义数量:" +pfp.getTotalItems());
        for (ProcessDefinition pd : pfp.getContent()) {
    
    
            System.out.println("流程定义:"+pd);
        }
    }

    /**
     * 部署流程
     */
    @Test
    public void testDeployProcess() {
    
    
        Deployment deploy = repositoryService.createDeployment()
                .addClasspathResource("processes/test.bpmn")
                .addClasspathResource("processes/test.png")
                .name("测试审批-1")
                .deploy();
        System.out.println("流程部署ID:"+deploy.getId());
        System.out.println("流程部署名称:"+deploy.getName());
    }

    /**
     * 启动流程
     */
    @Test
    public void  testStartProcess(){
    
    
        ProcessInstance test = runtimeService.startProcessInstanceByKey("test");
        System.out.println("流程实例id:"+test.getId());
        System.out.println("流程部署id:"+test.getProcessDefinitionId());
    }

    /**
     * 查询及完成任务
     */
    @Test
    public void testTaskProcess(){
    
    
        Task task = taskService.createTaskQuery()
                .taskAssignee("user2")
                .singleResult();
        System.out.println("任务id:"+task.getId());
        System.out.println("任务处理人:"+task.getAssignee());
        System.out.println("流程实例id:"+task.getProcessInstanceId());
        //完成任务
        taskService.complete(task.getId());
    }

}

数据库历史表:
在这里插入图片描述
总结:
到这里,activiti7整合SpringBoot 的环境搭建以及初步的流程测试已经完毕,后续继续更新。

猜你喜欢

转载自blog.csdn.net/Lv_vI/article/details/108143398