👉 這是一個或許對你有用的社群
《專案實戰(影片)》:從書中學,往事上“練” 《網際網路高頻面試題》:面朝簡歷學習,春暖花開 《架構 x 系統設計》:摧枯拉朽,掌控面試高頻場景題 《精進 Java 學習指南》:系統學習,網際網路主流技術棧 《必讀 Java 原始碼專欄》:知其然,知其所以然

👉這是一個或許對你有用的開源專案國產 Star 破 10w+ 的開源專案,前端包括管理後臺 + 微信小程式,後端支援單體和微服務架構。功能涵蓋 RBAC 許可權、SaaS 多租戶、資料許可權、商城、支付、工作流、大屏報表、微信公眾號、CRM 等等功能:
Boot 倉庫:https://gitee.com/zhijiantianya/ruoyi-vue-pro Cloud 倉庫:https://gitee.com/zhijiantianya/yudao-cloud 影片教程:https://doc.iocoder.cn 【國內首批】支援 JDK 21 + SpringBoot 3.2.2、JDK 8 + Spring Boot 2.7.18 雙版本
背景
基於 Spring Boot + MyBatis Plus + Vue & Element 實現的後臺管理系統 + 使用者小程式,支援 RBAC 動態許可權、多租戶、資料許可權、工作流、三方登入、支付、簡訊、商城等功能
專案地址:https://github.com/YunaiV/ruoyi-vue-pro 影片教程:https://doc.iocoder.cn/video/
分析並列出需要解決的問題思路

