§ 前言
工作流开发(微服务版)基于原有echain工作流改造而来,逻辑类似,使用方式略有区别
工作流开发环境依赖数据库目前支持Oracle,Mysql,Db2这三种关系型数据库开发
§ 本文目标
掌握流程图绘制,配置以及工作流的发起、提交等操作
§ 练习场景
以押品入库为例,开发押品入库、流转
前提:
- 依赖基础微服务工程:yusp-app-oca、yusp-app-common、yusp-echain
- RabbitMQ环境
- 使用工作流的微服务工程
§ 初始化配置
§ 工作流引擎代码下载
链接:https://pan.baidu.com/s/1GUseg6zONVpQ9X3mKOvaQA 提取码:y1xe
§ 引入工作流相关表结构
wf_xx及wfi_xx开头的表结构,可联系统一开发平台获得初始化脚本及数据
§ 初始化数据更新
wf_client
wf_client_instu
wf_studio
wf_studio_folder
wf_client.clientsign字段值需与wf_client_instu.clientsign中字段值保持一致
wf_client_instu.instu_cde需与admin_sm_instu.instu_cde中项目组使用的机构码保持一致
wf_studio和wf_studio_folder,可清空,生产初始化表结构时需保留
§ 配置流程文件路径
修改echain.properties文件
echain.properties
echainstudiopath=F:\\wk\\yusp-app-framework\\yusp-app-single-starter\\echain-studio\\ #设置流程图文件夹位置
§ 配置流程启动文件
eChainStudio.jnlp

§ 流程图绘制
§ 下载eChainStudio.jnlp文件
推荐使用Chrome浏览器下载

§ 启动eChainStudio.jnlp
javaws -verbose C:\Users\figue\Desktop\eChainStudio.jnlp

§ 绘制流程图,见视频
https://pan.baidu.com/s/1cM5IUG8aH-quDq7BwmIHFQ
§ 绘制完流程图,重启工作流引擎[yusp-echain]
§ 流程关联业务配置
详见视频:https://pan.baidu.com/s/1cM5IUG8aH-quDq7BwmIHFQ
§ 新增流程适用业务配置

§ 配置流程流转业务功能页面

注:
2.0及其以上版本直接填写前端页面的路由ID,前端页面的路由ID在route.echain.js里配置,会自动关联到页面

流程关联业务页面需要自己开发,示例见exampleInfo.html与exampleInfo.js
§ 流程关联机构配置
详见视频:https://pan.baidu.com/s/1cM5IUG8aH-quDq7BwmIHFQ

§ 创建业务表
以押品表[WFI_DEMO_YAPIN]为例,字段最好含CUST_NAME和CUST_ID【待办会很直观】,且必须要有一个主键

