初始化
This commit is contained in:
42
easyflow-modules/easyflow-module-job/pom.xml
Normal file
42
easyflow-modules/easyflow-module-job/pom.xml
Normal file
@@ -0,0 +1,42 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
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>
|
||||
<parent>
|
||||
<groupId>tech.easyflow</groupId>
|
||||
<artifactId>easyflow-modules</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>easyflow-module-job</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-quartz</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<artifactId>mybatis-flex-spring-boot3-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>tech.easyflow</groupId>
|
||||
<artifactId>easyflow-common-base</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>tech.easyflow</groupId>
|
||||
<artifactId>easyflow-common-satoken</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>tech.easyflow</groupId>
|
||||
<artifactId>easyflow-common-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>tech.easyflow</groupId>
|
||||
<artifactId>easyflow-module-log</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>tech.easyflow</groupId>
|
||||
<artifactId>easyflow-module-ai</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,13 @@
|
||||
package tech.easyflow.job.config;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@MapperScan("tech.easyflow.job.mapper")
|
||||
public class JobModuleConfig {
|
||||
|
||||
public JobModuleConfig() {
|
||||
System.out.println("启用模块 >>>>>>>>>> module-job");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package tech.easyflow.job.entity;
|
||||
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import tech.easyflow.job.entity.base.SysJobBase;
|
||||
|
||||
|
||||
/**
|
||||
* 系统任务表 实体类。
|
||||
*
|
||||
* @author xiaoma
|
||||
* @since 2025-05-20
|
||||
*/
|
||||
@Table(value = "tb_sys_job", comment = "系统任务表")
|
||||
public class SysJob extends SysJobBase {
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package tech.easyflow.job.entity;
|
||||
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import tech.easyflow.job.entity.base.SysJobLogBase;
|
||||
|
||||
|
||||
/**
|
||||
* 系统任务日志 实体类。
|
||||
*
|
||||
* @author xiaoma
|
||||
* @since 2025-05-20
|
||||
*/
|
||||
@Table(value = "tb_sys_job_log", comment = "系统任务日志")
|
||||
public class SysJobLog extends SysJobLogBase {
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
package tech.easyflow.job.entity.base;
|
||||
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import com.mybatisflex.annotation.Id;
|
||||
import com.mybatisflex.annotation.KeyType;
|
||||
import com.mybatisflex.core.handler.FastjsonTypeHandler;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import tech.easyflow.common.entity.DateEntity;
|
||||
|
||||
|
||||
public class SysJobBase extends DateEntity implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@Id(keyType = KeyType.Generator, value = "snowFlakeId", comment = "主键")
|
||||
private BigInteger id;
|
||||
|
||||
/**
|
||||
* 部门ID
|
||||
*/
|
||||
@Column(comment = "部门ID")
|
||||
private BigInteger deptId;
|
||||
|
||||
/**
|
||||
* 租户ID
|
||||
*/
|
||||
@Column(tenantId = true, comment = "租户ID")
|
||||
private BigInteger tenantId;
|
||||
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
@Column(comment = "任务名称")
|
||||
private String jobName;
|
||||
|
||||
/**
|
||||
* 任务类型
|
||||
*/
|
||||
@Column(comment = "任务类型")
|
||||
private Integer jobType;
|
||||
|
||||
/**
|
||||
* 任务参数
|
||||
*/
|
||||
@Column(typeHandler = FastjsonTypeHandler.class, comment = "任务参数")
|
||||
private Map<String, Object> jobParams;
|
||||
|
||||
/**
|
||||
* cron表达式
|
||||
*/
|
||||
@Column(comment = "cron表达式")
|
||||
private String cronExpression;
|
||||
|
||||
/**
|
||||
* 是否并发执行
|
||||
*/
|
||||
@Column(comment = "是否并发执行")
|
||||
private Integer allowConcurrent;
|
||||
|
||||
/**
|
||||
* 错过策略
|
||||
*/
|
||||
@Column(comment = "错过策略")
|
||||
private Integer misfirePolicy;
|
||||
|
||||
/**
|
||||
* 其他配置
|
||||
*/
|
||||
@Column(typeHandler = FastjsonTypeHandler.class, comment = "其他配置")
|
||||
private Map<String, Object> options;
|
||||
|
||||
/**
|
||||
* 数据状态
|
||||
*/
|
||||
@Column(comment = "数据状态")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@Column(comment = "创建时间")
|
||||
private Date created;
|
||||
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
@Column(comment = "创建者")
|
||||
private BigInteger createdBy;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
@Column(comment = "修改时间")
|
||||
private Date modified;
|
||||
|
||||
/**
|
||||
* 修改者
|
||||
*/
|
||||
@Column(comment = "修改者")
|
||||
private BigInteger modifiedBy;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@Column(comment = "备注")
|
||||
private String remark;
|
||||
|
||||
public BigInteger getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(BigInteger id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public BigInteger getDeptId() {
|
||||
return deptId;
|
||||
}
|
||||
|
||||
public void setDeptId(BigInteger deptId) {
|
||||
this.deptId = deptId;
|
||||
}
|
||||
|
||||
public BigInteger getTenantId() {
|
||||
return tenantId;
|
||||
}
|
||||
|
||||
public void setTenantId(BigInteger tenantId) {
|
||||
this.tenantId = tenantId;
|
||||
}
|
||||
|
||||
public String getJobName() {
|
||||
return jobName;
|
||||
}
|
||||
|
||||
public void setJobName(String jobName) {
|
||||
this.jobName = jobName;
|
||||
}
|
||||
|
||||
public Integer getJobType() {
|
||||
return jobType;
|
||||
}
|
||||
|
||||
public void setJobType(Integer jobType) {
|
||||
this.jobType = jobType;
|
||||
}
|
||||
|
||||
public Map<String, Object> getJobParams() {
|
||||
return jobParams;
|
||||
}
|
||||
|
||||
public void setJobParams(Map<String, Object> jobParams) {
|
||||
this.jobParams = jobParams;
|
||||
}
|
||||
|
||||
public String getCronExpression() {
|
||||
return cronExpression;
|
||||
}
|
||||
|
||||
public void setCronExpression(String cronExpression) {
|
||||
this.cronExpression = cronExpression;
|
||||
}
|
||||
|
||||
public Integer getAllowConcurrent() {
|
||||
return allowConcurrent;
|
||||
}
|
||||
|
||||
public void setAllowConcurrent(Integer allowConcurrent) {
|
||||
this.allowConcurrent = allowConcurrent;
|
||||
}
|
||||
|
||||
public Integer getMisfirePolicy() {
|
||||
return misfirePolicy;
|
||||
}
|
||||
|
||||
public void setMisfirePolicy(Integer misfirePolicy) {
|
||||
this.misfirePolicy = misfirePolicy;
|
||||
}
|
||||
|
||||
public Map<String, Object> getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
public void setOptions(Map<String, Object> options) {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
public Integer getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Integer status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public Date getCreated() {
|
||||
return created;
|
||||
}
|
||||
|
||||
public void setCreated(Date created) {
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
public BigInteger getCreatedBy() {
|
||||
return createdBy;
|
||||
}
|
||||
|
||||
public void setCreatedBy(BigInteger createdBy) {
|
||||
this.createdBy = createdBy;
|
||||
}
|
||||
|
||||
public Date getModified() {
|
||||
return modified;
|
||||
}
|
||||
|
||||
public void setModified(Date modified) {
|
||||
this.modified = modified;
|
||||
}
|
||||
|
||||
public BigInteger getModifiedBy() {
|
||||
return modifiedBy;
|
||||
}
|
||||
|
||||
public void setModifiedBy(BigInteger modifiedBy) {
|
||||
this.modifiedBy = modifiedBy;
|
||||
}
|
||||
|
||||
public String getRemark() {
|
||||
return remark;
|
||||
}
|
||||
|
||||
public void setRemark(String remark) {
|
||||
this.remark = remark;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
package tech.easyflow.job.entity.base;
|
||||
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import com.mybatisflex.annotation.Id;
|
||||
import com.mybatisflex.annotation.KeyType;
|
||||
import com.mybatisflex.core.handler.FastjsonTypeHandler;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class SysJobLogBase implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@Id(keyType = KeyType.Generator, value = "snowFlakeId", comment = "主键")
|
||||
private BigInteger id;
|
||||
|
||||
/**
|
||||
* 任务ID
|
||||
*/
|
||||
@Column(comment = "任务ID")
|
||||
private BigInteger jobId;
|
||||
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
@Column(comment = "任务名称")
|
||||
private String jobName;
|
||||
|
||||
/**
|
||||
* 任务参数
|
||||
*/
|
||||
@Column(typeHandler = FastjsonTypeHandler.class, comment = "任务参数")
|
||||
private Map<String, Object> jobParams;
|
||||
|
||||
/**
|
||||
* 执行结果
|
||||
*/
|
||||
@Column(comment = "执行结果")
|
||||
private String jobResult;
|
||||
|
||||
/**
|
||||
* 错误信息
|
||||
*/
|
||||
@Column(comment = "错误信息")
|
||||
private String errorInfo;
|
||||
|
||||
/**
|
||||
* 数据状态
|
||||
*/
|
||||
@Column(comment = "数据状态")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 开始时间
|
||||
*/
|
||||
@Column(comment = "开始时间")
|
||||
private Date startTime;
|
||||
|
||||
/**
|
||||
* 结束时间
|
||||
*/
|
||||
@Column(comment = "结束时间")
|
||||
private Date endTime;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@Column(comment = "创建时间")
|
||||
private Date created;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@Column(comment = "备注")
|
||||
private String remark;
|
||||
|
||||
public BigInteger getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(BigInteger id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public BigInteger getJobId() {
|
||||
return jobId;
|
||||
}
|
||||
|
||||
public void setJobId(BigInteger jobId) {
|
||||
this.jobId = jobId;
|
||||
}
|
||||
|
||||
public String getJobName() {
|
||||
return jobName;
|
||||
}
|
||||
|
||||
public void setJobName(String jobName) {
|
||||
this.jobName = jobName;
|
||||
}
|
||||
|
||||
public Map<String, Object> getJobParams() {
|
||||
return jobParams;
|
||||
}
|
||||
|
||||
public void setJobParams(Map<String, Object> jobParams) {
|
||||
this.jobParams = jobParams;
|
||||
}
|
||||
|
||||
public String getJobResult() {
|
||||
return jobResult;
|
||||
}
|
||||
|
||||
public void setJobResult(String jobResult) {
|
||||
this.jobResult = jobResult;
|
||||
}
|
||||
|
||||
public String getErrorInfo() {
|
||||
return errorInfo;
|
||||
}
|
||||
|
||||
public void setErrorInfo(String errorInfo) {
|
||||
this.errorInfo = errorInfo;
|
||||
}
|
||||
|
||||
public Integer getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Integer status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public Date getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
public void setStartTime(Date startTime) {
|
||||
this.startTime = startTime;
|
||||
}
|
||||
|
||||
public Date getEndTime() {
|
||||
return endTime;
|
||||
}
|
||||
|
||||
public void setEndTime(Date endTime) {
|
||||
this.endTime = endTime;
|
||||
}
|
||||
|
||||
public Date getCreated() {
|
||||
return created;
|
||||
}
|
||||
|
||||
public void setCreated(Date created) {
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
public String getRemark() {
|
||||
return remark;
|
||||
}
|
||||
|
||||
public void setRemark(String remark) {
|
||||
this.remark = remark;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package tech.easyflow.job.job;
|
||||
|
||||
import cn.hutool.core.exceptions.ExceptionUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import org.quartz.Job;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import tech.easyflow.common.constant.enums.EnumJobExecStatus;
|
||||
import tech.easyflow.common.util.SpringContextUtil;
|
||||
import tech.easyflow.job.entity.SysJob;
|
||||
import tech.easyflow.job.entity.SysJobLog;
|
||||
import tech.easyflow.job.service.SysJobLogService;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public abstract class BaseQuartzJob implements Job {
|
||||
|
||||
protected Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private final static ThreadLocal<Date> TIME_RECORD = new ThreadLocal<>();
|
||||
|
||||
@Override
|
||||
public void execute(JobExecutionContext ctx) throws JobExecutionException {
|
||||
|
||||
SysJob job = (SysJob) ctx.getMergedJobDataMap().get(JobConstant.JOB_MAP_BEAN_NAME);
|
||||
|
||||
try {
|
||||
beforeExecute(ctx, job);
|
||||
Object result = doExecute(ctx, job);
|
||||
afterExecute(ctx, job, result, null);
|
||||
} catch (Exception e) {
|
||||
log.error("quartz 任务执行报错:", e);
|
||||
afterExecute(ctx, job, null, e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void beforeExecute(JobExecutionContext ctx, SysJob job) {
|
||||
TIME_RECORD.set(new Date());
|
||||
}
|
||||
|
||||
protected void afterExecute(JobExecutionContext ctx, SysJob job, Object result, Exception e) {
|
||||
Date startTime = TIME_RECORD.get();
|
||||
TIME_RECORD.remove();
|
||||
Date endTime = new Date();
|
||||
|
||||
SysJobLog sysJobLog = new SysJobLog();
|
||||
sysJobLog.setJobId(job.getId());
|
||||
sysJobLog.setJobName(job.getJobName());
|
||||
sysJobLog.setStatus(EnumJobExecStatus.SUCCESS.getCode());
|
||||
sysJobLog.setJobParams(job.getJobParams());
|
||||
if (result != null) {
|
||||
sysJobLog.setJobResult(JSON.toJSONString(result));
|
||||
}
|
||||
if (e != null) {
|
||||
String message = ExceptionUtil.getRootCauseMessage(e);
|
||||
if (message.length() > 1000) {
|
||||
message = message.substring(0, 1000);
|
||||
}
|
||||
sysJobLog.setErrorInfo(message);
|
||||
sysJobLog.setStatus(EnumJobExecStatus.FAIL.getCode());
|
||||
}
|
||||
sysJobLog.setStartTime(startTime);
|
||||
sysJobLog.setEndTime(endTime);
|
||||
sysJobLog.setCreated(new Date());
|
||||
SysJobLogService service = SpringContextUtil.getBean(SysJobLogService.class);
|
||||
service.save(sysJobLog);
|
||||
}
|
||||
|
||||
protected abstract Object doExecute(JobExecutionContext ctx, SysJob job) throws Exception;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package tech.easyflow.job.job;
|
||||
|
||||
public interface JobConstant {
|
||||
|
||||
String JOB_GROUP = "easyflow";
|
||||
String JOB_MAP_BEAN_NAME = "jobMapBean";
|
||||
|
||||
String BEAN_METHOD_KEY = "beanMethod";
|
||||
String JAVA_METHOD_KEY = "javaMethod";
|
||||
String WORKFLOW_KEY = "workflowId";
|
||||
String WORKFLOW_PARAMS_KEY = "workflowParams";
|
||||
String ACCOUNT_ID = "accountId";
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package tech.easyflow.job.job;
|
||||
|
||||
import org.quartz.JobExecutionContext;
|
||||
import tech.easyflow.job.entity.SysJob;
|
||||
import tech.easyflow.job.util.JobUtil;
|
||||
|
||||
/**
|
||||
* 可并发执行
|
||||
*/
|
||||
public class QuartzJob extends BaseQuartzJob {
|
||||
|
||||
@Override
|
||||
protected Object doExecute(JobExecutionContext ctx, SysJob job) throws Exception {
|
||||
return JobUtil.execute(job);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package tech.easyflow.job.job;
|
||||
|
||||
import org.quartz.DisallowConcurrentExecution;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import tech.easyflow.job.entity.SysJob;
|
||||
import tech.easyflow.job.util.JobUtil;
|
||||
|
||||
/**
|
||||
* 禁止并发执行
|
||||
*/
|
||||
@DisallowConcurrentExecution
|
||||
public class QuartzJobNoConcurrent extends BaseQuartzJob {
|
||||
|
||||
@Override
|
||||
protected Object doExecute(JobExecutionContext ctx, SysJob job) throws Exception {
|
||||
return JobUtil.execute(job);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package tech.easyflow.job.mapper;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import tech.easyflow.job.entity.SysJobLog;
|
||||
|
||||
/**
|
||||
* 系统任务日志 映射层。
|
||||
*
|
||||
* @author xiaoma
|
||||
* @since 2025-05-20
|
||||
*/
|
||||
public interface SysJobLogMapper extends BaseMapper<SysJobLog> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package tech.easyflow.job.mapper;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import tech.easyflow.job.entity.SysJob;
|
||||
|
||||
/**
|
||||
* 系统任务表 映射层。
|
||||
*
|
||||
* @author xiaoma
|
||||
* @since 2025-05-20
|
||||
*/
|
||||
public interface SysJobMapper extends BaseMapper<SysJob> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package tech.easyflow.job.service;
|
||||
|
||||
import com.mybatisflex.core.service.IService;
|
||||
import tech.easyflow.job.entity.SysJobLog;
|
||||
|
||||
/**
|
||||
* 系统任务日志 服务层。
|
||||
*
|
||||
* @author xiaoma
|
||||
* @since 2025-05-20
|
||||
*/
|
||||
public interface SysJobLogService extends IService<SysJobLog> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package tech.easyflow.job.service;
|
||||
|
||||
import com.mybatisflex.core.service.IService;
|
||||
import tech.easyflow.job.entity.SysJob;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 系统任务表 服务层。
|
||||
*
|
||||
* @author xiaoma
|
||||
* @since 2025-05-20
|
||||
*/
|
||||
public interface SysJobService extends IService<SysJob> {
|
||||
|
||||
void test();
|
||||
|
||||
void testParam(String a, Boolean b, Integer c);
|
||||
|
||||
void addJob(SysJob job);
|
||||
|
||||
void deleteJob(Collection<Serializable> ids);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package tech.easyflow.job.service.impl;
|
||||
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
import tech.easyflow.job.entity.SysJobLog;
|
||||
import tech.easyflow.job.mapper.SysJobLogMapper;
|
||||
import tech.easyflow.job.service.SysJobLogService;
|
||||
|
||||
/**
|
||||
* 系统任务日志 服务层实现。
|
||||
*
|
||||
* @author xiaoma
|
||||
* @since 2025-05-20
|
||||
*/
|
||||
@Service
|
||||
public class SysJobLogServiceImpl extends ServiceImpl<SysJobLogMapper, SysJobLog> implements SysJobLogService {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package tech.easyflow.job.service.impl;
|
||||
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
import org.quartz.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
import tech.easyflow.common.constant.enums.EnumMisfirePolicy;
|
||||
import tech.easyflow.job.entity.SysJob;
|
||||
import tech.easyflow.job.job.JobConstant;
|
||||
import tech.easyflow.job.job.QuartzJob;
|
||||
import tech.easyflow.job.job.QuartzJobNoConcurrent;
|
||||
import tech.easyflow.job.mapper.SysJobMapper;
|
||||
import tech.easyflow.job.service.SysJobService;
|
||||
import tech.easyflow.job.util.JobUtil;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 系统任务表 服务层实现。
|
||||
*
|
||||
* @author xiaoma
|
||||
* @since 2025-05-20
|
||||
*/
|
||||
@Service
|
||||
public class SysJobServiceImpl extends ServiceImpl<SysJobMapper, SysJob> implements SysJobService {
|
||||
|
||||
protected Logger log = LoggerFactory.getLogger(SysJobServiceImpl.class);
|
||||
|
||||
@Resource
|
||||
private Scheduler scheduler;
|
||||
|
||||
@Override
|
||||
public void test() {
|
||||
System.out.println("java bean 动态执行");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testParam(String a, Boolean b, Integer c) {
|
||||
System.out.println("动态执行spring bean,执行参数:" + "a="+ a + ",b="+ b + ",c="+ c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addJob(SysJob job) {
|
||||
Integer allowConcurrent = job.getAllowConcurrent();
|
||||
Class<? extends Job> jobClass = allowConcurrent == 1 ? QuartzJob.class : QuartzJobNoConcurrent.class;
|
||||
|
||||
JobDetail jobDetail = JobBuilder.newJob(jobClass)
|
||||
.withIdentity(JobUtil.getJobKey(job))
|
||||
.build();
|
||||
|
||||
jobDetail.getJobDataMap().put(JobConstant.JOB_MAP_BEAN_NAME, job);
|
||||
|
||||
CronScheduleBuilder cron = CronScheduleBuilder.cronSchedule(job.getCronExpression());
|
||||
|
||||
Integer misfirePolicy = job.getMisfirePolicy();
|
||||
if (EnumMisfirePolicy.MISFIRE_DO_NOTHING.getCode() == misfirePolicy) {
|
||||
cron.withMisfireHandlingInstructionDoNothing();
|
||||
}
|
||||
if (EnumMisfirePolicy.MISFIRE_FIRE_AND_PROCEED.getCode() == misfirePolicy) {
|
||||
cron.withMisfireHandlingInstructionFireAndProceed();
|
||||
}
|
||||
if (EnumMisfirePolicy.MISFIRE_IGNORE_MISFIRES.getCode() == misfirePolicy) {
|
||||
cron.withMisfireHandlingInstructionIgnoreMisfires();
|
||||
}
|
||||
|
||||
Trigger trigger = TriggerBuilder.newTrigger()
|
||||
.withIdentity(JobUtil.getTriggerKey(job))
|
||||
.withSchedule(cron).build();
|
||||
|
||||
try {
|
||||
scheduler.scheduleJob(jobDetail,trigger);
|
||||
} catch (SchedulerException e) {
|
||||
log.error("启动任务失败:", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteJob(Collection<Serializable> ids) {
|
||||
try {
|
||||
for (Serializable id : ids) {
|
||||
SysJob sysJob = new SysJob();
|
||||
sysJob.setId(new BigInteger(id.toString()));
|
||||
scheduler.deleteJob(JobUtil.getJobKey(sysJob));
|
||||
}
|
||||
} catch (SchedulerException e) {
|
||||
log.error("删除任务失败:", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
package tech.easyflow.job.util;
|
||||
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.mybatisflex.core.tenant.TenantManager;
|
||||
import com.easyagents.flow.core.chain.ChainDefinition;
|
||||
import com.easyagents.flow.core.chain.runtime.ChainExecutor;
|
||||
import org.quartz.JobKey;
|
||||
import org.quartz.TriggerKey;
|
||||
import tech.easyflow.common.constant.Constants;
|
||||
import tech.easyflow.common.constant.enums.EnumJobType;
|
||||
import tech.easyflow.common.satoken.util.SaTokenUtil;
|
||||
import tech.easyflow.common.util.SpringContextUtil;
|
||||
import tech.easyflow.job.entity.SysJob;
|
||||
import tech.easyflow.job.job.JobConstant;
|
||||
import tech.easyflow.system.entity.SysAccount;
|
||||
import tech.easyflow.system.service.SysAccountService;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
public class JobUtil {
|
||||
|
||||
/**
|
||||
* sysJobService.test()
|
||||
*/
|
||||
public static Object execSpringBean(SysJob job) {
|
||||
Map<String, Object> jobParams = job.getJobParams();
|
||||
if (jobParams != null) {
|
||||
String beanMethod = jobParams.get(JobConstant.BEAN_METHOD_KEY).toString();
|
||||
String[] strings = StrUtil.subBefore(beanMethod, "(", false).split("\\.");
|
||||
Object bean = SpringContextUtil.getBean(strings[0]);
|
||||
String param = StrUtil.subBetween(beanMethod, "(", ")");
|
||||
try {
|
||||
// 调用方法并传递参数
|
||||
return invoke(bean, strings[1], getParams(param));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("执行 beanMethod 报错:", e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* tech.easyflow.job.util.JobUtil.execTest("test",1,0.52D,100L)
|
||||
* @param job
|
||||
*/
|
||||
public static Object execJavaClass(SysJob job) {
|
||||
Map<String, Object> jobParams = job.getJobParams();
|
||||
if (jobParams != null) {
|
||||
try {
|
||||
String javaMethod = jobParams.get(JobConstant.JAVA_METHOD_KEY).toString();
|
||||
String before = StrUtil.subBefore(javaMethod, "(", false);
|
||||
String[] strings = before.split("\\.");
|
||||
String className = String.join(".", Arrays.copyOf(strings, strings.length - 1));
|
||||
String methodName = strings[strings.length - 1];
|
||||
String param = StrUtil.subBetween(javaMethod, "(", ")");
|
||||
Object obj = Class.forName(className).getDeclaredConstructor().newInstance();;
|
||||
return invoke(obj, methodName, getParams(param));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("执行 javaMethod 报错: ",e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Object execWorkFlow(SysJob job) {
|
||||
Map<String, Object> jobParams = job.getJobParams();
|
||||
JSONObject obj = new JSONObject(jobParams);
|
||||
String workflowId = obj.getString(JobConstant.WORKFLOW_KEY);
|
||||
JSONObject params = obj.getJSONObject(JobConstant.WORKFLOW_PARAMS_KEY);
|
||||
|
||||
ChainExecutor executor = SpringContextUtil.getBean(ChainExecutor.class);
|
||||
Object accountId = obj.get(JobConstant.ACCOUNT_ID);
|
||||
SysAccountService accountService = SpringContextUtil.getBean(SysAccountService.class);
|
||||
|
||||
try {
|
||||
TenantManager.ignoreTenantCondition();
|
||||
|
||||
ChainDefinition chain = executor.getDefinitionRepository().getChainDefinitionById(workflowId);
|
||||
if (chain != null) {
|
||||
if (accountId != null) {
|
||||
// 设置的归属者
|
||||
SysAccount account = accountService.getById(accountId.toString());
|
||||
if (account != null) {
|
||||
params.put(Constants.LOGIN_USER_KEY, SaTokenUtil.getLoginAccount());
|
||||
}
|
||||
}
|
||||
return executor.execute(workflowId, params);
|
||||
}
|
||||
} finally {
|
||||
TenantManager.restoreTenantCondition();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Object execute(SysJob job) {
|
||||
Object res = null;
|
||||
Integer jobType = job.getJobType();
|
||||
if (EnumJobType.TINY_FLOW.getCode() == jobType) {
|
||||
res = execWorkFlow(job);
|
||||
}
|
||||
if (EnumJobType.SPRING_BEAN.getCode() == jobType) {
|
||||
res = execSpringBean(job);
|
||||
}
|
||||
if (EnumJobType.JAVA_CLASS.getCode() == jobType) {
|
||||
res = execJavaClass(job);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public void execTest(String a,Integer b,Double c,Long d) {
|
||||
System.out.println("动态执行方法,执行参数:" + "a="+ a + ",b="+ b + ",c="+ c + ",d="+ d);
|
||||
}
|
||||
|
||||
private static Object[] getParams(String param) {
|
||||
if (StrUtil.isEmpty(param)) {
|
||||
return new Object[]{new Class<?>[]{}, new Object[]{}};
|
||||
}
|
||||
String[] splits = param.split(",");
|
||||
Object[] res = new Object[2];
|
||||
Object[] params = new Object[splits.length];
|
||||
Class<?>[] paramTypes = new Class[splits.length];
|
||||
for (int i = 0; i < splits.length; i++) {
|
||||
String split = splits[i].trim();
|
||||
if (split.startsWith("\"")) {
|
||||
params[i] = split.substring(1, split.length() - 1);
|
||||
paramTypes[i] = String.class;
|
||||
} else if ("true".equals(split) || "false".equals(split)) {
|
||||
params[i] = Boolean.valueOf(split);
|
||||
paramTypes[i] = Boolean.class;
|
||||
} else if (split.endsWith("L")) {
|
||||
params[i] = Long.valueOf(split.substring(0, split.length() - 1));
|
||||
paramTypes[i] = Long.class;
|
||||
} else if (split.endsWith("D")) {
|
||||
params[i] = Double.valueOf(split.substring(0, split.length() - 1));
|
||||
paramTypes[i] = Double.class;
|
||||
} else if (split.endsWith("F")) {
|
||||
params[i] = Float.valueOf(split.substring(0, split.length() - 1));
|
||||
paramTypes[i] = Float.class;
|
||||
} else {
|
||||
params[i] = Integer.valueOf(split);
|
||||
paramTypes[i] = Integer.class;
|
||||
}
|
||||
}
|
||||
res[0] = paramTypes;
|
||||
res[1] = params;
|
||||
return res;
|
||||
}
|
||||
|
||||
private static Object invoke(Object bean, String methodName, Object[] params) throws Exception {
|
||||
Object[] args = (Object[]) params[1];
|
||||
if (ArrayUtil.isEmpty(params[1])) {
|
||||
Method method = bean.getClass().getDeclaredMethod(methodName);
|
||||
return method.invoke(bean);
|
||||
} else {
|
||||
Method method = bean.getClass().getDeclaredMethod(methodName, (Class<?>[]) params[0]);
|
||||
return method.invoke(bean, args);
|
||||
}
|
||||
}
|
||||
|
||||
public static JobKey getJobKey(SysJob job) {
|
||||
return JobKey.jobKey(job.getId().toString(), JobConstant.JOB_GROUP);
|
||||
}
|
||||
|
||||
public static TriggerKey getTriggerKey(SysJob job) {
|
||||
return TriggerKey.triggerKey(job.getId().toString(), JobConstant.JOB_GROUP);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user