下载地址:

http://activiti.org/download.html

源码:

https://github.com/Activiti/Activiti

环境准备(检查项):

    • JDK 1.7 + JAVA_HOME :java -version
    • 下载 Eclipse Indigo +
    • 拷贝activiti-explorer.war 到 Tomcat/webapps目录
    • 运行Tomcat/bin目录startup.bat or startup.sh
    • 不修改Tomcat http端口情况下访问:http://localhost:8080/activiti-explorer
    • 如果不想使用in-memory H2 database(默认演示数据库),修改WEB-INF/classes下文件db.properties
      默认情况下,会创建user and groups, process definitions and models演示数据,如果不想建立,则设置WEB-INF/classes/engine.properties文件,修改为false

    • jar包依赖下载,通过Maven:mvn dependency:copy-dependencies on a module of the Activiti source code.
    • jar包依赖下载,通过放入classpath方式(直接引入依赖),下载地址:http://download.csdn.net/detail/starcrm/9650018
      • org.activiti:activiti-engine:jar:5.17.0
        +- org.activiti:activiti-bpmn-converter:jar:5.17.0:compile
        | \- org.activiti:activiti-bpmn-model:jar:5.17.0:compile
        | +- com.fasterxml.jackson.core:jackson-core:jar:2.2.3:compile
        | \- com.fasterxml.jackson.core:jackson-databind:jar:2.2.3:compile
        | \- com.fasterxml.jackson.core:jackson-annotations:jar:2.2.3:compile
        +- org.activiti:activiti-process-validation:jar:5.17.0:compile
        +- org.activiti:activiti-image-generator:jar:5.17.0:compile
        +- org.apache.commons:commons-email:jar:1.2:compile
        | +- javax.mail:mail:jar:1.4.1:compile
        | \- javax.activation:activation:jar:1.1:compile
        +- org.apache.commons:commons-lang3:jar:3.3.2:compile
        +- org.mybatis:mybatis:jar:3.2.5:compile
        +- org.springframework:spring-beans:jar:4.0.6.RELEASE:compile
        | \- org.springframework:spring-core:jar:4.0.6.RELEASE:compile
        +- joda-time:joda-time:jar:2.6:compile
        +- org.slf4j:slf4j-api:jar:1.7.6:compile
        +- org.slf4j:jcl-over-slf4j:jar:1.7.6:compile

    • 演示用户ID

UserId Password Security roles

kermit

kermit

admin

gonzo

gonzo

manager

fozzie

fozzie

user

 

开发准备:

配置项:activiti.cfg.xml

Spring配置:

<beans xmlns="http://www.springframework.org/schema/beans"
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"> <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration"> <property name="jdbcUrl" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000" />
<property name="jdbcDriver" value="org.h2.Driver" />
<property name="jdbcUsername" value="sa" />
<property name="jdbcPassword" value="" /> <property name="databaseSchemaUpdate" value="true" /> <property name="jobExecutorActivate" value="false" />
<property name="asyncExecutorEnabled" value="true" />
<property name="asyncExecutorActivate" value="false" /> <property name="mailServerHost" value="mail.my-corp.com" />
<property name="mailServerPort" value="5025" />
</bean> </beans>
  • 一般情况可以这样创建引擎实例(即读取activiti.cfg.xml):ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine()
  • 也可以使用beanid:ProcessEngineConfiguration.createProcessEngineConfigurationFromResource(String resource, String beanName);
  • 也可以通过程序设置:
ProcessEngine processEngine = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration()
.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE)
.setJdbcUrl("jdbc:h2:mem:my-own-db;DB_CLOSE_DELAY=1000")
.setAsyncExecutorEnabled(true)
.setAsyncExecutorActivate(false)
.buildProcessEngine();

DBCP 数据连接方式

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" >
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/activiti" />
<property name="username" value="activiti" />
<property name="password" value="activiti" />
<property name="defaultAutoCommit" value="false" />
</bean> <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration"> <property name="dataSource" ref="dataSource" />
...

JNDI Datasource数据连接方式

配置db.properties配置JNDI datasource:
activiti-webapp-explorer2/src/webapp/WEB-INF/activiti-standalone-context.xml
activiti-webapp-rest2/src/main/resources/activiti-context.xml

删除 beans named "dbProperties" and "dataSource".
添加:

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/activitiDB"/>
</bean>

替换activiti-webapp-explorer2/src/main/webapp/META-INF/context.xml:

