מקרה דוגמה לאזנן סרבל ServletListener

למערכת: ServletContextListener הוא אחד מההקשבים של Servlet הרבים שיש לנו. זהו המאמר החמישי בסדרה של יישום Java Web, כדאי לך לבדוק גם את ארבעת המאמרים הקודמים.

  1. יישום Java Web
  2. Servlets ב-Java
  3. ניהול סשן ב-Servlet
  4. מסנני Servlet

הקשב ל-Servlet

במדריך זה, אנחנו נתעסק ב־מאזין סרבלט, יתרונות של מאזני סרבלט, משימות נפוצות שאפשר לבצע עם מאזני, ממשקי מאזין של סרבלט API ואובייקטי אירוע. בסוף ניצור פרויקט ווב פשוט כדי להראות דוגמה למימוש מאזן נפוץ עבור ServletContext, Session ו־ServletRequest.

  1. למה יש לנו מאזין סרבלט?

  2. ממשקי מאזין סרבלט ואובייקטים אירוע

  3. תצורת מאזן סרבלט

  4. דוגמת מאזן סרבלט

  5. ServletContextListener

  6. ServletContextAttributeListener

  7. HttpSessionListener

  8. ServletRequestListener

  9. למה יש לנו מאזין Servlet?

אנו יודעים שבאמצעות ServletContext, אנו יכולים ליצור מאפיין עם טווח יישום שכל הסרבלטים האחרים יכולים לגשת אליו, אך אנו יכולים לאתחל מאפייני הגדרת ServletContext כמחרוזת בלבד בקובץ התיאור (web.xml). מה קורה אם היישום שלנו ממוקד במסד נתונים ואנו רוצים להגדיר מאפיין ב ServletContext לחיבור למסד נתונים. אם היישום שלך מכיל נקודת כניסה יחידה (התחברות משתמש), אז ניתן לעשות זאת בבקשת הסרבלט הראשונה אבל אם יש לנו מספר נקודות כניסה, אז עשיית זה בכל מקום יביא להרבה חוזר קוד. גם אם המסד נתונים לא פעיל או לא הוגדר באופן תקין, אנו לא נדע עד שבקשת לקוח ראשונה תגיע לשרת. כדי לטפל בסצנריו אלה, API של הסרבלט מספק ממשקי תקשורת שניתן לממש ולהגדיר כדי להאזין לאירוע ולבצע פעולות מסוימות. אירוע הוא התרחשות של משהו, בעולם היישומות של האינטרנט, אירוע יכול להיות אתחול היישום, השמדת היישום, בקשה מלקוח, יצירת/השמדת סשן, שינוי מאפיין בסשן וכו '. API של הסרבלט מספק ממשקי תקשורת שונים שניתן לממש ולהגדיר בקובץ web.xml כדי לעבד משהו כאשר אירוע מסוים מתרחש. לדוגמה, בתרחיש לעיל ניתן ליצור מאזין עבור אירוע התחלת היישום כדי לקרוא מאפייני איתחול של ההקשר וליצור חיבור למסד נתונים ולהגדיר אותו כמאפיין של ההקשר לשימוש של משאבים אחרים.8. ### ממשקי מאזין של הסרבלט ואובייקטי אירוע

