前言

首先,感谢大家对上一篇文章[业务可视化-让你的流程图"Run"起来(5.SpringBoot集成&微服务编排)]的支持。

分享一下近期我对这个项目的一些改进。

在项目中,经常会有一些批处理的定时任务需要配置,目前的java项目一般采用Spring-Batch来作为批处理的平台。

但是Spring-Batch在对Job流程(并行,分支,条件分支,合并等)的支持略显复杂臃肿。

尤其是流程可视化这方面几乎不支持。

所以,最近对ladybugflow做了改进,在天然支持可视化流程的基础上,追加了对定时任务的支持。

本篇文章介绍ladybugflow定时任务的配置,和与SpringBatch相结合完成批处理的可视化操作的例子。

定时任务

对于流程的执行,前面文章介绍了流程的启动方法,如下:

Flow1 testFlow = new Flow1();
testFlow.startFlow(true);

这样只能完成流程的一次启动,如果需要定时启动流程,ladybugflow提供了在启动节点中设置cron表达式的方法来实现定时启动流程。

cron表达式

我们首先简单的了解一下cron表达式

Cron表达式是有六个空格分隔的时间和日期字段(域)组成的字符串。

┌───────────── second (0-59)
 │ ┌───────────── minute (0 - 59)
 │ │ ┌───────────── hour (0 - 23)
 │ │ │ ┌───────────── day of the month (1 - 31)
 │ │ │ │ ┌───────────── month (1 - 12) (or JAN-DEC)
 │ │ │ │ │ ┌───────────── day of the week (0 - 7)
 │ │ │ │ │ │          (0 or 7 is Sunday, or MON-SUN)
 │ │ │ │ │ │
 *  *  *  *  *  *

比如:

“0 0 * * * *” = 每天 00:00。
"*/10 * * * * *" = 每 10 秒。
“0 0 8-10 * * *” = 每天 8、9 和 10 个小时。
"0 0 6,19 * * *" = 每天早上 6:00 和晚上 7:00。
“0 0/30 8-10 * * *” = 每天 8:00、8:30、9:00、9:30、10:00 和 10:30。
"0 0 9-17 * * MON-FRI" = 工作日 9 到 5
“0 0 0 25 12 ?” = 圣诞节午夜
"0 0 0 L * *" = 每个月的午夜
"0 0 0 L-3 * *" = 每月第三天到最后一天午夜
"0 0 0 1W * *" = 每月第一个工作日午夜
"0 0 0 LW * *" = 每月最后一个工作日的午夜
"0 0 0 * * 5L" = 每月最后一个星期五的午夜
"0 0 0 * * THUL" = 每月最后一个星期四的午夜
"0 0 0 ? * 5#2" = 每月第二个星期五的午夜
"0 0 0 ? * MON#1" = 每月第一个星期一的午夜

在ladybugflow中配置cron表达式

在流程编辑器中,将流程的首节点的启动类型设置成Timer,然后输入cron表达式,如下图所示

点击更新,更新json,

将json字符串拷贝到工程里,

启动工程,如下:

运行结果

