■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
                      2007年10月21日

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

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


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


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


では、前回のソース・コードの解説をしておきましょう。

まず、testform01.htmlのHTMLのほうから説明します。

当初はHTML自体の詳しい説明もしようと思っていたのですが、
あまりJava以外のお話まで詳しくし過ぎると、時間がかかって
しようがないので、必要最小限の説明だけに留めることにします。

なお、HTMLの言語は、小文字で書いても大文字で書いても、どち
らでもいいことになっているのですが、当メールマガジンでは、
見やすくするために適当に大文字と小文字を使い分けることがあ
ります。ただし、気分的なもので、あまり意味はありません。

--------------------------------------------------------
<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>
--------------------------------------------------------

まず最初に、上記の<HTML>や<HEAD>や<BODY ・・・・>といった、
<>の中の先頭に書かれた単語は、「タグ(tag)」と呼ばれます。
また、タグの後ろ、たとえばBODYの後ろに書かれているbgcolor
などは、そのタグの「属性」と呼ばれます。

そして、最初に書かれるHTMLタグ(つまり<HTML>という行)は、
「これからHTMLの文書を書き始めます」という意味を表します。
これに対して、最後の</HTML>というタグは、「以上でHTMLの
文書を終わります」という意味を表します。
つまり、/で始まるタグは終わりの意味を表すのです。
以下、同様に、</TITLE>は<TITLE>の終わり、</HEAD>は<HEAD>
の終わりという意味になります。

次のHEADタグは、ヘッダー(header = 頭書き)の記述のための
タグです。ヘッダーは文書の本文に含まれない情報を記述する
ところで、主として書かれる情報は文書のタイトルです。
そして、そのタイトルは、TITLEタグによって記述します。つまり、
<TITLE>と</TITLE>にはさまれた部分がタイトルになります。
ここに記述されたタイトルは、Webページを開いたときにWebブラ
ウザーのタイトル・バーに表示されます。
TITLEタグ自体は、<HEAD>と</HEAD>に囲まれた範囲内に書かなけ
ればなりません。

そして文書の本体は、BODYタグの範囲内に記述します。つまり、
<BODY>から</BODY>までの間に記述します。
ここに書かれた内容が、実際にWebブラウザーに表示されること
になります。

上の例では、

<BODY bgcolor="#77ffff" text="#fa5a00">

というように、BODYタグにbgcolorという属性とtextという属性
が指定されています。
このbgcolorはWebページの背景色(background color)を指定
するもので、

bgcolor="#rrggbb"

という形式で、RGBの値が16進数で指定されます。つまり、rrの
ところはRed(赤)、ggのところはGreen(緑)、bbのところは
Blue(青)の数値を16進数で指定します。

同様にtextはWebページの文字の色を指定するもので、

text="#rrggbb"

という形式で、RGBの値が16進数で指定されます。


次の

<H1>vol.074 doPostのテスト・ページ</H1>

のH1タグは見出し(heading)を書くためのタグで、文字列の
強調表示をしてくれるものです。H1のほかにもH2、H3〜H6と
いったものがあり、番号の小さいほうを大きい見出しに使います。
たとえば、H1を大見出しに、H2を中見出しに、H3を小見出しに、
といった使い方をします。
基本的には、字を太く大きく表示してくれるのですが、実際に
どのように表示されるかについては、Webブラウザーに依存し、
すべてのWebブラウザーで同じように表示されるわけではありま
せん。


次のFORMタグは、フォーム(form)を記述するためのタグです。
フォーム(form)の元々の意味は、何かの申し込みなどに使う用紙
のことです。
つまり、申し込み用紙などをWebページにするために用意されたのが、
このFORMタグなのです。

実際には、用紙(をWebページ化したもの)に入力された情報(データ)
をCGIなどのプログラムに送って処理してもらう必要がありますので、
処理するプログラムを指定しておく必要があります。
そこで、FORMタグでは、

<FORM action="http://localhost:8080/JStudy2/servlet/test2" method="POST">

のように、action属性によって、プログラム(ここではサーブレット)
のURLを指定し、method属性によって、処理の方式(POSTかGETか)を
指定するようになっています。

この<FORM>と</FORM>の間に入力する内容を記述していくわけですが、
上記の例では、「生年月日をYYYYMMDDの形式で入力してください。」
という文字列を表示したあと、

