Servlet监听器(Listener)

以下内容是翻译自http://www.journaldev.com/1945/servletcontextlistener-servlet-listener-example

为什么使用Servlet Listener?

我们知道使用ServletContext,我们可以创建一个具有所有其他servlet可以访问的应用范围的属性,但是我们可以在部署描述符(web.xml)中将ServletContext init参数初始化为String。如果我们的应用程序是面向数据库的,并且我们要在数据库连接的ServletContext中设置一个属性,该怎么办?如果应用程序具有单个入口点(用户登录),那么可以在第一个Servlet请求中执行,但是如果我们有多个入口点,那么在任何地方都会执行代码冗余。另外,如果数据库关闭或配置不正确,我们将不会知道,直到第一个客户端请求到达服务器。为了处理这些情况,Servlet API提供了Listener接口,我们可以实现和配置监听事件并执行某些操作。

事件(Event)是发生的事情,在Web应用程序世界中,事件可以是应用程序的初始化,销毁应用程序,从客户端请求,创建/销毁会话,会话中的属性修改等。

Servlet API提供了不同类型的侦听器接口,我们可以在web.xml中实现和配置,以便在特定事件发生时处理某些事件。例如,在上述情况下,我们可以为应用程序启动事件创建一个侦听器来读取上下文初始化参数并创建数据库连接,并将其设置为上下文属性以供其他资源使用。

Servlet Listener接口和事件(Event)对象

Servlet API为不同类型的事件提供了不同类型的侦听器。侦听器接口声明方法来处理一组类似的事件,例如我们有ServletContext Listener监听上下文的启动和关闭事件。侦听器界面中的每个方法都将事件对象作为输入。事件对象作为一个包装器,为侦听器提供特定的对象。

