Webプログラミングのトラブル事象は星の数ほどありますが,実は初級者/入門者がはまってしまうトラブルにはいくつか決まったパターンがあります。そこでPart2では,よくあるトラブルを取り上げて,その問題点と解決方法を説明します。「日本語の文字化け」「クロスサイト・スクリプティング」「最新データが表示されない」「二重クリックによる二重処理」「例外ハンドリング漏れ」の五つを取り上げます。

トラブル1 日本語が文字化けする!

 ブラウザに表示した文字列が,“?”や意味不明の記号に変換されることがあります。これを一般的に「文字化け」と言います。Webプログラミングでは,文字化けが発生することがよくあります。ここでは「画面に表示した日本語」「ブラウザから送信された日本語」の文字化けについて,解決策を紹介します。

(1)画面に表示した日本語が文字化けする
 図1は,「こんにちは」と表示するはずのJSP(JavaServer Pages)のプログラムを実行したところ,文字化けが発生した様子です。JSPのソースコードは,

<html>
<body>
こんにちは
</body>
</html>

 のようになっています。非常に簡単なコードで,一見どこも間違っていないように見えます。しかし,何がいけないのかわかりますか?

図1●「こんにちは」と表示するJSPを実行したところ,文字化けしてしまった様子
図1●「こんにちは」と表示するJSPを実行したところ,文字化けしてしまった様子

 この文字化けは,ブラウザがどの文字エンコーディング(特定の文字をどのようなバイナリ値で表現するかを規定したルール)を使うべきかわからず,そのため規定のISO-8859-1(西ヨーロッパ言語)で表示してしまったことが原因です。そこでリスト1のように,先のコードに文字化け対策をしてみました。

<%@ page contentType="text/html; charset=Windows-31J" %>
<html>
  <body>
    こんにちは
  </body>
</html>
リスト1●文字化け対策をしたJSPのコード

 先頭の行に

 <%@ page contentType="text/html; charset=Windows-31J" %>

 という記述を追加しています。この一行は,JSPを構成する要素の一つであるpageディレクティブ(JSPファイル全体に適用される様々な属性を定義する)を指定しています。contentTypeでMIMEタイプ(テキスト,画像,音声などを扱うための規格)を指定し,charsetで文字エンコーディングを指定しています。注意すべきポイントは,
・JSPの先頭行にpageディレクティブの記述漏れをしないこと
・charsetから続く文字セットを間違わないこと
です。なお,文字エンコーディング“Windows-31J”を“Windows31J”と一文字でも間違えて指定すると,JSPのコンパイル・エラーが発生するので注意してください。

(2)ブラウザから送信された日本語が文字化けする
 図2は,入力されたデータをWebサーバーに送信する画面です。

図2●文字列を送信するWebアプリケーションの画面
図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>
リスト2●文字列を送信するJSP

 しかし,データを受信する側のサーブレットで,リスト3(1)のように受信したデータを出力してみると,図3のように文字化けが発生しています。いったいどこが間違っているのでしょう?

リスト3●文字列を受信して出力するサーブレット
リスト3●文字列を受信して出力するサーブレット
図3●リスト3のサーブレットで文字列を出力すると文字化けが発生する
図3●リスト3のサーブレットで文字列を出力すると文字化けが発生する

 これは,リクエスト情報の文字エンコーディングが設定されていないのが原因です。リスト3(1)の前に,

 request.setCharacterEncoding("Windows-31J");

という具合に,ブラウザから受け取るリクエスト情報に文字エンコーディングを指定すれば解決できます(リスト4)。

リスト4●ブラウザから受け取る文字列に,文字エンコーディングを指定したサーブレット
リスト4●ブラウザから受け取る文字列に,文字エンコーディングを指定したサーブレット

 前述したpageディレクティブのcharsetは「ブラウザへ送信するデータの文字エンコーディングを指定する」ものであり,setCharacterEncodingは「ブラウザから受け取るデータの文字エンコーディングを指定する」ものです。

 なおリスト4は,HttpServletクラスのサブクラスで文字エンコーディングを指定していますが,HttpServletのロジックより先に実行されるjavax.servlet.Filterクラスで文字エンコーディング指定をすることがあります。リスト4の方法では,すべてのHttpServletのサブクラスで文字エンコーディング指定が必要となりますが,Filterクラスを使うと,web.xml(Webアプリケーションの定義ファイル)の設定次第で,一つのクラスで文字エンコーディング指定を完了できます。