<Context antiJARLocking="true" path="/activiti-explorer2">
<Resource auth="Container"
name="jdbc/activitiDB"
type="javax.sql.DataSource"
scope="Shareable"
description="JDBC DataSource"
url="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000"
driverClassName="org.h2.Driver"
username="sa"
password=""
defaultAutoCommit="false"
initialSize="5"
maxWait="5000"
maxActive="120"
maxIdle="5"/>
</Context>

替换activiti-webapp-rest2/src/main/webapp/META-INF/context.xml :

<?xml version="1.0" encoding="UTF-8"?>
<Context antiJARLocking="true" path="/activiti-rest2">
<Resource auth="Container"
name="jdbc/activitiDB"
type="javax.sql.DataSource"
scope="Shareable"
description="JDBC DataSource"
url="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=-1"
driverClassName="org.h2.Driver"
username="sa"
password=""
defaultAutoCommit="false"
initialSize="5"
maxWait="5000"
maxActive="120"
maxIdle="5"/>
</Context>

Tomcat 环境下, the JNDI resource:

$CATALINA_BASE/conf/[enginename]/[hostname]/[warname].xml

$CATALINA_BASE/conf/Catalina/localhost/activiti-explorer.xml

<?xml version="1.0" encoding="UTF-8"?>
<Context antiJARLocking="true" path="/activiti-explorer2">
<Resource auth="Container"
name="jdbc/activitiDB"
type="javax.sql.DataSource"
description="JDBC DataSource"
url="jdbc:mysql://localhost:3306/activiti"
driverClassName="com.mysql.jdbc.Driver"
username="sa"
password=""
defaultAutoCommit="false"
initialSize="5"
maxWait="5000"
maxActive="120"
maxIdle="5"/>
</Context>

支持的数据库

databases :

Activiti database type Example JDBC URL Notes

h2

jdbc:h2:tcp://localhost/activiti

Default configured database

mysql

jdbc:mysql://localhost:3306/activiti?autoReconnect=true

Tested using mysql-connector-java database driver

oracle

jdbc:oracle:thin:@localhost:1521:xe

 

postgres

jdbc:postgresql://localhost:5432/activiti

 

db2

jdbc:db2://localhost:50000/activiti

 

mssql

jdbc:sqlserver://localhost:1433;databaseName=activiti (jdbc.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver)OR jdbc:jtds:sqlserver://localhost:1433/activiti (jdbc.driver=net.sourceforge.jtds.jdbc.Driver)

Tested using Microsoft JDBC Driver 4.0 (sqljdbc4.jar) and JTDS Driver

建立数据库表和索引的方式1:通过程序建立

  • Add the activiti-engine jars to your classpath

  • Add a suitable database driver,比如mysql-connector-java

  • 添加配置文件 (activiti.cfg.xml) to your classpath

  • Execute the main method of the DbSchemaCreate class

建立数据库表和索引的方式2:运行SQL脚本

SQL脚本在 database/create 目录

前缀缩写含义

  • ACT_RE_*: RE stands for repository.

  • ACT_RU_*: RU stands for runtime. runtime data of process instances, user tasks, variables, jobs, etc.

  • ACT_ID_*: ID stands for identity. users, groups...

  • ACT_HI_*: HI stands for history. past process instances, variables, tasks...

  • ACT_GE_*: general data, which is used in various use cases.

主要的类

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

RuntimeService runtimeService = processEngine.getRuntimeService();
RepositoryService repositoryService = processEngine.getRepositoryService();
TaskService taskService = processEngine.getTaskService();
ManagementService managementService = processEngine.getManagementService();
IdentityService identityService = processEngine.getIdentityService();
HistoryService historyService = processEngine.getHistoryService();
FormService formService = processEngine.getFormService();

通过程序部署流程

新建 xml file VacationRequest.bpmn20.xml in the src/test/resources/org/activiti/test resource folder