[I]2022/08/09 18:23:35.547  main:ladybugflow.properties in root path not found, use default configuration
[I]2022/08/09 18:23:35.558 main:NodePool started.
[I]2022/08/09 18:23:35.559 main:Ready queue consumer thread started.
[I]2022/08/09 18:23:35.610 main:Complete queue consumer thread started.
[I]2022/08/09 18:23:36.230 [your flow id][283eb8de-e12c-4de0-9484-51da87538032] main:json:
{"flowId":"your flow id","nodes":[{"id":"1","label":"start","readyCheck":0,"startType":3,"startCron":"0 0/1 * * * ?"},{"id":"a1a38c2e-0e05-4c68-bd49-f12aea070876","label":"查询用户信息","readyCheck":0,"startType":0,"startCron":null},{"id":"1a90a997-4390-470a-ae7c-626a725438d2","label":"查询酒店信息","readyCheck":0,"startType":0,"startCron":null},{"id":"52289e99-363d-4453-8077-ca8bdc6d35bf","label":"下单","readyCheck":0,"startType":0,"startCron":null},{"id":"16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2","label":"下单成功","readyCheck":0,"startType":0,"startCron":null}],"edges":[{"id":"1","from":"1","to":"2","condition":null,"arrows":"to"},{"id":"b3ad7ab3-8fb6-4527-8cae-6845e03da3e4","from":"1","to":"a1a38c2e-0e05-4c68-bd49-f12aea070876","condition":null,"arrows":"to"},{"id":"001375c7-19e7-436b-bbcd-68e36c8f23b7","from":"1","to":"1a90a997-4390-470a-ae7c-626a725438d2","condition":null,"arrows":"to"},{"id":"dd830043-c7a7-4c71-b91c-10c007b7b19c","from":"1a90a997-4390-470a-ae7c-626a725438d2","to":"52289e99-363d-4453-8077-ca8bdc6d35bf","condition":null,"arrows":"to"},{"id":"21c2c69d-0050-4eca-8283-5a2bcbdc6c37","from":"52289e99-363d-4453-8077-ca8bdc6d35bf","to":"16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2","condition":null,"arrows":"to"},{"id":"19f2f329-8163-4dc6-a353-800df79d18a6","from":"a1a38c2e-0e05-4c68-bd49-f12aea070876","to":"52289e99-363d-4453-8077-ca8bdc6d35bf","condition":null,"arrows":"to"}]}
[your flow id] next execute time:2022/08/09 18:24:00
[I]2022/08/09 18:24:00.027 [your flow id][cef59351-e2b5-4e81-b85a-5c751e35d8c4] ThreadPoolTaskScheduler-1:json:
{"flowId":"your flow id","nodes":[{"id":"1","label":"start","readyCheck":0,"startType":3,"startCron":"0 0/1 * * * ?"},{"id":"a1a38c2e-0e05-4c68-bd49-f12aea070876","label":"查询用户信息","readyCheck":0,"startType":0,"startCron":null},{"id":"1a90a997-4390-470a-ae7c-626a725438d2","label":"查询酒店信息","readyCheck":0,"startType":0,"startCron":null},{"id":"52289e99-363d-4453-8077-ca8bdc6d35bf","label":"下单","readyCheck":0,"startType":0,"startCron":null},{"id":"16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2","label":"下单成功","readyCheck":0,"startType":0,"startCron":null}],"edges":[{"id":"1","from":"1","to":"2","condition":null,"arrows":"to"},{"id":"b3ad7ab3-8fb6-4527-8cae-6845e03da3e4","from":"1","to":"a1a38c2e-0e05-4c68-bd49-f12aea070876","condition":null,"arrows":"to"},{"id":"001375c7-19e7-436b-bbcd-68e36c8f23b7","from":"1","to":"1a90a997-4390-470a-ae7c-626a725438d2","condition":null,"arrows":"to"},{"id":"dd830043-c7a7-4c71-b91c-10c007b7b19c","from":"1a90a997-4390-470a-ae7c-626a725438d2","to":"52289e99-363d-4453-8077-ca8bdc6d35bf","condition":null,"arrows":"to"},{"id":"21c2c69d-0050-4eca-8283-5a2bcbdc6c37","from":"52289e99-363d-4453-8077-ca8bdc6d35bf","to":"16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2","condition":null,"arrows":"to"},{"id":"19f2f329-8163-4dc6-a353-800df79d18a6","from":"a1a38c2e-0e05-4c68-bd49-f12aea070876","to":"52289e99-363d-4453-8077-ca8bdc6d35bf","condition":null,"arrows":"to"}]}
[I]2022/08/09 18:24:00.032 [your flow id][cef59351-e2b5-4e81-b85a-5c751e35d8c4] pool-1-thread-1:execute node id:1
[I]2022/08/09 18:24:00.032 [your flow id][cef59351-e2b5-4e81-b85a-5c751e35d8c4] pool-1-thread-1:execute node name:start
启动开始 (模拟业务等待3秒)
启动结束
[I]2022/08/09 18:24:03.055 [your flow id][cef59351-e2b5-4e81-b85a-5c751e35d8c4] pool-1-thread-1:execute node id:a1a38c2e-0e05-4c68-bd49-f12aea070876
[I]2022/08/09 18:24:03.055 [your flow id][cef59351-e2b5-4e81-b85a-5c751e35d8c4] pool-1-thread-1:execute node name:查询用户信息
[I]2022/08/09 18:24:03.055 [your flow id][cef59351-e2b5-4e81-b85a-5c751e35d8c4] pool-1-thread-2:execute node id:1a90a997-4390-470a-ae7c-626a725438d2
查询用户信息开始 (模拟业务等待3秒)
[I]2022/08/09 18:24:03.055 [your flow id][cef59351-e2b5-4e81-b85a-5c751e35d8c4] pool-1-thread-2:execute node name:查询酒店信息
查询酒店信息开始 (模拟业务等待3秒)
查询用户信息结束
查询酒店信息结束
[I]2022/08/09 18:24:06.071 [your flow id][cef59351-e2b5-4e81-b85a-5c751e35d8c4] pool-1-thread-2:execute node id:52289e99-363d-4453-8077-ca8bdc6d35bf
[I]2022/08/09 18:24:06.071 [your flow id][cef59351-e2b5-4e81-b85a-5c751e35d8c4] pool-1-thread-2:execute node name:下单
下单开始 (模拟业务等待3秒)
下单结束
[I]2022/08/09 18:24:09.074 [your flow id][cef59351-e2b5-4e81-b85a-5c751e35d8c4] pool-1-thread-2:execute node id:16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2
[I]2022/08/09 18:24:09.074 [your flow id][cef59351-e2b5-4e81-b85a-5c751e35d8c4] pool-1-thread-2:execute node name:下单成功
下单成功开始 (模拟业务等待3秒)
下单成功结束
[I]2022/08/09 18:24:12.083 [your flow id][cef59351-e2b5-4e81-b85a-5c751e35d8c4] Thread-1:Complete success.
[I]2022/08/09 18:24:12.087 [your flow id][cef59351-e2b5-4e81-b85a-5c751e35d8c4] Thread-1:json:
{"nodes":[{"id": "1","label": "start" ,"color": "#36AE7C"},{"id": "a1a38c2e-0e05-4c68-bd49-f12aea070876","label": "查询用户信息" ,"color": "#36AE7C"},{"id": "1a90a997-4390-470a-ae7c-626a725438d2","label": "查询酒店信息" ,"color": "#36AE7C"},{"id": "52289e99-363d-4453-8077-ca8bdc6d35bf","label": "下单" ,"color": "#36AE7C"},{"id": "16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2","label": "下单成功" ,"color": "#36AE7C"}],"edges":[{"id": "1","from": "1","to": "2","arrows": "to"},{"id": "b3ad7ab3-8fb6-4527-8cae-6845e03da3e4","from": "1","to": "a1a38c2e-0e05-4c68-bd49-f12aea070876","arrows": "to"},{"id": "001375c7-19e7-436b-bbcd-68e36c8f23b7","from": "1","to": "1a90a997-4390-470a-ae7c-626a725438d2","arrows": "to"},{"id": "dd830043-c7a7-4c71-b91c-10c007b7b19c","from": "1a90a997-4390-470a-ae7c-626a725438d2","to": "52289e99-363d-4453-8077-ca8bdc6d35bf","arrows": "to"},{"id": "21c2c69d-0050-4eca-8283-5a2bcbdc6c37","from": "52289e99-363d-4453-8077-ca8bdc6d35bf","to": "16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2","arrows": "to"},{"id": "19f2f329-8163-4dc6-a353-800df79d18a6","from": "a1a38c2e-0e05-4c68-bd49-f12aea070876","to": "52289e99-363d-4453-8077-ca8bdc6d35bf","arrows": "to"}]}