Servlet API提供以下事件对象:

  1. javax.servlet.AsyncEvent - 在ServletRequest(通过调用ServletRequest#startAsync或ServletRequest#startAsync(ServletRequest,ServletResponse))启动的异步操作已完成,超时或产生错误时触发的事件。
  2. javax.servlet.http.HttpSessionBindingEvent - 将此类型的事件发送到实现HttpSessionBindingListener的对象,当该对象从会话绑定或解除绑定时,或者发送到在web.xml中配置的HttpSessionAttributeListener,当绑定任何属性时,在会话中取消绑定或替换。会话通过对HttpSession.setAttribute的调用来绑定对象,并通过调用HttpSession.removeAttribute解除对象的绑定。当对象从会话中删除时,我们可以使用此事件进行清理活动。
  3. javax.servlet.http.HttpSessionEvent - 这是表示Web应用程序中会话更改的事件通知的类。
  4. javax.servlet.ServletContextAttributeEvent - 关于对Web应用程序的ServletContext的属性进行更改的通知的事件类。
  5. javax.servlet.ServletContextEvent - 这是关于Web应用程序的servlet上下文更改的通知的事件类。
  6. javax.servlet.ServletRequestEvent - 此类事件表示ServletRequest的生命周期事件。事件的源代码是这个Web应用程序的ServletContext。
  7. javax.servlet.ServletRequestAttributeEvent - 这是事件类,用于对应用程序中servlet请求的属性进行更改的通知。

Servlet API提供了以下监听器接口:

  1. javax.servlet.AsyncListener - 如果在添加了侦听器的ServletRequest上启动的异步操作已完成,超时或导致错误,将会通知侦听器。
  2. javax.servlet.ServletContextListener - 用于接收关于ServletContext生命周期更改的通知事件的接口。
  3. javax.servlet.ServletContextAttributeListener - 接收关于ServletContext属性更改的通知事件的接口。
  4. javax.servlet.ServletRequestListener - 用于接收关于进入和超出Web应用程序范围的请求的通知事件的接口。
  5. javax.servlet.ServletRequestAttributeListener - 接收关于ServletRequest属性更改的通知事件的接口。
  6. javax.servlet.http.HttpSessionListener - 接收关于HttpSession生命周期更改的通知事件的接口。
  7. javax.servlet.http.HttpSessionBindingListener - 使对象从会话绑定到绑定或从其绑定时被通知。
  8. javax.servlet.http.HttpSessionAttributeListener - 用于接收关于HttpSession属性更改的通知事件的接口。
  9. javax.servlet.http.HttpSessionActivationListener - 绑定到会话的对象可能会侦听容器事件,通知他们会话将被钝化,该会话将被激活。需要在VM或持久化会话之间迁移会话的容器来通知绑定到实现HttpSessionActivationListener的会话的所有属性。

Servlet Listener配置

我们可以使用@WebListener注解来声明一个类作为Listener,但是该类应该实现一个或多个Listener接口。

我们可以在web.xml中定义listener:

<listener>
    <listener-class>
        com.journaldev.listener.AppContextListener
    </listener-class>
</listener>

Servlet Listener示例

让我们创建一个简单的Web应用程序来查看Servlet侦听器的操作。我们将在Eclipse ServletListenerExample中创建动态Web项目,这些项目结构将如下图所示。

web.xml:在部署描述符中,我将定义一些上下文初始化参数和监听器配置。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>ServletListenerExample</display-name>

  <context-param>
    <param-name>DBUSER</param-name>
    <param-value>pankaj</param-value>
  </context-param>
  <context-param>
    <param-name>DBPWD</param-name>
    <param-value>password</param-value>
  </context-param>
  <context-param>
    <param-name>DBURL</param-name>
    <param-value>jdbc:mysql://localhost/mysql_db</param-value>
  </context-param>

  <listener>
    <listener-class>com.journaldev.listener.AppContextListener</listener-class>
  </listener>
  <listener>
    <listener-class>com.journaldev.listener.AppContextAttributeListener</listener-class>
  </listener>
  <listener>
    <listener-class>com.journaldev.listener.MySessionListener</listener-class>
  </listener>
  <listener>
    <listener-class>com.journaldev.listener.MyServletRequestListener</listener-class>
  </listener>
</web-app>

DBConnectionManager:这是数据库连接的类,为了简单起见,我没有为实际的数据库连接提供代码。我们将这个对象设置为servlet上下文的属性。

package com.journaldev.db;

import java.sql.Connection;

public class DBConnectionManager {

    private String dbURL;
    private String user;
    private String password;
    private Connection con;

    public DBConnectionManager(String url, String u, String p){
        this.dbURL=url;
        this.user=u;
        this.password=p;
        //create db connection now

    }

    public Connection getConnection(){
        return this.con;
    }

    public void closeConnection(){
        //close DB connection here
    }
}

MyServlet:一个简单的servlet类,我将使用会话,属性等。

package com.journaldev.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@WebServlet("/MyServlet")
public class MyServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            ServletContext ctx = request.getServletContext();
            ctx.setAttribute("User", "Pankaj");
            String user = (String) ctx.getAttribute("User");
            ctx.removeAttribute("User");

            HttpSession session = request.getSession();
            session.invalidate();

            PrintWriter out = response.getWriter();
            out.write("Hi "+user);
    }

}

现在我们将实现监听器类,我为常用的监听器提供了示例侦听器类 - ServletContextListener,ServletContextAttributeListener,ServletRequestListener和HttpSessionListener。

ServletContextListener

我们将读取servlet context init参数来创建DBConnectionManager对象,并将其设置为ServletContext对象的属性。

package com.journaldev.listener;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

import com.journaldev.db.DBConnectionManager;

@WebListener
public class AppContextListener implements ServletContextListener {

    public void contextInitialized(ServletContextEvent servletContextEvent) {
        ServletContext ctx = servletContextEvent.getServletContext();

        String url = ctx.getInitParameter("DBURL");
        String u = ctx.getInitParameter("DBUSER");
        String p = ctx.getInitParameter("DBPWD");

        //create database connection from init parameters and set it to context
        DBConnectionManager dbManager = new DBConnectionManager(url, u, p);
        ctx.setAttribute("DBManager", dbManager);
        System.out.println("Database connection initialized for Application.");
    }

    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        ServletContext ctx = servletContextEvent.getServletContext();
        DBConnectionManager dbManager = (DBConnectionManager) ctx.getAttribute("DBManager");
        dbManager.closeConnection();
        System.out.println("Database connection closed for Application.");

    }

}

ServletContextAttributeListener

在servlet上下文中添加,删除或替换属性时,记录事件的简单实现。

