在Listener(监听器)定时启动的TimerTask(定时任务)中使用Spring@Service注解的bean
1.有时候在项目中需要定时启动某个任务,对于这个需求,基于JavaEE规范,我们可以使用Listener与TimerTask来实现,代码如下:
public class TestTaskListener implements ServletContextListener {
//Context()初始化方法
@Override
public void contextInitialized(ServletContextEvent sce) {
//新建一个定时管理器
new TestTimerManager();
}
public TestTaskListener() {
super();
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
2.contextInitialized方法中新建了一个定时管理器,代码如下:
public class TestTimerManager {
//新建一个定时器
Timer timer = new Timer();
public TestTimerManager() {
super();
//新建一个定时任务
TestTimerTask task = new TestTimerTask();
//设置定时任务
timer.schedule(task, firstTimeToStartTheTask, period);
}
}
3.在定时任务的Constructor中新建了一个定时任务,其代码如下:
@Configuration
public class TestTimerTask extends TimerTask {
//采用Spring框架的依赖注入
@Autowired
private SelectDataService selectDataService; public TestTimerTask() {
super();
}
@Override
public void run(){
try {
//访问数据库
MyData myData = selectDataService.selectMyDataById(id);
}catch(Exception ex) {
System.out.println("定时任务出错");
ex.printStackTrace();
}
}
}
spring是个性能非常优秀的抽象工厂,可以生产出工程所需要的实例,这里采用Spring容器的自动注入selectDataService实例。上面代码中,selectDataService这个类是采用Spring的@Service注解的,在项目中主要通过Spring容器注入到Controller中,其作用主要用来访问数据库。
运行项目将会发现NullPointerException,也就是说SelectDataService的实例没有被注入到变量selectDataService中。那么,这是什么原因呢?首先来看看配置文件。
下面是web.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>com.test.TestTaskListener</listener-class>
</listener>
在启动web项目时,Servlet容器(比如Tomcat)会读web.xml配置文件中的两个节点和,节点用来加载appliactionContext.xml(即Spring的配置文件),节点用来创建监听器(比如TestTaskListener)实例。Listener的生命周期是由servlet容器管理的,例中的TestTaskListener是由servlet容器实例化并调用其contextInitialized方法的,但是,SelectDataService是通过@Service注解的,也就是说SelectDataService是由Spring容器管理的,在Spring容器外无法直接通过依赖注入得到Spring容器管理的bean实例的引用。为了在Spring容器外得到Spring容器管理的bean,可以使用Spring提供的工具类WebApplicationContextUtils。也就是说,可以在servlet容器管理的Listener中使用该工具类获Spring管理的bean。
看如下代码:
public class TestTaskListener implements ServletContextListener {
//Context()初始化方法
@Override
public void contextInitialized(ServletContextEvent sce) {
//获得Spring容器
WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
//从Spring容器中获得SelectDataServlet的实例
SelectDataService selectDataService = ctx.getBean(SelectDataService.class);
//新建一个定时管理器
new TestTimerManager();
}
public TestTaskListener() {
super();
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
那么在Listener中获得的SelectDataService实例如何在TestTimerTask中使用呢?可以通过作为参数传递过去,看如下代码:
public class TestTaskListener implements ServletContextListener {
//Context()初始化方法
@Override
public void contextInitialized(ServletContextEvent sce) {
//获得Spring容器
WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
//从Spring容器中获得SelectDataServlet的实例
SelectDataService selectDataService = ctx.getBean(SelectDataService.class);
//新建一个定时管理器
new TestTimerManager(selectDataService);
}
public TestTaskListener() {
super();
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
public class TestTimerManager {
//新建一个定时器
Timer timer = new Timer();
public TestTimerManager(SelectDataService selectDataService) {
super();
//新建一个定时任务
TestTimerTask task = new TestTimerTask(selectDataService);
//设置定时任务
timer.schedule(task, firstTimeToStartTheTask, period);
}
}
@Configuration
public class TestTimerTask extends TimerTask {
private SelectDataService selectDataService;
public TestTimerTask(SelectDataService selectDataService) {
super();
this.selectDataService = selectDataService;
}
@Override
public void run(){
try {
//访问数据库
MyData myData = selectDataService.selectMyDataById(id);
}catch(Exception ex) {
System.out.println("定时任务出错");
ex.printStackTrace();
}
}
}
再回到web.xml
由于Servlet容器在初始化TestTaskListener时,获取了Spring容器,所以必须保证,在此之前,Spring容器已经初始化完成。因为Spring容器的初始化也是由Listener(ContextLoaderListener)完成,该监听器用Spring框架提供,可以在web应用启动时启动Spring容器。所以,在web.xml中,要先配置ContextLoaderListener,再配置TestTaskListener。
1.有时候在项目中需要定时启动某个任务,对于这个需求,基于JavaEE规范,我们可以使用Listener与TimerTask来实现,代码如下:
public class TestTaskListener implements ServletContextListener {
//Context()初始化方法
@Override
public void contextInitialized(ServletContextEvent sce) {
//新建一个定时管理器
new TestTimerManager();
}
public TestTaskListener() {
super();
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
2.contextInitialized方法中新建了一个定时管理器,代码如下:
public class TestTimerManager {
//新建一个定时器
Timer timer = new Timer();
public TestTimerManager() {
super();
//新建一个定时任务
TestTimerTask task = new TestTimerTask();
//设置定时任务
timer.schedule(task, firstTimeToStartTheTask, period);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
3.在定时任务的Constructor中新建了一个定时任务,其代码如下:
@Configuration
public class TestTimerTask extends TimerTask {
//采用Spring框架的依赖注入
@Autowired
private SelectDataService selectDataService;
public TestTimerTask() {
super();
}
@Override
public void run(){
try {
//访问数据库
MyData myData = selectDataService.selectMyDataById(id);
}catch(Exception ex) {
System.out.println("定时任务出错");
ex.printStackTrace();
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
spring是个性能非常优秀的抽象工厂,可以生产出工程所需要的实例,这里采用Spring容器的自动注入selectDataService实例。上面代码中,selectDataService这个类是采用Spring的@Service注解的,在项目中主要通过Spring容器注入到Controller中,其作用主要用来访问数据库。
运行项目将会发现NullPointerException,也就是说SelectDataService的实例没有被注入到变量selectDataService中。那么,这是什么原因呢?首先来看看配置文件。
下面是web.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>com.test.TestTaskListener</listener-class>
</listener>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
在启动web项目时,Servlet容器(比如Tomcat)会读web.xml配置文件中的两个节点和,节点用来加载appliactionContext.xml(即Spring的配置文件),节点用来创建监听器(比如TestTaskListener)实例。Listener的生命周期是由servlet容器管理的,例中的TestTaskListener是由servlet容器实例化并调用其contextInitialized方法的,但是,SelectDataService是通过@Service注解的,也就是说SelectDataService是由Spring容器管理的,在Spring容器外无法直接通过依赖注入得到Spring容器管理的bean实例的引用。为了在Spring容器外得到Spring容器管理的bean,可以使用Spring提供的工具类WebApplicationContextUtils。也就是说,可以在servlet容器管理的Listener中使用该工具类获Spring管理的bean。
看如下代码:
public class TestTaskListener implements ServletContextListener {
//Context()初始化方法
@Override
public void contextInitialized(ServletContextEvent sce) {
//获得Spring容器
WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
//从Spring容器中获得SelectDataServlet的实例
SelectDataService selectDataService = ctx.getBean(SelectDataService.class);
//新建一个定时管理器
new TestTimerManager();
}
public TestTaskListener() {
super();
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
那么在Listener中获得的SelectDataService实例如何在TestTimerTask中使用呢?可以通过作为参数传递过去,看如下代码:
public class TestTaskListener implements ServletContextListener {
//Context()初始化方法
@Override
public void contextInitialized(ServletContextEvent sce) {
//获得Spring容器
WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
//从Spring容器中获得SelectDataServlet的实例
SelectDataService selectDataService = ctx.getBean(SelectDataService.class);
//新建一个定时管理器
new TestTimerManager(selectDataService);
}
public TestTaskListener() {
super();
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
public class TestTimerManager {
//新建一个定时器
Timer timer = new Timer();
public TestTimerManager(SelectDataService selectDataService) {
super();
//新建一个定时任务
TestTimerTask task = new TestTimerTask(selectDataService);
//设置定时任务
timer.schedule(task, firstTimeToStartTheTask, period);
}
}
@Configuration
public class TestTimerTask extends TimerTask {
private SelectDataService selectDataService;
public TestTimerTask(SelectDataService selectDataService) {
super();
this.selectDataService = selectDataService;
}
@Override
public void run(){
try {
//访问数据库
MyData myData = selectDataService.selectMyDataById(id);
}catch(Exception ex) {
System.out.println("定时任务出错");
ex.printStackTrace();
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
再回到web.xml
由于Servlet容器在初始化TestTaskListener时,获取了Spring容器,所以必须保证,在此之前,Spring容器已经初始化完成。因为Spring容器的初始化也是由Listener(ContextLoaderListener)完成,该监听器用Spring框架提供,可以在web应用启动时启动Spring容器。所以,在web.xml中,要先配置ContextLoaderListener,再配置TestTaskListener。
在Listener(监听器)定时启动的TimerTask(定时任务)中使用Spring@Service注解的bean的更多相关文章
- atititt.java定时任务框架选型Spring Quartz 注解总结
atititt.java定时任务框架选型Spring Quartz 总结 1. .Spring Quartz (ati recomm) 1 2. Spring Quartz具体配置 2 2.1. 增 ...
- 如何在自定义Listener(监听器)中使用Spring容器管理的bean
正好以前项目中碰到这个问题,现在网上偶然又看到这个问题的博文,那就转一下吧. 原文:http://blog.lifw.org/post/46428852 感谢作者 另外补充下:在web Server容 ...
- quartz 框架定时任务,使用spring @Scheduled注解执行定时任务
配置quartz 在spring中需要三个jar包: quartz-1.6.5.jar.commons-collections-3.2.jar.commons-logging-1.1.jar 首先要配 ...
- 服务器启动完成执行定时任务Timer,TimerTask
由于项目需求:每隔一段时间就要调外部接口去进行某些操作,于是在网上找了一些资料,用了半天时间弄好了,代码: import java.util.TimerTask; public class Accou ...
- Listener监听器和Filter过滤器
Listener监听器 WEB中的监听器 WEB 中的 Listener 和 Filter 是属于 Servlet 规范中的高级的技术.WEB中的监听器共有三类八种(监听三个域对象)* 事件源:Ser ...
- TimerTask定时任务
web.xml <listener> <listener-class>com.sign.listener.NFDFlightDataTaskListener</liste ...
- [Java] JSP笔记 - Listener 监听器
Java Web 开发时,可以使用 Listener 来监听来监听一些事件,从而实现一些功能.实际上这个监听器,原理就是 Delphi 中大家常用的各种事件. 1. 那么,监听器的主要用途用哪些呢: ...
- listener监听器的相关知识
从别人的博客上我学习了listener的相关知识现在分享给大家 1.概念: 监听器就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上 ...
- listener监听器
前言:之前写了一篇关于Filter的文章:http://tianweili.github.io/blog/2015/01/26/java-filter/,现在再来一篇Listener的,Filter和 ...
随机推荐
- secureCRT在Windows上面的安装过程
参考这篇文章: https://www.cnblogs.com/yjd_hycf_space/p/7729796.html
- 算法:快速排序实现 & 定制比较函数
1. 快速排序基本算法 #include<stdio.h> ; int quick_sort(int *a, int start, int end){ if (start >= en ...
- spring boot整合mybatis+mybatis-plus
Spring boot对于我来说是一个刚接触的新东西,学习过程中,发现这东西还是很容易上手的,Spring boot没配置时会默认使用Spring data jpa,这东西可以说一个极简洁的工具,可是 ...
- multiMap遍历方法
/* multimap中的三种遍历方法 multimap中如果没有查找到相应元素,则返回的迭代器是依据该元素的排列顺序该键应该插入的位置 如果找不到,则方法一和方法二返回的两个迭代器应该相等 */ # ...
- 解决webstorm本地IP访问页面出错的问题,webstorm支持IP访问
想在手机端访问webstorm做出的页面,遇到了根据IP地址访问页面错误的问题,试了网上的方法:“设置webstorm可以被外部连接访问”,依旧不能解决 解决方法: 在webstorm下:ctrl+a ...
- java.security.NoSuchAlgorithmException: Cannot find any provider supporting DESede/CBC/PKCS5Padding
最近在做3DES加密,在本地window下面运行ok的程序,放到linux环境上竟然报错: Java.security.NoSuchAlgorithmException: Cannot find an ...
- stl 迭代器失效
1.对于基于连续内存的容器,容器元素的增删,有可能会导致迭代器的失效.考虑: int main(int argc, char* argv[]) { vector<int> intVec; ...
- 史上最全面的Buffalo WHR-G300N CH v2 刷OpenWrt教程
Buffalo WHR-G300N CH v2 刷OpenWrt.有两种办法.一种是Windows下刷.一种是在linux下使用tftp刷.Buffalo WHR-G300N-CH v2的openwr ...
- linux curl工具
http://www.linuxidc.com/Linux/2008-01/10891.htm http://www.cnblogs.com/-clq/archive/2012/01/29/23308 ...
- Netcore使用MailKit进行邮件发送
public void TestSendMailDemo() { var message = new MimeKit.MimeMessage(); message.From.Add(new MimeK ...