zoukankan      html  css  js  c++  java
  • Liferay7 BPM门户开发之5: Activiti和Spring集成

    参考文档:

    https://github.com/jbarrez/spring-boot-with-activiti-example
    https://github.com/sxyx2008/spring-activiti-webapp
    http://www.cnblogs.com/hongwz/p/5548473.html

    Spring典型配置

    <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="org.h2.Driver" />
    <property name="url" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000" />
    <property name="username" value="sa" />
    <property name="password" value="" />
    </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="jobExecutorActivate" value="false" />
    </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" />
    
    ...

    自定义的实体类可以这么设置:

    <beans>
    ...
    <tx:annotation-driven transaction-manager="transactionManager"/>
    
    <bean id="userBean" class="org.activiti.spring.test.UserBean">
    <property name="runtimeService" ref="runtimeService" />
    </bean>
    
    <bean id="printer" class="org.activiti.spring.test.Printer" />
    
    </beans>

    写注解:

    @ContextConfiguration("classpath:org/activiti/spring/test/transaction/SpringTransactionIntegrationTest-context.xml")

    然后就可以访问Activiti的工厂类和自定义的实体类,
    比如RepositoryService的实例这样获得,同时这也是Spring集成环境下的bpmn文件的部署方式:

    RepositoryService repositoryService =
    (RepositoryService) applicationContext.getBean("repositoryService");
    String deploymentId = repositoryService
    .createDeployment()
    .addClasspathResource("org/activiti/spring/test/hello.bpmn20.xml")
    .deploy()
    .getId();

    new 一个自定义的实体类实例:

    UserBean userBean = (UserBean) applicationContext.getBean("userBean");
    userBean.hello();

    自定义的实体类:

    public class UserBean {
    
    /** Spring 注入 */
    private RuntimeService runtimeService;
    
    @Transactional
    public void hello() {
    runtimeService.startProcessInstanceByKey("helloProcess");
    }
    
    public void setRuntimeService(RuntimeService runtimeService) {
    this.runtimeService = runtimeService;
    }
    }

    表达式

    在流程定义文件bpmn20.xml使用表达式

    表达式可以灵活动态的使用类的方法,他可以实现流程计算逻辑和实体类的解耦,说具体些就是流程定义文件可以不用Hardcode了,直接通过接口调用的形式访问具体的类,
    举例,定义一个输出打印的类,

    public class Printer {
    
    public void printMessage() {
      System.out.println("hello world");
    }
    }

    在Spring里注册:

    <beans>
    ...
    
    <bean id="printer" class="org.activiti.examples.spring.Printer" />
    
    </beans>

    建立关联配置:

    <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
    ...
    <property name="beans">
    <map>
    <entry key="printer" value-ref="printer" />
    </map>
    </property>
    </bean>

    最后,就可以在流程定义文件bpmn20.xml使用表达式,定义了一个serviceTask:
    这种调用方法非常灵活,也是集成Spring高效和方便的地方

    <definitions id="definitions">
    
    <process id="helloProcess">
    
    <startEvent id="start" />
    <sequenceFlow id="flow1" sourceRef="start" targetRef="print" />
    
    <serviceTask id="print" activiti:expression="#{printer.printMessage()}" />
    <sequenceFlow id="flow2" sourceRef="print" targetRef="end" />
    
    <endEvent id="end" />
    
    </process>
    
    </definitions>

    使用Spring自动部署bpmn20.xml
    仅当文件变化的时候,才会被重新部署,特别方便用于系统调试,程序员必备

    <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
    ...
    <property name="deploymentResources"
    value="classpath*:/org/activiti/spring/test/autodeployment/autodeploy.*.bpmn20.xml" />
    </bean>
    
    <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
    <property name="processEngineConfiguration" ref="processEngineConfiguration" />
    </bean>

    可以使用通配符

    <property name="deploymentResources" value="classpath*:/activiti/*.bpmn" />
    <property name="deploymentMode" value="single-resource" />

    Hibernate 4.2.x集成

    POM:

    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-orm</artifactId>
    <version>${org.springframework.version}</version>
    </dependency>
    
    <dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.183</version>
    </dependency>

    配置是不是很简单?

    然后就可以开发了

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @ComponentScan
    @EnableAutoConfiguration
    public class MyApplication {
    
    public static void main(String[] args) {
    SpringApplication.run(MyApplication.class, args);
    }
    
    @Bean
    public CommandLineRunner init(final RepositoryService repositoryService,
    final RuntimeService runtimeService,
    final TaskService taskService) {
    
    return new CommandLineRunner() {
    @Override
    public void run(String... strings) throws Exception {
    System.out.println("Number of process definitions : "
    + repositoryService.createProcessDefinitionQuery().count());
    System.out.println("Number of tasks : " + taskService.createTaskQuery().count());
    runtimeService.startProcessInstanceByKey("oneTaskProcess");
    System.out.println("Number of tasks after process start: " + taskService.createTaskQuery().count());
    }
    };
    
    }
    }

    使用MySQL数据库
    POM:

    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.34</version>
    </dependency>
    <dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-jdbc</artifactId>
    <version>8.0.15</version>
    </dependency>

    数据源

    @Bean
    public DataSource database() {
    return DataSourceBuilder.create()
    .url("jdbc:mysql://127.0.0.1:3306/activiti-spring-boot?characterEncoding=UTF-8")
    .username("alfresco")
    .password("alfresco")
    .driverClassName("com.mysql.jdbc.Driver")
    .build();
    }

    REST开发扩展

    Spring Boot可以快速开发web api接口,REST对集成第三方应用非常重要
    POM:

    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>${spring.boot.version}</version>
    </dependency>

    开发服务类,服务类是用于控制器的重复调用,即帮助类

    @Service
    public class MyService {
    
    @Autowired
    private RuntimeService runtimeService;
    
    @Autowired
    private TaskService taskService;
    
    @Transactional
    public void startProcess() {
    runtimeService.startProcessInstanceByKey("oneTaskProcess");
    }
    
    @Transactional
    public List<Task> getTasks(String assignee) {
    return taskService.createTaskQuery().taskAssignee(assignee).list();
    }
    
    }

    控制器:
    注意:启动流程使用POST,获取任务使用了GET,在输出时自动把实体类(TaskRepresentation)转换为JSON格式

    @RestController
    public class MyRestController {
    
    @Autowired
    private MyService myService;
    
    @RequestMapping(value="/process", method= RequestMethod.POST)
    public void startProcessInstance() {
    myService.startProcess();
    }
    
    @RequestMapping(value="/tasks", method= RequestMethod.GET, produces=MediaType.APPLICATION_JSON_VALUE)
    public List<TaskRepresentation> getTasks(@RequestParam String assignee) {
    List<Task> tasks = myService.getTasks(assignee);
    List<TaskRepresentation> dtos = new ArrayList<TaskRepresentation>();
    for (Task task : tasks) {
    dtos.add(new TaskRepresentation(task.getId(), task.getName()));
    }
    return dtos;
    }
    
    static class TaskRepresentation {
    
    private String id;
    private String name;
    
    public TaskRepresentation(String id, String name) {
    this.id = id;
    this.name = name;
    }
    
    public String getId() {
    return id;
    }
    public void setId(String id) {
    this.id = id;
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    
    }
    
    }

    需要注意@ComponentScan一定在加在application类的注解

    测试:
    curl -X POST http://localhost:8080/process
    curl http://localhost:8080/tasks?assignee=kermit
    [{"id":"10004","name":"my task"}]

    JPA支持

    默认JPA是Hibernate

    POM:

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

    实体类:

    @Entity
    class Person {
    
    @Id
    @GeneratedValue
    private Long id;
    
    private String username;
    
    private String firstName;
    
    private String lastName;
    
    private Date birthDate;
    
    public Person() {
    }
    
    public Person(String username, String firstName, String lastName, Date birthDate) {
    this.username = username;
    this.firstName = firstName;
    this.lastName = lastName;
    this.birthDate = birthDate;
    }
    
    public Long getId() {
    return id;
    }
    
    public void setId(Long id) {
    this.id = id;
    }
    
    public String getUsername() {
    return username;
    }
    
    public void setUsername(String username) {
    this.username = username;
    }
    
    public String getFirstName() {
    return firstName;
    }
    
    public void setFirstName(String firstName) {
    this.firstName = firstName;
    }
    
    public String getLastName() {
    return lastName;
    }
    
    public void setLastName(String lastName) {
    this.lastName = lastName;
    }
    
    public Date getBirthDate() {
    return birthDate;
    }
    
    public void setBirthDate(Date birthDate) {
    this.birthDate = birthDate;
    }
    }

    如果不使用in-memory数据库,数据表不会自动建立,需要 application.properties 增加配置:
    spring.jpa.hibernate.ddl-auto=update

    增加接口:

    public interface PersonRepository extends JpaRepository<Person, Long> {
    
    Person findByUsername(String username);
    
    }

    服务类:

    @Service
    @Transactional
    public class MyService {
    
    @Autowired
    private RuntimeService runtimeService;
    
    @Autowired
    private TaskService taskService;
    
    @Autowired
    private PersonRepository personRepository;
    
    public void startProcess(String assignee) {
    
    Person person = personRepository.findByUsername(assignee);
    
    Map<String, Object> variables = new HashMap<String, Object>();
    variables.put("person", person);
    runtimeService.startProcessInstanceByKey("oneTaskProcess", variables);
    }
    
    public List<Task> getTasks(String assignee) {
    return taskService.createTaskQuery().taskAssignee(assignee).list();
    }
    
    public void createDemoUsers() {
    if (personRepository.findAll().size() == 0) {
    personRepository.save(new Person("jbarrez", "Joram", "Barrez", new Date()));
    personRepository.save(new Person("trademakers", "Tijs", "Rademakers", new Date()));
    }
    }
    
    }

    在CommandLineRunner 初始化的时候,添加用户持久化数据(createDemoUsers())

    @Bean
    public CommandLineRunner init(final MyService myService) {
    
    return new CommandLineRunner() {
    public void run(String... strings) throws Exception {
      myService.createDemoUsers();
    }
    };
    
    }

    控制器:

    @RestController
    public class MyRestController {
    
    @Autowired
    private MyService myService;
    
    @RequestMapping(value="/process", method= RequestMethod.POST)
    public void startProcessInstance(@RequestBody StartProcessRepresentation startProcessRepresentation) {
    myService.startProcess(startProcessRepresentation.getAssignee());
    }
    
    ...
    
    static class StartProcessRepresentation {
    
    private String assignee;
    
    public String getAssignee() {
    return assignee;
    }
    
    public void setAssignee(String assignee) {
    this.assignee = assignee;
    }
    }

    流程定义再一次使用了表达式:

    <userTask id="theTask" name="my task" activiti:assignee="${person.id}"/>

    测试:POST一个流程启动者的username
    curl -H "Content-Type: application/json" -d '{"assignee" : "jbarrez"}' http://localhost:8080/process
    curl http://localhost:8080/tasks?assignee=1

    [{"id":"12505","name":"my task"}]

    更高级的内容可以自行研究:

    • Actuator support
    • Spring Integration support
    • Rest API integration
    • Spring Security support
  • 相关阅读:
    2020.10.23 19级training 补题报告
    2020.10.17 天梯赛练习 补题报告
    2020.10.16 19级training 补题报告
    2020.10.9 19级training 补题报告
    2020.10.10 天梯赛练习 补题报告
    2020.10.3 天梯赛练习 补题报告
    2020.10.2 19级training 补题报告
    第十届山东省ACM省赛复现补题报告
    VVDI Key Tool Plus Adds VW Passat 2015 Key via OBD
    Xhorse VVDI Prog Software V5.0.3 Adds Many MCUs
  • 原文地址:https://www.cnblogs.com/starcrm/p/5948485.html
Copyright © 2011-2022 走看看