第2章

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

これまで紹介した例はブラウザ側から Servlet にデータを渡すことはなかったが、ブラウザから Servletにパラメータを渡して Servlet の振舞いを変えることも可能である。CGI/Servlet などのサーバサイド
プログラムにパラメータを渡す方法には GET と POST の 2 種類がある。
GET は URL の後ろに ‘?’ という文字をつけ、その後にパラメータを書く方法で、FORM を用意しなくても、簡易にパラメータを渡すことができる。その代わり、送ることのできるデータのバイト数に制限がある。

GET によるパラメータの例:

http://maps.google.co.jp/maps?hl=ja&ll=34.292821,134.063587&z=15
POST は HTML のフォームからデータを送る必要がある。送ることのできるデータのバイト数に制限はない。
HTML のページの中に、文字列を入力するための場所やチェックボックスなどが埋め込まれていることがある。この入力のための領域がフォームと呼ばれる部分である。
フォームの例:
ファイル Aisatsu.html左の部分の HTML のソース

<form action=’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 タグの action 属性にデータを受けとるサーブレット（ 一般にサーバーサイドプログラム）の URL を指定する。この例では、同じ階層にある、Aisatsu というサーブレットにデータを送る。

情報システム演習（ Servlet の作成）- 第 2 章 p.1

2.1

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

まず GET について説明する。
例題: キーワード のハイライト
キーワード をパラメータとして受け取り、特定のファイルを読み込んで、キーワード の部分を色を変えて表示する Servlet（ HighLight.java ）を作成する。
ファイル HighLight.java

import java.io.BufferedReader;import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;import java.io.PrintWriter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HighLight extends HttpServlet {@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)throws IOException {response.setContentType("text/html; charset=Windows-31J");
PrintWriter out = response.getWriter();out.println("<html><head></head><body><pre>");// 適当な Java のソースファイル（ 例えば HighLight.java のコピー）を// WEB アプリのルートフォルダに Tekito.java という名前で置いておくこと
File f = new File(getServletContext().getRealPath("/Tekito.java"));String word = request.getQueryString();
InputStreamReader fr = new InputStreamReader(new FileInputStream(f), "Windows-31J");
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></body></html>");out.close();GET で Servlet にパラメータを渡すには URL のあとに “?” に続けて文字列を書けば良い。この文字列の部分（ Query String と呼ぶ）がパラメータとして Servlet に渡される。例えば
http://localhost:8080/SoftEngEnshu/HighLight?print
情報システム演習（ Servlet の作成）- 第 2 章 p.2

の、print の部分が Query String（パラメータ）になる。
Servlet プログラム中では、このパラメータは doGet の第 1 引数（ HttpServletRequest クラス）に対する getQueryString() というメソッド で受け取ることができる。結局、String word = request.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; にそれぞれ置き換えている。
結局、このプログラムは HighLight.java のソース自身（これは別のファイルにしても良い）の中のキーワード を赤色で表示することになる。

http://localhost:8080/SoftEngEnshu/HighLight?print
だと、print という部分文字列が赤色で表示されることになる。
問 2.1.1 （ カレンダー）
例えば 、MyCalerdar?200804 のような形でパラメータを渡されると、2008 年 4 月のカレンダーを作成するような Servlet を作成せよ。
ヒント : y 年 m 月 d 日の曜日を求めるのに、java.util.Calendar クラスのメソッド もしくは次のような 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 が土曜}
問 2.1.2 （ スライド ショー）
images ディレクトリ中に 1.png, 2.png, . . . のような名前の画像ファイルを用意しておくと、この画像ファイルを順に表示するような Servlet（ SlideShow.java ）を作成せよ。
ヒント : パラメータが渡されなかった場合（ request.getQueryString() の戻り値が null になる）
は、1.png を表示する。パラメータが n のときは、次のような HTML を生成する。

<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 は設置するサーブレット自身の名前である。
情報システム演習（ Servlet の作成）- 第 2 章 p.3

2.2 フォーム
この節では、HTML のフォーム I（ 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という属性がついていると最初からチェックされている状態で表示する。
• <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 は高さを指定する。〜の部分の文字列が 、このテキストボックスに最初に表示される。
情報システム演習（ Servlet の作成）- 第 2 章 p.4

2.3

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

