關(guān)于Activiti工作流使用

什么是Activiti?

Activiti5是由Alfresco軟件在2010年5月17日發(fā)布的業(yè)務(wù)流程管理(BPM)框架孟抗,它是覆蓋了業(yè)務(wù)流程管理躲胳、工作流龄糊、服務(wù)協(xié)作等領(lǐng)域的一個(gè)開源的扬绪、靈活的奶甘、易擴(kuò)展的可執(zhí)行流程語言框架挥吵。Activiti基于Apache許可的開源BPM平臺重父,創(chuàng)始人Tom Baeyens是JBoss jBPM的項(xiàng)目架構(gòu)師,它特色是提供了eclipse插件忽匈,開發(fā)人員可以通過插件直接繪畫出業(yè)務(wù)流程圖房午。本文采用activiti5.22版本。數(shù)據(jù)庫是ORACLE11g

1.Activiti數(shù)據(jù)庫結(jié)構(gòu)

1)通過運(yùn)行activiti官方提供的數(shù)據(jù)庫腳本創(chuàng)建數(shù)據(jù)庫丹允,支持db2郭厌、h2袋倔、hsql、mssql沪曙、mysql奕污、oracle、postgres數(shù)據(jù)庫
image.png

1液走、act_ge_ 通用數(shù)據(jù)表碳默,ge是general的縮寫
2、act_hi_ 歷史數(shù)據(jù)表缘眶,hi是history的縮寫嘱根,對應(yīng)HistoryService接口
3、act_id_ 身份數(shù)據(jù)表巷懈,id是identity的縮寫该抒,對應(yīng)IdentityService接口
4、act_re_ 流程存儲表顶燕,re是repository的縮寫凑保,對應(yīng)RepositoryService接口,存儲流程部署和流程定義等靜態(tài)數(shù)據(jù)
5涌攻、act_ru_ 運(yùn)行時(shí)數(shù)據(jù)表欧引,ru是runtime的縮寫,對應(yīng)RuntimeService接口

2.xml配置文件

<?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="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
        <property name="dataSource" ref="dataSource"/>
        <property name="transactionManager" ref="transactionManager"/>
        <property name="databaseSchemaUpdate" value="true"/>
        <property name="jobExecutorActivate" value="false"/>
    </bean>

    <!-- 定義流程引擎 -->
    <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
        <property name="processEngineConfiguration" ref="processEngineConfiguration"/>
    </bean>

    <!-- 定義Service服務(wù) -->
    <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="identityService" factory-bean="processEngine"
          factory-method="getIdentityService"/>
    <bean id="formService" factory-bean="processEngine"
          factory-method="getFormService"></bean>

</beans>

七大接口:

1.RepositoryService:提供一系列管理流程部署和流程定義的API恳谎。
2.RuntimeService:在流程運(yùn)行時(shí)對流程實(shí)例進(jìn)行管理與控制芝此。
3.TaskService:對流程任務(wù)進(jìn)行管理,例如任務(wù)提醒因痛、任務(wù)完成和創(chuàng)建任務(wù)等婚苹。
4.IdentityService:提供對流程角色數(shù)據(jù)進(jìn)行管理的API,這些角色數(shù)據(jù)包括用戶組鸵膏、用戶及它們之間的關(guān)系膊升。
5.ManagementService:提供對流程引擎進(jìn)行管理和維護(hù)的服務(wù)。
6.HistoryService:對流程的歷史數(shù)據(jù)進(jìn)行操作谭企,包括查詢用僧、刪除這些歷史數(shù)據(jù)。
7.FormService:表單服務(wù)赞咙。

3.activiti-webapp-explorer2整合

1)將模板導(dǎo)入項(xiàng)目中

explorer整合實(shí)現(xiàn)在線編輯工作流
將src目錄下diagram-viewer责循,editor-app,modeler.html 復(fù)制到自己項(xiàng)目中攀操,如下圖院仿,本文是復(fù)制到webapp下


image.png

image.png
2)配置全局路徑

配置前段訪問路徑,否則activiti編輯器會(huì)無法訪問

