springboot整合Activiti工作流

前言

初学activiti工作流引擎的时候踩过很多坑,在此进行统一的做个总结。
activiti的依赖中包含springsecurity,需要先进行security的配置(非常重要!!!非常重要!!!非常重要!!!非常重要!!!非常重要!!!非常重要!!!非常重要!!!)

activiti-spring-boot-starter依赖

1. 引入activiti依赖

		<dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter</artifactId>
            <version>7.0.0.Beta2</version>
        </dependency>

2. 相关springboot配置

server:
  port: 8088

spring:
  datasource:
    url: jdbc:mysql://192.168.11.4:3306/activiti?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 1234

  # activiti7配置
  activiti:
    # 自动部署验证设置:true-开启(默认)、false-关闭
    check-process-definitions: true
    # 保存历史数据
    history-level: full
    # 检测历史表是否存在
    db-history-used: true
    # 关闭SpringAutoDeployment
    deployment-mode: never-fail
    # 对数据库中所有表进行更新操作,如果表不存在,则自动创建
    database-schema-update: true
    # 解决频繁查询SQL问题
    async-executor-activate: false

!!!!!!!注意
activiti会扫描数据库中act开头的表,如果有则不会初始化创建新表,database-schema-update失效,将数据源配置中的url中增加参数 nullCatalogMeansCurrent=true 即可解决 !!!!!!!!!!!!

3. 配置SpringSecurity相关

这里简单的配置一下几个用户放到内存中,正常情况下应该是一个完善的权限配置。这里就不多赘述,有兴趣的话可以去了解SpringSecurtiy的校验流程。

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;

@Configuration
@EnableWebSecurity
public class DemoApplicationConfiguration extends WebSecurityConfigurerAdapter {

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

工具类,用来模拟登录权限认证,主要是将isAuthenticated属性设置为true获取权限。此处不在过多赘述,详情请自行翻阅SpringSecurity的认证流程。

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

4. 创建流程图文件

流程图目录结构
默认路径为resources下的processes,可在springboot配置文件中自行更改。
绘制bpmn流程图需要idea安装插件actiBPM,高版本的idea已经搜不到这个插件,可以去https://plugins.jetbrains.com/ 下载,然后本地安装即可。

actiBpm插件

重启idea,在processes下新建Bqmn文件
新建流程图
双击打开这个文件
插件布局
可以看到插件有三个部分,第一个部分就是流程图,第二个部分就是流程图中使用的结点图标,第三部分就是流程图及结点的定义信息。
!!!!!注意,如果打开后缺少第三部分 bpmn editor,重新设置idea主题即可,目前原因未知。
设置idea主题为高亮
关闭bqmn文件,再次打开bqmn文件,即可看到第三部分 bpmn editor。
!!!!!!注意,如果出现第一部分流程图结点的名称设置成中文之后,关闭bqmn文件之后重新打开乱码这种情况,请设置文件编码为UTF-8。
-Dfile.encoding=utf-8
设置文件编码为UTF-8
设置文件编码为UTF-8

5. 启动springboot

启动springboot,会发现在第二步配置的数据源中的activiti数据库中已经新增了一批表完成初始化,并且插入了一条流程
activiti数据库
test1流程
请假流程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值