流程開發Activiti 與SpringMVC整合實例

流程(Activiti)java

 

流程是完成一系列有序動做的概述。每個節點動做的結果將對後面的具體操做步驟產生影響。信息化系統中流程的功能徹底等同於紙上辦公的層級審批,尤爲在oa系統中各種電子流提現較爲明顯。通常的步驟爲:node

 

①   申請者發起申請。web

②   各級領導審批。通常由低級別往高級別審批。spring

③   每一級別審批結果將影響或者決定申請結果。若下一節點非結束節點,此節點若審批經過將轉給下一節點審批;若此節點審批不經過這次審批將被駁回修改申請或者直接結束。apache

                                                    圖1  流程圖實例json

 

④   當流程審批結束或者中途某節點審批不經過,在達到結束節點時,能夠根據具體審批結果進行相關的業務操做。 如經過審批進行虛擬機資源分配;沒經過審批則不予以分配。瀏覽器

 

業務場景:緩存

完成某業務需通過多個步驟處理每一個步驟處理人或處理人角色不一樣。session

 

流程優點:mybatis

①   業務邏輯容易理解。

流程的執行邏輯和紙上辦公層級審批一致,能夠輕鬆設計出適合各業務的流程實例。

②   使用靈活。

流程在配置時,能夠在執行過程當中動態的將某個節點指定給具體人或者具備某種角色的人(某部門人員)。若指定的是具體的某人,則該人員登錄後便可查看到本身相關的任務進行直接辦理;若指定的含有某角色的人,則含有該角色的人登錄後都能查看到該任務,能夠根據我的狀況,選擇性的對某條審批進行簽收後進行審批。

③   與代碼低耦合

在不是用流程而採用傳統if else判斷也可實現流程功能,但相對而言操做較爲複雜,代碼量較多,尤爲是在後期邏輯較複雜狀況下,須要增長審批節點或者修改現有邏輯,將會形成大量的改動,且不易於測試,容易產生未知bug。

流程的引入將有效規避上述問題。流程自己提供了衆多接口以便用戶使用,同時能夠根據具體業務須要進行有效擴展。能夠在較少代碼量基礎上實現相同的業務功能。設計流程時也相對簡單,經過拖拽配置便可完成。全部流程方法均可共用,不一樣流程根據流程名字進行區分,僅在流程啓動時用於判斷,待啓動後全部流程操做都同樣。在對現有流程增長或者刪除審批節點時無需修改任何java代碼,簡單修改流程xml便可,即使是對複雜節點的增長或者修改,也僅須要修改簡單代碼便可。

④   直觀展現。

流程能夠根據流程圖直觀展現流程某時刻具體處於哪個審批節點,以及具體的審批路徑,每一個節點的審批信息,歷史信息等。

 

activiti中最重要的就是org.activiti.spring.ProcessEngineFactoryBean,比如汽車的發動車,沒有它什麼也幹不了

開發步驟:

① 引入相關包,增長配置文件 applicationContext-activiti.xml,配置文件中jpa相關我都註釋了,採用的mybatis,使用jpa的朋友直接放開就行了

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
        http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">


    <!-- Jpa Entity Manager 配置 -->
<!--     <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> -->
<!--         <property name="dataSource" ref="masterDataSource"/> -->
<!--         <property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter"/> -->
<!--         <property name="packagesToScan" value="com.wish.wishstack.web.activiti"/> -->
<!--         <property name="jpaProperties"> -->
<!--             <props> -->
<!--                 <prop key="hibernate.dialect">${hibernate.dialect}</prop> -->
<!--                 <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop> -->
<!--                 <prop key="hibernate.hbm2ddl.auto">update</prop> -->
<!--             </props> -->
<!--         </property> -->
<!--     </bean> -->

<!--     <bean id="hibernateJpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/> -->

    <!-- Spring Data Jpa配置 -->
<!--     <jpa:repositories base-package="com.wish.wishstack.web.activiti" transaction-manager-ref="transactionManager" -->
<!--                       entity-manager-factory-ref="entityManagerFactory"/> -->

    <!-- Jpa 事務配置 -->
