Javaの道 Javaに関する
 ニュースJava基本Servlet・JSPオープンソースFAQ掲示板
Javaの道 > Servlet・JSP > Servlet −13.文字化け対策
更新日:2012/2/26
Servlet−13.文字化け対策
ここでは、Servlet・JSPでの文字化け対策について解説します。文字エンコード方法を理解してプログラム開発を行うことにより、Servlet・JSPでの日本語の文字化けを防ぐことができます。

実行環境
・WindowsXP Home Edition
・J2SE 1.5.0_03
・Tomcat 5.0.18
ブラウザ出力時の文字コード
Servlet・JSPで作成したプログラムをブラウザに出力する際の文字コードの指定方法について解説します。HTMLでは以下の順序で文字コードの認識が行われます。
1. HTTPヘッダのContent-Type(charset)の値
2. HTMLファイル内のMETAタグのContent-Type(charset)の値
Tomcatなどのサーブレットコンテナは指定しない限りデフォルトの文字コード(Tomcatの場合は、ISO-8859-1)をHTTPヘッダのContent-Typeに指定します。そのため、Servlet・JSPでMETAタグを記載し、文字コードを指定していた場合でもその値は無視されます。
Servlet・JSPで文字コードを指定するためには、HTTPヘッダのContent-Typeを指定する必要があります。HTTPヘッダのContent-Typeを指定する方法を以下に記載します。
Servlet
Servletの場合は、HttpServletResponseインタフェースのsetContentTypeメソッドでHTTPヘッダのContent-Typeの指定を行います。 Content-Typeの指定は、データがブラウザに返される前に行う必要があります。
public class EncodeServ extends HttpServlet { 
  public void doGet(HttpServletRequest req, 
                    HttpServletResponse res) 
              throws ServletException, IOException {

    res.setContentType("text/html; charset=Windows-31J");

    -----------------------------
    -----------------------------
JSP
JSPの場合は、pageディレクティブのcontentType属性でHTTPヘッダのContent-Typeの指定を行います。
<%@ page language="java" 
    contentType="text/html; charset=Windows-31J" %>

----------------------------- -----------------------------
パラメータの文字コード
<form>タグなどから送信されるパラメータを受け取る際の文字コードを指定することができます。パラメータの文字コードと、ブラウザ出力時の文字コードが異なる場合はパラメータが文字化けします。
Servlet
Servletの場合は、HttpServletRequestインタフェースのsetCharacterEncodingメソッドでパラメータの文字コードを指定します。文字コードの指定は、パラメータを取得する前に行う必要があります。
public class EncodeServ extends HttpServlet { 
  public void doGet(HttpServletRequest req, 
                    HttpServletResponse res) 
              throws ServletException, IOException {

    res.setContentType("text/html; charset=Windows-31J");
    req.setCharacterEncoding("Windows-31J");

    -----------------------------
    -----------------------------
JSP
JSPの場合は、requestオブジェクトのsetCharacterEncodingメソッドでパラメータの文字コードを指定します。
<%@ page language="java" 
    contentType="text/html; charset=Windows-31J" %>

<html>
<body>

<% request.setCharacterEncoding("Windows-31J"); %>

-----------------------------
-----------------------------

※Tomcat5.xより、FORMのGETメソッドでパラメータを送信した場合、setCharacterEncodingメソッドを無視するようになりました。POSTメソッドの場合は有効です。
GETメソッドの場合、server.xmlファイルの<connector>タグのuseBodyEncodingForURI属性をtrueに指定することで、setCharacterEncodingメソッドを有効にできます。

Tomcat7.xから、useBodyEncodingForURI属性の設定は不要になりました。

setCharacterEncoding以外の対策
setCharacterEncodingがうまく動作しない場合は、getBytesメソッドでパラメータをバイト配列に変換し、それを出力したい文字コード(例ではWindows-31J)を指定して変換しなおすことで、文字化けを解消できます。但し、ほとんどのケースでsetCharacterEncodingの設定で対応できると思いますので、まずはsetCharacterEncodingの設定を確認しましょう。
<%@ page language="java" 
    contentType="text/html; charset=Windows-31J" %>

<html>
<body>

<% String nameA = request.getParameter("nameA");
   nameA = new String(nameA.getBytes("8859_1"),"Windows-31J"); %>

-----------------------------
-----------------------------
JSP実行時の文字コード
Java内部ではすべての文字がUnicodeで処理されています。そのため、JSPで記載されたプログラムも、一旦UnicodeにエンコードされてJava内部で処理されています。ここでは、Unicodeにエンコードされる際のJSPの文字コードの指定方法について解説します。

JSPの文字コードの指定はpageディレクティブのpageEncoding属性で行います。JSPをEUC-JPで記載している場合は、EUC-JPと、Windows-31Jで記載している場合はWindows-31Jで記載します。pageEncoding属性が指定されていない場合は、contentType属性の値が指定されます。
<%@ page contentType="text/html; charset=Windows-31J"
         pageEncoding="Windows-31J" %>

----------------------------- -----------------------------
pageEncoding属性の指定が正しく行われていない場合、文字化けの原因となります。あまり行うことはないと思いますが、contentType属性とpageEncoding属性を正しく指定することによりEUC-JPで記載したJSPをWindows-31Jで出力することなどができます。

JSPは一旦、Servletに変換されて実行されます。index.jspというファイル名のJSPはindex_jsp.javaというファイル名のServletに変換されて実行されます。Servletに変換されたファイルはデフォルトの設定では、$CATALINA_HOME\work\Catalina\localhost\コンテキスト名の配下にあります。

JSPからServletに変換される際、デフォルトの設定では文字コードはUnicodeで変換されます。デバッグなどのため、Servletを閲覧すると他の文字コードでJSPを記載していた場合、文字化けしています。web.xmlファイルでjavaEncodingパラメータを指定することにより、Servletへ変換する際の文字コードを指定することができます。
<servlet>
  <servlet-name>jsp</servlet-name>
  <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>

  ----------------------------

  <init-param>
    <param-name>javaEncoding</param-name>
    <param-value>Windows-31J</param-value>
  </init-param>

  ----------------------------  

</servlet>

JSPでの文字コード判別手順は以下のようになります。
Javaの道_JSP_文字コード判別手順
Windows-31J
Windows-31Jとは、Windows環境で用いられている文字コードのことです。Windows環境の文字コードはShift_JISと思われている方も多いですが、正確にはWindows-31JとShift_JISは異なるものです。Windows-31JとShift_JISの違いは特殊文字をサポートしているかにあります。Windows-31Jは特殊文字として、NEC特殊文字(まる1、(株)など)、IBM特殊文字(はしご高)などをサポートしています。

JDK1.4.1からShift_JISと指定した場合の参照する文字コードが変わっています。
JDK1.4.1以前:Windows-31Jを参照
JDK1.4.1以降:Shift_JISを参照

Windows環境の場合、文字コードはWindows-31Jと指定しましょう。Windows-31Jと指定すると、実行環境に依存せずWindows-31Jが参照されます。 Shift_JISと指定した場合、Java実行環境によってはWindows-31Jが参照されたり、Shift_JISが参照されたりします。



このページのトップへ
 ニュースJava基本Servlet・JSPオープンソースFAQ掲示板
Javaの道_CopyrightJavaの道