HttpServletRequestインターフェースのgetSessionメソッドで、引数にtrueを指定することで現在のセッションが存在しない場合に新しいセッションが生成されます。 (メソッドの定義) public HttpSession getSession(boolean create) HttpSessionインターフェースのsetAttributeメソッドでセッションに情報を設定できます。どの型のオブジェクトでも設定できます。 (メソッドの定義) public void setAttribute(java.lang.String name, java.lang.Object value) HttpServletRequestインターフェースのgetSessionメソッドで、引数にfalseを指定することで新しいセッションを作成しなくなります。もし、セッションが存在しない場合にはnullが返ってきます。 HttpSessionインターフェースのgetAttributeメソッドでセッションに設定されている情報を取得できます。 (メソッドの定義) public java.lang.Object getAttribute(java.lang.String name) ◆セッションのタイムアウト時間について あるサイトにログインしたユーザーが必ずログアウトするとは限らないので(たとえばブラウザを閉じてしまう)、セッションにはタイムアウト時間が存在します。タイムアウト時間がないとサーバーにユーザーのセッション情報が残ったままになってしまうからです。Tomcatの場合、このタイムアウト時間はデフォルトでは30分になっています。Webアプリケーション毎にセッションのタイムアウト時間を設定するにはweb.xmlファイルを編集します。 ■セッションのタイムアウト時間の設定(Webアプリケーション毎) 60分に設定する場合です。分単位で設定します。 web.xml 60 ■セッションのタイムアウト時間の設定(セッション毎) セッション毎にタイムアウト時間を設定するには、HttpSessionインターフェースのsetMaxInactiveIntervalメソッドを使用します。web.xmlの設定よりこの設定の方が優先されます。 5分に設定する場合です。秒単位で設定します。 HttpSession session = request.getSession(true); session.setMaxInactiveInterval(60 * 5); ------------------------------------------------ <フィルタクラスの作り方> 1. javax.servlet.Filterインターフェースを実装(implements)する。 2. doFilter()、init()、destroy()メソッドの3つを実装する。 3. doFilter()メソッドに処理を記述する。 HelloWorldFilter.java(ここからダウンロード) import java.io.*; import javax.servlet.*; public class HelloWorldFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { /** ここに処理を記述 **/ // ログに出力します。 System.out.println("Hello World Filter"); // 次のフィルタまたは元々要求されていたリソースを呼び出します。 // (今回の場合はサーブレット) chain.doFilter(req, res); } public void init(FilterConfig config) throws ServletException { } public void destroy() { } } ◆web.xmlファイルにフィルタの設定を記述 次にweb.xmlファイルにフィルタの設定を記述します。ここではHelloWorldServletにリクエストがあった場合にHelloWorldFilterをフィルタとして使用するという設定を記述します。 web.xml helloFilter HelloWorldFilter helloFilter /servlet/HelloWorldServlet ■説明 ・・・フィルタクラスを定義します。 ・・・あるURLにリクエストがあったときにどのフィルタを使用するか定義します。 ここでは/servlet/HelloWorldServletにリクエストがあったときに上で定義したhelloFilterを使うように記述しています。 /servlet/* のようにワイルドカードも使用できます。 ■文字エンコーディングを指定するフィルタ フィルタでリクエストの文字エンコーディングを指定します。このフィルタを使用するサーブレットではパラメーターの文字エンコーディングを変更しなくて済みます。 HelloWorldEncodingFilter.java import java.io.*; import javax.servlet.*; public class HelloWorldEncodingFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { // エンコーディング指定 req.setCharacterEncoding("Shift_JIS"); // 元々要求されていたリソースを呼び出します chain.doFilter(req, res); } public void init(FilterConfig config) throws ServletException { } public void destroy() { } } ---- フィルタの作成 フィルタは「javax.servlet.Filter」インターフェースを実装して作成します。このインターフェースで定義されているメソッドは3つで、それぞれが呼び出されるタイミングおよび処理内容は以下の通りです。 init(javax.servlet.FilterConfig) フィルタが初めて使用されるときに呼び出されます。「FilterConfig」は主にフィルタの初期設定値を読み出すために使用します。 doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain) フィルタの対象となるリソースが呼び出されたときに実行されます。「FilterChain」は次のフィルタやリクエストの対象であるJSPページやサーブレットの処理を実行するのに使用されます。 destroy() フィルタが破棄されるときに呼び出されます。何らかの後処理が必要な場合に実装します。 以下はリクエストの文字コードを指定するフィルタです。文字コードを初期設定値から読み出して指定しています。 1: import javax.servlet.Filter; 2: import javax.servlet.FilterConfig; 3: import javax.servlet.FilterChain; 4: import javax.servlet.ServletRequest; 5: import javax.servlet.ServletResponse; 6: import javax.servlet.ServletException; 7: import java.io.IOException; 8: 9: public final class EncodingFilter implements Filter{ 10: private String encoding=null; 11: public void init(FilterConfig config) throws ServletException{ 12: encoding=config.getInitParameter("encoding"); 13: } 14: 15: public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain) 16: throws ServletException,IOException{ 17: request.setCharacterEncoding(encoding); 18: chain.doFilter(request,response); 19: } 20: 21: public void destroy(){ 22: encoding=null; 23: } 24:}12行目、FilterConfigの「getInitParameter」で初期設定値を読み出しています。設定の行い方は次節で説明します。15〜19行目の「doFilter」メソッド内でリクエストの文字コードを指定しています(17行目)。18行目で次のフィルタ(当該フィルタが最後のフィルタの場合は、リクエストの対象のリソース)が呼び出されます。 レスポンスに対して処理を行う事も可能です。以下のフィルタはページの最後に訪問者数を表示しています。訪問者数の管理には「ServletContext」を利用しています。ServletContextにおいても、「getAttribute」「setAttribute」メソッドでオブジェクトの登録が行えます。登録されたオブジェクトはWebアプリケーション全体で共有されます。 public final class CounterFilter implements Filter{ private ServletContext context=null; public void init(FilterConfig config) throws ServletException{ context=config.getServletContext(); context.setAttribute("counter", new Integer(1); } public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain) throws ServletException,IOException{ chain.doFilter(request,response); Integer counter=(Integer)context.getAttribute("counter"); PrintWriter writer=((HttpServletResponse)response).getWriter(); writer.println(counter.intValue()); context.setAttribute("counter", new Integer(counter.intValue()+1)); } public void destroy(){ context=null; } }FilterChainのdoFilterメソッドによって一連の処理が実行されるので、これより前で処理を行うか後ろで処理を行うかで、クライアントからの要求と応答のどちら側でフィルタリングを行うか決定する事ができます。 6.3.フィルタの設定 フィルタの設定も「WEB-INF/web.xml」で行います。フィルタの宣言と、フィルタを適応するURLの設定の2種類に分かれます。 Encoding EncodingFilter Counter CounterFilter Encoding /servlet/* Counter /servlet/IndexServlet フィルタの宣言はタグで行います。およびの設定は、の次、より前で行います。タグはで構成されており、前者でフィルタを識別する名前、後者でフィルタを実装したクラス名を指定します。タグとよく似た構成をしています。 フィルタを適応するURLの設定はタグで行います。その中ので適応するフィルタ名、でフィルタを適応するURLのパターンを指定します。の指定方法はと同じで以下のようになっています。 /???/* /???/で始まる全てのURLにマッチします。例:「/resource/*」と指定した場合は、「http://***/sample/resource/」で始まる全てのURL「http://***/sample/resource/test/test」等にマッチします。 *.??? ???を拡張子にもつ全てのURLにマッチします。例:「*.cgi」と指定した場合は、「http://***/sample/」以下で、「cgi」を拡張子に持つURL全てにマッチします。 /* 全てのURLにマッチします。あらゆるWWWアプリケーションのリクエストに対して、フィルタが適応されます。 複数のフィルタがマッチした場合にはどうなるでしょうか。その場合にはマッチしたフィルタ全てが起動されます。起動される順番は、設定の順番です。ですからについては内容だけでなく、順番にも注意が必要です。 最後にフィルタに対する初期設定値を与える方法を説明します。タグ内にタグを用いて指定します。タグ内で初期設定値を与える方法と同じです。 Encoding EncodingFilter encoding EUC-JP 複数初期設定値を与える場合は、その数だけタグを繰り返します。 ----------------------- 他のサーブレットの呼び出し サーブレットから他のサーブレットに処理を一部委託したい場合や、全面的に引き継ぎたい場合が考えられます。昔のJava Servlet APIでは、「ServletContext」クラスの「getServlet」「getServlets」メソッドで、「Servlet」オブジェクトを取得する事ができたので、このメソッドを介して他のサーブレットに処理を委託する事ができました。 しかしバージョン2.1以降、この方法は問題が多いので削除される事となりました。現在もこれらのメソッドは定義されていますが、常にnullが返されるようになっています。その代わりとして、「include」と「forward」が提供されるようになりました。includeはSSIのようなもので、一部分の表示を他に委託して任せるというものです。1つのページの中に他の「HTML」や、「JSP」「Servlet」の処理結果を含める事ができます。 「forward」は、処理を完全に他に転送してしまいます。HTTPにもリダイレクトがありますが、これは一旦クライアント側に応答を返した後、クライアント側から別のページへ自動的に移動するという形をとります。サーブレットのforwardはサーバ内部で転送が行われるので、クライアントに応答を返すというオーバーヘッドがありません。以降、includeとforwardについて説明します。 5.2.include includeもforwardも「javax.servlet.RequestDispatcher」インターフェースを介して実行します。このインターフェースは、「ServletRequest」の「getRequestDispatcher」および「ServletContext」の「getNamedDispatcher」「getRequestDispatcher」から取得します。これらの違いは、処理を依頼する先のリソース(「HTML」「JSP」「Servlet」)の指定方法の違いに表れます。 ServletRequest getRequestDispatcher 相対パスか、WWWアプリケーションルートからの絶対パスで指定する。 ServletContext getRequestDispatcher WWWアプリケーションルートからの絶対パスで指定する。 getNamedDispatcher リソースにつけられた名前で指定する。 例えば、以下のように「WEB-INF/web.xml」に指定された2つのサーブレットがあるとします。WWWアプリケーションのルートは「http://***/sample/」とします。 Sample SampleServlet Included IncludedServlet Sample /servlet/Sample   Included /resource/Included 以下は「SampleServlet」から「IncludedServlet」を呼び出すサンプルです。それぞれ指定の方法で呼び出しています。「ServletRequest」の「getRequestDispatcher」はアプリケーションルートからの絶対パスでも指定可能で、その場合は「ServletContext」の「getRequestDispatcher」と同じ方法で指定します。「/」から始まっているかどうかで区別されています。 public final class SampleServlet extends HttpServlet{ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException{ response.setContentType("text/html; charset=EUC-JP"); PrintWriter writer=response.getWriter(); writer.println(""); //ServletRequet.getRequestDispatcher request.getRequestDispatcher("../resource/Included").include(request,response); //ServletContext.getRequestDispatcher getServletContext().getRequestDispatcher("/resource/Included").include(request,response); //ServletContext.getNamedDispatcher getServletContext().getNamedDispatcher("Included").include(request,response); writer.println("hello!

"); } }「IncludedServlet」が上記のような場合、「SampleServlet」から送出されるHTMLは以下のようになります。

hello!

hello!

hello!

(実習課題1) 4章の実習課題3のプログラムを改良しなさい。 1つのHTMLファイル(任意)を「include」して表示するようにする事。 解答例はこちら 5.3.forward 「forward」は他のリソース(「HTML」「JSP」「Servlet」)に処理を転送する機能です。includeのように、表示の一部だけを任せるという訳ではありません。そのため、1つ制約があり、forwardを行うまでに何らかの表示を返してはいけません。その場合にはIllegalStateExceptionが発生します。以下のサンプルでは、forwardの直前に出力を行っていますので、例外が発生します。 public final class ForwardServlet extends HttpServlet{ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ response.setContentType("text/html; charset=EUC-JP"); PrintWriter writer=response.getWriter(); writer.println(""); //前の行で出力があるので、例外が発生する。 request.getRequestDispatcher("/resource/Included").forward(request,response); } }逆にforwardした後、何の出力を行っても、例外は発生しませんが意味はありません。 forwardは処理(Servlet)と表示(JSP)を切り分けてアプリケーションを開発する際に、非常に重要な機能です。 (実習課題2) 3章の実習課題3のプログラムを改良しなさい。 Internet Explorerだった場合には、実習課題1(5章)のプログラムに「forward」する。 解答例はこちら 5.4.ServletRequestを用いたデータ共有 呼び出したサーブレットとデータ共有をしたい事が考えられます。ServletRequestのgetParameterで取得できる値は、呼び出した側も呼び出された側も同じになるのですが、それ以外に追加したい場合が考えられます。その場合にはServletRequestの「setAttribute」「getAttribute」を使用します。HttpSessionと使用方法は同じです。 無論、HttpSessionでもデータ共有はできるのですが、こちらと違い、ServletRequestの場合には1回のクライアントからの要求から応答までの間でのみ、データが保持されます。セッションの間でデータ共有したい場合にはHttpSession、1回の要求の間だけの場合にはServletRequestを使用します。 public final class TimeServlet extends HttpServlet{ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ String msg="ただ今の時刻は "+new SimpleDateFormat().format(new Date())+" です。"; request.setAttribute("msg",msg); request.getRequestDispatcher("/servlet/MessageShowServlet").forward(request,response); } }public final class MessageShowServlet extends HttpServlet{ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ response.setContentType("text/html; charset=EUC-JP"); PrintWriter writer=response.getWriter(); wrieter.println("
"); String msg=(String)request.getAttribute("msg"); writer.println("
"); } }MessageShowServletは汎用的な表示を行うサーブレットです。TimeServletから表示させたい値をServletRequestを介して渡してやる事により、全体として1つの表示を行っています。MessageShowServletの部分を、JSPで行う事がJ2EEでは推奨されています。 ---------------------