§ 前端流程发起
[示例见SampleWfInit.js、SampleWfInit.html]
流程发起核心js代码:
startWorkFlow: function () {
var _self = this;
this.$confirm('发起流程?', '提示', {
confirmButtonText: '同意',
cancelButtonText: '取消',
type: 'success',
center: true
}).then(function(){
var comitData = {};
comitData.bizSeqNo = '修改为业务主键';
comitData.wfSign = '修改为流程标识';
comitData.applType = '修改为流程申请类型';// 有了流程标识就不再需要申请类型
comitData.custId='客户ID';
comitData.custName='客户名称';
comitData.paramMap={};//自定义流程参数,此处comitData.paramMap={"bxje":"xxxx"},路由脚本里可以拿到String bxje=(String)obj.paramMap.get("bxje");
_self.$refs.yufpWfInit.wfInit(comitData);
})
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
核心html代码:
yufp-wf-init ref="yufpWfInit" @afterinit="onAfterInit" @afterclose="onAfterClose" :common-params="wfCommonParams" />
注意:
需要引入js (./custom/widgets/js/YufpWfInit.js)

§ 业务微服务做后业务处理
集成开发无需依赖RabbitMQ及相关配置
§ pom.xml引入依赖jar包
务微服务的后业务处理,通过mq的监听实现,业务微服务引用工作流客户端jar包
pom.xml
<dependency>
<groupId>cn.com.yusys.yusp</groupId>
<artifactId>yusp-echain-client</artifactId>
<version>2.1.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2
3
4
5
6
7
8
9
§ RabbitMQ中添加queue
rabbmitMQ安装(步骤略)
2.0及以上版本队列名称为【echain.流程标识】,队列在mq中手动添加

修改springboot配置文件中mq的地址
spring:
# rabbitmq配置
rabbitmq:
host: localhost #MQ地址
port: 5672 #MQ端口
username: username #MQ用户名
password: password #MQ密码
2
3
4
5
6
7
复制如下代码到业务微服务工程中
package cn.com.yusys.yusp.echain.server.clientdemo;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import cn.com.yusys.yusp.echain.client.consts.Consts;
import cn.com.yusys.yusp.echain.client.message.InstanceMessageProcessor;
import cn.com.yusys.yusp.echain.client.message.InstanceMessageProcessorFactory;
@Component
public class InstanceMessageListeners {
private final Logger log = LoggerFactory.getLogger(InstanceMessageListeners.class);
@Autowired
private InstanceMessageProcessorFactory processorFactory;
@RabbitListener(queues = {"RabbitMQ中queue名称"})// 队列名称,多个时以逗号隔开;2.0及以上版本队列名称为【echain.流程标识】,队列在mq中手动添加
@RabbitHandler
public void receiveQueue(String message) {
List<InstanceMessageProcessor> processors = processorFactory.getProcessors(message);
for (InstanceMessageProcessor processor : processors) {
try {
processor.process(message);
} catch (Exception e) {
log.error(e.toString(), e);
}
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
§ 后业务逻辑操作
继承InstanceMessageProcessor.java,完成发起,提交,退回,打回等
示例代码如下:
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.ObjectMapper;
import cn.com.yusys.yusp.echain.client.consts.Consts;
import cn.com.yusys.yusp.echain.client.message.InstanceMessage;
import cn.com.yusys.yusp.echain.client.message.InstanceMessageProcessor;
/**
* 后业务处理示例
*/
@Component
public class BizInstanceMessageProcessorDemo implements InstanceMessageProcessor {
private final Logger log = LoggerFactory.getLogger(this.getClass());
private ObjectMapper objectMapper = new ObjectMapper();
@Override
public boolean should(String message) {
try {
InstanceMessage instanceMessage = objectMapper.readValue(message, InstanceMessage.class);// 字符串转为对象
String wfSign = instanceMessage.getInstanceInfo().getWfSign();
if ("修改为流程标"识.equals(wfSign)) {// 根据流程标识,决定此流程是否走此后业务处理
log.debug("后业务处理类命中:" + this.getClass());
return true;
}
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
@Override
public int order() {
return 0;
}
@Override
public void process(String message) throws Exception {
// instanceMessage 对象中包含业务表主键等信息,便于后业务处理
InstanceMessage instanceMessage = objectMapper.readValue(message, InstanceMessage.class);
String messageType = instanceMessage.getType();
try {
if (Consts.MESSAGE_TYPE_INIT.equals(messageType)) {
log.debug("初始化操作:" + message);
} else if (Consts.MESSAGE_TYPE_SUBMIT.equals(messageType)) {
log.debug("提交操作:" + message);
} else if (Consts.MESSAGE_TYPE_SIGNIN.equals(messageType)) {
log.debug("签收操作:" + message);
} else if (Consts.MESSAGE_TYPE_SIGNOFF.equals(messageType)) {
log.debug("签收取消操作:" + message);
} else if (Consts.MESSAGE_TYPE_CHANGE.equals(messageType)) {
log.debug("转办操作:" + message);
} else if (Consts.MESSAGE_TYPE_JUMP.equals(messageType)) {
log.debug("跳转操作:" + message);
} else if (Consts.MESSAGE_TYPE_END.equals(messageType)) {
log.debug("结束操作:" + message);
} else if (Consts.MESSAGE_TYPE_RETURNBACK.equals(messageType)) {
log.debug("退回操作:" + message);
} else if (Consts.MESSAGE_TYPE_CALLBACK.equals(messageType)) {
log.debug("打回操作:" + message);
} else if (Consts.MESSAGE_TYPE_TAKEBACK.equals(messageType)) {
log.debug("拿回操作:" + message);
} else if (Consts.MESSAGE_TYPE_CANCEL.equals(messageType)) {
log.debug("撤销操作:" + message);
} else if (Consts.MESSAGE_TYPE_HANG.equals(messageType)) {
log.debug("挂起操作:" + message);
} else if (Consts.MESSAGE_TYPE_WAKE.equals(messageType)) {
log.debug("唤醒操作:" + message);
} else if (Consts.MESSAGE_TYPE_REFUSE.equals(messageType)) {
log.debug("否决操作:" + message);
} else {
log.warn("未知操作:" + message);
}
} catch (Exception e) {
e.printStackTrace();
log.error("后业务处理失败"+e.toString());
// 后业务处理失败时,将 message保存到自己的异常表中,调用bizInstanceMessageProcessorDemo.process(String message)进行手动重试
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
§ 统一待办处理


§ 流程发起视频演示
视频链接:https://pan.baidu.com/s/1cM5IUG8aH-quDq7BwmIHFQ
§ FAQ
http://192.168.251.151:8090/pages/viewpage.action?pageId=1114467