项目每次注册新建任务都需要手动操作配置xxl-job,不同的环境都需要手动操作配置一次,比较麻烦,为此想要简化相关的手动操作工作,基于注解的形式实现自动注册新建任务。
本篇是在之前一篇基于代码实现新建任务的基础上进一步实现。主要思路就是在原有的@XxlJob注解上新增一个自定义注解@XxlJobRegister,暂时是在事件监听机制中扫描目标方法,然后根据自定义注解实现自动注册新建任务的功能。
- 自定义注册新建任务的注解
@Target({
ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface XxlJobRegister {
String jobDesc() default "default jobDesc";
String author() default "default Author";
String alarmEmail () default "";
/** NONE CRON FIX_RATE */
String scheduleType() default "CRON";
String cronExpression();
/** 默认为 ROUND 轮询方式 可选: FIRST LAST ROUND RANDOM CONSISTENT_HASH
* LEAST_FREQUENTLY_USED LEAST_RECENTLY_USED FAILOVER BUSYOVER SHARDING_BROADCAST */
String executorRouteStrategy() default "ROUND";
/** DO_NOTHING FIRE_ONCE_NOW */
String misfireStrategy() default "DO_NOTHING";
String executorBlockStrategy() default "SERIAL_EXECUTION";
int executorTimeout() default 0;
int executorFailRetryCount() default 0;
String glueType() default "BEAN";
String glueRemark() default "GLUE代码初始化";
int triggerStatus() default 0;
boolean isStart() default false;
}
- 基于事件监听机制,监听ApplicationReadyEvent事件,扫描带有@XxlJob注解的目标方法,然后在根据@XxlJobRegister注解实现自动注册新建任务
@Slf4j
@Component
public class JobInfoRegisterListener implements ApplicationContextAware, ApplicationListener<ApplicationReadyEvent> {
@Value("${xxl.job.executor.app-name:}")
private String appName;
@Value("${xxl.job.executor.name:}")
private String name;
/** 执行器地址类型:0=自动注册、1=手动录入 */
@Value("${xxl.job.executor.address-type:0}")
private Integer addressType;
/** 执行器地址列表,多地址逗号分隔(手动录入) */
@Value("${xxl.job.executor.address-list:}")
private String addressList;
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
JobGroupService jobGroupService = applicationContext.getBean(JobGroupService.class);
JobGroup jobGroup = jobGroupService.readByAppName(appName);
if (ObjectUtil.isNull(jobGroup)) {
Boolean result = jobGroupService.save(appName, name, addressType, addressList);
if (result) {
jobGroup = jobGroupService.readByAppName(appName);
}
}
if (ObjectUtil.isNull(jobGroup)) {
return;
}
int jobGroupId = jobGroup.getId();
JobInfoService jobInfoService = applicationContext.getBean(JobInfoService.class);
Map<String, Object> beanMap =
applicationContext.getBeansOfType(Object.class, false, true);
for (Map.Entry<String, Object> beanEntry : beanMap.entrySet()) {
Map<Method, XxlJob> methodXxlJobMap = MethodIntrospector.selectMethods(beanEntry.getValue().getClass(),
new MethodIntrospector.MetadataLookup<XxlJob>() {
@Override
public XxlJob inspect(Method method) {
return AnnotatedElementUtils.findMergedAnnotation(method, XxlJob.class);
}
});
for (Map.Entry<Method, XxlJob> methodXxlJobEntry : methodXxlJobMap.entrySet()) {
Method method = methodXxlJobEntry.getKey();
if (!method.isAnnotationPresent(XxlJobRegister.class)) {
continue;
}
XxlJobRegister xxlJobRegister = method.getAnnotation(XxlJobRegister.class);
if (ObjectUtil.isNull(xxlJobRegister)) {
continue;
}
String executorHandler = methodXxlJobEntry.getValue().value();
JobInfo jobInfo = jobInfoService.readByJobGroupIdAndHandler(jobGroupId, executorHandler);
if (ObjectUtil.isNotNull(jobInfo)) {
log.info("Job info already exists {} {}", jobGroupId, executorHandler);
continue;
}
try {
jobInfoService.save(jobGroupId, executorHandler, xxlJobRegister);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
}
}
}
自此,可以根据项目的需求,自主配置是否在项目启动的时候自动注册新建任务至xxl-job。