top / index / prev / next / target / source

2004-03-17 diary: Java Servletのシンプル雛形ソースコードの探求

いがぴょんの日記 日記形式でつづる いがぴょんコラム ウェブページです。

old-v2

Java Servletのシンプル雛形ソースコードの探求

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");
    }
}

私にとっての疑問点

参考リンク

参考日記

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本さんと 喫茶店で書籍打ち合わせ。ニューブリッジの意味を考えてみる。ああ なるほど 「新橋」のことか… (苦笑)

Eclipse Tomcatプラグイン

さあて、調査開始 (少し前も同じことを言っていたような気が…)

手順

しかしこれで、Eclipseからうまく起動・終了などはできるのですが、はて、なぜかブレークポイントを利用したデバッグを行うことが出来ません。はて。

HTTPプロトコルのメモ

いつも調べては見つけるHTTPプロトコルのRFC日本語訳

(業務連絡) これを見ると、Cache-Control と Pragma: no-cacheとの位置づけがわかりますね > たむぽん

Webブラウザの通信内容を横取りするソフト

協力会社のたむぽんさんから ソフトを教えてもらう。

ネットワークをキャプチャリングして閲覧するという一連の流れを、とてもスムーズに実施可能です。すばらしい。Web系開発の現場にはとても便利だと思いました。基本的にはネットワークキャプチャソフトが好きなのですが、こういう簡便なソフトも場面によってはより使い勝手がよいようですね。…ただしその開発者の方には artonさんの FreePeekを教えておきました。また FreePeekユーザを増やすことに成功したようです。

更新頻度の低いサイトが閲覧漏れになりがち

ふうむ。私もそう思います。では、これを改善すべく、アンテナ依存症加速装置を工夫して、たとえば、前回の閲覧時間を記憶して、そういうサイトが更新されれば優先的に上位に表示するような、そんな手が加わればとっても便利ですう。(と勝手に希望仕様を書いていたら、作者さんがすぐさま反応されてられました)

オーケストラへのいざない

日記に引っ越しなどと書いていたら、昔所属していたオーケストラから 勧誘のメールが届きました。

アルファシステムズ、教育機関向けのLinuxカスタマイズサービスを提供

ほほう。KNOPPIXベースですか。やるなあ。


この日記について