Activiti 學習記錄

說明:畫圖插件用的是eclipse的插件,地址:Location:http://activiti.org/designer/update/   

Name:Activiti

工作流配置:

Pom.xml

<!--流程審批-->
<dependency>
   <groupId>org.activiti</groupId>
   <artifactId>activiti-engine</artifactId>
   <version>5.21.0</version>
</dependency>
<dependency>
   <groupId>org.activiti</groupId>
   <artifactId>activiti-spring</artifactId>
   <version>5.21.0</version>
</dependency>

Datasource.xml 數據庫設計

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="
     http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
   <!-- 數據源 -->

   <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
      <!-- 基本屬性 url、user、password -->
      <property name="driverClassName" value="com.mysql.jdbc.Driver" />
      <property name="url" value="jdbc:mysql://127.0.0.1:3306/approval?useUnicode=true&characterEncoding=utf-8" />
      <property name="username" value="root" />
      <property name="password" value="mysql" />
      <!-- 配置初始化大小、最小、最大 -->
      <property name="initialSize" value="1" />
      <property name="minIdle" value="1" />
      <property name="maxActive" value="20" />
      <!-- 配置獲取連接等待超時的時間 -->
      <property name="maxWait" value="60000" />
      <!-- 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連接,單位是毫秒 -->
      <property name="timeBetweenEvictionRunsMillis" value="60000" />
      <!-- 配置一個連接在池中最小生存的時間,單位是毫秒 -->
      <property name="minEvictableIdleTimeMillis" value="300000" />
      <property name="validationQuery" value="SELECT 'x'" />
      <property name="testWhileIdle" value="true" />
      <property name="testOnBorrow" value="false" />
      <property name="testOnReturn" value="false" />
      <!-- 打開PSCache,並且指定每個連接上PSCache的大小 -->
      <property name="poolPreparedStatements" value="false" />
      <property name="maxPoolPreparedStatementPerConnectionSize" value="20" />
      <!-- 配置監控統計攔截的filters -->
      <property name="filters" value="stat" />
   </bean>
   <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      <property name="dataSource" ref="druidDataSource" />
   </bean>
   <!--工作流引擎配置 -->
   <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
      <property name="dataSource" ref="druidDataSource" />
      <property name="transactionManager" ref="transactionManager" />
      <property name="databaseSchemaUpdate" value="true" />
      <property name="jobExecutorActivate" value="false" />
      <property name="history" value="full" />
   </bean>
   <!--工作流引擎 -->
   <bean id="processEngineFactory" class="org.activiti.spring.ProcessEngineFactoryBean">
      <property name="processEngineConfiguration" ref="processEngineConfiguration" />
   </bean>
   <!--擴展服務 -->
   <!--<bean id="processDefinitionService" factory-bean="processEngine" factory-method="getProcessDefinitionService" />
   <bean id="processLogService" factory-bean="processEngine" factory-method="getProcessLogService" />
   <bean id="processManagementService" factory-bean="processEngine" factory-method="getProcessManagementService" />-->
   <!--原生服務 -->
   <!--<bean id="processEngine" factory-bean="processEngineFactory" factory-method="getObject" />-->
   <bean id="repositoryService" factory-bean="processEngineFactory" factory-method="getRepositoryService" />
   <bean id="runtimeService" factory-bean="processEngineFactory" factory-method="getRuntimeService" />
   <bean id="taskService" factory-bean="processEngineFactory" factory-method="getTaskService" />
   <bean id="historyService" factory-bean="processEngineFactory" factory-method="getHistoryService" />
   <bean id="managementService" factory-bean="processEngineFactory" factory-method="getManagementService" />
   <bean id="formService" factory-bean="processEngineFactory" factory-method="getFormService" />
   <bean id="identityService" factory-bean="processEngineFactory" factory-method="getIdentityService" />
   <!--設置默認的資源類型-->
   <!--<bean id="contentTypeResolver" class="org.activiti.rest.common.application.DefaultContentTypeResolver" />-->
</beans>

注意:以下使用的service前提是需要注入:

 

@Autowired
ProcessEngine processEngine;
@Autowired
RepositoryService repositoryService;
@Autowired
RuntimeService runtimeService;
@Autowired
TaskService taskService;
@Autowired
IdentityService identityService;
@Autowired
HistoryService historyService;

