二、中间件(middleware)
1. 中间件(middleware)
Django中的中间件主要实现一些附加功能,在request被用户handler处理前,以及用户handler处理后生存的response进行处理。因此大部分中间件的主要功能是实现了process_request或者process_response之一,当然也可以两者都实现,意味着该中间件涉及到处理的request和response的处理。
1.1 类视图
在中间件的类关系中,基本类是MiddlewareMixin,其他所有的中间件类都继承自该类,该类仅有一个成员变量get_response,该变量在连接各个中间件起着非常重要的作用。该类有两个成员函数:__init__和__call__,前者用于实现初始化,后者执行主要的功能。
def __call__(self, request):
response = None
if hasattr(self, 'process_request'):
response = self.process_request(request)
if not response:
response = self.get_response(request)
if hasattr(self, 'process_response'):
response = self.process_response(request, response)
return response
其中process_request和process_response自不必多言,中间件需要实现的主要功能,通过hasattr()调用,判断当前中间件是否具有process_request和process_response,有则调用。
不同功能的中间件,根据要完成的功能,可以扩展自己的成员变量和成员函数,通常,自定义的成员函数被process_request和process_response调用,即这些自定义的成员函数通常不对外开放。
其中,__init__成员函数有入参函数之一: get_response,这在后续的加载中间件时很重要好。
下图是中间件SecurityMiddleware类的类视图关系图,其他中间件的视图关系类似。
1.2 中间件初始化
在工程的配置文件(Project/Project/setting.py)中指定要使用的中间件,注意各插件在序列中的顺序,这决定了当请求到来时,各个中间件的执行顺序,排在最前面的中间件得到最先执行,最后的中间件最后执行。其表现通常如下所示:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
下面来看,中间件是如何被加载和初始化的。class BaseHandler(object):中定义了load_middleware接口,具体细节如下:
handler = convert_exception_to_response(self._get_response) /*handler[0]*/
for middleware_path in reversed(settings.MIDDLEWARE):
middleware =
import_string(middleware_path)
mw_instance = middleware(handler)
handler = convert_exception_to_response(mw_instance) /*handler[i]*/
self._middleware_chain = handler /*handler[end]*/
在上述例程中,开始遍历所有中间件之前,handler(即handler[0])赋值给调用实体的_get_response成员函数。 (比如class WSGIHandler(base.BaseHandler),WSGIHandler. load_middleware()调用之后,handler[0] = WSGIHandler._get_response = BaseHandler._get_response())。遍历所有中间件过程中,加载并初始化(middleware()调用对应着__init__成员函数)中间件,因此中间件的get_response赋值为handler[i],注意middleware()返回一个中间件类实体,接着调用调用handler = convert_exception_to_response (mw_instance),convert_exception_to_response只是对输入函数进行了容错封装,在分析逻辑时,可以简单看成输入函数本身,因此,可以看成handler = mw_instance(request),对于一个类实体调用即调用__call__成员函数,从目前来看,大部分的中间件并没有重载该成员函数,因此是直接调用基类的成员函数,即: MiddlewareMixin. __call__(self)。因此handler[i] = MiddlewareMixin. __call__(self)。注意该函数有一个self输入参数,各个中间件在调用时,传入该中间件对应的self实体,这样self.process_request, self.process_response的调用就分别对应着不同中间夹的处理函数。load_middleware()调用之后,各个中间件通过get_response链接起来,这样一个request请求到来时,可以顺序通过各个中间件依次进行处理,如下图所示:
在调用的最后,将self._middleware_chain = handler[end],类似于将中间件链表的链表头保存起来,下次处理时,从该链表头开始进行遍历处理。
1.3 中间件使用
各个中间件的调用顺序如下递归图所示:
在类视图一节中对__call__基类成员函数进行过介绍,该函数主要有先后执行的三个函数构成:process_request()、get_response()、process_response(),而get_response()通常指向下一个中间件的__call__成员函数(中间件链表的最后一个中间件除外,其get_response()指向handler[0]),由于各个中间件的get_response()这一特性(绝大部分指向基类__call__成员函数),使得中间件链表处理有点类似递归调用的感觉。A,B,A1,B1,A2,B2,C2,C1,C,这一递归调用顺序,决定了各个中间件处理的一些特点:
1、最先进行流程处理的中间件,其process_request()(如果存在的话)最先被执行,但是其process_response()(如果存在的话)却最后得到处理。
2、最后进行流程处理的中间件,其process_request()(如果存在的话)最后被执行,但是其process_response()(如果存在的话)紧接着得到处理。
3、在中间件处理流程中,如果出现某个中间件的process_request()返回了response,这种情况通常是处理过程中出现了异常情况,该中间件后续的中间件不再参与处理,直接调用该中间件的process_response()(如果存在的话),或者直接返回。
二、中间件(middleware)的更多相关文章
- C# Owin 创建与测试自己的中间件Middleware(二)
本文纯属介绍怎么简单地创建自己的Owin.还没有理解owin概念的请看上一篇文章:http://www.cnblogs.com/alunchen/p/7049307.html 目录 1.创建项目 2. ...
- ASP.NET Core -中间件(Middleware)使用
ASP.NET Core开发,开发并使用中间件(Middleware). 中间件是被组装成一个应用程序管道来处理请求和响应的软件组件. 每个组件选择是否传递给管道中的下一个组件的请求,并能之前和下一组 ...
- {Django基础九之中间件} 一 前戏 二 中间件介绍 三 自定义中间件 四 中间件的执行流程 五 中间件版登陆认证
Django基础九之中间件 本节目录 一 前戏 二 中间件介绍 三 自定义中间件 四 中间件的执行流程 五 中间件版登陆认证 六 xxx 七 xxx 八 xxx 一 前戏 我们在前面的课程中已经学会了 ...
- ASP.NET Core 开发-中间件(Middleware)
ASP.NET Core开发,开发并使用中间件(Middleware). 中间件是被组装成一个应用程序管道来处理请求和响应的软件组件. 每个组件选择是否传递给管道中的下一个组件的请求,并能之前和下一组 ...
- ASP.NET Core中间件(Middleware)实现WCF SOAP服务端解析
ASP.NET Core中间件(Middleware)进阶学习实现SOAP 解析. 本篇将介绍实现ASP.NET Core SOAP服务端解析,而不是ASP.NET Core整个WCF host. 因 ...
- laravel中间件-----------middleware
middleware中间件 是访问到达服务器后在被对应的路由处理之前所经过的一层过滤层,故称中间件. 中间件是存放在app\http\middleware中,需要定一个 handle 处理方法,在ha ...
- 中间件(Middleware)
中间件(Middleware) ASP.NET Core开发,开发并使用中间件(Middleware). 中间件是被组装成一个应用程序管道来处理请求和响应的软件组件. 每个组件选择是否传递给管道中的下 ...
- 初探中间件(middleware)
初探中间件(middleware) 因为考虑到文章的长度, 所以 BaseHandler 的展开被推迟了. 在 BaseHandler 中隐藏着中间件的信息, 较常见的 SessionMiddlewa ...
- django中间件Middleware
熟悉web开发的同学对hook钩子肯定不陌生,通过钩子可以方便的实现一些触发和回调,并且做一些过滤和拦截. django中的中间件(middleware)就是类似钩子的一种存在.下面我们来介绍一下,并 ...
随机推荐
- 趣拍SDK接入问题Android
Android接入趣拍问题. 大部分android开发者第一次下载SDK后,特别是导入到eclipse后,可以运行工程,但点击app中的record没反映,每次点击record按钮 会出现如下log. ...
- ImageEdit 加载图片
从本地加载图片 <dxe:ImageEdit Name="iePortrait" Height="120" Width="100" S ...
- RDD分区2GB限制
本文目的 最近使用spark处理较大的数据时,遇到了分区2G限制的问题(ken).找到了解决方法,并且在网上收集了一些资料,记录在这里,作为备忘. 问题现象 遇到这个问题时,spark日志 ...
- “粪便银行”:救人拿钱两不误 A Poop Bank in Massachusetts Will Pay You $40 Every Day
“粪便银行”:救人拿钱两不误 如果你年龄小于50岁,排便规律,而且愿意每天去美国麻省麦德福德跑一趟,那么没准你可以每天得到40美元的外快,而你需要做的事情只是生产便便. 要想得到这笔收入,请拜访“开放 ...
- mybatis 3.2.3 maven dependency pom.xml 配置
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis< ...
- 使用 ContentProviderOperation 来提升性能
ContentProviders 是android 系统核心组件之一,ContentProviders 封装了数据的访问接口,其底层数据一般都是保存在数据库中或者保存在云端. 有时候你需要更新多行数 ...
- HL AsySocket 服务开发框架 - 一般性测试1
一 概述 Socket服务器性能要好就要经过无数次的测试,来保证,以下是记录一次的测试经过. 机器配置:Inter(R) Core(TM) i3-2310m CPU 2.10GHz RAM 6.00G ...
- C++读取mysql中utf8mb4编码表数据乱码问题及UTF8转GBK编码
数据库编码为utf8,但是由于某些表的一些字段存储了emoji字符,表采用了utf8mb4编码,默认情况下在C++代码中读出的中文字段值都变成了乱码. 解决方法为,在进行数据库查询前,在C++中执行一 ...
- UICollectionView瀑布流的实现原理(转)
http://ios.jobbole.com/85689/ 和使用 UIScollView 创刊一个瀑布流是一样的方式 7cc829d3gw1f4nq2oc09zj20j00hvq90.jpg 我的 ...
- Ubuntu12.04 安装PyCharm
1. 下载 选择Linux Tab,选择下载免费的Community Edition[1].当前版本是3.4 2. 安装PyCharm 按照官网给出的安装指导[2]进行安装. (1) Copy the ...