<INPUT TYPE="text" NAME="dayOfBirth" VALUE="" SIZE=10>

というINPUTタグによって入力フィールドを一つ用意しているだけです。

INPUTタグはフォームの入力情報を記述するためのタグです。
INPUTタグでTYPE="text"というパラメーターを指定したものは、
テキスト・フィールドを表します。そしてNAMEパラメーターは
そのテキスト・フィールドに名前をつけるためのものです。
ここでは、dayOfBirthという名前をつけていますが、この名前が
サーブレットで使用されることになります。
VALUE属性はテキスト・フィールドの初期値(デフォルト値)を指定
するもので、ここでは何も指定していません。つまり、Webページが
表示された段階ではこのテキスト・フィールドは空の状態になってい
ます。
最後のSIZEパラメーターは、この入力フィールドの表示幅を(半角の
文字数で)指定するものです。ここでは10文字まで表示できる幅を
指定しています。

BRタグは改行を意味するタグです。


<INPUT TYPE="submit" NAME="sumit" VALUE="送信">

は、このフォームに入力されたデータを送信するためのもので、
TYPE属性に"submit"という値を指定すると送信を行うためのボタン
を表示してくれます。また、VALUE属性に指定した文字列は、その
ボタンに表示されます。


では続いて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();
   }

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

TestServletのdoGet()メソッドの内容が理解できていれば
ほとんど理解できると思いますが、新出のメソッドとして、
HttpServletRequest(正確にはそのスーパーインターフェース
のServletRequest)のgetParameter()が使われています。
これは、HTMLのFORMを使って入力されたデータを受け取るため
のメソッドで、引数としてINPUTタグで指定したNAME属性の値を
指定します。
つまり、さきほどのHTMLでは入力フィールドの指定が

<INPUT TYPE="text" NAME="dayOfBirth" VALUE="" SIZE=10>

となっていましたから、そのNAME属性の値は"dayOfBirth"です
から、getParameter()メソッドの引数にも"dayOfBirth"を指定
します。
そうすると、この入力フィールドに入力されたデータがgetParameter()
メソッドの戻り値として返される、という仕組みになっています。
この戻り値はString型なので、上のソース・コードでは

String dob = request.getParameter("dayOfBirth");

というようにString型の変数で受け取っています。

なお、ここで受け取った文字列は、YYYYMMDDの形式の生年月日ですが、
このサーブレットでは、この文字列(文字列といっても数字ですが)
をYYYYとMMとDDの三つの部分に分割しています。そのために使っている
のが、Stringオブジェクトのsubstring()メソッドです。
substring()メソッドは、Stringの文字列の中から部分的な文字列を
取り出すメソッドで、引数にはStringの文字列の中の何文字目から
何文字目までを取り出すかを指定します。ただし、インデックス
(0から始まる番号)で指定し、最後の文字の番号はその文字の番号
自体ではなく、最後の文字の番号+1で指定します。
たとえば、上のソース・コードではdob.substring(0, 4)という形で
YYYYの部分を取り出していますが、これは、0番目の文字から始まり
3番目の文字に終わる文字列を取り出すことを指定したことになります。

最後の

out.close();

は形式的なもので、実際にはなくても問題はありませんが、一度
close()を実行するともうprintln()は実行できなくなりますので、
書き出しを終了することを明確にするという意味があります。


以上でTestServlet2のソース・コードは理解できることと思います。



では、少しこのアプリケーションを変更して、日本語の文字列も入力
させてみましょう。

まず、testform01.htmlを下記のように変更してみましょう。
見ての通り、氏名を入力するためのコードが追加されただけです。

--------------------------------------------------------
<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">
氏名を漢字で入力してください。
<BR>
<INPUT TYPE="text" NAME="name" VALUE="" SIZE=20>
<BR>
<BR>
生年月日をYYYYMMDDの形式で入力してください。
<BR>
<INPUT TYPE="text" NAME="dayOfBirth" VALUE="" SIZE=10>
<BR>
<BR>
<INPUT TYPE="submit" NAME="sumit" VALUE="送信">
</FORM>
</BODY>
</HTML>
--------------------------------------------------------


これに合わせて、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");
      String name = request.getParameter("name");
      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(name + "さんの生年月日は" + dob.substring(0, 4) + "年" + dob.substring(4, 6) + "月" + dob.substring(6, 8) + "日です。");
      out.println("</BODY>");
      out.println("</HTML>");
      out.close();
   }

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

