zoukankan      html  css  js  c++  java
  • Liferay7 BPM门户开发之3: Activiti开发环境搭建

    下载地址:

    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

    UserIdPasswordSecurity 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 typeExample JDBC URLNotes

    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

  • 相关阅读:
    个人作业——软件工程实践总结&个人技术博客
    Vue实现表格导出Excel
    个人作业——软件测评
    结对第二次—某次疫情统计可视化的实现
    结对第一次—疫情统计可视化(原型设计)
    代码规范
    软工实践寒假作业(2/2)
    软工实践寒假作业(1/2)
    个人作业——软件工程实践总结&个人技术博客
    Android 自定义控件
  • 原文地址:https://www.cnblogs.com/starcrm/p/5946419.html
Copyright © 2011-2022 走看看