<!--     <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> -->
<!--         <property name="entityManagerFactory" ref="entityManagerFactory"/> -->
<!--     </bean> -->

    <!-- 使用annotation定義事務 -->
<!--     <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/> -->

    <!-- Activiti begin -->
    <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
        
        <property name="dataSource" ref="masterDataSource" />  
        <property name="transactionManager" ref="transactionManager" />  
        <property name="databaseSchemaUpdate" value="true" />  
        <property name="jobExecutorActivate" value="false" />  
        <property name="activityFontName" value="宋體"/>  
        <property name="labelFontName" value="宋體"/>  

        <!-- mail -->
        <property name="mailServerHost" value="localhost"/>
        <property name="mailServerUsername" value="kafeitu"/>
        <property name="mailServerPassword" value="000000"/>
        <property name="mailServerPort" value="2025"/>

        <!-- UUID做爲主鍵生成策略
        <property name="idGenerator" ref="uuidGenerator" />
        -->

        <!-- 生成流程圖的字體 -->
<!--         <property name="activityFontName" value="${diagram.activityFontName}"/> -->
<!--         <property name="labelFontName" value="${diagram.labelFontName}"/> -->

        <!-- 緩存支持
        <property name="processDefinitionCache">
            <bean class="me.kafeitu.demo.activiti.util.cache.DistributedCache" />
        </property>-->

        <!-- 自動部署 -->
        <property name="deploymentResources">
            <list>
                <value>classpath*:/deployments/*.bpmn20.xml</value>
            </list>
        </property>

        <!-- 自定義表單字段類型 -->
        <property name="customFormTypes">
            <list>
<!--                 <bean class="me.kafeitu.demo.activiti.activiti.form.UsersFormType"/> -->
            </list>
        </property>

        <!-- JPA -->
<!--         <property name="jpaEntityManagerFactory" ref="entityManagerFactory" /> -->
<!--         <property name="jpaHandleTransaction" value="false" /> -->
<!--         <property name="jpaCloseEntityManager" value="false" /> -->

        <!-- 全局事件 -->
        <property name="typedEventListeners">
            <map>
                <entry key="VARIABLE_CREATED" >
                    <list>
<!--                         <ref bean="variableCreateListener"/> -->
                    </list>
                </entry>
            </map>
        </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="formService" factory-bean="processEngine" factory-method="getFormService"/>
    <bean id="identityService" factory-bean="processEngine" factory-method="getIdentityService"/>
    <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"/>
    <!-- Activiti end -->

<!--     <jaxws:endpoint id="leaveWebService" implementor="me.kafeitu.demo.activiti.webservice.LeaveWebServiceImpl" address="/leave"/> -->
</beans>

 

②開發頁面, 全部的業務邏輯和標準springMVC一致,只是後臺在處理的時候調用了activiti相關接口進行處理, activiti自帶了15+—張表

核心service類以下,爲了通用性,須要根據狀況再次封裝

package xiaochangwei.zicp.net.service.activity.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricProcessInstanceQuery;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceQuery;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import org.activiti.bpmn.constants.BpmnXMLConstants;


@Service("leaveWorkFlowService")
public class LeaveWorkflowServiceImpl implements LeaveWorkflowService {

    private static Logger logger = LoggerFactory.getLogger(LeaveWorkflowServiceImpl.class);

    @Resource
    private LeaveDao leaveDao;

    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private IdentityService identityService;

    /**
     * 啓動流程
     *
     * @param entity
     */
    public ProcessInstance startWorkflow(Leave entity, Map<String, Object> variables) {
        leaveDao.saveLeave(entity);
        logger.debug("save entity: {}", entity);
        String businessKey = entity.getId().toString();

        ProcessInstance processInstance = null;
        try {
            // 用來設置啓動流程的人員ID,引擎會自動把用戶ID保存到activiti:initiator中
            identityService.setAuthenticatedUserId(entity.getUserId());

            processInstance = runtimeService.startProcessInstanceByKey("leave", businessKey, variables);
            String processInstanceId = processInstance.getId();
            entity.setProcessInstanceId(processInstanceId);
            leaveDao.update(entity);
            logger.debug("start process of {key={}, bkey={}, pid={}, variables={}}",
                    new Object[] { "leave", businessKey, processInstanceId, variables });
        } finally {
            identityService.setAuthenticatedUserId(null);
        }
        return processInstance;
    }

    /**
     * 查詢待辦任務
     *
     * @param userId
     *            用戶ID
     * @return
     */
    @Transactional(readOnly = true)
    public List<Leave> findTodoTasks(String userId, Page<Leave> page) {
        List<Leave> results = new ArrayList<Leave>();

        // 根據當前人的ID查詢
        TaskQuery taskQuery = taskService.createTaskQuery().taskCandidateOrAssigned(userId);
        List<Task> tasks = taskQuery.list();

        // 根據流程的業務ID查詢實體並關聯
        for (Task task : tasks) {
            String processInstanceId = task.getProcessInstanceId();
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                    .processInstanceId(processInstanceId).active().singleResult();
            String businessKey = processInstance.getBusinessKey();
            if (businessKey == null) {
                continue;
            }
            Leave leave = leaveDao.getLeave(new Long(businessKey));
            leave.setTask(task);
            leave.setProcessInstance(processInstance);
            leave.setProcessDefinition(getProcessDefinition(processInstance.getProcessDefinitionId()));
            results.add(leave);
        }

        page.setTotalCount((int) taskQuery.count());
        page.setResult(results);
        return results;
    }

    /**
     * 讀取運行中的流程
     *
     * @return
     */
    @Transactional(readOnly = true)
    public List<Leave> findRunningProcessInstaces(Page<Leave> page) {
        List<Leave> results = new ArrayList<Leave>();
        
        ProcessInstanceQuery query = runtimeService.createProcessInstanceQuery().processDefinitionKey("leave").active()
                .orderByProcessInstanceId().desc();
        List<ProcessInstance> list = query.listPage(page.getStartIndex(), page.getEndIndex());

        // 關聯業務實體
        for (ProcessInstance processInstance : list) {
            String businessKey = processInstance.getBusinessKey();
            if (businessKey == null) {
                continue;
            }
            Leave leave = leaveDao.getLeave(new Long(businessKey));
            if (leave != null) {
                leave.setProcessInstance(processInstance);
                leave.setProcessDefinition(getProcessDefinition(processInstance.getProcessDefinitionId()));
                
                // 設置當前任務信息
                List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstance.getId()).active()
                        .orderByTaskCreateTime().desc().listPage(0, 1);
                leave.setTask(tasks.get(0));
                
                results.add(leave);
            }

        }

        page.setTotalCount((int) query.count());
        page.setResult(results);
        return results;
    }

    /**
     * 讀取已結束中的流程
     *
     * @return
     */
    @Transactional(readOnly = true)
    public List<Leave> findFinishedProcessInstaces(Page<Leave> page) {
        List<Leave> results = new ArrayList<Leave>();
        HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery()
                .processDefinitionKey("leave").finished().orderByProcessInstanceEndTime().desc();
        List<HistoricProcessInstance> list = query.listPage(page.getStartIndex(), page.getEndIndex());

        // 關聯業務實體
        for (HistoricProcessInstance historicProcessInstance : list) {
            String businessKey = historicProcessInstance.getBusinessKey();
            Leave leave = leaveDao.getLeave(new Long(businessKey));
            leave.setProcessDefinition(getProcessDefinition(historicProcessInstance.getProcessDefinitionId()));
            leave.setHistoricProcessInstance(historicProcessInstance);
            results.add(leave);
        }
        page.setTotalCount((int) query.count());
        page.setResult(results);
        return results;
    }

    /**
     * 查詢流程定義對象
     *
     * @param processDefinitionId
     *            流程定義ID
     * @return
     */
    public ProcessDefinition getProcessDefinition(String processDefinitionId) {
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionId(processDefinitionId).singleResult();
        return processDefinition;
    }

    @Autowired
    public void setRuntimeService(RuntimeService runtimeService) {
        this.runtimeService = runtimeService;
    }

    @Autowired
    public void setTaskService(TaskService taskService) {
        this.taskService = taskService;
    }

    @Autowired
    public void setHistoryService(HistoryService historyService) {
        this.historyService = historyService;
    }

    @Autowired
    public void setRepositoryService(RepositoryService repositoryService) {
        this.repositoryService = repositoryService;
    }

}

 

