热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

controller中@autowired报错_quartz(四)如何在job中使用spring自动注入

跨年篇:祝愿大家万事随心,吃饭吃得饱,睡觉睡得好,没有烦扰。一、背景我在Job实现类中使用Resource和Autowire
b104d894843d8e2d6f1dcde10c970117.png

跨年篇:祝愿大家万事随心,吃饭吃得饱,睡觉睡得好,没有烦扰。

一、背景

我在Job实现类中使用@Resource和@Autowired注入mapper类时,出现了如下的错误:

2020-12-31 20:41:07.311 ERROR 22456 --- [eduler_Worker-5] org.quartz.core.ErrorLogger : Job (repeat.test2 threw an exception.org.quartz.SchedulerException: Job threw an unhandled exception.at org.quartz.core.JobRunShell.run(JobRunShell.java:213)at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
Caused by: java.lang.NullPointerException: nullat com.example.docker_images.job.HelloJob.execute(HelloJob.java:26)at org.quartz.core.JobRunShell.run(JobRunShell.java:202)... 1 common frames omitted

  1. 为啥会有空指针?

答:出现这个原因是没有注入成功,所以为null,再通过这个对象调用mapper的方法不报错才怪。

  1. 这里你会很奇怪吧,明明使用了@Resource和@Autowired来注入,为什么注入后的对象还是null呢?

答:这里我来解释一下,这个是因为Job的实现类并没有加入到spring容器中,自然无法使用自动注入。

  1. 那进入今天的主题吧,怎么在Job实现类中使用spring的自动注入呢?

答:自然是将Job加入到Spring容器中,然后就可以执行自动注入了。 事先申明一下,这篇文章是在quartz(三)任务持久化-jdbc篇(一看就会)上优化的,有兴趣的可以看一下三。注入方式如下:

二、代码实现

通用代码(在三的基础上加了数据库的操作):

import com.example.docker_images.entity.User;
import com.example.docker_images.entity.common.CwConstant;
import com.example.docker_images.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;import javax.annotation.Resource;
import java.util.List;@Slf4j
public class HelloJob implements Job {@Resourceprivate IUserService iUserService;@Overridepublic void execute(JobExecutionContext context) throws JobExecutionException {//通过jobDetail获取数据String payload = context.getTrigger().getJobDataMap().getString(CwConstant.PAYLOAD);System.out.println(payload);System.out.println("hello world!!!");List list = iUserService.list();System.out.println(list.size());}
}

1. pom配置


org.quartz-schedulerquartz2.2.1


org.springframework.bootspring-boot-starter-quartz

2. 通过配置类将spring上下文注入到JobFactory中

  1. spring容器操作类

import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;public final class ApplicationContextHolder extends SpringBeanJobFactoryimplements ApplicationContextAware {private static ApplicationContext context;private transient AutowireCapableBeanFactory beanFactory;@Overridepublic void setApplicationContext(final ApplicationContext context) {beanFactory = context.getAutowireCapableBeanFactory();ApplicationContextHolder.context = context;}@Overrideprotected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {final Object job = super.createJobInstance(bundle);beanFactory.autowireBean(job);return job;}public static ApplicationContext getContext() {return context;}
}

  1. 通过配置类创建schedulerFactory

import com.example.docker_images.job.ApplicationContextHolder;
import org.quartz.Scheduler;
import org.quartz.spi.JobFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;import java.io.IOException;@Configuration
public class QuartzConfiguration {@Autowiredprivate ApplicationContext applicationContext;/*** Create the job factory bean** @return Job factory bean*/@Beanpublic JobFactory jobFactory() {ApplicationContextHolder jobFactory = new ApplicationContextHolder();jobFactory.setApplicationContext(applicationContext);return jobFactory;}/*** Create the Scheduler Factory bean** @return scheduler factory object*/@Beanpublic SchedulerFactoryBean schedulerFactory() {SchedulerFactoryBean factory = new SchedulerFactoryBean();factory.setAutoStartup(true);factory.setSchedulerName("CarWash Scheduler");factory.setOverwriteExistingJobs(true);factory.setJobFactory(jobFactory());return factory;}/*** 获得Scheduler 对象** @return* @throws IOException*/@Beanpublic Scheduler scheduler() throws IOException {return schedulerFactory().getScheduler();}
}

  1. 通过schedulerFactory获取Scheduler

import com.example.docker_images.entity.common.APIResult;
import com.example.docker_images.entity.common.CwConstant;
import com.example.docker_images.entity.common.ReturnCodeEnum;
import com.example.docker_images.entity.job.JobPayload;
import com.example.docker_images.job.HelloJob;
import com.example.docker_images.service.JobService;
import com.example.docker_images.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.TriggerBuilder.newTrigger;@Slf4j
@Service
public class JobServiceImpl implements JobService {//这里不可以使用&#64;Resource来注入&#xff0c;必须使用&#64;Autowired&#64;Autowiredprivate SchedulerFactoryBean schedulerFactory;&#64;Overridepublic APIResult initiate(JobPayload payload) {try {Scheduler scheduler &#61; schedulerFactory.getScheduler();JobDetail jobDetail &#61; JobBuilder.newJob(HelloJob.class).withIdentity(payload.getName(), payload.getGroup()).build();switch (payload.getScheduleType()){case CwConstant.JobType.NOW:Trigger build &#61; newTrigger().withIdentity(payload.getName(), payload.getGroup()).startNow().usingJobData(CwConstant.PAYLOAD,payload.getDataMap()).withDescription(payload.getDesc()).build();scheduler.scheduleJob(jobDetail,build);scheduler.start();log.info("成功创建即刻执行任务!!!");break;case CwConstant.JobType.ONCE:Trigger trigger &#61; newTrigger().withIdentity(payload.getName(), payload.getGroup()).startAt(DateUtil.parseYYYYMMDD(payload.getCron())).usingJobData(CwConstant.PAYLOAD,payload.getDataMap()).withDescription(payload.getDesc()).build();scheduler.scheduleJob(jobDetail,trigger);scheduler.start();log.info("成功创建未来执行一次任务!!!");break;case CwConstant.JobType.REPEAT:CronTrigger cronTrigger &#61; newTrigger().withIdentity(payload.getName(), payload.getGroup()).usingJobData(CwConstant.PAYLOAD,payload.getDataMap()).withDescription(payload.getDesc()).withSchedule(cronSchedule(payload.getCron())).build();scheduler.scheduleJob(jobDetail,cronTrigger);scheduler.start();log.info("成功创建重复任务!!!");break;}} catch (Exception e) {log.info("job initial failure:{}",e);return APIResult.error(ReturnCodeEnum.JOB_INITIAL_FAILURE);}return APIResult.success(null);}&#64;Overridepublic APIResult getJobList(String name, String groupName) {List jobs &#61; new ArrayList<>();try {Scheduler scheduler &#61; schedulerFactory.getScheduler();Set jobKeys;if(StringUtils.isEmpty(groupName)){if(!StringUtils.isEmpty(name)){CronTrigger trigger &#61; (CronTrigger)scheduler.getTrigger(new TriggerKey(name, groupName));jobs.add(JobPayload.getInstance(trigger));return APIResult.success(jobs);}jobKeys &#61; scheduler.getJobKeys(GroupMatcher.anyGroup());}else {jobKeys &#61; scheduler.getJobKeys(GroupMatcher.jobGroupEquals(groupName));}jobKeys.forEach(jobKey -> {try {CronTrigger trigger &#61; (CronTrigger)scheduler.getTrigger(new TriggerKey(jobKey.getName(), jobKey.getGroup()));JobPayload instance &#61; JobPayload.getInstance(trigger);jobs.add(instance);} catch (SchedulerException e) {log.info("任务不存在&#xff1a;{}",e);}});log.info("获取任务列表成功!!!");}catch (Exception e){log.info("任务列表获取失败{}",e);return APIResult.success(jobs);}return APIResult.success(jobs);}&#64;Overridepublic APIResult update(JobPayload jobPayload) {try {Scheduler scheduler &#61; schedulerFactory.getScheduler();TriggerKey triggerKey &#61; new TriggerKey(jobPayload.getName(), jobPayload.getGroup());switch (jobPayload.getScheduleType()){case CwConstant.JobType.ONCE://获取trigger,修改执行频率Trigger trigger &#61; scheduler.getTrigger(triggerKey);Date startTime &#61; trigger.getStartTime();Date date &#61; DateUtil.parseYYYYMMDD(jobPayload.getCron());boolean equals &#61; date.equals(startTime);if(!equals){Trigger build &#61; newTrigger().withIdentity(triggerKey).startAt(date).withDescription(jobPayload.getDesc()).usingJobData(CwConstant.PAYLOAD,jobPayload.getDataMap()).build();scheduler.rescheduleJob(triggerKey,build);}case CwConstant.JobType.REPEAT:CronTrigger cronTrigger &#61; (CronTrigger)scheduler.getTrigger(triggerKey);String cronExpression &#61; cronTrigger.getCronExpression();if(!ObjectUtils.nullSafeEquals(jobPayload.getCron(),cronExpression)){CronTrigger build &#61; newTrigger().withIdentity(triggerKey).withDescription(jobPayload.getDesc()).usingJobData(CwConstant.PAYLOAD,jobPayload.getDataMap()).withSchedule(cronSchedule(jobPayload.getCron())).build();scheduler.rescheduleJob(triggerKey,build);}}log.info("更新任务成功!!!");}catch (Exception e){log.info("修改失败:{}",e);return APIResult.error(ReturnCodeEnum.JOB_INITIAL_FAILURE);}return APIResult.success(null);}&#64;Overridepublic APIResult delete(String name, String groupName) {try {Scheduler scheduler &#61; schedulerFactory.getScheduler();TriggerKey triggerKey &#61; new TriggerKey(name, groupName);if(scheduler.checkExists(triggerKey)){scheduler.pauseTrigger(triggerKey);scheduler.unscheduleJob(triggerKey);scheduler.deleteJob(new JobKey(name,groupName));log.info("任务删除成功!!!");}}catch (Exception e){log.info("删除任务失败:{}",e);return APIResult.error(ReturnCodeEnum.JOB_INITIAL_FAILURE);}return APIResult.success(null);}&#64;Overridepublic APIResult pauseJob(String name, String groupName) {try {Scheduler scheduler &#61; schedulerFactory.getScheduler();scheduler.pauseTrigger(new TriggerKey(name, groupName));log.info("暂停任务成功!!!");}catch (Exception e){log.info("暂停任务失败:{}",e);return APIResult.error(ReturnCodeEnum.JOB_INITIAL_FAILURE);}return APIResult.success(null);}&#64;Overridepublic APIResult resumeJob(String name, String groupName) {try {Scheduler scheduler &#61; schedulerFactory.getScheduler();scheduler.resumeTrigger(new TriggerKey(name, groupName));log.info("恢复任务成功!!!");}catch (Exception e){log.info("恢复任务失败:{}",e);return APIResult.error(ReturnCodeEnum.JOB_INITIAL_FAILURE);}return APIResult.success(null);}
}

三、测试结果

  1. swagger调用
3b17820cb3cb0653c9988b8899e79e6c.png
  1. 执行日志

2020-12-31 21:58:02.709 INFO 12472 --- [nio-8088-exec-2] c.e.d.service.impl.JobServiceImpl : 成功创建重复任务!!!
{name:&#39;ljl&#39;}
hello world!!!
2020-12-31 21:58:07.706 INFO 12472 --- [eduler_Worker-1] com.alibaba.druid.pool.DruidDataSource : {dataSource-1} inited
2020-12-31 21:58:07.712 DEBUG 12472 --- [eduler_Worker-1] c.e.d.mapper.UserMapper.selectList : &#61;&#61;> Preparing: SELECT id,user_name FROM user
2020-12-31 21:58:07.720 DEBUG 12472 --- [eduler_Worker-1] c.e.d.mapper.UserMapper.selectList : &#61;&#61;> Parameters:
2020-12-31 21:58:07.754 DEBUG 12472 --- [eduler_Worker-1] c.e.d.mapper.UserMapper.selectList : <&#61;&#61; Total: 2
2
{name:&#39;ljl&#39;}
hello world!!!
2020-12-31 21:58:12.008 DEBUG 12472 --- [eduler_Worker-2] c.e.d.mapper.UserMapper.selectList : &#61;&#61;> Preparing: SELECT id,user_name FROM user
2020-12-31 21:58:12.008 DEBUG 12472 --- [eduler_Worker-2] c.e.d.mapper.UserMapper.selectList : &#61;&#61;> Parameters:
2020-12-31 21:58:12.036 DEBUG 12472 --- [eduler_Worker-2] c.e.d.mapper.UserMapper.selectList : <&#61;&#61; Total: 2
2

从日志结果来看&#xff0c;任务执行正常&#xff0c;没有出现空指针异常了。希望采纳&#xff01;



推荐阅读
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 本文介绍了UVALive6575题目Odd and Even Zeroes的解法,使用了数位dp和找规律的方法。阶乘的定义和性质被介绍,并给出了一些例子。其中,部分阶乘的尾零个数为奇数,部分为偶数。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • 本文详细介绍了GetModuleFileName函数的用法,该函数可以用于获取当前模块所在的路径,方便进行文件操作和读取配置信息。文章通过示例代码和详细的解释,帮助读者理解和使用该函数。同时,还提供了相关的API函数声明和说明。 ... [详细]
  • 电话号码的字母组合解题思路和代码示例
    本文介绍了力扣题目《电话号码的字母组合》的解题思路和代码示例。通过使用哈希表和递归求解的方法,可以将给定的电话号码转换为对应的字母组合。详细的解题思路和代码示例可以帮助读者更好地理解和实现该题目。 ... [详细]
  • Linux服务器密码过期策略、登录次数限制、私钥登录等配置方法
    本文介绍了在Linux服务器上进行密码过期策略、登录次数限制、私钥登录等配置的方法。通过修改配置文件中的参数,可以设置密码的有效期、最小间隔时间、最小长度,并在密码过期前进行提示。同时还介绍了如何进行公钥登录和修改默认账户用户名的操作。详细步骤和注意事项可参考本文内容。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
author-avatar
爱娟一辈子-_709
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有