<?xml version="1.0" encoding="UTF-8" ?>
<definitions id="definitions"
targetNamespace="http://activiti.org/bpmn20"
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:activiti="http://activiti.org/bpmn"> <process id="vacationRequest" name="Vacation request"> <startEvent id="request" activiti:initiator="employeeName">
<extensionElements>
<activiti:formProperty id="numberOfDays" name="Number of days" type="long" value="1" required="true"/>
<activiti:formProperty id="startDate" name="First day of holiday (dd-MM-yyy)" datePattern="dd-MM-yyyy hh:mm" type="date" required="true" />
<activiti:formProperty id="vacationMotivation" name="Motivation" type="string" />
</extensionElements>
</startEvent>
<sequenceFlow id="flow1" sourceRef="request" targetRef="handleRequest" /> <userTask id="handleRequest" name="Handle vacation request" >
<documentation>
${employeeName} would like to take ${numberOfDays} day(s) of vacation (Motivation: ${vacationMotivation}).
</documentation>
<extensionElements>
<activiti:formProperty id="vacationApproved" name="Do you approve this vacation" type="enum" required="true">
<activiti:value id="true" name="Approve" />
<activiti:value id="false" name="Reject" />
</activiti:formProperty>
<activiti:formProperty id="managerMotivation" name="Motivation" type="string" />
</extensionElements>
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>management</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask>
<sequenceFlow id="flow2" sourceRef="handleRequest" targetRef="requestApprovedDecision" /> <exclusiveGateway id="requestApprovedDecision" name="Request approved?" />
<sequenceFlow id="flow3" sourceRef="requestApprovedDecision" targetRef="sendApprovalMail">
<conditionExpression xsi:type="tFormalExpression">${vacationApproved == 'true'}</conditionExpression>
</sequenceFlow> <task id="sendApprovalMail" name="Send confirmation e-mail" />
<sequenceFlow id="flow4" sourceRef="sendApprovalMail" targetRef="theEnd1" />
<endEvent id="theEnd1" /> <sequenceFlow id="flow5" sourceRef="requestApprovedDecision" targetRef="adjustVacationRequestTask">
<conditionExpression xsi:type="tFormalExpression">${vacationApproved == 'false'}</conditionExpression>
</sequenceFlow> <userTask id="adjustVacationRequestTask" name="Adjust vacation request">
<documentation>
Your manager has disapproved your vacation request for ${numberOfDays} days.
Reason: ${managerMotivation}
</documentation>
<extensionElements>
<activiti:formProperty id="numberOfDays" name="Number of days" value="${numberOfDays}" type="long" required="true"/>
<activiti:formProperty id="startDate" name="First day of holiday (dd-MM-yyy)" value="${startDate}" datePattern="dd-MM-yyyy hh:mm" type="date" required="true" />
<activiti:formProperty id="vacationMotivation" name="Motivation" value="${vacationMotivation}" type="string" />
<activiti:formProperty id="resendRequest" name="Resend vacation request to manager?" type="enum" required="true">
<activiti:value id="true" name="Yes" />
<activiti:value id="false" name="No" />
</activiti:formProperty>
</extensionElements>
<humanPerformer>
<resourceAssignmentExpression>
<formalExpression>${employeeName}</formalExpression>
</resourceAssignmentExpression>
</humanPerformer>
</userTask>
<sequenceFlow id="flow6" sourceRef="adjustVacationRequestTask" targetRef="resendRequestDecision" /> <exclusiveGateway id="resendRequestDecision" name="Resend request?" />
<sequenceFlow id="flow7" sourceRef="resendRequestDecision" targetRef="handleRequest">
<conditionExpression xsi:type="tFormalExpression">${resendRequest == 'true'}</conditionExpression>
</sequenceFlow> <sequenceFlow id="flow8" sourceRef="resendRequestDecision" targetRef="theEnd2">
<conditionExpression xsi:type="tFormalExpression">${resendRequest == 'false'}</conditionExpression>
</sequenceFlow>
<endEvent id="theEnd2" /> </process> </definitions>

部署:

package activitiLearn;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator; public class test { public static void main(String[] args) {
// TODO Auto-generated method stub PropertyConfigurator.configure("bin/log4j.properties");
Logger log=Logger.getLogger(test.class);
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
repositoryService.createDeployment()
.addClasspathResource("bpmn20/VacationRequest.bpmn20.xml")
.deploy(); log.info("Number of process definitions: " + repositoryService.createProcessDefinitionQuery().count());
} }

输出:

