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张图片

                                                                                   图片来自网络

如上图中(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.

 * 

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.  *

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】,请入群交流学习。

 

 

你可能感兴趣的:(java相关,spring,spring,boot)