ServletContextListener 的 Servlet 监听器示例

ServletContextListener是我们拥有的众多Servlet监听器之一。这是Java Web应用程序系列中的第五篇文章,您也许想查看前面的四篇文章。

    1. Java网络应用程序

 

    1. Java中的Servlet

 

    1. Servlet会话管理

 

    Servlet过滤器

Servlet监听器

在本教程中,我们将研究Servlet监听器、Servlet监听器的好处、我们可以使用监听器完成的一些常见任务、Servlet API监听器接口和事件对象。最后,我们将创建一个简单的Web项目,展示ServletContext、Session和ServletRequest的常用监听器实现的示例。

    1. 为什么我们要有Servlet监听器?

Servlet监听器接口和事件对象

Servlet监听器配置

Servlet监听器示例

ServletContextListener

ServletContextAttributeListener

HttpSessionListener

ServletRequestListener

为什么我们要有Servlet监听器?

我们知道,使用ServletContext,我们可以创建一个具有应用程序范围的属性,所有其他servlet都可以访问,但我们只能在部署描述符(web.xml)中将ServletContext初始化参数初始化为字符串。如果我们的应用程序是面向数据库的,并且我们想在ServletContext中设置一个用于数据库连接的属性,那该怎么办呢?如果您的应用程序只有一个入口点(用户登录),那么您可以在第一个servlet请求中进行设置,但如果我们有多个入口点,那么在每个地方都进行设置将导致大量的代码冗余。此外,如果数据库关闭或配置不正确,我们将不会知道,直到第一个客户端请求到达服务器。为了处理这些情况,servlet API提供了可以实现和配置以侦听事件并执行某些操作的侦听器接口。事件是发生的某个事情,在Web应用程序世界中,事件可以是应用程序的初始化、销毁应用程序、来自客户端的请求、创建/销毁会话、会话中的属性修改等。Servlet API提供了不同类型的侦听器接口,我们可以在web.xml中实现和配置,以在特定事件发生时进行处理。例如,在上述情况中,我们可以创建一个侦听器用于应用程序启动事件,以读取上下文初始化参数并创建数据库连接,并将其设置为上下文属性,供其他资源使用。

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

    1. javax.servlet.AsyncEvent – 当通过调用ServletRequest#startAsync或ServletRequest#startAsync(ServletRequest,ServletResponse)在ServletRequest上启动的异步操作已完成、超时或出现错误时触发的事件。

 

    1. javax.servlet.http.HttpSessionBindingEvent – 当将实现HttpSessionBindingListener的对象绑定或解除绑定到会话时,或者当为每个会话配置了HttpSessionAttributeListener并在会话中绑定、解绑或替换任何属性时,会发送此类事件。会话通过调用HttpSession.setAttribute绑定对象,并通过调用HttpSession.removeAttribute解除绑定对象。当对象从会话中移除时,我们可以使用此事件进行清理活动。

 

    1. javax.servlet.http.HttpSessionEvent – 这是表示网页应用程序中会话更改的事件通知的类。

 

    1. javax.servlet.ServletContextAttributeEvent – 用于通知有关网页应用程序的ServletContext属性更改的事件类。

 

    1. javax.servlet.ServletContextEvent – 这是用于通知网页应用程序的servlet上下文更改的事件类。

 

    1. javax.servlet.ServletRequestEvent – 此类事件指示ServletRequest的生命周期事件。事件的来源是此网页应用程序的ServletContext。

 

    javax.servlet.ServletRequestAttributeEvent – 这是用于通知应用程序中servlet请求属性更改的事件类。

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

    1. javax.servlet.AsyncListener – 当在已添加该监听器的ServletRequest上启动的异步操作完成、超时或出现错误时,将通知该监听器。

javax.servlet.ServletContextListener – 用于接收有关ServletContext生命周期更改的通知事件的接口。

javax.servlet.ServletContextAttributeListener – 用于接收有关ServletContext属性更改的通知事件的接口。

javax.servlet.ServletRequestListener – 用于接收有关进入和离开Web应用程序范围的请求的通知事件的接口。

javax.servlet.ServletRequestAttributeListener – 用于接收有关ServletRequest属性更改的通知事件的接口。

javax.servlet.http.HttpSessionListener – 用于接收有关HttpSession生命周期更改的通知事件的接口。

javax.servlet.http.HttpSessionBindingListener – 在对象绑定到或从会话解绑时,会通知该对象。

javax.servlet.http.HttpSessionAttributeListener – 用于接收有关HttpSession属性更改的通知事件的接口。

javax.servlet.http.HttpSessionActivationListener – 绑定到会话的对象可以监听容器事件,通知它们会话将被钝化和会话将被激活。迁移会话之间的容器VM或持久化会话需要通知实现HttpSessionActivationListener 的所有绑定到会话的属性。

Servlet Listener配置

我们可以使用@WebListener注解将一个类声明为监听器,但是这个类应该实现一个或多个监听器接口。我们可以在web.xml中定义监听器:

<listener>
    <listener-class>
    com.Olivia.listener.AppContextListener
    </listener-class>
</listener>
    Servlet监听器示例

我们来创建一个简单的Web应用程序来查看Servlet监听器的功能。我们将在Eclipse中创建一个动态Web项目,ServletListenerExample,该项目结构将如下图所示。web.xml:在部署描述符中,我将定义一些上下文init参数和监听器配置。

<?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>scdev</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.Olivia.listener.AppContextListener</listener-class>
  </listener>
  <listener>
    <listener-class>com.Olivia.listener.AppContextAttributeListener</listener-class>
  </listener>
  <listener>
    <listener-class>com.Olivia.listener.MySessionListener</listener-class>
  </listener>
  <listener>
    <listener-class>com.Olivia.listener.MyServletRequestListener</listener-class>
  </listener>
</web-app>

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

package com.Olivia.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
	}
}

我的Servlet:一个简单的Servlet类,我将在其中处理会话、属性等。

package com.Olivia.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。27. ## ServletContextListener

我们将读取servlet上下文初始化参数来创建DBConnectionManager对象,并将其设置为ServletContext对象的属性。

package com.Olivia.listener;

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

import com.Olivia.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.");
    	
    }
	
}
    1. ServletContextAttributeListener

 

    监听器

在servlet上下文中,当属性添加、删除或替换时,可以使用简单的实现来记录事件。

package com.Olivia.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()+"}");
    }
	
}
    1. HttpSessionListener

 

    会话监听器

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

package com.Olivia.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 in Chinese: ServletRequestListener

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

package com.Olivia.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 https://localhost:8080/ServletListenerExample/MyServlet 访问 MyServlet 时,在服务器日志文件中会看到以下日志。

ServletContext attribute added::{DBManager,com.Olivia.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}
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中的所有内容了,接下来我们将深入研究cookie以及一些常见的servlet示例。你可以从下面的链接下载这个项目,并用它来进行更多的实践学习。

下载 Servlet 监听器示例项目

请查看有关Servlet中Cookies的系列文章的下一篇。

发表回复 0

Your email address will not be published. Required fields are marked *


广告
将在 10 秒后关闭
bannerAds