むかーしに書かれたコードを触っていると、文字コードが統一されていなかったりしてJSPで作成したページが文字化けしました。
今回は文字化けの対応する中で、原因等も調べた結果をまとめます。
(統一されていれば何の問題も無いのですが・・・。)
そもそも何で文字化けするのか
Webアプリケーションで文字化けが発生する原因は、レスポンスされたHTMLのエンコーディングと、
ブラウザが解釈しようとしているエンコーディングが不一致になってしまうことです。
HTMLがUTF-8でエンコードされているのに、ブラウザがEUC-JPでエンコードしようとする、など。
ブラウザのエンコーディングはどうやって決まるのか
ブラウザは自動的にエンコーディングを判断します。
- レスポンスヘッダのContent-Type
- 上記がない場合は、HTMLのmetaタグにあるcharset
どちらも指定がある場合はレスポンスヘッダの方が優先されます。
文字化けの対処でmetaタグでcharsetを指定してもエンコーディングが変わらないのは、レスポンスヘッダで別のエンコーディングが指定されているためということがよくあります。
JSPの文字化け
以上を踏まえて、JSPの文字化けについて述べていきます。
レスポンスヘッダのcharset
JSPは以下のタグを指定することによって、レスポンスヘッダのContent-Typeを指定することができます。
<%@ page contentType="text/html; charset=UTF-8" %>
これで万事解決!といきたいところですが、JSPファイル自体のエンコーディングも関連してきます。
JSPの簡単な仕組み
JSPはServletに変換されます。実際にHTMLを生成、レスポンスしているのは、ここで生成されたServletです。
デフォルトでは、TomcatなどのAPサーバのworkディレクトリ内に変換されたServletが生成されています。
JSPに書かれた内容をServletに変換していきますが、ここでもエンコーディングが関わってきます。
たとえばUTF-8で作成されたJSPを、EUC-JPだと思い込んでServletに変換すると、この段階で文字化けします。
変換処理の中でJSPの文字コードをどうやって判断するか
JSPファイル自体のエンコーディングは以下のタグで指定できます。
<%@ page pageEncoding="UTF-8" %>
pageEncodingが指定されていない場合は、contentTypeのcharsetに指定された値で判断します。
つまり以下のような場合、UTF-8と判断します。
<%@ page contentType="text/html; charset=UTF-8" %>
contentTypeのcharsetとpageEncodingは異なる値を指定することができるので、
UTF-8で作成されたJSPをShift-JISのHTMLとして返却したい場合は以下のように指定することができます。
<%@ page contentType="text/html; charset=Shift_JIS" pageEncoding="UTF-8" %>
ただし、UTF-8で利用できるが、Shift_JISに含まれない文字、たとえば🍔などの絵文字とかが含まれていると、それは文字化けします。
結論
JSPのcontentTypeとpageEncodingを適切に指定しましょう。
いっそのこと全部UTF-8にしましょう。
参考
contentTypeやpageEncodingをいちいち指定するのが面倒な場合は、web.xmlに以下を設定するといいです。
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<page-encoding>UTF-8</page-encoding>
</jsp-property-group>
</jsp-config>
これでJSPで記載しなくても、pageEncodingがUTF-8になります。
また、contentTypeを指定しない場合のcharsetはpageEncodingの指定に従うので、
JSPでは、contentTypeの指定も省略することができます。
ちなみにこの場合、web.xmlで指定した値と異なるエンコーディングをJSP側で指定すると例外が発生します。