ServletContextListener Servlet監聽器示例

ServletContextListener 是我們擁有的許多 Servlet 監聽器之一。這是 Java Web 應用程式 系列中的第五篇文章,您可能也想查看前四篇文章。

  1. Java Web 應用程式
  2. Java 中的 Servlet
  3. Servlet 會話管理
  4. Servlet 過濾器

Servlet 監聽器

在這個教學裡,我們將研究服務器監聽器,服務器監聽器的好處,我們可以用監聽器做的一些常見任務,服務器API監聽器接口和事件對象。最後,我們將創建一個簡單的web項目,以顯示常用的監聽器實現的示例,如ServletContextSessionServletRequest

  1. 為什麼我們有服務程序監聽器?

  2. 服務器監聽器接口和事件對象

  3. 服務器監聽器配置

  4. 服務器監聽器示例

  5. ServletContextListener

  6. ServletContextAttributeListener

  7. HttpSessionListener

  8. ServletRequestListener

  9. 為什麼我們需要 Servlet 監聽器?

我們知道使用ServletContext,我們可以創建一個具有應用程序範圍的屬性,所有其他Servlet都可以訪問,但我們只能在部署描述符(web.xml)中初始化ServletContext初始化參數為字符串。如果我們的應用程序是面向數據庫的,並且我們想要為ServletContext設置一個數據庫連接的屬性,那怎麼辦?如果應用程序有一個單一的入口點(用戶登錄),那麼您可以在第一個Servlet請求中執行它,但如果我們有多個入口點,那麼在每個地方都這樣做將導致很多代碼冗余。而且,如果數據庫掛掉或未正確配置,我們將在第一個客戶端請求到達服務器時才知道。為了處理這些情況,Servlet API提供了我們可以實現並配置為監聽事件並執行某些操作的監聽器接口。 事件是某事發生的事件,在Web應用程序世界中,事件可以是應用程序的初始化,應用程序的銷毀,來自客戶端的請求,創建/銷毀會話,會話中屬性的修改等。 Servlet API提供了不同類型的監聽器接口,我們可以實現並在web.xml中配置以在發生特定事件時處理某些事物。例如,在上述情境中,我們可以為應用程序啟動事件創建一個監聽器,以讀取上下文初始化參數並創建數據庫連接,然後將其設置為上下文屬性,以供其他資源使用。8. ### Servlet監聽器接口和事件對象

Servlet API 為不同類型的事件提供了不同種類的監聽器。監聽器介面聲明了方法來處理一組相似的事件,例如我們有 ServletContext 監聽器來監聽上下文的啟動和關閉事件。

  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 – 這是有關於網絡應用程序的Servlet上下文更改通知的事件類。
  6. javax.servlet.ServletRequestEvent – 此類事件指示ServletRequest的生命周期事件。事件的來源是此Web應用程序的ServletContext。
  7. javax.servlet.ServletRequestAttributeEvent – 這是應用程序中有關於Servlet請求屬性更改的通知的事件類。

Servlet API提供以下Listener接口。

  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 – 與會話綁定的對象可以聆聽容器事件,通知它們會話將被啟動並且會話將被活化。遷移會話在虛擬機之間或持久化會話的容器需要通知所有實現HttpSessionActivationListener的會話屬性。
  10. Servlet Listener Configuration

我們可以使用@WebListener 註釋來將一個類聲明為監聽器,但該類必須實現一個或多個監聽器接口。我們可以在web.xml中定義監聽器:

<listener>
    <listener-class>
    com.journaldev.listener.AppContextListener
    </listener-class>
</listener>
  1. Servlet Listener Example

讓我們創建一個簡單的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物件,並將其設置為Servlet上下文物件的屬性。

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

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

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());
    }
	
}
  1. ServletRequestListener

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 中監聽器的全部內容,接下來我們將查看有關 cookies 和一些常見 Servlet 實例的信息。您可以從以下鏈接下載項目並進行更多實驗以深入了解。

下載 Servlet 監聽器範例專案

查看系列文章中的下一篇,有關Servlet 中的 Cookies

Source:
https://www.digitalocean.com/community/tutorials/servletcontextlistener-servlet-listener-example