服务器启动完成执行定时任务Timer,TimerTask
由于项目需求:每隔一段时间就要调外部接口去进行某些操作,于是在网上找了一些资料,用了半天时间弄好了,代码:
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层业务进行定时任务了。