服务器启动完成执行定时任务Timer,TimerTask

时间:2021-02-10 00:12:15

由于项目需求:每隔一段时间就要调外部接口去进行某些操作,于是在网上找了一些资料,用了半天时间弄好了,代码:

1 import java.util.TimerTask;
2
3 public class AccountTask extends TimerTask {
4
5 @Override
6 public void run() {
7 System.out.prinln("开始执行定时任务业务");
8 }
9 }

 

 1 import java.util.Timer;
2
3 import javax.servlet.ServletContextEvent;
4 import javax.servlet.ServletContextListener;
5
6 public class AccountTimerListener implements ServletContextListener {
7
8 private Timer timer = null;
9
10 @Override
11 public void contextInitialized(ServletContextEvent event) {
12 timer = new Timer(true);
13 event.getServletContext().log("定时器已启动");
14 // 服务器启动后,延迟7秒启动,5秒执行一次
15 timer.scheduleAtFixedRate(new AccountTask(), 7 * 1000, 5 * 1000);
16 }
17
18 @Override
19 public void contextDestroyed(ServletContextEvent event) {
20 if (timer != null) {
21 timer.cancel();
22 event.getServletContext().log("定时器销毁");
23 }
24 }
25 }

然后在web.xml文件中配置监听

1     <listener>
2 <listener-class>com.xxx.AccountTimerListener</listener-class>
3 </listener>

启动之后,会发现没隔5秒打印一次: 开始执行定时任务业务 。

然而,当调度类中调用service层业务时,启动tomcat后,执行定时任务时会报空指针异常,这是由于这个定时任务目前只是一个普通的类,我们需要将这个定时任务注入到spring中,监听。

解决方案如下:

 1 package com.test.utils;
2
3 import javax.servlet.ServletContextEvent;
4 import javax.servlet.ServletContextListener;
5
6 import org.springframework.context.ApplicationContext;
7 import org.springframework.web.context.WebApplicationContext;
8 import org.springframework.web.context.support.WebApplicationContextUtils;
9
10 public class SpringInit implements ServletContextListener {
11
12 private static WebApplicationContext springContext;
13
14 public SpringInit() {
15 super();
16 }
17
18 @Override
19 public void contextDestroyed(ServletContextEvent event) {
20 // TODO Auto-generated method stub
21 }
22
23 @Override
24 public void contextInitialized(ServletContextEvent event) {
25 springContext = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
26 }
27
28 public static ApplicationContext getApplicationContext() {
29 return springContext;
30
31 }
32
33 }

web.xml文件:

1 <!-- SpringInit类所在的包 -->
2 <context:component-scan base-package="com.test.utils" />
3
4
5 <listener>
6 <listener-class>com.test.utils.SpringInit</listener-class>
7 </listener>

若  context:component-scan  出报错,可能是因为没有引入标签。

在xmlns:xsi 里加上  

1 http://www.springmodules.org/schema/cache/springmodules-cache.xsd http://www.springmodules.org/schema/cache/springmodules-ehcache.xsd

xsi:schemaLocation里加上  

1  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd

上面的问题解决。

最后,我们掉用service之前,这样来获取bean:

DetailService detailService = (DetailService) SpringInit.getApplicationContext().getBean("detailService");

然后就可以掉用service层业务进行定时任务了。