網關:網關分爲排他網關與並行網關。

排他網關:進入某一個流程分之,可設置默認分之;並行網關:同時進入多個流程分之;


圖上爲排他網關,進入哪個分之是根據條件判斷。

 

條件寫法${判斷條件}其中圖上activition爲自定義名稱 ,此名稱需要和map中的key對應(後面會寫),審批時只會走下面的其中一個流程,如果決策都沒有返回true,則會拋出異常,如果第一個返回true,則直接走進第一個流程分之;

 

 

圖上爲並行網關:

1).一個流程中流程實例只有1個,執行對象有多個

2).並行網關的功能是基於進入和外出的順序流的:

分支(fork): 並行後的所有外出順序流,爲每個順序流都創建一個併發分支。

匯聚(join): 所有到達並行網關,在此等待的進入分支, 直到所有進入順序流的分支都到達以後, 流程就會通過匯聚網關。

3).並行網關的進入和外出都是使用相同節點標識

4).如果同一個並行網關有多個進入和多個外出順序流, 它就同時具有分支和匯聚功能。 這時,網關會先匯聚所有進入的順序流,然後再切分成多個並行分支。

5).並行網關不會解析條件。 即使順序流中定義了條件,也會被忽略。

6).並行網關不需要是“平衡的”(比如, 對應並行網關的進入和外出節點數目不一定相等)。

審批人的設定:

 

 

首先我們可以設置Assignee,這個設置只能是一個人,不能是多個;也可以寫成變量的形式${user1} 等等;

Map<String , Object> map = new HashMap<String, Object>();
map.put("users1", “1”);

 

 

還可以設置candidate user 中間用隔開,這個可以設置多個人;也可以用變量的形式${users1} 方式:

Map<String , Object> map = new HashMap<String, Object>();
String[] strs = {"1","2"};
map.put("users1", Arrays.asList(strs)); 直接用list添加

此種方式需要有認領的概念,即雖然在任務中能看到此條數據,但是不能進行審批;因爲他的Assignee爲空;

 

查看這個方式的可以審批的人物:

taskService.getIdentityLinksForTask("任務id");



還可以使用監聽類的方式:

類的寫法

public class TaskListenerTest implements TaskListener{
private static final long serialVersionUID = 1L;
/**
 * 可以設置任務的辦理人(個人組人和組任務)
 */
@Override
public void notify(DelegateTask task) {
// TODO Auto-generated method stub
//直接添加一個用戶
        task.addCandidateUser("12345678");
        task.addCandidateUser("87654321");
 
        //添加一個用戶集合
        List<String> list = new ArrayList<String>();
        list.add("1");
        list.add("2");
        list.add("3");
        task.addCandidateUsers(list);
}
}

 

此種方式和以上的用candidateuser 的方式一樣;

還有一種方式,用組的方式:

 

以下是設置組的方式

 

以上的group就相當於下面的經理, 此方法沒有測試過,需要使用人員進行測試;

 

 

具體的方法:

bpmn文件部署上去 部署流程有幾種方式 。

//第一中方式,classpass方式
Deployment deployment=repositoryService
        .createDeployment()
        .addClasspathResource("hbyt_tenant.bpmn")
        .addClasspathResource("hbyt_tenant.png")
        .name("部署流程")
        .deploy();
System.out.println(deployment);
 
 
//Inputstream方式 
@Test
public void deployementProcessDefinitionByInputStream() throws FileNotFoundException {
    //獲取資源相對路徑  
    String bpmnPath = "diagrams/helloworld.bpmn";
    String pngPath = "diagrams/helloworld.png";
    //讀取資源作爲一個輸入流  
    FileInputStream bpmnfileInputStream = new FileInputStream(bpmnPath);
    FileInputStream pngfileInputStream = new FileInputStream(pngPath);
    Deployment deployment = processEngine.getRepositoryService()//獲取流程定義和部署對象相關的Service  
            .createDeployment()//創建部署對象  
            .addInputStream("helloworld.bpmn",bpmnfileInputStream)
            .addInputStream("helloworld.png", pngfileInputStream)
            .deploy();//完成部署  
    System.out.println("部署ID:"+deployment.getId());//1  
    System.out.println("部署時間:"+deployment.getDeploymentTime());
}
 