ה- API של Servlet מספק סוגים שונים של מאזינים לסוגים שונים של אירועים. ממשקי המאזינים מצהירים על שיטות לעבוד עם קבוצה של אירועים דומים, לדוגמה יש לנו את מאזין ה- ServletContext להאזנה לאירועי ההתחלה והסיום של ההקשר. כל שיטה בממשק המאזין מקבלת אובייקט אירוע כקלט. אובייקט האירוע פועל כמעטרה לספק אובייקט ספציפי למאזינים. ה- API של Servlet מספק אובייקטי אירועים הבאים:

  1. javax.servlet.AsyncEvent – אירוע שנזרק כאשר הפעולה האסינכרונית שנפתחה על ידי ServletRequest (באמצעות קריאה ל- ServletRequest#startAsync או ServletRequest#startAsync(ServletRequest, ServletResponse)) הושלמה, פגתה תוקפה, או יצרה שגיאה.
  2. javax.servlet.http.HttpSessionBindingEvent – אירועים מסוג זה נשלחים או לאובייקט שמיישם את HttpSessionBindingListener כאשר הוא מחובר או מנותק מהסשן, או ל- HttpSessionAttributeListener שהוגדר בקובץ ה- web.xml כאשר כל מאפיין מחובר, מנותק או מוחלף בסשן. הסשן מחבר את האובייקט באמצעות קריאה ל- HttpSession.setAttribute ומנתק את האובייקט באמצעות קריאה ל- HttpSession.removeAttribute. ניתן להשתמש באירוע זה לפעילויות ניקיון כאשר האובייקט מוסר מהסשן.
  3. javax.servlet.http.HttpSessionEvent – זהו המחלקה המייצגת התראות אירוע לשינויים בסשנים בתוך יישום אינטרנט.
  4. javax.servlet.ServletContextAttributeEvent – מחלקת האירועים להתראות על שינויים במאפייני ה- ServletContext של יישום אינטרנט.
  5. javax.servlet.ServletContextEvent – זהו מחלקת האירועים עבור התראות על שינויים בהקשר השרת של יישום אינטרנט.
  6. javax.servlet.ServletRequestEvent – אירועים מסוג זה מציינים אירועי מחזור חיים עבור ServletRequest. מקור האירוע הוא ההקשר של ServletContext של יישום האינטרנט הזה.
  7. javax.servlet.ServletRequestAttributeEvent – זו מחלקת האירועים עבור התראות של שינויים בתכונות בקשת השרת ביישום מסוים.

API של Servlet מספק ממשקי מאזין הבאים.

  1. javax.servlet.AsyncListener – מאזין שיתוף יתר שיודע לקבל התראה במקרה שפעולה אסינכרונית שהופעלה על ServletRequest שאליו המאזין נוסף הושלמה, פגה בזמן או גרמה לשגיאה.

  2. javax.servlet.ServletContextListener – ממשק לקבלת אירועי התראה על שינויים במחזור החיים של ServletContext.

  3. javax.servlet.ServletContextAttributeListener – ממשק לקבלת אירועי התראה על שינויים במאפייני ServletContext.

  4. javax.servlet.ServletRequestListener – ממשק לקבלת אירועי הודעה על בקשות הנכנסות ויוצאות מהקפיצה של אפליקציה אינטרנט.

  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 – אובייקטים שקשורים להפעלת סשן יכולים להאזין לאירועים של מיכל המודיעים להם כי סשנים יעברו למצב passivated וכי סשן יופעל. מיכל שמעביר סשנים בין VMs או שמשמר סשנים נדרש להודיע לכל התכונות הקשורות לסשנים שמיישמים את HttpSessionActivationListener.

  10. הגדרת מקשיב לסרבלט

אנו יכולים להשתמש ב- @WebListener אנוטציה כדי להצהיר על מחלקה כסובלת של האזנה, עם זאת, יש למחלקה לממש אחת או יותר מממשקי האזנה. ניתן להגדיר את האזנה ב- web.xml כך:

<listener>
    <listener-class>
    com.journaldev.listener.AppContextListener
    </listener-class>
</listener>
  1. דוגמה לאזנה של סרבל

בואו ליצור יישום אינטרנט פשוט כדי לראות את האזנה של סרבל בפעולה. ניצור פרויקט ווב דינמי ב- Eclipse 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>

מנהל חיבורי מסד נתונים: זהו המחלקה לחיבור למסד נתונים, לפשטות אני לא מספק קוד לחיבור ממשי למסד נתונים. נקבע את העצם הזה כמאפיין להקשר של הסרבלט.

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: מחלקת סרבלט פשוטה בה אני אעבוד עם סשן, מאפיינים וכו '.

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

נקרא פרמטרי התחלה של ההקשר של הסרבלט כדי ליצור את עצם 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.");
    	
    }
	
}
  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());
    }
	
}

כעת כאשר נטען את היישום שלנו ונגיע ל־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}
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.

שים לב לסדר הלוגים והוא בסדר הביצוע. הלוג האחרון יופיע כאשר תכבה את היישום או תכבה את התכולה.

זהו הכל לגבי המאזין בסרבלט, נבדוק עוגיות ודוגמאות מסרבלט נפוצות אחרות בהמשך. ניתן להוריד את הפרויקט מהקישור למטה ולשחק איתו כדי ללמוד עוד.

הורד דוגמא לפרויקט של מאזין סרבלט

בדוק את המאמר הבא בסדרה על עוגיות בסרבלט.

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