image.png
/*
 * Activiti Modeler component part of the Activiti project
 * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
'use strict';

var ACTIVITI = ACTIVITI || {};

ACTIVITI.CONFIG = {
    'contextRoot' : '/',#配置全文訪問路徑
};
3)后臺配置

1.配置后臺,頁面訪問接口配置歹垫,activti提供了基本的頁面獲取剥汤、流程保存、流程編輯等接口排惨,用于工作流的在線演示與編輯吭敢。


image.png

2.將stencilset.json賦值到配置文件目錄下,保證StencilsetRestResource能訪問到暮芭,這是流程設(shè)計(jì)器的菜單和功能文件鹿驼,保存為json格式。


image.png

4.后臺實(shí)例代碼

1)創(chuàng)建流程
/**
     * 創(chuàng)建流程
     */
    @RequestMapping("/createActiviti")
    public void createActiviti(HttpServletRequest request,HttpServletResponse response) throws IOException{
        Model model = repositoryService.newModel();

        String name = "新建流程";
        String description = "";
        int revision = 1;
        String key = "processKey";

        ObjectNode modelNode = objectMapper.createObjectNode();
        modelNode.put(ModelDataJsonConstants.MODEL_NAME, name);
        modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);
        modelNode.put(ModelDataJsonConstants.MODEL_REVISION, revision);

        model.setName(name);
        model.setKey(key);
        model.setMetaInfo(modelNode.toString());

        repositoryService.saveModel(model);
        String id = model.getId();

        //完善ModelEditorSource
        ObjectNode editorNode = objectMapper.createObjectNode();
        editorNode.put("id", "canvas");
        editorNode.put("resourceId", "canvas");
        ObjectNode stencilSetNode = objectMapper.createObjectNode();
        stencilSetNode.put("namespace",
                "http://b3mn.org/stencilset/bpmn2.0#");
        editorNode.put("stencilset", stencilSetNode);
        repositoryService.addModelEditorSource(id, editorNode.toString().getBytes("utf-8"));
//        return "redirect:/modeler.html?modelId=" + id;
        response.sendRedirect(request.getContextPath() + "/modeler.html?modelId="+id);
    }
2)更新流程
    /**
     * 更新流程
     */
    @RequestMapping("/updateActiviti")
    public void updateActiviti(String id,HttpServletRequest request,HttpServletResponse response) throws IOException{
        response.sendRedirect(request.getContextPath() + "/modeler.html?modelId="+id);
    }
3)發(fā)布流程
      /**
     * 發(fā)布
     */
    @PostMapping("/publish")
    @ResponseBody
    public Object publish(@RequestParam(value="id")String id){
        Result result=new Result();
        try {
            Model modelData=repositoryService.getModel(id);
            byte[] bytes=repositoryService.getModelEditorSource(modelData.getId());
            if(bytes==null){
                result.setMsg("模型不得為空");
                result.setSuccess(false);
                return result;
            }
            JsonNode modelNode=null;
            modelNode=new ObjectMapper().readTree(bytes);
            BpmnModel model=new BpmnJsonConverter().convertToBpmnModel(modelNode);
            if(model.getProcesses().size()==0){
                result.setMsg("數(shù)據(jù)不符合要求");
                result.setSuccess(false);
                return result;
            }
            byte[] bpmnByates = new BpmnXMLConverter().convertToXML(model);
            //發(fā)布流程
            String processName=modelData.getName()+".bpmn20.xml";
            String convertToXML=new String(bpmnByates);
            System.out.println(convertToXML);
            Deployment deployment=repositoryService.createDeployment()
                    .name(modelData.getName())
                    .addString(processName, new String(bpmnByates, "UTF-8"))
                    .deploy();
            modelData.setDeploymentId(deployment.getId());
            repositoryService.saveModel(modelData);
            result.setMsg("發(fā)布成功");
            result.setSuccess(true);
        } catch (Exception e) {
            result.setMsg("發(fā)布失敗");
            result.setSuccess(false);
        }
        return result;
    }
3)流程查詢
    /**
     * 流程查詢
     */
    @PostMapping("/deployDatagrid")
    @ResponseBody
    public Object deployDatagrid(String s_name, HttpServletResponse response,Integer page, Integer rows, String sort, String order){
        PageInfo pageInfo = new PageInfo(page, rows, sort, order);
        if(StringUtils.isBlank(s_name)){
            s_name="";
        }
        int p1=page-1;
        int r1=9-p1;
        List<Deployment> deploymentList=repositoryService.createDeploymentQuery()
                .deploymentNameLike("%" + s_name + "%").orderByDeploymenTime().desc()
                .listPage(p1, r1);
        long total=repositoryService.createDeploymentQuery().deploymentNameLike("%"+s_name+"%").count();
        List<com.pasic.model.po.DeploymentEntity> deploymentList2=new ArrayList<com.pasic.model.po.DeploymentEntity>();
        for (Deployment deployment : deploymentList) {
            com.pasic.model.po.DeploymentEntity depm=new com.pasic.model.po.DeploymentEntity(deployment.getId(),deployment.getName(),deployment.getCategory(),deployment.getTenantId(),deployment.getDeploymentTime());
            deploymentList2.add(depm);
        }

        System.out.println(deploymentList2);
        pageInfo.setRows(deploymentList2);
        pageInfo.setTotal((int)total);
        if(total/rows==0){
            pageInfo.setPagesize(0);
        }else{
            pageInfo.setPagesize(page++);
        }
        
        pageInfo.setNowpage(page);
        pageInfo.setSize(rows);
        pageInfo.setSuccess(true);
        pageInfo.setMessage("列表獲取成功");
        return pageInfo;
    }
4)刪除流程
    /**
     * 刪除流程
     */
    @PostMapping("/deleteDeploy")
    @ResponseBody
    public Object deleteDeploy(@RequestParam(value="id")String id){
        Result result=new Result();
        try {
            //加true強(qiáng)制刪除
            repositoryService.deleteDeployment(id,true);
            result.setSuccess(true);
            result.setMsg("刪除成功");
        } catch (Exception e) {
            result.setSuccess(false);
            result.setMsg("刪除失敗");
        }
        return result;
    }
