ServletContextListenerは多くのServletリスナーの1つです。これはJava Web Applicationシリーズの5番目の記事であり、以前の4つの記事もチェックしてみたいかもしれません。
Servletリスナー
このチュートリアルでは、サーブレットリスナー、サーブレットリスナーの利点、リスナーで行える一般的なタスク、サーブレットAPIのリスナーインターフェースとイベントオブジェクトについて説明します。最後に、ServletContext、Session、ServletRequestの一般的に使用されるリスナーの実装の例を示すために、簡単なウェブプロジェクトを作成します。
われわれは、ServletContext
を使用して、アプリケーションスコープの属性を作成し、他のすべてのサーブレットからアクセスできますが、ServletContext initパラメータはデプロイメント記述子(web.xml)ではStringのみを初期化できます。アプリケーションがデータベース志向であり、ServletContextにデータベース接続の属性を設定したい場合、アプリケーションに単一のエントリポイント(ユーザーログイン)がある場合、最初のサーブレットリクエストで行うことができますが、複数のエントリポイントがある場合はどこでも行うことになります。コードの冗長性が生じます。また、データベースがダウンしているか、適切に構成されていない場合、最初のクライアントリクエストがサーバーに到達するまでわかりません。これらのシナリオを処理するために、Servlet APIはリスナーインタフェースを提供し、イベントを監視し、特定の操作を実行できるように構成できます。イベントは何かの発生を意味し、Webアプリケーションの世界では、イベントはアプリケーションの初期化、アプリケーションの破棄、クライアントからのリクエスト、セッションの作成/破棄、セッションでの属性の変更などが含まれます。Servlet APIは、特定のイベントが発生したときに何かを処理するために、異なるタイプのリスナーインタフェースを提供します。たとえば、上記のシナリオでは、アプリケーションの起動イベントのリスナーを作成して、コンテキスト初期化パラメータを読み取り、データベース接続を作成し、他のリソースで使用するためにコンテキスト属性に設定できます。
Servlet APIは、さまざまな種類のイベントに対する異なる種類のリスナーを提供します。リスナーインターフェースは、類似のイベントのグループで動作するメソッドを宣言します。たとえば、ServletContextリスナーは、コンテキストの起動およびシャットダウンイベントをリッスンするためのものです。リスナーインターフェースのすべてのメソッドは、イベントオブジェクトを入力として受け取ります。イベントオブジェクトは、リスナーに特定のオブジェクトを提供するラッパーとして機能します。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アプリケーションのサーブレットコンテキストの変更に関する通知のイベントクラスです。
- javax.servlet.ServletRequestEvent – この種のイベントは、ServletRequestのライフサイクルイベントを示します。イベントのソースは、このWebアプリケーションのServletContextです。
- javax.servlet.ServletRequestAttributeEvent – これは、アプリケーション内のサーブレットリクエストの属性の変更の通知のイベントクラスです。
Servlet APIは以下のリスナーインターフェースを提供しています。
-
javax.servlet.AsyncListener – リスナーは、リスナーが追加されていたServletRequestで非同期操作が完了、タイムアウト、またはエラーが発生した場合に通知されます。
-
javax.servlet.ServletContextListener – ServletContextライフサイクルの変更に関する通知イベントを受け取るためのインターフェースです。
-
javax.servlet.ServletContextAttributeListener – ServletContext属性の変更に関する通知イベントを受け取るためのインターフェースです。
-
javax.servlet.ServletRequestListener – ウェブアプリケーションのスコープに入るリクエストおよびスコープを出るリクエストに関する通知イベントを受信するためのインターフェース。
-
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 リスナーの設定
@WebListener アノテーションを使用して、クラスをリスナーとして宣言できます。ただし、クラスは1つ以上のリスナーインターフェースを実装する必要があります。web.xmlでリスナーを定義できます:
<listener>
<listener-class>
com.journaldev.listener.AppContextListener
</listener-class>
</listener>
Servletリスナーを動作させるために、シンプルなWebアプリケーションを作成しましょう。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: これはデータベース接続のためのクラスです。実際のデータベース接続のコードは簡単のため提供していません。このオブジェクトをサーブレットコンテキストの属性として設定します。
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;
//ここでDB接続を作成する
}
public Connection getConnection(){
return this.con;
}
public void closeConnection(){
//ここでDB接続を閉じる
}
}
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。
ServletContextListener
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");
ServletContextの初期化パラメータを読み取り、DBConnectionManagerオブジェクトを作成してそれをServletContextオブジェクトの属性として設定します。
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のリスナーに関する説明はこれで終わりです。次にクッキーや一般的なServletの例を見ていきます。プロジェクトは以下のリンクからダウンロードして試してみてください。
Download Servlet Listener Example Project
次の記事をチェックしてください:ServletのCookieに関するもの。
Source:
https://www.digitalocean.com/community/tutorials/servletcontextlistener-servlet-listener-example