@@ -409,7 +409,7 @@ initFlashMapManager方法会向容器注册SessionFlashMapManager对象,类图
409409
410410## HandlerMapping初始化
411411
412- 此接口用以根据请求的URL寻找合适的处理器。从前面配置解析一节可以看出,我们的容器中有三个HandlerMapping实现,下面进行分别说明 。
412+ 此接口用以根据请求的URL寻找合适的处理器。从前面配置解析一节可以看出,我们的容器中有三个HandlerMapping实现,下面以RequestMappingHandlerMapping位代表进行说明 。
413413
414414### RequestMappingHandlerMapping
415415
@@ -435,6 +435,7 @@ protected void initHandlerMethods() {
435435 }
436436 }
437437 }
438+ // 空实现
438439 handlerMethodsInitialized(getHandlerMethods());
439440}
440441```
@@ -453,6 +454,7 @@ detectHandlerMethods方法将反射遍历类中所有的public方法,如果方
453454
454455``` java
455456public void register(T mapping, Object handler, Method method) {
457+ // 包装bean和方法
456458 HandlerMethod handlerMethod = createHandlerMethod(handler, method);
457459 this . mappingLookup. put(mapping, handlerMethod);
458460 List<String > directUrls = getDirectUrls(mapping);
@@ -472,7 +474,113 @@ public void register(T mapping, Object handler, Method method) {
472474}
473475```
474476
477+ mapping其实是一个RequestMappingInfo对象,可以将其看做是** @RequestMapping 注解各种属性的一个封装** 。最终由RequestMappingInfo.createRequestMappingInfo方法创建,源码:
475478
479+ ``` java
480+ protected RequestMappingInfo createRequestMappingInfo(
481+ RequestMapping requestMapping, RequestCondition<?> customCondition) {
482+ return RequestMappingInfo
483+ .paths(resolveEmbeddedValuesInPatterns(requestMapping. path()))
484+ .methods(requestMapping. method())
485+ .params(requestMapping. params())
486+ .headers(requestMapping. headers())
487+ .consumes(requestMapping. consumes())
488+ .produces(requestMapping. produces())
489+ .mappingName(requestMapping. name())
490+ .customCondition(customCondition)
491+ .options(this . config)
492+ .build();
493+ }
494+ ```
495+
496+ 这就很明显了,具体每种属性什么意义可以参考@RequestMapping 源码。
497+
498+ register方法中urlLookup其实就是将paths属性中的每个path都与处理器做映射。
499+
500+ getNamingStrategy方法得到的是一个HandlerMethodMappingNamingStrategy接口的实例,此接口用以根据HandlerMethod得到一个名字,类图:
501+
502+ ![ HandlerMethodMappingNamingStrategy类图] ( images/HandlerMethodMappingNamingStrategy.jpg )
503+
504+ 比如对于我们的控制器,SimpleController.echo方法,最终得到的名字将是SC#echo。
505+
506+ #### 跨域请求
507+
508+ spring-mvc自4.2开启加入了跨域请求Cors的支持,主要有两种配置方式:
509+
510+ - xml:
511+
512+ ``` xml
513+ <mvc : cors >
514+ <mvc : mapping path =" " />
515+ </mvc : cors >
516+ ```
517+
518+ - @CrossOrigin 注解。
519+
520+ Cors的原理可以参考:
521+
522+ [ 探讨跨域请求资源的几种方式] ( http://www.cnblogs.com/dojo-lzz/p/4265637.html )
523+
524+ 而initCorsConfiguration方法的作用便是将@CrossOrigin 注解的各种属性封装在CorsConfiguration中。
525+
526+ ## HandlerAdapter初始化
527+
528+ 同样,我们以RequestMappingHandlerAdapter为例进行说明,类图:
529+
530+ ![ RequestMappingHandlerAdapter类图] ( images/RequestMappingHandlerAdapter.jpg )
531+
532+ 显然,入口在afterPropertiesSet方法:
533+
534+ ``` java
535+ @Override
536+ public void afterPropertiesSet() {
537+ // Do this first, it may add ResponseBody advice beans
538+ initControllerAdviceCache();
539+ if (this . argumentResolvers == null ) {
540+ List<HandlerMethodArgumentResolver > resolvers = getDefaultArgumentResolvers();
541+ this . argumentResolvers = new HandlerMethodArgumentResolverComposite ()
542+ .addResolvers(resolvers);
543+ }
544+ if (this . initBinderArgumentResolvers == null ) {
545+ List<HandlerMethodArgumentResolver > resolvers = getDefaultInitBinderArgumentResolvers();
546+ this . initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite ()
547+ .addResolvers(resolvers);
548+ }
549+ if (this . returnValueHandlers == null ) {
550+ List<HandlerMethodReturnValueHandler > handlers = getDefaultReturnValueHandlers();
551+ this . returnValueHandlers = new HandlerMethodReturnValueHandlerComposite ()
552+ .addHandlers(handlers);
553+ }
554+ }
555+ ```
556+
557+ ### @ControllerAdvice
558+
559+ initControllerAdviceCache方法用以解析并存储标注了@ControllerAdvice 的bean,这东西是干什么的参考:
560+
561+ [ Spring3.2新注解@ControllerAdvice ] ( http://jinnianshilongnian.iteye.com/blog/1866350 )
562+
563+ ### 参数解析器
564+
565+ HandlerMethodArgumentResolver即参数解析器,负责从request中解析、得到Controller方法所需的参数。afterPropertiesSet方法设置了一组默认的解析器。具体是哪些参考getDefaultArgumentResolvers方法。类图:
566+
567+ ![ HandlerMethodArgumentResolver类图] ( images/HandlerMethodArgumentResolver.jpg )
568+
569+ ### @InitBinder 支持
570+
571+ 此注解定义的其实是自定义类型转换器。使用方法参考:
572+
573+ [ springMVC @initBinder 使用] ( http://blog.csdn.net/songzaiblog/article/details/49757253 )
574+
575+ getDefaultInitBinderArgumentResolvers返回了一组默认使用的转换器,不过其实这里的转换器和上面的参数解析器其实是一个类型的,这里留个坑。
576+
577+ ### 返回结果解析器
578+
579+ HandlerMethodReturnValueHandler接口用以处理方法调用(Controller方法)的返回值,类图:
580+
581+ ![ HandlerMethodReturnValueHandler类图] ( images/HandlerMethodReturnValueHandler.jpg )
582+
583+ getDefaultReturnValueHandlers方法便返回了一坨这东西。
476584
477585# 请求响应
478586
@@ -507,5 +615,53 @@ Spring MVC会在请求分发之前进行上下文的准备工作,含两部分:
507615
508616## 请求分发
509617
618+ DispatcherServlet.doDispatch简略版源码:
619+
620+ ``` java
621+ protected void doDispatch(HttpServletRequest request, HttpServletResponse response) {
622+ HandlerExecutionChain mappedHandler = getHandler(processedRequest);
623+ HandlerAdapter ha = getHandlerAdapter(mappedHandler. getHandler());
624+ mv = ha. handle(processedRequest, response, mappedHandler. getHandler());
625+ applyDefaultViewName(processedRequest, mv);
626+ mappedHandler. applyPostHandle(processedRequest, response, mv);
627+ processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
628+ }
629+ ```
510630
631+ ### 处理器查找
632+
633+ 即为请求寻找合适的Controller的过程。DispatcherServlet.getHandler:
634+
635+ ``` java
636+ protected HandlerExecutionChain getHandler(HttpServletRequest request) {
637+ for (HandlerMapping hm : this . handlerMappings) {
638+ HandlerExecutionChain handler = hm. getHandler(request);
639+ if (handler != null ) {
640+ return handler;
641+ }
642+ }
643+ return null ;
644+ }
645+ ```
646+
647+ 从这里可以看出,寻找处理器实际上委托给HandlerMapping实现,寻找的过程便是遍历所有的HandlerMapping进行查找,** 一旦找到,那么不再继续进行遍历** 。也就是说HandlerMapping之间有优先级的概念,而根据AnnotationDrivenBeanDefinitionParser的注释,RequestMappingHandlerMapping其实有最高的优先级。
648+
649+ AbstractHandlerMapping.getHandler:
650+
651+ ``` java
652+ @Override
653+ public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
654+ Object handler = getHandlerInternal(request);
655+ HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
656+ if (CorsUtils . isCorsRequest(request)) {
657+ CorsConfiguration globalConfig = this . corsConfigSource. getCorsConfiguration(request);
658+ CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
659+ CorsConfiguration config = (globalConfig != null ?
660+ globalConfig. combine(handlerConfig) : handlerConfig);
661+ executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
662+ }
663+ return executionChain;
664+ }
665+ ```
511666
667+ getHandlerInternal方法便是根据url进行查找的过程,可以参见MVC初始化-HandlerMapping初始化一节。下面重点是执行链的生成。
0 commit comments