同時還有不少接口用於如流程圖。xml展現,或者流程軌跡展現等

package com.wish.wishstack.web.activiti;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.ManagementService;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.identity.User;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.image.ProcessDiagramGenerator;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.activiti.spring.ProcessEngineFactoryBean;
import org.apache.commons.io.FilenameUtils;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.node.ObjectNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

/**
 * 流程管理控制器
 *
 */
@Controller
@RequestMapping(value = "/workflow")
public class ActivitiController {

    protected Logger logger = LoggerFactory.getLogger(getClass());

//    protected WorkflowProcessDefinitionService workflowProcessDefinitionService;

    protected RepositoryService repositoryService;

    protected RuntimeService runtimeService;

    protected TaskService taskService;

//    protected WorkflowTraceService traceService;

    @Autowired
    ManagementService managementService;

    protected static Map<String, ProcessDefinition> PROCESS_DEFINITION_CACHE = new HashMap<String, ProcessDefinition>();

    @Autowired
    ProcessEngineFactoryBean processEngine;

    @Autowired
    ProcessEngineConfiguration processEngineConfiguration;

    /**
     * 流程定義列表
     *
     * @return
     */
//    @RequestMapping(value = "/process-list")
//    public ModelAndView processList(HttpServletRequest request) {
//        ModelAndView mav = new ModelAndView("workflow/process-list");
//
//    /*
//     * 保存兩個對象,一個是ProcessDefinition(流程定義),一個是Deployment(流程部署)
//     */
//        List<Object[]> objects = new ArrayList<Object[]>();
//
//        Page<Object[]> page = new Page<Object[]>(PageUtil.PAGE_SIZE);
//        int[] pageParams = PageUtil.init(page, request);
//
//        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery().orderByDeploymentId().desc();
//        List<ProcessDefinition> processDefinitionList = processDefinitionQuery.listPage(pageParams[0], pageParams[1]);
//        for (ProcessDefinition processDefinition : processDefinitionList) {
//            String deploymentId = processDefinition.getDeploymentId();
//            Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();
//            objects.add(new Object[]{processDefinition, deployment});
//        }
//
//        page.setTotalCount(processDefinitionQuery.count());
//        page.setResult(objects);
//        mav.addObject("page", page);
//
//        return mav;
//    }

