array(2) { ["docs"]=> array(10) { [0]=> array(10) { ["id"]=> string(3) "428" ["text"]=> string(77) "Visual Studio 2017 单独启动MSDN帮助(Microsoft Help Viewer)的方法" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(8) "DonetRen" ["tagsname"]=> string(55) "Visual Studio 2017|MSDN帮助|C#程序|.NET|Help Viewer" ["tagsid"]=> string(23) "[401,402,403,"300",404]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400964" ["_id"]=> string(3) "428" } [1]=> array(10) { ["id"]=> string(3) "427" ["text"]=> string(42) "npm -v;报错 cannot find module "wrapp"" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "zzty" ["tagsname"]=> string(50) "node.js|npm|cannot find module "wrapp“|node" ["tagsid"]=> string(19) "[398,"239",399,400]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400760" ["_id"]=> string(3) "427" } [2]=> array(10) { ["id"]=> string(3) "426" ["text"]=> string(54) "说说css中pt、px、em、rem都扮演了什么角色" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(12) "zhengqiaoyin" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400640" ["_id"]=> string(3) "426" } [3]=> array(10) { ["id"]=> string(3) "425" ["text"]=> string(83) "深入学习JS执行--创建执行上下文(变量对象,作用域链,this)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "Ry-yuan" ["tagsname"]=> string(33) "Javascript|Javascript执行过程" ["tagsid"]=> string(13) "["169","191"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511399901" ["_id"]=> string(3) "425" } [4]=> array(10) { ["id"]=> string(3) "424" ["text"]=> string(30) "C# 排序技术研究与对比" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "vveiliang" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(8) ".Net Dev" ["catesid"]=> string(5) "[199]" ["createtime"]=> string(10) "1511399150" ["_id"]=> string(3) "424" } [5]=> array(10) { ["id"]=> string(3) "423" ["text"]=> string(72) "【算法】小白的算法笔记:快速排序算法的编码和优化" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "penghuwan" ["tagsname"]=> string(6) "算法" ["tagsid"]=> string(7) "["344"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511398109" ["_id"]=> string(3) "423" } [6]=> array(10) { ["id"]=> string(3) "422" ["text"]=> string(64) "JavaScript数据可视化编程学习(二)Flotr2,雷达图" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "chengxs" ["tagsname"]=> string(28) "数据可视化|前端学习" ["tagsid"]=> string(9) "[396,397]" ["catesname"]=> string(18) "前端基本知识" ["catesid"]=> string(5) "[198]" ["createtime"]=> string(10) "1511397800" ["_id"]=> string(3) "422" } [7]=> array(10) { ["id"]=> string(3) "421" ["text"]=> string(36) "C#表达式目录树(Expression)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "wwym" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(4) ".NET" ["catesid"]=> string(7) "["119"]" ["createtime"]=> string(10) "1511397474" ["_id"]=> string(3) "421" } [8]=> array(10) { ["id"]=> string(3) "420" ["text"]=> string(47) "数据结构 队列_队列实例:事件处理" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "idreamo" ["tagsname"]=> string(40) "C语言|数据结构|队列|事件处理" ["tagsid"]=> string(23) "["246","247","248",395]" ["catesname"]=> string(12) "数据结构" ["catesid"]=> string(7) "["133"]" ["createtime"]=> string(10) "1511397279" ["_id"]=> string(3) "420" } [9]=> array(10) { ["id"]=> string(3) "419" ["text"]=> string(47) "久等了,博客园官方Android客户端发布" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(3) "cmt" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511396549" ["_id"]=> string(3) "419" } } ["count"]=> int(200) } 222 Spring接收处理HTTP请求流程浅析 - 爱码网
  • spring web Http request 请求流程
  1. 服务器容器监听端口,接收到请求后调用Servlet的service方法。以Tomcat为例,Tomcat监听8080端口(8080为默认配置端口,也可以自行更改),当有请求到达8080端口时,容器将调用Servlet的service方法。javax.servlet.Servlet中定义了所有Servlet必须要实现的方法。在spring web中接收请求的servlet就是DispatcherServlet。
  2. 在service方法中判断请求类型是GET、POST、PUT......,然后调用相应的doGet()、doPost()、doPut()方法。
  3. 在doGet/doPost方法中执行processRequest()方法,processRequest()方法执行请求上下文的初始化过程。
  4. 调用doService()方法,由doService()方法执行doDispatch()方法。
  5. 最后由doDispatch方法去获取请求的mappedHandler和HandlerAdapter,处理完用户请求之后通过新建一个ServletWebRequest来渲染返回数据。

 

Spring接收处理HTTP请求流程浅析

                                                                                   图片来自网络

如上图中(1)步骤:

请求首先通过ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse)方法调用DispatcherServlet的service(ServletRequest, ServletResponse)方法,但是DispatcherServlet中没有此方法,所以调用父类GenericServlet的抽象service(ServletRequest, ServletResponse)方法。最后请求到达HttpServlet.service(ServletRequest, ServletResponse)方法。源码如下

//HttpServlet.service方法的源码

@Override

    public void service(ServletRequest req, ServletResponse res)

        throws ServletException, IOException {



        HttpServletRequest  request;

        HttpServletResponse response;



        try {

            request = (HttpServletRequest) req;

            response = (HttpServletResponse) res;

        } catch (ClassCastException e) {

            throw new ServletException("non-HTTP request or response");

        }

        service(request, response);

}

通过debug源码,service(request,response)调用org.springframework.web.servlet.FrameworkServlet.service(HttpServletRequest, HttpServletResponse)方法。源码如下。

/**

 * Override the parent class implementation in order to intercept PATCH requests.

 */

@Override

protected void service(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {



HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());

if (httpMethod == HttpMethod.PATCH || httpMethod == null) {

processRequest(request, response);

}

else {

super.service(request, response);

}

}

FrameworkServlet接收到请求后将请求交个父类HttpServlet.service(HttpServletRequest, HttpServletResponse)处理,此方法中判断请求类型是get、post还是其他请求,更具请求类型调用相应的doGet、doPost方法。源码如下。

protected void service(HttpServletRequest req, HttpServletResponse resp)

        throws ServletException, IOException {



        String method = req.getMethod();



        if (method.equals(METHOD_GET)) {

            long lastModified = getLastModified(req);

            if (lastModified == -1) {

                // servlet doesn't support if-modified-since, no reason

                // to go through further expensive logic

                doGet(req, resp);

            } else {

                long ifModifiedSince;

                try {

                    ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);

                } catch (IllegalArgumentException iae) {

                    // Invalid date header - proceed as if none was set

                    ifModifiedSince = -1;

                }

                if (ifModifiedSince < (lastModified / 1000 * 1000)) {

                    // If the servlet mod time is later, call doGet()

                    // Round down to the nearest second for a proper compare

                    // A ifModifiedSince of -1 will always be less

                    maybeSetLastModified(resp, lastModified);

                    doGet(req, resp);

                } else {

                    resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);

                }

            }



        } else if (method.equals(METHOD_HEAD)) {

            long lastModified = getLastModified(req);

            maybeSetLastModified(resp, lastModified);

            doHead(req, resp);



        } else if (method.equals(METHOD_POST)) {

            doPost(req, resp);



        } else if (method.equals(METHOD_PUT)) {

            doPut(req, resp);



        } else if (method.equals(METHOD_DELETE)) {

            doDelete(req, resp);



        } else if (method.equals(METHOD_OPTIONS)) {

            doOptions(req,resp);



        } else if (method.equals(METHOD_TRACE)) {

            doTrace(req,resp);



        } else {

            //

            // Note that this means NO servlet supports whatever

            // method was requested, anywhere on this server.

            //



            String errMsg = lStrings.getString("http.method_not_implemented");

            Object[] errArgs = new Object[1];

            errArgs[0] = method;

            errMsg = MessageFormat.format(errMsg, errArgs);



            resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);

        }

}