2016-10-10 21:04:55 INFO [org.activiti.engine.ProcessEngines] Initializing process engine using configuration 'file:/D:/workspace/activitiLearn/bin/activiti.cfg.xml'
2016-10-10 21:04:55 INFO [org.activiti.engine.ProcessEngines] initializing process engine for resource file:/D:/workspace/activitiLearn/bin/activiti.cfg.xml
2016-10-10 21:04:56 INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] Loading XML bean definitions from resource loaded through InputStream
2016-10-10 21:04:58 INFO [org.activiti.engine.impl.db.DbSqlSession] performing create on engine with resource org/activiti/db/create/activiti.h2.create.engine.sql
2016-10-10 21:04:58 INFO [org.activiti.engine.impl.db.DbSqlSession] performing create on history with resource org/activiti/db/create/activiti.h2.create.history.sql
2016-10-10 21:04:58 INFO [org.activiti.engine.impl.db.DbSqlSession] performing create on identity with resource org/activiti/db/create/activiti.h2.create.identity.sql
2016-10-10 21:04:58 INFO [org.activiti.engine.impl.ProcessEngineImpl] ProcessEngine default created
2016-10-10 21:04:58 INFO [org.activiti.engine.ProcessEngines] initialised process engine default
2016-10-10 21:04:58 INFO [org.activiti.engine.impl.bpmn.deployer.BpmnDeployer] Processing resource bpmn20/VacationRequest.bpmn20.xml
2016-10-10 21:04:58 INFO [org.test] Number of process definitions: 1

打开管理后台看看,已经成功部署了

开始一个流程实例:

Map<String, Object> variables = new HashMap<String, Object>();
variables.put("employeeName", "Kermit");
variables.put("numberOfDays", new Integer(4));
variables.put("vacationMotivation", "I'm really tired!"); RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("vacationRequest", variables); // Verify that we started a new process instance
Log.info("Number of process instances: " + runtimeService.createProcessInstanceQuery().count());

查询任务:

TaskService taskService = processEngine.getTaskService();
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("management").list();
for (Task task : tasks) {
Log.info("Task available: " + task.getName());
}

完成任务:

Task task = tasks.get(0);

Map<String, Object> taskVariables = new HashMap<String, Object>();
taskVariables.put("vacationApproved", "false");
taskVariables.put("managerMotivation", "We have a tight deadline!");
taskService.complete(task.getId(), taskVariables);

流程挂起:

repositoryService.suspendProcessDefinitionByKey("vacationRequest");
try {
runtimeService.startProcessInstanceByKey("vacationRequest");
} catch (ActivitiException e) {
e.printStackTrace();
}

挂起后重启:

runtimeService.activateProcessInstanceXXX

任务查询:

只能实现AND逻辑

List<Task> tasks = taskService.createTaskQuery()
.taskAssignee("kermit")
.processVariableValueEquals("orderId", "0815")
.orderByDueDate().asc()
.list();

复杂逻辑比如OR逻辑需要自己写SQL

List<Task> tasks = taskService.createNativeTaskQuery()
.sql("SELECT count(*) FROM " + managementService.getTableName(Task.class) + " T WHERE T.NAME_ = #{taskName}")
.parameter("taskName", "gonzoTask")
.list(); long count = taskService.createNativeTaskQuery()
.sql("SELECT count(*) FROM " + managementService.getTableName(Task.class) + " T1, "
+ managementService.getTableName(VariableInstanceEntity.class) + " V1 WHERE V1.TASK_ID_ = T1.ID_")
.count();

流程变量

一个流程实例可以有任意多的变量process variables,变量用来传递数据。

变量存储在数据表ACT_RU_VARIABLE

通过RuntimeService建立:ProcessInstance startProcessInstanceByKey(String processDefinitionKey, Map<String, Object> variables);

在实例运行时,也可以随时设置变量:

void setVariable(String executionId, String variableName, Object value);
void setVariableLocal(String executionId, String variableName, Object value);
void setVariables(String executionId, Map<String, ? extends Object> variables);
void setVariablesLocal(String executionId, Map<String, ? extends Object> variables);
Map<String, Object> getVariables(String executionId);
Map<String, Object> getVariablesLocal(String executionId);
Map<String, Object> getVariables(String executionId, Collection<String> variableNames);
Map<String, Object> getVariablesLocal(String executionId, Collection<String> variableNames);
Object getVariable(String executionId, String variableName);
<T> T getVariable(String executionId, String variableName, Class<T> variableClass); execution.getVariables();
execution.getVariables(Collection<String> variableNames);
execution.getVariable(String variableName); execution.setVariables(Map<String, object> variables);
execution.setVariable(String variableName, Object value);

TaskService也可以使用getVariables,这意味着can have local variables that are alive just for the duration of the task

