【activiti 工作流】关于acitiviti 和 spring boot 集成遇到的一些问题总结

栏目: Java · 发布时间: 5年前

内容简介:最近在调查activiti工作流的事。项目上打算做一个工作流服务,给微服务中的一些需要流程定义的服务用。所以我尝试用spring boot集成activiti。以下是我调查中遇到的一些问题和一些调查到的结果。activity cloud 不知道怎么使用,但是看官方解释比较适合云服务(spring cloud)便于扩展,但是activity cloud 貌似是云平台。因为不会搭建,所以就放弃了。activity7 与 activity6 相比,7 多了processruntime与taskruntime 两个

最近在调查activiti工作流的事。项目上打算做一个工作流服务,给微服务中的一些需要流程定义的服务用。所以我尝试用spring boot集成activiti。以下是我调查中遇到的一些问题和一些调查到的结果。

1. activity7 与 activity6 与 activiti cloud

activity cloud 不知道怎么使用,但是看官方解释比较适合云服务(spring cloud)便于扩展,但是activity cloud 貌似是云平台。因为不会搭建,所以就放弃了。activity7 与 activity6 相比,7 多了processruntime与taskruntime 两个类。这两个类需要与security 一起使用,官方里对于TaskRuntime API 有这样一段话:

Something important to notice here, is that in order to interact with the TaskRuntime API as a user, you need to have the role: ACTIVITI_USER (Granted Authority: ROLE_ACTIVITI_USER) .

因为我项目还没和spring security 集成起来,所以就只好不用这两个类了。我的做法是用activity7 的core,但是还是用 6.0使用方式。

继承方式很简单,在pom里引入就OK了

<activiti-dependencies.version>7.0.0.SR1</activiti-dependencies.version>
       ... ...
       
       <!--activiti starter-->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter</artifactId>
        </dependency>

        <!-- Activiti生成流程图 -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-image-generator</artifactId>
        </dependency>

2. activity 数据表遇到的问题

首先是基本25张表

ACT_GE_* : “GE”代表“General”(通用)

ACT_HI_* : “HI”代表“History”(历史) 这些表中保存的都是历史数据,比如执行过的流程实例、变量、任务,等等

ACT_ID_* : “ID”代表“Identity”(身份)这些表中保存的都是身份信息,如用户和组以及两者之间的关系。如果Activiti被集成在某一系统当中的话,这些表可以不用,可以直接使用现有系统中的用户或组信息

ACT_RE_* : “RE”代表“Repository”(仓库) 这些表中保存一些‘静态’信息,如流程定义和流程资源(如图片、规则等)

ACT_RU_* : “RU”代表“Runtime”(运行时)这些表中保存一些流程实例、用户任务、变量等的运行时数据。Activiti只保存流程实例在执行过程中的运行时数据,并且当流程结束后会立即移除这些数据,这是为了保证运行时表尽量的小并运行的足够快;

其中 history-level: full 这个参数关系着是否会生成 ACT_HI_* 的系列表。 ACT_ID_* 这个系列的表在7里已经没有了。

none:不保存任何的历史数据,因此,在流程执行过程中,这是最高效的。

activity:级别高于none,保存流程实例与流程行为,其他数据不保存。

audit:除activity级别会保存的数据外,还会保存全部的流程任务及其属性。audit为history的默认值。

full:保存历史数据的最高级别,除了会保存audit级别的数据外,还会保存其他全部流程相关的细节数据,包括一些流程参数等。

参照: activiti学习笔记(十八) History

其次,如果使用的是 mysql 数据库,在通一个mysql服务器上不能有两个用于activiti的基础数据库。例如,数据库A已经有一套表结构了,如果打算将schema 切换到b想再生成一套新的表结构,这样是会生成失败的。下面连接里楼主说的就是这种情况,我debug代码追踪的结果也和楼主讲的一样,只要删除掉其中一个,就能正常运行了。 参照:一个MySql实例自动创建多个Activiti数据库问题

3. activity 与 spring boot 集成时遇到的问题

如果是想在yml下配置,用这样的方式就能正常生成表 并启动。

spring:
  activiti:
    db-history-used: true 
    database-schema: activity #指定数据库schema
    history-level: full
    async-executor-activate: true #开启异步,定时任务
    database-schema-update: true

关于 database-schema-update:

flase: 默认值。activiti在启动时,会对比数据库表中保存的版本,如果没有表或者版本不匹配,将抛出异常。

true: activiti会对数据库中所有表进行更新操作。如果表不存在,则自动创建。

create_drop: 在activiti启动时创建表,在关闭时删除表(必须手动关闭引擎,才能删除表)。

drop-create: 在activiti启动时删除原来的旧表,然后在创建新表(不需要手动关闭引擎)。

