ServletContextListener是我们拥有的许多Servlet监听器之一。这是《Java Web应用程序》系列的第五篇文章,您可能还想查看前面的四篇文章。
Servlet监听器
在本教程中,我们将探讨Servlet监听器,Servlet监听器的好处,可以使用监听器完成的一些常见任务,Servlet API监听器接口和事件对象。最后,我们将创建一个简单的Web项目,以展示对ServletContext、Session和ServletRequest常用监听器实现的示例。
我们知道使用ServletContext
,我们可以创建一个应用程序范围的属性,所有其他servlet都可以访问,但我们只能在部署描述符(web.xml)中初始化ServletContext初始化参数为String。如果我们的应用程序是数据库导向的,我们想要为数据库连接在ServletContext中设置属性。如果您的应用程序有一个单一的入口点(用户登录),那么您可以在第一个servlet请求中执行此操作,但是如果我们有多个入口点,那么在每个地方执行此操作将导致大量的代码冗余。而且,如果数据库宕机或配置不正确,我们在第一个客户端请求到达服务器之前就不会知道。为了处理这些情况,Servlet API提供了我们可以实现和配置以侦听事件并执行某些操作的侦听器接口。事件是某事的发生,在Web应用程序世界中,事件可以是应用程序的初始化、销毁应用程序、来自客户端的请求、创建/销毁会话、会话中的属性修改等。Servlet API提供了不同类型的侦听器接口,我们可以实现和配置在web.xml中处理某些事件发生时的某些事情。例如,在上述情况下,我们可以为应用程序启动事件创建一个侦听器,以读取上下文初始化参数并创建数据库连接,然后将其设置为上下文属性,供其他资源使用。8. ### Servlet Listener接口和事件对象
Servlet API提供了不同类型的监听器来处理不同类型的事件。监听器接口声明了与一组类似事件一起工作的方法,例如,我们有ServletContext监听器来监听上下文的启动和关闭事件。监听器接口中的每个方法都以Event对象作为输入。Event对象充当包装器,为监听器提供特定的对象。Servlet API提供以下事件对象。
- javax.servlet.AsyncEvent – 当在ServletRequest上启动异步操作(通过调用ServletRequest#startAsync或ServletRequest#startAsync(ServletRequest, ServletResponse))完成、超时或产生错误时触发的事件。
- javax.servlet.http.HttpSessionBindingEvent – 此类型的事件被发送到实现HttpSessionBindingListener的对象,当它从会话中绑定或解绑时,或者发送到在web.xml中配置了的HttpSessionAttributeListener,当在会话中绑定、解绑或替换任何属性时。会话通过调用HttpSession.setAttribute绑定对象,并通过调用HttpSession.removeAttribute解绑对象。我们可以利用此事件进行清理活动,当对象从会话中移除时。
- javax.servlet.http.HttpSessionEvent – 这是表示在web应用程序中对会话进行更改的事件通知的类。
- javax.servlet.ServletContextAttributeEvent – 用于通知有关web应用程序的ServletContext属性更改的事件类。
- javax.servlet.ServletContextEvent – 这是用于通知有关 Web 应用程序的 Servlet 上下文更改的事件类。
- javax.servlet.ServletRequestEvent – 这种类型的事件指示了 ServletRequest 的生命周期事件。事件的来源是此 Web 应用程序的 ServletContext。
- javax.servlet.ServletRequestAttributeEvent – 这是用于通知应用程序中 Servlet 请求属性更改的事件类。
Servlet API 提供以下监听器接口。
-
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 – 绑定到会话的对象可以侦听容器事件,通知它们会话将被钝化并且会话将被激活。迁移会话的容器或持久化会话的容器必须通知实现了 HttpSessionActivationListener 的所有绑定到会话的属性。
-
Servlet 监听器配置
我们可以使用@WebListener 注解将一个类声明为Listener,但是该类应该实现一个或多个Listener接口。我们可以在web.xml中定义监听器:
<listener>
<listener-class>
com.journaldev.listener.AppContextListener
</listener-class>
</listener>
让我们创建一个简单的Web应用程序来看看Servlet监听器的实际效果。我们将在Eclipse中创建一个动态Web项目ServletListenerExample,该项目结构将如下图所示。 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;
//现在创建数据库连接
}
public Connection getConnection(){
return this.con;
}
public void closeConnection(){
//在这里关闭数据库连接
}
}
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。27. ## ServletContextListener
我们将读取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");
//从初始化参数创建数据库连接并设置到上下文
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.");
}
}
A simple implementation to log the event when attribute is added, removed or replaced in servlet context.
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()+"}");
}
}
A simple implementation to log the event when session is created or destroyed.
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());
}
}
A simple implementation of ServletRequestListener interface to log the ServletRequest IP address when request is initialized and destroyed.
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 https://localhost:8080/ServletListenerExample/MyServlet
访问 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}
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中的Cookies的内容。
Source:
https://www.digitalocean.com/community/tutorials/servletcontextlistener-servlet-listener-example