定时任务的实现方式

ladybugflow采用spring的scheduling来实现对cron表达式的解析,

流程启动后,如果首节点类型是Timer,则会根据cron表达式来向ThreadPoolTaskScheduler中注册一个定时任务。

taskScheduler.schedule(new Runnable() {
@Override
public void run() { try {
FlowRunner flowRunnerNew = flowRunner.getClass().newInstance(); String flowPath = flowRunnerNew.getClass().getName(); if (StringUtil.isNotEmpty(jsonFileName)) {
flowPath = jsonFileName.replace(".json", "");
} FlowEntity flow = createHistory(flowPath);
String flowId = flow.flowEntity.getFlowId();
String historyId = flow.flowEntity.getHistoryId(); FlowContainer.flowRunnerMap.put(flowId + "," + historyId, flowRunnerNew); HistoryNodeEntity firstNode = FlowContainer.selectNodeByKey(flowId, nodeId, historyId);
firstNode.setNodeStatus(NodeStatus.READY);
startNode(flowId, historyId, nodeId); } catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} }
}, new CronTrigger(cron));

Spring-Batch与ladybugflow的集成

1.新建一个Spring-Batch工程,并且导入ladybugflow。

build.gradle

plugins {
id 'org.springframework.boot' version '2.7.2'
id 'io.spring.dependency-management' version '1.0.12.RELEASE'
id 'java'
} group = 'nobuglady'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8' repositories {
mavenCentral()
} dependencies {
implementation 'org.springframework.boot:spring-boot-starter-batch'
implementation 'io.github.nobuglady:ladybugflow:0.0.8'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
} tasks.named('test') {
useJUnitPlatform()
}