package com.journaldev.listener;

import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class AppContextAttributeListener implements ServletContextAttributeListener {

    public void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) {
        System.out.println("ServletContext attribute added::{"+servletContextAttributeEvent.getName()+","+servletContextAttributeEvent.getValue()+"}");
    }

    public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) {
        System.out.println("ServletContext attribute replaced::{"+servletContextAttributeEvent.getName()+","+servletContextAttributeEvent.getValue()+"}");
    }

    public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) {
        System.out.println("ServletContext attribute removed::{"+servletContextAttributeEvent.getName()+","+servletContextAttributeEvent.getValue()+"}");
    }

}

HttpSessionListener

创建或销毁会话时记录事件的简单实现。

package com.journaldev.listener;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

@WebListener
public class MySessionListener implements HttpSessionListener {

    public void sessionCreated(HttpSessionEvent sessionEvent) {
        System.out.println("Session Created:: ID="+sessionEvent.getSession().getId());
    }

    public void sessionDestroyed(HttpSessionEvent sessionEvent) {
        System.out.println("Session Destroyed:: ID="+sessionEvent.getSession().getId());
    }

}

ServletRequestListener

ServletRequestListener接口的简单实现,用于在请求初始化和销毁??时记录ServletRequest IP地址。

package com.journaldev.listener;

import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class MyServletRequestListener implements ServletRequestListener {

    public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
        ServletRequest servletRequest = servletRequestEvent.getServletRequest();
        System.out.println("ServletRequest destroyed. Remote IP="+servletRequest.getRemoteAddr());
    }

    public void requestInitialized(ServletRequestEvent servletRequestEvent) {
        ServletRequest servletRequest = servletRequestEvent.getServletRequest();
        System.out.println("ServletRequest initialized. Remote IP="+servletRequest.getRemoteAddr());
    }

}

现在,当我们将使用URL部署我们的应用程序并在浏览器中访问MyServlet时http://localhost:8080/ServletListenerExample/MyServlet,我们将在服务器日志文件中看到以下日志。

ServletContext attribute added::{DBManager,[email protected]}
Database connection initialized for Application.
ServletContext attribute added::{org.apache.jasper.compiler.TldLocationsCache,[email protected]}

ServletRequest initialized. Remote IP=0:0:0:0:0:0:0:1%0
ServletContext attribute added::{User,Pankaj}
ServletContext attribute removed::{User,Pankaj}
Session Created:: ID=8805E7AE4CCCF98AFD60142A6B300CD6
Session Destroyed:: ID=8805E7AE4CCCF98AFD60142A6B300CD6
ServletRequest destroyed. Remote IP=0:0:0:0:0:0:0:1%0

ServletRequest initialized. Remote IP=0:0:0:0:0:0:0:1%0
ServletContext attribute added::{User,Pankaj}
ServletContext attribute removed::{User,Pankaj}
Session Created:: ID=88A7A1388AB96F611840886012A4475F
Session Destroyed:: ID=88A7A1388AB96F611840886012A4475F
ServletRequest destroyed. Remote IP=0:0:0:0:0:0:0:1%0

Database connection closed for Application.

注意日志的顺序,它按照执行的顺序。当您关闭应用程序或关闭容器时,将显示最后一个日志。

这是Servlet中的所有的监听器。

时间: 2024-10-13 11:42:41

Servlet监听器(Listener)的相关文章

servlet监听器Listener(理论+例子)

Listener采用了观察者模式(24种模式之一),Listener是servlet的监听器,他可以监听客户端的请求.服务器端的操作等, 通过监听器,可以自动激发一些操作.比如:监听在线用户数量 当增加一个HttpSession时,就会激发sessinCreated(HttpSessionEvent sce)方法,这样就可以给在线人数+1了. 常见的监听器接口: ServletContextAttributeListener 监听对servletContext属性的操作,比如删除.增加.修改属性

Servlet监听器Listener

Listener实在servlet2.3中加入的,主要用于对Session,request,context等进行监控. 使用Listener需要实现响应的接口.触发Listener事件的时候,tomcat会自动调用Listener的方法. 在web.xml中配置标签,一般要配置在<servlet>标签前面,可配置多个,同一种类型也可配置多个 <listener> <listener-class>com.xxx.xxx.ImplementListener</list

