Servlet监听

在《Servlet和Jsp》中我们使用了ServletConfig获取Servlet的初始配置,用ServletContext来获取整个Web应用的初始配置,但如果需要在所有的Servlet之前初始化资源怎么办呢?比如DataSource、Log4j等,可惜Servlet没有main方法,它是靠Web容器(如Tomcat)来加载的。

幸运的是Servlet提供了一个类javax.servlet.ServletContextListener,它能够监听ServletContext一生中的两个关键事件:初始化(创建)和撤销。

小示例

新建net.oseye.web.listener.MyTestContextListener类实现javax.servlet.ServletContextListener:

public class MyTestContextListener implements ServletContextListener {

	public void contextInitialized(ServletContextEvent arg0) {
//通过ServletContext传递资源
arg0.getServletContext().setAttribute("name", "kevin");
} public void contextDestroyed(ServletContextEvent arg0) {
// 不需要销毁资源
}
}

在DD文件中配置Context监听:

<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app>
<display-name>Archetype Created Web Application</display-name> <listener>
<listener-class>net.oseye.web.listener.MyTestContextListener</listener-class>
</listener> <servlet>
<servlet-name>HelloOther</servlet-name>
<display-name>HelloOther</display-name>
<description></description>
<servlet-class>net.oseye.web.HelloOther</servlet-class>
</servlet> <servlet-mapping>
<servlet-name>HelloOther</servlet-name>
<url-pattern>/HelloOther</url-pattern>
</servlet-mapping> </web-app>

在Servlet中获取Context值并使用:

String name=(String) getServletContext().getAttribute("name");
response.getWriter().println("name:"+name);

Servlet中使用Log4J

Log4j的配置文件在项目中的位置如下图:

log4j.properties内容

log4j.logger.net.oseye=INFO,WebFile

log4j.appender.WebFile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.WebFile.File=d:/log/testweb/web.log
log4j.appender.WebFile.DatePattern=yyyy-MM-dd-HH'.log'
log4j.appender.WebFile.layout=org.apache.log4j.PatternLayout
log4j.appender.WebFile.layout.ConversionPattern=%d{HH:mm:ss,SSS} %M %m%n

在pom.xml中添加slf4j依赖

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.6</version>
</dependency>

web.xml配置监听

<listener>
<listener-class>
net.oseye.web.listener.MyTestContextListener
</listener-class>
</listener>

net.oseye.web.listener.MyTestContextListener监听类代码

public class MyTestContextListener implements ServletContextListener {

	public void contextInitialized(ServletContextEvent arg0) {
//通过ServletContext传递资源
arg0.getServletContext().setAttribute("name", "kevin");
PropertyConfigurator.configure(arg0.getServletContext().getRealPath("/config/log4j.properties"));
} public void contextDestroyed(ServletContextEvent arg0) {
// 不需要销毁资源
}
}

在Servlet中记录日志

Logger logger=LoggerFactory.getLogger(HelloOther.class);
logger.info("测试Log4j");

监听器

只要是在生命周期里的重要时刻,总会有一个监听器在监听,下面是8个监听器

场景 监听器接口 时间类型
你想知道一个web应用上下文中是否增加、删除或替换了一个属性

javax.servlet.ServletContextAttributeListener
attributeAdded
attributeRemoved
attributeReplaced

ServletContextAttributeEvent
你想知道有多少个并发用户,也就是说,你想跟踪活动的会话

javax.servlet.http.HttpSessionListener
sessionCreated
sessionDestroyed

HttpSessionEvent
每次请求到来时你都想知道,以便建立日志记录

javax.servlet.ServletRequestListener
requestInitialized
requestDestroyed

ServletRequestEvent
增加、删除或替换一个请求属性时你希望能够知道

javax.servlet.ServletRequestAttributeListener
attributeAdded
attributeRemoved
attributeReplaced

ServletRequestAttributeListener
你有一个属性类,而且你希望这个类型的对象在绑定到一个会话或从会话中或从会话删除时得到通知

