有些人会遇到自己写了个监听器,继承了ServletContextListener,在Tomcat等服务器启动的时候contextInitialized方法被执行了两次,百思不得其解。
其实,实际上不是简单的contextInitialized方法被调用两次,是Tomcat被启动了两次(或者说放到Tomcat的webapps中的Web应用被启动了两次)
为什么这么说呢?(上面红色加粗的观点),因为像下面配置的一个Servlet,也是会被new两次的(可以在其init方法内打印语句,可以看到打印了两条!)。这就说明并不仅仅是contextInitialized被执行了两次,说明的是在web.xml中配置的启动Tomcat就new出Servlet的对象也被new了两次。进而可以把结论更加推广-------------------其实是整个Web应用被启动了两次,或者在网上有种更加通俗但我认为不准确的说法:Tomcat被启动了两次。
<servlet>
<servlet-name>ProxyBean</servlet-name>
<servlet-class>work.servlet.ServletProxy</servlet-class>
<init-param>
<param-name>targetBean</param-name>
<param-value>toHtml</param-value>
</init-param>
<load-on-startup>40</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ProxyBean</servlet-name>
<url-pattern>/ToHtml.do</url-pattern>
</servlet-mapping>
下面转载别人的文章,解决问题了。我是采用了把Web应用不放在Tomcat的webapps上,而放到与webapps之外与webapps文件夹同级的文件夹WEBROOT下
这个做法顺带还解决了以前一个矛盾的、纠结了很久的问题:为什么我的log4j记录日志会出现昨天的日志被今天的日志覆盖,用于只有一份最新的,log4j的配置文件是绝对绝对正确的。
前提:
1、存在某个应用:hello
2、该应用存放路径:D:\apache-tomcat-5.5.17\webapps\hello
3、Tomcat的server.xml部分配置信息如下:
...
<Context path="" reloadable="true" docBase="hello"/>
...
(这么做的目的就是为了将hello应用设为根,访问IP时就直接访问该应用)
4、hello下有一个 servlet(目的是为了系统在启动时执行某些初始化的操作),该servlet里存在init()方法,目前该方法里只打印“hello word”字符串;
5、hello 应用的 web.xml 部分配置信息如下:
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>HelloServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
问题:
在启动 tomcat5 时,控制台窗口会打印出两行“hello word”字符串?
问题原因:
因为hello应用本来就放在Tomat的默认webapp目录下(tomcat在启动时肯定会加载1次),然后又在server.xml中做了配置,为了达到访问根就可以访问hello应用(这样tomcat就又加载1次);结果,Tomcat就会加载两次。
解决办法:
办法1、不要将 hello 应用放在Tomat的默认webapp目录下,把它移出去,然后在server.xml中修改docBase的值为hello应用在新位置的绝对路径就可以了;
办法2、删除掉server.xml中 Context 的手动配置,这样就不会加载两次,因为hello应用在webapp下,所以在访问时,就只能是: 这样来访问了。
相关推荐
tomcat启动|退出执行事件类: import java.io.File; import java.io.FileWriter; import java.io.IOException; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import ...
这个监听器需要继承`javax.servlet.ServletContextListener`接口并实现其`contextInitialized`方法。在这个方法中,我们可以调用Servlet的URL,使其在Tomcat启动时被访问: ```java import javax.servlet.*; import...
当Tomcat服务器启动时,会触发`contextInitialized`方法,我们可以在该方法中初始化我们的`Timer`,设置好定时任务,这样就可以确保任务在服务器启动时一同运行。 以下是实现步骤: 1. 创建一个Java类,实现`...
在 ServletContextListener 接口中定义了处理 ServletContextEvent 事件的两个方法:contextInitialized() 和 contextDestroyed()。 contextInitialized() 方法是在 Servlet 容器启动 Web 应用时被调用的。在调用完...
当Web应用启动时,服务器会自动调用实现了`ServletContextListener`接口类的`contextInitialized`方法,而在Web应用停止时,会调用`contextDestroyed`方法。这为开发者提供了一个全局的、统一的入口点来执行一些初始...
在Java Web开发中,`ServletContextListener`是一个非常重要的接口,它是Servlet API的一部分,定义了两个方法:`contextInitialized`和`contextDestroyed`。这个接口的主要作用是监听Servlet上下文(`...
ServletContextListener接口有两个重要的方法:contextInitialized和contextDestroyed,这两个方法分别在Tomcat启动和关闭时被调用。我们可以在contextInitialized方法中执行游戏的主函数,以实现自启动。 三、计时...
`YourTimerInitializer`是一个自定义的监听器类,它需要实现`ServletContextListener`接口,并在`contextInitialized`方法中创建并启动定时器: ```java import javax.servlet.ServletContextEvent; import javax....
`ServletContextListener`是一个接口,它包含两个方法:`contextInitialized`和`contextDestroyed`。当Web应用程序启动时,服务器会调用`contextInitialized`方法,而在应用程序关闭时调用`contextDestroyed`。...
通过以上步骤,Web应用在启动时会自动运行`ServiceLoader.contextInitialized`,从而启动后台任务,而在应用关闭时,`ServiceLoader.contextDestroyed`会被调用,停止后台任务,确保了任务生命周期与Web应用同步。...
要创建一个`ServletContextListener`,你需要实现`javax.servlet.ServletContextListener`接口,并重写两个方法:`contextInitialized(ServletContextEvent sce)`和`contextDestroyed(ServletContextEvent sce)`。...
当Web应用启动时,监听器会自动触发`contextInitialized`方法,在这里可以创建并启动定时任务;而当应用关闭时,`contextDestroyed`方法会被调用,用于停止定时任务。在`web.xml`配置文件中添加监听器即可: ```xml...
- `contextInitialized()`:该方法会在Web应用被加载到容器中时调用。 - `contextDestroyed()`:该方法会在Web应用从容器卸载时调用。 3. **配置监听器**:接下来,在`web.xml`文件中注册这个监听器。 ##### 2.2 ...
例如,实现`ServletContextListener`需要覆盖`contextInitialized`和`contextDestroyed`方法。 5. **监听器与Servlet过滤器的区别** 监听器和Servlet过滤器都是处理Web应用程序生命周期的组件,但它们的焦点不同。...
这样,当项目启动时, InitListener 类的 contextInitialized 方法将被执行,从而执行指定的方法。 总结来说,使用 ServletContextListener 可以轻松地实现 Java 项目启动时执行指定方法。通过实现这个接口,我们...
要创建一个监听器,你需要编写一个类,实现`ServletContextListener`接口,并重写它的两个方法:`contextInitialized(ServletContextEvent sce)`和`contextDestroyed(ServletContextEvent sce)`。前者在Web应用启动...
这可能包括在`ServletContextListener`中创建数据库连接池,或者在应用程序启动时执行初始化脚本。 **源码分析** 标签中的“源码”意味着可能有关于实际代码实现的详细信息。在博文链接中,你可能会找到如何配置和...
在 NFDFlightDataTaskListener 类中,我们实现了 contextInitialized 方法,在这个方法中,我们创建了 TimerManager 对象,并启动了定时任务的执行。 知识点 6:web.xml 配置 在 web.xml 文件中,我们需要配置 ...
public void contextInitialized(ServletContextEvent sce) { JedisPoolConfig poolConfig = new JedisPoolConfig(); // 设置连接池相关配置 Set<HostAndPort> nodes = new HashSet(); // 添加Redis集群节点,...
这个接口有两个主要方法:`contextInitialized(ServletContextEvent event)`和`contextDestroyed(ServletContextEvent event)`。前者在Web应用启动时被调用,后者在Web应用关闭时被调用。我们可以利用这两个方法来...