将生成的Json文件和对应的Flow.java文件放在同一个目录下:

Flow1.java

package io.github.nobuglady.network.demo.batch.ladybugflow;

import org.springframework.stereotype.Component;

import io.github.nobuglady.network.fw.FlowRunner;
import io.github.nobuglady.network.fw.annotation.Node; /**
*
* @author NoBugLady
*
*/
@Component
public class Flow1 extends FlowRunner { private String result; public String getResult() {
return result;
} @Node(label = "start")
public void processStart() throws InterruptedException {
System.out.println("启动开始 (模拟业务等待3秒)");
Thread.sleep(3000);
System.out.println("启动结束");
} @Node(label = "查询用户信息")
public void processSearchUser() throws InterruptedException {
System.out.println("查询用户信息开始 (模拟业务等待3秒)");
Thread.sleep(3000);
System.out.println("查询用户信息结束");
} @Node(label = "查询酒店信息")
public void processSearchHotel() throws InterruptedException {
System.out.println("查询酒店信息开始 (模拟业务等待3秒)");
Thread.sleep(3000);
System.out.println("查询酒店信息结束");
} @Node(label = "下单")
public void processOrder() throws InterruptedException {
System.out.println("下单开始 (模拟业务等待3秒)");
Thread.sleep(3000);
System.out.println("下单结束");
} @Node(label = "下单成功")
public void processSuccess() throws InterruptedException {
System.out.println("下单成功开始 (模拟业务等待3秒)");
Thread.sleep(3000);
System.out.println("下单成功结束");
result = "success";
}
}

Flow1.json

{
"flowId": "your flow id",
"nodes": [
{
"id": "1",
"label": "start",
"readyCheck": 0,
"startType": 3,
"startCron": "0 0/1 * * * ?"
},
{
"id": "a1a38c2e-0e05-4c68-bd49-f12aea070876",
"label": "查询用户信息",
"readyCheck": 0
},
{
"id": "1a90a997-4390-470a-ae7c-626a725438d2",
"label": "查询酒店信息",
"readyCheck": 0
},
{
"id": "52289e99-363d-4453-8077-ca8bdc6d35bf",
"label": "下单",
"readyCheck": 0
},
{
"id": "16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2",
"label": "下单成功",
"readyCheck": 0
}
],
"edges": [
{
"id": "1",
"from": "1",
"to": "2",
"arrows": "to"
},
{
"id": "b3ad7ab3-8fb6-4527-8cae-6845e03da3e4",
"from": "1",
"to": "a1a38c2e-0e05-4c68-bd49-f12aea070876",
"arrows": "to"
},
{
"id": "001375c7-19e7-436b-bbcd-68e36c8f23b7",
"from": "1",
"to": "1a90a997-4390-470a-ae7c-626a725438d2",
"arrows": "to"
},
{
"id": "dd830043-c7a7-4c71-b91c-10c007b7b19c",
"from": "1a90a997-4390-470a-ae7c-626a725438d2",
"to": "52289e99-363d-4453-8077-ca8bdc6d35bf",
"arrows": "to"
},
{
"id": "21c2c69d-0050-4eca-8283-5a2bcbdc6c37",
"from": "52289e99-363d-4453-8077-ca8bdc6d35bf",
"to": "16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2",
"arrows": "to"
},
{
"id": "19f2f329-8163-4dc6-a353-800df79d18a6",
"from": "a1a38c2e-0e05-4c68-bd49-f12aea070876",
"to": "52289e99-363d-4453-8077-ca8bdc6d35bf",
"arrows": "to"
}
]
}

