项目结构如上图,
<?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.megalith</groupId>
<artifactId>security_simple</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>security_simple</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<pagehelper.version>1.1.0</pagehelper.version>
<mybatis.generator.version>1.3.2</mybatis.generator.version>
<fastjson.version>1.2.31</fastjson.version>
<jackson.version>2.9.7</jackson.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- <exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions> -->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency> -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- aop -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- json处理 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- jackson json begin -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- jackson json end -->
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.uuid</groupId>
<artifactId>java-uuid-generator</artifactId>
<version>3.1.3</version>
</dependency>
<!-- druid datasource -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.27</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
<!--mybatis代码生成器 -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>${mybatis.generator.version}</version>
</dependency>
<!-- bean验证 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- spring boot 开发工具 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<!-- 测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--spring-security-oauth2 begin-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.0.6.RELEASE</version>
</dependency>
<!--spring-security-oauth2 end-->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
ActivitiConfiguration是activiti的配置类
package activitiPro;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import org.activiti.designer.test.test;
import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.ManagementService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.spring.SpringProcessEngineConfiguration;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import com.alibaba.druid.pool.DruidDataSource;
@Configuration
public class ActivitiConfiguration {
private static final Logger log = LogManager.getLogger(ActivitiConfiguration.class);
@Autowired
private TestService testService;
@Bean(name = "activitiDataSource")
@ConfigurationProperties(prefix = "spring.datasource.activiti")
public DataSource activitiDataSource(){
log.info("activitiDataSource 初始化...");
return new DruidDataSource();
}
@Bean
public PlatformTransactionManager txManager() {
return new DataSourceTransactionManager(activitiDataSource());
}
@Bean
public ProcessEngine processEngine() throws IOException {
SpringProcessEngineConfiguration configuration = new SpringProcessEngineConfiguration();
//自动部署已有的流程文件
Resource[] resources = new PathMatchingResourcePatternResolver().getResources(ResourceLoader.CLASSPATH_URL_PREFIX + "diagrams/*.bpmn");
configuration.setTransactionManager(txManager());
configuration.setDataSource(activitiDataSource());
configuration.setDatabaseSchemaUpdate("true");
configuration.setDeploymentResources(resources);
configuration.setDbIdentityUsed(false);
Map<Object, Object>beans=new HashMap<Object, Object>();
beans.put("testService",testService);
configuration.setBeans(beans);
return configuration.buildProcessEngine();
}
@Bean
public RepositoryService repositoryService(ProcessEngine processEngine) {
return processEngine.getRepositoryService();
}
@Bean
public RuntimeService runtimeService(ProcessEngine processEngine) {
return processEngine.getRuntimeService();
}
@Bean
public TaskService taskService(ProcessEngine processEngine) {
return processEngine.getTaskService();
}
@Bean
public HistoryService historyService(ProcessEngine processEngine) {
return processEngine.getHistoryService();
}
@Bean
public ManagementService managementService(ProcessEngine processEngine) {
return processEngine.getManagementService();
}
@Bean
public IdentityService identityService(ProcessEngine processEngine) {
return processEngine.getIdentityService();
}
}
configuration.setBeans(beans); //如果流程设计中需要使用${}或者#{}表达式,就需要把这个bean进行暴露,如果不进行暴露则报未知标识符错误
如果使用spring则在配置文件中设置:
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
...
<property name="beans">
<map>
<entry key="printer" value-ref="printer" />
</map>
</property>
</bean>
<bean id="printer" class="org.activiti.examples.spring.Printer" />
测试中 :
ProcessInstance pi= runtimeService.startProcessInstanceByKey("myProcess"); //标识启动流程,一般前端填写表达时进行调用后端这句话进行启动
同时会在流程表中穿件记录
流程执行过程中是根据流程id查询流程状态和执行流程。
如下:
List<Task> task = taskService.createTaskQuery().processInstanceId(pi.getId()).list(); //查询流程状态
taskService.complete(task.get(0).getId());//执行流程
只有执行了流程,流程才会流转到下一步
List<Task> task1 = taskService.createTaskQuery().processInstanceId(pi.getId()).list();//查询流程状态
System.out.println(task1.get(0).getAssignee());
askService.complete(task1.get(0).getId());//执行流程
以此类推
TaskQuery taskQuery = taskService.createTaskQuery().taskCandidateOrAssigned(userId);//根据人查询自己的任务
流程启动之后会在流程表act_ru_execution存储一条记录,
流程执行之后会修改act_ru_execution表中ACT_ID_字段,对应流程任务id,如下图
同时在流程任务表中存储流程任务信息
如果流程任务有对应的候选人会在对应act_ru_identitylink表中产生候选人任务对应数据
流程执行完之后会清空act_ru_*表中数据,产生历史数据
判断
可以通过
Map<String,Object>pa=new HashMap<String, Object>();
pa.put("type",0);
ProcessInstance pi= runtimeService.startProcessInstanceByKey("myProcess",pa);
进行参数设置,
或者在流程执行时执行
taskService.complete(task.get(0).getId(),pa);
开发中发现使用
(排他网管)进行判断,
红框中的配置和之上一样,代码写法也一样。
事件监听 定义一个类实现TaskListener
public class MyStakLinster implements TaskListener{
@Override
public void notify(DelegateTask delegateTask) {
//通过代理对象可以实现各种设置
delegateTask.setAssignee("kk");
}
}
然后在流程图中配置上这个类,就可以了。
首先是我们已经对Activiti流程的开启有了了解之后,在进行下文
流程中用到最多的就是用户任务了,包括谁办理,什么时候办理,办理结果是什么,办理历史等等
下文先介绍下用户任务的办理相关操作
用户任务分类:
分为4中状态:未签收/待办理、已签收/办理中、运行中/办理中、已完成/已办结
首先,我们要了解下 TaskService 这个服务的作用:
1、查询分配给用户或组的任务
2、创建独立运行任务。这些任务与流程实例无关。
3、手工设置任务的执行者,或者这些用户通过何种方式与任务关联。
4、认领并完成一个任务。认领意味着一个人期望成为任务的执行者, 即这个用户会完成这个任务。完成意味着“做这个任务要求的事情”。 通常来说会有很多种处理形式。
状态:
通过TaskService来获得任务
API简述
从类 org.activiti.engine.impl.ServiceImpl 继承的字段
所有已实现的接口:TaskService
TaskService taskService = processEngine.getTaskService();
//这边我定义了几个通用 变量
//String userId = "Ypp";
//String userGroup = new String["Ypp1","Ypp101"];
1、未签收/待办理
那么流程开启之后,如何能让下一个办理人取得待办任务呢?
通过下面几种的方法,将取得指定签收人/办理人的待办数据
//单人待签收/待办理
List<Task> tasks = taskService.createTaskQuery().taskCandidateUser(userId).list();
//用户组待签收/待办理
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup(userGroup).list();
//进行签收操作,也就是将要接收办理这个任务
//这边可以使用循环,也可以通过其他方法,常用的是先加载一个任务待办列表到页面上,签收任务传递后台一个taskId
//task.getId() = taskId
taskService.claim(task.getId(), userId);//完成签收这个时候就任务Task的Assignee属性就有了值
//已经签收过的任务列表,某种意义上我理解为真正的办理人
List<Task> tasks = taskService.createTaskQuery().taskAssignee(userId).list();
2、办理
通过 1、未签收/待办理 中取得需要办理的任务Task之后
//调用 task.getId() = taskId 完成任务的办理,taskService服务自动流转到下一个办理节点
taskService.complete(task.getId());
//taskService.complete()方法 提供了重载,提供了3种方式供你选择
complete(String taskId)
complete(String taskId, Map<String,Object> variables)
complete(String taskId, Map<String,Object> variables, boolean localScope)
如果更深的了解如何流转的可以查看源码
---------------------------------------------------------------------------
插一下
任务并不一定要先签收再办理,可以直接到待办理中,而不是待签收中
可以把
taskService.claim(task.getId(), userId);方法
替换为
setAssignee(String taskId, String userId)
经过以上步骤,任务已经在 办理中状态了
3、已完成/已办结
任务的已完成(调用过complete方法)是指当前待办的任务状态,而非整个流程实例的完成状态
流程中数据使用到 historyService 服务
//查询指定用户发起的流程 (流程历史 用户发起 )
//finished 完成的流程
//unfinish 还在运行中的流程
List<HistoricActivityInstance> hais = 下面的3中方法
historyService.createHistoricProcessInstanceQuery().finished().startedBy(name).orderByProcessInstanceStartTime().desc().listPage(firstResult, maxResults);
//查询指定用户参与的流程信息 (流程历史 用户参与 )
List hpis = historyService.createHistoricProcessInstanceQuery().involvedUser(name).orderByProcessInstanceStartTime().desc().listPage(firstResult, maxResults);
//查询指定流程的任务流转路径 (流程历史 任务 流转 路经)
historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).orderByHistoricTaskInstanceEndTime().asc().list();
//查看流程是否完整的运行完毕方法也有好几种
for (HistoricActivityInstance hai : hais) {
//如果下面的方法返回不是空,那就是已办结
hai.getEndTime()
}
//查看ACT_RU_TASK表
Long long = taskService.createTaskQuery().processInstanceId("processInstanceId").taskId("taskId").count();
//如果long为空,那么也是办结了
taskService.createTaskQuery()查询条件是可选的
可以是
taskService.createTaskQuery().processInstanceId("processInstanceId")
taskService.createTaskQuery().taskId("taskId")
或者其他更多条件
总结:
//流程在流转中对于当前办理人/组和签收人/组来说,都是可以进行动态调整变化的
//需要对程序进行特殊处理,添加监听或者其他方法
//得到用户组待签收
TaskService taskService = processEngine.getTaskService();
//单人待签收
//List<Task> tasks = taskService.createTaskQuery().taskCandidateUser(userId).list();
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup(userGroup).list();
for (Task task : tasks) {
// 签收
taskService.claim(task.getId(), userId);
}
//得到用户待办
tasks = taskService.createTaskQuery().taskAssignee(userId).list();
for (Task task : tasks) {
//办理
taskService.complete(task.getId());
}
//顺便查看历史看看
HistoryService historyService = processEngine.getHistoryService();
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(procId).singleResult();
可以参考http://www.mossle.com/docs/activiti/index.html#springExpressions