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