我们以post请求为例,继续debug源码,此时doPost方法执行的是org.springframework.web.servlet.FrameworkServlet.doPost(HttpServletRequest, HttpServletResponse)方法,再由此方法执行org.springframework.web.servlet.FrameworkServlet.processRequest(HttpServletRequest, HttpServletResponse),最后请求又回到DispatcherServlet.doService(HttpServletRequest, HttpServletResponse)方法,然后委托给DispatcherServlet.doDispatch(HttpServletRequest, HttpServletResponse)处理。到此,流程中步骤(1)结束。

源码如下。

/**

 * Process the actual dispatching to the handler.

 * <p>The handler will be obtained by applying the servlet's HandlerMappings in order.

 * The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters

 * to find the first that supports the handler class.

 * <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers

 * themselves to decide which methods are acceptable.

 * @param request current HTTP request

 * @param response current HTTP response

 * @throws Exception in case of any kind of processing failure

 */

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {

HttpServletRequest processedRequest = request;

HandlerExecutionChain mappedHandler = null;

boolean multipartRequestParsed = false;



WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);



try {

ModelAndView mv = null;

Exception dispatchException = null;



try {

//检查容器中是否同时存在多个不同的请求

processedRequest = checkMultipart(request);

multipartRequestParsed = (processedRequest != request);



// 确定当前请求的处理程序

//步骤2、3

mappedHandler = getHandler(processedRequest);

if (mappedHandler == null) {

noHandlerFound(processedRequest, response);

return;

}



// 为当前请求确定处理程序适配器。步骤4

//这个过程中,会调用MappedInterceptor的matches方法,以此来判断次url是否在拦截范围内

HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());



// Process last-modified header, if supported by the handler.

String method = request.getMethod();

boolean isGet = "GET".equals(method);

if (isGet || "HEAD".equals(method)) {

long lastModified = ha.getLastModified(request, mappedHandler.getHandler());

if (logger.isDebugEnabled()) {

logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);

}

if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {

return;

}

}

