`

Tomcat启动完毕后启动方法任务

阅读更多

        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.bijian.web.video;


import static com.bijian.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
 */
@Controller
public 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.bijian.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.bijian.web.video.CleanVideoJsonRedis</listener-class>
</listener>

        注意:<listener/> 标签一定要在<filter/>之后,在<servlet/>之前配置。

CleanVideoJsonRedis.java

package com.baijian.web.video;
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.bijian.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
 */
@Controller
public 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.bijian.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.bijian.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");  
}

        至此spring quartz多线程并发问题解决。回顾下,我们要使用isTerminated()方法等多线程结束后再结束job;多线程任务派发结束后,要使用shutdown()方法顺序关闭线程(等待正在执行任务,不接受新任务)。

 

文章来源:http://blog.csdn.net/kenhins/article/details/50514712

分享到:
评论

相关推荐

    quartz 随tomcat启动执行一次

    - **利用 Job 完成后停止调度器**:可以在 Job 中实现逻辑,在任务执行完毕后关闭调度器。这种方式需要更细致地控制 Job 的生命周期。 ```java public void execute(JobExecutionContext context) throws ...

    tomcat7连接eclipse配置

    总的来说,配置Eclipse与Tomcat 7的集成是一项基础且重要的任务,对于Java Web开发者来说必不可少。通过上述步骤,开发者能够快速地在Eclipse环境中建立开发环境,为后续的Web应用开发打下坚实的基础。随着对Eclipse...

    Tomcat线程池实现简介

    6. 任务执行完毕后,线程返回到线程池,重新标记为空闲,等待下次分配。 Tomcat的线程池设计注重平衡资源利用率和响应速度。通过控制线程的创建和销毁,避免频繁的线程创建销毁带来的性能开销。同时,`ThreadPool`...

    windows下配置nginx反向代理tomcat

    在 Windows 环境下配置 Nginx 作为 Tomcat 的反向代理服务器是一项常见的任务,主要用于实现负载均衡、提高安全性及提升性能等目的。本文将从下载 Nginx 开始,详细介绍如何在 Windows 系统上完成这一配置。 #### ...

    linux下tomcat安装配置.docx

    Linux环境下安装配置Tomcat是一个常见的任务,特别是在需要运行基于Java的Web应用程序时。Tomcat作为Apache软件基金会Jakarta项目的组成部分,是一个开源且免费的Web应用服务器,特别适合于中小型系统和并发访问用户...

    普元启动服务失败的解决方法.pdf

    将查询结果在新的SQL窗口中执行,执行完毕后重新启动服务。 此外,如果遇到EOS连接失败的问题,可以查看是否有被锁的对象。使用以下查询查看所有被锁对象: ```sql select * from v$locked_object; ``` 进一步确定...

    Linux下配置jdk-tomcat-vsftpd

    配置完毕后,可以通过启动Tomcat的`startup.sh`脚本来启动服务,使用`shutdown.sh`脚本来停止服务。在浏览器中输入`http://localhost:8080`,如果能看到Tomcat的欢迎页面,说明Tomcat已经成功运行。 最后,配置...

    redhat LINUX5.0上安装oracle 10g tomcat5 jdk帮助文档

    在Redhat LINUX5.0操作系统上安装Oracle 10g、Tomcat5和JDK是一项技术性较强的任务,涉及到多个层面的知识点。首先,我们来详细解析这些关键组件的安装和配置过程。 1. **Oracle 10g安装**: Oracle 10g是一款关系...

    Java Web应用开发 06 课堂案例-安装与配置Tomcat.docx

    安装完成后,任务栏右下角会出现Tomcat的服务图标。若未启动,图标显示为红色。启动Tomcat服务,可以通过右键点击图标,选择"Start Service"。启动后,图标变为绿色三角形。同样,你可以通过"Stop Service"来停止...

    how tomcat works

    2. **初始化生命周期监听器**:根据配置,初始化一系列监听器,用于在特定生命周期事件(如启动、停止等)中执行特定任务。 3. **启动Connector**:Coyote组件负责监听网络端口,接收HTTP请求。 4. **启动Engine**:...

    Linux下安装Tomcat7.0.82的简单方法

    在Linux系统中安装Apache Tomcat 7.0.82是一个常见的任务,尤其对于那些需要部署Java Web应用程序的开发者来说。下面将详细介绍如何在Linux环境下简单有效地安装Tomcat 7.0.82。 首先,我们需要获取Apache Tomcat的...

    linux下apache2.2整合tomcat6详细步骤.docx

    完成上述步骤后,Apache2.2和Tomcat6就已经整合完毕,可以通过Apache访问部署在Tomcat上的Java Web应用程序了。注意,在实际操作中可能需要根据具体的系统环境和需求进行调整,例如端口设置、防火墙规则等。

    Tomcat9安装windows服务的详细教程

    解压完毕后,需要进入Tomcat的bin目录找到service.bat文件,并对其进行编辑。通常编辑操作需要打开命令提示符cmd(如果权限不足,以管理员身份运行)。 在service.bat中,可以通过搜索"setSERVICE_NAME="来设置服务...

    详解windows 10中Tomcat安装和部署的教程

    在Windows 10操作系统中,安装和部署Apache Tomcat服务器是一项基本的任务,这对于开发者和运维人员来说至关重要。本文将详细讲解这一过程,分为两个主要部分:Java环境的配置和Tomcat的安装与部署。 首先,Java...

    配置好的solr启动环境

    Solr,全称为Apache Solr,是一款开源的全文搜索引擎,被广泛应用于企业级...一旦配置完毕,通过Tomcat启动Solr,便可以开始进行高效的全文搜索了。这个预配置的环境为你提供了快速上手的基础,大大简化了部署流程。

    浅谈Tomcat乱码与端口占用的解决方案

    修改完毕后重启Tomcat服务器,乱码问题应该会被解决。 其次,关于Tomcat端口占用的问题,这通常发生在服务器尝试绑定到一个已经被其他进程使用的端口上。在Windows系统中,可使用命令行工具netstat -ano来查看哪个...

    在Win10上安装Tomcat服务器及配置环境变量的详细教程(图文)

    解压完毕后,接下来就是启动Tomcat服务器。在Tomcat的bin目录里双击运行startup.bat文件,如果成功启动,浏览器输入地址“***.*.*.*:8080”或“localhost:8080”便可以访问Tomcat的主界面。 在使用Tomcat过程中,...

    手动启动JobExecutorServlet

    首先,我们需要在`web.xml`中将JobExecutorServlet的配置暂时注释掉,防止它在Tomcat启动时自动加载。以下是相关的XML配置段: ```xml &lt;!-- &lt;servlet-name&gt;JobExecutorServlet &lt;servlet-class&gt;org.jbpm.job....

Global site tag (gtag.js) - Google Analytics