■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
                      2007年10月14日

    楽しいJava講座 - 初心者から達人へのパスポート
                  vol.074

                                セルゲイ・ランダウ
 バックナンバー: http://www.flsi.co.jp/Java_text/
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


[このメールマガジンは、画面を最大化して見てください。]


========================================================
◆ 01.Tomcatのアプリケーション開発
========================================================


前回は、日本語(文字コードとしてShift_JISを使う場合)の文字
を表示するためのサーブレットの注意点についてお話しました。
しかし、今はグローバルな時代といわれていますし、今後は、
日本語以外にもさまざまな言語の文字を混在させるような国際的
なWebページを表示したい場面(例えば、同じページに韓国語(ハン
グル文字)と日本語と中国語(簡体字)を同時に表示したい場合など)
も増えてくるかもしれません。
この場合はShift_JISの代わりにUnicodeの出番となります。
(Unicodeは、同じコード体系で複数の言語の文字を扱えるように
した文字コードなのです。)

というわけで、Unicodeを使って日本語の文字を表示するように、
TestServletを書き換えてみましょう。(他の言語の文字の混在に
ついては後述します。)

TestServletを下記のように書き換えてみてください。
何が変わったかわかりますね。
--------------------------------------------------------
package jp.flsi.lecture.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class TestServlet extends HttpServlet {

   public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
      response.setContentType("text/html; charset=UTF-8");
      PrintWriter out = response.getWriter();
      out.println("<HTML>");
      out.println("<HEAD>");
      out.println("<TITLE>サーブレットのテストのページ</TITLE>");
      out.println("</HEAD>");
      out.println("<BODY bgcolor=\"#77ffff\" text=\"#fa5a00\">");
      out.println("<H1>vol.074 テスト・ページ</H1>");
      out.println("このページは、TestServletの出力です。");
      out.println("</BODY>");
      out.println("</HTML>");
   }

}
--------------------------------------------------------

Unicodeにはいくつかのエンコーディング(encoding = 符号化:
データを一定のルールに基づいて符号に変換すること)の方式があり、
現在一番よく使われているエンコーディングの方式はUTF-8です。
上記のソース・コードでも、UTF-8を使用しています。

(なお、混乱する人がいるので解説を加えますが、エンコーディングは
符号化という意味であり、文字を符号化すると符号(code = コード)に
なります。(ここでいう符号は、コンピューターの内部では数値で表現され
るものです。)この符号化された文字を文字コードと呼ぶことができますか
ら、「エンコーディングはUTF-8を使います」というふうにエンコーディング
を指定すれば文字コードが決まることになります。
そのため、エンコーディングと文字コードはしばしば同義で使われること
があります。
しかし、文字コードという言葉は少々あいまいに使われています。
例えば、Unicodeなどの一つの文字体系(文字セット)自体を文字コード
と呼ぶこともあり、文字コードという言葉だけではUTF-8などの特定の
エンコーディングを表さないことがあります。
Unicodeでは、一つのエンコーディング方式だけでは都合が悪いことが
あるため複数のエンコーディングが行われるようになったのです。
このように最近では、文字コードとエンコーディングが1対1に対応しなくなっ
て来ています。
このため、混乱を避けるためには、エンコーディングという言葉を使ったほう
がいいのです。)

TestServletを上記のソース・コードのように編集したら、保管(コン
パイル)し、サーブレットをテストしてみてください。
(サーブレットのテストの仕方を忘れた人はvol.072を復習してください。)

最近のWebブラウザーのほとんどは、UTF-8に対応していますから大丈夫
だと思いますが、もしうまく表示できないというWebブラウザーをお持ち
の方がいましたら、このメールマガジンの下のほうに書いてある質問用の
Webページにてご報告ください。


さて、ここでUnicodeに関係するお話で注意しなければならないことが
ありますので、再度TestServletを編集してみましょう。

今度は、TestServletを下記のように書き換えて、テストしてみてくだ
さい。
(注意:通常、Webブラウザーでは、以前見たのと同じWebページを開こう
とするとキャッシュ(一時記憶)に残ったページを表示してしまうため、
変更された新しいページが見られません。この場合は、Webブラウザーの
更新ボタンを何度かクリックして最新のWebページを開くようにしてくだ
さい。)

