top / index / prev / next / target / source
日記形式でつづる いがぴょんコラム ウェブページです。
Java Servlet (ジャバ・サーブレット)のシンプルサンプル ソースコードを作成しています。最もシンプルなものを作っているはずなのに、意外にもステップ数があります。
すごく単純な Java Servletのソースコードとは どのようになるのかについてサンプルソースをメモしておきます。さしずめシンプルサーブレット計画とでも呼びましょうか。 SampleServlet.java
/*
* すごく単純な Java Servletサンプルソースコード構築計画
* Copyright (C) 2004-2005 いがぴょん
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* すごく単純な Java Servletサンプルソースコード
*
* @author iga
* @version 2004.11.13
*/
public class SampleServlet extends HttpServlet {
/**
* <code>ENCODING</code> HTMLで扱う文字コードを与えます。
*/
public static final String ENCODING = "ISO-2022-JP";
/**
* Java Servletのエントリポイントです。
*
* @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest,
* javax.servlet.http.HttpServletResponse)
*/
public final void service(final HttpServletRequest request,
final HttpServletResponse response) throws ServletException,
IOException {
BufferedReader reader = null;
PrintWriter writer = null;
setResponseDefault(response);
try {
reader = request.getReader();
writer = response.getWriter();
for (;;) {
String line = reader.readLine();
if (line == null) {
break;
}
System.out.println("REQ:" + line);
}
writer
.write("<HEAD>\n"
+ "<META http-equiv=\"Content-Type\" content=\"text/html; charset="
+ "\""
+ ENCODING
+ "\">\n"
+ "<META http-equiv=\"Content-Style-Type\" content=\"text/css\">\n"
+ "<META http-equiv=\"Cache-Control\" content=\"no-cache\">\n"
+ "<META http-equiv=\"Pragma\" content=\"no-cache\">\n"
+ "<META http-equiv=\"Expires\" content=\"0\">\n"
+ "<TITLE>シンプルなサーブレットサンプルです</TITLE>\n</HEAD>\n");
writer.write("<BODY>\n");
writer.write("<P>シンプルサーブレット</P>\n");
for (Enumeration enum = request.getHeaderNames(); enum
.hasMoreElements();) {
String key = (String) enum.nextElement();
writer.write("<LI>H:" + key + "=" + request.getHeader(key)
+ "</LI>\n");
}
for (Enumeration enum = request.getAttributeNames(); enum
.hasMoreElements();) {
String key = (String) enum.nextElement();
writer.write("<LI>A:" + key + "=" + request.getAttribute(key)
+ "</LI>\n");
}
for (Enumeration enum = request.getParameterNames(); enum
.hasMoreElements();) {
String key = (String) enum.nextElement();
String value = new String(((String) request.getParameter(key))
.getBytes("ISO8859-1"), ENCODING);
writer.write("<LI>P:" + key + "=" + value + "</LI>\n");
}
writer.write("<FORM action=\"SampleServlet.do\">\n");
writer
.write("<INPUT type=\"text\" name=\"INPUTVALUE\" size=\"20\">\n");
writer
.write("<INPUT type=\"submit\" value=\"実験\" name=\"execute\">\n");
writer.write("</FORM>\n");
writer.write("</BODY>\n");
} finally {
// ReaderもWriterもクローズしません。flushも呼び出してはなりません。(2005.03.13に判明)
}
}
/**
* デフォルトとなるレスポンスヘッダーの付与
*
* @param response
* レスポンスオブジェクトを与えます。
*/
private void setResponseDefault(final HttpServletResponse response) {
response.setContentType("text/html; charset=" + ENCODING);
response.addHeader("Content-Type", "text/html");
response.addHeader("charset", ENCODING);
response.addHeader("Cache-Control", "no-cache");
response.addHeader("Pragma", "no-cache");
response.addHeader("Expires", "0");
}
}
私にとっての疑問点
Java Servletの Request や Responseから得られる Reader や Writerは クローズしなくて良いのか? それはなぜか? 昔から ず~っと不思議なのです。、、、そうか、BluePrintを見れば良いですね。 2005.03.13 → この問題は解決しました。結論から言うと、クローズしなくても良いのです。むしろクローズすると有害です。詳細は後述。
なんで 文字化け対応を行わなくてはならないのか? う~む。これまた難易度が高そうです。
参考リンク
参考日記
2004.11.13 エンコーディングを ISO-2022-JP に変更しました。METAタグにエンコーディングを追加しました。一部キャッシュまわりで都市伝説みたいなコードが残っていますけれどもね。 Expiresに0を設定するようにしました。-1というのは都市伝説だった模様。RFCで 0 が正解であることを確認しました。それにしても、最低レベルが、なぜこんなに沢山のコードが必要なのでしょう。不思議な気持ちでいっぱいです。
2005.03.13 Request や Responseから得られる Reader や Writerは クローズしないのが作法ということがわかりました。むしろクローズしてはいけません。まだflushも呼び出してはなりません。「Java Computing 2005 Spring」 の JaJakarta BOFにおいて、下記の方々に教えていただきました。
なんでも昔はクローズしないといけなかったのだそうですが、HTTP 1.1 の時代になったら一転 今度はクローズしてはいけなくなったのだそうです。これは HTTP 1.1においては Keep Aliveがデフォルトですが、closeを明示的に呼び出すと ソケットをクローズしてしまう問題が発生する (場合がある) とのことです。無理にクローズしてしまうと、クライアント側が異常を検知してしまうことがあるとのこと。、、、この問題は 難易度が高かったです。でもあるべき姿を知ることが出来てとても嬉しいです。
関連する日記
著者プロフィールとか帯とかの小物は書きました。
Y本さんと 喫茶店で書籍打ち合わせ。ニューブリッジの意味を考えてみる。ああ なるほど 「新橋」のことか… (苦笑)
さあて、調査開始 (少し前も同じことを言っていたような気が…)
http://eclipsewiki.net/eclipse/index.php?Tomcat%A5%D7%A5%E9%A5%B0%A5%A4%A5%F3
Sysdeo Eclipse Tomcat Launcher plugin
http://www.sysdeo.com/eclipse/tomcatPlugin.html 2.2.1を試す。tomcatPluginV221.zip。なんと日本語化がなされています! びっくり!
手順
Eclispeが(もし動いていたら)停止
%eclipse_home%/plugins に 解凍したファイルをコピー (よくあるプラグインの導入方法ですね)
Eclipseを起動
「プラグインの有効化」
ウィンドウ(W) → パースペクティブのカスタマイズ(Z)
その他 → Tomcat にチェックを入れる
OKを押す
「Tomcat ホームディレクトリの設定」
ウィンドウ(W) → 設定(P)
Tomcatツリーノードを選択
バージョンを選択
ウィンドウ(W)→設定(P)
[Java]ツリーノード内の [インストール済み JRE] ツリーノードを選択
[追加]ボタン
[JREの作成]ウィンドウ
ウィンドウ(W)→設定(P)
[Tomcat]ツリーノード内の [JVMの設定] ツリーノードを選択
しかしこれで、Eclipseからうまく起動・終了などはできるのですが、はて、なぜかブレークポイントを利用したデバッグを行うことが出来ません。はて。
いつも調べては見つけるHTTPプロトコルのRFC日本語訳
RFC-Translations related HTTP http://www.studyinghttp.net/rfc_ja/
Hypertext Transfer Protocol -- HTTP/1.1 [RFC2616] [http://www.studyinghttp.net/rfc_ja/2616/rfc2616_ja.html](http://www.studyinghttp.net/rfc_ja/2616/rfc2616_ja.html)
キャッシュコントロール http://www.studyinghttp.net/rfc_ja/2616/sec14.html#sec14.9
(業務連絡) これを見ると、Cache-Control と Pragma: no-cacheとの位置づけがわかりますね > たむぽん
協力会社のたむぽんさんから ソフトを教えてもらう。
横取り丸 http://hide.maruo.co.jp/software/ydm.html HTTP電文メッセージを横取りするソフト。秀丸ソフトの姉妹品。
InetSpy http://hide.maruo.co.jp/software/inetspy.html 横取り丸を利用する際に一緒にインストールする。
ネットワークをキャプチャリングして閲覧するという一連の流れを、とてもスムーズに実施可能です。すばらしい。Web系開発の現場にはとても便利だと思いました。基本的にはネットワークキャプチャソフトが好きなのですが、こういう簡便なソフトも場面によってはより使い勝手がよいようですね。…ただしその開発者の方には artonさんの FreePeekを教えておきました。また FreePeekユーザを増やすことに成功したようです。
ふうむ。私もそう思います。では、これを改善すべく、アンテナ依存症加速装置を工夫して、たとえば、前回の閲覧時間を記憶して、そういうサイトが更新されれば優先的に上位に表示するような、そんな手が加わればとっても便利ですう。(と勝手に希望仕様を書いていたら、作者さんがすぐさま反応されてられました)
日記に引っ越しなどと書いていたら、昔所属していたオーケストラから 勧誘のメールが届きました。
ほほう。KNOPPIXベースですか。やるなあ。