1. 程式人生 > >Activiti工作流樣例教程(請假-審批流程並向用戶展示工作流實時過程圖)

Activiti工作流樣例教程(請假-審批流程並向用戶展示工作流實時過程圖)

1 配置工作流。

啟動activiti-explorer並登入。(使用者名稱:kermit;密碼:kermit)

選擇 流程->流程設計工作區->新建模型 輸入流程名稱進入流程設計介面,繪製流程圖:

給事件和活動新增ID,並給活動分配(Assignments)代理人(assignee):

儲存退出編輯介面,處理模型選擇匯出模型,導出工作流process.bpmn20.xml。並將檔案新增進專案中:

<process id="approvalprocess" isExecutable="true">
    <startEvent id="beginId"></startEvent>
    <userTask id="leaveId" name="請假申請" activiti:assignee="員工"></userTask>
    <sequenceFlow id="sid-3E778B12-F461-4ED0-B332-6711B1BF8006" sourceRef="beginId" targetRef="leaveId"></sequenceFlow>
    <userTask id="approvalId" name="總經理審批" activiti:assignee="總經理"></userTask>
    <sequenceFlow id="sid-4D19FF7E-CADE-4BA7-BC8E-FE02384B5318" sourceRef="leaveId" targetRef="approvalId"></sequenceFlow>
    <endEvent id="endId"></endEvent>
    <sequenceFlow id="sid-1D5CAC61-71D7-4A33-BD98-5FD661BE8494" sourceRef="approvalId" targetRef="endId"></sequenceFlow>
</process>

在maven中配置activiti的依賴

<dependency>
     <groupId>org.activiti</groupId>
     <artifactId>activiti-engine</artifactId>
     <version>${activiti.version}</version>
</dependency>

<dependency>
     <groupId>org.activiti</groupId>
     <artifactId>activiti-spring</artifactId>
     <version>${activiti.version}</version>
</dependency>

在Spring中配置資料來源、事務管理、流程引擎及幾個必要的xxxService

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
                           http://www.springframework.org/schema/tx      http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

    <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/activiti" />
        <property name="username" value="root" />
        <property name="password" value="root" />
    </bean>

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
        <property name="dataSource" ref="dataSource" />
        <property name="transactionManager" ref="transactionManager" />
        <property name="databaseSchemaUpdate" value="true" />
        <property name="mailServerHost" value="localhost" />
        <property name="mailServerPort" value="5025" />
        <property name="jpaHandleTransaction" value="true" />
        <property name="jpaCloseEntityManager" value="true" />
        <property name="jobExecutorActivate" value="false" />
        <property name="xmlEncoding" value="utf-8" />
        <property name="labelFontName" value="宋體"></property>
        <property name="activityFontName" value="宋體"></property>
    </bean>

    <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
        <property name="processEngineConfiguration" ref="processEngineConfiguration" />
    </bean>

    <bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService" />
    <bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService" />
    <bean id="taskService" factory-bean="processEngine" factory-method="getTaskService" />
    <bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService" />
    <bean id="managementService" factory-bean="processEngine" factory-method="getManagementService" />
    <bean id="formService" factory-bean="processEngine" factory-method="getFormService" />
    <bean id="identityService" factory-bean="processEngine" factory-method="getIdentityService" />

</beans>

2 開發工作流。

首先部署工作流檔案:

@RequestMapping("/deployment")
    public void deployment(@RequestParam("resourceName")String resourceName) {
        Deployment deployment = repositoryService
                .createDeployment()
                .addClasspathResource("workflow/"+resourceName)
                .deploy();
    }

    2.1 啟動工作流

根據process.bpmn20.xml中配置的工作流Id啟動該工作流例項,並得到該流程例項的id,儲存到資料庫中:

ProcessInstance pi = runtimeService.startProcessInstanceByKey(id);
String processid = pi.getId();

    2.2 推進工作流

根據流程例項id找到任務代理人(assignee)的流程任務,呼叫complete方法完成該任務,使任務向下推進:

String processid = (String) map.get("processid");
String assignee = "員工";
Task task = taskService.createTaskQuery().processInstanceId(processid).taskAssignee(assignee).singleResult();
taskService.complete(task.getId());

繼續完成下一步任務

String processid = (String) map.get("processid");
String assignee = "總經理";
Task task = taskService.createTaskQuery().processInstanceId(processid).taskAssignee(assignee).singleResult();
taskService.complete(task.getId());

3 檢視工作流

根據流程例項id找到當前流程定義實體,根據該流程定義獲取流程部署的id和圖形資源名稱,根據其得到圖形輸入流,將其輸出到瀏覽器可得到當前流程的流程圖:

                String processid = (String) map.get("processid");
                ExecutionEntity execution = (ExecutionEntity) runtimeService.createExecutionQuery().processInstanceId(processid).singleResult();
                ProcessDefinitionEntity def = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
                        .getDeployedProcessDefinition(execution.getProcessDefinitionId());
                String diagramResourceName = def.getDiagramResourceName();
                InputStream is = repositoryService.getResourceAsStream(
                        def.getDeploymentId(), diagramResourceName);
                try {
                    OutputStream os = httpServletResponse.getOutputStream();
                    byte [] bs = new byte[1024];
                    int i = 0;
                    while((i=is.read(bs))!=-1){
                        os.write(bs,0,i);
                    }
                } catch (IOException e) {
                }

根據流程例項id找到當前正在執行的任務節點,得到該節點的座標,在頁面上通過座標標示相應的提示紅框:

                String processid = (String) map.get("processid");
                ExecutionEntity execution = (ExecutionEntity) runtimeService.createExecutionQuery().processInstanceId(processid).singleResult();
                String activitiId = execution.getCurrentActivityId();// 當前例項的執行到哪個節點
                ProcessDefinitionEntity def = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
                        .getDeployedProcessDefinition(execution.getProcessDefinitionId());
                List<ActivityImpl> activitiList = def.getActivities();// 獲得當前任務的所有節點
                ActivityImpl actImpl = null;
                for (ActivityImpl activityImpl : activitiList) {
                    String id = activityImpl.getId();
                    if (id.equals(activitiId)) {// 獲得執行到那個節點
                        actImpl = activityImpl;
                        break;
                    }
                }
                if(actImpl==null) return null;
                Map currentActivityMap=new HashMap();
                currentActivityMap.put("x",actImpl.getX());
                currentActivityMap.put("y",actImpl.getY());
                currentActivityMap.put("width",actImpl.getWidth());
                currentActivityMap.put("height",actImpl.getHeight());
                String msg=JSON.toJSONString(currentActivityMap);

頁面展示當前工作流流程圖:

<head>
<script type="text/javascript">
  var id="<%=id%>";
  $(function(){
    var data = U.action("/leaveApprove/nextActivityId", {pk:id});
    var json = JSON.parse(data.msg);
    $("#next").css({"position":"absolute","top":json.y,"left":json.x,"width":json.width,"height":json.height});
  });
</script>
</head>

<body>
  <img src="<%=basePath%>/leaveApprove/watch?pk=<%=id%>" />
  <div id="next" style="border: 1px red solid"></div>
</body>
</html>
效果如圖:展示當前流程圖,並提示正在進行中的任務。