Spring filter原理深入浅出
来源:互联网 发布:手机淘宝宝贝描述模板 编辑:程序博客网 时间:2024/06/03 20:46
title: Spring filter原理深入浅出
tag: Spring
date: 2017-12-21 16:05:00
categories: Spring
Spring filter原理深入浅出
在这篇文章中,我会介绍一个请求从浏览器进来,是如何被Spring拦截到的,Spring又是如何处理这个请求的,filter有什么作用,filter的原理等
一、前置知识
OK,我们首先介绍一下,请求从浏览器过来,我们的服务器会经历些什么。先看一张jetty的内部结构图
我们看到jetty的核心组件包括了一大堆的*Handler
,对于这些handler,不论任何容器基本都有,可能名称不太相同,笔者这里以undertow这个容器为例,浏览器发送过来的请求,会经过一个FilterHandler
这个handler跟我们今天的主题相关。
二、Request阶段
先看一下这个handler的处理代码
public void handleRequest(HttpServerExchange exchange) throws Exception { ServletRequestContext servletRequestContext = (ServletRequestContext)exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY); ServletRequest request = servletRequestContext.getServletRequest(); ServletResponse response = servletRequestContext.getServletResponse(); DispatcherType dispatcher = servletRequestContext.getDispatcherType(); Boolean supported = (Boolean)this.asyncSupported.get(dispatcher); if (supported != null && !supported.booleanValue()) { servletRequestContext.setAsyncSupported(false); } List<ManagedFilter> filters = (List)this.filters.get(dispatcher); if (filters == null) { this.next.handleRequest(exchange); } else { FilterHandler.FilterChainImpl filterChain = new FilterHandler.FilterChainImpl(exchange, filters, this.next, this.allowNonStandardWrappers); filterChain.doFilter(request, response); } }
前面都是拿request和response我们不用看,主要是看后面几行代码,filters
如果我们有配置自己的filter,这里肯定不会为空,那么就走下面的filter 链 ,我们看下FilterHandler里面的doFilter的代码
int index = this.location++;if (index >= this.filters.size()) { this.next.handleRequest(this.exchange);} else { ((ManagedFilter)this.filters.get(index)).doFilter(request, response, this);}
location默认是0,所以会从list里面的第一个元素取起,依次执行,OK,我们知道,filter里面一般会有一个filterChain.doFilter(request, response);
这句话,代表filter链继续执行,这时候,这里的location就会+1 ,变成执行第二个,第三个,链条就转动起来了。终于执行到我们自己写的ResponseWrapperFilter
,这个filter大家可以在我后面的源码里看到,这里我先说有这么一个自己写的filter,我用来包装我们的response,给response做些手脚。哈哈。
OK,我们继续,当所有的filter都执行完毕之后,就会开始执行this.next.handleRequest(exchange); 这段代码,也就是在继续执行我们刚才的handler链,next表示的是ServletHandler` 这个类,执行代码如下。
try { servlet = this.managedServlet.getServlet(); ((Servlet)servlet.getInstance()).service(request, response); } catch (UnavailableException var12) { if (var12.isPermanent()) { UndertowServletLogger.REQUEST_LOGGER.stoppingServletDueToPermanentUnavailability(this.managedServlet.getServletInfo().getName(), var12); this.managedServlet.stop(); this.managedServlet.setPermanentlyUnavailable(true); exchange.setStatusCode(404); } else { unavailableUntilUpdater.set(this, System.currentTimeMillis() + (long)(var12.getUnavailableSeconds() * 1000)); UndertowServletLogger.REQUEST_LOGGER.stoppingServletUntilDueToTemporaryUnavailability(this.managedServlet.getServletInfo().getName(), new Date(until), var12); exchange.setStatusCode(503); }
一旦掉用了下面这段代码,我们的处理逻辑就会被调用,说白了就是我们Controller里面的那些逻辑就会被调用
((Servlet)servlet.getInstance()).service(request, response);
这段代码很重要
三、reponse阶段
经过了上面这段代码的执行,我们的filter开始收拢了,所有的filter在执行filterChain.doFilter(request, response);
这段代码之后其实代码是还没有执行完的,如果你下面还有写代码的话,大家好好品味一下这句话,是不是这个意思。因为每个filter都去调用下一个filter了,等最后一个filter执行完毕之后,就开始慢慢收拢,这时候我们的reponse也有了。
当所有的filter执行完毕自己的后置代码之后,就回到了我们最初的地方,我们的最初的FilterHandler开始调用的地方。undertow服务器就继续开始执行了,它就会执行下面的代码输出你想要的信息
if (!exchange.isDispatched() && !(exchange.getConnection() instanceof ServletInitialHandler.MockServerConnection)) { servletRequestContext.getOriginalResponse().responseDone(); servletRequestContext.getOriginalRequest().clearAttributes(); }
主要就是把输出流写入到socket中,然后客户端接收
好啦,今天就讲到这里啦,这文章还没有结束,请期待后续 ^ _ ^
- Spring filter原理深入浅出
- Spring深入浅出原理剖析
- Spring 编码过滤 -- 解析Filter实现原理
- Spring 编码过滤 -- 解析Filter实现原理
- 深入浅出DirectShow Filter
- 深入浅出DirectShow Filter
- 深入浅出DirectShow Filter
- 深入浅出DirectShow Filter(一)
- filter原理
- 深入浅出Spring
- spring filter
- 深入浅出DirectShow Filter(一)
- 深入浅出DirectShow Filter(二)
- 深入浅出DirectShow Filter(一)
- 深入浅出DirectShow Filter(二)
- 深入浅出DirectShow Filter(一)
- 深入浅出DirectShow Filter(二)
- 深入浅出DirectShow Filter(二)
- redis学习
- Android深入分析NativeMessageQueue和Looper.cpp(Native层消息机制)
- 学习笔记:SVM
- 清澄A1039. 欢乐的跳跃者
- Ruby on rails 安装教程
- Spring filter原理深入浅出
- linux发送邮件配置
- C语言经典算法(三)——求二进制中1的个数的五种方法
- 关于std::shared_ptr与std::enable_shared_from_this循环引用导致的问题
- Mac 下安装 java环境
- 分享下我用Retrofit + Rxjava请求后台数据时遇到的问题
- 小希的迷宫 简单并查集
- 博弈论常用结论
- python_fullstack-小知识点