    /**
     * 部署所有流程
     *
     * @return
     * @throws Exception
     */
//    @RequestMapping(value = "/redeploy/all")
//    public String redeployAll(@Value("#{APP_PROPERTIES['export.diagram.path']}") String exportDir) throws Exception {
//        workflowProcessDefinitionService.deployAllFromClasspath(exportDir);
//        return "redirect:/workflow/process-list";
//    }

    /**
     * 讀取資源,經過部署ID
     *
     * @param processDefinitionId 流程定義
     * @param resourceType        資源類型(xml|image)
     * @throws Exception
     */
//    @RequestMapping(value = "/resource/read")
//    public void loadByDeployment(@RequestParam("processDefinitionId") String processDefinitionId, @RequestParam("resourceType") String resourceType,
//                                 HttpServletResponse response) throws Exception {
//        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
//        String resourceName = "";
//        if (resourceType.equals("image")) {
//            resourceName = processDefinition.getDiagramResourceName();
//        } else if (resourceType.equals("xml")) {
//            resourceName = processDefinition.getResourceName();
//        }
//        InputStream resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resourceName);
//        byte[] b = new byte[1024];
//        int len = -1;
//        while ((len = resourceAsStream.read(b, 0, 1024)) != -1) {
//            response.getOutputStream().write(b, 0, len);
//        }
//    }