5)查看流程圖片

1.后臺

    /**
     * 查看流程圖 圖片
     */
    @GetMapping("/showProcessPng")
    public String showProcessPng(@RequestParam(value="deployId")String deployId,org.springframework.ui.Model model){
        
//      model.addAttribute("diagramResourceName", processDefinition.getDiagramResourceName());
        model.addAttribute("deployId", deployId);
        return "activiti/deploy/showProcessPng";
    }
    
    @RequestMapping("/showView")
    public String showView(String deploymentId, HttpServletResponse response)
            throws Exception {
        ProcessDefinition processDefinition=repositoryService.createProcessDefinitionQuery()
                   .deploymentId(deploymentId)
                   .singleResult();
        InputStream inputStream = repositoryService.getResourceAsStream(deploymentId, processDefinition.getDiagramResourceName());
        OutputStream outputStream = response.getOutputStream();
        for (int b = -1; (b = inputStream.read()) != -1; ) {
            outputStream.write(b);
        }
        outputStream.close();
        inputStream.close();
        return null;
    }

2.前臺

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ include file="/commons/global.jsp" %>
<script>
</script>
<div class="bootui-layout" data-options="fit:true,border:false">
    <div data-options="region:'center',fit:true,border:false">
        <img style="position:absolute;top:0px;left:0px" src="${path }/act/showView?deploymentId=${deployId}">
    </div>
</div>
6)將用戶同步到activiti認(rèn)證表中
    /**
     * 同步用戶到activiti中
     */
    @PostMapping("/syncdata")
    @ResponseBody
    public Object syncdata(){
        Result result=new Result();
        try {
            Wrapper<SysUser> wrapper=new EntityWrapper<SysUser>();
            List<SysUser> userList=userService.selectList(wrapper);
            User au = null;
            for (SysUser user : userList) {
                au=new UserEntity();
                au.setId(user.getId());
                au.setFirstName(user.getName());
                au.setEmail("");
                identityService.deleteUser(au.getId());
                identityService.saveUser(au);
            }
            Wrapper<SysRole> wrapper2=new EntityWrapper<SysRole>();
            List<SysRole> sysRoleList=roleService.selectList(wrapper2);
            Group group=null;
            for (SysRole role : sysRoleList) {
                group=new GroupEntity();
                group.setId(role.getId());
                group.setName(role.getName());
                identityService.deleteGroup(group.getId());
                identityService.saveGroup(group);
            }
            Wrapper<SysUserRole> wrapper3=new EntityWrapper<SysUserRole>();
            List<SysUserRole> roleUserList=userRoleService.selectList(wrapper3);
            for (SysUserRole userRole : roleUserList) {
                identityService.deleteMembership(userRole.getUserId(), userRole.getRoleId());
                identityService.createMembership(userRole.getUserId(), userRole.getRoleId());
            }
            result.setMsg("同步成功");
            result.setSuccess(true);
        } catch (Exception e) {
            result.setMsg("同步失敗");
            result.setSuccess(false);
        }
        return result;
    }

*****整合完成后效果

image.png

image.png

image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末辕宏,一起剝皮案震驚了整個(gè)濱河市畜晰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌瑞筐,老刑警劉巖凄鼻,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異聚假,居然都是意外死亡块蚌,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門膘格,熙熙樓的掌柜王于貴愁眉苦臉地迎上來匈子,“玉大人,你說我怎么就攤上這事闯袒。” “怎么了游岳?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵政敢,是天一觀的道長。 經(jīng)常有香客問我胚迫,道長喷户,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任访锻,我火速辦了婚禮褪尝,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘期犬。我一直安慰自己河哑,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布龟虎。 她就那樣靜靜地躺著璃谨,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上佳吞,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天拱雏,我揣著相機(jī)與錄音,去河邊找鬼底扳。 笑死铸抑,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的衷模。 我是一名探鬼主播鹊汛,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼算芯!你這毒婦竟也來了柒昏?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤熙揍,失蹤者是張志新(化名)和其女友劉穎职祷,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體届囚,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡有梆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了意系。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片泥耀。...
    茶點(diǎn)故事閱讀 38,622評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蛔添,靈堂內(nèi)的尸體忽然破棺而出痰催,到底是詐尸還是另有隱情,我是刑警寧澤迎瞧,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布夸溶,位于F島的核電站,受9級特大地震影響凶硅,放射性物質(zhì)發(fā)生泄漏缝裁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一足绅、第九天 我趴在偏房一處隱蔽的房頂上張望捷绑。 院中可真熱鬧,春花似錦氢妈、人聲如沸粹污。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽厕怜。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間粥航,已是汗流浹背琅捏。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留递雀,地道東北人柄延。 一個(gè)月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像缀程,于是被迫代替她去往敵國和親搜吧。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容