项目每次注册新建任务都需要手动操作配置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;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) {this.applicationContext = applicationContext;}@Overridepublic 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>() {@Overridepublic 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。