    /**
     * 讀取資源,經過流程ID
     *
     * @param resourceType      資源類型(xml|image)
     * @param processInstanceId 流程實例ID
     * @param response
     * @throws Exception
     */
    @RequestMapping(value = "/resource/process-instance")
    public void loadByProcessInstance(@RequestParam("type") String resourceType, @RequestParam("pid") String processInstanceId, HttpServletResponse response)
            throws Exception {
        InputStream resourceAsStream = null;
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processInstance.getProcessDefinitionId())
                .singleResult();

        String resourceName = "";
        if (resourceType.equals("image")) {
            resourceName = processDefinition.getDiagramResourceName();
        } else if (resourceType.equals("xml")) {
            resourceName = processDefinition.getResourceName();
        }
        resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resourceName);
        byte[] b = new byte[1024];
        int len = -1;
        while ((len = resourceAsStream.read(b, 0, 1024)) != -1) {
            response.getOutputStream().write(b, 0, len);
        }
    }

//    /**
//     * 刪除部署的流程,級聯刪除流程實例
//     *
//     * @param deploymentId 流程部署ID
//     */
//    @RequestMapping(value = "/process/delete")
//    public String delete(@RequestParam("deploymentId") String deploymentId) {
//        repositoryService.deleteDeployment(deploymentId, true);
//        return "redirect:/workflow/process-list";
//    }
//
//    /**
//     * 輸出跟蹤流程信息
//     *
//     * @param processInstanceId
//     * @return
//     * @throws Exception
//     */
//    @RequestMapping(value = "/process/trace")
//    @ResponseBody
//    public List<Map<String, Object>> traceProcess(@RequestParam("pid") String processInstanceId) throws Exception {
//        List<Map<String, Object>> activityInfos = traceService.traceProcess(processInstanceId);
//        return activityInfos;
//    }
//
    /**
     * 讀取帶跟蹤的圖片
     */
    @RequestMapping(value = "/process/trace/auto/{executionId}")
    public void readResource(@PathVariable("executionId") String executionId, HttpServletResponse response)
            throws Exception {
        response.setHeader("Cache-Control", "no-store");    //禁止瀏覽器緩存 
        response.setHeader("Pragrma", "no-cache");    //禁止瀏覽器緩存 
        response.setDateHeader("Expires", 0);    //禁止瀏覽器緩存 
        response.setCharacterEncoding("UTF-8"); 
        
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(executionId).singleResult();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
        List<String> activeActivityIds = runtimeService.getActiveActivityIds(executionId);
        // 不使用spring請使用下面的兩行代碼
//    ProcessEngineImpl defaultProcessEngine = (ProcessEngineImpl) ProcessEngines.getDefaultProcessEngine();
//    Context.setProcessEngineConfiguration(defaultProcessEngine.getProcessEngineConfiguration());

        // 使用spring注入引擎請使用下面的這行代碼
        processEngineConfiguration = processEngine.getProcessEngineConfiguration();
        Context.setProcessEngineConfiguration((ProcessEngineConfigurationImpl) processEngineConfiguration);

        ProcessDiagramGenerator diagramGenerator = processEngineConfiguration.getProcessDiagramGenerator();
//        InputStream imageStream = diagramGenerator.generateDiagram(bpmnModel, "png", activeActivityIds);
        InputStream imageStream = new DefaultProcessDiagramGenerator().generateDiagram(
                bpmnModel, "png",
                activeActivityIds, Collections.<String>emptyList(), 
                processEngine.getProcessEngineConfiguration().getActivityFontName(), 
                processEngine.getProcessEngineConfiguration().getLabelFontName(), 
                null, 1.0);
        // 輸出資源內容到相應對象
        byte[] b = new byte[1024];
        int len;
        while ((len = imageStream.read(b, 0, 1024)) != -1) {
            response.getOutputStream().write(b, 0, len);
        }
    }