javax.servlet.HttpSessoinBindingListener
valueBound
valueUnbound

HttpSessionBindingEvent
增加、删除或添加一个会话属性时你希望能够知道

javax.servlet.HttpSessionAttributeListener
attributeAdded
attributeRemoved
attributeReplaced

HttpSessionBindingEvent
你想知道是否创建或撤销了一个上下文

javax.servlet.ServletContextListener
contextInitializated
contextDestroyed

ServletContextEvent
你有一个属性类,而且希望这个类型的对象在其绑定的会话迁移到另一个JVM时得到通知

javax.servlet.http.HttpSessionActivationListener
sessionDidActivite
sessionWillPassivate

HttpSessionEvent

HttpSessionListener和HttpSessionActivationListener共用HttpSessionEvent事件;ServletSessionBindingListener和ServletSessionAttributeListener共用HttpSessionBindingEvent事件。
如在部署描述文件web.xml添加监听

<listener>
<listener-class>net.oseye.web.listener.ContextAttributeListener</listener-class>
</listener>
<listener>
<listener-class>net.oseye.web.listener.SessionLinstener</listener-class>
</listener>

net.oseye.web.listener.ContextAttributeListener

public class ContextAttributeListener implements ServletContextAttributeListener {
private static Logger logger=LoggerFactory.getLogger(ContextAttributeListener.class); public void attributeAdded(ServletContextAttributeEvent arg0) {
logger.info("name:{} val:{}",arg0.getName(),arg0.getValue().toString()); } public void attributeRemoved(ServletContextAttributeEvent arg0) {
// TODO Auto-generated method stub } public void attributeReplaced(ServletContextAttributeEvent arg0) {
// TODO Auto-generated method stub }
}

net.oseye.web.listener.SessionLinstener

public class SessionLinstener implements HttpSessionListener {
private static Logger log=LoggerFactory.getLogger(SessionLinstener.class); public void sessionCreated(HttpSessionEvent arg0) {
log.info("创建-"+arg0.getSession().getId());
} public void sessionDestroyed(HttpSessionEvent arg0) {
log.info("销毁-"+arg0.getSession().getId());
}
}

对于ServletContextAttributeListener我的测试只能监听ServletContext()操作的属性,而对于在DD文件中的却没能监听到,如web.xml配置:

<context-param>
<param-name>email</param-name>
<param-value>kevin@oseye.net</param-value>
</context-param>

PS:这里是我理解错误,把属性和上下文参数搞混了,在web.xml中配置的是上下文参数。


Context属性和会话属性的多线程

Context属性和会话属性因为作用域很大,所以他们不是线程安全的,我们一般这样保证线程安全

synchronized (getServletContext()) {
getServletContext().setAttribute("name", "kevin");
getServletContext().setAttribute("age", "22");
} synchronized (request.getSession()) {
request.getSession().setAttribute("name", "kevin");
request.getSession().setAttribute("age", "22");
}

PS:每个Servlet只有一个实例对象(Instance),但可以被多个线程访问;这里强调这点并不是为了解释上面的属性线程不安全,因为即使是多个实例对象,也会有多个Servlet造成属性线程不安全的。

Servlet的监听的更多相关文章

  1. jsp&servlet——session监听

    session监听,需要实现HttpSessionAttributeListener接口 attributeAdded:监听添加session attributeRemoved:监听删除session ...

  2. java web hello world(二)基于Servlet理解监听

    java web最开始实现是通过Servlet实现,这里就来实现下,最原始的监听是如何实现的. 第一步,创建一个基本的web项目 ,参见(java web hello world(一)) 第二步,we ...

  3. Servlet之监听事件细究

    观察者三个模式: ServletContextListener:用于监听WEB 应用启动和销毁的事件,监听器类需要实现javax.servlet.ServletContextListener 接口. ...

  4. javaweb监听

