feat: 新增 solon 适配示例

This commit is contained in:
xieshuang 2024-10-26 14:25:13 +08:00
parent 09c6f6d833
commit 6a18a6ded8
15 changed files with 475 additions and 22 deletions

View File

@ -3,7 +3,7 @@ buildscript {
ext {
springBootVersion = "2.7.0"
mybatisPlusVersion = "3.5.7"
solonVersion = "2.7.2"
solonVersion = "3.0.1"
}
//

View File

@ -0,0 +1,10 @@
description "flowlong spring boot example"
dependencies {
implementation project(":flowlong-spring-boot-starter")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-jdbc")
implementation("com.baomidou:mybatis-plus-boot-starter")
implementation("mysql:mysql-connector-java")
}

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" ?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.noear</groupId>
<artifactId>solon-parent</artifactId>
<version>3.0.1</version>
<relativePath/>
</parent>
<artifactId>flowlong-solon-example</artifactId>
<dependencies>
<dependency>
<groupId>com.aizuda</groupId>
<artifactId>flowlong-solon-plugin</artifactId>
<version>1.0.4</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-solon-plugin</artifactId>
<version>3.5.9</version>
</dependency>
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon-web</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.7.1</version>
</dependency>
<!-- solon的logback日志实现 -->
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon-logging-logback</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon-scheduling-simple</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,18 @@
package com.aizuda.bpm.solon.example;
import org.noear.solon.Solon;
import org.noear.solon.annotation.SolonMain;
import org.noear.solon.scheduling.annotation.EnableScheduling;
@EnableScheduling
@SolonMain
public class FlowLongApplication {
/**
* 运行该模块注释根目录 build.gradle 文件 afterEvaluate 代码块
*/
public static void main(String[] args) {
Solon.start(FlowLongApplication.class, args, app -> {
});
}
}

View File

@ -0,0 +1,20 @@
package com.aizuda.bpm.solon.example.config;
import com.aizuda.bpm.engine.core.FlowCreator;
import com.aizuda.bpm.engine.core.enums.InstanceEventType;
import com.aizuda.bpm.engine.entity.FlwHisInstance;
import com.aizuda.bpm.engine.listener.InstanceListener;
import com.aizuda.bpm.engine.model.NodeModel;
import org.noear.solon.annotation.Component;
import java.util.function.Supplier;
@Component
public class EventInstanceListener implements InstanceListener {
@Override
public boolean notify(InstanceEventType eventType, Supplier<FlwHisInstance> supplier, NodeModel nodeModel, FlowCreator flowCreator) {
System.out.println("eventType:" + eventType + ",supplier:" + supplier + ",nodeModel:" + nodeModel + ",flowCreator:" + flowCreator);
return true;
}
}

View File

@ -0,0 +1,28 @@
package com.aizuda.bpm.solon.example.config;
import com.aizuda.bpm.engine.core.FlowCreator;
import com.aizuda.bpm.engine.core.enums.TaskEventType;
import com.aizuda.bpm.engine.entity.FlwTask;
import com.aizuda.bpm.engine.listener.TaskListener;
import com.aizuda.bpm.engine.model.NodeModel;
import org.noear.solon.annotation.Component;
import java.util.function.Supplier;
/**
* 同步监听任务事件需要注入该监听器有效
* <p>
* 不可以 EventTaskListener 同时使用
* </p>
*/
@Component
public class TestTaskListener implements TaskListener {
@Override
public boolean notify(TaskEventType eventType, Supplier<FlwTask> supplier, NodeModel nodeModel, FlowCreator flowCreator) {
System.err.println("当前执行任务 = " + supplier.get().getTaskName() +
" ,执行事件 = " + eventType.name() + ",创建人=" + flowCreator.getCreateBy());
return true;
}
}

View File

@ -0,0 +1,24 @@
package com.aizuda.bpm.solon.example.config;
import com.aizuda.bpm.engine.TaskReminder;
import com.aizuda.bpm.engine.core.FlowLongContext;
import com.aizuda.bpm.engine.entity.FlwTask;
import org.noear.solon.annotation.Component;
import org.noear.solon.scheduling.annotation.EnableScheduling;
import java.util.Date;
/**
* 注入自定义任务提醒处理类
* 注解 EnableScheduling 必须启动
*/
@Component
@EnableScheduling
public class TestTaskReminder implements TaskReminder {
@Override
public Date remind(FlowLongContext context, Long instanceId, FlwTask currentTask) {
System.out.println("测试提醒:" + instanceId);
return null;
}
}

View File

@ -0,0 +1,42 @@
package com.aizuda.bpm.solon.example.controller;
import com.aizuda.bpm.engine.FlowLongEngine;
import com.aizuda.bpm.engine.core.FlowCreator;
import com.aizuda.bpm.engine.entity.FlwInstance;
import lombok.AllArgsConstructor;
import org.noear.solon.annotation.Controller;
import org.noear.solon.annotation.Get;
import org.noear.solon.annotation.Mapping;
import java.util.HashMap;
import java.util.Map;
@Controller
@Mapping("/process")
@AllArgsConstructor
public class TestController {
protected static FlowCreator testCreator = FlowCreator.of("test001", "测试001");
protected FlowLongEngine flowLongEngine;
/**
* <a href="http://localhost:8000/process/deploy">流程部署</a>
*/
@Get
@Mapping("/deploy")
public Long deployByResource() {
return flowLongEngine.processService().deployByResource("process.json", testCreator, false);
}
/**
* <a href="http://localhost:8000/process/instance-start">启动流程实例</a>
*/
@Get
@Mapping("/instance-start")
public FlwInstance instanceStart() {
Map<String, Object> args = new HashMap<>();
args.put("day", 8);
args.put("assignee", "test001");
return flowLongEngine.startInstanceByProcessKey("process", null, testCreator, args).get();
}
}

View File

@ -0,0 +1,57 @@
server.port: 8000
server.request.maxBodySize: 1024mb
# 设定最大的上传文件大小
server.request.maxFileSize: 1024mb
solon.app:
name: flowlong-solon
# 参数注解校验时true 对每个参数都进行校验false 只要有一个参数校验失败就返回
solon:
validation:
validateAll: true
# 日志公共配置
solon.logging.appender:
console:
level: INFO # appender 设置为 TRACE 级别,后面的 logger 设置为 INFO 级别,这样就可以只输出 INFO 级别以上的日志,才能实现动态调整日志级别功能
pattern: "%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) %magenta(${PID:-}) --- %-15([%15.15thread]) %-56(%cyan(%-40.40logger{39}%L)) : %msg%n"
file:
name: "/home/logs/${solon.app.name}/${solon.app.name}.log"
level: INFO
pattern: "%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level ${PID:-} --- %-15([%15.15thread]) %-44(%-40.40logger{39}%L) : %msg%n"
maxFileSize: "20 MB" # 单个日志文件最大大小
maxHistory: "30" # 日志文件最大保留天数
cloud:
level: INFO
# 序列化公共配置
solon.serialization.json:
dateAsFormat: 'yyyy-MM-dd HH:mm:ss' #配置日期格式(默认输出为时间戳)
dateAsTimeZone: 'GMT+8' #配置时区
dateAsTicks: false #将date转为毫秒数和 dateAsFormat 二选一)
longAsString: true #将long型转为字符串输出 默认为false
boolAsInt: false #将bool型转为字符串输出 默认为false
nullStringAsEmpty: false
nullBoolAsFalse: false
nullNumberAsZero: false
nullArrayAsEmpty: false
nullAsWriteable: true #输出所有null值
enumAsName: true #枚举使用名字v2.2.1 后支持)
solon.dataSources:
flowlong!: #数据源(!结尾表示 typed=true
class: "com.zaxxer.hikari.HikariDataSource"
maxPoolSize: 60
schema: public
jdbcUrl: jdbc:postgresql://127.0.0.1:5436/flowlong
driverClassName: org.postgresql.Driver
username: postgres
password: qwer963.
# FlowLong Config
flowlong:
remind:
cron: "*/5 * * * * ?"
eventing:
task: true

View File

@ -0,0 +1,96 @@
{
"key": "process",
"name": "请假审批",
"nodeConfig": {
"nodeName": "发起人",
"nodeKey": "001",
"type": 0,
"nodeRoleList": [],
"childNode": {
"nodeName": "条件路由",
"nodeKey": "002",
"type": 4,
"conditionNodes": [
{
"nodeName": "长期",
"nodeKey": "0021",
"type": 3,
"priorityLevel": 1,
"conditionMode": 1,
"conditionList": [
[
{
"label": "请假天数",
"field": "day",
"operator": ">",
"value": "7"
}
]
],
"childNode": {
"nodeName": "领导审批",
"nodeKey": "0022",
"type": 1,
"setType": 1,
"nodeAssigneeList": [
{
"id": "test001",
"name": "何敏"
}
],
"nodeRoleList": [],
"examineLevel": 1,
"directorLevel": 1,
"selectMode": 1,
"termAuto": false,
"term": 0,
"termMode": 1,
"examineMode": 1,
"directorMode": 0
}
},
{
"nodeName": "短期",
"nodeKey": "0031",
"type": 3,
"priorityLevel": 2,
"conditionMode": 1,
"conditionList": [],
"childNode": {
"nodeName": "直接主管审批",
"nodeKey": "0032",
"type": 1,
"setType": 2,
"nodeAssigneeList": [
{
"id": "zg0001",
"name": "张三"
}
],
"nodeRoleList": [],
"examineLevel": 1,
"directorLevel": 1,
"selectMode": 1,
"termAuto": false,
"term": 0,
"termMode": 1,
"examineMode": 1,
"directorMode": 0
}
}
],
"childNode": {
"nodeName": "抄送人",
"nodeKey": "005",
"type": 2,
"userSelectFlag": true,
"nodeAssigneeList": [
{
"id": "test002",
"name": "何秀英"
}
]
}
}
}
}

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
@ -14,7 +14,7 @@
<description>flowLong mybatis-plus solon plugin</description>
<properties>
<solon.version>2.7.2</solon.version>
<solon.version>3.0.1</solon.version>
</properties>
<dependencies>
@ -30,7 +30,7 @@
</dependency>
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon.scheduling</artifactId>
<artifactId>solon-scheduling</artifactId>
<version>${solon.version}</version>
</dependency>
<dependency>

View File

@ -30,7 +30,7 @@ public class SolonExpression implements Expression {
if (expr.startsWith("#{")) {
expr = expr.substring(2, expr.length() - 2);
} else if (expr.startsWith("#")) {
expr = expr.substring(1, expr.length() - 2);
expr = expr.substring(1);
}
return (Boolean) AviatorEvaluator.execute(expr, args);
});