//字符串方式
@Test
public void deployementProcessDefinitionByString() throws FileNotFoundException{
    //字符串
    String text = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><definitions>...</definitions>";

    Deployment deployment = processEngine.getRepositoryService()//獲取流程定義和部署對象相關的Service
            .createDeployment()//創建部署對象
            .addString("helloworld.bpmn",text)
            .deploy();//完成部署
    System.out.println("部署ID:"+deployment.getId());//1
    System.out.println("部署時間:"+deployment.getDeploymentTime());
}
 
//部署流程定義(zip)  
@Test
public void deployementProcessDefinitionByzip(){
    //從classpath路徑下讀取資源文件  
    InputStream in = this.getClass().getClassLoader().getResourceAsStream("diagrams/helloworld.zip");
    ZipInputStream zipInputStream = new ZipInputStream(in);
    Deployment deployment = processEngine.getRepositoryService()//獲取流程定義和部署對象相關的Service  
            .createDeployment()//創建部署對象                   
            .addZipInputStream(zipInputStream)//使用zip方式部署,將helloworld.bpmn和helloworld.png壓縮成zip格式的文件  
            .deploy();//完成部署  
    System.out.println("部署ID:"+deployment.getId());//1  
    System.out.println("部署時間:"+deployment.getDeploymentTime());
}


部署成功之後可以查看數據庫表 

ACT_RE_DEPLOYMENT(部署對象表)

 

ACT_RE_PROCDEF(流程定義表)

 

ACT_GE_BYTEARRAY(資源文件表)

 

ACT_GE_PROPERTY(主鍵生成表)

 

開啓流程:

Map<String , Object> map = new HashMap<String, Object>();
String[] strs = {"1","2"};
map.put("users1", Arrays.asList(strs));
map.put("users2",Arrays.asList(strs));
map.put("users3" , Arrays.asList(strs));
ProcessInstance processInstance=runtimeService.startProcessInstanceByKey(“流程的key”,map);


以上map中的users1 必須是與bpmn中的變量名成對應;

查詢待完成的任務:

 

//查詢個人的任務
List<Task> list1 = taskService.createTaskQuery().taskAssignee("1").list();
//查詢組的任務
List<Task> list = taskService.createTaskQuery().taskCandidateUser("1").list();
List<Task> groupOrg = taskService.createTaskQuery().taskCandidateGroup("部門").list();

審批:

 

Map<String , Object> map = new HashMap<String, Object>();
map.put("activition" , "2");
Task task = taskService.createTaskQuery().taskAssignee("1").processInstanceId("2501").singleResult();
taskService.complete(task.getId(),map);

 

 

注意:如果用組的方式,candidateUser的方式都需要先認領任務;然後再進行審批;

//認領任務
 taskService.claim("10003" , "1");//前面是任務Id,後面是用戶的id
//將任務回退到未認領狀態
     //任務ID
 String taskId = "6308";
 processEngine.getTaskService()
             .setAssignee(taskId, null);  


查詢任務:包括已完成的和未完成的;

//查詢自己的所有的歷史任務,包括已完成和未完成的
List<HistoricTaskInstance> list1 = historyService.createHistoricTaskInstanceQuery().taskAssignee("1").list();
//已完成的
List<HistoricTaskInstance> list2 = historyService.createHistoricTaskInstanceQuery().taskAssignee("1").finished().list();
//包含變量
List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery().taskAssignee("49").includeProcessVariables().list();
 


查看流程是否還在開啓:

ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId("1").singleResult();
if(processInstance != null){
    //證明流程還沒有結束;
}

 

可以給任務添加說明

//type 爲 測試數據; message 爲 ceshi (參數分別爲:taskId , instanceId ,type ,message)
taskService.addComment("10009" , "10001" , "測試數據" , "ceshi");
//type爲 common message 爲 測試數據1111111
taskService.addComment("10009" , "10001" , "測試數據1111111");

//拿到type爲測試數據的commons 不加默認取出 type爲common的
List<Comment> taskComments = taskService.getTaskComments("10009" , "測試數據");
System.out.println(JSON.toJSONString(taskComments));

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章