//执行拦截器中的preHandle拦截方法

if (!mappedHandler.applyPreHandle(processedRequest, response)) {

return;

}



// 调用实际处理程序。步骤5、6、7

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());



if (asyncManager.isConcurrentHandlingStarted()) {

return;

}

//渲染默认的mv。步骤10

applyDefaultViewName(processedRequest, mv);

//执行PostHandle拦截方法

mappedHandler.applyPostHandle(processedRequest, response, mv);

}

catch (Exception ex) {

dispatchException = ex;

}

catch (Throwable err) {

// As of 4.3, we're processing Errors thrown from handler methods as well,

// making them available for @ExceptionHandler methods and other scenarios.

dispatchException = new NestedServletException("Handler dispatch failed", err);

}

//渲染返回值。步骤11。

processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

}

catch (Exception ex) {

triggerAfterCompletion(processedRequest, response, mappedHandler, ex);

}

catch (Throwable err) {

triggerAfterCompletion(processedRequest, response, mappedHandler,

new NestedServletException("Handler processing failed", err));

}

finally {

if (asyncManager.isConcurrentHandlingStarted()) {

// Instead of postHandle and afterCompletion

if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);

}

}

else {

// Clean up any resources used by a multipart request.

if (multipartRequestParsed) {

cleanupMultipart(processedRequest);

}

}

}

}
  • SpringBoot请求流程方法调用栈
  1. get请求

debug源码,方法调用如下(出入参解析使用fastjson):

ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 166	
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 231	

//ApplicationFilterChain.internalDoFilter中执行的是DispatcherServlet.service(ServletRequest, ServletResponse)方法,
//但是DispatcherServlet中没有此方法,所以调用父类HttpServlet.service(ServletRequest, ServletResponse)的方法
DispatcherServlet(HttpServlet).service(ServletRequest, ServletResponse)
DispatcherServlet(FrameworkServlet).service(HttpServletRequest, HttpServletResponse)
DispatcherServlet(HttpServlet).service(HttpServletRequest, HttpServletResponse) line: 628
DispatcherServlet(FrameworkServlet).doGet(HttpServletRequest, HttpServletResponse) line: 866	
DispatcherServlet(FrameworkServlet).processRequest(HttpServletRequest, HttpServletResponse) line: 959	
DispatcherServlet.doService(HttpServletRequest, HttpServletResponse) line: 889	
DispatcherServlet.doDispatch(HttpServletRequest, HttpServletResponse) line: 949	
RequestMappingHandlerAdapter(AbstractHandlerMethodAdapter).handle(HttpServletRequest, HttpServletResponse, Object) line: 87	
RequestMappingHandlerAdapter.handleInternal(HttpServletRequest, HttpServletResponse, HandlerMethod) line: 779	
RequestMappingHandlerAdapter.invokeHandlerMethod(HttpServletRequest, HttpServletResponse, HandlerMethod) line: 852	
ServletInvocableHandlerMethod.invokeAndHandle(ServletWebRequest, ModelAndViewContainer, Object...) line: 102	
	//解析传入参数、调用方法、返回结果
	ServletInvocableHandlerMethod(InvocableHandlerMethod).invokeForRequest(NativeWebRequest, ModelAndViewContainer, Object...) line: 131	
		//解析传入参数
		ServletInvocableHandlerMethod(InvocableHandlerMethod).getMethodArgumentValues(NativeWebRequest, ModelAndViewContainer, Object...) line: 150	
			HandlerMethodArgumentResolverComposite.resolveArgument(MethodParameter, ModelAndViewContainer, NativeWebRequest, WebDataBinderFactory) line: 120	
				RequestParamMethodArgumentResolver(AbstractNamedValueMethodArgumentResolver).resolveArgument(MethodParameter, ModelAndViewContainer, NativeWebRequest, WebDataBinderFactory) line: 97	


		//调用处理方法,返回结果
		ServletInvocableHandlerMethod(InvocableHandlerMethod).doInvoke(Object...) line: 207	
	//处理返回值
	HandlerMethodReturnValueHandlerComposite.handleReturnValue(Object, MethodParameter, ModelAndViewContainer, NativeWebRequest) line: 78	
		RequestResponseBodyMethodProcessor.handleReturnValue(Object, MethodParameter, ModelAndViewContainer, NativeWebRequest) line: 175	
			//调用数据解析器
			RequestResponseBodyMethodProcessor(AbstractMessageConverterMethodProcessor).writeWithMessageConverters(T, MethodParameter, ServletServerHttpRequest, ServletServerHttpResponse) line: 184	
				//调用fastjson序列化结果参数
				FastJsonHttpMessageConverter.write(Object, Type, MediaType, HttpOutputMessage) line: 184	
