ServletContextListener Servlet侦听器示例

在本教程中,我们将研究Servlet侦听器Servlet侦听器的优点,可以使用侦听器执行的一些常见任务,Servlet API侦听器接口和Event对象。最后,我们将创建一个简单的Web项目,以显示ServletContextSessionServletRequest的常用侦听器实现的示例。

为什么我们有Servlet Listener?

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

事件是某事的发生,在Web应用程序世界中,事件可以是应用程序初始化,破坏应用程序,来自客户端的请求,创建/销毁会话,在会话中进行属性修改等。

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

Servlet侦听器接口和事件对象

Servlet API为不同类型的事件提供了不同种类的侦听器。侦听器接口声明用于与一组类似事件一起工作的方法,例如,我们有ServletContext侦听器来侦听上下文的启动和关闭事件。侦听器接口中的每个方法都将Event对象作为输入。事件对象充当包装器,以向侦听器提供特定的对象。

Servlet API提供以下事件对象。

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的会话的所有属性。
  10. javax.servlet.AsyncEvent-在ServletRequest上发起的异步操作(通过调用ServletRequest#startAsync或ServletRequest#startAsync(ServletRequest,ServletResponse))完成,超时或产生错误时,将触发此事件。
  11. javax.servlet.http.HttpSessionBindingEvent –这种类型的事件或者在绑定或从会话取消绑定时发送到实现HttpSessionBindingListener的对象,或者在绑定任何属性时发送到在web.xml中配置的HttpSessionAttributeListener,在会话中未绑定或替换。
    会话通过调用HttpSession.setAttribute来绑定对象,并通过调用HttpSession.removeAttribute来取消绑定对象。
    当从会话中删除对象时,我们可以将此事件用于清理活动。
  12. javax.servlet.http.HttpSessionEvent –这是一个类,表示Web应用程序中会话更改的事件通知。
  13. javax.servlet.ServletContextAttributeEvent –事件类,用于通知有关Web应用程序ServletContext属性更改的通知。
  14. javax.servlet.ServletContextEvent-这是事件类,用于通知有关Web应用程序Servlet上下文更改的信息。
  15. javax.servlet.ServletRequestEvent –这种事件表示ServletRequest的生命周期事件。事件的来源是此Web应用程序的ServletContext。
  16. javax.servlet.ServletRequestAttributeEvent-这是事件类,用于通知应用程序中Servlet请求的属性更改。

Servlet侦听器配置

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

我们可以在web.xml中将侦听器定义为:


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

Servlet侦听器示例

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

 

 

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

 

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://java.sun.com/xml/ns/javaee" xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://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。

我们将读取Servlet上下文初始化参数以创建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.");
    	
    }
	
}

一个简单的实现,用于在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()+"}");
    }
	
}

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


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接口的一个简单实现,用于在初始化和销毁​​请求时记录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时https://localhost:8080/ServletListenerExample/MyServlet,我们将在服务器日志文件中看到以下日志。


ServletContext attribute added::{DBManager,com.journaldev.db.DBConnectionManager@4def3d1b}
Database connection initialized for Application.
ServletContext attribute added::{org.apache.jasper.compiler.TldLocationsCache,org.apache.jasper.compiler.TldLocationsCache@1594df96}

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}
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中侦听器的全部内容,接下来我们将研究cookie和一些常见的servlet示例。

您可以从下面的链接下载该项目并进行试用以了解更多信息。

原文地址:https://blog.csdn.net/allway2

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习编程?其实不难,不过在学习编程之前你得先了解你的目的是什么?这个很重要,因为目的决定你的发展方向、决定你的发展速度。
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面设计类、前端与移动、开发与测试、营销推广类、数据运营类、运营维护类、游戏相关类等,根据不同的分类下面有细分了不同的岗位。
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生学习Java开发,但要结合自身的情况,先了解自己适不适合去学习Java,不要盲目的选择不适合自己的Java培训班进行学习。只要肯下功夫钻研,多看、多想、多练
Can’t connect to local MySQL server through socket \'/var/lib/mysql/mysql.sock问题 1.进入mysql路径
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 sqlplus / as sysdba 2.普通用户登录
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服务器有时候会断掉,所以写个shell脚本每五分钟去判断是否连接,于是就有下面的shell脚本。
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。
假如你已经使用过苹果开发者中心上架app,你肯定知道在苹果开发者中心的web界面,无法直接提交ipa文件,而是需要使用第三方工具,将ipa文件上传到构建版本,开...
下面的 SQL 语句指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。**提示:**如果列名称包含空格,要求使用双引号或方括号:
在使用H5混合开发的app打包后,需要将ipa文件上传到appstore进行发布,就需要去苹果开发者中心进行发布。​
+----+--------------+---------------------------+-------+---------+
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 nu...
第一步:到appuploader官网下载辅助工具和iCloud驱动,使用前面创建的AppID登录。
如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式):
前不久在制作win11pe,制作了一版,1.26GB,太大了,不满意,想再裁剪下,发现这次dism mount正常,commit或discard巨慢,以前都很快...
赛门铁克各个版本概览:https://knowledge.broadcom.com/external/article?legacyId=tech163829
实测Python 3.6.6用pip 21.3.1,再高就报错了,Python 3.10.7用pip 22.3.1是可以的
Broadcom Corporation (博通公司,股票代号AVGO)是全球领先的有线和无线通信半导体公司。其产品实现向家庭、 办公室和移动环境以及在这些环境...
发现个问题,server2016上安装了c4d这些版本,低版本的正常显示窗格,但红色圈出的高版本c4d打开后不显示窗格,
TAT:https://cloud.tencent.com/document/product/1340