View File

@ -3,22 +3,45 @@
*/
package com.aizuda.bpm.solon.autoconfigure;
import com.aizuda.bpm.engine.*;
import com.aizuda.bpm.engine.Expression;
import com.aizuda.bpm.engine.FlowLongEngine;
import com.aizuda.bpm.engine.FlowLongScheduler;
import com.aizuda.bpm.engine.ProcessModelParser;
import com.aizuda.bpm.engine.ProcessService;
import com.aizuda.bpm.engine.QueryService;
import com.aizuda.bpm.engine.RuntimeService;
import com.aizuda.bpm.engine.TaskAccessStrategy;
import com.aizuda.bpm.engine.TaskActorProvider;
import com.aizuda.bpm.engine.TaskCreateInterceptor;
import com.aizuda.bpm.engine.TaskReminder;
import com.aizuda.bpm.engine.TaskService;
import com.aizuda.bpm.engine.TaskTrigger;
import com.aizuda.bpm.engine.cache.FlowCache;
import com.aizuda.bpm.engine.core.FlowLongContext;
import com.aizuda.bpm.engine.core.FlowLongEngineImpl;
import com.aizuda.bpm.engine.dao.*;
import com.aizuda.bpm.engine.dao.FlwExtInstanceDao;
import com.aizuda.bpm.engine.dao.FlwHisInstanceDao;
import com.aizuda.bpm.engine.dao.FlwHisTaskActorDao;
import com.aizuda.bpm.engine.dao.FlwHisTaskDao;
import com.aizuda.bpm.engine.dao.FlwInstanceDao;
import com.aizuda.bpm.engine.dao.FlwProcessDao;
import com.aizuda.bpm.engine.dao.FlwTaskActorDao;
import com.aizuda.bpm.engine.dao.FlwTaskDao;
import com.aizuda.bpm.engine.handler.ConditionNodeHandler;
import com.aizuda.bpm.engine.handler.CreateTaskHandler;
import com.aizuda.bpm.engine.handler.FlowJsonHandler;
import com.aizuda.bpm.engine.impl.*;
import com.aizuda.bpm.engine.impl.GeneralAccessStrategy;
import com.aizuda.bpm.engine.impl.GeneralTaskActorProvider;
import com.aizuda.bpm.engine.impl.ProcessServiceImpl;
import com.aizuda.bpm.engine.impl.QueryServiceImpl;
import com.aizuda.bpm.engine.impl.RuntimeServiceImpl;
import com.aizuda.bpm.engine.impl.TaskServiceImpl;
import com.aizuda.bpm.engine.listener.InstanceListener;
import com.aizuda.bpm.engine.listener.TaskListener;
import com.aizuda.bpm.engine.scheduling.JobLock;
import com.aizuda.bpm.engine.scheduling.LocalLock;
import com.aizuda.bpm.solon.adaptive.SolonExpression;
import com.aizuda.bpm.solon.adaptive.SolonFlowJsonHandler;
import com.aizuda.bpm.solon.adaptive.SolonScheduler;
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Condition;
import org.noear.solon.annotation.Configuration;
@ -144,7 +167,7 @@ public class FlowLongAutoConfiguration {
}
@Bean
public void scheduler(FlowLongContext flowLongContext,
public void scheduler(FlowLongEngine flowLongEngine,
FlowLongProperties properties,
@Inject(required = false) TaskReminder taskReminder,
JobLock jobLock,
@ -152,17 +175,15 @@ public class FlowLongAutoConfiguration {
if (taskReminder == null) {
return;
}
SolonScheduler scheduler = new SolonScheduler();
scheduler.setContext(flowLongContext);
scheduler.setRemindParam(properties.getRemind());
scheduler.setTaskReminder(taskReminder);
scheduler.setJobLock(jobLock);
FlowLongScheduler flowLongScheduler = new FlowLongScheduler() {
};
flowLongScheduler.setFlowLongEngine(flowLongEngine);
flowLongScheduler.setRemindParam(properties.getRemind());
flowLongScheduler.setJobLock(jobLock);
//注册 job不再需要返回了
jobManager.jobAdd("flowlong",
new ScheduledAnno().cron(scheduler.getRemindParam().getCron()), ctx -> {
scheduler.remind();
new ScheduledAnno().cron(flowLongScheduler.getRemindParam().getCron()), ctx -> {
flowLongScheduler.remind();
});
}

View File

@ -0,0 +1,82 @@
package com.aizuda.bpm.solon.autoconfigure;
import com.aizuda.bpm.engine.dao.FlwExtInstanceDao;
import com.aizuda.bpm.engine.dao.FlwHisInstanceDao;
import com.aizuda.bpm.engine.dao.FlwHisTaskActorDao;
import com.aizuda.bpm.engine.dao.FlwHisTaskDao;
import com.aizuda.bpm.engine.dao.FlwInstanceDao;
import com.aizuda.bpm.engine.dao.FlwProcessDao;
import com.aizuda.bpm.engine.dao.FlwTaskActorDao;
import com.aizuda.bpm.engine.dao.FlwTaskDao;
import com.aizuda.bpm.mybatisplus.impl.FlwExtInstanceDaoImpl;
import com.aizuda.bpm.mybatisplus.impl.FlwHisInstanceDaoImpl;
import com.aizuda.bpm.mybatisplus.impl.FlwHisTaskActorDaoImpl;
import com.aizuda.bpm.mybatisplus.impl.FlwHisTaskDaoImpl;
import com.aizuda.bpm.mybatisplus.impl.FlwInstanceDaoImpl;
import com.aizuda.bpm.mybatisplus.impl.FlwProcessDaoImpl;
import com.aizuda.bpm.mybatisplus.impl.FlwTaskActorDaoImpl;
import com.aizuda.bpm.mybatisplus.impl.FlwTaskDaoImpl;
import com.aizuda.bpm.mybatisplus.mapper.FlwExtInstanceMapper;
import com.aizuda.bpm.mybatisplus.mapper.FlwHisInstanceMapper;
import com.aizuda.bpm.mybatisplus.mapper.FlwHisTaskActorMapper;
import com.aizuda.bpm.mybatisplus.mapper.FlwHisTaskMapper;
import com.aizuda.bpm.mybatisplus.mapper.FlwInstanceMapper;
import com.aizuda.bpm.mybatisplus.mapper.FlwProcessMapper;
import com.aizuda.bpm.mybatisplus.mapper.FlwTaskActorMapper;
import com.aizuda.bpm.mybatisplus.mapper.FlwTaskMapper;
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Condition;
import org.noear.solon.annotation.Configuration;
@Configuration
public class FlowLongMybatisPlusConfiguration {
@Bean
@Condition(onMissingBean = FlwExtInstanceDao.class)
public FlwExtInstanceDao extInstanceDao(FlwExtInstanceMapper extInstanceMapper) {
return new FlwExtInstanceDaoImpl(extInstanceMapper);
}
@Bean
@Condition(onMissingBean = FlwHisInstanceDao.class)
public FlwHisInstanceDao hisInstanceDao(FlwHisInstanceMapper hisInstanceMapper) {
return new FlwHisInstanceDaoImpl(hisInstanceMapper);
}
@Bean
@Condition(onMissingBean = FlwHisTaskActorDao.class)
public FlwHisTaskActorDao hisTaskActorDao(FlwHisTaskActorMapper hisInstanceMapper) {
return new FlwHisTaskActorDaoImpl(hisInstanceMapper);
}
@Bean
@Condition(onMissingBean = FlwHisTaskDao.class)
public FlwHisTaskDao hisTaskDao(FlwHisTaskMapper hisTaskMapper) {
return new FlwHisTaskDaoImpl(hisTaskMapper);
}
@Bean
@Condition(onMissingBean = FlwInstanceDao.class)
public FlwInstanceDao instanceDao(FlwInstanceMapper instanceMapper) {
return new FlwInstanceDaoImpl(instanceMapper);
}
@Bean
@Condition(onMissingBean = FlwProcessDao.class)
public FlwProcessDao processDao(FlwProcessMapper processMapper) {
return new FlwProcessDaoImpl(processMapper);
}
@Bean
@Condition(onMissingBean = FlwTaskActorDao.class)
public FlwTaskActorDao taskActorDao(FlwTaskActorMapper taskActorMapper) {
return new FlwTaskActorDaoImpl(taskActorMapper);
}
@Bean
@Condition(onMissingBean = FlwTaskDao.class)
public FlwTaskDao taskDao(FlwTaskMapper taskMapper) {
return new FlwTaskDaoImpl(taskMapper);
}
}

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.aizuda</groupId>
@ -21,7 +21,7 @@
<spring-boot.version>2.7.0</spring-boot.version>
<mybatis.plus-version>3.5.7</mybatis.plus-version>
<mysql.version>8.0.32</mysql.version>
<solon.version>2.7.2</solon.version>
<solon.version>3.0.1</solon.version>
<maven-surefire-plugin.version>3.1.2</maven-surefire-plugin.version>
<maven-compiler-plugin.version>3.10.1</maven-compiler-plugin.version>
<lombok.version>1.18.30</lombok.version>