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来渲染返回数据。

 

                                                                                   图片来自网络

如上图中(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】,请入群交流学习。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值