前面一小节提到了需要了解 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 调用。