tornado 学习笔记7 RequestHandler功能分析
转载自廖飞的博客
在第5部分讲到,构建一个tornado网站,必须包含一个或者多个handler,这些handler是RequestHandler的子类。每个请求都会被映射到handler中进行处理,处理后再将结果返回给客户端。所以,可以看到hanlder作为客户端请求跟业务服务逻辑间的桥梁,如果拿MVC的模式来类比的话,每个handler就相当于MVC中的Controller。
RequestHanlder作为所有hanlder的父类,我们看看他有哪些方法与接口,子类需要怎样继承?
7.1构造函数
定义:
def __init__(self, application, request, **kwargs):
参数:
application: Application对象
request: request请求对象
kwargs:其他参数,在hanlder映射配置时,可以设置。
处理过程:
super(RequestHandler, self).__init__()self.application = application self.request = request self._headers_written = False self._finished = False self._auto_finish = True self._transforms = None # will be set in _execute self._prepared_future = None self.path_args = None self.path_kwargs = None self.ui = ObjectDict((n, self._ui_method(m)) for n, m inapplication.ui_methods.items()) # UIModules are available as both `modules` and `_tt_modules` in the # template namespace. Historically only `modules` was available # but could be clobbered by user additions to the namespace. # The template {% module %} directive looks in `_tt_modules` to avoid # possible conflicts. self.ui["_tt_modules"] = _UIModuleNamespace(self,application.ui_modules) self.ui["modules"] = self.ui["_tt_modules"] self.clear() self.request.connection.set_close_callback(self.on_connection_close) self.initialize(**kwargs)
- 对外部属性跟内部属性(带下划线)的赋值。注意:从源码可以看出application为RequestHandler类实例对象的属性
- 然后对ui的处理,这个暂时不做深入细读。
- self.clear() 调用clear方法,初始化一些属性。
- 设置请求连接关闭时的回调函数。
self.request.connection.set_close_callback(self.on_connection_close)
5. 调用初始化函数。
self.initialize(**kwargs)
这个被子类继承,针对每个hanlder实现自己的初始化过程。
入点函数
7.2 initialize方法
该方法被子类重写,实现初始化过程。参数的来源于配置Application时,传递的参数。举例如下:
# -*- coding: utf-8 -*- from tornado.ioloop import IOLoop from tornado.web import Application, RequestHandler__author__ = 'Administrator'class BookRequestHandler(RequestHandler):def initialize(self, welcome):self.welcome = welcomedef get(self, *args, **kwargs):print(self.welcome)self.write(self.welcome)welcome = "**大学图书馆" app = Application(handlers=[(r"/book", BookRequestHandler, dict(welcome=welcome)), ])def main():app.listen(8888)IOLoop.current().start()if __name__ == "__main__":main()
将welcome初始化的值传递到BookRequestHandler的self.welcome属性中。当访问http://localhost:8888/book时,打印出welcome的值。
7.3 prepare 、 on_finish方法
class BookRequestHandler(RequestHandler):def initialize(self, welcome,value2):print("initialize method:initilize some variables....")self.welcome = welcomeself.value2=value2def get(self, *args, **kwargs):#print(self.welcome + "\r\n" + "and value2 =" + self.value2)print("get method: Processing get Method...........")self.write(self.welcome + "\r\n" + "and value2 =" + self.value2)def set_default_headers(self):self._headers.add("custom_header1", "custom_header1")self._headers.add("custom_header2", "custom_header2")def prepare(self):print("prepare method:initilize some variables....")def on_finish(self):print("on_finish method:clear some memory or close database connection")
执行的结果如下:
所以得出执行的顺序为:
initialize > prepare > get > on_finish
如果有熟悉Java 的JUnit的话呢,prepare跟on_finish方法相当于before跟behind两个注解的功能。
获得输入的函数:
7.4 get_argument、get_arguments方法
返回给定参数的值,get_argument获得单个值,而get_arguments是针对参数存在多个值得情况下使用,返回多个值的列表。看一get_arguments方法的源代码,如下:
修改BookRequestHanlder的get方法。如下:
def get(self, *args, **kwargs):#print(self.welcome + "\r\n" + "and value2 =" + self.value2)print("get method: Processing get Method...........")#self.write(self.welcome + "\r\n" + "and value2 =" + self.value2)self.write("参数name的值为:" + self.get_argument("name", "liaofei"))
向游览器中打印出参数name的值,游览器中访问:http://localhost:8888/book?name=brain,结果如下图所示:
在举个POST方式提交参数的例子,在BookRequestHanlder 中新增POST方法,如下:
def post(self, *args, **kwargs):print(self.request.arguments)print("POS age:" + self.get_argument("age"))self.write("POS age:" + self.get_argument("age"))
网上下载一个模拟工具进行POST数据提交,我找了很久用了,找到如下工具(很多工具不能用,这个稍微能用一下),
后台打印的结果为:,HTTPRequest 的arguments属性是一个字典。
提一个问题?如果URL中带有age查询参数,而post过去也有age参数,这时HTTPRequest 的arguments中age的值会是什么???测试一下便知。按照如下访问,
后台打印的结果为:,age的值是一个列表集合,将POST提交方式age参数值跟GET提交方式age参数值合并啦,而且是GET在前,POST再后。而get_arguments获得最后一个。
7.5 get_query_argument
、get_query_arguments方法
与get_argument、get_arguments功能类似,只是他仅仅是从URL查询参数中获取值。
7.6 get_body_argument
、get_body_arguments方法
与get_argument、get_arguments功能类似,只是他仅仅是从body中获取值。
再提一个问题?????get_query_argument、get _argument、
get_body_argument的区别????测试一下便知。
按如下修改post方法,
def post(self, *args, **kwargs):print(self.request.query_arguments)print(self.request.arguments)print(self.request.body_arguments)print("POS age:" + self.get_argument("age"))self.write("POS age:" + self.get_argument("age"))
按如下方式模拟访问:
后台打印的结果如下图:
所以得出结论就是,get _argument获取的值范围是get_query_argument与get_body_argument两者范围的合并。
输出响应函数:
7.7 clear方法
重置响应的所有的头部以及内容。
"""Resets all headers and content for this response.""" self._headers = httputil.HTTPHeaders({"Server": "TornadoServer/%s" % tornado.version,"Content-Type": "text/html; charset=UTF-8","Date": httputil.format_timestamp(time.time()), }) self.set_default_headers() self._write_buffer = [] self._status_code = 200 self._reason = httputil.responses[200]
处理过程
- 首先默认设置3个响应头部,分别是Server,Content_Type、Date.
- 调用set_default_headers 方法,实现自定义header的设置。
- 其他参数的默认设置。
7.9 set_default_headers方法
上面说了set_default_headers 方法是实现请求响应头部的自定义实现,被子类重写。举个例子。
def set_default_headers(self):self._headers.add("custom_header1", "custom_header1")self._headers.add("custom_header2", "custom_header2")
通过游览器访问http://localhost:8888/book,用firebug查询响应头。结果如下:
7.10 write方法
将给定的块输出到输出缓存中。如果给定的块是一个字典,就会将这个快当成是JSON并且将Content_Type设置成application/json返回给客户端。但是,如果你想用不同的Content_Type发送JSON,可以在调用write方法后再调用set_header方法进行设置。
注意,list 列表集合是不会转化成JSON的,原因是考虑到跨域的安全。所有的JSON输出都必须用字典包装。具体源码说明如下:
7.11 rend 方法
用给定的参数渲染模板。这个涉及到模板的概念,后续再学。
7.12 write_error方法
重写自定义错误页面的实现。
如果error是由没有捕获的异常(包括HTTPError)引起的,通过kwargs[|”exc_info”]能获取exc_info元组。实现代码如下:
举个例子实现一个自定义的错误页面,在BookRequestHandler中添加如下代码:
def write_error(self, status_code, **kwargs):self.write("oh,my god!出错啦!!!!请联系系统管理员。\n")self.write("呵呵,也没关系,我已经讲错误信息记录在日志中去了,系统管理员会看到的。\r\n")if "exc_info" in kwargs:self.write("错误信息为:\r\n")for line in traceback.format_exception(*kwargs["exc_info"]):self.write(line)self.finish()
并将get方法修改成:
def get(self, *args, **kwargs):# print(self.welcome + "\r\n" + "and value2 =" + self.value2)print("get method: Processing get Method...........")# self.write(self.welcome + "\r\n" + "and value2 =" + self.value2)# print(self.request.query_arguments)# print(self.request.arguments)# print(self.request.body_arguments)# self.write("参数name的值为:" + self.get_argument("name", "liaofei"))print(1/0)
print(1/0)语句,人为地制造一个错误。在游览器中访问http://localhost:8888/book,得到如下结果,
就是使用了重写write_error中的方法实现。
Cookie相关函数
7.13
get_cookie
、set_cookie
获取与设置cookie的值。这个对熟悉web开发的人,一看就明白。就不多解释。
7.14
get_secure_cookie
、set_secure_cookie
获取与设置安全cookie的值。与7.13 相比加了一个单词secure(安全),就说明是为cookie安全加密解密的作用。这个方法涉及到
cookie_secret 的Application 设置选项。来举个列子说明他们之间的区别:
加入以下代码:
class CookieRequestHandler(RequestHandler):def get(self, flag):if flag == '0':self.set_cookie("user", "liaofei")elif flag == '1':userCookie = self.get_cookie("user")self.write(userCookie)
修改application的配置
settings = {"debug":False,"cookie_secret":"gagagaarwrslijwlrjoiajfoajgojowurwojrowjojgfoaguuuu9", }app = Application(handlers=[(r"/book", BookRequestHandler, dict(welcome=welcome, value2=value2)),(r"/cookie/([0-1]+)", CookieRequestHandler), ], **settings)(r"/cookie/([0-1]+)", CookieRequestHandler), ], **settings)
注意settings中设置了cookie_secret的值。
访问http://localhost:8888/cookie/0时,调用set_cookie
设置cookie中user的值为liaofei,并调用set_secure_cookie
设置cookie 中usersecure的值同样为liaofei。用firebug查看这个相同值得cookie(都是liaofei),发现在游览器客户端的值是不一样的,一个加密过,一个未加密。具体结果如下图:
关注 - 3
粉丝 - 11
» 下一篇:tornado 学习笔记8 模板以及UI
转载于:https://www.cnblogs.com/silence-cc/p/10010024.html
tornado 学习笔记7 RequestHandler功能分析相关推荐
- tornado学习笔记day08-tornado中的异步
概述 应为epoll主要用来解决网络的并发问题,所以tornado中的异步也是主要体现在网络的IO异步上,即异步web请求 tornado.httpclient.AsyncHTTPClient tor ...
- tornado学习笔记day06-应用安全
应用安全 cookie 普通cookie 一般我们的用户表中都有啥呢 你在购物的时候,加入购物车,让你登录,那你登录之后,他怎么知道你登录了呢 token 这个值是随机的,存在cookie里面 设置 ...
- tornado学习笔记day05-访问数据库
模板## 配置模板路径 这个在之前我们已经配置好了,可以参考前面的文章 settings = {# 就像upfile就没有,你写了也白扯'template_path': os.path.join(BA ...
- tornado学习笔记day04-执行顺序
响应输出 -> write 原型 self.write()函数 源码中是这样定义的 def write(self, chunk: Union[str, bytes, dict]) -> N ...
- tornado学习笔记day03-响应输出
write: 作用: 将chunk中的数据写到输出缓冲区 利用write方法写json数据 我们自己手动序列化json的那种方式Content-Type 的属性值为text-html 而我们采用wri ...
- tornado学习笔记day02-进阶与提升
整理基础工程 请看第一天的配置文件目录,搭建了一个框架的基础目录 Application settings debug 作用 可以设置tornado是否工作在调试模式下面,默认为false,即工作在生 ...
- tornado学习笔记day01-高并发性能web框架
tornado的安装 这里我使用的是虚拟环境中的pip安装,配合清华大学镜像源安装的 pip install tornado -i https://pypi.tuna.tsinghua.edu.cn/ ...
- tornado学习笔记day07-同步与异步
同步 概念 同步就是按部就班的依次执行我们的代码 进阶 但是有些情况我们有一些比较耗时的从操作,比如去别的地方拿点资源,去其他网站请求数据,去访问数据库,上传文件等等,所以这里面优点瑕疵,有小编一一道 ...
- Tornado 学习笔记
Tornado是使用Python编写的一个强大的.可扩展的Web服务器.它在处理严峻的网络流量时表现得足够强健,在创建和编写时有着足够的轻量级,能被用在大量的应用和工具中. tornadoweb.or ...
- Tornado学习笔记(四)
一.Tornado的语言国际化方法 Tornado做国际化折腾了一下下,Tornado这部分的官方文档太poor了.所以自己记录一下如何用tornado结合gettext做国际化. 第一步,在项目路径 ...
最新文章
- 将整数拆分为勾股数的问题解决
- 检查文件上传完成_“我的数据上传NCBI又报错了...” “攻略拿去!”
- python大文件排序_python实现按创建时间对文件排序
- 20. Cookie 和 Session
- 6425C-Lab3 管理用户与服务帐户(1)
- OpenCasCade在一个窗体中的两个picture控件中 分别显示
- Ubuntu安装SSTP
- 位置不可用无法访问介质受写入保护怎样解决?
- graphene-django开发实践——登录为例
- 手机连上电脑热点发现网络不可用,怎么办?
- 电脑一键重装系统发现内存占用率过高怎么办
- 深入理解浏览器兼容性模式
- 与Ubuntu16.04+pycharm+第三方包决战的点点滴滴
- python black_如何使用Black自动格式化Python代码
- c++顺时针螺旋方阵
- 【复杂网络社团结构研究】拉普拉斯矩阵定义及性质详细推导
- java抛异快捷键_Java 如何抛出异常、自定义异常、手动或主动抛出异常
- Tomcat应用部署是否要一个萝卜一个坑?
- JavaSE_03面向对象-编程单词词汇
- linux 用户权限详解,Linux用户及权限详解
热门文章
- PHP:A mono-alphabetic cipher 单字母密码加解密算法(附完整源码)
- 手机企业邮箱客户端哪个好用?
- 【渝粤教育】电大中专中药学基础作业 题库
- EOS的trace_api_plugin插件测试
- python绘制世界人口地图
- Open-DrainPush-Pull
- 超级邮件群发代理服务器设置,超级邮件群发教程
- 学java用不用学ps_【No935】零基础学习从入门到精通Ps课程
- 通过Grafana进行监控报警
- 成为虚无鸿蒙系统掌控者,飞剑问道:烟雨飞剑破开鸿蒙空间,秦云成第四位鸿蒙掌控者!...