路由系统是每一个python web框架都要提供的功能,tornado也不例外,虽然各自实现上有说不同,但本质上都是在建立请求path和处理该类请求代码(函数,类)之间的映射关系。
import tornado.ioloop
from tornado.web import RequestHandler, Application
from tornado.httpserver import HTTPServer
from tornado.options import options, define
define('port', default=8000, help='监听端口')
class HelloHandler(RequestHandler):
def get(self):
self.write('hello world')
class IndexHandler(RequestHandler):
def get(self):
self.write('welcome to IndexHandler')
if __name__ == '__main__':
options.parse_command_line()
handlers_routes = [
(r'/', HelloHandler),
(r'/index', IndexHandler)
]
app = Application(handlers=handlers_routes)
http_server = HTTPServer(app)
http_server.listen(options.port)
tornado.ioloop.IOLoop.current().start()
在创建Application对象时,需要设置handlers参数,如上代码所示,handlers_routes 是一个列表,列表里的元素是元组,元素第一个元素是正则表达式,描述的是请求的path,第二个元素是RequestHandler类,处理path符合前面正则表达式的请求。
tornado 也支持动态路由,需要你了解一点正则表达式分组的知识
class UserHandler(RequestHandler):
def get(self, name):
self.write(f'welcome {name}')
if __name__ == '__main__':
options.parse_command_line()
handlers_routes = [
(r'/', HelloHandler),
(r'/index', IndexHandler),
(r'/user/(.*)', UserHandler)
]
我只贴出来部分修改新增的代码,r'/user/(.*)' 是一个正则表达式,(.*) 是一个分组,其匹配到的内容将传递给UserHandler类的get方法中的name参数。正则表达式里有几个分组,在对应的处理请求的方法里就要有几个参数。
下面的正则表达式也成立,而且代码更利于阅读,你可以根据正则表达式里的捕获分组准确的理解path里每一个分组的含义。
(r'/user/(?P<name>.*)', UserHandler)
关于正则表达式分组,如果你并不十分熟练,推荐你阅读python正则表达式精讲--分组
偶尔,你也会看到这样的写法
from tornado.routing import URLSpec
handlers_routes = [
(r'/', HelloHandler),
URLSpec(r'/index', IndexHandler),
(r'/user/(?P<name>.*)', UserHandler)
]
可以使用URLSpec类来确定路径和处理请求类之间的映射关系,这与使用元组在效果上是相同的。使用元组,tornado会根据元组里的数据生成Rule对象,而URLSpec是Rule的子类。
Application 类的add_handlers方法允许你自由添加路由规则,不仅如此,还可以向指定的host进行添加。
app = Application(handlers=handlers_routes)
app.add_handlers(r'.*', [(r'/user/(?P<name>.*)', UserHandler)])
add_handlers的第一个参数是host_pattern,根据host_pattern生成Matcher对象,只有请求头里的host匹配了host_pattern才会生效,r'.*' 表示任意字符重复0次或多次,任意host都可以使用这些路由规则。app = Application(handlers=handlers_routes) 这种写法在源码里生成的是AnyMatches对象,同r'.*'一样,匹配任意host。
如果你的web服务有多个域名,而且希望不同的域名有不同的路由规则,那么你可以使用add_handlers方法来实现,在/etc/hosts里配置如下域名解析
127.0.0.1 mycool.com
127.0.0.1 mypythonweb.com
修改web应用
app = Application(handlers=handlers_routes)
app.add_handlers(r'mycool.com', [(r'/user/(?P<name>.*)', UserHandler)])
访问http://mycool.com:8000/user/dongsheng 可以得到正确响应,而访问http://mypythonweb.com:8000/user/dongsheng ,得到的就是一个404 not found, host_pattern 可以匹配mycool.com,但不能匹配mypythonweb.com,因此(r'/user/(?P
QQ交流群: 211426309