- 组件化优化,移除对 spring 的依赖:非spring应用选用 "XxlJobExecutor" 、spring应用选用 "XxlJobSpringExecutor" 作为执行器组件;
- 任务RollingLog展示逻辑优化,修复超时任务无法查看的问题;
This commit is contained in:
parent
af6c46743f
commit
df2b9f7e0c
|
@ -1328,12 +1328,14 @@ Tips: 历史版本(V1.3.x)目前已经Release至稳定版本, 进入维护阶段
|
|||
- 2、底层通讯组件迁移至 xxl-rpc;
|
||||
- 3、IP获取逻辑优化,优先遍历网卡来获取可用IP;
|
||||
- 4、任务新增的API服务接口返回任务ID,方便调用方实用;
|
||||
- 5、新增无框架执行器Sample示例项目 "xxl-job-executor-sample-frameless"。不依赖第三方框架,只需main方法即可启动运行执行器;
|
||||
- 6、[迭代中]任务状态与quartz解耦,降低quartz调度压力,仅NORMAL状态任务绑定quartz;
|
||||
- 7、[迭代中]新增任务默认运行状态,任务更新时运行状态保持不变;
|
||||
- 8、[迭代中]原生提供通用命令行任务Handler(Bean任务,"CommandJobHandler");业务方只需要提供命令行即可,可执行任意命令;
|
||||
- 9、[迭代中]cron在线生成工具,如 "cronboot/cron.qqe2";
|
||||
- 10、[迭代中]docker镜像,并且推送docker镜像到中央仓库,更进一步实现产品开箱即用;
|
||||
- 5、组件化优化,移除对 spring 的依赖:非spring应用选用 "XxlJobExecutor" 、spring应用选用 "XxlJobSpringExecutor" 作为执行器组件;
|
||||
- 6、新增无框架执行器Sample示例项目 "xxl-job-executor-sample-frameless"。不依赖第三方框架,只需main方法即可启动运行执行器;
|
||||
- 7、任务RollingLog展示逻辑优化,修复超时任务无法查看的问题;
|
||||
- 8、[迭代中]任务状态与quartz解耦,降低quartz调度压力,仅NORMAL状态任务绑定quartz;
|
||||
- 9、[迭代中]新增任务默认运行状态,任务更新时运行状态保持不变;
|
||||
- 10、[迭代中]原生提供通用命令行任务Handler(Bean任务,"CommandJobHandler");业务方只需要提供命令行即可,可执行任意命令;
|
||||
- 11、[迭代中]cron在线生成工具,如 "cronboot/cron.qqe2";
|
||||
- 12、[迭代中]docker镜像,并且推送docker镜像到中央仓库,更进一步实现产品开箱即用;
|
||||
|
||||
|
||||
### TODO LIST
|
||||
|
|
|
@ -13,6 +13,7 @@ import com.xxl.job.core.biz.model.ReturnT;
|
|||
import com.xxl.job.core.biz.model.TriggerParam;
|
||||
import com.xxl.job.core.enums.ExecutorBlockStrategyEnum;
|
||||
import com.xxl.rpc.util.IpUtil;
|
||||
import com.xxl.rpc.util.ThrowableUtil;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -190,7 +191,7 @@ public class XxlJobTrigger {
|
|||
runResult = executorBiz.run(triggerParam);
|
||||
} catch (Exception e) {
|
||||
logger.error(">>>>>>>>>>> xxl-job trigger error, please check if the executor[{}] is running.", address, e);
|
||||
runResult = new ReturnT<String>(ReturnT.FAIL_CODE, ""+e );
|
||||
runResult = new ReturnT<String>(ReturnT.FAIL_CODE, ThrowableUtil.toString(e));
|
||||
}
|
||||
|
||||
StringBuffer runResultSB = new StringBuffer(I18nUtil.getString("jobconf_trigger_run") + ":");
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
$(function() {
|
||||
|
||||
// trigger fail, end
|
||||
if (triggerCode != 200) {
|
||||
if ( !(triggerCode == 200 || handleCode != 0) ) {
|
||||
$('#logConsoleRunning').hide();
|
||||
$('#logConsole').append('<span style="color: red;">'+ I18n.joblog_rolling_log_triggerfail +'</span>');
|
||||
return;
|
||||
|
|
|
@ -179,7 +179,7 @@ $(function() {
|
|||
"render": function ( data, type, row ) {
|
||||
// better support expression or string, not function
|
||||
return function () {
|
||||
if (row.triggerCode == 200){
|
||||
if (row.triggerCode == 200 || row.handleCode != 0){
|
||||
var temp = '<a href="javascript:;" class="logDetail" _id="'+ row.id +'">'+ I18n.joblog_rolling_log +'</a>';
|
||||
if(row.handleCode == 0){
|
||||
temp += '<br><a href="javascript:;" class="logKill" _id="'+ row.id +'" style="color: red;" >'+ I18n.joblog_kill_log +'</a>';
|
||||
|
|
|
@ -36,13 +36,6 @@
|
|||
<version>${commons-exec.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- spring-context -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- jackson -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
|
@ -50,6 +43,14 @@
|
|||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- spring-context -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -4,7 +4,6 @@ import com.xxl.job.core.biz.AdminBiz;
|
|||
import com.xxl.job.core.biz.ExecutorBiz;
|
||||
import com.xxl.job.core.biz.impl.ExecutorBizImpl;
|
||||
import com.xxl.job.core.handler.IJobHandler;
|
||||
import com.xxl.job.core.handler.annotation.JobHandler;
|
||||
import com.xxl.job.core.log.XxlJobFileAppender;
|
||||
import com.xxl.job.core.thread.ExecutorRegistryThread;
|
||||
import com.xxl.job.core.thread.JobLogFileCleanThread;
|
||||
|
@ -21,9 +20,6 @@ import com.xxl.rpc.util.IpUtil;
|
|||
import com.xxl.rpc.util.NetUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
@ -31,7 +27,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
/**
|
||||
* Created by xuxueli on 2016/3/2 21:14.
|
||||
*/
|
||||
public class XxlJobExecutor implements ApplicationContextAware {
|
||||
public class XxlJobExecutor {
|
||||
private static final Logger logger = LoggerFactory.getLogger(XxlJobExecutor.class);
|
||||
|
||||
// ---------------------- param ----------------------
|
||||
|
@ -65,16 +61,6 @@ public class XxlJobExecutor implements ApplicationContextAware {
|
|||
this.logRetentionDays = logRetentionDays;
|
||||
}
|
||||
|
||||
// ---------------------- applicationContext ----------------------
|
||||
private static ApplicationContext applicationContext;
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
public static ApplicationContext getApplicationContext() {
|
||||
return applicationContext;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------- start + stop ----------------------
|
||||
public void start() throws Exception {
|
||||
|
@ -82,12 +68,10 @@ public class XxlJobExecutor implements ApplicationContextAware {
|
|||
// init logpath
|
||||
XxlJobFileAppender.initLogPath(logPath);
|
||||
|
||||
// init JobHandler Repository
|
||||
initJobHandlerRepository(applicationContext);
|
||||
|
||||
// init admin-client
|
||||
initAdminBizList(adminAddresses, accessToken);
|
||||
|
||||
|
||||
// init JobLogFileCleanThread
|
||||
JobLogFileCleanThread.getInstance().start(logRetentionDays);
|
||||
|
||||
|
@ -108,6 +92,7 @@ public class XxlJobExecutor implements ApplicationContextAware {
|
|||
jobThreadRepository.clear();
|
||||
}
|
||||
|
||||
|
||||
// destory JobLogFileCleanThread
|
||||
JobLogFileCleanThread.getInstance().toStop();
|
||||
|
||||
|
@ -228,27 +213,6 @@ public class XxlJobExecutor implements ApplicationContextAware {
|
|||
public static IJobHandler loadJobHandler(String name){
|
||||
return jobHandlerRepository.get(name);
|
||||
}
|
||||
private void initJobHandlerRepository(ApplicationContext applicationContext){
|
||||
if (applicationContext == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// init job handler action
|
||||
Map<String, Object> serviceBeanMap = applicationContext.getBeansWithAnnotation(JobHandler.class);
|
||||
|
||||
if (serviceBeanMap!=null && serviceBeanMap.size()>0) {
|
||||
for (Object serviceBean : serviceBeanMap.values()) {
|
||||
if (serviceBean instanceof IJobHandler){
|
||||
String name = serviceBean.getClass().getAnnotation(JobHandler.class).value();
|
||||
IJobHandler handler = (IJobHandler) serviceBean;
|
||||
if (loadJobHandler(name) != null) {
|
||||
throw new RuntimeException("xxl-job jobhandler naming conflicts.");
|
||||
}
|
||||
registJobHandler(name, handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---------------------- job thread repository ----------------------
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
package com.xxl.job.core.executor.impl;
|
||||
|
||||
import com.xxl.job.core.executor.XxlJobExecutor;
|
||||
import com.xxl.job.core.glue.GlueFactory;
|
||||
import com.xxl.job.core.handler.IJobHandler;
|
||||
import com.xxl.job.core.handler.annotation.JobHandler;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* xxl-job executor (for spring)
|
||||
*
|
||||
* @author xuxueli 2018-11-01 09:24:52
|
||||
*/
|
||||
public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationContextAware {
|
||||
|
||||
|
||||
@Override
|
||||
public void start() throws Exception {
|
||||
|
||||
// init JobHandler Repository
|
||||
initJobHandlerRepository(applicationContext);
|
||||
|
||||
// refresh GlueFactory
|
||||
GlueFactory.refreshInstance(1);
|
||||
|
||||
|
||||
// super start
|
||||
super.start();
|
||||
}
|
||||
|
||||
private void initJobHandlerRepository(ApplicationContext applicationContext){
|
||||
if (applicationContext == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// init job handler action
|
||||
Map<String, Object> serviceBeanMap = applicationContext.getBeansWithAnnotation(JobHandler.class);
|
||||
|
||||
if (serviceBeanMap!=null && serviceBeanMap.size()>0) {
|
||||
for (Object serviceBean : serviceBeanMap.values()) {
|
||||
if (serviceBean instanceof IJobHandler){
|
||||
String name = serviceBean.getClass().getAnnotation(JobHandler.class).value();
|
||||
IJobHandler handler = (IJobHandler) serviceBean;
|
||||
if (loadJobHandler(name) != null) {
|
||||
throw new RuntimeException("xxl-job jobhandler naming conflicts.");
|
||||
}
|
||||
registJobHandler(name, handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------- applicationContext ----------------------
|
||||
private static ApplicationContext applicationContext;
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
public static ApplicationContext getApplicationContext() {
|
||||
return applicationContext;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,90 +1,43 @@
|
|||
package com.xxl.job.core.glue;
|
||||
|
||||
import com.xxl.job.core.executor.XxlJobExecutor;
|
||||
import com.xxl.job.core.glue.impl.SpringGlueFactory;
|
||||
import com.xxl.job.core.handler.IJobHandler;
|
||||
import groovy.lang.GroovyClassLoader;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
/**
|
||||
* glue factory, product class/object by name
|
||||
*
|
||||
* @author xuxueli 2016-1-2 20:02:27
|
||||
*/
|
||||
public class GlueFactory {
|
||||
private static Logger logger = LoggerFactory.getLogger(GlueFactory.class);
|
||||
|
||||
|
||||
private static GlueFactory glueFactory = new GlueFactory();
|
||||
public static GlueFactory getInstance(){
|
||||
return glueFactory;
|
||||
}
|
||||
public static void refreshInstance(int type){
|
||||
if (type == 0) {
|
||||
glueFactory = new GlueFactory();
|
||||
} else if (type == 1) {
|
||||
glueFactory = new SpringGlueFactory();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* groovy class loader
|
||||
*/
|
||||
private GroovyClassLoader groovyClassLoader = new GroovyClassLoader();
|
||||
|
||||
// ----------------------------- spring support -----------------------------
|
||||
private static GlueFactory glueFactory = new GlueFactory();
|
||||
public static GlueFactory getInstance(){
|
||||
return glueFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* inject action of spring
|
||||
* @param instance
|
||||
* load new instance, prototype
|
||||
*
|
||||
* @param codeSource
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
private void injectService(Object instance){
|
||||
if (instance==null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Field[] fields = instance.getClass().getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
if (Modifier.isStatic(field.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Object fieldBean = null;
|
||||
// with bean-id, bean could be found by both @Resource and @Autowired, or bean could only be found by @Autowired
|
||||
if (AnnotationUtils.getAnnotation(field, Resource.class) != null) {
|
||||
try {
|
||||
Resource resource = AnnotationUtils.getAnnotation(field, Resource.class);
|
||||
if (resource.name()!=null && resource.name().length()>0){
|
||||
fieldBean = XxlJobExecutor.getApplicationContext().getBean(resource.name());
|
||||
} else {
|
||||
fieldBean = XxlJobExecutor.getApplicationContext().getBean(field.getName());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
if (fieldBean==null ) {
|
||||
fieldBean = XxlJobExecutor.getApplicationContext().getBean(field.getType());
|
||||
}
|
||||
} else if (AnnotationUtils.getAnnotation(field, Autowired.class) != null) {
|
||||
Qualifier qualifier = AnnotationUtils.getAnnotation(field, Qualifier.class);
|
||||
if (qualifier!=null && qualifier.value()!=null && qualifier.value().length()>0) {
|
||||
fieldBean = XxlJobExecutor.getApplicationContext().getBean(qualifier.value());
|
||||
} else {
|
||||
fieldBean = XxlJobExecutor.getApplicationContext().getBean(field.getType());
|
||||
}
|
||||
}
|
||||
|
||||
if (fieldBean!=null) {
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
field.set(instance, fieldBean);
|
||||
} catch (IllegalArgumentException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
} catch (IllegalAccessException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------- load instance -----------------------------
|
||||
// load new instance, prototype
|
||||
public IJobHandler loadNewInstance(String codeSource) throws Exception{
|
||||
if (codeSource!=null && codeSource.trim().length()>0) {
|
||||
Class<?> clazz = groovyClassLoader.parseClass(codeSource);
|
||||
|
@ -104,4 +57,13 @@ public class GlueFactory {
|
|||
throw new IllegalArgumentException(">>>>>>>>>>> xxl-glue, loadNewInstance error, instance is null");
|
||||
}
|
||||
|
||||
/**
|
||||
* inject service of bean field
|
||||
*
|
||||
* @param instance
|
||||
*/
|
||||
public void injectService(Object instance) {
|
||||
// do something
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
package com.xxl.job.core.glue.impl;
|
||||
|
||||
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
|
||||
import com.xxl.job.core.glue.GlueFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
/**
|
||||
* @author xuxueli 2018-11-01
|
||||
*/
|
||||
public class SpringGlueFactory extends GlueFactory {
|
||||
private static Logger logger = LoggerFactory.getLogger(SpringGlueFactory.class);
|
||||
|
||||
|
||||
/**
|
||||
* inject action of spring
|
||||
* @param instance
|
||||
*/
|
||||
@Override
|
||||
public void injectService(Object instance){
|
||||
if (instance==null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (XxlJobSpringExecutor.getApplicationContext() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Field[] fields = instance.getClass().getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
if (Modifier.isStatic(field.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Object fieldBean = null;
|
||||
// with bean-id, bean could be found by both @Resource and @Autowired, or bean could only be found by @Autowired
|
||||
|
||||
if (AnnotationUtils.getAnnotation(field, Resource.class) != null) {
|
||||
try {
|
||||
Resource resource = AnnotationUtils.getAnnotation(field, Resource.class);
|
||||
if (resource.name()!=null && resource.name().length()>0){
|
||||
fieldBean = XxlJobSpringExecutor.getApplicationContext().getBean(resource.name());
|
||||
} else {
|
||||
fieldBean = XxlJobSpringExecutor.getApplicationContext().getBean(field.getName());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
if (fieldBean==null ) {
|
||||
fieldBean = XxlJobSpringExecutor.getApplicationContext().getBean(field.getType());
|
||||
}
|
||||
} else if (AnnotationUtils.getAnnotation(field, Autowired.class) != null) {
|
||||
Qualifier qualifier = AnnotationUtils.getAnnotation(field, Qualifier.class);
|
||||
if (qualifier!=null && qualifier.value()!=null && qualifier.value().length()>0) {
|
||||
fieldBean = XxlJobSpringExecutor.getApplicationContext().getBean(qualifier.value());
|
||||
} else {
|
||||
fieldBean = XxlJobSpringExecutor.getApplicationContext().getBean(field.getType());
|
||||
}
|
||||
}
|
||||
|
||||
if (fieldBean!=null) {
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
field.set(instance, fieldBean);
|
||||
} catch (IllegalArgumentException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
} catch (IllegalAccessException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -22,7 +22,7 @@
|
|||
<context:component-scan base-package="com.xxl.job.executor.service.jobhandler" />
|
||||
|
||||
<!-- 配置02、执行器 -->
|
||||
<bean id="xxlJobExecutor" class="com.xxl.job.core.executor.XxlJobExecutor" init-method="start" destroy-method="destroy" >
|
||||
<bean id="xxlJobSpringExecutor" class="com.xxl.job.core.executor.impl.XxlJobSpringExecutor" init-method="start" destroy-method="destroy" >
|
||||
<!-- 执行器注册中心地址[选填],为空则关闭自动注册 -->
|
||||
<property name="adminAddresses" value="${xxl.job.admin.addresses}" />
|
||||
<!-- 执行器AppName[选填],为空则关闭自动注册 -->
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package com.xxl.job.executor.core.config;
|
||||
|
||||
import com.xxl.job.core.executor.XxlJobExecutor;
|
||||
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
@ -41,18 +41,18 @@ public class XxlJobConfig {
|
|||
|
||||
|
||||
@Bean(initMethod = "start", destroyMethod = "destroy")
|
||||
public XxlJobExecutor xxlJobExecutor() {
|
||||
public XxlJobSpringExecutor xxlJobExecutor() {
|
||||
logger.info(">>>>>>>>>>> xxl-job config init.");
|
||||
XxlJobExecutor xxlJobExecutor = new XxlJobExecutor();
|
||||
xxlJobExecutor.setAdminAddresses(adminAddresses);
|
||||
xxlJobExecutor.setAppName(appName);
|
||||
xxlJobExecutor.setIp(ip);
|
||||
xxlJobExecutor.setPort(port);
|
||||
xxlJobExecutor.setAccessToken(accessToken);
|
||||
xxlJobExecutor.setLogPath(logPath);
|
||||
xxlJobExecutor.setLogRetentionDays(logRetentionDays);
|
||||
XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
|
||||
xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
|
||||
xxlJobSpringExecutor.setAppName(appName);
|
||||
xxlJobSpringExecutor.setIp(ip);
|
||||
xxlJobSpringExecutor.setPort(port);
|
||||
xxlJobSpringExecutor.setAccessToken(accessToken);
|
||||
xxlJobSpringExecutor.setLogPath(logPath);
|
||||
xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
|
||||
|
||||
return xxlJobExecutor;
|
||||
return xxlJobSpringExecutor;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue