Tomcat启动完成后再执行一个指定的方法 - 不影响Tomcat的启动时间
程序员文章站
2022-07-12 12:18:59
...
本文主要介绍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.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 swang6@ebay.com */ @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中的配置
<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接口的任务实现类 :
- public class InitJob implements Job {
- @Override
- public void execute(JobExecutionContext arg0) throws JobExecutionException {
- // TODO Auto-generated method stub
- }
- public void executeA() throws JobExecutionException {
- // TODO Auto-generated method stub
- .........
- }
Spring配置文件中配置的任务
- <bean id="initJob" class="com.xxx.services.InitJob" />
- <!--定时器任务配置(开始)-->
- <!--配置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="1000" />
- <property name="repeatInterval" value="0" />
- <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>
- <!--定时器任务配置(结束)-->