tornado 学习笔记6 Application 源码分析
Application 是Tornado重要的模块之一,主要是配置访问路由表及其他应用参数的设置。
源代码位于虚拟运行环境文件夹下(我的是env),具体位置为env > lib>sit-packages>tornado>web.py。
注释大体意思:
Application是由请求handlers集合组成,配置好application之后,直接作为参数传递给HTTPServer。
这个类的构造函数包含URLSpec对象集合或者(正则表达式,request handler)元组集合。当服务器接收到请求时,我们会按顺序迭代循环集合,找到第一个与请求路径相匹配的正则表达式对应的配置项,然后实例化配置项中对应的hanlder对象。
当然,tornado也支持虚拟主机,就是使用add_handles方法,使用主机正则表达式作为第一个参数。
6.1 构造函数
定义:
def __init__(self, handlers=None, default_host="", transforms=None,
**settings):
参数:
- hanlders:为配置的URLSpec集合或者(正则表达式,hanlder)元组集合
- default_host:默认的服务器名称。(暂时不知道干什么用的)
- transforms:转换。是一个集合,内容转换处理器集合。用来对响应的内容进行转换处理,比如压缩处理。
- settings:配置字典。
主要处理过程:
(1) 对静态文件的处理。
#如果在设置中配置了static_path参数 if self.settings.get("static_path"): #得到static_path参数值 path = self.settings["static_path"] handlers = list(handlers or []) #得到static_url_prefix参数值,默认值为/static/ static_url_prefix = settings.get("static_url_prefix", "/static/") #得到static_handler_class参数值,也就是静态文件处理类,默认值为StaticFileHandler static_handler_class = settings.get("static_handler_class", StaticFileHandler) #得到static_handler_args参数值,其他参数 static_handler_args = settings.get("static_handler_args", {}) static_handler_args['path'] = path #1将以static_url_prefix为前缀的路径访问以及根目录下的favicon.ico和robots.txt组成正则表达式, #2并将这些正则表达式关联到static_handler_class作为元组 #3将这些元组一个一个插入到hanlders集合的最前面 for pattern in [re.escape(static_url_prefix) + r"(.*)", r"/(favicon\.ico)", r"/(robots\.txt)"]: handlers.insert(0, (pattern, static_handler_class, static_handler_args))
因为tornado请求的都是由hanlder来处理,由hanlder决定怎么返回响应。静态文件比如css文件、图片文件、以及其他word、excel、txt等文件,当游览器访问这些静态文件时,需进行区别业务hanlder的处理方式。
举个例子:
源码结构为:
源代码为:
STATIC_ROOT = os.path.join(os.path.dirname(__file__), 'static').replace('\\', '/') settings = { "static_path": STATIC_ROOT, "static_url_prefix": "/static/", 'debug': True, } app = Application(handlers=[ url(r"/", MainHanlder), url(r"/story/([0-9]+)", StoryHanlder, dict(db=db), name="story"), ], **settings)
最后在游览器中访问style.css静态样式表文件。结果如下。
当然,可以根据你项目自身的结构配置static_path、static_url_prefix两个参数。
(2) 对handlers的处理
if handlers:
self.add_handlers(".*$", handlers)
这里调用了add_handlers的方法。
(3) 对设置参数情况的处理
if self.settings.get('debug'): self.settings.setdefault('autoreload', True) self.settings.setdefault('compiled_template_cache', False) self.settings.setdefault('static_hash_cache', False) self.settings.setdefault('serve_traceback', True) # Automatically reload modified modules if self.settings.get('autoreload'): from tornado import autoreload autoreload.start()
6.2 设置参数说明
Application可以设置的参数包括3种类型,分别是一般参数、授权和安全设置参数、模板参数、静态文件配置参数。
一般参数:
- l autoreload: 如果是True,当任何源文件改变时,服务器进程将会重新启动。这个选项只有在3.2版本有,以前这个功能被debug选项控制。
- l debug: 设置成调试模式。debug = True 等同于 autoreload=True,compiled_template=False,static_hash_cache=False,serve_traceback=True.
- l default_handler_class 以及default_handler_args: 如果没有找到相匹配的handler,会使用这个默认的handler.s使用这个可以自定义404页面。
- l compresss_response: 如果设置成True.文本格式返回的响应会被压缩。在tornado 4.0版本才有这功能。
- l gzip : 从4.0版本后过时,被compresss_response替代
- l log_function :在每个请求响应之后,这个函数会被调用,用来记录结果。默认实现是写入到logging模块的跟日志记录器中。这个可以被自定义。
- l serve_traceback: 如果设置成true. 默认的错误页面会包含错误跟踪。这个选项在3.2版本新增的。之前的版本通过设置debug=true来实现功能。
- l ui_modules 和ui_methods:设置对ui 模板的 UIModule 或者UIMethods的映射。
授权和安全设置参数:
- l cookie_secret: 被RequestHandler.get_secure_cookie 和set_secure_cookie使用,用来签发cookies;
- l login_url:如果用户没有登录,使用了authenticated装饰器的请求处理都会重定向到这个url.可以重写RequestHanlder.get_login_url进行进一步的自定义。
- l xsrf_cookies: 如果设置成True,跨站(Cross-site)保护会被启动。
模板参数:
- l autoscape: 为模板控制自动转义。可以设置成None来禁用转义,或者设置成一个函数名称,这样所有的输出都会被传递。默认值为 xhtml_escape.可以通过 {% autoescape %}指令在每一个模板上进行改变;
- l compiled_template_cache: 默认设置为True。如果设置成False,针对每个请求,每个模板都会重新编译。这个选项在3.2版本中新增,以前版本都是通过设置debug选项来实现。
- l template_path :包含template文件的文件夹目录。可以重写 RequestHandler.get_template_path来进一步自定义。
- l template_loader: 给tornado.template.BaseLoader设置一个实例,用来自定义模板的加载。如果这个选项设置了,那么template_path 以及 autoescape 这两个选项会被忽视。这个通过重写RequestHandler.create_template_loader来进一步实现自定义。
静态文件设置:
- l static_hash_cache: 默认值为True.如果为False,针对每一个请求,静态url将会被重新计算。这个选项是在3.2版本新增的。以前这个功能只能通过debug设置来控制。
- l static_path: 静态文件所在目录。
- l static_url_prefix:静态文件访问得url前缀。默认为:“/static”
- l static_handler_class,static_handler_args: 可以使用自定义的静态文件处理器去替代默认的tornado.web.StaticFileHandler。static_handler_args,如果设置了,必须为一个字典,而且会被传递到handler的initialize方法作为参数。
6.3 add_handlers方法
在构造函数中处理中,有一个很重要的过程,就是对配置的handlers进行处理。就是add_hanlders方法。
这个方法的是将给定的hanlders追加到我们的hanlder列表中。
- 方法定义:def add_handlers(self, host_pattern, host_handlers):
- 参数:
host_pattern: 虚拟主机匹配的正则表达式。Application默认设置为””
host_handlers :要添加的handlers。
- 源码分析:
if not host_pattern.endswith("$"): host_pattern += "$" handlers = [] # The handlers with the wildcard host_pattern are a special # case - they're added in the constructor but should have lower # precedence than the more-precise handlers added later. # If a wildcard handler group exists, it should always be last # in the list, so insert new groups just before it. if self.handlers and self.handlers[-1][0].pattern == '.*$': self.handlers.insert(-1, (re.compile(host_pattern), handlers)) else: self.handlers.append((re.compile(host_pattern), handlers)) for spec in host_handlers: if isinstance(spec, (tuple, list)): assert len(spec) in (2, 3, 4) spec = URLSpec(*spec) handlers.append(spec) if spec.name: if spec.name in self.named_handlers: app_log.warning( "Multiple handlers named %s; replacing previous value", spec.name) self.named_handlers[spec.name] = spec
方法主要逻辑是将handlers添加至Application的handlers属性中,但是添加的hanlder首先必须转换成URLSpec类型。如果hanlder配置了命名参数,检验名称的唯一性,并如果存在重复,将进行覆盖,并记录在日志中。
通过 if isinstance(spec, (tuple, list)) 源码可以看出,hanlders的配置类型可以有两种类型,一种是元组集合,一种是列表,而如果是列表的话,那么列表中的项是URLSpec类型。而且每一handler是可以命名的。举个例子:Application的创建可以以下两个方式:
方式一:hanlders用URLSpec对象列表传递,并且可以命名。
app = Application(handlers=[ url(r"/", MainHanlder), url(r"/story/([0-9]+)", StoryHanlder, dict(db=db), name="story"), ], **settings)
方式二:hanlders用元组集合传递
app = Application(handlers=[ url(r"/", MainHanlder), url(r"/story/([0-9]+)", StoryHanlder, dict(db=db), name="story"), ], **settings)