--------------------------------------------------------
package jp.flsi.lecture.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class TestServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
response.setContentType("text/html; charset=Shift_JIS");
PrintWriter out = response.getWriter();
out.println("<HTML>");
out.println("<HEAD>");
out.println("<TITLE>サーブレットのテストのページ</TITLE>");
out.println("</HEAD>");
out.println("<BODY bgcolor=\"#77ffff\" text=\"#fa5a00\">");
out.println("<H1>vol.074 テスト・ページ</H1>");
out.println("このページは、TestServletの出力です。");
out.println("@〜Bなどの特殊な文字が文字化けするのは?");
out.println("</BODY>");
out.println("</HTML>");
}

}
--------------------------------------------------------

どうですか。@〜Bの部分が文字化けしてしまいますね。

これがどういうことか、少し解説しておきましょう。

まず、Javaは内部コードとしてUnicodeを採用していることを以前
(vol.015で)お話しました。
これはJavaのソース・コードは、通常、そのコンピューターのネイ
ティブな文字コードで書かれますが、ソース・コードをコンパイルして
バイトコードに変換すると、文字や文字列のリテラルがUnicodeに変換
されるということを意味します。
たとえば、上記のソース・コードの例では、ダブルクウォーテーション
(")で囲まれている文字列がUnicodeに変換されてバイトコードの中に
保管されることになります。

ところが、上記のソース・コードでは、
--------------------------------------------------------
response.setContentType("text/html; charset=Shift_JIS");
--------------------------------------------------------
という指定がありますから、Tomcatはこれらの文字列をUnicodeから
Shift_JISに変換してWebブラウザーに返します。

ところが、(文字コード自体は標準化されていても)文字コードの
変換(一つの文字コードから別の文字コードへの変換)はきちんと
標準化されておらず、問題が生じることがあるのです。
つまり、上記のテストで文字化けしたように、特殊な文字の場合、
適切に変換されない文字がいくつかあるのです。


では、今度はTestServletを再度、次のように書き換えてテストして
みてください。

--------------------------------------------------------
package jp.flsi.lecture.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class TestServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
response.setContentType("text/html; charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("<HTML>");
out.println("<HEAD>");
out.println("<TITLE>サーブレットのテストのページ</TITLE>");
out.println("</HEAD>");
out.println("<BODY bgcolor=\"#77ffff\" text=\"#fa5a00\">");
out.println("<H1>vol.074 テスト・ページ</H1>");
out.println("このページは、TestServletの出力です。");
out.println("@〜Bなどの特殊な文字が文字化けするのは?");
out.println("</BODY>");
out.println("</HTML>");
}

}
--------------------------------------------------------

これは、たんにShift_JISをUTF-8に書き換えただけですね。
これなら、Unicodeの文字列がUnicodeのまま表示されることになりますね。
テストしてみると、文字化けが起こらないことがわかります。


この文字化けの問題については、また後ほど再度詳しくお話いたします。



では、続いて、doPost()メソッドを使ったサーブレットのお話を
しましょう。

今度は、POST方式を使うわけですから、HTML(HTML自体は後ほど
詳しく説明します)のFORMタグというものを使って、サーブレットを
呼ぶ出すようにHTMLのファイルを作成しておきます。

(1) Eclipseのパッケージ・エクスプローラーでJStudy2を右クリックし、
「新規」→「ファイル」を選択します。
(2) 「ファイル名」にtestform01.htmlと入力し、「OK」ボタンをクリック
しましょう。
(3) パッケージ・エクスプローラーの中にtestform01.htmlができました
ら、それを右クリックし、「アプリケーションから開く」→
「テキスト・エディター」を選択します。

testform01.htmlのエディターが開きましたら、下記のようなコードを
入力して保管(Ctrl + S)しましょう。

--------------------------------------------------------
<HTML>
<HEAD>
<TITLE>サーブレットのdoPostのテストのページ</TITLE>
</HEAD>
<BODY bgcolor="#77ffff" text="#fa5a00">
<H1>vol.074 doPostのテスト・ページ</H1>
<FORM action="http://localhost:8080/JStudy2/servlet/test2" method="POST">
生年月日をYYYYMMDDの形式で入力してください。
<BR>
<INPUT TYPE="text" NAME="dayOfBirth" VALUE="" SIZE=10>
<BR>
<BR>
<INPUT TYPE="submit" NAME="sumit" VALUE="送信">
</FORM>
</BODY>
</HTML>
--------------------------------------------------------

