一、3W
- Why:原生Servlet操作麻烦》提升开发效率
- What:表述层和控制层各细分领域需要解决的问题全方位覆盖,提供全面解决方案
- How:统一的DispatcherServlet
二、初始化过程
1、加载WebApplicationContext(spring容器):ContextLoaderListener》initWebApplicationContext
2、DispatcherServlet初始化过程(SpringMVC容器):
initWebApplicationContext事项:
- 初始化WebApplicationContext>创建WebApplicationContext>DispatcherServlet初始化策略
三、执行流程
1、Spring MVC整体流程
2、DispatcherServlet调用组件处理源码分析
…》processRequest()>doService()>doDispatch()>processDispatchResult()
/*
mappedHandler:调用链
包含handler、interceptorList、interceptorIndex
handler:浏览器发送的请求所匹配的控制器方法
interceptorList:处理控制器方法的所有拦截器集合
interceptorIndex:拦截器索引,控制拦截器afterCompletion()的执行
*/
mappedHandler = getHandler(processedRequest);
// 通过控制器方法创建相应的处理器适配器,调用所对应的控制器方法
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 调用拦截器的preHandle()
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 由处理器适配器调用具体的控制器方法,最终获得ModelAndView对象
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
applyDefaultViewName(processedRequest, mv);
// 调用拦截器的postHandle()
mappedHandler.applyPostHandle(processedRequest, response, mv);
// 后续处理:处理模型数据和渲染视图
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
// 处理模型数据和渲染视图
render(mv, request, response);
// 调用拦截器的afterCompletion()
mappedHandler.triggerAfterCompletion(request, response, null);
四、解析、绑定/转换/验证
- doService:943, DispatcherServlet在向请求域中存一些数据。
- doDispatch:1040, DispatcherServlet (org.springframework.web.servlet)根据请求地址从处理器映射器中拿到要执行的handler,再拿到处理器适配器(HandlerAdapter)去执行Handler。
- handle:87, AbstractHandlerMethodAdapter (org.springframework.web.servlet.mvc.method)
- handleInternal:792, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)具体的处理类
- invokeHandlerMethod:878, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)大部分都是赋值
- returnValue = invokeAndHandle:105, ServletInvocableHandlerMethod 通过反射的方式调用指定的方法去执行此次请求
1). invokeForRequest:134, InvocableHandlerMethod
- Object[] args = getMethodArgumentValues:167, InvocableHandlerMethod 获取此次请求执行所需的参数
for(int i = 0; i < parameters.length; ++i) {循环 根据parameters数组中每一个参数的信息拿到参数值放到Object数组中。
args[i] = this.resolvers.resolveArgument:121, HandlerMethodArgumentResolverComposite (org.springframework.web.method.support)
HandlerMethodArgumentResolver resolver = this.getArgumentResolver(parameter);获取具体的解析器:存在多种(RequestResponseBody*、RequestParam*、ServletRequest*、RequestHeader*、PathVariable*等)
return resolver.resolveArgument:131, RequestResponseBodyMethodProcessor (org.springframework.web.servlet.mvc.method.annotation)具体的解析类去执行。
readWithMessageConverters:158, RequestResponseBodyMethodProcessor (org.springframework.web.servlet.mvc.method.annotation)
readWithMessageConverters:230, AbstractMessageConverterMethodArgumentResolver (org.springframework.web.servlet.mvc.method.annotation)
for (HttpMessageConverter<?> converter : this.messageConverters) {循环尝试多种转换器(根据contentType)
转换器:MappingJackson2*、ByteArray*、String*、MappingJackson2Xml*
-
return this.doInvoke(args); 拿到此次请求的参数后去执行具体的控制层中方法。
2). returnValueHandlers.handleReturnValue(returnValue 处理结果,与处理请求类似,循环尝试多种转换器
handleReturnValue:81, HandlerMethodReturnValueHandlerComposite
handleReturnValue:174, RequestResponseBodyMethodProcessor
writeWithMessageConverters:224, AbstractMessageConverterMethodProcessor
HttpMessageConverter接口有只有5个方法,根据MediaType处理;接收到请求时判断是否能读(canRead),能读则读(read);返回结果时判断是否能写(canWrite),能写则写(write)。
四、其它
- HandlerAdapter、HandlerMapping
- 拦截器 :配置》注解
- 异常处理 :配置》注解
- 配置类替换*.xml的方式
五、获取请求参数几种方式
3.1 通过ServletAPI获取请求参数
3.2 通过控制器方法的形参获取请求参数
参数名要求一致
3.3 @RequestParam、@RequestHeader、@CookieValue 、@PathVariable注解
@RequestHeader注解 和 @CookieValue注解 的属性和用法跟@RequestParam相同,不同的是
@RequestHeader注解是将请求头信息和控制器方法的形参创建映射关系
@CookieValue注解是将cookie数据和控制器方法的形参创建映射关系
3.4 通过POJO获取请求参数
3.5 @RequestBody 注解