用戶和組
Activiti內(nèi)置了一套相對簡單的對用戶和組的支持,可以滿足基本的業(yè)務(wù)需求。其中,組可以理解為我們常說的角色,和用戶的關(guān)系是多對對。
用戶
先看一個例子:
@Rule
public ActivitiRule activitiRule = new ActivitiRule();
/**
* activiti 保存用戶
*/
@Test
public void testUser() {
IdentityService identityService = activitiRule.getIdentityService();
User user = identityService.newUser("1");
user.setFirstName("xi");
user.setLastName("yu");
identityService.saveUser(user);
User userdb = identityService.createUserQuery().userId("1").singleResult();
System.out.println(userdb);
identityService.deleteUser("1");
User user1 = identityService.createUserQuery().userId("1").singleResult();
System.out.println(user1);
}
上面的代碼塊就是創(chuàng)建一個簡單的用戶,以及查詢一個用戶和刪除一個用戶,activiti都給我們提供好了現(xiàn)成的api.
組
來看一個組的例子
@Test
public void testGroup() {
IdentityService identityService = activitiRule.getIdentityService();
Group group = identityService.newGroup("dept");
group.setId("dept1");
group.setName("leader");
identityService.saveGroup(group);
Group group1 = identityService.createGroupQuery().groupId("dept1").singleResult();
identityService.deleteGroup("dept1");
Group group2 = identityService.createGroupQuery().groupId("dept1").singleResult();
}
基本和用戶的用法類似
用戶和組的關(guān)系
了解了用戶,也了解了組,現(xiàn)在我們要做的就是把用戶和組聯(lián)系起來。
@Test
public void testMemberShip() {
IdentityService identityService = activitiRule.getIdentityService();
Group group = identityService.newGroup("dept");
group.setId("dept1");
group.setName("leader");
identityService.saveGroup(group);
User user = identityService.newUser("1");
user.setFirstName("xi");
user.setLastName("yu");
identityService.saveUser(user);
identityService.createMembership("1", "dept1");
User groupUser = identityService.createUserQuery().memberOfGroup("dept1").singleResult();
System.out.println(groupUser);
Group group1 = identityService.createGroupQuery().groupMember("1").singleResult();
System.out.println(group1);
}
主要的代碼就是:identityService.createMembership("1", "dept1"); 建立用戶和組的關(guān)系。
用戶任務(wù)中的用戶和組
用戶和組有了關(guān)系,現(xiàn)在應(yīng)該把這個關(guān)系擴(kuò)展到實(shí)際的應(yīng)用當(dāng)中,所謂的實(shí)際應(yīng)用也就是一個個任務(wù)。
候選組
先來看一個簡單的流程:
先看一下xml 配置
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1533434256601" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema">
<process id="user" isClosed="false" processType="None">
<startEvent id="start" name="StartEvent"/>
<userTask activiti:candidateGroups="dept1" id="userGroup"/>
<endEvent id="end" name="end"/>
<sequenceFlow id="_3" sourceRef="start" targetRef="userGroup"/>
<sequenceFlow id="_2" sourceRef="userGroup" targetRef="end"/>
</process>
<bpmndi:BPMNDiagram documentation="background=#3C3F41;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram">
<bpmndi:BPMNPlane bpmnElement="user">
<bpmndi:BPMNShape bpmnElement="end" id="Shape-end">
<dc:Bounds height="32.0" width="32.0" x="320.0" y="210.5"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="userGroup" id="Shape-userGroup">
<dc:Bounds height="55.0" width="85.0" x="115.0" y="190.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="start" id="Shape-start">
<dc:Bounds height="32.0" width="32.0" x="20.0" y="200.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="_2" id="BPMNEdge__2" sourceElement="userGroup" targetElement="end">
<di:waypoint x="200.0" y="217.5"/>
<di:waypoint x="320.0078144082805" y="226.5"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="-1.0" width="-1.0" x="-1.0" y="-1.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_3" id="BPMNEdge__3" sourceElement="start" targetElement="userGroup">
<di:waypoint x="52.0" y="216.0"/>
<di:waypoint x="115.0" y="217.5"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
對于的流程圖:

