In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-07 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
Today, I will introduce you to the API instance analysis of Activiti workflow. The content of the article is good. Now I would like to share it with you. Friends who feel in need can understand it. I hope it will be helpful to you. Let's read it along with the editor's ideas.
First, establish a flow chart
Before starting to do workflow, we should first reflect the specific business in the deployment flowchart of the workflow, and all the tests have passed, which is equivalent to half the success, and the development of the specific business behind is relatively easier.
First of all, let's take a look at what controls are available in idea and the commonly used controls are annotated.
Let's talk about the specific process of creating a flowchart.
First, we need to pull a start node into the bpmn file, which is the graphical interface, just pull in.
Then, we pull a UserTask user task node from the control into the bpmn file.
In this way, there are two approval nodes. If we need some other business requirements, we can also add some gateways, which will not be added here for the time being.
Finally, we only need an end node EndEvent to complete the deployment diagram of the workflow.
Finally, let's take a look at the complete example.
It seems that we have completed the drawing of the whole flow chart, but the only problem is that we have not set up the examination and approval of mentors and counselors, so we still need to take a look at how to set up approval personnel.
First, we need to select an approval node, for example, select the mentor approval node.
Second, we can obviously see a property box called BPMN editor on the left side of the idea editor, which contains all the properties that can be set for a user task node.
Note: candidate users, candidate groups, and task listeners, these three attributes are not discussed here for the time being, but will be added later.
Since, in this step, we need to set up the approver, we need to set our approver in the Assignee property.
As shown in the figure above, the tutor approval node is set to be sihai. In addition to setting up the approver directly, there are two ways to set it, which will be added later.
Another approval node can also be set up in this way to complete the settings of the approver.
Very good, which basically completes the creation of a flowchart. Next, we will explain the explanation of Activiti's API through an example.
Second, an example to explain API
In the creation of the above flowchart, we have not yet generated a png picture, so if you do not know how to generate it, you can refer to the previous article: Activiti Workflow from getting started to burying: integrating spring.
Since we are talking about API, let's take a look at the main API first, so that we can have an overall grasp.
How to use these API? let's follow them one by one.
2.1 process definition
Since it is a process definition, it must be how to deploy the process definition.
2.1.1 deployment process definition method 1 @ Autowired private ProcessEngine processEngine; @ Autowired private TaskService taskService; @ Autowired private RuntimeService runtimeService; @ Autowired private HistoryService historyService / * deployment process definition (from classpath) * / @ Test public void deploymentProcessDefinition_classpath () {Deployment deployment = processEngine.getRepositoryService () / / Service .createdeployment () / / create a deployment object .name ("process definition") / / add the name of the deployment .addClasspathResource ("bpmn/hello.bpmn") / / load from resources in classpath Only one file can be loaded at a time .addClasspathResource ("bpmn/hello.png") / / from resources in classpath, and only one file .deploy () can be loaded at a time. / / complete deployment System.out.println ("deployment ID:" + deployment.getId ()); System.out.println ("deployment name:" + deployment.getName ());}
Note: the junit test environment after integrating spring is used here. How to integrate spring can be found in this article: Activiti Workflow from getting started to burying: integrating spring.
Output result:
In this way, we deploy the process. So how exactly does it operate? let's take a look at the whole process.
Get the process engine object: this is integrated with spring.
A RepositoryService object (repository object) is obtained through the process engine.
A deployment object configuration object is generated by the service object of the warehouse, which is used to encapsulate the configuration of the deployment operation.
This is a chain programming, set the display name in the deployment configuration object, and upload the process definition rule file
Store the rule information defined by the process in the database table.
In fact, this step uses three tables in the Activiti database, namely: act_re_deployment (deployment object table), act_re_procdef (process definition table), and act_ge_bytearray (resource file table).
Let's take a look at the changes in these three tables:
1) act_re_deployment
As you can see, the deployment ID and the deployment name are in this table.
2) act_re_procdef
In this table, the id, bpmn resource file name, png image name and other information of the deployed Deployment_ID deployment process are stored.
3) act_ge_bytearray
Store the deployment information related to the process definition. That is, the place where the process definition document is stored. Each deployment adds two records, one for the bpmn rule file and one for the image (if only one file bpmn is specified during deployment, activiti parses the contents of the bpmn file at deployment time and automatically generates a flowchart). The two files are not very large and are stored in the database in binary form.
2.1.2 deployment process definition method 2 / * deploy process definition (from zip) * / @ Test public void deploymentProcessDefinition_zip () {InputStream in = this.getClass () .getClassLoader () .getResourceAsStream ("bpmn/hello.zip"); ZipInputStream zipInputStream = new ZipInputStream (in) Deployment deployment = processEngine.getRepositoryService () / Service .createdeployment () / related to process definition and deployment objects / / create a deployment object .name ("process definition") / / add the name of the deployment .addZipInputStream (zipInputStream) / / specify a file in zip format to complete the deployment .deploy () / / complete deployment System.out.println ("deployment ID:" + deployment.getId ()); / / System.out.println ("deployment name:" + deployment.getName ()); / /}
The project structure is as follows:
Output result:
From this point of view, there is no problem, the only difference is that the file is compressed into zip format, using zip's input stream as the deployment process definition, and there is no difference in other uses.
After deploying the process definition, we should want to take a look at some information about the process definition.
2.1.3 View process definition / * query process definition * / @ Test public void findProcessDefinition () {List list = processEngine.getRepositoryService () / / Service .createProcessDefinitionQuery () / / create a process definition query / * * specify query conditions Where condition * / / .deploymentId (deploymentId) / / use deployment object ID query / / .processDefinitionId (processDefinitionId) / / use process definition ID query / / .processDefinitionKey (processDefinitionKey) / / use process defined key query / / .processDefinitionNameLike (processDefinitionNameLike) / / use process defined Name fuzzy query / * * sort * / .orderByProcessDefinitionVersion () .orderByProcessDefinitionVersion () / / sort by version in ascending order / / .orderByProcessDefinitionName () .orderByProcessDefinitionName () .orderByProcessDefinitionName () / / sort the result set returned by process definition in descending order / * * result set * / .list () / / returns a list of collections encapsulating the process definition / / .singleResult (); / / returns the unique result set / / .count (); / / returns the number of result sets / / .listPage (firstResult, maxResults) / / paging query if (listings defined null & & list.size () > 0) {for (ProcessDefinition pd:list) {System.out.println ("process definition ID:" + pd.getId ()); / / key+ version of the process definition + random generated number System.out.println ("name of the process definition:" + pd.getName ()) / / corresponding name attribute value System.out.println in hello.bpmn file ("key of process definition:" + pd.getKey ()); / / corresponding id attribute value System.out.println in hello.bpmn file ("version of process definition:" + pd.getVersion ()) / / when the key values defined by the process are the same, the version is upgraded. The default is 1 System.out.println ("Resource name bpmn File:" + pd.getResourceName ()); System.out.println ("Resource name png File:" + pd.getDiagramResourceName ()); System.out.println ("deployment object ID:" + pd.getDeploymentId () System.out.println ("*");}}
Output result:
Summary of query process definition:
The Service related to the process definition and the deployment object is RepositoryService, and later you will find that the process definition is RepositoryService.
Use this createProcessDefinitionQuery () method to set some query parameters, such as passing conditions, descending and ascending order, and so on.
2.1.4 Delete process definition
By deleting the information that deploys ID 2501.
/ * Delete process definition * / @ Test public void deleteProcessDefinition () {/ / use deployment ID to complete deletion. Specify deployment object id to be 2501 and delete String deploymentId = "2501" / * * deletion without cascading * can only delete processes that are not started. If the process starts, an exception will be thrown * / / processEngine.getRepositoryService () / .deletedeployment (deploymentId) / * * cascading deletion * can delete * / processEngine.getRepositoryService () / / .deletedeployment (deploymentId, true) regardless of whether the process is started or not; System.out.println ("deleted successfully!") ;}
Output result:
Check the database and find that the data in act_re_deployment no longer exists.
Again, the deployment definition object is obtained through the getRepositoryService () method, and then the ID deletion information is specified.
2.1.5 get the resources of the process definition document
The main function here is to query the picture, through the picture can be done in the back of the process display. Let's see how to check it out.
/ * View the flowchart * * @ throws IOException * / @ Test public void viewPic () throws IOException {/ * * put the generated image under the folder * / String deploymentId = "5001"; / / get the image resource name List list = processEngine.getRepositoryService () / / .getDeploymentResourceNames (deploymentId) / / define the name of the picture resource String resourceName = ""; if (list! = null & & list.size () > 0) {for (String name: list) {if (".png") > = 0) {resourceName = name } / / get the input stream of the picture InputStream in = processEngine.getRepositoryService () / / .getResourceAsStream (deploymentId, resourceName); / / generate the picture to the directory of F disk File file = new File ("FRV /" + resourceName); / / write the image of the input stream to disk FileUtils.copyInputStreamToFile (in, file) }
Under the F disk, you can find the picture.
2.1.6 query the latest version of the process definition / * query the latest version of the process definition * / @ Test public void findLastVersionProcessDefinition () {List list = processEngine.getRepositoryService () / / .createProcessDefinitionQuery () / .orderByProcess DefinitionVersion (). Asc () / sort .list () using the version ascending order of the process definition Characteristics of / * * map collection: when the key value of the map collection is the same, the latter value will replace the previous value * / Map map = new LinkedHashMap (); if (list! = null & & list.size () > 0) {for (ProcessDefinition pd: list) {map.put (pd.getKey (), pd) }} List pdList = new ArrayList (map.values ()); if (pdList! = null & & pdList.size () > 0) {for (ProcessDefinition pd: pdList) {System.out.println ("process definition ID:" + pd.getId ()) / / key+ version of process definition + random generated number System.out.println ("name of process definition: + pd.getName ()); / / corresponding name attribute value System.out.println in hello.bpmn file (" key of process definition: "+ pd.getKey () / / corresponds to the id attribute value System.out.println in the hello.bpmn file ("version of the process definition:" + pd.getVersion ()); / / when the key value of the process definition is the same, the version is upgraded. The default is 1 System.out.println ("Resource name bpmn File:" + pd.getResourceName ()). System.out.println ("Resource name png File:" + pd.getDiagramResourceName ()); System.out.println ("deployment object ID:" + pd.getDeploymentId ()) System.out.println ("* *");}}
Output result:
2.1.7 Summary of process definition
1. The deployment process definition uses the following tables of Activiti.
Act_re_deployment: deployment object table
Act_re_procdef: process definition table
Act_ge_bytearray: resource file tabl
Act_ge_property: primary key generation strategy table
2. We find that all the operations defined in the deployment process are performed under the class RepositoryService. We only need to get the object through getRepositoryService (), and all the operations defined in the deployment process can be carried out through chain rules.
2.2 use of complete instances of workflow
In this section, we will summarize some of the basic knowledge mentioned above through a complete example, so that we can better learn the previous and later knowledge points, which can also be regarded as a transitional chapter.
Back to the establishment flow chart in the first section, we have already established the basic bpmn diagram, but we need to do a complete example, and we still need to add some content, so that we can do such an example well. Let's first take the bpmn diagram in the first section.
First of all, we need to be clear: so far in this diagram, we have simply drawn the process. For example, when we need to audit, we need to be specific to a specific person to review, so, we need to set up specific personnel for each node to audit.
Note: the auditors who set up the node will talk about it in detail later. Here is just a simple example, so you only need to be able to understand it here and ok it.
Set up auditor steps
First, we need to select a node, for example, the "mentor approval" node in the following figure.
Next, in the left toolbar, we will see a number of options, one of which is Assignee, in which we need to set the approver that our node needs to set.
Assignee format: you can use either English or Chinese directly, for example, sihai. More complex settings will be discussed later.
The node settings below are exactly the same as above.
The examiners approved by counselors are: Ouyang Sihai.
Perfect, so that the task of the flowchart is complete, so we can proceed to the test phase of this example.
1) deployment process definition
The deployment process definition, as described in the previous chapter, can be handled in two ways, one is to load the bpmn file and the png file, and the other is to compress the two files into a compressed file in zip format and then load it. Here we use the first way to deal with it.
/ * deployment process definition (from classpath) * / @ Test public void deploymentProcessDefinition_classpath () {Deployment deployment = processEngine.getRepositoryService () / / Service .createdeployment () / / create a deployment object .name ("hello") / / add the name of the deployment. AddClasspathResource ("bpmn/hello.bpmn") / / load from resources in classpath Only one file can be loaded at a time .addClasspathResource ("bpmn/hello.png") / / from resources in classpath, and only one file .deploy () can be loaded at a time. / / complete deployment log.info ("deployment ID:" + deployment.getId ()); log.info ("deployment name:" + deployment.getName ());}
Now that the process definition is in place, we need to start the process instance.
For information about what has been done in this step, you can see it in the previous section.
2) start the process instance
/ * start the process instance * / @ Test public void startProcessInstance () {/ / 1, the key of the process definition, and use this key to start the process instance String processDefinitionKey = "hello"; / / 2. The Service / / startProcessInstanceByKey method related to the executing process instance and execution object can also set other parameters, such as process variables. ProcessInstance pi = processEngine.getRuntimeService () .startProcessInstanceByKey (processDefinitionKey); / / start the process instance using the key defined by the process. Key corresponds to the attribute value of id in the helloworld.bpmn file and starts with the key value. The default is to start log.info according to the latest version of the process definition ("process instance ID:" + pi.getId ()); / / process instance ID log.info ("process definition ID:" + pi.getProcessDefinitionId (). / / process definition ID}
Note: processDefinitionKey is the name of the bpmn file.
Steps
1 get the runtimeService instance.
2 start the process instance with the name of the bpmn file, that is, processDefinitionKey.
3 after starting the process, the task of the process goes to the tutor's approval node.
The following is the query for personal tasks. We can query the tasks of the tutor's approval node.
3) query personal tasks
/ * query the current person's personal tasks * / @ Test public void findPersonalTask () {String assignee = "sihai" List list = processEngine.getTaskService () / / Service .createTaskQuery () / / create task query object / * * query criteria (where section) * / .taskAssignee (assignee) / / specify personal task query Specify the handler of the / .taskCandidateUser (candidateUser) / / group task query / / .processDefinitionId (processDefinitionId) / / use the process definition ID query / / .processInstanceId (processInstanceId) / / use the process instance ID query / / .executionId (executionId) / / use the execution object ID to query Query / * * sort * / .orderByTaskCreateTime (). Asc () / sort using ascending order of creation time / * * return result set * / / .singleResult () / / return unique result set / / .count () / number of result sets returned / / .listPage (firstResult MaxResults) / / pagination query .list (); / return list if (listings null & & list.size () > 0) {for (Task task:list) {log.info ("task ID:" + task.getId ()); log.info ("task name:" + task.getName ()) Log.info ("Task creation time:" + task.getCreateTime ()); log.info ("Task Manager:" + task.getAssignee ()); log.info ("process instance ID:" + task.getProcessInstanceId ()); log.info ("execution object ID:" + task.getExecutionId ()) Log.info ("process definition ID:" + task.getProcessDefinitionId ()); log.info ("*");}
Through sihai, the approver, we found the following information.
Analysis step
1 first, the TaskService object is obtained through the getTaskService method.
2 create the query object through the createTaskQuery method.
(3) the auditor is set up by taskAssignee method.
4 for the return of the results, we can set sorting and other information through orderByTaskCreateTime (). Asc ().
It should be noted here that an important piece of information obtained from the query is: task id (taskId). Next, we need to complete the task through this task id.
4) handle personal tasks
/ * complete my task * / @ Test public void completePersonalTask () {/ / Task ID, which is obtained by the previous query. String taskId = "7504"; processEngine.getTaskService () / / Service .complete (taskId) related to the management of the task being executed; log.info ("complete task: task ID:" + taskId);}
Complete the task through the task id: 7504 in the previous step.
Steps
1 first, get the TaskService object through the getTaskService method.
2 call the complete method to complete the task given a specific task id.
5) query the process status (determine which node the process goes to)
This interface is still very needed. When we are in a specific business, we need to judge the state of our process, or which node our process has reached. This interface saves us a lot of things to implement the business.
/ * query process status (determine which node the process goes to) * / @ Test public void isProcessActive () {String processInstanceId = "7501" ProcessInstance pi = processEngine.getRuntimeService () / indicates the executing process instance and execution object. CreateProcessInstanceQuery () / create process instance query .processInstanceId (processInstanceId) / / query .singleResult () using process instance ID; if (pi = = null) {log.info ("process ended") } else {log.info ("process does not end"); / / get task status log.info ("Node id:" + pi.getActivityId ());}}
Steps:
1 get the process instance ProcessInstance object.
2 obtain the instance Id (node id) through the getActivityId method.
So what is the use of Id when you get the node?
In fact, with this Id, we can judge where the process goes. For example, the output node id above is _ 4, and this _ 4 is the id of the corresponding counselor approval node, so we can read that the process has actually reached this node, and it will play a role later when the page displays the process status.
6) query the historical information of the process execution
By looking at the official API interface of activiti 5, it is found that there are the following query interfaces for viewing historical information.
Let's test the following methods one by one with the above examples.
Historical activity instance query API
/ * * Historical activity query API * / @ Test public void findHistoryActivity () {String processInstanceId = "7501"; List hais = processEngine.getHistoryService () / / .createHistoricActivityInstanceQuery () .processInstanceId (processInstanceId) .list () For (HistoricActivityInstance hai: hais) {log.info ("activity id:" + hai.getActivityId () + "approver:" + hai.getAssignee () + "Task id:" + hai.getTaskId ()) Log.info ("*");}}
Not only can you find this information through this interface, but there are other ways to get more other information about historical activities.
Historical process instance query interface
/ * query historical process instance * / @ Test public void findHistoryProcessInstance () {String processInstanceId = "7501" HistoricProcessInstance hpi = processEngine.getHistoryService () / Service related to historical data (history table). CreateHistoricProcessInstanceQuery () / create historical process instance query. ProcessInstanceId (processInstanceId) / use process instance ID query .orderByPr ocessInstanceStartTime (). Asc (). SingleResult () Log.info (hpi.getId () + "+ hpi.getProcessDefinitionId () +" + hpi.getStartTime () + "+ hpi.getEndTime () +" + hpi.getDurationInMillis ());}
This interface can query all the information about historical process instances.
Historical task instance query interface
/ * * query history task * / @ Test public void findHistoryTask () {String processInstanceId = "7501"; List list = processEngine.getHistoryService () / / Service .createHistoricTaskInstanceQuery () / / create history task instance query .processInstanceId (processInstanceId) / / .orderByHistoricTaskInstanceStartTime (). List (). If (list! = null & & list.size () > 0) {for (HistoricTaskInstance hti: list) {log.info ("\ nTask Id:" + hti.getId () + "Task name:" + hti.getName () + "process instance Id:" + hti.getProcessInstanceId () + "\ nstart time:" + hti .getStartTime () + "end time:" + hti.getEndTime () + "duration:" + hti.getDurationInMillis () }}}
This query interface can query historical task information.
Historical process variable query interface
/ * query historical process variables * / @ Test public void findHistoryProcessVariables () {String processInstanceId = "7501"; List list = processEngine.getHistoryService () / / .createHistoricVariableInstanceQuery () / / create a historical process variable query object .processInstanceId (processInstanceId) / / .list () If (list! = null & & list.size () > 0) {for (HistoricVariableInstance hvi: list) {log.info ("\ n" + hvi.getId () + "+ hvi.getProcessInstanceId () +"\ n "+ hvi.getVariableName () +" + hvi.getVariableTypeName () + "+ hvi.getValue ());}
No process variables are set in this example, so no historical information can be queried here.
This interface is mainly about the setting of historical process variables.
Historical local interface query interface
/ * * query historical data by executing sql, because the underlying layer of activiti is the database table. * / @ Test public void findHistoryByNative () {HistoricProcessInstance hpi = processEngine.getHistoryService () .createNativeHistoricProcessInstanceQuery () .sql ("query sql statements for underlying database tables") .singleResult () Log.info ("\ n" + hpi.getId () + "+ hpi.getProcessDefinitionId () +" + hpi.getStartTime () + "\ n" + hpi.getEndTime () + "" + hpi.getDurationInMillis ());}
This interface provides the ability to query historical information directly through sql statements. We only need to write the native sql statement in the sql () method to query the data.
The above is the whole content of the API instance analysis of Activiti workflow, more content related to the API instance analysis of Activiti workflow can search the previous article or browse the following article to learn ha! I believe the editor will add more knowledge to you. I hope you can support it!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.