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()),啓動另一個線程來執行,具體代碼如下。

 

Java代碼 複製代碼 收藏代碼
  1. /**  
  2.  *   
  3.  */  
  4. package com.ebay.montage.pm;   
  5.   
  6.   
  7. import java.util.concurrent.Callable;   
  8. import java.util.concurrent.FutureTask;   
  9.   
  10. import javax.servlet.ServletException;   
  11. import javax.servlet.http.HttpServlet;   
  12.   
  13. import org.apache.log4j.Logger;   
  14. import org.springframework.beans.factory.annotation.Value;   
  15. import org.springframework.scheduling.annotation.Scheduled;   
  16. import org.springframework.stereotype.Component;   
  17.   
  18. import com.ebay.montage.pm.collector.NucleonEventDataCollector;   
  19. import com.ebay.montage.pm.constants.CMConstants;   
  20. import com.ebay.montage.pm.utils.ConfigurationUtils;   
  21. import com.ebay.montage.pm.utils.LoggerUtils;   
  22. import com.ebay.system.ShutdownAwaitLatch;   
  23.   
  24. /**  
  25.  * Trigger to consume data from Nucleon Event Bus  
  26.  *   
  27.  * @author Josh Wang(Sheng)  
  28.  *  
  29.  * @email  [email protected]  
  30.  */  
  31. @Component("processor")   
  32. public class NucleonEventProcessor extends HttpServlet {   
  33.        
  34.     private static final long serialVersionUID = -9045451275234606838L;   
  35.   
  36.     private static final Logger log = Logger.getLogger(NucleonEventProcessor.class);   
  37.        
  38.     // Servlet的init方法會在Tomcat啓動的時候執行   
  39.     @Override  
  40.     public void init() throws ServletException {   
  41.         FutureTask<String> task = new FutureTask<String>(new Callable<String>(){   
  42.   
  43.            @Override  
  44.            public String call() throws Exception {   
  45.         start(); // 使用另一個線程來執行該方法,會避免佔用Tomcat的啓動時間   
  46.         return "Collection Completed";   
  47.            }   
  48.                
  49.         });   
  50.            
  51.         new Thread(task).start();   
  52.     }   
  53.   
  54.         // 希望Tomcat啓動結束後執行的方法   
  55.     private void start() {   
  56.         if (ConfigurationUtils.isEnableEventCollector()) {   
  57.             String topic = CMConstants.NUCLEON_EVENT_TOPIC;   
  58.                
  59.             new NucleonEventDataCollector().collect(topic);   
  60.                
  61.             LoggerUtils.info(log, "NuclenonEventDataCollector started to consume data from Collector Bus - NUCLEON_EVENT_TOPIC: " + topic);        
  62.             new ShutdownAwaitLatch().awaitForShutdown();   
  63.             LoggerUtils.info(log, "Complete processing and publishing Event Data");   
  64.   
  65.         } else {   
  66.             log.info("There disable the collector, please enable it on dev/qa/prod property if needed");   
  67.         }   
  68.            
  69.     }   
  70.   
  71.   
  72. }  
/**
 * 
 */
package com.ebay.montage.pm;


import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.ebay.montage.pm.collector.NucleonEventDataCollector;
import com.ebay.montage.pm.constants.CMConstants;
import com.ebay.montage.pm.utils.ConfigurationUtils;
import com.ebay.montage.pm.utils.LoggerUtils;
import com.ebay.system.ShutdownAwaitLatch;

/**
 * Trigger to consume data from Nucleon Event Bus
 * 
 * @author Josh Wang(Sheng)
 *
 * @email  [email protected]
 */
@Component("processor")
public class NucleonEventProcessor extends HttpServlet {
	
	private static final long serialVersionUID = -9045451275234606838L;

	private static final Logger log = Logger.getLogger(NucleonEventProcessor.class);
	
	// Servlet的init方法會在Tomcat啓動的時候執行
	@Override
	public void init() throws ServletException {
		FutureTask<String> task = new FutureTask<String>(new Callable<String>(){

	       @Override
	       public String call() throws Exception {
		start(); // 使用另一個線程來執行該方法,會避免佔用Tomcat的啓動時間
		return "Collection Completed";
	       }
			
		});
		
		new Thread(task).start();
	}