Liferay7 BPM门户开发之3: Activiti开发环境搭建的更多相关文章

  1. Liferay7 BPM门户开发之11: Activiti工作流程开发的一些统一规则和实现原理(完整版)

    注意:以下规则是我为了规范流程的处理过程,不是Activiti公司的官方规定. 1.流程启动需要设置启动者,在Demo程序中,“启动者变量”名统一设置为initUserId 启动时要做的: ident ...

  2. Liferay7 BPM门户开发之15: Liferay开发体系简介

    Liferay SDK 开发体系 主要分6种: Portlet Hook Theme Layout Templates Web Modules Ext Portlet :类似于servlet的web组 ...

  3. Liferay7 BPM门户开发之8: Activiti实用问题集合

    1.如何实现审核的上级获取(任务逐级审批) 这个是必备功能,通过Spring的注入+Activiti表达式可以很容易解决. 可参考: http://blog.csdn.net/sunxing007/a ...

  4. Liferay7 BPM门户开发之5: Activiti和Spring集成

    参考文档: https://github.com/jbarrez/spring-boot-with-activiti-examplehttps://github.com/sxyx2008/spring ...

  5. Liferay7 BPM门户开发之7: Activiti中的重要概念和主要数据库结构

    流程的人员参与角色: Assignee :签收者(即待办人) Candidate:候选人 Owner:拥有者 Starter:启动者 participant:参与者,包含查阅 流程变量的类型: Str ...

  6. Liferay7 BPM门户开发之6: Activiti数据库换为mysql

    第一步: 在mysql中创建数据库名字叫 'activiti' 执行D:\activiti-5.21.0\database\create下的脚本 第二步: 打开=> apache-tomcat/ ...

  7. Liferay7 BPM门户开发之4: Activiti事件处理和监听Event handlers

    事件机制从Activiti 5.15开始引入,这非常棒,他可以让你实现委托. 可以通过配置添加事件监听器,也可以通过Runtime API加入注册事件. 所有的事件参数子类型都来自org.activi ...

  8. Liferay7 BPM门户开发之17: Portlet 生命周期

    Portlet 生命周期 init() =〉 render() =〉 processAction() =〉 processEvent() =〉 serveResource() =〉destroy() ...

  9. Liferay7 BPM门户开发之37: Liferay7下的OSGi Hook集成开发

    hook开发是Liferay客制扩展的一种方式,比插件灵活,即可以扩展liferay门户,也能对原有特性进行更改,Liferay有许多内置的服务,比如用hook甚至可以覆盖Liferay服务. 可作为 ...

随机推荐

  1. 转载:轻量级Config文件AppSettings节点编辑帮助类

    using System.Configuration; using System.Windows.Forms; namespace Allyn.Common { public class XmlHep ...

  2. 第一个只出现一次的字符字符(python)

    题目描述 在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).   # -*- codin ...

  3. GitHub下载子目录

    背景 整个Github目录太大,国内网速不好,且其他部分也不需要. 方法 把 /tree/master 改成 trunk. svn checkout https://github.com/lodash ...

  4. git创建新的分支

    1.本地创建一个新的分支 git branch develop 2.切换到新创建的分支 git checkout develop 3.将新的分支发布到gitlab上 git push origin d ...

  5. IMU

    (1)用IMU来进行预测 读入一个10/20帧的数据集,通过IMU来初步预测出位姿以及显示其路径. Christian Forster, Luca Carlone, Frank Dellaert, D ...

  6. 判断是否是json

    转:https://blog.csdn.net/dy_smile/article/details/46739251 function isJson(obj) { var isjson = typeof ...

  7. python基础之Day12

    一.闭包函数 什么是闭包函数? 闭:函数是一个内部函数 包:指的是该函数包含对外部作用域(非全局作用域)名字的引用. 给函数传值的方式有两种: 1.使用参数直接给函数传值 2.包给函数 1 2 3 4 ...

  8. MongoDB 官网教程 下载 安装

    官网:https://www.mongodb.com/ Doc:https://docs.mongodb.com/ Manual:https://docs.mongodb.com/manual/ 安装 ...

  9. How to configure Samba Server share on Debian 9 Stretch Linux

    Lubos Rendek Debian 13 June 2017 Contents 1. Objective 2. Operating System and Software Versions 3.  ...

  10. php 高效日志记录扩展seaslog 的使用

    群里交流,听说seaslog不错,此文旨在记录使用. $ wget https://github.com/Neeke/SeasLog/archive/master.zip $ unzip master ...