打断点分析
分析任何源码时,如果一开始不清楚类的继承结构,具体执行流程,都可以通过打断点的方式获得调用栈,然后就知道具体如何执行。
在上面打断点后,具体调用栈如下
test:51, DemoController (com.lagou.edu.controller)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
doInvoke:190, InvocableHandlerMethod (org.springframework.web.method.support)
invokeForRequest:138, InvocableHandlerMethod (org.springframework.web.method.support)
invokeAndHandle:105, ServletInvocableHandlerMethod (org.springframework.web.servlet.mvc.method.annotation)
invokeHandlerMethod:893, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)
handleInternal:798, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)
handle:87, AbstractHandlerMethodAdapter (org.springframework.web.servlet.mvc.method)
doDispatch:1040, DispatcherServlet (org.springframework.web.servlet)
doService:943, DispatcherServlet (org.springframework.web.servlet)
processRequest:1006, FrameworkServlet (org.springframework.web.servlet)
doGet:898, FrameworkServlet (org.springframework.web.servlet)
service:621, HttpServlet (javax.servlet.http)
service:883, FrameworkServlet (org.springframework.web.servlet)
service:728, HttpServlet (javax.servlet.http)
internalDoFilter:305, ApplicationFilterChain (org.apache.catalina.core)
doFilter:210, ApplicationFilterChain (org.apache.catalina.core)
doFilter:51, WsFilter (org.apache.tomcat.websocket.server)
internalDoFilter:243, ApplicationFilterChain (org.apache.catalina.core)
doFilter:210, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:201, CharacterEncodingFilter (org.springframework.web.filter)
doFilter:119, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:243, ApplicationFilterChain (org.apache.catalina.core)
doFilter:210, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:94, HiddenHttpMethodFilter (org.springframework.web.filter)
doFilter:119, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:243, ApplicationFilterChain (org.apache.catalina.core)
doFilter:210, ApplicationFilterChain (org.apache.catalina.core)
invoke:222, StandardWrapperValve (org.apache.catalina.core)
invoke:123, StandardContextValve (org.apache.catalina.core)
invoke:502, AuthenticatorBase (org.apache.catalina.authenticator)
invoke:171, StandardHostValve (org.apache.catalina.core)
invoke:100, ErrorReportValve (org.apache.catalina.valves)
invoke:953, AccessLogValve (org.apache.catalina.valves)
invoke:118, StandardEngineValve (org.apache.catalina.core)
service:408, CoyoteAdapter (org.apache.catalina.connector)
process:1041, AbstractHttp11Processor (org.apache.coyote.http11)
process:603, AbstractProtocol$AbstractConnectionHandler (org.apache.coyote)
run:312, JIoEndpoint$SocketProcessor (org.apache.tomcat.util.net)
runWorker:1142, ThreadPoolExecutor (java.util.concurrent)
run:617, ThreadPoolExecutor$Worker (java.util.concurrent)
run:745, Thread (java.lang)
从上面的调用栈可以分析得知一个关键点,就是从HttpServlet.service方法开始执行(更下面的细节可以忽略)
最终调用DispatcherServlet.doDispatch开始真正的请求转发,大概执行流程就是如下
- HttpServlet.service
- FrameworkServlet.service
- HttpServlet.service
- FrameworkServlet.doGet
- FrameworkServlet.processRequest
- DispatcherServlet.doService
- DispatcherServlet.doDispatch
- 下面开始分析具体流程
HttpServlet.service
主要功能是根据不同的请求方式,调用不同的分支方法,不负责具体逻辑
FrameworkServlet.service
该方法重写了父类的service方法,单独用于处理HttpMethod.PATCH分支,其他情况调用父类的service方法
从上面就可以看出之前的调用栈为什么是HttpServlet.service - -> FrameworkServlet.service --> HttpServlet.service
因为FrameworkServlet虽然你实现HttpServlet的service方法,但是只处理了HttpMethod.PATCH这种请求方式,其他的依然由父类实现
FrameworkServlet.doGet
- 没有业务逻辑,直接调用内部的processRequest方法
- 此类的doGet doPost doPut doDelete doOptions 等等方法都是调用processRequest
FrameworkServlet.processRequest
- 获取上一个请求保存的LocaleContext
- 建立新的LocaleContext
- 获取上一个请求保存的RequestAttributes
- 建立新的RequestAttributes
- 新的RequestAttributes设置进LocalThread
- 调用doService处理请求,此类中是个抽象方法,由子类DispatcherServlet实现
DispatcherServlet.doService
主要负责设置request的相关属性,真正的请求转发由doDispatch实现
DispatcherServlet.doDispatch
这个才是最终的请求转发处理流程,主要流程有以下几个方面
- 文件上传解析,如果请求类型是multipart将通过MultipartResolver进行文件上传解析
- 通过HandlerMapping,获取请求映射到处理器HandlerExecutionChain,它包括一个处理器、多个HandlerInterceptor拦截器,处理请求时,先经过拦截器链处理完成后,才通过Handler处理请求
- 根据Handler获取处理请求的处理器适配器 HandlerAdapter,因为不同的请求处理方式可能不一样,通过适配器封装成统一的处理方式
- applyPreHandle 调用HandlerExecutionChain的interceptor 执行请求前置处理
- 实际处理器处理请求,返回结果视图对象
- applyPostHandle调用HandlerExecutionChain的interceptor 执行请求后置处理
- 最终调用HandlerInterceptor的afterCompletion 方法
总结
以上就是请求的大概处理流程,大致流程如下,每一个分支流程的细节会在后面的文章详细分析。
- 如果是文件上传请求,处理文件上传
- 先根据url获取请求处理器,
- 获取处理器适配,
- 真正的处理请求并返回结果视图,
- 在处理请求的前后有拦截器的前置和后置处理,
- 最后调用拦截器的afterCompletion方法,不管有没有异常。