//    @RequestMapping(value = "/deploy")
//    public String deploy(@Value("#{APP_PROPERTIES['export.diagram.path']}") String exportDir, @RequestParam(value = "file", required = false) MultipartFile file) {
//
//        String fileName = file.getOriginalFilename();
//
//        try {
//            InputStream fileInputStream = file.getInputStream();
//            Deployment deployment = null;
//
//            String extension = FilenameUtils.getExtension(fileName);
//            if (extension.equals("zip") || extension.equals("bar")) {
//                ZipInputStream zip = new ZipInputStream(fileInputStream);
//                deployment = repositoryService.createDeployment().addZipInputStream(zip).deploy();
//            } else {
//                deployment = repositoryService.createDeployment().addInputStream(fileName, fileInputStream).deploy();
//            }
//
//            List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).list();
//
//            for (ProcessDefinition processDefinition : list) {
//                WorkflowUtils.exportDiagramToFile(repositoryService, processDefinition, exportDir);
//            }
//
//        } catch (Exception e) {
//            logger.error("error on deploy process, because of file input stream", e);
//        }
//
//        return "redirect:/workflow/process-list";
//    }
//
//    @RequestMapping(value = "/process/convert-to-model/{processDefinitionId}")
//    public String convertToModel(@PathVariable("processDefinitionId") String processDefinitionId)
//            throws UnsupportedEncodingException, XMLStreamException {
//        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
//                .processDefinitionId(processDefinitionId).singleResult();
//        InputStream bpmnStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(),
//                processDefinition.getResourceName());
//        XMLInputFactory xif = XMLInputFactory.newInstance();
//        InputStreamReader in = new InputStreamReader(bpmnStream, "UTF-8");
//        XMLStreamReader xtr = xif.createXMLStreamReader(in);
//        BpmnModel bpmnModel = new BpmnXMLConverter().convertToBpmnModel(xtr);
//
//        BpmnJsonConverter converter = new BpmnJsonConverter();
//        com.fasterxml.jackson.databind.node.ObjectNode modelNode = converter.convertToJson(bpmnModel);
//        Model modelData = repositoryService.newModel();
//        modelData.setKey(processDefinition.getKey());
//        modelData.setName(processDefinition.getResourceName());
//        modelData.setCategory(processDefinition.getDeploymentId());
//
//        ObjectNode modelObjectNode = new ObjectMapper().createObjectNode();
//        modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, processDefinition.getName());
//        modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1);
//        modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, processDefinition.getDescription());
//        modelData.setMetaInfo(modelObjectNode.toString());
//
//        repositoryService.saveModel(modelData);
//
//        repositoryService.addModelEditorSource(modelData.getId(), modelNode.toString().getBytes("utf-8"));
//
//        return "redirect:/workflow/model/list";
//    }
//
//    /**
//     * 待辦任務--Portlet
//     */
//    @RequestMapping(value = "/task/todo/list")
//    @ResponseBody
//    public List<Map<String, Object>> todoList(HttpSession session) throws Exception {
//        User user = UserUtil.getUserFromSession(session);
//        List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm");
//
//        // 已經簽收的任務
//        List<Task> todoList = taskService.createTaskQuery().taskAssignee(user.getId()).active().list();
//        for (Task task : todoList) {
//            String processDefinitionId = task.getProcessDefinitionId();
//            ProcessDefinition processDefinition = getProcessDefinition(processDefinitionId);
//
//            Map<String, Object> singleTask = packageTaskInfo(sdf, task, processDefinition);
//            singleTask.put("status", "todo");
//            result.add(singleTask);
//        }
//
//        // 等待簽收的任務
//        List<Task> toClaimList = taskService.createTaskQuery().taskCandidateUser(user.getId()).active().list();
//        for (Task task : toClaimList) {
//            String processDefinitionId = task.getProcessDefinitionId();
//            ProcessDefinition processDefinition = getProcessDefinition(processDefinitionId);
//
//            Map<String, Object> singleTask = packageTaskInfo(sdf, task, processDefinition);
//            singleTask.put("status", "claim");
//            result.add(singleTask);
//        }
//
//        return result;
//    }