POST でデータを受け取る場合（つまり、フォームからデータを受け取る場合）、Servlet は doGet
ではなく doPost というメソッド を実行する。Servlet では、この 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” とエンコードされる（元の文字コードが Windows-31Jの場合）。そこで、これをデコード する必要がある。
例題: おうむ返し
この章の最初に例として紹介した Aisatsu.html のフォームを処理する Servlet である。
（この例ではAisatsu.html はアプリケーションルートの直下に置かれると仮定している。）Aisatsu.html の「送信」ボタンを押すと、そのフォームに入力された内容を、そのままおうむ返しに表示する。
ファイル Aisatsu.java

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Aisatsu extends HttpServlet {@Override
public void doPost(HttpServletRequest request, HttpServletResponse response)throws IOException {response.setContentType("text/html; charset=Windows-31J");
PrintWriter out = response.getWriter();out.println("<html><head></head><body>");request.setCharacterEncoding("Windows-31J");
String family = request.getParameter("family");
String given = request.getParameter("given");out.printf("こんにちは ,%s %s!%n", family, given);out.println("</body></html>");out.close();}}
フォームに日本語が入っている場合に対応するためにはデコードをする必要がある。そのためには、

情報システム演習（ Servlet の作成）- 第 2 章 p.5

request.setCharacterEncoding("Windows-31J");の setCharacterEncoding メソッドで、フォームに使われている文字コードを指定する1 。”Windows31J”の代わりに ”JISAutoDetect”とすると、 Shift JIS, EUC-JP, ISO-2022-JP のなかから自動判別する。
（ただし 、文字列が短い場合は自動判別を間違う場合があるのであまりお奨めできない。）
問 2.3.1 （ 見積り作成 Servlet ）
品名と単価の表と、その個数を入力してもらうためのフォーム（テキストボックス）を表示
する HTML ファイルと、そのフォームから入力を受け取って、合計金額を表示する Servletを作成せよ。
（ さらに結果を見積書のようにテーブルとして整形せよ。）

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

例題: ゲストブック
Web ページを見た人に名前やメールアドレス、感想などを記入してもらい、HTML ファイルに保存する Servlet である。フォームの HTML は次のような内容でアプリケーションルートに作成する。）
ファイル GuestBook.html<html><head><meta http-equiv=’Content-Type’ content=’text/html; charset=Windows-31J’><title>ゲストブック記帳</title></head><body><form action=’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>
1

通常の行儀の良いブラウザの場合は、フォ−ムが書かれていた HTML ファイル（ 上の例の場合は Aisatsu.html ）の文
字コ−ド と同じ文字コ−ド でエンコ−デ ィングしてくれる。

情報システム演習（ Servlet の作成）- 第 2 章 p.6