//视图解析
RequestMappingHandlerAdapter.getModelAndView(ModelAndViewContainer, ModelFactory, NativeWebRequest) line: 1000	
  1. post请求
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse)

DispatcherServlet(HttpServlet).service(ServletRequest, ServletResponse)	

DispatcherServlet(HttpServlet).service(HttpServletRequest, HttpServletResponse)


org.springframework.web.servlet.FrameworkServlet.doPost(HttpServletRequest, HttpServletResponse)
org.springframework.web.servlet.FrameworkServlet.doService(HttpServletRequest, HttpServletResponse)
org.springframework.web.servlet.DispatcherServlet.doService(HttpServletRequest, HttpServletResponse)
DispatcherServlet.doDispatch(HttpServletRequest, HttpServletResponse)	

RequestMappingHandlerAdapter(AbstractHandlerMethodAdapter).handle(HttpServletRequest, HttpServletResponse, Object)

RequestMappingHandlerAdapter.handleInternal(HttpServletRequest, HttpServletResponse, HandlerMethod)	

//调用处理器方法,执行请求,处理结果并且返回试图解析器
RequestMappingHandlerAdapter.invokeHandlerMethod(HttpServletRequest, HttpServletResponse, HandlerMethod)	

//调用请求并且处理结果
ServletInvocableHandlerMethod.invokeAndHandle(ServletWebRequest, ModelAndViewContainer, Object...)	

//1、调用请求
ServletInvocableHandlerMethod(InvocableHandlerMethod).invokeForRequest(NativeWebRequest, ModelAndViewContainer, Object...)
//1.1、解析传入参数
ServletInvocableHandlerMethod(InvocableHandlerMethod).getMethodArgumentValues(NativeWebRequest, ModelAndViewContainer, Object...)	
//1.1.1
HandlerMethodArgumentResolverComposite.resolveArgument(MethodParameter, ModelAndViewContainer, NativeWebRequest, WebDataBinderFactory) line: 121	
//1.1.2
RequestResponseBodyMethodProcessor.resolveArgument(MethodParameter, ModelAndViewContainer, NativeWebRequest, WebDataBinderFactory) line: 129	


//1.2、执行方法,返回结果
ServletInvocableHandlerMethod(InvocableHandlerMethod).doInvoke(Object...)

//处理返回结果
HandlerMethodReturnValueHandlerComposite.handleReturnValue(Object, MethodParameter, ModelAndViewContainer, NativeWebRequest)	
RequestResponseBodyMethodProcessor.handleReturnValue(Object, MethodParameter, ModelAndViewContainer, NativeWebRequest)	
RequestResponseBodyMethodProcessor(AbstractMessageConverterMethodProcessor).writeWithMessageConverters(T, MethodParameter, ServletServerHttpRequest, ServletServerHttpResponse)	
//调用实际序列化方法
FastJsonHttpMessageConverter.write(Object, Type, MediaType, HttpOutputMessage)	
org.springframework.http.converter.AbstractHttpMessageConverter.write(T, MediaType, HttpOutputMessage)
com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter.writeInternal(Object, HttpOutputMessage)

注意:作者使用springboot进行源码调试,因为版本问题有细微差别。

参考文章:https://www.cnblogs.com/canmeng-cn/p/9040395.html

四川乐山程序员联盟【571814743】,请入群交流学习。

 

 

相关文章: