Webプログラミングのトラブル事象は星の数ほどありますが,実は初級者/入門者がはまってしまうトラブルにはいくつか決まったパターンがあります。そこでPart2では,よくあるトラブルを取り上げて,その問題点と解決方法を説明します。「日本語の文字化け」「クロスサイト・スクリプティング」「最新データが表示されない」「二重クリックによる二重処理」「例外ハンドリング漏れ」の五つを取り上げます。
トラブル1 日本語が文字化けする!
ブラウザに表示した文字列が,“?”や意味不明の記号に変換されることがあります。これを一般的に「文字化け」と言います。Webプログラミングでは,文字化けが発生することがよくあります。ここでは「画面に表示した日本語」「ブラウザから送信された日本語」の文字化けについて,解決策を紹介します。
(1)画面に表示した日本語が文字化けする
図1は,「こんにちは」と表示するはずのJSP(JavaServer Pages)のプログラムを実行したところ,文字化けが発生した様子です。JSPのソースコードは,
<html>
<body>
こんにちは
</body>
</html>
のようになっています。非常に簡単なコードで,一見どこも間違っていないように見えます。しかし,何がいけないのかわかりますか?

この文字化けは,ブラウザがどの文字エンコーディング(特定の文字をどのようなバイナリ値で表現するかを規定したルール)を使うべきかわからず,そのため規定のISO-8859-1(西ヨーロッパ言語)で表示してしまったことが原因です。そこでリスト1のように,先のコードに文字化け対策をしてみました。
<%@ page contentType="text/html; charset=Windows-31J" %>
<html>
<body>
こんにちは
</body>
</html>
先頭の行に
<%@ page contentType="text/html; charset=Windows-31J" %>
という記述を追加しています。この一行は,JSPを構成する要素の一つであるpageディレクティブ(JSPファイル全体に適用される様々な属性を定義する)を指定しています。contentTypeでMIMEタイプ(テキスト,画像,音声などを扱うための規格)を指定し,charsetで文字エンコーディングを指定しています。注意すべきポイントは,
・JSPの先頭行にpageディレクティブの記述漏れをしないこと
・charsetから続く文字セットを間違わないこと
です。なお,文字エンコーディング“Windows-31J”を“Windows31J”と一文字でも間違えて指定すると,JSPのコンパイル・エラーが発生するので注意してください。
(2)ブラウザから送信された日本語が文字化けする
図2は,入力されたデータをWebサーバーに送信する画面です。

JSPのコードはリスト2の通りで,前述したpageディレクティブ指定に問題はありません。
<%@ page contentType="text/html; charset=Windows-31J" %>
<html>
<body>
<form method="post" action="example">
メッセージ:<input type="text" name="msg">
<input type="submit" value="送信">
</form>
</body>
</html>
しかし,データを受信する側のサーブレットで,リスト3(1)のように受信したデータを出力してみると,図3のように文字化けが発生しています。いったいどこが間違っているのでしょう?


これは,リクエスト情報の文字エンコーディングが設定されていないのが原因です。リスト3(1)の前に,
request.setCharacterEncoding("Windows-31J");
という具合に,ブラウザから受け取るリクエスト情報に文字エンコーディングを指定すれば解決できます(リスト4)。

前述したpageディレクティブのcharsetは「ブラウザへ送信するデータの文字エンコーディングを指定する」ものであり,setCharacterEncodingは「ブラウザから受け取るデータの文字エンコーディングを指定する」ものです。
なおリスト4は,HttpServletクラスのサブクラスで文字エンコーディングを指定していますが,HttpServletのロジックより先に実行されるjavax.servlet.Filterクラスで文字エンコーディング指定をすることがあります。リスト4の方法では,すべてのHttpServletのサブクラスで文字エンコーディング指定が必要となりますが,Filterクラスを使うと,web.xml(Webアプリケーションの定義ファイル)の設定次第で,一つのクラスで文字エンコーディング指定を完了できます。