在启动的类中启动流程

LadybugflowDemoBatchApplication.java

package io.github.nobuglady.network.demo.batch;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import io.github.nobuglady.network.demo.batch.ladybugflow.Flow1; @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class LadybugflowDemoBatchApplication implements ApplicationRunner { @Autowired
private Flow1 flow1; public static void main(String[] args) {
SpringApplication.run(LadybugflowDemoBatchApplication.class, args);
} @Override
public void run(ApplicationArguments args) throws Exception { flow1.startFlow(true);
System.out.println(flow1.getResult()); } }

运行结果:


. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.7.2) 2022-08-09 18:21:04.166 INFO 3208 --- [ main] .n.n.d.b.LadybugflowDemoBatchApplication : No active profile set, falling back to 1 default profile: "default"
2022-08-09 18:21:04.769 INFO 3208 --- [ main] .n.n.d.b.LadybugflowDemoBatchApplication : Started LadybugflowDemoBatchApplication in 0.907 seconds (JVM running for 1.78)
[I]2022/08/09 18:21:04.772 main:ladybugflow.properties in root path not found, use default configuration
[I]2022/08/09 18:21:04.773 main:NodePool started.
[I]2022/08/09 18:21:04.774 main:Ready queue consumer thread started.
[I]2022/08/09 18:21:04.779 main:Complete queue consumer thread started.
[I]2022/08/09 18:21:04.961 [your flow id][a31bb47d-be78-491d-9ecd-7d59302b565a] main:json:
{"flowId":"your flow id","nodes":[{"id":"1","label":"start","readyCheck":0,"startType":3,"startCron":"0 0/1 * * * ?"},{"id":"a1a38c2e-0e05-4c68-bd49-f12aea070876","label":"查询用户信息","readyCheck":0,"startType":0,"startCron":null},{"id":"1a90a997-4390-470a-ae7c-626a725438d2","label":"查询酒店信息","readyCheck":0,"startType":0,"startCron":null},{"id":"52289e99-363d-4453-8077-ca8bdc6d35bf","label":"下单","readyCheck":0,"startType":0,"startCron":null},{"id":"16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2","label":"下单成功","readyCheck":0,"startType":0,"startCron":null}],"edges":[{"id":"1","from":"1","to":"2","condition":null,"arrows":"to"},{"id":"b3ad7ab3-8fb6-4527-8cae-6845e03da3e4","from":"1","to":"a1a38c2e-0e05-4c68-bd49-f12aea070876","condition":null,"arrows":"to"},{"id":"001375c7-19e7-436b-bbcd-68e36c8f23b7","from":"1","to":"1a90a997-4390-470a-ae7c-626a725438d2","condition":null,"arrows":"to"},{"id":"dd830043-c7a7-4c71-b91c-10c007b7b19c","from":"1a90a997-4390-470a-ae7c-626a725438d2","to":"52289e99-363d-4453-8077-ca8bdc6d35bf","condition":null,"arrows":"to"},{"id":"21c2c69d-0050-4eca-8283-5a2bcbdc6c37","from":"52289e99-363d-4453-8077-ca8bdc6d35bf","to":"16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2","condition":null,"arrows":"to"},{"id":"19f2f329-8163-4dc6-a353-800df79d18a6","from":"a1a38c2e-0e05-4c68-bd49-f12aea070876","to":"52289e99-363d-4453-8077-ca8bdc6d35bf","condition":null,"arrows":"to"}]}
[your flow id] next execute time:2022/08/09 18:22:00
[I]2022/08/09 18:22:00.020 [your flow id][d343ba1a-a367-4f63-aaa4-32b1d31b5edb] ThreadPoolTaskScheduler-1:json:
{"flowId":"your flow id","nodes":[{"id":"1","label":"start","readyCheck":0,"startType":3,"startCron":"0 0/1 * * * ?"},{"id":"a1a38c2e-0e05-4c68-bd49-f12aea070876","label":"查询用户信息","readyCheck":0,"startType":0,"startCron":null},{"id":"1a90a997-4390-470a-ae7c-626a725438d2","label":"查询酒店信息","readyCheck":0,"startType":0,"startCron":null},{"id":"52289e99-363d-4453-8077-ca8bdc6d35bf","label":"下单","readyCheck":0,"startType":0,"startCron":null},{"id":"16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2","label":"下单成功","readyCheck":0,"startType":0,"startCron":null}],"edges":[{"id":"1","from":"1","to":"2","condition":null,"arrows":"to"},{"id":"b3ad7ab3-8fb6-4527-8cae-6845e03da3e4","from":"1","to":"a1a38c2e-0e05-4c68-bd49-f12aea070876","condition":null,"arrows":"to"},{"id":"001375c7-19e7-436b-bbcd-68e36c8f23b7","from":"1","to":"1a90a997-4390-470a-ae7c-626a725438d2","condition":null,"arrows":"to"},{"id":"dd830043-c7a7-4c71-b91c-10c007b7b19c","from":"1a90a997-4390-470a-ae7c-626a725438d2","to":"52289e99-363d-4453-8077-ca8bdc6d35bf","condition":null,"arrows":"to"},{"id":"21c2c69d-0050-4eca-8283-5a2bcbdc6c37","from":"52289e99-363d-4453-8077-ca8bdc6d35bf","to":"16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2","condition":null,"arrows":"to"},{"id":"19f2f329-8163-4dc6-a353-800df79d18a6","from":"a1a38c2e-0e05-4c68-bd49-f12aea070876","to":"52289e99-363d-4453-8077-ca8bdc6d35bf","condition":null,"arrows":"to"}]}
[I]2022/08/09 18:22:00.023 [your flow id][d343ba1a-a367-4f63-aaa4-32b1d31b5edb] pool-1-thread-1:execute node id:1
[I]2022/08/09 18:22:00.024 [your flow id][d343ba1a-a367-4f63-aaa4-32b1d31b5edb] pool-1-thread-1:execute node name:start
启动开始 (模拟业务等待3秒)
启动结束
[I]2022/08/09 18:22:03.028 [your flow id][d343ba1a-a367-4f63-aaa4-32b1d31b5edb] pool-1-thread-1:execute node id:a1a38c2e-0e05-4c68-bd49-f12aea070876
[I]2022/08/09 18:22:03.028 [your flow id][d343ba1a-a367-4f63-aaa4-32b1d31b5edb] pool-1-thread-1:execute node name:查询用户信息
查询用户信息开始 (模拟业务等待3秒)
[I]2022/08/09 18:22:03.028 [your flow id][d343ba1a-a367-4f63-aaa4-32b1d31b5edb] pool-1-thread-2:execute node id:1a90a997-4390-470a-ae7c-626a725438d2
[I]2022/08/09 18:22:03.028 [your flow id][d343ba1a-a367-4f63-aaa4-32b1d31b5edb] pool-1-thread-2:execute node name:查询酒店信息
查询酒店信息开始 (模拟业务等待3秒)
查询酒店信息结束
查询用户信息结束
[I]2022/08/09 18:22:06.034 [your flow id][d343ba1a-a367-4f63-aaa4-32b1d31b5edb] pool-1-thread-1:execute node id:52289e99-363d-4453-8077-ca8bdc6d35bf
[I]2022/08/09 18:22:06.034 [your flow id][d343ba1a-a367-4f63-aaa4-32b1d31b5edb] pool-1-thread-1:execute node name:下单
下单开始 (模拟业务等待3秒)
下单结束
[I]2022/08/09 18:22:09.043 [your flow id][d343ba1a-a367-4f63-aaa4-32b1d31b5edb] pool-1-thread-1:execute node id:16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2
[I]2022/08/09 18:22:09.044 [your flow id][d343ba1a-a367-4f63-aaa4-32b1d31b5edb] pool-1-thread-1:execute node name:下单成功
下单成功开始 (模拟业务等待3秒)
下单成功结束
[I]2022/08/09 18:22:12.053 [your flow id][d343ba1a-a367-4f63-aaa4-32b1d31b5edb] Thread-4:Complete success.
[I]2022/08/09 18:22:12.055 [your flow id][d343ba1a-a367-4f63-aaa4-32b1d31b5edb] Thread-4:json:
{"nodes":[{"id": "1","label": "start" ,"color": "#36AE7C"},{"id": "a1a38c2e-0e05-4c68-bd49-f12aea070876","label": "查询用户信息" ,"color": "#36AE7C"},{"id": "1a90a997-4390-470a-ae7c-626a725438d2","label": "查询酒店信息" ,"color": "#36AE7C"},{"id": "52289e99-363d-4453-8077-ca8bdc6d35bf","label": "下单" ,"color": "#36AE7C"},{"id": "16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2","label": "下单成功" ,"color": "#36AE7C"}],"edges":[{"id": "1","from": "1","to": "2","arrows": "to"},{"id": "b3ad7ab3-8fb6-4527-8cae-6845e03da3e4","from": "1","to": "a1a38c2e-0e05-4c68-bd49-f12aea070876","arrows": "to"},{"id": "001375c7-19e7-436b-bbcd-68e36c8f23b7","from": "1","to": "1a90a997-4390-470a-ae7c-626a725438d2","arrows": "to"},{"id": "dd830043-c7a7-4c71-b91c-10c007b7b19c","from": "1a90a997-4390-470a-ae7c-626a725438d2","to": "52289e99-363d-4453-8077-ca8bdc6d35bf","arrows": "to"},{"id": "21c2c69d-0050-4eca-8283-5a2bcbdc6c37","from": "52289e99-363d-4453-8077-ca8bdc6d35bf","to": "16422cbb-ccb0-4fe2-952b-e3ad5c3acbb2","arrows": "to"},{"id": "19f2f329-8163-4dc6-a353-800df79d18a6","from": "a1a38c2e-0e05-4c68-bd49-f12aea070876","to": "52289e99-363d-4453-8077-ca8bdc6d35bf","arrows": "to"}]}

