Index: [Article Count Order] [Thread]

Date: Sat, 21 Sep 2002 21:55:47 +0900
From: GOTO Kentaro <gotoken@notwork.org>
Subject: [webrickja:62] Re: サーブレットの引数
To: webrickja@notwork.org
Message-Id: <200209211255.g8LCtlND033848@miso.k.notwork.org>
In-Reply-To: <20020921105707.74371.qmail@web301.mail.yahoo.co.jp>
References: <200209210616.g8L6G4ND033274@miso.k.notwork.org>	<20020921105707.74371.qmail@web301.mail.yahoo.co.jp>
X-Mail-Count: 00062

At Sat, 21 Sep 2002 19:57:07 +0900 (JST),
Takeshi Honda wrote:
> 設定ファイルをサーブレットとは別に外だしして、
> URLによって違う設定ファイルを読み込ませて、
> その設定ファイルに従った動作をする、
> というのを考えています。

なるほど。その場合、一般的な方針としては、サーブレットの種類
(クラス)は同じだけど個体(インスタンス)は別物ということになる
んじゃないでしょうか。

ドキュメントめいたものを示すと以下のようになっています。

=begin

--- HTTPserver#mount(path, servletclass, *options)

    path に serveletclass と options を関連づけます。
    この関連づけは HTTPServer#service で使われます。

--- HTTPServer#service(req, res)

    このメソッドはそのサーバに要求があったときに run から呼ばれます。
    service は path に対する要求を受けると mount で指定された
    対応する servletclass を検索し、

      si = servletclass.get_instance(self, *options)

    によって得られたサーブレットインスタンス si に対して

      si.service(req, res)

    を呼びます。

=end

つまり WEBrick の意図としては、

   * mount はパスに対してサーブレットクラスをマウントするもの

   * サーブレットクラスのクラスメソッド get_instance を適宜
     定義することで望みのサーブレットインスタンスにサービス
     させることができる

という仕組みになってます。

例えば、全然面白くない例ですが、パスごとに異なる初期値を持つ
アクセスカウンタを設置するには以下のようになります。

   require "webrick"
   class Counter < WEBrick::HTTPServlet::AbstractServlet
     INSTANCE = {}
     
     def self.get_instance(server, path, count = 0)
       Thread.exclusive do INSTANCE[path] ||= new(count) end
     end

     def initialize(count)
       @count = count
     end

     def do_GET(req, res)
       Thread.exclusive do @count += 1 end
       res.body = "This is #{@count}th access\n"
       res['content-type'] = "text/plain"
     end
   end

   s = WEBrick::HTTPServer.new(:Port => 8808)
   s.mount(path = "/foo", Counter, path)
   s.mount(path = "/bar", Counter, path)
   s.mount(path = "/baz", Counter, path, 10000)
   s.start

-- Gotoken