SpringBoot请求参数解析全过程
1、完整的请求过程
上述是SpringMVC完整的请求过程,经过三次TCP/IP的握⼿之后来到请求。⽽请求参数的解析主要是在第5、6步完成的。
前⾯⼏个步骤的过程可以参考,下⾯主要介绍请求参数是如何解析获得的。
2、DispatcherServlet整体调度
public class DispatcherServlet extends FrameworkServlet {
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response)throws Exception {
springboot是啥...
try{
doDispatch(request, response);
}
finally{
...
}
}
protected void doDispatch(HttpServletRequest request, HttpServletResponse response)throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed =false;//判断是否是⽂件上传
try{
ModelAndView mv = null;//响应的视图
Exception dispatchException = null;
try{
// 1. 检查是否是⽂件上传
processedRequest =checkMultipart(request);
multipartRequestParsed =(processedRequest != request);
// 2. 到映射器处理器MappingHandler
mappedHandler =getHandler(processedRequest);
if(mappedHandler == null){
noHandlerFound(processedRequest, response);
return;
}
// 3. 到处理器的适配器
HandlerAdapter ha =Handler());
// 4. 的前置PreHandle⽅法执⾏
if(!mappedHandler.applyPreHandle(processedRequest, response)){
return;
}
// 5. 获取参数、执⾏controller
mv = ha.handle(processedRequest, response, Handler());
// 6. 使⽤默认的视图名进⾏封装(⾸页)
applyDefaultViewName(processedRequest, mv);
// 7. 执⾏的后置postHandle⽅法
mappedHandler.applyPostHandle(processedRequest, response, mv);
// 8. 对执⾏结果的参数、视图,内部执⾏的afterCompletion⽅法
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
.
..
...
}
1. 前⾯⼏个步骤没啥⽤,主要是第(2)步到Controller.Method⽅法
2. 然后开始为这个Method⽅法到合适的适配器进⾏处理,SpringBoot⼀启动就⾃动配置了5个映射器,4个适配器。
3. 最后参数解析、Controller.Method的执⾏都在第(5)步完成。
3、RequestMappingHandlerAdapter适配器先⾏⼀步
这⾥需要注意适配器是不唯⼀的,但是他们都是AbstractHandlerMethodAdapter抽象类的实现,这⾥以@RequestMapping标注的⽅法为事例。
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
implements BeanFactoryAware, InitializingBean {
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod)throws Exception {
ModelAndView mav;
checkRequest(request);
// Execute invokeHandlerMethod in synchronized block if required.
if(this.synchronizeOnSession){
HttpSession session = Session(false);
if(session != null){
Object mutex = SessionMutex(session);
synchronized(mutex){
mav =invokeHandlerMethod(request, response, handlerMethod);
}
}
else{
// No HttpSession available -> no mutex necessary
mav =invokeHandlerMethod(request, response, handlerMethod);
}
}
else{
// No synchronization on session demanded
mav =invokeHandlerMethod(request, response, handlerMethod);
}
....
return mav;
}
@Nullable
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod)throws Exception {
ServletWebRequest webRequest =new ServletWebRequest(request, response);
try{
...
...
// 1. 创建⼀个请求 - 处理对象
ServletInvocableHandlerMethod invocableMethod =createInvocableHandlerMethod(handlerMethod);
// 2. 设置参数解析器(核⼼)
if(this.argumentResolvers != null){
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
}
// 3. 设置返回值处理器(Model、ModelAndView、@ResponseBody等等)
urnValueHandlers != null){
invocableMethod.urnValueHandlers);
}
// 这⾥还有⼀系列的初始化东西,在这⾥省略。
...
// 4. 执⾏和处理。
invocableMethod.invokeAndHandle(webRequest, mavContainer);
if(asyncManager.isConcurrentHandlingStarted()){
return null;
}
return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally{
}
}
}
1. 可以看到核⼼⽅法invokeHandlerMethod就是这个,但是这⾥经过了⼀系列的针对Session有效的验证。
2. 到这⾥还没有进⾏参数的解析,只是配置了默认情况下所有的参数解析器(27个左右)和 返回值处理器(15个左右)
3. 中间还有⼀系列的东西需要配置、初始化等等,最后再交给invokeAndHandle(webRequest, mavContainer)⽅法去完成处理。
4、ServletInvocableHandlerMethod
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer providedArgs)throws Exception { // 1. 获取返回值
Object returnValue =invokeForRequest(webRequest, mavContainer, providedArgs);
// 2. 设置响应状态
setResponseStatus(webRequest);
}
}
1. 可以看到第(2)步已经开始进⾏响应状态的设置,所以可以猜到到这⾥请求已经结束了但是没有响
应。
2. 根据上⾯的推测,那么参数解析、执⾏都藏匿在invokeForRequest()⽅法中。
5、InvocableHandlerMethod
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论