一、什么是工作流?
工作流
(Workflow)
,就是通过计算机对业务流程自动化执行管理。它主要解决的是
“
使在多个参与者
之间按照某种预定义的规则自动进行传递文档、信息或任务的过程,从而实现某个预期的业务目标,或者促使此目标的实现”
。说白了就是流程一个过程。(比如请假流程,报销流程,审批流程等等..)。
Activiti 是一个工作流引擎, activiti 可以将业务系统中复杂的业务流程抽取出来,使用专门的建模语言 (BPMN2.0 )进行定义,业务系统按照预先定义的流程进行执行,实现了业务系统的业务流程由 activiti 进行管理,减少业务系统由于流程变更进行系统升级改造的工作量,从而提高系统的健壮性,同时也减少了系统开发维护成本。
二、 springboot集成使用
1.idea安装插件
2.创建流程图(在resourcs目录下创建一个processes文件夹,把文件和导出的图片放里面)
设置属性
2.1
创建流程图时,要给每个控件设置属性
开始和结束事件设置
id
和
name
(用自带的也行)
流程过程需要指定负责人
Assignee
# 可以使用表达式${ 属性值 } ;因为后面我们可以传一个 map 对象进行,可以直接这样子获取属性定义的值
3.
创建流程图后保存图片
以上准备步骤就做好了,下面开始写代码
总的步骤来说就是分为以下步骤:
- 创建并启动流程实例
- 查询角色任务
- 拾取并完成对应的任务
@Autowired
private TaskRuntime taskRuntime;
@Autowired
private RuntimeService runtimeService;
@Autowired
private ProcessRuntime processRuntime;
//注入定义的工具类
@Autowired
private SecurityUtil securityUtil;
//获取流程定义
@Test
public void test2(){
securityUtil.login("张三");
//这里获取的是失败的,因为它默认使用了安全框架,我们没有配置,所以报错
ProcessDefinition processDefinition =processRuntime.processDefinition("mydemo");
//所以我们还要配置一下安全框架
System.out.println(processDefinition);
}
//启动流程实例,完成操作
@Test
public void test3(){
//以员工的身份进行登录
securityUtil.login("李四");
//模拟用户点击按钮事件,从当前用户创建并启动启动实例
//配置uel表达式中的内容
Map<String,Object> assigneeMap = new HashMap<>();
assigneeMap.put("assignee01","李四");
assigneeMap.put("assignee02","部门经理");
assigneeMap.put("assignee03","总经理");
runtimeService.startProcessInstanceByKey("mydemo",assigneeMap);
}
//查询流程角色的任务
@Test
public void test4(){
//以员工的身份进行登录
securityUtil.login("总经理");
//查询当前用户的任务
Page<Task> tasks = taskRuntime.tasks(Pageable.of(0, 10));
for (Task task:tasks.getContent()) {
System.out.println(task);
}
}
//根据对应角色,输入不同的任务id进行完成任务
@Test
public void test5(){
securityUtil.login("总经理");
String id = "c8279ecf-ad3b-11ef-a0d4-782b46e90895";
//完成任务
taskRuntime.complete(TaskPayloadBuilder
.complete()
.withTaskId(id)
.build());
}
注意的是,
activiti7
内部已经整合了
spring
安全框架,所以使用的时候需要对
SpringSecurity
进行相对于的配置。
因为我的之前写的
SpringSecurity
项目不知为何启动报错了,一时半会没有解决,所以我在这里模仿了网上的案例教学,写了一些固定的配置:
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 login(String userName){
UserDetails userDetails =userDetailsService.loadUserByUsername(userName);
if (userDetails == null){
throw new IllegalStateException("用户:"+userName+"不存在,请重新登录");
}
SecurityContextHolder.setContext(new SecurityContextImpl(
new Authentication() {
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return userDetails.getAuthorities();
}
@Override
public Object getCredentials() {
return userDetails.getPassword();
}
@Override
public Object getDetails() {
return userDetails;
}
@Override
public Object getPrincipal() {
return userDetails;
}
@Override
public boolean isAuthenticated() {
return true;
}
@Override
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
}
@Override
public String getName() {
return userDetails.getUsername();
}
}
));
//调用activiti7自带的方法进行安全认证;
org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(userName
);
}
}
SpringSecurity配置类
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.net.PasswordAuthentication;
import java.util.Arrays;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.stream.Collectors;
@Configuration
public class SecurityConfig {
@Bean
public UserDetailsService myUserDetailsService(){
InMemoryUserDetailsManager inMemoryUserDetailsManager = new
InMemoryUserDetailsManager();
//这里写死,设置用户及密码和权限
String[][] userGroupAndRole = {
{"张三","password","ROLE_ACTIVITI_USER"},
{"李四","password","ROLE_ACTIVITI_USER"},
{"部门经理","password","ROLE_ACTIVITI_USER"},
{"总经理","password","ROLE_ACTIVITI_USER"},
{"财务部","password","ROLE_ACTIVITI_USER"},
};
for (String[] users:userGroupAndRole) {
//用户的角色
List<String>authStrList=Arrays.asList(Arrays.copyOfRange(users,2,users.length));
inMemoryUserDetailsManager.createUser(new User(users[0],passwordEncoder().encode(users[1]),zhuuanghan(authStrList)));
}
return inMemoryUserDetailsManager;
}
//写一个密码加密的方法
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
//定义一个方法,将authStrList转圜为另外一个集合对象
public List<SimpleGrantedAuthority> zhuuanghan(List<String> authStrList){
return authStrList.stream().map(str->new
SimpleGrantedAuthority(str)).collect(Collectors.toList());
}
}