Tomcat启动完毕后启动方法任务
来源:互联网 发布:周易掐指算法 编辑:程序博客网 时间:2024/06/04 19:42
Tomcat启动完成后再执行一个指定的方法 - 不影响Tomcat的启动时间
本文主要介绍Tomcat启动真正完成后(即在eclipse的控制台上出现类似于Server started in 2300ms这样的消息后)执行一个操作。如下的3种方法都是在Tomcat启动过程中执行的,这样会影响Tomcat的启动时间,从而造成Tomcat不能启动成功:
1.配置一个Servlet默认自动启动。
2.配置一个Listener来启动
3.实现Spring的InitializingBean接口
要想不影响Tomcat的启动,便联想到了异步调用 。即无非就是新创建了一个线程来单独执行,这样Tomcat执行到相应的操作就可以直接继续下去了,不会处于等待的状态,避免了启动超时。基于这样的思想,可以有两种方法来完成:
方法一: 使用如上三种方式中的任何一种来在启动Tomcat的过程中执行相应的方法,然后在执行的过程中使用另一个线程来执行:比如说将要执行的方法所在的类继承HttpServlet并在web.xml中配置,然后在该Servlet的init中去调用想要执行的方法时(假设这个方法名叫start()),启动另一个线程来执行,具体代码如下。
package com.cc.ovp.web.video;import static com.cc.ovp.util.RedisUtils.getPool;import java.util.List;import java.util.concurrent.Callable;import java.util.concurrent.FutureTask;import javax.annotation.Resource;import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Controller;import redis.clients.jedis.Jedis;import ayou.util.DOC;import ayou.util.StringUtil;import com.cc.ovp.dao.M3u8ContentDAO;import com.cc.ovp.dao.M3u8_db;import com.cc.ovp.domain.M3u8Content;import com.cc.ovp.service.MongoSearchService;import com.cc.ovp.util.JsonUtil;import com.cc.ovp.util.Pager;/** * 定时清理一下videojson 的redis缓存 * 需求: * 查询m3u8_content的status字段不为8, * 就清除redis 缓存,重新set值到redis, * cleanRedisVideoJSon(String vid), * 更新m3u8_content的status 字段为8 */@Controllerpublic class CleanVideoJsonRedis extends HttpServlet{ private static final Logger logger = LoggerFactory.getLogger(CleanVideoJsonRedis.class); private final int sleepTime=5*60*1000; @Resource(name = "m3u8ContentDAO") private M3u8ContentDAO m3u8ContentDAO; @Resource(name="videoJson") private VideoJson videoJson; // Servlet的init方法会在Tomcat启动的时候执行 @Override public void init() throws ServletException { FutureTask<String> task = new FutureTask<String>(new Callable<String>(){ @Override public String call() throws Exception { taskstart(); //使用另一个线程来执行该方法,会避免占用Tomcat的启动时间 return "Collection Completed"; } }); new Thread(task).start();; } public void taskstart(){ while (true) { try { System.out.println("init"); System.out.println("=============================="); Thread.sleep(5*1000); Pager pager = new Pager(1, 200); pager.setSortname("dateAdded"); pager.setSortorder("desc"); List<M3u8Content> list = m3u8ContentDAO.findList(pager); System.out.println("=============================="+list.size()); logger.info("tomcat 测试方法"); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }}
web.xml配置文件增加一个serlvet
<servlet> <servlet-name>event-collector</servlet-name> <servlet-class>com.cc.ovp.web.video.CleanVideoJsonRedis</servlet-class> <load-on-startup>60</load-on-startup> </servlet> <servlet-mapping> <servlet-name>event-collector</servlet-name> <url-pattern>/event-collect</url-pattern> </servlet-mapping>
方法二:配置一个Listener来启动
web.xml
<!-- Spring 上下文监听器 由此启动Spring上下文容器 --><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!-- 增加监听启动类的listener --> <listener><listener-class>com.cc.ovp.web.video.CleanVideoJsonRedis</listener-class></listener>
注意:<listener/> 标签一定要在<filter/>之后,在<servlet/>之前配置
2。CleanVideoJsonRedis.javapackage myservlet;import javax.servlet.*;import java.util.*;public class CleanVideoJsonRedis implements ServletContextListener{public CleanVideoJsonRedis(){ System.out.println("调用了构造方法");}public void contextInitialized(ServletContextEvent event) { System.out.println(" ----------创建了Context created on " + new Date() + "."); } public void contextDestroyed(ServletContextEvent event) { System.out.println("--------销毁了Context destroyed on " + new Date() + "."); }}说明:listener 配置在web.xml中,当web服务启动时,会实例化<listener-class/>中指定的类,所以里面一定要写完整类路径.
方法三: 使用Spring的Timer或者是著名的Quartz在Tomcat启动后再执行该方法,Spring中的Timer非常简单,这个地方不想讲解了,Quartz相对更复杂些,下面主要介绍下在Spring中怎么样使用Quartz来实现上面的需求:
例子:
package com.cc.ovp.web.video;import static com.cc.ovp.util.RedisUtils.getPool;import java.util.List;import java.util.concurrent.Callable;import java.util.concurrent.FutureTask;import javax.annotation.Resource;import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Controller;import redis.clients.jedis.Jedis;import ayou.util.DOC;import ayou.util.StringUtil;import com.cc.ovp.dao.M3u8ContentDAO;import com.cc.ovp.dao.M3u8_db;import com.cc.ovp.domain.M3u8Content;import com.cc.ovp.service.MongoSearchService;import com.cc.ovp.util.JsonUtil;import com.cc.ovp.util.Pager;/** * 定时清理一下videojson 的redis缓存 * 需求: * 查询m3u8_content的status字段不为8, * 就清除redis 缓存,重新set值到redis, * cleanRedisVideoJSon(String vid), * 更新m3u8_content的status 字段为8 */@Controllerpublic class CleanVideoJsonRedis implements Job{ private static final Logger logger = LoggerFactory.getLogger(CleanVideoJsonRedis.class); private final int sleepTime=5*60*1000; @Resource(name = "m3u8ContentDAO") private M3u8ContentDAO m3u8ContentDAO; @Resource(name="videoJson") private VideoJson videoJson; @Override public void execute(JobExecutionContext arg0) throws JobExecutionException { // TODO Auto-generated method stub } public void executeA() throws JobExecutionException { // TODO Auto-generated method stub logger.info("==========clean redis videojson"); //cleanRedis(); } /** * 每隔5分钟,执行一次 时间, * 在spring配置文件设置 dispatcher-servlet.xml */ public void cleanRedis(){ Pager pager = new Pager(1, 2000); pager.setSortname("dateAdded"); pager.setSortorder("desc"); List<M3u8Content> list = m3u8ContentDAO.findList(pager); if(list.size()>0){ for(int i=0;i<list.size();i++){ M3u8Content m3u8content = new M3u8Content(); cleanRedisVideoJSon(m3u8content.getVideoPoolId());//覆盖redis.videojson缓存 logger.info("定时程序, 覆盖redis.videojson缓存"); //更改状态 m3u8content.setStatus(8); m3u8ContentDAO.updateStatus(m3u8content); logger.info("定时程序, 修改m3u8_content的status的值为8"); } } } /** * 定时清除videoJson 的redis缓存 */ public void cleanRedisVideoJSon(String vid){ Jedis jedis = null; //String userid = vid.substring(0,10); //String jsonbody = JsonUtil.docToJson(vdoc); jedis = getPool().getResource(); String videokey = "videojson_"+vid; //String userkey = "userjson_"+userid; String videojson = jedis.get(videokey); if(!StringUtil.isFine(videojson)){ DOC vdoc = videoJson.videoJson(vid); if (vdoc!=null && vdoc.size()!=0){ videojson = JsonUtil.docToJson(vdoc); //预防缓存了空json if(videojson.length()>10){ jedis.set(videokey, videojson); } } } } /** * 测试方法 */ public void taskstart(){ System.out.println("init"); Pager pager = new Pager(1, 1000);// pager.setSortname("dateAdded");// pager.setSortorder("desc"); logger.info("================s=============="); List<M3u8Content> list = m3u8ContentDAO.findList(pager); logger.info("==================s============"+list.size()); logger.info("==================u============"); cleanRedisVideoJSon("fffdd2a8ecfdddfa9aee376070e1c759");//覆盖redis.videojson缓存 M3u8Content m3u8content = new M3u8Content(); m3u8content.setBitRateIndex(1); m3u8content.setVideoPoolId("fffdd2a8ecfdddfa9aee376070e1c759"); m3u8content.setStatus(8); m3u8ContentDAO.updateStatus(m3u8content); logger.info("==================u============"); logger.info("tomcat 测试方法"); }}
spring 定时任务调度设置:(在spring配置文件增加如下配置)
<!-- 配置 定时任务 videoJson.redisbegin Begin --><bean id="initJob" class="com.cc.ovp.web.video.CleanVideoJsonRedis" /> <!--定时器任务配置(开始)--> <!--配置JOB--> <bean id="initJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="initJob" /> <property name="targetMethod" value="executeA" /> <!-- <property name="arguments" /> --> </bean> <!--配置Trigger--> <bean id="initTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean"> <property name="jobDetail" ref="initJobDetail" /> <property name="startDelay" value="10000" /> <property name="repeatInterval" value="300000" /> <!-- <property name="repeatCount" value="0" /> --> </bean> <!--配置Scheduler--> <bean id="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" autowire="no"> <property name="triggers"> <list> <ref bean="initTrigger" /> </list> </property> <property name="autoStartup" value="true"/> </bean> <!--定时器任务配置(结束)--> <!-- 配置 定时任务 videoJson.redisbegin end -->
并发执行设置
是设置执行模式的,大概意思是:比如您设置了5分钟,可以在该任务执行之后的5分钟后继续执行下一次,就是上一次任务必须执行完毕之后执行下一次。还有就是无论上次任务有没有执行完毕,那么过五分钟之后继续执行下次任务。
<property name="concurrent" value="false" />
<!-- 配置 定时任务 videoJson.redisbegin Begin --><bean id="initJob" class="com.cc.ovp.web.video.CleanVideoJsonRedis" /> <!--定时器任务配置(开始)--> <!--配置JOB--> <bean id="initJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="initJob" /> <property name="targetMethod" value="executeA" /> <property name="concurrent" value="false" /> <!-- 不允许并发 --><!-- <property name="arguments" /> --> </bean> <!--配置Trigger--> <bean id="initTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean"> <property name="jobDetail" ref="initJobDetail" /> <property name="startDelay" value="10000" /> <property name="repeatInterval" value="1000" /> </bean> <!--配置Scheduler--> <bean id="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" autowire="no"> <property name="triggers"> <list> <ref bean="initTrigger" /> </list> </property> <property name="autoStartup" value="true"/> </bean> <!--定时器任务配置(结束)--> <!-- 配置 定时任务 videoJson.redisbegin end -->
或者使用Java的线程池实现:
public void execute() throws InterruptedException { System.out.println("Start job"); ExecutorService exec = Executors.newFixedThreadPool(1); Thread thread = new Thread(new Runnable() { @Override public void run() { System.out.println("thread start"); try { Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("thread end"); } }); exec.execute(thread); exec.shutdown(); while (!exec.isTerminated()) { // 等待所有子线程结束,才退出主线程 } System.out.println("end job"); }
OK,至此spring quartz多线程并发问题解决。回顾下,我们要使用isTerminated()方法等多线程结束后在结束job;多线程任务派发结束后,要使用shutdown()方法顺序关闭线程(等待正在执行任务,不接受新任务)
1 0
- Tomcat启动完毕后启动方法任务
- Tomcat启动完毕后启动方法任务
- Spring MVC项目启动时在容器加载完毕后插入一个定时任务
- Tomcat启动后自动执行某方法
- Tomcat启动真正完成后,执行方法
- CentOS 7下Tomcat启动后无法启动问题解决方法
- 任务:启动任务的方法
- 项目启动后开启定时任务方法-->ServletContextListener
- 项目启动后开启定时任务方法-->InitializingBean
- Tomcat自动启动后台任务
- Tomcat启动完成后再执行一个指定的方法 - 不影响Tomcat的启动时间
- Tomcat启动完成后再执行一个指定的方法 - 不影响Tomcat的启动时间
- 还是关于安装完毕后启动程序的问题
- Tomcat安装后启动一闪而过,启动失败
- 扩大myeclipse中tomcat启动后使用的内存方法
- Tomcat的启动方法
- window tomcat 启动方法
- tomcat的启动方法
- Hisi单独编译kernel
- django小技巧
- poj-3020-二分图最大匹配
- Android Fragment 真正的完全解析(上)(转自鸿洋大大)
- bzoj3754: Tree之最小方差树
- Tomcat启动完毕后启动方法任务
- 本地ORACLE忘记SYS用户密码解决方法
- 谷歌成立虚拟现实部门
- 数据库知识点总结
- live555 实现一个最简单的RTSP服务器
- Hibernate 一二级缓存的使用场景
- 文章标题 java 中文传值乱码问题
- mysql与oracle区别
- 通过live555实现H264 RTSP直播