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. 高斯RBF核函数中Sigma取值和SVM分离面的影响

    1:高斯RBF核函数的定义 k(x) = exp(-x^2/(2×sigma)) 在MATLAB中输入一下代码:ezsurf('exp(-x^2/(2*sigma^2))'); 在GOOGLE中输入“ ...

  2. Flex回声消除的最佳方法

    Adobe Flash Player 已经成为音频和视频播放的非常流行的工具.实际上,目前大多数因特网视频均使用 Flash Player观看. Flash Player 通过将许多技术进行组合可以提 ...

  3. (一)Redis在windows下的安装和使用

    1.下载redis服务端,地址:https://github.com/MSOpenTech/redis/releases 包含安装程序和源码. 2.解压<Redis-x64-3.2.100.zi ...

  4. easyui帮助文档地址

    http://www.jeasyui.com/documentation/index.php# http://www.jeasyui.net/tutorial/22.html http://www.j ...

  5. twemproxyRedis协议解析探索——剖析twemproxy代码正编

    这篇文章会对twemproxyRedis协议解析代码部分进行一番简单的分析,同时给出twemproxy目前支持的所有Redis命令.在这篇文章开始前,我想大家去简单地理解一下有限状态机,当然不理解也是 ...

  6. 在ubuntu linux 中编写一个自己的bash脚本

    在ubuntu linux 中编写一个自己的简单的bash脚本. 实现功能:终端中输入简单的命令(以pm为例(play music)),来实现音乐的播放.注:本人ununut中安装了audacious ...

  7. Extjs学习笔记之九 数据模型(上)-extjs

    来源:niutuku.com | vincent上传于2012-07-20 | 1802次浏览 | 0条评论 本文开始进入Extjs最核心最优秀的部分. 标签:Extjs 数据模型   Extjs的数 ...

  8. Dirty Flag 模式及其应用

    之前在开发中就发现"dirty"是一种不错的解决方案:可以用来延缓计算或者避免不必要的计算.后来在想,这应该也算一种设计模式吧,于是搜索"Dirty设计模式", ...

  9. setTimeout()和setInterval()的用法

    JS里设定延时: 使用SetInterval和设定延时函数setTimeout 很类似.setTimeout 运用在延迟一段时间,再进行某项操作. setTimeout("function& ...

  10. getchar()不停止原因

    应该是你的输入流中还有残留的字符,getchar()()会接受那个字符.你可以在调用getchar()()之前用fflush(stdin)刷新一下输入缓冲区. 上面一段里面,应该有读入语句吧,没读干净 ...