        // 希望Tomcat啓動結束後執行的方法
	private void start() {
		if (ConfigurationUtils.isEnableEventCollector()) {
			String topic = CMConstants.NUCLEON_EVENT_TOPIC;
			
			new NucleonEventDataCollector().collect(topic);
			
			LoggerUtils.info(log, "NuclenonEventDataCollector started to consume data from Collector Bus - NUCLEON_EVENT_TOPIC: " + topic);		
			new ShutdownAwaitLatch().awaitForShutdown();
			LoggerUtils.info(log, "Complete processing and publishing Event Data");

		} else {
			log.info("There disable the collector, please enable it on dev/qa/prod property if needed");
		}
		
	}


}

 web.xml中的配置

 

 

 

Java代碼 複製代碼 收藏代碼
  1. <servlet>   
  2.     <servlet-name>event-collector</servlet-name>   
  3.     <servlet-class>com.ebay.montage.pm.NucleonEventProcessor</servlet-class>   
  4.     <load-on-startup>5</load-on-startup>   
  5. </servlet>   
  6.   
  7. <servlet-mapping>   
  8.     <servlet-name>event-collector</servlet-name>   
  9.     <url-pattern>/event-collect</url-pattern>   
  10. </servlet-mapping>  
    <servlet>
    	<servlet-name>event-collector</servlet-name>
    	<servlet-class>com.ebay.montage.pm.NucleonEventProcessor</servlet-class>
    	<load-on-startup>5</load-on-startup>
    </servlet>
    
    <servlet-mapping>
    	<servlet-name>event-collector</servlet-name>
    	<url-pattern>/event-collect</url-pattern>
    </servlet-mapping>

 

 

方法二:使用Spring的Timer或者是著名的Quartz在Tomcat啓動後再執行該方法,Spring中的Timer非常簡單,這個地方不想講解了,Quartz相對更復雜些,下面主要介紹下在Spring中怎麼樣使用Quartz來實現上面的需求:

實現Job接口的任務實現類 :

Java代碼  收藏代碼
  1. public class InitJob implements Job {  
  2.   
  3.     @Override  
  4.     public void execute(JobExecutionContext arg0) throws JobExecutionException {  
  5.         // TODO Auto-generated method stub  
  6.     }  
  7.       
  8.     public void executeA() throws JobExecutionException {  
  9.         // TODO Auto-generated method stub  
  10.         .........  
  11.     }  

 

 

Spring配置文件中配置的任務 

Xml代碼  收藏代碼
  1. <bean id="initJob" class="com.xxx.services.InitJob" />  
  2. <!--定時器任務配置(開始)-->       
  3.     <!--配置JOB-->  
  4.     <bean id="initJobDetail"  
  5.         class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">  
  6.         <property name="targetObject" ref="initJob" />  
  7.         <property name="targetMethod" value="executeA" />  
  8. <!--         <property name="arguments" /> -->  
  9.     </bean>  
  10.     <!--配置Trigger-->  
  11.     <bean id="initTrigger"    
  12.         class="org.springframework.scheduling.quartz.SimpleTriggerBean">    
  13.         <property name="jobDetail" ref="initJobDetail" />    
  14.         <property name="startDelay" value="1000" />  
  15.         <property name="repeatInterval" value="0" />  
  16.         <property name="repeatCount" value="0" />  
  17.     </bean>  
  18.     <!--配置Scheduler-->  
  19.     <bean id="schedulerFactory"    
  20.         class="org.springframework.scheduling.quartz.SchedulerFactoryBean" autowire="no">    
  21.         <property name="triggers">    
  22.             <list>    
  23.                 <ref bean="initTrigger" />    
  24.             </list>    
  25.         </property>    
  26.         <property name="autoStartup" value="true"/>  
  27.     </bean>  
  28.     <!--定時器任務配置(結束)-->  
發佈了3 篇原創文章 · 獲贊 3 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章