第3章

3.1

GET と POST によるパラメータ渡し

Servlet へのパラメータ渡し（ GET 編）

これまで紹介した例はブラウザ側から Servlet にデータを渡すことはなかったが 、ブラウザからServlet にパラメータを渡して Servlet の振舞いを変えることも可能である。CGI/Servlet などのサーバサイドプログラムにパラメータを渡す方法には GET と POST の 2 種類がある。ここではまず GET について説明する。
例題: キーワード のハイライト
キーワード をパラメータとして受け取り、特定のファイルを読み込んで、キーワード の部分を色を変えて表示する Servlet（ HiLite.java ）を作成する。
ファイル HiLite.java

import java.io.*;import javax.servlet.*;import javax.servlet.http.*;public class HiLite extends HttpServlet {public void doGet(HttpServletRequest req, HttpServletResponse res)throws IOException {res.setContentType("text/html; charset=SJIS");
PrintWriter out = res.getWriter();out.println("<html><head></head><body>");out.println("<pre>");File f = new File(getServletContext().getRealPath("/WEB-INF/src/HiLite.java"));String word = req.getQueryString();
InputStreamReader fr = new InputStreamReader(new FileInputStream(f), "SJIS");
BufferedReader in = new BufferedReader(fr);}}while(true) {String line = in.readLine();if (line==null) break;line = line.replace("&", "&amp;");line = line.replace("<", "&lt;");line = line.replace(">", "&gt;");if (word!=null && word.length()!=0) {line = line.replace(word, "<font color=’red’>"+word+"</font>");}out.println(line);}
out.println("</pre>");out.println("</body></html>");out.close();

ソフトウェア工学演習 - 11

GET で Servlet にパラメータを渡すには URL のあとに “?” に続けて文字列を書けば良い。この文字列の部分（ Query String と呼ぶ）がパラメータとして Servlet に渡される。例えば
http://localhost:8080/SoftEngEnshu/servlet/HiLite?printの、print の部分が Query String（パラメータ）になる。
Servlet プログラム中では、このパラメータは doGet の第 1 引数（ HttpServletRequest クラス）に対する getQueryString() というメソッド で受け取ることができる。結局、String word = req.getQueryString();の部分で、URL の “?” 以降の部分の文字列が変数 word に入ることになる。

line = line.replace(word, "<font color=’red’>"+word+"</font>");で、このキーワードを赤色にするように置換している。ここで、replace は文字列中の部分文字列を別の文字列に置換するメソッド である。
ところで、表示するテキストの中に “<” や “>” が入っていると、HTML のタグと解釈されてしまって、表示が乱れるおそれがある。次の部分

line = line.replace("&", "&amp;");line = line.replace("<", "&lt;");line = line.replace(">", "&gt;");は、これらを &lt;, &gt; にそれぞれ置き換えている。
結局、このプログラムは HiLite.java のソース自身（これは別のファイルにしても良い）の中のキーワード を赤色で表示することになる。

http://localhost:8080/SoftEngEnshu/servlet/HiLite?print
だと、print という部分文字列が赤色で表示されることになる。
問 3.1.1 （ カレンダー）
例えば 、MyCalerdar?200410 のような形でパラメータを渡されると、2004 年 10 月のカレンダーを作成するような Servlet を作成せよ。
ヒント : y 年 m 月 d 日の曜日を求めるのに次のような Zellar の公式を用いよ

