Java

Tomcat メモ – GET リクエストのパラメータのエンコーディング

Servlet / JSP で GET/POST パラメータを受け取るときは request#setCharacterEncoding() を事前に読んでおく。

これは今時常識ですが、Tomcat でどうしても文字化けしてしまい、2時間くらいハマりました。

WebLogic ではどのバージョンでも setCharacterEncoding() で指定した文字セットでデコードしてくれるのに、Tomcat だと ISO-8859-1 として文字列が取得できてしまうという状況です。

Apache のバグデータベースにも Open 中のバグはなく、ぶらぶら調べてみたら@IT の記事に答えがありました!

なんと Tomcat 5.x から GET パラメータに対しては setCharacterEncoding() が効かなくなったそうです。

・@IT – Javaの文字化け対策FAQ(3)

■GETメソッド利用時の注意点

setCharacterEncodingメソッドの利用において1点注意すべき点は、フォームのデータ送信にGETメソッドを用いたときの振る舞いがWebコンテナの実装依存であることだ。

対策方法は useBodyEncodingForURI というパラメータを servlet.xml 内で指定することだそうです。
恐らく一般的な Tomcat ユーザでは常識なんでしょうね。
例えばこんな感じ。

    <Connector port="8080" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" redirectPort="8443" acceptCount="100"
connectionTimeout="20000" disableUploadTimeout="true" useBodyEncodingForURI="true"/>

明示的にエンコーディングを指定したのだから、それに従うべき、と個人的には思いますが・・。
勉強になりました。

追記:
仕様(2.3/2.4 で確認)によると"It must be called prior to parsing any post data or reading any input from the request." とあり、setCharacterEncoding は post データのエンコードを決定するためのメソッドであることがわかります。
GET のパラメータのエンコーディングについては仕様がなく、コンテナ依存になっている状態のようですね。
#最新の 2.5 では未確認

追記2:
いや、GET リクエストは HTTP リクエストの一行目に書かれているのだから、デコード対象である "any input from the request" に含まれるんじゃないの?

追記3:
単にリクエストからデータを呼び出す前にこのメソッドを呼び出しておけよと言っているだけで、 GET パラメータにもこのエンコーディングが適用されるようなことは暗黙的にも明示的にも言ってないですね。
Servlet Spec 2.5 – SRV.3.9 Request data encoding では、

The default encoding of a request the container uses to create the
request reader and parse POST data must be “ISO-8859-1” if none has been
specified by the client request.

と言っているので、このセクションでは POST データのエンコーディングについて説明していることが暗黙的に読み取れます。
GET リクエストパラメータのエンコーディングについてはざっとみたところ Servlet Spec 2.5 でも触れられていないみたいでした。

関連エントリ:
るいもの戯れ言 – HTTP GETリクエストにおけるパラメータの文字コード