プログラミング研修で扱ったJava-Servlet-JSPで、
JSPページが文字化けする。charsetで文字コード指定は入っているし、
JSPファイルの文字エンコードも間違っていない。
でも文字化けされて表示される! って現象に当たりました。
原因見つけて、『これでも文字化けでちゃうんだ』と覚え書き。
1 2 3 4 5 6 7 8 9 10 11 |
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>おはようございます</title> </head> <body> <h1>サンプル日本語</h1> </body> </html> |
このソースがこんな表示になっていました。
文字化けのよくある原因
「JSP 文字化け」で調べるとバーッと出てくるように、文字化けはよく起こします。
ブラウザと作成者の解釈違い(文字コード)で、
JSPにcharsetを指定していないから。が原因の多くですね。
HttpServletResponseのWriterへ直接HTMLソースを書き込む場合は、
キャラクターエンコードの指定忘れ。が原因のほとんどになります。
今回のケースはJSP使ってレスポンス作成していたので、
JSPファイルを中心にコードの確認をしていましたが…結果と合わない…
ServletのdoPost内での処理
文字化けが発生したのはプレーンなJava-Servletのプログラムで、
Servletが処理をしたあとで、固定文字列を表示する(冒頭のような)JSP表示というプログラム。
特にresponseの文字エンコードを書き換える部分も見当たらなかった。
1 2 3 4 5 6 7 8 9 10 11 |
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /* * * * * * * */ request.getRequestDispatcher("/WEB-INF/sample.jsp").forward(request, response); } |
ブラウザのDeveloperToolでHTTP ResposeHeaderのContent-Typeを確認すると、
charsetがISO-8859-1になっていました。
なんで??って思いながらも調査続行。
自動生成コードの功罪
ServletクラスとJSPファイルのソースを見ていても、
明確な原因が分からなかったので一連の操作を見ることにしました。
問題のページ(Servlet)へのリクエストを飛ばすところが
Htmlのanchorタグで書かれていたので詳細確認。
JavaScriptも無く素のanchorでリクエスト。
『あれ?GET? ServletはPOST処理に書かれてなかったか?』
と…問題のServletのdoGetを見てみると…
『お…おぅ… ???』
Eclipseで自動生成されたコードが残ったままで、
doPost()をcall。
HttpServletResponseのWriterに出力掛けた後に、JSP出力?
不要なコードではあったので除去してもらい、確認したところ文字化けが解消されました。
自動生成されたコードでコンパイルエラーも出ないとは言え、
”Auto-generated method stub”と書かれている代用品コードをそのまま置いて置くのは注意ですね。
ServletResponse#getWriter()の仕様確認
文字化けするという不具合の解消後、HttpServletResponse#getWriter()周りの仕様を確認。
今回のISO-8859-1にcharsetがセットされてしまうのは、APIの仕様上正常な動作でした。
文字化けもAPI仕様上は正しい結果でしたね。
ServletResponse#getWriter()ドキュメント
クライアントに文字テキストを送信できる
PrintWriter
オブジェクトを返します。PrintWriter
は、getCharacterEncoding()
によって返される文字エンコードを使用します。getCharacterEncoding
に従って、レスポンスの文字エンコードが指定されていない場合(つまり、メソッドはデフォルト値ISO-8859-1
を返すだけ)、getWriter
はそれをISO-8859-1
に更新します。https://spring.pleiades.io/ より引用
文字化けの起因となった自動生成コードの実行タイミングでは、
レスポンスの文字エンコードは未指定状態であった。
そのため、レスポンスの文字エンコードをデフォルトの”ISO-8859-1″に設定。
JSPを基にレスポンス出力時も↑の出力先に書き出しているので、
レスポンスHeaderのcharsetがISO-8859-1で返され、文字コードが合わないJSP内の文字が化けた。
という事ですね。
まとめ
Java-ServletでJSPからの結果が文字化けした時は、レスポンスHeaderのcharsetを確認する。
JSPファイルでのcharset指定漏れ、JSPファイルの文字コード不一致の他に、
ServletResponse#getWriter()呼び出しによる見えない部分での文字エンコード指定がある。
必要ではないコードはバグのもと。
”わからないから触らなかった -> バグ発生で対応に多大な費用を要した。”
なんて事になったら笑えないですね。
コメント