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)
时间: 2024-10-01 03:13:29

6 Application 源码分析的相关文章

ABP源码分析四十:ZERO的Application和Tenant

ABP的Zero模块以数据库为数据源实现了ABP框架中的tenant management (multi-tenancy), role management, user management, session, authorization (permission management), setting management, language management, audit logging等核心功能.ABP中的这些功能具体实现都依赖外部的持久层,所以ABP框架中仅仅定义了接口和一些空的实现

tornado源码分析-Application

tornado.web包含web框架的大部分主要功能,Application是其中一个重要的类 Application类的作用是实现 URI 转发,将 Application 的实例传递给 httpserver ,当监听到请求时,把服务器传回来的请求进行转发,通过调用 __call__ ,处理请求. Application源码: class Application(httputil.HTTPServerConnectionDelegate): """A collection

Spark的Master和Worker集群启动的源码分析

基于spark1.3.1的源码进行分析 spark master启动源码分析 1.在start-master.sh调用master的main方法,main方法调用 def main(argStrings: Array[String]) { SignalLogger.register(log) val conf = new SparkConf val args = new MasterArguments(argStrings, conf) val (actorSystem, _, _, _) =

redis源码分析3---结构体---字典

redis源码分析3---结构体---字典 字典,简单来说就是一种用于保存键值对的抽象数据结构: 注意,字典中每个键都是独一无二的:在redis中,内部的redis的数据库就是使用字典作为底层实现的: 1 字典的实现 在redis中,字典是使用哈希表作为底层实现的,一个hash表里面可以有多个hash表节点,而每个hash表节点就保存了字典中的一个键值对: hash表定义 table属性是一个数组,数组中的每个元素都是一个指向dictEntry结构的指针,每个dictEntry结构保存着一个键值

SpringMVC源码分析(3)DispatcherServlet的请求处理流程

<SpringMVC源码分析(1)标签解析>:介绍了解析过程中,初始化若干组件. <SpringMVC源码分析(2)DispatcherServlet的初始化>:初始化DispatcherServlet的多个组件. 本文继续分析DispatcherServlet解析请求的过程. 概览 ①:DispatcherServlet是springmvc中的前端控制器(front controller),负责接收request并将request转发给对应的处理组件. ②:HanlerMappi

spark core源码分析6 Spark job的提交

本节主要讲解SparkContext的逻辑 首先看一个spark自带的最简单的例子: object SparkPi { def main(args: Array[String]) { val conf = new SparkConf().setAppName("Spark Pi") val spark = new SparkContext(conf) val slices = if (args.length > 0) args(0).toInt else 2 val n = ma

Android应用setContentView与LayoutInflater加载解析机制源码分析

[工匠若水 http://blog.csdn.net/yanbober 转载烦请注明出处,尊重分享成果] 1 背景 其实之所以要说这个话题有几个原因: 理解xml等控件是咋被显示的原理,通常大家写代码都是直接在onCreate里setContentView就完事,没怎么关注其实现原理. 前面分析<Android触摸屏事件派发机制详解与源码分析三(Activity篇)>时提到了一些关于布局嵌套的问题,当时没有深入解释. 所以接下来主要分析的就是View或者ViewGroup对象是如何添加至应用程

keystone源码分析(一)——Paste Deploy的应用

本keystone源码分析系列基于Juno版Keystone,于2014年10月16日随Juno版OpenStack发布. Keystone作为OpenStack中的身份管理与授权模块,主要实现系统用户的身份认证.基于角色的授权管理.其他OpenStack服务的地址发现和安全策略管理等功能.Keystone作为开源云系统OpenStack中至关重要的组成部分,与OpenStack中几乎所有的其他服务(如Nova, Glance, Neutron等)都有着密切的联系.同时,Keystone作为开源

Spark资源调度机制源码分析--基于spreadOutApps及非spreadOutApps两种资源调度算法

Spark资源调度机制源码分析--基于spreadOutApps及非spreadOutApps两种资源调度算法 1.spreadOutApp尽量平均分配到每个executor上: 2.非spreadOutApp尽量在使用单个executor的资源. 源码分析 org.apache.spark.deploy.master.Master 1.首先判断,master状态不是ALIVE的话,直接返回2.调度driver3. Application的调度机制(核心之核心,重中之重) 源码如下: 1 /*