項目結構如上圖,
<?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