Java
JSP
文字化け

JSPが文字化けしたときの対処

むかーしに書かれたコードを触っていると、文字コードが統一されていなかったりして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側で指定すると例外が発生します。