日本語Form入力

まずは日本語Form入力。

servletで、GETやPOSTで送られてくるパラメータを取得するには、

request.getParameter("text");

と、やりますが、ディフォールとのままでは、日本語のパラメータは化けてしまいます。
なので、例えばWindows-31J*1のページから投稿された場合、リクエストを処理する一番最初に、、、

request.setCharacterEncoding("Windows-31J");

エンコーディングを設定してから取得すると、ちゃんと取得できます。(Servlet2.3-API以降)

Servlet2.2-API以前には、、、

value = request.getParameter("text");
value = new String(value.getBytes("iso-8859-1"), "Windows-31J");

のようにして、1つひとつ値を変換していたようです。


しかし、、、

調子に乗ってこんなコードを書いてみたら動きません。

String encoding = request.getParameter("encoding");
if (encoding == null)
    encoding = "Windows-31J";
request.setCharacterEncoding(encoding);
String searchText = (String) request.getParameter("SearchText");

ようするに"encoding"と言うパラメータを用意して、その内容にしたがってsetCharacterEncoding()しようとしたのですが、なぜか、ENCTYPE="multipart/form-data"でPOSTしたときにだけ、日本語が取得できて、あとは"multipart/x-www-form-data"の時やGETの時には文字化けしてしまいます。

なぜでしょう。

Servletのrequest.setCharacterEncoding()のJavaDocを見ると、、、

This method must be called prior to reading request parameters or reading input using getReader().

なので、ようするに、request.setCharacterEncoding()をする前にrequest.getParameter()を呼んでいると、無効になるのですね。(エラーにしてくれればいいのに、、、)

先にJavaDocをよく読んでおけばよかったです、、、

ちなみに、上のようなことをしたいときには、まず、、、

String encoding = request.getParameter("encoding");

を読んだ後に、Servlet2.2-APIの頃の方法と同様に、、、

String value = request.getParameter("PARAM");
value = new String(value.getBytes("iso-8859-1"), encoding);

として一つ一つ変換して行く必要があるようです。(これ用にStrutsのDynamiyActionForm等をサブクラスしてあげると良いかも。)

実例1

StrutsのActionServletをサブクラスする場合。

/**
 * 日本語FORM入力をハンドルするためのActionServletクラス。
 * 
 */
public class JapaneseActionServlet extends ActionServlet {

    /**
    * 日本語FORM入力をハンドルするためのActionServlet.process().
    * requestにsetCharacterEncoding()することで以降のgetParameter()からの日本語
    * パラメータを、文字化けさせずに変換する。ここではShift_JIS(Windows-31J)で
    * 書かれたページからのFORM投稿を想定している。
    * 
    */
    protected void process(javax.servlet.http.HttpServletRequest request,
	        javax.servlet.http.HttpServletResponse response)
            throws java.io.IOException, javax.servlet.ServletException {
        request.setCharacterEncoding("Windows-31J");
        super.process(request, response);
    }
}

これに対応するようにweb.xmlも変更する。

    
        action
        path.to.JapaneseActionServlet
         ...

実例2

Servlet2.3-APIからは、Servletの処理の前に処理される、Filter機能が追加された。このFilterでsetCharacterEncoding()する物を作れば、複数のServletがあるWebAppにも適応できる。

/**
 * 日本語FORM入力をハンドルするためのServletFilter用クラス。
 * 
 */
public class EncodingFilter implements Filter {

    /**
    * 日本語FORM入力をハンドルするためのFilter.doFilter().
    * requestにsetCharacterEncoding()することで以降のgetParameter()からの日本語
    * パラメータを、文字化けさせずに変換する。ここではShift_JIS(Windows-31J)で
    * 書かれたページからのFORM投稿を想定している。
    */
    public void doFilter(
        ServletRequest request,
        ServletResponse response,
        FilterChain chain)
        throws IOException, ServletException {

        request.setCharacterEncoding("Windows-31J");
        chain.doFilter(request, response);
    }

    public void init(FilterConfig arg0) throws ServletException {
        // do nothing.
    }

    public void destroy() {
        // do nothing.
    }
}

このFilterを使うためのweb.xmlファイル設定は、、、

EncodingFilter path.to.EncodingFilter EncodingFilter *

追記メモ

tomcatの5.xでGETなFORMでのエンコーディングは、tomcatの設定ファイルservlet.xmlに、、、


のように、「useBodyEncodingForURI="true"」を入れておかなければならない。


参考リンク

*1:シフトJISとほぼ同義