インクルード(include)

広告

ここからは複数のサーブレット間で強調して処理を行う方法を確認していきます。

まずはサーブレット内に他のサーブレットの処理をインクルードする方法です。

例えば、サーブレットAが呼ばれ、レスポンスに対して出力をしている途中でサーブレットBをインクルードしたとします。そうするといったんサーブレットBへ処理が移った後でサーブレットBの処理が終わったら呼び出し元のサーブレットAへ処理が戻り、残りの処理を行うと言った感じです。

インクルードを行うには、まず"RequestDispatcher"インターフェースのオブジェクトを作成する必要があります。このオブジェクトはクライアントからのリクエストをディスパッチ(他へ委譲する)ためのものです。

オブジェクトを作成するには、"HttpServletRequest"インターフェースの親インターフェースである"ServletRequest"インターフェースで定義されている"getRequestDispatcher"メソッドを使います。

Returns a RequestDispatcher object that acts as a wrapper for the resource 
located at the given path. A RequestDispatcher object can be used to 
forward a request to the resource or to include the resource in a response. 
The resource can be dynamic or static. 

The pathname specified may be relative, although it cannot extend outside 
the current servlet context. If the path begins with a "/" it is 
interpreted as relative to the current context root. This method returns 
null if the servlet container cannot return a RequestDispatcher. 

The difference between this method and 
ServletContext.getRequestDispatcher(java.lang.String) is that this method 
can take a relative path. 

Parameters:
  path - a String specifying the pathname to the resource. If it is 
    relative, it must be relative against the current servlet. 
Returns:
  a RequestDispatcher object that acts as a wrapper for the resource 
    at the specified path, or null if the servlet container cannot 
    return a RequestDispatcher

引数には委譲先のファイルやサーブレットのパスを指定します。例えばこのWebアプリケーションのパスが「/dispatch」でインクルードしたいサーブレットが「/dispatch/includetest」だった場合は次のようになります。

public void doGet(HttpServletRequest request, HttpServletResponse response)
  throws IOException, ServletException{

  String disp = "/includetest";
  RequestDispatcher dispatch = request.getRequestDispatcher(disp);
}

ディスパッチャーが作成できましたら、「RequestDispatcher」インターフェースで定義されている"include"メソッドを使って外部へ処理を委譲します。

Includes the content of a resource (servlet, JSP page, HTML file) in
the response. In essence, this method enables programmatic 
server-side includes. 

The ServletResponse object has its path elements and parameters remain
unchanged from the caller's. The included servlet cannot change the 
response status code or set headers; any attempt to make a change is 
ignored. 

The request and response parameters must be either the same objects as
were passed to the calling servlet's service method or be subclasses of
the ServletRequestWrapper or ServletResponseWrapper classes that wrap 
them. 

Parameters:
  request - a ServletRequest object that contains the client's request
  response - a ServletResponse object that contains the servlet's 
    response 
Throws: 
  ServletException - if the included resource throws this exception 
  java.io.IOException - if the included resource throws this exception

"include"メソッドの引数には、呼び出し元のサーブレットの"doGet"メソッドや"doPost"メソッドが呼び出された時に引数に指定されている値をそのまま渡します。

利用方法としては下記のようになります。

public void doGet(HttpServletRequest request, HttpServletResponse response)
  throws IOException, ServletException{

  String disp = "/includetest";
  RequestDispatcher dispatch = request.getRequestDispatcher(disp);

  dispatch.include(request, response);
}

サンプルプログラム

では簡単に試してみます。

今回作成するWebアプリケーションのパスは「dispatch」とし、Webアプリケーションの置き場所は「d:¥servlet-sample¥dispatch¥」としました。コンテキストファイルは下記のようになります。

dispatch.xml

<Context path="/dispatch"
docBase="d:/servlet-sample/dispatch"/>

web.xmlファイルは下記のようにしました。

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
   http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
  version="2.4">

  <servlet>
    <servlet-name>dispatchtest</servlet-name>
    <servlet-class>DispatchTest</servlet-class>
  </servlet>

  <servlet>
    <servlet-name>includetest</servlet-name>
    <servlet-class>IncludeTest</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>dispatchtest</servlet-name>
    <url-pattern>/dispatchtest</url-pattern>
  </servlet-mapping>

  <servlet-mapping>
    <servlet-name>includetest</servlet-name>
    <url-pattern>/includetest</url-pattern>
  </servlet-mapping>
</web-app>

プログラムは下記の通りです。

DispatchTest.java

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class DispatchTest extends HttpServlet {
  public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws IOException, ServletException{

    response.setContentType("text/html; charset=Shift_JIS");
    PrintWriter out = response.getWriter();

    out.println("<html>");
    out.println("<head>");
    out.println("<title>ディスパッチ</title>");
    out.println("</head>");
    out.println("<body>");

    out.println("<p>この下の部分がインクルードで処理されています</p>");

    String disp = "/includetest";
    RequestDispatcher dispatch = request.getRequestDispatcher(disp);

    dispatch.include(request, response);

    out.println("<p>この上の部分がインクルードで処理されています</p>");

    out.println("</body>");
    out.println("</html>");
  }
}

IncludeTest.java

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class IncludeTest extends HttpServlet {
  public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws IOException, ServletException{

    response.setContentType("text/html; charset=Shift_JIS");
    PrintWriter out = response.getWriter();

    out.println("<p style=¥"background:#ff0000¥">");
    out.println("インクルードファイル内で処理されています");
    out.println("</p>");
  }
}

上記をコンパイル後に「d:¥servlet-sample¥dispatch¥WEB-INF¥classes¥」ディレクトリにクラスファイルを移動した後で、ブラウザで「http://localhost:8080/dispatch/dispatchtest」へアクセスしてみます。

include

分かりやすいようにインクルードされたサーブレットで処理された部分は背景を赤くしてあります。

このようにインクルードとはサーブレットの処理中に別のサーブレットへ処理を移し、そして元の処理に戻ってくることになります。あたかもサーブレット内に別のサーブレットを挿入して処理しているようになります。

( Written by Tatsuo Ikura )

関連記事 (一部広告含む)