Servlet では、Guests.html というファイルの最後の方にフォームに入力された内容を書き足していくことにする。一度、tmp.html という名前のファイルで変更した内容を作成し 、あとで tmp.htmlのファイル名を Guests.html に変更する。
最初、Guests.html は次のような内容でアプリケーションルートに作成しておく。
ファイル Guests.html<?xml version="1.0" encoding="Shift_JIS"?><html><head><title>ゲストブック</title></head><body><h1 align="center">ゲストブック</h1>
記帳しても更新されていないときはリロードしてください。
<hr/></body></html>プログラムは長いのでいくつかに分割して提示する。最初はこれまでのプログラムと違う点はない。
ファイル GuestBook.java（その 1 ）import java.io.BufferedReader;import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;import java.io.OutputStreamWriter;
import java.io.PrintWriter;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class GuestBook extends HttpServlet {（その 2 ）では、Guests.html, tmp.html の 2 つのファイルをオープンし 、“</body>” 文字列を含む行が現れるまでは、単に Guests.html から tmp.html へコピーをする。

情報システム演習（ Servlet の作成）- 第 2 章 p.7

ファイル GuestBook.java（その 2 ）@Override
public void doPost(HttpServletRequest request, HttpServletResponse response)throws IOException {response.setContentType("text/html; charset=Windows-31J");
request.setCharacterEncoding("Windows-31J");
PrintWriter out = response.getWriter();out.println("<html><head></head><body>");try {File f = new File(getServletContext().getRealPath("/Guests.html"));BufferedReader fin = new BufferedReader(new InputStreamReader(new FileInputStream(f), "Windows-31J"));

File tmp = new File(getServletContext().getRealPath("/tmp.html"));PrintWriter fout = new PrintWriter(new OutputStreamWriter(new FileOutputStream(tmp), "Windows-31J"));
String line;
while (true) {line = fin.readLine();if (line==null) {out.println("<h1>内部エラー: Guests.html が壊れています。</h1>");line="</body>";break;}
if (line.contains("</body>")) break;fout.println(line);}
次に（その 3 ）では、フォームから入力されたデータからテーブルを生成している。
ファイル GuestBook.java（その 3 ）fout.println("<table border>");fout.printf("<tr><td>名前</td><td>%s</td></tr>%n",request.getParameter("名前"));fout.printf("<tr><td> メールアドレス</td><td>%s</td></tr>%n",request.getParameter(" メールアドレス"));
fout.printf("<tr><td>ホームページ </td><td>%s</td></tr>%n",request.getParameter("ホームページ "));
fout.printf("<tr><td>ひとこと </td><td>%s</td></tr>%n",request.getParameter("ひとこと "));
fout.println("</table>");fout.println("<hr/>");

情報システム演習（ Servlet の作成）- 第 2 章 p.8

（その 4 ）では、line（その 2 で読み込まれていた</body>を含む行）を出力し 、Guests.html の残りの部分を tmp.html にコピーする。最後に両方のストリームを close() して、Guests.html を削除し 、tmp.html の名前を Guests.html に変更している。
ファイル GuestBook.java（その 4 ）fout.println(line);
while (true) {line = fin.readLine();if (line==null) break;fout.println(line);}
fin.close();fout.close();f.delete();tmp.renameTo(f);（その 5 ）では、お礼の文章と、できあがったゲストブックへのリンクをブラウザに表示して実行を終える。
ファイル GuestBook.java（その 5 ）out.println("御記帳有難うございました。<br/>");
out.println("ゲストブックは <a href=’Guests.html’>こちら </a>です。");}} catch (Exception e) {e.printStackTrace(out);}
out.println("</body></html>");out.close();問 2.3.3 （ 日記作成 Servlet ）「日付」と「天気」と「題名」と「日記」の 4 つの入力ができる日記作成 Servlet（ Diary.java ）を作成せよ。ゲストブックと逆に、新しい日記ほど 前に 付け加えられるようにせよ。
問 2.3.4 （ 家計簿）
右のようなフォームから入力を受け取って、簡単な家計簿を生成する Servlet を作成せよ。入力した項目に加えて、その日の支出の計とそれまでの支出の累計の両方を計算してテーブルの形に整形し 、ゲストブックとおなじようにファイルにテーブルを追加していくようにせよ。

参考: DOM の利用 Guests.html のような HTML ファイル（一般に XML ファイル）を操作するとき、単なるテキスト形式ではなく、木構造として操作できると便利である。XML を木構造として扱うための取り決めとして DOM（ Document Object Model ）がある。
情報システム演習（ Servlet の作成）- 第 2 章 p.9

DOM については、Java の javax.xml.parsers パッケージ、javax.xml.transform パッケージ 、org.w3c.dom パッケージの API ド キュメントの説明を参考に、各自で調べて欲しい。

2.4

参考: デバッグ用サーブレット

POST を利用する Servlet をデバッグするときには、フォームから送られてくるデータを保存しておくと便利である。それには次のような Servlet を利用すれば良い。
ファイル Debug.java
import java.io.BufferedReader;import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Debug extends HttpServlet {@Override
public void doPost(HttpServletRequest request, HttpServletResponse response)throws IOException {response.setContentType("text/html; charset=Windows-31J");
PrintWriter out = response.getWriter();out.println("<html><head></head><body>");int len = request.getContentLength();char[] buf = new char[len];File f = new File(getServletContext().getRealPath("/Debug.out"));PrintWriter fout = new PrintWriter(new FileWriter(f));
BufferedReader in = request.getReader();
in.read(buf);
in.close();fout.print(buf);
fout.close();out.printf("<tt>CONTENT_LENGTH</tt>は %d です。%n", len);out.println("<a href=’Debug.out’>Debug.out</a>に情報を書きこみました。");
out.println("</body></html>");out.close();}}この Servlet はフォームから送られてくる情報を Debug.out というファイルに書き出す。

キーワード :
GET, Query String, getParameter メソッド , フォーム, POST, doPost メソッド , setCharacterEncoding
メソッド , DOM

情報システム演習（ Servlet の作成）- 第 2 章 p.10