//    private Map<String, Object> packageTaskInfo(SimpleDateFormat sdf, Task task, ProcessDefinition processDefinition) {
//        Map<String, Object> singleTask = new HashMap<String, Object>();
//        singleTask.put("id", task.getId());
//        singleTask.put("name", task.getName());
//        singleTask.put("createTime", sdf.format(task.getCreateTime()));
//        singleTask.put("pdname", processDefinition.getName());
//        singleTask.put("pdversion", processDefinition.getVersion());
//        singleTask.put("pid", task.getProcessInstanceId());
//        return singleTask;
//    }
//
//    private ProcessDefinition getProcessDefinition(String processDefinitionId) {
//        ProcessDefinition processDefinition = PROCESS_DEFINITION_CACHE.get(processDefinitionId);
//        if (processDefinition == null) {
//            processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
//            PROCESS_DEFINITION_CACHE.put(processDefinitionId, processDefinition);
//        }
//        return processDefinition;
//    }
//
//    /**
//     * 掛起、激活流程實例
//     */
//    @RequestMapping(value = "processdefinition/update/{state}/{processDefinitionId}")
//    public String updateState(@PathVariable("state") String state, @PathVariable("processDefinitionId") String processDefinitionId,
//                              RedirectAttributes redirectAttributes) {
//        if (state.equals("active")) {
//            redirectAttributes.addFlashAttribute("message", "已激活ID爲[" + processDefinitionId + "]的流程定義。");
//            repositoryService.activateProcessDefinitionById(processDefinitionId, true, null);
//        } else if (state.equals("suspend")) {
//            repositoryService.suspendProcessDefinitionById(processDefinitionId, true, null);
//            redirectAttributes.addFlashAttribute("message", "已掛起ID爲[" + processDefinitionId + "]的流程定義。");
//        }
//        return "redirect:/workflow/process-list";
//    }
//
//    /**
//     * 導出圖片文件到硬盤
//     *
//     * @return
//     */
//    @RequestMapping(value = "export/diagrams")
//    @ResponseBody
//    public List<String> exportDiagrams(@Value("#{APP_PROPERTIES['export.diagram.path']}") String exportDir) throws IOException {
//        List<String> files = new ArrayList<String>();
//        List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();
//
//        for (ProcessDefinition processDefinition : list) {
//            files.add(WorkflowUtils.exportDiagramToFile(repositoryService, processDefinition, exportDir));
//        }
//
//        return files;
//    }
//
//    @RequestMapping(value = "activity/jump")
//    @ResponseBody
//    public boolean jump(@RequestParam("executionId") String executionId,
//                        @RequestParam("activityId") String activityId) {
//        Command<Object> cmd = new JumpActivityCmd(executionId, activityId);
//        managementService.executeCommand(cmd);
//        return true;
//    }
//
//    @RequestMapping(value = "bpmn/model/{processDefinitionId}")
//    @ResponseBody
//    public BpmnModel queryBpmnModel(@PathVariable("processDefinitionId") String processDefinitionId) {
//        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
//        return bpmnModel;
//    }

//    @Autowired
//    public void setWorkflowProcessDefinitionService(WorkflowProcessDefinitionService workflowProcessDefinitionService) {
//        this.workflowProcessDefinitionService = workflowProcessDefinitionService;
//    }

    @Autowired
    public void setRepositoryService(RepositoryService repositoryService) {
        this.repositoryService = repositoryService;
    }

    @Autowired
    public void setRuntimeService(RuntimeService runtimeService) {
        this.runtimeService = runtimeService;
    }

//    @Autowired
//    public void setTraceService(WorkflowTraceService traceService) {
//        this.traceService = traceService;
//    }

    @Autowired
    public void setTaskService(TaskService taskService) {
        this.taskService = taskService;
    }

}

 

 

根據須要本身整理吧,因代碼涉及到公司機密,就不展現了

相關文章
相關標籤/搜索