如果是想用bean自己配置,参考以下方式。 我第一次用bean配置的时候,出现了表无法生成的情况。一开始没有使用SpringProcessEngineConfiguration,并且调用configuration.buildProcessEngine() 生成ProcessEngine,不知道为什么就是无法将HistoryLevel的值设进去,后来修改了写法后就成功了。

@Bean
    public SpringProcessEngineConfiguration processEngineConfiguration(DataSource dataSource, PlatformTransactionManager manager){
        SpringProcessEngineConfiguration configuration =  new SpringProcessEngineConfiguration();
        configuration.setDataSource(dataSource);
        configuration.setTransactionManager(manager);
        configuration.setAsyncExecutorActivate(true);
        configuration.setHistoryLevel(HistoryLevel.FULL);
        configuration.setDatabaseSchema("activity");
        configuration.setDbHistoryUsed(true);
        configuration.setDatabaseSchemaUpdate(DB_SCHEMA_UPDATE_TRUE);
        configuration.setEnableDatabaseEventLogging(true); //是否开启dblog
        return configuration;
    }

4. activity 使用时遇到的问题

  • 七大service接口

【activiti 工作流】关于acitiviti 和 spring boot 集成遇到的一些问题总结

实际上在7里, IdentifyService, FormService 已经没有了。基本上剩下的service对应的就是数据库里每个类别的表的操作。

  • 如何调用restful接口(其他微服务接口)

使用serviceTask,通过实现JavaDelegate 来实现调用外部restful接口

<serviceTask id="vacation_service" name="假期处理" activiti:delegateExpression="${jumpService}">
      <extensionElements>
        <activiti:field name="restUrl">
          <activiti:string><![CDATA[http://stores/decreaseDay]]></activiti:string>
        </activiti:field>
        <activiti:field name="param">
          <activiti:string><![CDATA[day,businessKey,action]]></activiti:string>
        </activiti:field>
      </extensionElements>
</serviceTask>
@Service
public class JumpService implements JavaDelegate {
    private final static Logger logger = LoggerFactory.getLogger(JobServiceImpl.class);
    //restTemplate 配置了ribbon
    @Autowired
    RestTemplate restTemplate;
    //调用地址
    private Expression restUrl;
    // 参数
    private Expression param;

    public void setRestUrl(Expression restUrl) {
        this.restUrl = restUrl;
    }
    public void setParam(Expression param) {
        this.param = param;
    }

    @Override
    public void execute(DelegateExecution delegateExecution) {

        //取得从xml中传过来的参数列表
        String params = (String) param.getValue(delegateExecution);
        //取得从xml中传过来的地址
        String strUrl = (String) restUrl.getValue(delegateExecution);
        
        //TODO:通过调用restTemplate来调用其他微服务接口,或者暴露的restful接口
       
    }
}

参照:activiti6.x调用RESTful服务例子

  • 关于scriptTask 脚本任务的使用

如果要使用groovy 脚本,需要引入jar包到pom中

<dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
            <version>2.5.7</version>
            <type>pom</type>
        </dependency>

编写一个获取spring bean的 工具

@Component
public class SpringContextUtil implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    public static Object getBean(String name){
       return applicationContext.getBean(name);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringContextUtil.applicationContext = applicationContext;
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }
}

然后就可以在脚本中引入工具类后,在脚本中使用这些bean来完成业务了

<scriptTask id="cancel_claim" name="取消认领" scriptFormat="groovy">
      <script>
         import org.cango.activity.util.SpringContextUtil
         import org.activiti.engine.TaskService
         import org.activiti.engine.task.Task

         def taskService = SpringContextUtil.getBean("taskServiceBean");
         def task = taskService.createTaskQuery().taskId(taskId).singleResult();
         if (task == null) {
            println("审核任务ID:"+ taskId+"查询到任务为空!");
         }else if(task.getAssignee()){
            taskService.unclaim(taskId);
            println("审核任务ID:"+ taskId+"取消认领完成");
         }else{
            println("审核任务ID:"+ taskId+"未被认领");
         }
      </script>
    </scriptTask>

值得注意的是,生成activiti的五大类的bean的地方是在 AbstractProcessEngineConfiguration 这个类中。所以向要使用什么类,在这个类中查看具体的类名。

以上就是到目前为止的调查结果。如果还有新的内容会在后面更新~

附件参照: activiti 7 官方说明文档activiti 6 官方使用文档


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Seasoned Schemer

The Seasoned Schemer

Daniel P. Friedman、Matthias Felleisen / The MIT Press / 1995-12-21 / USD 38.00

drawings by Duane Bibbyforeword and afterword by Guy L. Steele Jr.The notion that "thinking about computing is one of the most exciting things the human mind can do" sets both The Little Schemer (form......一起来看看 《The Seasoned Schemer》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具