前面一小節提到了需要了解 web.py 這個文件,這個文件最關鍵的地方是定義了 Application 和 RequestHandler 類。我們再看看 Tornado 的 Hello World,我們再精簡一下,下面是最簡單的實例化並啓動 Application的方式:
4 |
application = web.Application([ |
7 |
application.listen( 8888 ) |
8 |
ioloop.IOLoop.instance().start() |
從代碼裏可以看到的是:應用裏定義了 URI 路由和對應的處理類,並以此構建了application對象,然後讓這個對象監聽在8888端口,最後由 ioloop 單例進入循環,不斷分發事件。
這裏的URI路由就是r"/",對應處理類就是 MainHandler,它們被放在同一個 tuple 裏形成了關聯。可以看到,application 是接受一個列表的,因此可以定義多個全局路由對應不同處理,往列表裏 append 就是了。
如果只是在 tornado 的框架基礎上進行開發,那就只需要不斷定義不同的處理類,並把對應路由與其關聯即可。
tornado.web 裏的 RequestHandler 和 Application 類
Tornado 使用 web 模塊的 Application 做URI轉發,然後通過RequestHandler處理請求。
Application 提供了一個 listen 方法作爲 HTTPServer 中的 listen 的封裝。
初始化 Application 時,一般將處理器直接傳入,它會調用 add_handlers 添加這些處理器,初始化還包括 transforms (分塊、壓縮等)、UI模塊、靜態文件處理器的初始化。 add_handlers 方法負責添加URI和處理器的映射。
Application 實現 URI 轉發時使用了一個技巧,它實現了 __call__ 方法,並將 Application 的實例傳遞給 HTTPServer ,當監聽到請求時,它通過調用 Application 實例觸發 __call__ 。 __call__ 方法中完成具體的URI轉發工作,並調用已註冊的處理器的 _execute 方法,處理請求。
01 |
def __call__( self ,
request): |
02 |
transforms = [t(request) for t in self .transforms] |
06 |
handlers = self ._get_host_handlers(request) |
08 |
handler = RedirectHandler( |
09 |
self ,
request, url = "http://" + self .default_host + "/" ) |
12 |
match = spec.regex.match(request.path) |
14 |
handler = spec.handler_class( self ,
request, * * spec.kwargs) |
17 |
if spec.regex.groupindex: |
20 |
for (k,
v) in match.groupdict().iteritems()) |
22 |
args = [unquote(s) for s in match.groups()] |
25 |
handler = ErrorHandler( self ,
request, status_code = 404 ) |
27 |
handler._execute(transforms, * args, * * kwargs) |
RequestHandler 完成具體的請求,開發者需要繼承它,並根據需要,覆蓋 head 、 get 、 post 、 delete 、 patch 、 put 、 options 等方法,定義處理對應請求的業務邏輯。
RequestHandler 提供了很多鉤子,包括 initialize 、 prepare 、 on_finish 、 on_connection_close 、 set_default_headers 等等。
下面是 _execute 的處理流程:
RequestHandler 中涉及到很多 HTTP 相關的技術,包括 Header、Status、Cookie、Etag、Content-Type、鏈接參數、重定向、長連接等等,還有和用戶身份相關的XSRF和CSRF等等。這方面的知識可以參考《HTTP權威指南》。
Tornado默認實現了幾個常用的處理器:
-
ErrorHandler :生成指定狀態碼的錯誤響應。
-
RedirectHandler :重定向請求。
-
StaticFileHandler :處理靜態文件請求。
-
FallbackHandler :使可以在Tornado中混合使用其他HTTP服務器。
上面提到了 transform ,Tornado 使用這種機制來對輸出做分塊和壓縮的轉換,默認給出了 GZipContentEncoding 和 ChunkedTransferEncoding 。也可以實現自定義的轉換,只要實現 transform_first_chunk 和 transform_chunk 接口即可,它們由 RequestHandler 中的 flush 調用。