感谢您阅读到这里。

最后

源码:https://github.com/nobuglady/ladybugflow

本章实例源码:https://github.com/nobuglady/ladybugflow-demo/tree/main/ladybugflow-demo-batch

业务可视化-让你的流程图"Run"起来(6.定时任务&Spring-Batch的集成)的更多相关文章

  1. 业务可视化-让你的流程图"Run"起来(2.问题与改进)

    前言 首先,感谢大家对上一篇文章[业务可视化-让你的流程图"Run"起来]的支持. 分享一下近期我对这个项目的一些改进. 问题&改进 问题1: 流程运行开始后,异步执行,无 ...

  2. 业务可视化-让你的流程图"Run"起来(3.分支选择&跨语言分布式运行节点)

    前言 首先,感谢大家对上一篇文章[业务可视化-让你的流程图"Run"起来(2.问题与改进)]的支持. 分享一下近期我对这个项目的一些改进. 1. 增加了分支选择工程,可以根据节点的 ...

  3. 业务可视化-让你的流程图"Run"起来(4.实际业务场景测试)

    前言 首先,感谢大家对上一篇文章[业务可视化-让你的流程图"Run"起来(3.分支选择&跨语言分布式运行节点)]的支持. 下面我以实际业务场景为例,来介绍一下ladybug ...

  4. 业务可视化-让你的流程图"Run"起来

    前言 最近在研究业务可视化的问题,在日常的工作中,流程图和代码往往是分开管理的. 一个被维护多次的系统,到最后流程图和代码是否匹配这个都很难说. 于是一直有一个想法,让程序直接读流程图,根据流程图的配 ...

  5. 业务流程可视化-让你的流程图"Run"起来(7.运行状态持久化&轻量工作流支持)

    前言 感谢大家阅读本项目系列文章和对项目的支持.分享一下我对这个项目的新的改进. 之前项目做到了流程设计可视化和流程运行结果可视化. 本期发布的版本中实现了中间的运行过程的实时可视化,和流程状态持久化 ...

  6. 11张流程图帮你搞定 Spring Bean 生命周期

    在网上已经有跟多Bean的生命周期的博客,但是很多都是基于比较老的版本了,最近吧整个流程化成了一个流程图.待会儿使用流程图,说明以及代码的形式来说明整个声明周期的流程.注意因为代码比较多,这里的流程图 ...

  7. 阶段3 2.Spring_07.银行转账案例_5 编写业务层和持久层事务控制代码并配置spring的ioc

    Service中就需要用到 TransactionManager中的方法.提供set方法等着spring注入 这里面所有的操作都可以加上事物控制 其他的方法都是相同的操作 这里没有返回结果 转账的方法 ...

  8. Spring Cloud ZooKeeper集成Feign的坑3,程序Run模式运行没事,Debug模式下报错

    请更新Spring Cloud的版本: <dependency> <groupId>org.springframework.cloud</groupId> < ...

  9. Spring Boot整合Spring Batch

    引言 Spring Batch是处理大量数据操作的一个框架,主要用来读取大量数据,然后进行一定的处理后输出指定的形式.比如我们可以将csv文件中的数据(数据量几百万甚至几千万都是没问题的)批处理插入保 ...

