コンテンツタイプの設定(setContentType)

広告

クライアントに対して何か出力するにあたってまず行うべき事はどのようなデータを送るのかを指定するコンテンツタイプの設定です。HTTPレスポンスヘッダの中の「Content-Type」を設定します。

コンテンツタイプには次のような種類があります。

種類拡張子Content-Type
HTMLファイルhtml, htmtext/html
テキストファイルtxttext/plain
GIFgifimage/gif
PNGpngimage/png
Windows 実行ファイルexeapplication/octet-stream

クライアントは受け取ったデータのヘッダーに含まれるコンテンツタイプを見て、データをどのようにするかを処理するかを判別します。例えばブラウザに表示したり、ファイルに保存するかどうかを確認したり、といったことです。この挙動はブラウザやクライアント側の設定に依存します。

コンテンツタイプを設定するには「HttpServletResponse」インターフェースの親インターフェースである「ServletResponse」インタフェースで定義されている「setContentType」メソッドを使います。

Sets the content type of the response being sent to the client, if the 
response has not been committed yet. The given content type may include 
a character encoding specification, for example, text/html;charset=UTF-8. 
The response's character encoding is only set from the given content 
type if this method is called before getWriter is called. 

This method may be called repeatedly to change content type and character 
encoding. This method has no effect if called after the response has been 
committed. It does not set the response's character encoding if it is 
called after getWriter has been called or after the response has been 
committed. 

Containers must communicate the content type and the character encoding 
used for the servlet response's writer to the client if the protocol 
provides a way for doing so. In the case of HTTP, the Content-Type 
header is used. 

Parameters:
  type - a String specifying the MIME type of the content

実際に使う場合には次のように記述します。

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

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

    response.setContentType("text/html");

    /* ... */
  }
}

またコンテンツタイプの中には含まれるデータの文字セットを合わせて指定できるものがあります。例えばHTMLファイルやテキストファイルです。文字コードを合わせて指定する場合には次のように「charset=」の後に文字コードを記述します。

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

※文字コードの種類については『IANA character-sets』などを参考にして下さい。

文字コードを設定しなかった場合には次のページで説明する通りデータ本文が「ISO-8859-1(Latin1)」でエンコードされます。その為、日本語を扱うデータの場合は文字化けしてしまいますので注意して下さい。

setCharacterEncodingメソッド

文字セットの指定には「HttpServletResponse」インターフェースの親インターフェースである「ServletResponse」インタフェースで定義されている「setCharacterEncoding」メソッドを使っても設定が可能です。

Sets the character encoding (MIME charset) of the response being sent to 
the client, for example, to UTF-8. If the character encoding has already 
been set by setContentType(java.lang.String) or setLocale(java.util.Locale), 
this method overrides it. Calling setContentType(java.lang.String) with 
the String of text/html and calling this method with the String of UTF-8 
is equivalent with calling setContentType with the String of 
text/html; charset=UTF-8. 

This method can be called repeatedly to change the character encoding.
This method has no effect if it is called after getWriter has been called 
or after the response has been committed. 

Containers must communicate the character encoding used for the servlet
response's writer to the client if the protocol provides a way for doing 
so. In the case of HTTP, the character encoding is communicated as part 
of the Content-Type header for text media types. Note that the character 
encoding cannot be communicated via HTTP headers if the servlet does not 
specify a content type; however, it is still used to encode text written 
via the servlet response's writer. 

Parameters:
  charset - a String specifying only the character set defined by IANA
    Character Sets (http://www.iana.org/assignments/character-sets)

使い方としては次のようになります。

response.setContentType("text/html");
response.setCharacterEncoding("Shift_JIS");

これは次のように記述した場合とまったく同じです。

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

サンプルプログラム

では簡単なサンプルで試して見ます。今回は文字コードを設定した場合としなかった場合でブラウザでの出力を比較します。

ResponseSample1.java

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

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

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

    StringBuffer sb = new StringBuffer();

    sb.append("<html>");
    sb.append("<head>");
    sb.append("<title>サンプル</title>");
    sb.append("</head>");
    sb.append("<body>");

    sb.append("<p>Sample Page</p>");
    sb.append("<p>サンプルページ</p>");

    sb.append("</body>");
    sb.append("</html>");

    out.println(new String(sb));

    out.close();
  }
}

ResponseSample2.java

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

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

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

    StringBuffer sb = new StringBuffer();

    sb.append("<html>");
    sb.append("<head>");
    sb.append("<title>サンプル</title>");
    sb.append("</head>");
    sb.append("<body>");

    sb.append("<p>Sample Page</p>");
    sb.append("<p>サンプルページ</p>");

    sb.append("</body>");
    sb.append("</html>");

    out.println(new String(sb));

    out.close();
  }
}

2つのサンプルプログラムの違いは「setContentType」メソッドの引数に文字セットを指定しているかどうかです。

サンプルプログラムをコンパイルして作成した「ResponseSample1.class」ファイルと「ResponseSample2.class」ファイルを別途作成した「web.xml」ファイルを次のように配置します。

D:¥ -- servlet-sample
        |
        +-- WEB-INF
             |
             +-- (web.xml)
             |
             +-- classes
                  |
                  +-- (ResponseSample1.class)
                  |
                  +-- (ResponseSample2.class)

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>ResponseSample1</servlet-name>
    <servlet-class>ResponseSample1</servlet-class>
  </servlet>

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

  <servlet>
    <servlet-name>ResponseSample2</servlet-name>
    <servlet-class>ResponseSample2</servlet-class>
  </servlet>

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

コンテキストファイルを作成し「(Tomcatをインストールしたディレクトリ)¥Tomcat 5.5¥conf¥Catalina¥localhost¥」ディレクトリに「sample.xml」ファイルとして保存します。内容は以下の通りです。

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

準備は以上です。ではTomcatを再起動してから「http://localhost:8080/sample/ResponseSample1」へブラウザでアクセスして下さい。

コンテンツタイプの設定

コンテンツタイプの文字コードが設定されていなかったためデータ本文はLatin1でエンコードされてクライアントに送られてきます。その為、日本語は文字化けして表示されてしまいます。

では「http://localhost:8080/sample/ResponseSample2」へブラウザでアクセスして下さい。

コンテンツタイプの設定

今度は適切な文字コードが設定されていますので日本語が含まれるデータをブラウザに返した場合でも、文字化けせずに表示されます。

( Written by Tatsuo Ikura )