何が変更されたかは、わかりますね。

では、これらを保管してから、テストしてみてください。
(テストの仕方を忘れた人はvol.072を復習してください。)


どうですか。漢字で入力した氏名が文字化けしてしまいますね。


前回は、サーブレットから送られてくる文字コードの問題について
お話しましたが、今回の問題はサーブレットに送信する文字コード
(エンコーディング)の問題であり、前回とはまた別の問題なのです。

皆さんの環境のWebブラウザーから入力した文字列はShift_JISになっ
ているはずなので、サーブレットにもそれを知らせておく必要があり
ます。

そのためには、HttpServletRequest(正確にはそのスーパーインター
フェースのServletRequest)のsetCharacterEncoding()というメソッ
ドを使って、
request.setCharacterEncoding("Shift_JIS");
というコードを追加し、TestServlet2を下記のように修正します。
(setCharacterEncoding()メソッドはgetParameter()メソッドよりも
前に実行しておく必要があります。)

--------------------------------------------------------
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");
      request.setCharacterEncoding("Shift_JIS");
      PrintWriter out = response.getWriter();
      String dob = request.getParameter("dayOfBirth");
      String name = request.getParameter("name");
      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(name + "さんの生年月日は" + dob.substring(0, 4) + "年" + dob.substring(4, 6) + "月" + dob.substring(6, 8) + "日です。");
      out.println("</BODY>");
      out.println("</HTML>");
      out.close();
   }

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

どうですか。これでテストすると文字化けしなくなったでしょう。


では、次にdoGet()メソッドでWebブラウザーからの入力データを
受け取る方法を説明しましょう。

まず、TestServlet2を下記のように修正しましょう。
つまり、TestServlet2にdoGet()メソッドを追加し、doPost()とほと
んど同じ処理内容にします。

--------------------------------------------------------
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");
      request.setCharacterEncoding("Shift_JIS");
      PrintWriter out = response.getWriter();
      String dob = request.getParameter("dayOfBirth");
      String name = request.getParameter("name");
      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(name + "さんの生年月日は" + dob.substring(0, 4) + "年" + dob.substring(4, 6) + "月" + dob.substring(6, 8) + "日です。");
      out.println("</BODY>");
      out.println("</HTML>");
      out.close();
   }

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

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

これを保管したら、Webブラウザーで

http://localhost:8080/JStudy2/servlet/test2?name=Nihon%20Tarou&dayOfBirth=19810203

のようにURLを入力してみましょう。
こうすると、doGet()メソッドが呼び出されて、処理結果がWebブラウ
ザーに表示されますね。(「vol.075 doGetのテスト・応答ページ」と
いうように表示されるからdoGet()メソッドが実行されていることは
わかりますね。)

このようにGET方式を使用する場合はURLの中に
?name=xxxx&dayOfBirth=xxxx
というような形式でデータを指定してサーバーに渡すことができます。

ただ、このやり方だと、特殊な文字や日本の文字を入力するのが非常
に面倒になります。たとえば、上記の例では、スペースをそのまま渡
せないので「Nihon%20Tarou」の中の%20のように16進数の数字を使っ
て記します。

というわけで、GET方式を使用するやり方は手で入力する方法としては
不便です。
なお、GET方式はFORMタグを使っても指定できます(methodパラメーター
で指定)が、GET方式では送信できるデータ量に制限があるため、どう
せFORMを使うのであればPOST方式を使ったほうがいいということになり
ます。


ところで、サーブレットの中で、いちいちPrintWriterのout.println()
メソッドを呼び出してHTMLの文書を出力させるのは、面倒ですね。
それに、Webのデザイナー(Webのページをきれいに(芸術的という意味で)
仕上げる仕事をする人)はHTMLは知っていてもJava言語は知らないかも
しれません。
できれば、Java言語ではなくHTMLそのものに近いイメージでコーディング
できたほうがいいのです。

そこで登場したのがJSPです。
現在のWebアプリケーションの開発では、サーブレットには処理の流れを
制御する役目をさせ、実際のHTML文書を出力するのはJSPに役割分担させ
るのが主流になっています。

次回から、そのお話をしていきたいと思います。

今回はここまでにします。
何か、わからないところがありましたら、下記の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. 不許無断複製