tomcat 创建多少个tomcat listenerstart 实例

2000人阅读
javaWeb(8)
使用ServletContextListener在服务器启动和关闭时创建和关闭缓存。ServletContext 被 Servlet 程序用来与 Web 容器通信。例如写日志,转发请求。每一个 Web 应用程序含有一个Context,被Web应用内的各个程序共享。因为Context可以用来保存资源并且共享,所以我所知道的 ServletContext 的最大应用是Web缓存----把不经常更改的内容读入内存,所以服务器响应请求的时候就不需要进行慢速的磁盘I/O了。
ServletContextListener 是 ServletContext 的监听者,如果 ServletContext 发生变化,如服务器启动时 ServletContext 被创建,服务器关闭时 ServletContext 将要被销毁。
在JSP文件中,application 是 ServletContext 的实例,由JSP容器默认创建。Servlet 中调用 getServletContext()方法得到 ServletContext 的实例。
我们使用缓存的思路大概是:
1 : 服务器启动时,ServletContextListener 的 contextInitialized()方法被调用,所以在里面创建好缓存。可以从文件中或者从数据库中读取取缓存内容生成类,用 servletContext.setAttribute()方法将缓存类保存在 ServletContext 的实例中。
2 : 程序使用 ServletContext.getAttribute()读取缓存。如果是 JSP,使用
application.getAttribute()
如果是 Servlet,使用
getServletContext().getAttribute()
如果缓存发生变化(如访问计数),你可以同时更改缓存和文件/数据库。或者你等 变化积累到一定程序再保存,也可以在下一步保存。
3 : 服务器将要关闭时,ServletContextListener 的 contextDestroyed()方法被调用,所以在里面保存缓存的更改。将更改后的缓存保存回文件或者数据库,更新原来的内容。
//my&own&classimport&DatabaseM&
//&my&own&classimport&javax.servlet.ServletC
import&javax.servlet.ServletContextL
public&class&MyContextListener&implements&ServletContextListener&{
&&&&private&ServletContext&context&=&null;&
&&&&public&void&contextInitialized(ServletContextEvent&event)&{&&
&&&&&&&&context&=&event.getServletContext();&&
&&&&&&&&User&user&=&DatabaseManager.getUserById(1);&&
&&&&&&&&context.setAttribute(&user1&,&user);
&&&&public&void&contextDestroyed(ServletContextEvent&event)&{&&
&&&&&&&&User&user&=&(User)context.getAttribute(&user1&);&&
&&&&&&&&DatabaseManager.updateUserData(user);&&
&&&&&&&&this.context&=&null;&
布署 ServletContextListener
你实现(implements)了 ServletContextListener 编译后,把它放在正确的WEB-INF/classes目录下,更改WEB-INF目录下的 web.xml文件,在web-app节点里添加
&listener&&
&&&&&listener-class&MyServletContextListener&/listener-class&
&/listener&
最后,掌握这个的用处:
1、tomcat一启动就把字典表的数据或.properties文件的内容加载到内存。可以定义一个静态常量类来存放。
public class cunfangConstants {
&&& public static String ServerIP =
&& &public static String username=
public&class&MyContextListener&implements&ServletContextListener&{
&&&&private&ServletContext&context&=&null;&
&&&&public&void&contextInitialized(ServletContextEvent&event)&{&&
&&&&&&&&cunfangConstants.ServerIP=&1.1.1.1&;//这里写死了,具体ip地址可以从数据库里取,或者从.properties文件里取
&&&&public&void&contextDestroyed(ServletContextEvent&event)&{&
&&&&&&&cunfangConstants.ServerIP=&null;&
这样就实现了把数据库或者.properties文件的内容加载到了cunfangConstants类中,以后在java里只需调用它(cunfangConstants.ServerIP)就行。
在jsp中除了上面提到application.getAttribute()可以调用外,还可以这样调用:
&%@ page language=&java& contentType=&text/ charset=UTF-8&
&&& pageEncoding=&UTF-8& isErrorPage=&true& %&
&&%@ page import=&com.supc.wczw.cunfangConstants& language=&java&%&&
&&%@ page import=&java.lang.String& language=&java&%&
&!DOCTYPE HTML PUBLIC &-//W3C//DTD HTML 4.01//EN& &http://www.w3.org/TR/html4/strict.dtd&&
&title&&/title&&
&script type=&text/javascript&&
&& &alert('&%=cunfangConstants.ServerIP%&');//调用
&/script& &
&/head&&& &
===================================================
【附:JSP中Application的具体用例】
JSP中Application有两种含义,第一,表示四种属性范围中的“服务器范围”。第二,表示一个内置对象(JSP有九大内置对象)。综合起来也就是说,它是这么一个对象,当服务器打开时它就创建,服务器关闭时,它就消失。
范例:监视器实现,
ServletContextAttribute.jsp:
&%@ page language=&java& import=&java.util.*& pageEncoding=&ISO-8859-1&%&
  &head&
    &title&My JSP 'ServletContextAttribute.jsp' starting page&/title&
  &/head&
  &body&
    &%
      application.setAttribute(&name&,&Hello&) ;
      application.removeAttribute(&name&) ;
    %&
  &/body&
ServletContextListenerDemo.java:
package org.lxh.listener.
import javax.servlet.ServletContextAttributeE
import javax.servlet.ServletContextAttributeL
import javax.servlet.ServletContextE
import javax.servlet.ServletContextL
public class ServletContextListenerDemo implements
    ServletContextAttributeListener, ServletContextListener {
  public void attributeAdded(ServletContextAttributeEvent arg0) {
    System.out.println(&** 增加属性:& + arg0.getName() + & --& & + arg0.getValue()) ;
  public void attributeRemoved(ServletContextAttributeEvent arg0) {
    System.out.println(&** 删除属性:& + arg0.getName() + & --& & + arg0.getValue()) ;
  public void attributeReplaced(ServletContextAttributeEvent arg0) {
    System.out.println(&** 替换属性:& + arg0.getName() + & --& & + arg0.getValue()) ;
  public void contextDestroyed(ServletContextEvent arg0) {
    System.out.println(&** 容器销毁:& + arg0.getServletContext().getRealPath(&/&));
  public void contextInitialized(ServletContextEvent arg0) {
    System.out.println(&** 容器初始化:& + arg0.getServletContext().getRealPath(&/&));
===================================================================================
若对ServletContextListener还不了解的话,转一遍详细介绍ServletContextListener的文章:
&& 在Servlet API中有一个ServletContextListener接口,它能够监听ServletContext对象的生命周期,实际上就是监听Web应用的生命周期。
&& 当Servlet容器启动或终止Web应用时,会触发ServletContextEvent事件,该事件由 ServletContextListener 来处理。在 ServletContextListener 接口中定义了处理&&&& ServletContextEvent事件的两个方法。
&& contextInitialized(ServletContextEvent sce):当Servlet容器启动Web应用时调用该方法。在调用完该方法之后,容器再对Filter初始化,并且对那些在Web应用启动时就需要&&& 被初始化的Servlet进谐跏蓟?/P&
&&&& contextDestroyed(ServletContextEvent sce):当Servlet容器终止Web应用时调用该方法。在调用该方法之前,容器会先销毁所有的Servlet和Filter过滤器。
下面通过一个例子来介绍ServletContextListener的用法。本章4.4.1节的例程4-9的CounterServlet类只能统计当Web应用启动后,网页被客户端访问的次数。如果重新启动Web应用,计数器又会重新从1开始统计访问次数。在实际应用中,往往需要统计自Web应用被发布后网页被客户端访问的次数,这就要求当Web应用被终止时,计数器的数值被永久存储在一个文件中或者数据库中,等到Web应用重新启动时,先从文件或数据库中读取计数器的初始值,然后在此基础上继续计数。
向文件中写入或读取计数器的数值的功能可以由自定义的 MyServletContextListener类(参见例程4-11)来完成,它具有以下功能:
在 Web 应用启动时从文件中读取计数器的数值,并把表示计数器的 Counter对象存放到 Web 应用范围内。存放计数器的文件的路径为helloapp/count/count.txt。
在Web应用终止时把Web应用范围内的计数器的数值保存到count.txt文件中。
例程4-11 MyServletContextListener.java
public class MyServletContextListener implements ServletContextListener{
public void contextInitialized(ServletContextEvent sce){
System.out.println(&helloapp application is Initialized.&);
&&& //获取ServletContext对象
ServletContext context=sce.getServletContext();
//从文件中读取计数器的数值
BufferedReader reader=new BufferedReader(
new InputStreamReader(context.
getResourceAsStream(&/count/count.txt&)));
int count=Integer.parseInt(reader.readLine());
reader.close();
&&&&& //创建计数器对象
Counter counter=new Counter(count);
//把计数器对象保存到Web应用范围
context.setAttribute(&counter&,counter);
}catch(IOException e){e.printStackTrace();}
public void contextDestroyed(ServletContextEvent sce){
System.out.println(&helloapp application is Destroyed.&);
&&& //获取ServletContext对象
ServletContext context=sce.getServletContext();
&&& //从Web应用范围获得计数器对象
Counter counter=(Counter)context.getAttribute(&counter&);
&&& if(counter!=null){
//把计数器的数值写到count.txt文件中
String filepath=context.getRealPath(&/count&);
filepath=filepath+&/count.txt&;
PrintWriter pw=new PrintWriter(filepath);
pw.println(counter.getCount());
pw.close();
}catch(IOException e){e.printStackTrace();}
用户自定义的MyServletContextListener监听器只有先向Servlet容器注册,Servlet容器在启动或终止Web应用时,才会调用该监听器的相关方法。在web.xml文件中,&listener&元素用于向容器注册监听器:
下面按如下步骤演示MyServletContextListener监听器的作用。
(1)在helloapp/count目录下创建count.txt文件,在该文件中存放了一个数字“5”。
(2)启动 Tomcat。在浏览器中通过&&访问CounterServlet,在第一次访问该Servlet时,浏览器端显示计数器的值为5。
(3)刷新上述访问 CounterServlet 的页面,会看到每刷新一次,计数器的值增加1,假定最后一次刷新后的计数器的值为10。
(4)手工终止helloapp应用。查看helloapp/count/count.txt文件,会发现在该文件中存放的数字变为10。
(5)手工重新启动 helloapp 应用。在浏览器中再次访问 CounterServlet,当第一次访问该Servlet时,浏览器端显示计数器的值为10。
从上述实验中可以看出,MyServletContextListener 监听器与 CounterServlet 共享Web应用范围内的代表计数器的Counter对象。监听器在Web应用启动或终止时会操纵Counter对象,而Servlet在每次响应客户请求时会操纵Counter对象。
观察MyServletContextListener及本章4.3.4节的名为lifeInit的 LifeServlet在 Tomcat 控制台的打印结果的先后顺序,会发现当 Web 应用启动时,Servlet容器先调用MyServletContextListener的contextInitialized()方法,再调用lifeInit的init()方法;当Web应用终止时,Servlet容器先调用lifeInit的destroy()方法,再调用MyServletContextListener的contextDestroyed()方法。由此可见,在Web应用的生命周期中,ServletContext对象最早被创建,最晚被销毁
ServletContextListener接口有两方需要实现的方法:contextInitialized()和contextDestroyed();
Listener,译为监听者.顾名思义,它会监听Servlet容器,当应用开始的时候它会调用contextInitialized()方法;
当应用关闭的时候,它同样会调用contextDestroyed()方法.我们可以利用这个特性初始化一些信息,当然我们
也可以利用Servlet类init()方法,并在配置文件中让它启动应用的时候就执行,并且在关闭的时候执行destroy()方
法.但是继承此接口应该更符合容器的应用.
&listener&
&listener-class&mypack.MyServletContextListener&listener-class /&
&/listener&
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场从零认识tomcat,构建一机多实例tomcat集群
从零认识tomcat,构建一机多实例tomcat集群
& & & && &&从零认识tomcat,构建一机多实例tomcat集群1、了解tomcatTomcat不是一个完整意义上的Jave EE(j2ee)服务器,因为它没有提供完整的Java EE企业应用平台的API。但是由于Tomcat遵循apache开源协议,并且对当前Java开发框架开源组件Structs、Spring和Hibernate等实现完美支持,因此tomcat被众多企业用来部署配置众多的Java应用程序,实现替代一些商业的Java应用服务器。2、Tomcat的目录结构要部署使用tomcat,则必须了解tomcat的目录结构以及各目录的作用。这里以tomcat7为例安装Tomcat,再次不在阐述,进入tomcat安装目录下:|-- bin| & |-- bootstrap.jar
tomcat启动时所依赖的一个类,在启动tomcat时会发现Using CLASSPATH: 是加载的这个类| & |-- catalina-tasks.xml
定义tomcat载入的库文件,类文件| & |-- catalina.bat| & |-- catalina.sh
& & & & & & & & &tomcat单个实例在Linux平台上的启动脚本| & |-- commons-daemon-native.tar.gz & & & & & &jsvc工具,可以使tomcat已守护进程方式运行,需单独编译安装| & |-- commons-daemon.jar
& & & & & &jsvc工具所依赖的java类| & |-- configtest.bat| & |-- configtest.sh & & & &&tomcat检查配置文件语法是否正确的Linux平台脚本| & |-- cpappend.bat| & |-- daemon.sh
tomcat已守护进程方式运行时的,启动,停止脚本| & |-- digest.bat| & |-- digest.sh| & |-- setclasspath.bat| & |-- setclasspath.sh| & |-- shutdown.bat| & |-- shutdown.sh
tomcat服务在Linux平台下关闭脚本| & |-- startup.bat| & |-- startup.sh
& & & & &tomcat服务在Linux平台下启动脚本| & |-- tomcat-juli.jar| & |-- tomcat-native.tar.gz &使tomcat可以使用apache的apr运行库,以增强tomcat的性能需单独编译安装| & |-- tool-wrapper.bat| & |-- tool-wrapper.sh| & |-- version.bat| & `-- version.sh
查看tomcat以及JVM的版本信息|-- conf
顾名思义,配置文件目录| & |-- catalina.policy
配置tomcat对文件系统中目录或文件的读、写执行等权限,及对一些内存,session等的管理权限| & |-- catalina.properties
配置tomcat的classpath等| & |-- context.xml
tomcat的默认context容器| & |-- logging.properties
配置tomcat的日志输出方式| & |-- server.xml
& & & &tomcat的主配置文件| & |-- tomcat-users.xml & & & &tomcat的角色(授权用户)配置文件| & `-- web.xml
tomcat的应用程序的部署描述符文件|-- lib|-- logs
日志文件默认存放目录|-- temp| & `-- safeToDelete.tmp|-- webapps
& & & & &&tomcat默认存放应用程序的目录,好比apache的默认网页存放路径是/var/www/html一样| & |-- docs tomcat文档| & |-- examples & & & & & & & & & & tomcat自带的一个独立的web应用程序例子| & |-- host-manager & & & & & & &tomcat的主机管理应用程序| | & |-- META-INF & & & & &&整个应用程序的入口,用来描述jar文件的信息| | & | & `-- context.xml & &&当前应用程序的context容器配置,它会覆盖tomcat/conf/context.xml中的配置| | & |-- WEB-INF
&用于存放当前应用程序的私有资源| | & | & |-- classes
&用于存放当前应用程序所需要的class文件| & & & | & | |-- lib
& & & & &用于存放当前应用程序锁需要的jar文件| | & | & `-- web.xml
当前应用程序的部署描述符文件,定义应用程序所要加载的serverlet类,以及该程序是如何部署的| & |-- manager & & & & & & & & &tomcat的管理应用程序| & |-- ROOT & & & & & & &指tomcat的应用程序的根,如果应用程序部署在ROOT中,则可直接通过http://ip:port 访问到`-- work 用于存放JSP应用程序在部署时编译后产生的class文件3、了解tomcat的主配置文件(server.xml)结构及含义如下图所示,前端请求被tomcat直接接收或者由前端的代理,通过HTTP,或者AJP代理给Tomcat,此时请求被tomcat中的connector接收,不同的connector和Engine被service组件关联起来,在一个Engine中定义了许多的虚拟主机,由Host容器定义,每一个Host容器代表一个主机,在各自的Host中,又可以定义多个Context,用此来定义一个虚拟主机中的多个独立的应用程序。4、单实例应用程序配置一例由以上配置不难看出存在的一个问题。如果我们想要对其中一个应用程序的配置做一些修改,那么就必须重新启动tomcat,那样势必就会影响到另外两个应用程序的正常服务。因此以上配置是不适合线上使用的,因此需要将其配置为多实例,每个实例只跑一个独立的应用程序,那样我们应用程序之间就不会在互相受到影响。但是我们将面临这样一个问题,80端口只能被一个HTTP/1.1 Connector监听,而三个tomcat实例则至少需要3个HTTP/1.1 Connector,这样我们就需要一个前端代理做分发处理,接收HTTP 80端口的请求,按域名通过每个tomcat实例的AJP/1.3 Connector传递请求。而前端的代理选择apache,基于这样的思路,我们还可以做到tomcat的负载均衡,而且apache会将接收的HTTP超文本传输报文重新封装成二进制格式通过AJP/1.3 协议传递给后端的tomcat处理,在效率上也是有明显的提升。5、结合apache构造多实例tomcat集群apache结合tomcat的方式主要有三种:mod_jk,ajp_proxy,http_proxy(以http协议代理给tomcat),而当前使用最多的还是要数mod_jk。因为mod_jk出现的较早,技术已经相当成熟,而且具备集群节点健康检测功能,支持大型的AJP数据包。安装apache,tomcat这里不在详述,需要了解,安装tomcat-connectorstar zxvf tomcat-connectors-1.2.30-src.tar.gzcd tomcat-connectors/src./configure --with-apxs=/usr/local/apache/bin/apxsmake && make install①单独建立httpd-jk.conf单独建立httpd-jk.conf文件用来配置mod_jk的相关设置vim /usr/local/apache2/conf/extra/httpd-jk.confLoadModule jk_module modules/mod_jk.so# 配置apache装载mod_jk.so模块JkWorkersFile /usr/local/apache/conf/extra/workers.properties# 指定保存了worker相关工作属性定义的配置文件JkLogFile /usr/local/apache/logs/mod_jk.log# 定义mod_jk模块的日志文件JkLogLevel info# 定义mod_jk模块日志的记录级别②建立worker相关工作属性定义的配置文件vim /usr/local/apache/conf/extra/workers.propertiesworker.list=Cluster1,statworker.web2.port=8003worker.web2.host=172.23.138.19worker.web2.type=ajp13worker.web2.lbfactor=1worker.web3.port=8003worker.web3.host=172.23.136.144worker.web3.type=ajp13worker.web3.lbfactor=1worker.Cluster1.type=lbworker.Cluster1.balance_workers=web2,web3worker.Cluster1.sticky_session = 1worker.stat.type=statusworker.list=Cluster2worker.manager2.port=7003worker.manager2.host=172.23.138.19worker.manager2.type=ajp13worker.manager2.lbfactor=1worker.manager3.port=7003worker.manager3.host=172.23.136.144worker.manager3.type=ajp13worker.manager3.lbfactor=1worker.Cluster2.type=lbworker.Cluster2.balance_workers=manager2,manager3worker.Cluster2.sticky_session = 1③配置后端tomcat多实例使用脚本快速部署tomcat实例,修改新实例的AJP/1.3 Connector的监听端口,HTTP/1.1 Connector的监听端口以及Server容器的监听端口。脚本内容如下:现在后端每台tomcat节点的配置状况如下:实例:&Server port="8000"&&Connector port="8001" protocol="HTTP/1.1"&&Connector port="8003" protocol="AJP/1.3"&&/Server&实例:&Server port="7000"&&Connector port="7001" protocol="HTTP/1.1"&&Connector port="7003" protocol="AJP/1.3"&&/Server&使用新实例中的tomcat.sh进行启动每个实例&④配置多域名的负载均衡vim /usr/local/apache/conf/extra/httpd-vhosts.confNameVirtualHost *:80&VirtualHost *:80&& & ServerName & & JkMount /* Cluster1&/VirtualHost&&VirtualHost *:80&& & ServerName & & JkMount /* Cluster2& & JkMount /status stat&/VirtualHost&&到此基于多域名多实例的tomcat负载均衡集群构建完成,启动apache即可,基于当前结构还可结合持久会话管理器(PersistentManager)来实现会话持久的效果。文档摘录:http://grass51./3400
发表评论:
TA的最新馆藏[转]&[转]&这个J2EE小提示阐述了ServletContextListener的用法。这个事件类作为Web应用服务的一部分,处理Web应用的 servlet上下文(context)的变化的通知。这可以解释为,好像有个人在服务器旁不断地通知我们服务器在发生什么事件。那当然需要监听者了。因此,在通知上下文(context)初始化和销毁的时候,ServletContextListner非常有用。
Java代码 &
package&com. &&
import&javax.servlet.ServletContextL &&
import&javax.servlet.ServletContextE &&
import&javax.servlet.*; &&
public&class&MyContextListener&implements&ServletContextListener&{ &&
private&ServletContext&context&=&null; &&
&public&void&contextDestroyed(ServletContextEvent&event){ &&
&&System.out.println("The&Simple&Web&App.&Has&Been&Removed"); &&
&&this.context&=&null; &&
public&void&contextInitialized(ServletContextEvent&event){ &&
&&this.context&=&event.getServletContext(); &&
&&System.out.println("The&Simple&Web&App.&Is&Ready"); &&
package&com.&&
import&javax.servlet.ServletContextL&&
import&javax.servlet.ServletContextE&&
import&javax.servlet.*;&&
public&class&MyContextListener&implements&ServletContextListener&{&&
private&ServletContext&context&=&null;&&
&public&void&contextDestroyed(ServletContextEvent&event){&&
&&System.out.println("The&Simple&Web&App.&Has&Been&Removed");&&
&&this.context&=&null;&&
public&void&contextInitialized(ServletContextEvent&event){&&
&&this.context&=&event.getServletContext();&&
&&System.out.println("The&Simple&Web&App.&Is&Ready");&&
package com.
import javax.servlet.ServletContextL
import javax.servlet.ServletContextE
import javax.servlet.*;
public class MyContextListener implements ServletContextListener {
private ServletContext context =
public void contextDestroyed(ServletContextEvent event){
//Output a simple message to the server's console
System.out.println("The Simple Web App. Has Been Removed");
this.context =
// 这个方法在Web应用服务做好接受请求的时候被调用。
public void contextInitialized(ServletContextEvent event){
this.context = event.getServletContext();
//Output a simple message to the server's console
System.out.println("The Simple Web App. Is Ready");
在WEB.XML中
&&&com.listeners.MyContextListener &&
&&&com.listeners.MyContextListener&&
&listener&
&listener-class&
com.listeners.MyContextListener
&/listener-class&
&/listener&
&servlet/&
&servlet-mapping/&
&/web-app&
ServletContextListener接口有两方需要实现的方法: contextInitialized()和contextDestroyed(); Listener,译为监听者.顾名思义,它会监听Servlet容器,当应用开始的时候它会调用contextInitialized()方法; 当应用关闭的时候,它同样会调用contextDestroyed()方法. 我们可以利用这个特性初始化一些信息,当然我们也可以利用Servlet类init()方法,并在配置文件中让它启动应用的时候 就执行,并且在关闭的时候执行destroy()方法.但是继承此接口应该更符合容器的应用. 举个简单的例子:在一些论坛,社区及聊天室当中,删除在线的超时用户就可以利用这个接口来实现. 可以利用JAVA的TimerTask及Timer类来实现每隔一定的时间进行自动检测. 实例代码如下: UserOnlineTimerTask.java
Java代码 &
package&com.bcxy. &&
import&java.util.TimerT &&
import&mons.logging.L &&
import&mons.logging.LogF &&
public&class&UserOnlineTimerTask&extends&TimerTask&{ &&
Log&log&=&LogFactory.getLog(UserOnlineTimerTask.class); &&
public&void&run()&{ &&
<("删除在线的超时用户...."); &&
package&com.bcxy.&&
import&java.util.TimerT&&
import&mons.logging.L&&
import&mons.logging.LogF&&
public&class&UserOnlineTimerTask&extends&TimerTask&{&&
Log&log&=&LogFactory.getLog(UserOnlineTimerTask.class);&&
public&void&run()&{&&
<("删除在线的超时用户....");&&
package com.bcxy.
import java.util.TimerT
import mons.logging.L
import mons.logging.LogF
public class UserOnlineTimerTask extends TimerTask {
Log log = LogFactory.getLog(UserOnlineTimerTask.class);
public void run() {
// 删除超时在线用户
("删除在线的超时用户....");
SysListener.java
Java代码 &
package&com.bcxy. &&
import&java.io.IOE &&
import&java.util.T &&
import&javax.servlet.ServletContextE &&
import&javax.servlet.ServletContextL &&
import&javax.servlet.ServletE &&
import&javax.servlet.ServletR &&
import&javax.servlet.ServletR &&
import&javax.servlet.http.HttpS &&
import&mons.logging.L &&
import&mons.logging.LogF &&
public&class&SysListener &&
extends&HttpServlet &&
implements&ServletContextListener&{ &&
Log&log&=&LogFactory.getLog(SysListener.class); &&
Timer&timer&=&new&Timer(); &&
public&void&service(ServletRequest&request,&ServletResponse&response) &&
throws&ServletException,&IOException&{ &&
public&void&contextInitialized(ServletContextEvent&sce)&{ &&
<("initial&context...."); &&
timer.schedule(new&UserOnlineTimerTask(),&0,&10000); &&
public&void&contextDestroyed(ServletContextEvent&sce)&{ &&
<("destory&context...."); &&
timer.cancel(); &&
package&com.bcxy.&&
import&java.io.IOE&&
import&java.util.T&&
import&javax.servlet.ServletContextE&&
import&javax.servlet.ServletContextL&&
import&javax.servlet.ServletE&&
import&javax.servlet.ServletR&&
import&javax.servlet.ServletR&&
import&javax.servlet.http.HttpS&&
import&mons.logging.L&&
import&mons.logging.LogF&&
public&class&SysListener&&
extends&HttpServlet&&
implements&ServletContextListener&{&&
Log&log&=&LogFactory.getLog(SysListener.class);&&
Timer&timer&=&new&Timer();&&
public&void&service(ServletRequest&request,&ServletResponse&response)&&
throws&ServletException,&IOException&{&&
public&void&contextInitialized(ServletContextEvent&sce)&{&&
<("initial&context....");&&
timer.schedule(new&UserOnlineTimerTask(),&0,&10000);&&
public&void&contextDestroyed(ServletContextEvent&sce)&{&&
<("destory&context....");&&
timer.cancel();&&
package com.bcxy.
import java.io.IOE
import java.util.T
import javax.servlet.ServletContextE
import javax.servlet.ServletContextL
import javax.servlet.ServletE
import javax.servlet.ServletR
import javax.servlet.ServletR
import javax.servlet.http.HttpS
import mons.logging.L
import mons.logging.LogF
public class SysListener
extends HttpServlet
implements ServletContextListener {
Log log = LogFactory.getLog(SysListener.class);
Timer timer = new Timer();
public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException {
public void contextInitialized(ServletContextEvent sce) {
("initial context....");
timer.schedule(new UserOnlineTimerTask(), 0, 10000);
public void contextDestroyed(ServletContextEvent sce) {
("destory context....");
timer.cancel();
如果你没有使用log4j的话,你可以把()改为System.out.println()会得到同样的结果.
在Servlet API中有一个ServletContextListener接口,它能够监听ServletContext对象的生命周期,实际上就是监听Web应用的生命周期。
当Servlet容器启动或终止Web应用时,会触发ServletContextEvent事件,该事件由 ServletContextListener 来处理。在 ServletContextListener 接口中定义了处理ServletContextEvent事件的两个方法。
contextInitialized(ServletContextEvent sce):当Servlet容器启动Web应用时调用该方法。在调用完该方法之后,容器再对Filter初始化,并且对那些在Web应用启动时就需要被初始化的Servlet进谐跏蓟??/P&
contextDestroyed(ServletContextEvent sce):当Servlet容器终止Web应用时调用该方法。在调用该方法之前,容器会先销毁所有的Servlet和Filter过滤器。
下面通过一个例子来介绍ServletContextListener的用法。本章4.4.1节的例程4-9的CounterServlet类只能统计当Web应用启动后,网页被客户端访问的次数。如果重新启动Web应用,计数器又会重新从1开始统计访问次数。在实际应用中,往往需要统计自Web应用被发布后网页被客户端访问的次数,这就要求当Web应用被终止时,计数器的数值被永久存储在一个文件中或者数据库中,等到Web应用重新启动时,先从文件或数据库中读取计数器的初始值,然后在此基础上继续计数。
向文件中写入或读取计数器的数值的功能可以由自定义的 MyServletContextListener类(参见例程4-11)来完成,它具有以下功能:
在 Web 应用启动时从文件中读取计数器的数值,并把表示计数器的 Counter对象存放到 Web 应用范围内。存放计数器的文件的路径为helloapp/count/count.txt。
在Web应用终止时把Web应用范围内的计数器的数值保存到count.txt文件中。
例程4-11 MyServletContextListener.java
public class MyServletContextListener implements ServletContextListener{
public void contextInitialized(ServletContextEvent sce){
System.out.println("helloapp application is Initialized.");
&&& //获取ServletContext对象
ServletContext context=sce.getServletContext();
//从文件中读取计数器的数值
BufferedReader reader=new BufferedReader(
new InputStreamReader(context.
getResourceAsStream("/count/count.txt")));
int count=Integer.parseInt(reader.readLine());
reader.close();
&&&&& //创建计数器对象
Counter counter=new Counter(count);
//把计数器对象保存到Web应用范围
context.setAttribute("counter",counter);
}catch(IOException e){e.printStackTrace();}
public void contextDestroyed(ServletContextEvent sce){
System.out.println("helloapp application is Destroyed.");
&&& //获取ServletContext对象
ServletContext context=sce.getServletContext();
&&& //从Web应用范围获得计数器对象
Counter counter=(Counter)context.getAttribute("counter");
&&& if(counter!=null){
//把计数器的数值写到count.txt文件中
String filepath=context.getRealPath("/count");
filepath=filepath+"/count.txt";
PrintWriter pw=new PrintWriter(filepath);
pw.println(counter.getCount());
pw.close();
}catch(IOException e){e.printStackTrace();}
用户自定义的MyServletContextListener监听器只有先向Servlet容器注册,Servlet容器在启动或终止Web应用时,才会调用该监听器的相关方法。在web.xml文件中,&listener&元素用于向容器注册监听器:
&listener&
&listener-class&mypack.MyServletContextListener&listener-class /&
&/listener&
下面按如下步骤演示MyServletContextListener监听器的作用。
(1)在helloapp/count目录下创建count.txt文件,在该文件中存放了一个数字&5&。
(2)启动 Tomcat。在浏览器中通过
访问CounterServlet,在第一次访问该Servlet时,浏览器端显示计数器的值为5。
(3)刷新上述访问 CounterServlet 的页面,会看到每刷新一次,计数器的值增加1,假定最后一次刷新后的计数器的值为10。
(4)手工终止helloapp应用。查看helloapp/count/count.txt文件,会发现在该文件中存放的数字变为10。
(5)手工重新启动 helloapp 应用。在浏览器中再次访问 CounterServlet,当第一次访问该Servlet时,浏览器端显示计数器的值为10。
从上述实验中可以看出,MyServletContextListener 监听器与 CounterServlet 共享Web应用范围内的代表计数器的Counter对象。监听器在Web应用启动或终止时会操纵Counter对象,而Servlet在每次响应客户请求时会操纵Counter对象。
观察MyServletContextListener及本章4.3.4节的名为lifeInit的 LifeServlet在 Tomcat 控制台的打印结果的先后顺序,会发现当 Web 应用启动时,Servlet容器先调用MyServletContextListener的contextInitialized()方法,再调用lifeInit的init()方法;当Web应用终止时,Servlet容器先调用lifeInit的destroy()方法,再调用MyServletContextListener的contextDestroyed()方法。由此可见,在Web应用的生命周期中,ServletContext对象最早被创建,最晚被销毁
ServletContextListener接口有两方需要实现的方法:contextInitialized()和contextDestroyed();
Listener,译为监听者.顾名思义,它会监听Servlet容器,当应用开始的时候它会调用contextInitialized()方法;
当应用关闭的时候,它同样会调用contextDestroyed()方法.我们可以利用这个特性初始化一些信息,当然我们
也可以利用Servlet类init()方法,并在配置文件中让它启动应用的时候就执行,并且在关闭的时候执行destroy()方
法.但是继承此接口应该更符合容器的应用
阅读(...) 评论()}

我要回帖

更多关于 tomcat listener 顺序 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信