static int Zellar(int y, int m, int d) {if (m<3) {// 1 月、2 月は前年の 13 月、14 月として計算する。
y--; m+=12;}
return (y + y/4 - y/100 + y/400 + (13*m+8)/5 + d) % 7;// 0 が日曜、1 が月曜、... 6 が土曜}
問 3.1.2 （ スライド ショー）
images ディレクトリ中に 1.png, 2.png, . . . のような名前の画像ファイルを用意しておくと、この画像ファイルを順に表示するような Servlet（ SlideShow.java ）を作成せよ。
ヒント : パラメータが渡されなかった場合（ req.getQueryString() の戻り値が null になる）は、1.png を表示する。パラメータが n の時は、次のような HTML を生成する。
ソフトウェア工学演習 - 12

<html><head><title>スライド（ n ）</title></head><body><div align=’center’><img src=’../images/n .png’><hr><a href=’SlideShow?n-1’>前</a><a href=’SlideShow?n+1’>次</a></div></body></html>
ただし 、SlideShow は設置するサーブレット自身の名前である。

3.2 Form
HTML のページの中に、文字列を入力するための場所やチェックボックスなどが埋め込まれていることがある。この入力のための領域がフォームと呼ばれる部分である。
フォームの例:
ファイル Aisatsu.html<form action=’servlet/Aisatsu’ method=’post’>
あなたの名前を入力してください。<br>
姓<input type=’text’ size=’10’ name=’family’>
名<input type=’text’ size=’10’ name=’given’><br><input type=’submit’ value=’ 送信’></form>

フォームは全体を <form . . . >〜</form>というタグで囲む。その中に <input . . . >など のタグを使用する。

• <form action=’URI ’ method=’post’>〜</form>
URI は、このフォームのデータを受け取る CGI/Servlet の URI である。
なお、method=’post’ ではなく、method=’GET’ とすると、以前に紹介した URI の最後に ?をつけてパラメータを渡す方式（ GET ）で CGI/Servlet にデータを渡すことになる。しかし GET では受け渡しできるデータの大きさに限界があるので、フォームでは POST を使うことが多い。
• <input type=’text’ size=’n ’ name=’namae ’>
テキストボックスを表示する。テキストボックスは文字列を入力するための領域で、フォームの中で一番良く用いられる部品だと思われる。n は、このテキストボックスの幅、namae は、このテキストボックスを識別するための名前である。なお type=’text’ を type=’password’ に変えるとパスワード を入力するためのテキストボックス（ 入力した文字が伏せ字（ * ）になる）を表示する。
• <input type=’checkbox’ name=’namae ’ value=’str ’ >チェックボックスを表示する。str はこのチェックボックスがチェックされていたときに、CGI/Servlet に送る文字列であり、この value 属性が省略されているときは、“on” という文字列を送る。また checkedという属性がついていると最初からチェックされている状態で表示する。

ソフトウェア工学演習 - 13• <input type=’radio’ name=’namae ’ value=’str ’>
ラジオボタンを表示する。ラジオボタンはチェックボックスに似ているが、namae が同じラジオボタンはそのうち一つしか選択できない。str はこのラジオボタンが選択されていたときに、CGI/Servletに送る文字列である。checked 属性がついていると最初からチェックされている状態で表示する。

• <input type=’hidden’ name=’namae ’ value=’str ’>
隠し要素（ hidden ）は画面には表示されないが 、名前と値は CGI/Servlet に転送される。
• <input type=’submit’ value=’str ’>
送信ボタンを表示する。このボタンが押されると CGI/Servlet にフォームのデータを転送する。strはこのボタンに表示する文字列である。
• <input type=’reset’ value=’str ’>
リセットボタンを表示する。このボタンが押されるとフォームに記入した内容をクリアする。str はこのボタンに表示する文字列である。
• <textarea cols=’haba ’ rows=’takasa ’ name=’namae ’>〜</textarea>
複数行の文字が入力できるテキストボックスを表示する。haba は幅、takasa は高さを指定する。〜の部分の文字列が 、このテキストボックスに最初に表示される。

3.3

Servlet へのパラメータ渡し（ POST 編）

POST でデータを受け取る場合、Servlet は doGet の代わりに doPost というメソッド を実行するので、この doPost メソッド を定義する必要がある。
実はフォームからデータは次のような形の文字列として送られる。

name1 =value1 &name2 =value2 & . . . &namen =valuen
name1 , name2 , . . . は input タグや textarea タグに付けられていた name 属性で value1 , value2 ,. . . はそれぞれに対応する値（テキストボックスの場合は入力された文字列、チェックボックスやラジオボタンなどの場合は、タグ中の value 属性）である。
この value 属性を Servlet 中で読み込むには doPost の第 1 引数（ HttpServletRequest クラス）に対する getParameter メソッド を使う。getParameter メソッド の引数は name 属性を指定する。
getParameter メソッドは上のようなフォームから送られてくるデータを解析して対応する値（ value属性）を返す。
なお、フォームに日本語を入力する場合、日本語は特別なエンコーディングをされて送られてくる。
例えば “香川大学” は “%8D%81%90%EC%91%E5%8Aw” とエンコード される（元の文字コードが SJIS の場合）。そこで、これをデコード する必要がある。

ソフトウェア工学演習 - 14

例題: おうむ返し
さきほどの Aisatsu.html のフォームを処理する Servlet である。
（この例では Aisatsu.html はアプ
リケーションルートの直下に置かれる戸仮定している。）フォームに入力された内容を、そのままおうむ返しに表示する。
ファイル Aisatsu.java

import java.io.*;import javax.servlet.*;import javax.servlet.http.*;public class Aisatsu extends HttpServlet {public void doPost(HttpServletRequest req, HttpServletResponse res)throws IOException {res.setContentType("text/html; charset=SJIS");
PrintWriter out = res.getWriter();out.println("<html><head></head><body>");req.setCharacterEncoding("JISAutoDetect");
String family = req.getParameter("family");
String given = req.getParameter("given");out.println("こんにちは ,"+family+" "+given+"!");
out.println("</body></html>");out.close();}}
フォームに日本語が入っている場合に対応するためにはデコード をする必要がある。

req.setCharacterEncoding("JISAutoDetect");の setCharacterEncoding メソッド はフォームに使われている文字コード を指定する。この例で使われている”JISAutoDetect”の場合は、Shift-JIS, EUC-JP, ISO 2022 JP のなかから自動判別する。
問 3.3.1 （ 見積り作成 Servlet ）

品名と単価の表と、その個数を入力してもらうためのフォーム（テキストボックス）を表示する HTML
ファイルと、 そのフォームから入力を受け取って、合計金額を表示する Servlet を作成せよ。
（ さらに結果を見積書のようにテーブルとして整形せよ。）

問 3.3.2 （ HiLite の拡張）

右のようなフォームから入力を受け取って、あるファイル中の指定された文字列を、指定された色で強調して表示する Servlet を作成せよ。

ソフトウェア工学演習 - 15

例題: ゲストブック
Web ページを見た人に名前やメールアドレス、感想などを記入してもらい、HTML ファイルに保存する Servlet である。フォームの HTML のソースはつぎのようになる。
（この例ではアプ リケーションルートに作成すると仮定する。）
ファイル GuestBook.html<html><head><title>ゲストブック記帳</title></head><body><form action=’servlet/GuestBook’ method=’post’>ゲストブックに記帳をお願いします。<br><table><tr><td>名前:</td><td><input type=’text’ size=’30’ name=’ 名前’></td></tr><tr><td> メールアドレス:</td><td><input type=’text’ size=’30’ name=’ メールアドレス’></td></tr><tr><td>ホームページ :</td><td><input type=’text’ size=’30’ name=’ ホームページ ’></td></tr><tr><td>何かひとこと </td><td><textarea name=’ ひとこと ’ rows=’5’ cols=’30’></textarea></td></table><input type=’submit’ value=’ 送信’><input type=’reset’ value=’ やめ’></form></body></html>Servlet では、tmp というデ ィレクトリにある Guests.html というファイルの最後の方にフォームに入力された内容を書き足していくことにする。一度、tmp.html という名前のファイルで変更した内容を作成し 、あとで tmp.html のファイル名を Guests.html に変更する。
最初 Guests.html は次のような内容でアプリケーションルートに作成しておく。

ソフトウェア工学演習 - 16

ファイル Guests.html<html><head><title>ゲストブック</title></head><body><h1 align=’center’>ゲストブック</h1><hr><!-- OWARI --></body></html>プログラムは長いのでいくつかに分割して提示する。
ファイル GuestBook.java（その 1 ）import java.io.*;import java.util.*;// Enumeration 用に必要
import javax.servlet.*;import javax.servlet.http.*;public class GuestBook extends HttpServlet {最初の方は特にこれまでのプログラムと違う点はない。
ファイル GuestBook.java（その 2 ）public void doPost(HttpServletRequest req, HttpServletResponse res)throws IOException {res.setContentType("text/html; charset=SJIS");
req.setCharacterEncoding("JISAutoDetect");
PrintWriter out = res.getWriter();out.println("<html><head></head><body>");File f = new File(getServletContext().getRealPath("Guests.html"));BufferedReader fin = new BufferedReader(new InputStreamReader(new FileInputStream(f), "SJIS"));
File tmp = new File(getServletContext().getRealPath("tmp.html"));PrintWriter fout = new PrintWriter(new OutputStreamWriter(new FileOutputStream(tmp), "SJIS"));
while (true) {String line = fin.readLine();if (line.trim().equals("<!-- OWARI -->")) break;fout.println(line);}// 続く . . .
（その 2 ）では、Guests.html, tmp.html の 2 つのファイルをオープンし 、“<!-- OWARI -->” という行が現れるまでは、単に Guests.html から tmp.html へコピーをする。

ソフトウェア工学演習 - 17

ファイル GuestBook.java（その 3 ）fout.println("<table border>");Enumeration keys = req.getParameterNames();while (keys.hasMoreElements()) {fout.print("<tr>");String left = (String)keys.nextElement();
String right = req.getParameter(left);fout.print("<td>"+left+"</td>");fout.print("<td>"+right+"</td>");fout.print("</tr>");}fout.println("</table>");fout.println("<hr>");
ここでフォームからのデータを解析し 、テーブルを作成している。getParameterNames メソッド
はフォームの中で使われているすべての name 属性を列挙したデータ（ Enumeration 型 ）を返す。
Enumeration クラスは何かの “集まり” を表すデータ型である。このクラスのオブジェクトに対しては 、hasMoreElements というメソッド でデータがまだ残っているかど うかを調べることができる。
データが残っている場合は nextElement というメソッド で次のデータを取り出すことができる。ただし nextElement メソッド の戻り値の型は Object 型という一般的な型なので、このプログラムの場合は String 型にキャストする必要がある。
Enumeration については、Java の API ド キュメント :http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/util/Enumeration.htmlも参照すること。
ファイル GuestBook.java（その 4 ）fout.println("<!-- OWARI -->");
while (true) {String line = fin.readLine();if (line==null) break;fout.println(line);}
fin.close();fout.close();f.delete();tmp.renameTo(f);（その 4 ）では、次に Servlet を起動したときに書込む部分の目印になるように、“<!-- OWARI -->” と出力し 、Guests.html の残りの部分を tmp.html にコピーする。最後に両方のストリームを close()
して、Guests.html を削除し 、tmp.html の名前を Guests.html に変更している。
ファイル GuestBook.java（その 5 ）out.println("御記帳有難うございました。<br>");out.print("ゲストブックは <a href=’../Guests.html’>こちら </a>です。");}}

out.println("</body></html>");out.close();

お礼の文章と、できあがったゲストブックへのリンクをブラウザに表示して実行を終える。

ソフトウェア工学演習 - 18

問 3.3.3 （ 日記作成 Servlet ）「日付」と「天気」と「題名」と「日記」の 4 つの入力ができる日記作成 Servlet（ Diary.java ）を作成せよ。ゲストブックと逆に、新しい日記ほど 前に付け加えられるようにせよ。
問 3.3.4 （ 家計簿）
右のようなフォームから入力を受け取って、簡単な家計簿を生成する Servlet を作成せよ。入力した項目に加えて、その日の支出の計とそれまでの支出の累計の両方を計算してテーブルの形に整形し 、ゲストブックとおなじようにファイルにテーブルを追加していくようにせよ。

参考: POST を利用する Servlet をデバッグするときには、フォームから送られてくるデータを保存しておくと便利である。それには次のような Servlet を利用すれば良い。
ファイル Debug.java

import java.io.*;import javax.servlet.*;import javax.servlet.http.*;public class Debug extends HttpServlet {public void doPost(HttpServletRequest req, HttpServletResponse res)throws IOException {res.setContentType("text/html; charset=SJIS");
PrintWriter out = res.getWriter();out.println("<html><head></head><body>");int len = req.getContentLength();char[] buf = new char[len];File f = new File(getServletContext().getRealPath("Debug.out"));PrintWriter fout = new PrintWriter(new FileWriter(f));
BufferedReader in = req.getReader();
in.read(buf);
in.close();fout.print(buf);
fout.close();out.println("<tt>CONTENT_LENGTH</tt>は "+len+"です。");
out.println("<a href=’../Debug.out’>Debug.out</a>にデバッグ 情報を書きこみました。");
out.println("</body></html>");out.close();}}この Servlet はフォームから送られてくる情報を Debug.out というファイルに書き出す。

ソフトウェア工学演習 - 19

キーワード :GET, Query String, getParameter メソッド , フォーム, POST, doPost メソッド , setCharacterEncoding
メソッド , getParameterNames メソッド , Enumeration クラス,

ソフトウェア工学演習 - 20