サーブレットコンテキストリスナーサーブレットリスナーの例
ServletContextListenerは私たちが持っている多くのServletリスナーの1つです。これはJava Web Applicationシリーズの5番目の記事であり、以前の4つの記事もチェックすることをお勧めします。
-
- Java Webアプリケーション
-
- Javaにおけるサーブレット
-
- サーブレットセッション管理
- サーブレットフィルター
サーブレットリスナー
このチュートリアルでは、サーブレットリスナー、サーブレットリスナーの利点、リスナーを使用して行える一般的なタスク、サーブレットAPIのリスナーインターフェースやイベントオブジェクトについて説明します。最後に、ServletContext、Session、ServletRequestの一般的に使用されるリスナー実装の例を示すために、シンプルなウェブプロジェクトを作成します。
- なぜServletリスナーが必要なのですか?
私たちは、ServletContextを使用することで、他のすべてのサーブレットからアクセス可能なアプリケーションスコープの属性を作成できることを知っています。ただし、デプロイメント記述子(web.xml)では、ServletContextの初期化パラメータを文字列のみで設定できます。しかし、私たちのアプリケーションはデータベース指向であり、データベース接続のためにServletContextに属性を設定したい場合どうなるでしょうか。アプリケーションに単一のエントリーポイント(ユーザーログイン)がある場合、最初のサーブレットリクエストで行うことができますが、複数のエントリーポイントがある場合、すべての場所で行うとコードの重複が生じます。また、データベースがダウンしているか、正しく構成されていない場合、最初のクライアントリクエストがサーバーに到達するまでわかりません。このようなシナリオを処理するために、サーブレットAPIはリスナーインターフェースを提供しており、イベントを聞くための実装と構成を行うことができます。イベントとは何かが起こることであり、Webアプリケーションの世界では、イベントはアプリケーションの初期化、アプリケーションの破棄、クライアントからのリクエスト、セッションの作成/破棄、セッション内の属性の変更などといったことが考えられます。サーブレットAPIでは、特定のイベントが発生した際に何かを処理するために実装と構成できるさまざまなタイプのリスナーインターフェースが提供されています。例えば、上記のシナリオでは、アプリケーションの起動イベントに対してリスナーを作成し、コンテキストの初期化パラメータを読み取り、データベース接続を作成して他のリソースが使用できるようにコンテキスト属性に設定することができます。
Servlet APIは、さまざまな種類のイベントに対して異なるタイプのリスナーを提供しています。リスナーインターフェースは、同様のイベントのグループと一緒に作業するためのメソッドを宣言します。たとえば、ServletContextリスナーは、コンテキストの起動およびシャットダウンイベントを受け取るためのリスナーです。リスナーインターフェースのすべてのメソッドは、イベントオブジェクトを入力として受け取ります。イベントオブジェクトは、リスナーに特定のオブジェクトを提供するラッパーとして機能します。Servlet APIは以下のイベントオブジェクトを提供しています。
-
- javax.servlet.AsyncEvent – ServletRequestによって開始された非同期操作が完了した、タイムアウトした、またはエラーが発生したときに発火するイベントです。
-
- javax.servlet.http.HttpSessionBindingEvent – このタイプのイベントは、HttpSessionBindingListenerを実装したオブジェクトがセッションにバインドまたはアンバインドされた場合、またはweb.xmlで構成されたHttpSessionAttributeListenerがセッションに属性がバインド、アンバインド、または置換された場合に送信されます。セッションは、HttpSession.setAttributeによってオブジェクトをバインドし、HttpSession.removeAttributeによってオブジェクトをアンバインドします。オブジェクトがセッションから削除される場合のクリーンアップ活動にこのイベントを使用できます。
-
- javax.servlet.http.HttpSessionEvent – これはWebアプリケーション内のセッションへの変更のためのイベント通知を表すクラスです。
-
- javax.servlet.ServletContextAttributeEvent – ウェブアプリケーションのServletContextの属性の変更に関する通知のためのイベントクラスです。
-
- javax.servlet.ServletContextEvent – これはウェブアプリケーションのサーブレットコンテキストの変更に関するイベントクラスです。
-
- javax.servlet.ServletRequestEvent – この種のイベントは、ServletRequestのライフサイクルイベントを示します。イベントのソースは、このウェブアプリケーションのServletContextです。
- javax.servlet.ServletRequestAttributeEvent – これはアプリケーション内のservletリクエストの属性の変更の通知のためのイベントクラスです。
Servlet APIには、次のリスナーインターフェースが提供されています。
-
- javax.servlet.AsyncListener – サーブレットリクエストに追加されているリスナーによって初期化された非同期操作が完了した、タイムアウトした、またはエラーが発生した場合に通知されるリスナー。
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を実装したセッションにバインドされたすべての属性に通知する必要があります。
サーブレットリスナーの設定
@WebListenerアノテーションを使用してクラスをリスナーとして宣言することができますが、そのクラスは1つ以上のリスナーインターフェースを実装する必要があります。web.xmlにリスナーを定義することもできます。
<listener>
<listener-class>
com.scdev.listener.AppContextListener
</listener-class>
</listener>
- サーブレットリスナーの例
Servletリスナーを動作させるためのシンプルなWebアプリケーションを作成しましょう。Eclipse ServletListenerExample内に動的Webプロジェクトを作成し、以下のイメージのようなプロジェクト構造を作成します。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>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.scdev.listener.AppContextListener</listener-class>
</listener>
<listener>
<listener-class>com.scdev.listener.AppContextAttributeListener</listener-class>
</listener>
<listener>
<listener-class>com.scdev.listener.MySessionListener</listener-class>
</listener>
<listener>
<listener-class>com.scdev.listener.MyServletRequestListener</listener-class>
</listener>
</web-app>
DBConnectionManager: これはデータベースの接続性に関するクラスです。実際のデータベース接続のためのコードは省略しています。このオブジェクトはサーブレットコンテキストに属性として設定されます。
package com.scdev.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
}
}
MyServlet: セッション、属性などを操作するシンプルなサーブレットクラスです。
package com.scdev.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.
サーブレットコンテキストの初期パラメータを読み込んで、DBConnectionManagerオブジェクトを作成し、それをServletContextオブジェクトの属性として設定します。
package com.scdev.listener;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import com.scdev.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.");
}
}
- サーブレットコンテキスト属性リスナー
サーブレットコンテキストで属性が追加、削除、または置き換えられたときにイベントをログに記録するシンプルな実装。
package com.scdev.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()+"}");
}
}
-
- HttpSessionListener
- セッションのリスナー
セッションが作成または破棄されたときにイベントを記録するためのシンプルな実装。
package com.scdev.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
リクエストが初期化される際と破棄される際に、ServletRequestListenerインターフェースの簡単な実装を使用して、ServletRequestのIPアドレスをログに記録します。
package com.scdev.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.scdev.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に関する次の記事をご覧ください。