随机推荐

  1. css3常用动画

    //有道云笔记链接 http://note.youdao.com/s/72qbBVyv  

  2. React简单教程-4.1-hook

    前言 虽然我们简单感受了一下 useState 的用法,但我想你还是对 React 里的 hook 迷迷糊糊的.本文我们将明确下 React 的概念. HOOK 前生今世 在我示例中,写的 React ...

  3. Windows环境下安装RabbitMQ

    本地安装RabbitMQ安装注意事项: Erlang与RabbitMQ,安装路径都应不含空格符. Erlang使用了环境变量HOMEDRIVE与HOMEPATH来访问配置文件.erlang.cooki ...

  4. 《SQL Server基础——SQL语句》

    SQL Server基础--SQL语句       一.创建和删除数据库: 1.创建数据库(默认化初始值) 格式: CREATE DATABASE 数据库名称 例如: CREATE DATABASE ...

  5. 第六章、PXE高效网络装机、Kickstart无人值守安装

    目录 一.部署PXE远程安装服务 1PXE定义 2PXE服务优点 3搭建网络体系前提条件 4PXE实现过程讲解 二.搭建PXE远程安装服务器 三.Kickstart无人值守安装 一.部署PXE远程安装 ...

  6. NLog自定义Target之MQTT

    NLog是.Net中最流行的日志记录开源项目(之一),它灵活.免费.开源 官方支持文件.网络(Tcp.Udp).数据库.控制台等输出 社区支持Elastic.Seq等日志平台输出 实时日志需求 在工业 ...

  7. 《ECMAScript 6 入门》【三、字符串的扩展】(持续更新中……)

    前言: 本篇介绍 ES6 对字符串的改造和增强.一.字符的 Unicode 表示法 字符的 Unicode 码点必须在\u0000~\uFFFF之间,\uxxxx形式表示一个字符,其中xxxx表示字符 ...

  8. react的setState到底是同步还是异步

    在介绍这个问题之前,我们先来看一下一个例子: state = {number:1};componentDidMount(){this.setState({number:3})console.log(t ...

  9. 设计模式-策略模式前端应用校验vue写法

    1.定义:定义一系列算法,把它们一个个封装起来,并且它们可以相互替换 2.实际应用:减少if else的使用,在有多种算法相似的情况下,使用 if-else 所带来的复杂和难以维护,提高维护和可读性, ...

  10. MC34063降压电路

    MC34063芯片由温度自动补偿功能的基准电压发生器.比较器.占空比可控振荡器. 触发器和大电流输出开关电路等组成,具有功能齐全.价格低廉.体积小.效率高.仅需少量外部元器件等优点,其主要特性如表所示 ...