続いて、サーブレットを作りましょう。

TestServletと同じパッケージ内に下記のソース・コードのような
サーブレットを作ってみてください。サーブレットのクラス名は
TestServlet2です。
作業を簡単に済ませるためにコピー&ペーストの機能を使ってみ
ましょう。
(1) パッケージ・エクスプローラーの中のTestServlet(これが
コピー元)を右クリック→「コピー」を選択します。
(2) パッケージ・エクスプローラーの中のjp.flsi.lecture.servlet
(これがペースト(貼り付け)先)を右クリック→「貼り付け」を
選択します。
(3) 「名前の競合」ウインドウが表示されたら、「CopyOfTestServlet」
を「TestServlet2」に書き換えて「OK」ボタンをクリックします。

では、TestServlet2のエディターを開いて、下記のようにソース・
コードを編集しましょう。
--------------------------------------------------------
package jp.flsi.lecture.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class TestServlet2 extends HttpServlet {

public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
response.setContentType("text/html; charset=Shift_JIS");
PrintWriter out = response.getWriter();
String dob = request.getParameter("dayOfBirth");
out.println("<HTML>");
out.println("<HEAD>");
out.println("<TITLE>サーブレットのdoPostのテストの応答ページ</TITLE>");
out.println("</HEAD>");
out.println("<BODY bgcolor=\"#77ffff\" text=\"#fa5a00\">");
out.println("<H1>vol.074 doPostのテスト・応答ページ</H1>");
out.println("あなたの生年月日は" + dob.substring(0, 4) + "年" + dob.substring(4, 6) + "月" + dob.substring(6, 8) + "日です。");
out.println("</BODY>");
out.println("</HTML>");
out.close();
}

}
--------------------------------------------------------
ソース・コードの解説は次回行います。

このTestServlet2は新しいサーブレットですから、web.xmlに登録しておく
必要があります。

そこで、web.xmlを下記のように編集してください。(web.xmlの内容に
ついても、後ほど説明いたします。)
--------------------------------------------------------
<?xml version="1.0" encoding="ISO-8859-1"?>

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   version="2.5">

    <servlet>
        <servlet-name>TestServlet</servlet-name>
        <servlet-class>jp.flsi.lecture.servlet.TestServlet</servlet-class>
    </servlet>

    <servlet>
        <servlet-name>TestServlet2</servlet-name>
        <servlet-class>jp.flsi.lecture.servlet.TestServlet2</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>TestServlet</servlet-name>
        <url-pattern>/servlet/test</url-pattern>
    </servlet-mapping>


    <servlet-mapping>
        <servlet-name>TestServlet2</servlet-name>
        <url-pattern>/servlet/test2</url-pattern>
    </servlet-mapping>
</web-app>
--------------------------------------------------------

編集して保管したら、Tomcatを再起動しましょう。

そして、Webブラウザーで以下のURLを開いてください。

http://localhost:8080/JStudy2/testform01.html

このWebページに生年月日をYYYYMMDDの形式で入力してみましょう。
たとえば、1981年2月3日生まれの人であれば、

19810203

と入力します。
そして「送信」ボタンをクリックします。

そうすると、「あなたの生年月日は1981年02月03日です。」と答える
Webページが返って来ますね。


今回はここまでにします。
何か、わからないところがありましたら、下記のWebページまで質問を
お寄せください。


(続く)



┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
★ホームページ:
      http://www.flsi.co.jp/Java_text/
★このメールマガジンは
     「まぐまぐ(http://www.mag2.com)」
 を利用して発行しています。
★バックナンバーは
      http://www.flsi.co.jp/Java_text/
 にあります。
★このメールマガジンの登録/解除は下記Webページでできます。
      http://www.mag2.com/m/0000193915.html
★このメールマガジンへの質問は下記Webページにて受け付けて
 います。わからない所がありましたら、どしどしと質問をお寄
 せください。
      http://www.flsi.co.jp/Java_text/
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

Copyright (C) 2007 Future Lifestyle Inc. 不許無断複製