    监听项目启动 package com.java7115.quartz; import javax.servlet.ServletContextEvent; import javax.servlet.S ...

  5. JavaWeb监听器的使用(一)监听上下文和会话信息

    1.监听上下文的类 package com.examp.ch9; import java.io.FileOutputStream; import java.io.PrintWriter; import ...

  6. tomcat触发ServletContext初始化监听事件的源码(原创)

    tomcat 8.0.36 知识点: 动态监听器的好处可以根据环境条件进行选择性添加. 静态监听器有七类. ServletContextAttributeListener ServletRequest ...

  7. 【Java EE 学习 21 上】【其它类型的监听器】【使用HttpSessionActivationListener监听session的活化和钝化】

    一.ServletContextListener  Method Summary  void contextDestroyed(ServletContextEvent sce)           R ...

  8. 解决tomcat启动Socket监听端口死循环被hold问题

    原文链接:http://blog.csdn.net/dead_cicle/article/details/7073433 1.SOCKET监听置于servlet的init方法中,在web.xml里加入 ...

  9. java web session监听销毁跳转

    1.了解如何使用HttpSessionListener监听session的销毁. 2.了解如何使用HttpSessionBindingListener监听session的销毁. 一. 使用HttpSe ...

随机推荐

  1. Angular - - ngList、ngRepeat、ngModelOptions

    ngList 在文本输入的分隔的字符串和字符串数组间做转换,可以是一个固定的字符串分隔符(默认逗号)或正则表达式. 格式:ng-list=”value” value:表达式  通过这个值分隔字符串. ...

  2. iOS 之 static

    函数体内的static变量的作用范围是该函数体,在内存中只分配一次,下次调用时仍维持上次的值. 模块内的static全局变量可以被模块内的所有函数访问,但是不能被模块外的其它函数访问. 模块内的sta ...

  3. 2.6. 类型(Core Data 应用程序实践指南)

    单精度浮点数与双精度浮点数:创建NSManagedObject紫雷师,如果实体中单精度或双精度浮点数类型,那么在子类里,相关特性的类型是NSNumber. 小数:涉及货币时,建议设置为小数(decim ...

  4. CSS继承性和层叠性

    一. 继承性    1. 含义:从自己开始直到所包裹的最小的元素,都可以继承一些特有的属性.    2. 作用范围:  a. color.text-开头的.line-开头的.font-开头的,均可以继 ...

  5. Spring @Aspect切面参数传递

    Spring @Aspect切面参数传递: Xml: <?xml version="1.0" encoding="UTF-8"?> <bean ...

  6. Canvas createImageData

    createImageData() 方法创建新的空白 ImageData 对象.新对象的默认像素值 transparent black. 对于 ImageData 对象中的每个像素,都存在着四方面的信 ...

  7. 支付宝 Android 版使用的开源组件

    支付宝 Android 版使用的开源组件 前言: 花了点时间整理了 支付宝 Android 客户端使用的开源组件,给需要的同学.在你不知道用什么开源框架的时候可以作下参考,毕竟支付宝是阿里的重量级产品 ...

  8. python中关于__init__模块文件的理解

    一般来说新建的一个包下,必然会有一个__init__文件?那么这个文件到底邮有和作用呢? 总结几点如下: 1.__init__文件在包下,其中定义了包的属性,方法;必须要有这个文件,如果没有的话,这个 ...

  9. Kettle(Pentaho)实现web方式远程执行job或transformation

    一.背景 公司在用kettle做数据etl,每做完一个job或transformation发布上线想要立即执行看数据效果的话每次都是找运维同学登陆服务器打开kettle找到对应的文件点击执行,整个过程 ...

  10. 分布式搜索之搭建Solrcloud(Solr集群)

    Solrcloud介绍: SolrCloud(solr集群)是Solr提供的分布式搜索方案. 当你需要大规模,容错,分布式索引和检索能力时使用SolrCloud. 当索引量很大,搜索请求并发很高时,同 ...