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. mvn常用指令记录

    maven工程版本号更新: -------------------------------------------------------------------------------------- ...

  2. jquery 组合键键盘事件

    jQuery处理键盘事件,比如小说网站中常见的按左右键来实现上一篇文章和下一篇文章,按ctrl+回车实现表单提交,google reader和有道阅读中的全快捷键操作... 本文讲述jQuery处理按 ...

  3. Adapter接口及实现类

    Adapter本身只是一个接口,它派生了ListAdapter和SpinnerAdapter两个子接口,其中ListAdapter为AbsListView提供列表项,而SpinnerAdapter为A ...

  4. Servlet生命周期方法,request.getRequestDispatcher

    1,request.getRequestDispatcher 方法全称javax.servlet.ServletRequest.getRequestDispatcher(String) 2,在web. ...

  5. iOS tabbar点击动画效果实现

    正常情况下,我们点击tabbar都只有一个变色效果,但有时候,如果我们想给它添加一个点击动画,该如何做呢? 先上几个效果图: 1.先放大,再缩小 2.Z轴旋转               3.Y轴位移 ...

  6. jdbcTemplate获取mysql的blob

    java使用jdbcTemplate操作mysql数据库,遇到blob字段,正常读取出来是blob的地址,而不是blob的内容. 下面采用2中方式读取blob的内容: 1.以二进制数组形式读取blob ...

  7. Word,Excel,PowerPoint协作实用功能

    Word,Excel,PowerPoint协作实用功能 纯手打,可能有错别字,使用的版本是office2013 转载请注明出处,谢谢 将Word表格复制到Excel中 点击Word表格左上角的按钮-- ...

  8. 用php进行md5解密的源码,亲测可用

    <?php $md5 = "c1c95b382230eb9e27a60c4baceb5f2e"; $uid = "hhp-ImZRY"; $token = ...

  9. HTML5 & CSS3 初学者指南(4) – Canvas使用

    介绍 传统的HTML主要用于文本的创建,可以通过<img>标签插入图像,动画的实现则需要第三方插件.在这方面,传统的HTML极其缺乏满足现代网页多媒体需求的能力.HTML5的到来,带来了新 ...

  10. JAVA中的栈和堆

    JAVA在程序运行时,在内存中划分5片空间进行数据的存储.分别是:1:寄存器.2:本地方法区.3:方法区.4:栈.5:堆. 基本,栈stack和堆heap这两个概念很重要,不了解清楚,后面就不用学了. ...