對應(yīng)對代碼:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class)
public class AbstractTest {
@Rule
public ActivitiRule activitiRule = new ActivitiRule();
IdentityService identityService;
RuntimeService runtimeService;
TaskService taskService;
@Test
public void test() {
identityService = activitiRule.getIdentityService();
runtimeService = activitiRule.getRuntimeService();
taskService = activitiRule.getTaskService();
}
}
public class UserGroupTest extends AbstractTest {
@Before
public void setUp() {
super.test();
Group group = identityService.newGroup("dept1");
group.setId("dept1");
group.setType("assignment");
group.setName("leader");
identityService.saveGroup(group);
User user = identityService.newUser("1");
user.setFirstName("xi");
user.setLastName("yu");
identityService.saveUser(user);
identityService.createMembership("1", "dept1");
User groupUser = identityService.createUserQuery().memberOfGroup("dept1").singleResult();
System.out.println(groupUser);
Group group1 = identityService.createGroupQuery().groupMember("1").singleResult();
System.out.println(group1);
}
@After
public void afterDeal() {
identityService.deleteMembership("1", "dept1");
identityService.deleteUser("1");
identityService.deleteGroup("dept1");
}
@Test
@Deployment(resources = {"user.bpmn"})
public void testUserTask() {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("user");
System.out.println(processInstance);
Task task = taskService.createTaskQuery().taskCandidateUser("1").singleResult();
taskService.claim(task.getId(), "1");
taskService.complete(task.getId());
}
}
關(guān)鍵的代碼: Task task = taskService.createTaskQuery().taskCandidateUser("1").singleResult();
taskService.claim(task.getId(), "1"); 這行代碼的含義是,ID為1的用戶簽收了這個任務(wù)。
候選人
候選人和候選組類似
對于的xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1533434256601" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema">
<process id="user" isClosed="false" processType="None">
<startEvent id="start" name="StartEvent"/>
<userTask activiti:candidateUsers="xixi,xiaoyu" id="userGroup"/>
<endEvent id="end" name="end"/>
<sequenceFlow id="_3" sourceRef="start" targetRef="userGroup"/>
<sequenceFlow id="_2" sourceRef="userGroup" targetRef="end"/>
</process>
<bpmndi:BPMNDiagram documentation="background=#3C3F41;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram">
<bpmndi:BPMNPlane bpmnElement="user">
<bpmndi:BPMNShape bpmnElement="end" id="Shape-end">
<dc:Bounds height="32.0" width="32.0" x="320.0" y="210.5"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="userGroup" id="Shape-userGroup">
<dc:Bounds height="55.0" width="85.0" x="115.0" y="190.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="start" id="Shape-start">
<dc:Bounds height="32.0" width="32.0" x="20.0" y="200.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="_2" id="BPMNEdge__2" sourceElement="userGroup" targetElement="end">
<di:waypoint x="200.0" y="217.5"/>
<di:waypoint x="320.0078144082805" y="226.5"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="-1.0" width="-1.0" x="-1.0" y="-1.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_3" id="BPMNEdge__3" sourceElement="start" targetElement="userGroup">
<di:waypoint x="52.0" y="216.0"/>
<di:waypoint x="115.0" y="217.5"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
對應(yīng)的代碼:
@Before
public void setUp() {
super.test();
Group group = identityService.newGroup("dept1");
group.setId("dept1");
group.setType("assignment");
group.setName("leader");
identityService.saveGroup(group);
User user = identityService.newUser("1");
user.setFirstName("xi");
user.setLastName("yu");
identityService.saveUser(user);
identityService.createMembership("1", "dept1");
User groupUser = identityService.createUserQuery().memberOfGroup("dept1").singleResult();
System.out.println(groupUser);
Group group1 = identityService.createGroupQuery().groupMember("1").singleResult();
System.out.println(group1);
}
@After
public void afterDeal() {
identityService.deleteMembership("1", "dept1");
identityService.deleteUser("1");
identityService.deleteGroup("dept1");
}
@Test
@Deployment(resources = {"user.bpmn"})
public void testUserTask1() {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("user");
System.out.println(processInstance);
// xixi簽收
Task task = taskService.createTaskQuery().taskCandidateUser("xixi").singleResult();
taskService.claim(task.getId(), "xixi");
taskService.complete(task.getId());
//xiaoyu 簽收
Task task1 = taskService.createTaskQuery().taskCandidateUser("xiaoyu").singleResult();
taskService.claim(task1.getId(), "xiaoyu");
taskService.complete(task1.getId());
}
部署流程資源
流程資源可以是工作類型的文件,在啟動流程或者流程實(shí)例運(yùn)行過程中會被讀取。
流程定義文件:擴(kuò)展名為:bpmn20.xml 和bpmn
流程定義的圖片:用bmpn2.0規(guī)范的各種圖形描繪,一般用PNG格式
表單文件:把表單內(nèi)容包材在一個文件里,擴(kuò)展名為form
流程總是在先部署一個流程定義,然后根據(jù)部署的流程定義啟動流程實(shí)例。
classpath 方式
classpath方式就是要以class目錄為基礎(chǔ)尋找對應(yīng)的資源再部署。
//部署流程定義文件
RepositoryService repositoryService = processEngine.getRepositoryService();
// 讀取classpath 文件
Deployment deploy = processEngine.getRepositoryService()
.createDeployment()
.addClasspathResource("leave.bpmn")
.deploy();
InputStream 方式
使用InputStream方式部署流程資源需要傳入一個輸出流以及資源名稱,輸出流的來源不限。
String inputName = "";
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(inputName);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
processEngine.getRepositoryService()
.createDeployment().addInputStream(inputName,fileInputStream)
.deploy();
字符串方式
利用字符串方式可以直接傳入純文本作為資源的來源。
// string
String xml = "";
processEngine.getRepositoryService()
.createDeployment().addString("test.bpmn",xml)
.deploy();
zip/bar格式壓縮包
以上三種每次都只能部署一個流程資源,如果想要部署多個,就要打成bar或者zip的壓縮文件。
//bar zip
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("test.bar");
processEngine.getRepositoryService()
.createDeployment().addZipInputStream(new ZipInputStream(inputStream))
.deploy();
刪除流程部署
一個流程定義不能直接刪除,需要通過流程定義的部署ID來刪除。在執(zhí)行刪除的操作時,會同時刪除所有和本次部署相關(guān)的資源,已經(jīng)生產(chǎn)的流程,任務(wù),歷史的流程,任務(wù)都會刪除掉。
@Test
public void deleteDeployment() {
//不做級聯(lián)刪除
repositoryService.deleteDeployment("1");
//做級聯(lián)刪除
repositoryService.deleteDeployment("1",true);
}