Auth: 王海飞
Data:2019-02-17
Email:779598160@qq.com
github:https://github.com/coco369/knowledge
Tornado的官网中对路由的定义有一句描述: “A collection of request handlers that make up a web application.”即一个Web应用是由请求处理器集合和路由表组成。
在tornado.web.Application类中接收一个handlers参数,该参数由元祖组成,每个元组中包含匹配模式pattern和处理器handler。
当HTTPServer接收到一个HTTP请求时,服务端会从请求中解析出URL路由,然后去匹配路由表,如果能匹配到某个pattern,则将此HTTP请求交给pattern对应的处理器handler处理。
Tornado框架是基于正则的动态路由映射,动态路由的定义方式和Django类似。动态路由可以定义为带参数形式或不带参数形式,其中还可以使用‘(?P<参数名>)’这种形式来设置请求处理器接收参数的指定名称。
1) 指定带参数的动态路由
新增带参数的动态路由,并使用正则匹配规则‘(?P<参数名>)’来设置接收参数的名称。
class IndexHandler(tornado.web.RequestHandler):
def get(self, month, year):
self.write('日期:%s年%s月' % (year, month))
def make_app():
return tornado.web.Application(handlers=[
(r"/index/(?P<year>\d{4})/(?P<month>\d{2})/", IndexHandler),
])
示例中定义了接收参数的动态路由” /index/(?P
2)不指定参数名的动态路由
定义接收参数的动态路由。
class NewIndexHandler(tornado.web.RequestHandler):
def get(self, a, b, c):
self.write('%s %s %s' % (a, b, c))
def make_app():
return tornado.web.Application(handlers=[
(r"/index2/(\d+)/(\d+)/(\d+)/", NewIndexHandler),
])
示例中定义了接收三个参数的动态路由,如在浏览器中访问“/index2/2018/11/7/“地址,URL中的参数2018、11和7以参数的形式传递给NewIndexHandler类的get()方法,get(self, a, b, c)方法中接收三个参数,其中a的值为2018、b的值为11、c的值为7。
注意:
传递带参数的URL需要注意以下两点:
使用(?P<参数名>)来设置传递的参数名称,在继承RequestHandler类中的get()方法中接收参数的参数名顺序可以任意排序。
不指定动态路由中传递的参数名称,则在继承RequestHandler类中get()方法中设置接受参数的参数名,get()方法中第一个参数将取动态路由URL中第一个参数的值,get()方法中第二个参数将取动态路由URL中第二个参数的值....依次类推。
3)不带参数的路由
如下定义匹配根路径“/”的路由,并调用请求处理MainHandler类中与HTTP请求方式对应的get()方法来响应这个请求。
定义不带参数的动态路由。
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
def make_app():
return tornado.web.Application(handlers=[
(r"/", MainHandler),
])
在示例中的RequestHandler类都自定义了一个HTTP方法的行为,但是处理同一个URL的时候,有可能除了GET请求方式,也有可能会提交POST请求方式以及PATCH等请求方式。因此在自定义的RequestHandler类中还可以自定义HTTP请求的行为方法,如下展示常用的行为方法:
1)RequestHandler.get(*args, **kwargs)
2)RequestHandler.post(*args, **kwargs)
3)RequestHandler.delete(*args, **kwargs)
4)RequestHandler.patch(*args, **kwargs)
5)RequestHandler.put(*args, **kwargs)
6)RequestHandler.head(*args, **kwargs)
7)RequestHandler.options(*args, **kwargs)
【示例11-8】定义继承RequestHandler的子类的HTTP请求的行为方法。 class MainHandler(tornado.web.RequestHandler): def get(self, *args, **kwargs): self.write("处理get请求")
def post(self, *args, **kwargs):
self.write("处理post请求")
def patch(self, *args, **kwargs):
self.write("处理patch请求")
def put(self, *args, **kwargs):
self.write("处理put请求")
def head(self, *args, **kwargs):
self.write("处理head请求")
def options(self, *args, **kwargs):
self.write("处理options请求")
def delete(self, *args, **kwargs):
self.write("处理delete请求")
继承tornado.web.RequestHandler的子类中至少定义一个HTTP请求的行为方法,如get()函数、post()函数等。这些与HTTP请求所对应的行为方法也被叫做“Entry points”即切入点函数。
切入点函数除了get()函数、post()函数,还有如下方法:
1)RequestHandler.initialize()
用于子类的初始化。
2)RequestHandler.prepare()
在调用get()或post()方法之前被调用。
3)RequestHandler.on_finish()
在请求结束后调用,用于执行清理,日志记录等功能。
创建tornado_entry_points.py文件
import tornado.ioloop
import tornado.web
import tornado.httpserver
from tornado.options import define, options, parse_command_line
# 定义默认的端口
define('port', default=8000, type=int)
class MainHandler(tornado.web.RequestHandler):
def initialize(self):
self.name = ‘Python’
print('实例对象的初始化,并给name参数赋值')
def prepare(self):
print('在执行HTTP行为方法之前被调用')
def get(self):
print('执行GET方法')
self.write("name: %s" % self.name)
def on_finish(self):
print('响应后调用此方法,用于清理内存或日志记录等功能')
def make_app():
return tornado.web.Application(handlers=[
(r"/", MainHandler),
])
if __name__ == "__main__":
parse_command_line()
app = make_app()
app.listen(options.port)
tornado.ioloop.IOLoop.current().start()
执行流程分析:
步骤1: tornado.web.Application 会根据 URL 寻找一个匹配的 RequestHandler 类,并初始化它。它的 init() 方法会调用子类中定义的initialize() 方法。
步骤2: 接着根据不同的 HTTP 请求方式寻找该 handler 的 get/post() 等方法,并在执行前运行 prepare()。
步骤3: 最后会调用 handler 的 finish() 方法,这个方法最好别覆盖。它会调用 on_finish() 方法,它可以被覆盖,用于处理一些善后的事情(例如关闭数据库连接)
启动项目:
python tornado_entry_points.py --port=8888