JavaWeb开发——servlet监听器 listener

一.Servlet监听器的概念 Servlet监听器是Servlet规范中定义的一种特殊类,用于监听ServletContext.HttpSession和ServletRequest等域对象的创建与销毁事件, 以及监听这些域对象中属性发生修改的事件. 监听对象: 1.ServletContext:application,整个应用只存在一个 2.HttpSession:session,针对每一个对话 3.ServletRequest:request,针对每一个客户请求 监听内容:创建.销毁.属性改

【Listener】利用监听器Listener以MVC的思想通过JSP+Servlet+JDBC完成在线用户列表的输出

Servlet,监听器Listener与<[Filter]拦截器Filter>(点击打开链接)是JSP的三大核心组件,实际上监听器Listener相当于数据库里面的触发器,一旦用户触发了某种行为,则可以通过相关的Java文件执行相应的程序.用户在浏览网页的过程中,主要有打开浏览器的动作,对应的行为是Session的创建,可是,用户关闭浏览器的动作,并不是对应Session的消失,因此对于Session的消失我们意义不大:访问任意网页的动作,对应的行为是request请求的创建,request的

Servlet学习笔记(九):监听器Listener详解

一.简介 (一)概述 1.Listener 用于监听 java web程序中的事件,例如创建.修改.删除Session.request.context等,并触发响应的事件. 2. Listener 对应观察者模式,事件发生的时候会自动触发该事件对应的Listeer. Listener 主要用于对 Session.request.context 进行监控.servlet2.5 规范中共有 8 种Listener  . (二)实现 1.不同功能的Listener 需要实现不同的 Listener  

servlet/filter/listener/interceptor过滤器、监听器、拦截器区分

因为之前一直分不清过滤器和拦截器的区别,所以有了两者差不多的错觉,因此在这里总结下servlet/filter/listener/interceptor过滤器.监听器.拦截器. 在此之前先简单回顾下servlet: 概述:servlet是一种运行服务器端的java应用程序,它工作在客户端请求与服务器响应的中间层. 主要作用:在于交互式地浏览和修改数据,生成动态 Web 内容. 访问流程: 1,客户端发送请求至服务器端: 2,服务器将请求信息发送至 Servlet: 3,Servlet 生成响应内

Java Web开发——Servlet监听器

一.Servlet监听器的概念 Servlet监听器是Servlet规范中定义的一种特殊类,用于监听ServletContext.HttpSession和ServletRequest等域对象的创建与销毁事件,以及监听这些域对象中属性发生修改的事件. 监听对象: 1.ServletContext:application,整个应用只存在一个 2.HttpSession:session,针对每一个对话 3.ServletRequest:request,针对每一个客户请求 监听内容:创建.销毁.属性改变

javaweb学习总结(四十四)——监听器(Listener)学习

一.监听器介绍 1.1.监听器的概念 监听器是一个专门用于对其他对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监视的对象发生情况时,立即采取相应的行动.监听器其实就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法立即被执行. 1.2.监听器案例——监听window窗口的事件监听器 1 package me.gacl.listener.demo; 2 3 import java.awt.Fram

Servlet监听器笔记总结

监听器Listener的概念 监听器的概念很好理解,顾名思义,就是监视目标动作或状态的变化,目标一旦状态发生变化或者有动作,则立马做出反应. Servlet中的也有实现监听器的机制,就是Listener,Listener是一个实现特定接口的普通java程序,专门用来监听另一个java对象的方法调用或属性改变,当被监听对象发生变动时,监听器某个方法立即被执行. 监听器Listener的使用场景 理解了概念,接下来问题就来了,监听器Listener有哪些使用场景呢? 在使用Spring框架开发jav

javaweb学习总结(四十七)——监听器(Listener)在开发中的应用

监听器在JavaWeb开发中用得比较多,下面说一下监听器(Listener)在开发中的常见应用 一.统计当前在线人数 在JavaWeb应用开发中,有时候我们需要统计当前在线的用户数,此时就可以使用监听器技术来实现这个功能了. 1 package me.gacl.web.listener; 2 3 import javax.servlet.ServletContext; 4 import javax.servlet.http.HttpSessionEvent; 5 import javax.ser