基於 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現的後臺管理系統 + 使用者小程式,支援 RBAC 動態許可權、多租戶、資料許可權、工作流、三方登入、支付、簡訊、商城等功能
專案地址:https://github.com/YunaiV/yudao-cloud 影片教程:https://doc.iocoder.cn/video/
具體實現
判斷是否啟用XXl-JOB的實現方式
/**
* 自動裝配類
*/
@Configuration
@ConditionalOnProperty
(name =
"xxl.job.enable"
,havingValue =
"true"
)
@ComponentScan
(
"com.teoan.job.auto.core"
)
publicclassXxlJobAutoConfiguration
{
}
xxl.job.enable
的值,決定是否啟用XXl-JOB的實現方式,如果xxl.job.enable
為false,則就什麼都不裝配不修改實現方式,預設就是Spring自帶的實現方式。掃描並讀取註解值
@Service
,@Component
就是使被掃描到並將對應的類注入到Spring容器中。所以我們可以按照相同的思路,可以在應用啟動就緒之後,掃描@Scheduled
註解,對其進行對應的操作。Spring中的@EventListener註解
@EventListener
標記某個方法為應用監聽事件的處理邏輯,還能配合非同步註解@Async
實現非同步觸發,@EventListener
透過傳值的方式設定需要被監聽的事件型別,比如應用啟動時、應用就緒時、啟動失敗時等,具體有哪些監聽的事件,可以參考Spring原始碼包org.springframework.boot.context.event
。@Component
@Slf
4j
publicclassJobAutoRegister
{
@EventListener
(ApplicationReadyEvent
.
class
)
@
Async
publicvoidonApplicationEvent
(
ApplicationReadyEventevent
)
{
// 執行掃描註解,自動註冊xxl-job任務邏輯
}
}
掃描並獲取被@Scheduled標記的方法和物件
@Scheduled
註解對應的物件,必須是被Spring所託管的類,定時任務才會生效,所以我們可以掃描被@Component
標記的類,再定位@Scheduled
註解,獲取對應的值、物件、方法等資訊。privatevoidaddJobInfo()
{
List<Object> beanList = applicationContext.getBeansWithAnnotation(Component
.class).values().stream().toList()
;
beanList.forEach(bean -> {
Map<Method, Scheduled> annotatedMethods = MethodIntrospector.selectMethods(bean.getClass(),
(MethodIntrospector.MetadataLookup<Scheduled>) method -> AnnotatedElementUtils.findMergedAnnotation(method, Scheduled
.class))
;
annotatedMethods.forEach((k, v) -> {
// 停止Spring自帶的定時任務
// 自動註冊到xxl-job任務
// 註冊xxl-job的任務
});
});
}
關閉Spring自帶的定時任務
ScheduledAnnotationBeanPostProcessor
類是一個Spring框架的類,用於處理@Scheduled
註解,實現定時任務的功能。我們可以透過這個類,對Spring中的定時任務進行一定的操作。ScheduledAnnotationBeanPostProcessor
有這麼一個方法postProcessBeforeDestruction
,該方法實現DestructionAwareBeanPostProcessor
介面,用於銷燬一個Bean的前置操作,而在ScheduledAnnotationBeanPostProcessor
類中,這個方法的實現是取消某個Bean中的所有定時任務。具體可以看一下這個方法的原始碼。@Override
publicvoidpostProcessBeforeDestruction(Object bean, String beanName)
{
Set<ScheduledTask> tasks;
synchronized
(
this
.scheduledTasks) {
tasks =
this
.scheduledTasks.remove(bean);
}
if
(tasks !=
null
) {
for
(ScheduledTask task : tasks) {
task.cancel();
}
}
}
@Scheduled
註解標記過方法,我們可以直接透過方法物件,獲取到對應的Bean,將Bean作為入參傳入postProcessBeforeDestruction
方法中,關閉Spring自帶的定時任務。
/**
* 停止Spring自帶的定時註解
*
*
@param
clazz 帶有定時註解的類
*/
privatevoidstopScheduled(Class<?> clazz)
{
ScheduledAnnotationBeanPostProcessor processor = (ScheduledAnnotationBeanPostProcessor) applicationContext
.getBean(
"org.springframework.context.annotation.internalScheduledAnnotationProcessor"
);
processor.postProcessBeforeDestruction(applicationContext.getBean(clazz),
""
);
}
讀取註解資訊並將任務自動註冊到XXl-JOB
@Scheduled
註解的資訊,我們可以將 @Scheduled
所帶的資訊轉換為對應XXL-JOB上對應的任務型別,在啟動的時候自動地註冊到排程中心,簡化XXl-JOB任務排程的使用配置步驟。註冊JobHandler
@XxlJob
的原始碼,發現會將@XxlJob
所標記的方法,向排程中心註冊一個MethodJobHandler
型別的JobHandler,表示方法模式對應的處理器。❝com.xxl.job.core.executor.impl.XxlJobSpringExecutor#initJobHandlerMethodRepository❞
protectedvoidregistJobHandler(XxlJob xxlJob, Object bean, Method executeMethod)
{
if
(xxlJob ==
null
) {
return
;
}
String name = xxlJob.value();
//make and simplify the variables since they'll be called several times later
Class<?> clazz = bean.getClass();
String methodName = executeMethod.getName();
if
(name.trim().length() ==
0
) {
thrownew
RuntimeException(
"xxl-job method-jobhandler name invalid, for["
+ clazz +
"#"
+ methodName +
"] ."
);
}
if
(loadJobHandler(name) !=
null
) {
thrownew
RuntimeException(
"xxl-job jobhandler["
+ name +
"] naming conflicts."
);
}
// execute method
/*if (!(method.getParameterTypes().length == 1 && method.getParameterTypes()[0].isAssignableFrom(String.class))) {
throw new RuntimeException("xxl-job method-jobhandler param-classtype invalid, for[" + bean.getClass() + "#" + method.getName() + "] , " +
"The correct method format like \" public ReturnT<String> execute(String param) \" .");
}
if (!method.getReturnType().isAssignableFrom(ReturnT.class)) {
throw new RuntimeException("xxl-job method-jobhandler return-classtype invalid, for[" + bean.getClass() + "#" + method.getName() + "] , " +
"The correct method format like \" public ReturnT<String> execute(String param) \" .");
}*/
executeMethod.setAccessible(
true
);
// init and destroy
Method initMethod =
null
;
Method destroyMethod =
null
;
if
(xxlJob.init().trim().length() >
0
) {
try
{
initMethod = clazz.getDeclaredMethod(xxlJob.init());
initMethod.setAccessible(
true
);
}
catch
(NoSuchMethodException e) {
thrownew
RuntimeException(
"xxl-job method-jobhandler initMethod invalid, for["
+ clazz +
"#"
+ methodName +
"] ."
);
}
}
if
(xxlJob.destroy().trim().length() >
0
) {
try
{
destroyMethod = clazz.getDeclaredMethod(xxlJob.destroy());
destroyMethod.setAccessible(
true
);
}
catch
(NoSuchMethodException e) {
thrownew
RuntimeException(
"xxl-job method-jobhandler destroyMethod invalid, for["
+ clazz +
"#"
+ methodName +
"] ."
);
}
}
// 核心方法
registJobHandler(name,
new
MethodJobHandler(bean, executeMethod, initMethod, destroyMethod));
}
@Scheduled
標記的方法,以同樣的方式,註冊到排程中心中去。從而實現@XxlJob
同樣的效果。
/**
* 註冊任務到xxl-job上
*
*
@param
handlerName JobHandler名稱
*
@param
executeMethod 執行定時任務的方法
*/
privatevoidregistJobHandler(String handlerName, Method executeMethod)
{
executeMethod.setAccessible(
true
);
// xxl-job初始化和銷燬方法物件,後續有需要再賦值
Method initMethod =
null
;
Method destroyMethod =
null
;
//獲取方法的Bean物件
Object bean = applicationContext.getBean(executeMethod.getDeclaringClass());
XxlJobExecutor.registJobHandler(handlerName,
new
MethodJobHandler(bean, executeMethod, initMethod, destroyMethod));
}
自動向排程中心註冊執行器和對應的任務資訊
powerjob-client
的OpenAPI介面,但是問題不大,根據XXL-JOB的原始碼,我們可以自己實現一個,將獲取token,新增執行器資訊,新增任務資訊等包裝為service。publicbooleanautoRegisterGroup()
{
String url = adminAddresses +
"/jobgroup/save"
;
HttpRequest httpRequest = HttpRequest.post(url)
.form(
"appname"
, appName)
.form(
"title"
, title);
httpRequest.form(
"addressType"
, addressType);
if
(addressType.equals(
1
)) {
if
(Strings.isBlank(addressList)) {
thrownew
RuntimeException(
"手動錄入模式下,執行器地址列表不能為空"
);
}
httpRequest.form(
"addressList"
, addressList);
}
HttpResponse response = httpRequest.cookie(jobLoginService.getCookie())
.execute();
Object code = JSONUtil.parse(response.body()).getByPath(
"code"
);
if
(!code.equals(
200
)){
log.error(
">>>>>>>>>>> xxl-job auto register group fail!msg[{}]"
,JSONUtil.parse(response.body()).getByPath(
"msg"
));
returnfalse
;
}
returntrue
;
}
privatevoidaddJobInfo()
{
List<XxlJobGroup> jobGroups = jobGroupService.getJobGroup();
XxlJobGroup xxlJobGroup = jobGroups.get(
0
);
List<Object> beanList = applicationContext.getBeansWithAnnotation(Component
.class).values().stream().toList()
;
beanList.forEach(bean -> {
Map<Method, Scheduled> annotatedMethods = MethodIntrospector.selectMethods(bean.getClass(),
(MethodIntrospector.MetadataLookup<Scheduled>) method -> AnnotatedElementUtils.findMergedAnnotation(method, Scheduled
.class))
;
annotatedMethods.forEach((k, v) -> {
// 停止Spring自帶的定時任務
stopScheduled(k.getDeclaringClass());
// 自動註冊到xxl-job 暫定Handle名稱規則beanName#MethodName
String handlerName = StringUtils.joinWith(
"#"
, k.getDeclaringClass().getName(), k.getName());
// 註冊xxl-job的任務
registJobHandler(handlerName, k);
//因為是模糊查詢,需要再過濾一次
Optional<XxlJobInfo> first = jobInfoService.getJobInfo(xxlJobGroup.getId(), handlerName).stream()
.filter(xxlJobInfo -> xxlJobInfo.getExecutorHandler().equals(handlerName))
.findFirst();
XxlJobInfo xxlJobInfo = createXxlJobInfo(xxlJobGroup, v, handlerName);
if
(first.isEmpty()) {
Integer jobInfoId = jobInfoService.addJobInfo(xxlJobInfo);
if
(ObjectUtils.isNotEmpty(jobInfoId)) {
log.info(
">>>>>>>>>>> xxl-job auto add jobInfo success! JobInfoId[{}] JobInfo[{}]"
, jobInfoId,
JSONUtil.toJsonStr(xxlJobInfo));
}
}
});
});
}
將定時任務中的log.info()日誌輸出一份到XXL-JOB的線上日誌上
log.info()
依賴於Slf4j日誌門面。
/**
*
@author
Teoan
*
@description
處理日誌事件
*/
@Component
publicclassXxlJobLogAppenderextendsAppenderBase<ILoggingEvent>
{
@Override
protectedvoidappend(ILoggingEvent iLoggingEvent)
{
if
(XxlJobHelper.getJobId() == -
1
) {
return
;
}
if
(Level.ERROR.equals(iLoggingEvent.getLevel())) {
ThrowableProxy throwableProxy = (ThrowableProxy) iLoggingEvent.getThrowableProxy();
if
(throwableProxy !=
null
) {
XxlJobHelper.log(throwableProxy.getThrowable());
}
else
{
XxlJobHelper.log(iLoggingEvent.getMessage());
}
}
else
{
XxlJobHelper.log(iLoggingEvent.getMessage());
}
}
}
第三方應用整合Starter使用
在POM檔案中引入Starter依賴
<!-- xxl-job-core -->
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>${xxl-job.version}</version>
</dependency>
<dependency>
<groupId>com.teoan</groupId>
<artifactId>xxl-job-auto-spring-boot-starter</artifactId>
<version>${project.version}</version>
</dependency>
SpringBoor配置檔案中新增XXL-JOB的配置
server:
port:
8080
spring:
application:
name: xxlJobAuto
xxl:
job:
# 自動註冊自定義新增配置項 是否使用Xxl實現定時任務
enable:
true
accessToken:
admin:
addresses: http:
//localhost:8080/xxl-job-admin
# 以下admin配置為自動註冊自定義新增配置項,必須項
username: admin #admin 使用者名稱
password: password #admin 密碼
executor:
appname: ${spring.application.name}
ip:
address:
logpath:
logretentiondays:
3
port:
0
# 以下executor配置為自動註冊自定義新增配置項,可選
addressList: #在addressType為
1
的情況下,手動錄入執行器地址列表,多地址逗號分隔
addressType:
0
#執行器地址型別:
0
=自動註冊、
1
=手動錄入,預設為
0
title: ${spring.application.name} #執行器名稱
XXL-JOB執行器元件配置
@Configuration
@Slf
4j
publicclassXxlJobConfig
{
@Value
(
"${xxl.job.admin.addresses}"
)
private
String adminAddresses;
@Value
(
"${xxl.job.accessToken}"
)
private
String accessToken;
@Value
(
"${xxl.job.executor.appname}"
)
private
String appname;
@Value
(
"${xxl.job.executor.address}"
)
private
String address;
@Value
(
"${xxl.job.executor.ip}"
)
private
String ip;
@Value
(
"${xxl.job.executor.port}"
)
privateint
port;
@Value
(
"${xxl.job.executor.logpath}"
)
private
String logPath;
@Value
(
"${xxl.job.executor.logretentiondays}"
)
privateint
logRetentionDays;
@Bean
public XxlJobSpringExecutor xxlJobExecutor()
{
log.info(
">>>>>>>>>>> xxl-job config init."
);
XxlJobSpringExecutor xxlJobSpringExecutor =
new
XxlJobSpringExecutor();
xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
xxlJobSpringExecutor.setAppname(appname);
xxlJobSpringExecutor.setAddress(address);
xxlJobSpringExecutor.setIp(ip);
xxlJobSpringExecutor.setPort(port);
xxlJobSpringExecutor.setAccessToken(accessToken);
xxlJobSpringExecutor.setLogPath(logPath);
xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
return
xxlJobSpringExecutor;
}
}
使用SpringBoot自帶的@Scheduled註解開發定時任務
/**
*
@author
Teoan
*/
@Slf
4j
@Component
publicclassXxlJobAutoSamplesJob
{
@Scheduled
(fixedRate =
10000
)
publicvoidsamplesJob()
{
log.info(
"samplesJob executor success!"
);
}
}
啟動專案驗證
. ____ _ __ _ _
/\\ / ___
'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '
_ |
'_| | '
_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.0.5)
2023-05-07 15:46:19.633 [main] INFO com.teoan.job.auto.samples.XxlJobAutoApplication - Starting XxlJobAutoApplication using Java 17.0.6 with PID 28253 (/Users/teoan/Project/xxl-job-auto/xxl-job-auto-spring-boot-samples/target/classes started by teoan in /Users/teoan/Project/xxl-job-auto)
2023-05-07 15:46:19.645 [main] INFO com.teoan.job.auto.samples.XxlJobAutoApplication - No active profile set, falling back to 1 default profile: "default"
2023-05-07 15:46:21.083 [main] INFO o.s.boot.web.embedded.tomcat.TomcatWebServer - Tomcat initialized with port(s): 8080 (http)
2023-05-07 15:46:21.091 [main] INFO org.apache.coyote.http11.Http11NioProtocol - Initializing ProtocolHandler ["http-nio-8080"]
2023-05-07 15:46:21.092 [main] INFO org.apache.catalina.core.StandardService - Starting service [Tomcat]
2023-05-07 15:46:21.092 [main] INFO org.apache.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/10.1.7]
2023-05-07 15:46:21.179 [main] INFO o.a.c.core.ContainerBase.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext
2023-05-07 15:46:21.179 [main] INFO o.s.b.w.s.c.ServletWebServerApplicationContext - Root WebApplicationContext: initialization completed in 1295 ms
2023-05-07 15:46:21.367 [main] INFO com.teoan.job.auto.samples.config.XxlJobConfig - >>>>>>>>>>> xxl-job config init.
2023-05-07 15:46:21.797 [main] INFO o.s.b.actuate.endpoint.web.EndpointLinksResolver - Exposing 1 endpoint(s) beneath base path '
/actuator
'
2023-05-07 15:46:21.954 [main] INFO org.apache.coyote.http11.Http11NioProtocol - Starting ProtocolHandler ["http-nio-8080"]
2023-05-07 15:46:21.969 [main] INFO o.s.boot.web.embedded.tomcat.TomcatWebServer - Tomcat started on port(s): 8080 (http) with context path '
'
2023-05-07 15:46:21.998 [scheduling-1] INFO c.teoan.job.auto.samples.job.XxlJobAutoSamplesJob - samplesJob executor success!
2023-05-07 15:46:22.000 [main] INFO com.teoan.job.auto.samples.XxlJobAutoApplication - Started XxlJobAutoApplication in 3.014 seconds (process running for 3.887)
2023-05-07 15:46:22.020 [Thread-4] INFO com.xxl.job.core.server.EmbedServer - >>>>>>>>>>> xxl-job remoting server start success, nettype = class com.xxl.job.core.server.EmbedServer, port = 9999
2023-05-07 15:46:22.397 [RMI TCP Connection(2)-192.168.123.139] INFO o.a.c.core.ContainerBase.[Tomcat].[localhost].[/] - Initializing Spring DispatcherServlet '
dispatcherServlet
'
2023-05-07 15:46:22.399 [RMI TCP Connection(2)-192.168.123.139] INFO org.springframework.web.servlet.DispatcherServlet - Initializing Servlet '
dispatcherServlet
'
2023-05-07 15:46:22.402 [RMI TCP Connection(2)-192.168.123.139] INFO org.springframework.web.servlet.DispatcherServlet - Completed initialization in 3 ms
2023-05-07 15:47:31.997 [scheduling-1] INFO c.teoan.job.auto.samples.job.XxlJobAutoSamplesJob - samplesJob executor success!
2023-05-07 15:47:41.997 [scheduling-1] INFO c.teoan.job.auto.samples.job.XxlJobAutoSamplesJob - samplesJob executor success!
2023-05-07 15:47:51.996 [scheduling-1] INFO c.teoan.job.auto.samples.job.XxlJobAutoSamplesJob - samplesJob executor success!
2023-05-07 15:48:01.994 [scheduling-1] INFO c.teoan.job.auto.samples.job.XxlJobAutoSamplesJob - samplesJob executor success!
xxl.job.enable
設定為true,再看看日誌。
. ____ _ __ _ _
/\\ / ___
'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '
_ |
'_| | '
_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.0.5)
2023-05-07 15:56:50.011 [main] INFO com.teoan.job.auto.samples.XxlJobAutoApplication - Starting XxlJobAutoApplication using Java 17.0.6 with PID 30937 (/Users/teoan/Project/xxl-job-auto/xxl-job-auto-spring-boot-samples/target/classes started by teoan in /Users/teoan/Project/xxl-job-auto)
2023-05-07 15:56:50.025 [main] INFO com.teoan.job.auto.samples.XxlJobAutoApplication - No active profile set, falling back to 1 default profile: "default"
2023-05-07 15:56:51.538 [main] INFO o.s.boot.web.embedded.tomcat.TomcatWebServer - Tomcat initialized with port(s): 8080 (http)
2023-05-07 15:56:51.548 [main] INFO org.apache.coyote.http11.Http11NioProtocol - Initializing ProtocolHandler ["http-nio-8080"]
2023-05-07 15:56:51.549 [main] INFO org.apache.catalina.core.StandardService - Starting service [Tomcat]
2023-05-07 15:56:51.549 [main] INFO org.apache.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/10.1.7]
2023-05-07 15:56:51.642 [main] INFO o.a.c.core.ContainerBase.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext
2023-05-07 15:56:51.642 [main] INFO o.s.b.w.s.c.ServletWebServerApplicationContext - Root WebApplicationContext: initialization completed in 1351 ms
2023-05-07 15:56:51.835 [main] INFO com.teoan.job.auto.samples.config.XxlJobConfig - >>>>>>>>>>> xxl-job config init.
2023-05-07 15:56:52.282 [main] INFO o.s.b.actuate.endpoint.web.EndpointLinksResolver - Exposing 1 endpoint(s) beneath base path '
/actuator
'
2023-05-07 15:56:52.444 [main] INFO org.apache.coyote.http11.Http11NioProtocol - Starting ProtocolHandler ["http-nio-8080"]
2023-05-07 15:56:52.457 [main] INFO o.s.boot.web.embedded.tomcat.TomcatWebServer - Tomcat started on port(s): 8080 (http) with context path '
'
2023-05-07 15:56:52.477 [scheduling-1] INFO c.teoan.job.auto.samples.job.XxlJobAutoSamplesJob - samplesJob executor success!
2023-05-07 15:56:52.480 [main] INFO com.teoan.job.auto.samples.XxlJobAutoApplication - Started XxlJobAutoApplication in 3.118 seconds (process running for 3.86)
2023-05-07 15:56:52.515 [Thread-4] INFO com.xxl.job.core.server.EmbedServer - >>>>>>>>>>> xxl-job remoting server start success, nettype = class com.xxl.job.core.server.EmbedServer, port = 9999
2023-05-07 15:56:52.712 [RMI TCP Connection(3)-192.168.123.139] INFO o.a.c.core.ContainerBase.[Tomcat].[localhost].[/] - Initializing Spring DispatcherServlet '
dispatcherServlet
'
2023-05-07 15:56:52.714 [RMI TCP Connection(3)-192.168.123.139] INFO org.springframework.web.servlet.DispatcherServlet - Initializing Servlet '
dispatcherServlet
'
2023-05-07 15:56:52.715 [RMI TCP Connection(3)-192.168.123.139] INFO org.springframework.web.servlet.DispatcherServlet - Completed initialization in 1 ms
2023-05-07 15:56:53.145 [main] INFO com.teoan.job.auto.core.JobAutoRegister - >>>>>>>>>>> xxl-job auto register group success!
2023-05-07 15:56:53.490 [main] INFO com.xxl.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job register jobhandler success, name:com.teoan.job.auto.samples.job.XxlJobAutoSamplesJob#samplesJob, jobHandler:com.xxl.job.core.handler.impl.MethodJobHandler@223cbf0d[class com.teoan.job.auto.samples.job.XxlJobAutoSamplesJob#samplesJob]
2023-05-07 15:56:53.647 [main] INFO com.teoan.job.auto.core.JobAutoRegister - >>>>>>>>>>> xxl-job auto add jobInfo success! JobInfoId[11085] JobInfo[{"id":0,"jobGroup":2080,"jobDesc":"com.teoan.job.auto.samples.job.XxlJobAutoSamplesJob#samplesJob","author":"JobAutoRegister","scheduleType":"FIX_RATE","scheduleConf":"10","misfireStrategy":"DO_NOTHING","executorRouteStrategy":"FIRST","executorHandler":"com.teoan.job.auto.samples.job.XxlJobAutoSamplesJob#samplesJob","executorBlockStrategy":"SERIAL_EXECUTION","executorTimeout":0,"executorFailRetryCount":0,"glueType":"BEAN","glueRemark":"GLUE程式碼初始化","triggerStatus":1,"triggerLastTime":0,"triggerNextTime":0}]
2023-05-07 15:56:53.650 [main] INFO com.teoan.job.auto.core.JobAutoRegister - >>>>>>>>>>> xxl-job auto register success
2023-05-07 15:57:24.538 [xxl-job, EmbedServer bizThreadPool-123827075] INFO com.xxl.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job regist JobThread success, jobId:11085, handler:com.xxl.job.core.handler.impl.MethodJobHandler@223cbf0d[class com.teoan.job.auto.samples.job.XxlJobAutoSamplesJob#samplesJob]
2023-05-07 15:57:24.540 [xxl-job, JobThread-11085-1683446244537] INFO c.teoan.job.auto.samples.job.XxlJobAutoSamplesJob - samplesJob executor success!



實現過程中思考的幾個問題
是否實現任務資訊的更新
是否採用修改資料庫資料的方式實現任務的註冊
是否在自動裝配類上加上@Scheduled
@Scheduled
開啟SpringBoot的自動任務,但是為了儘量不影響正常的開發配置,開頭說到的儘量讓使用者無感知,所以這個 @Scheduled
還是需要starter的使用方自己去配置,然後走預設實現的定時任務開發。提供的Starter是否加上XXL-Job的依賴
總結
專案地址





