美文网首页
SpringMVC 4.3 源码分析之 HandlerAdapt

SpringMVC 4.3 源码分析之 HandlerAdapt

作者: 爱吃鱼的KK | 来源:发表于2018-03-06 00:30 被阅读326次
1. HandlerAdapter 概述

在 SpringMVC 中Handler可以是各种类型的类, 而DispatcherServlet肯定需要对 handler 进行激活, 所以这时需要一个适配类, 将各种handler适配成可以执行的类, 这时 HandlerAdapter就出现了; 主要代码如下

// Handler 处理适配器, 适配不同的 Handler
public interface HandlerAdapter {

    /** HandlerAdapter 是否支持这个 handler <-- 通常是检查这个 handler 是否是某一类
     *  如
     *    SimpleServletHandlerAdapter      -->  javax.servlet.Servlet
     *    SimpleControllerHandlerAdapter   -->  org.springframework.web.servlet.mvc.Controller
     *    HttpRequestHandlerAdapter        -->  org.springframework.web.HttpRequestHandler
     *    RequestMappingHandlerAdapter     -->  handler instanceof HandlerMethod
     * PS: 整个 DispatcherServlet 的入口是 HandlerAdapter.handle, 但其中真正执行的可能是  Servlet, Controller, HttpRequestHandler, HandlerMethod; 这时就需要 HandlerAdapter 来进行适配操作
     */
    boolean supports(Object handler);

    // 处理 HttpServletRequest 的入口方法
    ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;

    // Http 请求中的lastModifiedTime, 默认 -1
    long getLastModified(HttpServletRequest request, Object handler);
}

而 HandlerAdapter具有如下子类:


HandlerAdapter.png
1. SimpleServletHandlerAdapter:    适配实现 Servlet 接口的 Handler, 默认调用其 service 方法
2. SimpleControllerHandlerAdapter: 适配实现 Controller 接口的 Handler, 默认调用其 handleRequest 方法
3. HttpRequestHandlerAdapter:      适配实现 HttpRequestHandler 接口的 Handler, 默认调用其 handleRequest 方法
4. RequestMappingHandlerAdapter:   适配被@RequestMapping注释的方式, 一般都是解析一个一个参数, 并且通过反射进行激活

PS: 上面几个子类中只有 RequestMappingHandlerAdapter有复杂的逻辑, 也是使用最频繁的 HandlerAdapter

2. HandlerAdapter 的子类 SimpleServletHandlerAdapter

SimpleServletHandlerAdapter 适配 Servlet 调用的HandlerAdapter, 代码如下:

public boolean supports(Object handler) {
    return (handler instanceof Servlet); // 只要是个 Servlet, 就支持
}

public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception {
    // 直接调用 Servlet 的 service 接口返回
    ((Servlet) handler).service(request, response);
    return null;
}
3. HandlerAdapter 的子类 SimpleControllerHandlerAdapter

SimpleControllerHandlerAdapter 适配 Controller 接口的 HandlerAdapter, 代码如下:

public boolean supports(Object handler) {
    // 判断将要调用的 handler 是不是 Controller
    return (handler instanceof Controller);
}

public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception {
    // 调用 Controller 接口类的接口方法 handleRequest() 方法直接响应给前端
    return ((Controller) handler).handleRequest(request, response);
}
4. HandlerAdapter 的子类 HttpRequestHandlerAdapter

HttpRequestHandlerAdapter 适配 HttpRequestHandler 的 HandlerAdapter, 代码如下:

public boolean supports(Object handler) {
    // 判断将要调用的 handler 是不是 HttpRequestHandler
    return (handler instanceof HttpRequestHandler);
}
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    // 调用 HttpRequestHandler 接口类的接口方法 handleRequest() 方法直接响应给前端
    ((HttpRequestHandler) handler).handleRequest(request, response);
    return null;
}
5. RequestMappingHandlerAdapter 概述

RequestMappingHandlerAdapter 将被@RequestMapping注释修饰的方法封装成ServletInvocableHandlerMethod, 并进行激活, 其主要有如下组件:

// 参数解析器 HandlerMethodArgumentResolver, 比如 RequestResponseBodyMethodProcessor
private List<HandlerMethodArgumentResolver> customArgumentResolvers;
// 组合模式的参数解析器
private HandlerMethodArgumentResolverComposite argumentResolvers;
// initBinderArgumentResolvers 的 参数解析器
private HandlerMethodArgumentResolverComposite initBinderArgumentResolvers;
// 返回值处理器 比如 RequestResponseBodyMethodProcessor
private List<HandlerMethodReturnValueHandler> customReturnValueHandlers;
// 组合模式的 返回值解析器
private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
// ModelAndView 解析器
private List<ModelAndViewResolver> modelAndViewResolvers;
// 内容解析器 <-- 一般通过 HttpServletRequest 获取 MediaType
private ContentNegotiationManager contentNegotiationManager = new ContentNegotiationManager();
// HttpMessageConverter 转换器 --> 比如 form 表单的 FormHttpMessageConverter, Json 对应的 MappingJackson2HttpMessageConverter
private List<HttpMessageConverter<?>> messageConverters;
// request|response 对应的 Advice <-- 其实就像 AOP 中的 Advice的概念
private List<Object> requestResponseBodyAdvice = new ArrayList<Object>();

// 是否给予 Session 同步请求
private boolean synchronizeOnSession = false;
// Session 中存储|获取器
private SessionAttributeStore sessionAttributeStore = new DefaultSessionAttributeStore();
// 方法解析器, 默认使用 ASM | 反射来获取 <- 反射针对 Java 8
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
// BeanFactory
private ConfigurableBeanFactory beanFactory;

上面每个组件都有其对应的作用: 其中主要有 HandlerMethod 的参数解析器HandlerMethodArgumentResolver, 返回值处理器 HandlerMethodReturnValueHandler, 请求内容的格式解析器 ContentNegotiationManager, 知道了请求内容的格式,这时需要将字符串转为对应方法参数的参数转换器 HttpMessageConverter, Controller增强器 requestResponseBodyAdvice(这其实就像Aop中的Advice), 再者我们可以通过 @RequestParam 获取指定名称的参数内容, 所以还需要一个参数名称获取器 ParameterNameDiscoverer(有基于ASM, 有基于反射机制); 首先我们来看一下 RequestMappingHandlerAdapter 的初始化, 对应的初始化入口在 InitializingBean.afterPropertiesSet 中进行:

public void afterPropertiesSet() {
    // Do this first, it may add ResponseBody advice beans
    // 初始化 被 @ControllerAdvice 修饰的类 <-- 这是一个 Controller 增强器, 主要是通过 @ModelAttribute, @InitBinder 注解
    initControllerAdviceCache(); 
    // 初始化 HandlerMethodArgumentResolver, 最后封装成 HandlerMethodArgumentResolverComposite <-- 组合模式
    if (this.argumentResolvers == null) {
        List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
        this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);  // Spring 里面 composite 模式 的提现
    }
    // 初始化 参数绑定方法的参数解决器  <-- 这个平时用得比较少
    if (this.initBinderArgumentResolvers == null) { 
        List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
        this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
    }
    // 初始化 HandlerMethodReturnValueHandler 比如 -> RequestResponseBodyMethodProcessor
    if (this.returnValueHandlers == null) { 
        List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
        this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
    }
}

其上主要还是做了:

1. 初始化 被 @ControllerAdvice 修饰的类 <-- 这是一个 Controller 增强器, 主要是通过 @ModelAttribute, @InitBinder 注解
    1.1 收集 ApplicationContext 中所有被 @ControllerAdvice 注解修饰的 Bean, 并封装成 ControllerAdviceBean
    1.2 获取 Bean 上被 @ModelAttribute @RequestMapping 修饰的方法
    1.3 将被 @ModelAttribute @RequestMapping 修饰的方法 放入 modelAttributeAdviceCache
    1.4 获取 Bean 上被 @InitBinder 注解的方法, 并放入 initBinderAdviceCache 中
    1.5 若是 RequestBodyAdvice 子类, 则加入 requestResponseBodyAdviceBeans
    1.6 若是 RequestBodyAdvice 子类, 则加入 requestResponseBodyAdviceBeans
2. 初始化 HandlerMethodArgumentResolver(这里主要分成 基于注解的参数解决器, 基于参数类型的解决器), 最后封装成 HandlerMethodArgumentResolverComposite <-- 组合模式
3. 初始化 参数绑定方法的参数解决器(这里主要分成 基于注解的参数解决器, 基于参数类型的解决器), 最后封装成 HandlerMethodArgumentResolverComposite <-- 组合模式  <-- 这个平时用得比较少
4. 初始化 HandlerMethodReturnValueHandler(这里主要分成 基于注解的参数解决器, 单|多个目的的解决器) 比如 -> RequestResponseBodyMethodProcessor, 最后封装成 HandlerMethodReturnValueHandlerComposite <-- 组合模式

上面的参数解析器其实在 SpringMVC 中扮演着非常重要的角色, 也是 SpringMVC 扩展点的一个体现机制, 主要用到了如下的解析器:

private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() { // 获取默认的 HandlerMethodArgumentResolver
    List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>();
    // 基于注解的参数解析 <-- 解析的数据来源主要是 HttpServletRequest | ModelAndViewContainer
    // Annotation-based argument resolution
    // 解析被注解 @RequestParam, @RequestPart 修饰的参数, 数据的获取通过 HttpServletRequest.getParameterValues
    resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
    // 解析被注解 @RequestParam 修饰, 且类型是 Map 的参数, 数据的获取通过 HttpServletRequest.getParameterMap
    resolvers.add(new RequestParamMapMethodArgumentResolver());
    // 解析被注解 @PathVariable 修饰, 数据的获取通过 uriTemplateVars, 而 uriTemplateVars 却是通过 RequestMappingInfoHandlerMapping.handleMatch 生成, 其实就是 uri 中映射出的 key <-> value
    resolvers.add(new PathVariableMethodArgumentResolver());
    // 解析被注解 @PathVariable 修饰 且数据类型是 Map, 数据的获取通过 uriTemplateVars, 而 uriTemplateVars 却是通过 RequestMappingInfoHandlerMapping.handleMatch 生成, 其实就是 uri 中映射出的 key <-> value
    resolvers.add(new PathVariableMapMethodArgumentResolver());
    // 解析被注解 @MatrixVariable 修饰, 数据的获取通过 URI提取了;后存储的 uri template 变量值
    resolvers.add(new MatrixVariableMethodArgumentResolver());
    // 解析被注解 @MatrixVariable 修饰 且数据类型是 Map, 数据的获取通过 URI提取了;后存储的 uri template 变量值
    resolvers.add(new MatrixVariableMapMethodArgumentResolver());
    // 解析被注解 @ModelAttribute 修饰, 且类型是 Map 的参数, 数据的获取通过 ModelAndViewContainer 获取, 通过 DataBinder 进行绑定
    resolvers.add(new ServletModelAttributeMethodProcessor(false));
    // 解析被注解 @RequestBody 修饰的参数, 以及被@ResponseBody修饰的返回值, 数据的获取通过 HttpServletRequest 获取, 根据 MediaType通过HttpMessageConverter转换成对应的格式, 在处理返回值时 也是通过 MediaType 选择合适HttpMessageConverter, 进行转换格式, 并输出
    resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
    // 解析被注解 @RequestPart 修饰, 数据的获取通过 HttpServletRequest.getParts()
    resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice));
    // 解析被注解 @RequestHeader 修饰, 数据的获取通过 HttpServletRequest.getHeaderValues()
    resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
    // 解析被注解 @RequestHeader 修饰且参数类型是 Map, 数据的获取通过 HttpServletRequest.getHeaderValues()
    resolvers.add(new RequestHeaderMapMethodArgumentResolver());
    // 解析被注解 @CookieValue 修饰, 数据的获取通过 HttpServletRequest.getCookies()
    resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
    // 解析被注解 @Value 修饰, 数据在这里没有解析
    resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
    // 解析被注解 @SessionAttribute 修饰, 数据的获取通过 HttpServletRequest.getAttribute(name, RequestAttributes.SCOPE_SESSION)
    resolvers.add(new SessionAttributeMethodArgumentResolver());
    // 解析被注解 @RequestAttribute 修饰, 数据的获取通过 HttpServletRequest.getAttribute(name, RequestAttributes.SCOPE_REQUEST)
    resolvers.add(new RequestAttributeMethodArgumentResolver());

    // Type-based argument resolution
    // 解析固定类型参数(比如: ServletRequest, HttpSession, InputStream 等), 参数的数据获取还是通过 HttpServletRequest
    resolvers.add(new ServletRequestMethodArgumentResolver());
    // 解析固定类型参数(比如: ServletResponse, OutputStream等), 参数的数据获取还是通过 HttpServletResponse
    resolvers.add(new ServletResponseMethodArgumentResolver());
    // 解析固定类型参数(比如: HttpEntity, RequestEntity 等), 参数的数据获取还是通过 HttpServletRequest
    resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
    // 解析固定类型参数(比如: RedirectAttributes), 参数的数据获取还是通过 HttpServletResponse
    resolvers.add(new RedirectAttributesMethodArgumentResolver());
    // 解析固定类型参数(比如: Model等), 参数的数据获取通过 ModelAndViewContainer
    resolvers.add(new ModelMethodProcessor());
    // 解析固定类型参数(比如: Model等), 参数的数据获取通过 ModelAndViewContainer
    resolvers.add(new MapMethodProcessor());
    // 解析固定类型参数(比如: Errors), 参数的数据获取通过 ModelAndViewContainer
    resolvers.add(new ErrorsMethodArgumentResolver());
    // 解析固定类型参数(比如: SessionStatus), 参数的数据获取通过 ModelAndViewContainer
    resolvers.add(new SessionStatusMethodArgumentResolver());
    // 解析固定类型参数(比如: UriComponentsBuilder), 参数的数据获取通过 HttpServletRequest
    resolvers.add(new UriComponentsBuilderMethodArgumentResolver());
    // Custom arguments
    if (getCustomArgumentResolvers() != null) {
        resolvers.addAll(getCustomArgumentResolvers());
    }
    // Catch-all
    resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
    resolvers.add(new ServletModelAttributeMethodProcessor(true));
    return resolvers;
}

上面的解析器主要分成基于注解, 基于参数类型, 与自定义的参数解析器(PS: 大体上的数据来源是 HttpServletRequest的 header|body 中的属性, ModelAndViewContainer)! 然后就是处理返回值的处理器:

private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
    List<HandlerMethodReturnValueHandler> handlers = new ArrayList<HandlerMethodReturnValueHandler>();

    // Single-purpose return value types
    // 支持 ModelAndView 类型的 HandlerMethodReturnValueHandler, 最后将数据写入 ModelAndViewContainer
    handlers.add(new ModelAndViewMethodReturnValueHandler());
    // 支持 Map 类型的 HandlerMethodReturnValueHandler, 最后将数据写入 ModelAndViewContainer
    handlers.add(new ModelMethodProcessor());
    // 支持 View 类型的 HandlerMethodReturnValueHandler, 最后将数据写入 ModelAndViewContainer
    handlers.add(new ViewMethodReturnValueHandler());
    // 支持 ResponseEntity 类型的 HandlerMethodReturnValueHandler, 最后将数据写入 HttpServletResponse 的数据流中 OutputStream
    handlers.add(new ResponseBodyEmitterReturnValueHandler(getMessageConverters()));
    // 支持 ResponseEntity | StreamingResponseBody 类型的 HandlerMethodReturnValueHandler, 最后将数据写入 HttpServletResponse 的数据流中 OutputStream
    handlers.add(new StreamingResponseBodyReturnValueHandler());
    // 支持 HttpEntity | !RequestEntity 类型的 HandlerMethodReturnValueHandler, 最后将数据写入 HttpServletResponse 的数据流中 OutputStream
    handlers.add(new HttpEntityMethodProcessor(getMessageConverters(),this.contentNegotiationManager, this.requestResponseBodyAdvice));
    // 支持 HttpHeaders 类型的 HandlerMethodReturnValueHandler, 最后将数据写入 HttpServletResponse 的数据头部
    handlers.add(new HttpHeadersReturnValueHandler());
    // 支持 Callable 类型的 HandlerMethodReturnValueHandler
    handlers.add(new CallableMethodReturnValueHandler());
    handlers.add(new DeferredResultMethodReturnValueHandler());
    // 支持 WebAsyncTask 类型的 HandlerMethodReturnValueHandler
    handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));

    // Annotation-based return value types
    // 将数据加入 ModelAndViewContainer 的 HandlerMethodReturnValueHandler
    handlers.add(new ModelAttributeMethodProcessor(false));
    // 返回值被 ResponseBody 修饰的返回值, 并且根据 MediaType 通过 HttpMessageConverter 转化后进行写入数据流中
    handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(),this.contentNegotiationManager, this.requestResponseBodyAdvice));

    // Multi-purpose return value types
    // 支持返回值为 CharSequence 类型, 设置 ModelAndViewContainer.setViewName
    handlers.add(new ViewNameMethodReturnValueHandler());
    // 支持返回值为 Map, 并将结果设置到 ModelAndViewContainer
    handlers.add(new MapMethodProcessor());
    // Custom return value types
    if (getCustomReturnValueHandlers() != null) {
        handlers.addAll(getCustomReturnValueHandlers());
    }
    // Catch-all
    if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) {
        handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers()));
    }
    else {
        handlers.add(new ModelAttributeMethodProcessor(true));
    }
    return handlers;
}

在有了这些工具类后, 我们就可以完成AbstractHandlerMethodAdapter中定义的抽象方法handleInternal, 在 handleInternal 中主要进行了并发的控制(并发的粒度是 HttpSession), 而正真的方法激活交给了 ServletInvocableHandlerMethod, 对 ServletInvocableHandlerMethod 的初始化在 invokeHandlerMethod 中:

protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
        HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
    // 构建 ServletWebRequest <-- 主要由 HttpServletRequest, HttpServletResponse
    ServletWebRequest webRequest = new ServletWebRequest(request, response);
    try {
        // 构建 DataBinder 工厂
        WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
        // binderFactory 中存储着被 @InitBinder, @ModelAttribute 修饰的方法 <- 最终包裹成 InvocableHandlerMethod
        ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
        // 构建一个 ServletInvocableHandlerMethod
        ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
        // 设置方法参数解析器 HandlerMethodArgumentValueResolver
        invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
        // 返回值处理器 HandlerMethodReturnValueHandler
        invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
        // 设置 WebDataBinderFactory
        invocableMethod.setDataBinderFactory(binderFactory);
        // 设置 参数名解析器
        invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);

        ModelAndViewContainer mavContainer = new ModelAndViewContainer();
        // 获取 HttpServletRequest 中存储的 FlashMap
        mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
        // 这里是激活 @ModelAttribute, @InitBinder 方法, 并将返回值放入 ModelAndViewContainer
        modelFactory.initModel(webRequest, mavContainer, invocableMethod);
        mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
        // 将 HttpServletRequest 转换成方法的参数, 激活方法, 最后 通过 HandlerMethodReturnValueHandler 来处理返回值
        invocableMethod.invokeAndHandle(webRequest, mavContainer);      
        // 生成 ModelAndView
        return getModelAndView(mavContainer, modelFactory, webRequest); 
    }
    finally {
        webRequest.requestCompleted(); // 标志请求已经结束, 进行一些生命周期回调函数的激活
    }
}

代码到这边HandlerMethod还是没有激活, 还有非常重要的工作需要去做 -> 参数的解析与绑定 + 反射激活方法 + 返回值处理; 参数解析 + 绑定的操作在 InvocableHandlerMethod中, 具体流程如下:

private Object[] getMethodArgumentValues(NativeWebRequest request, ModelAndViewContainer mavContainer,Object... providedArgs) throws Exception {
    // 这里的 getMethodParameters 其实是在构造 MethodParameters 时创建的
    MethodParameter[] parameters = getMethodParameters();           
    Object[] args = new Object[parameters.length];
    // 从这里开始对参数进行一个一个解析 <- 主要是通过 HandlerMethodArgumentResolver
    for (int i = 0; i < parameters.length; i++) {                   
        MethodParameter parameter = parameters[i];
        // 设置参数名解析器 ParameterNameDiscoverer (默认通过 ASM)
        parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
        // 这一步是尝试 判断 参数 providedArgs 里面的类型是否满足 parameter 
        args[i] = resolveProvidedArgument(parameter, providedArgs);             
        if (args[i] != null) continue;
        // 判断是否 argumentResolvers 里面含有对应的 解释器
        if (this.argumentResolvers.supportsParameter(parameter)) {              
            try { // 通过 argumentResolvers 解析 HandlerMethod 里面 对应的参数内容
                args[i] = this.argumentResolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
                continue;
            }
            catch (Exception ex) {throw ex;}
        }
    }
    return args;
}

再得到参数后其实就可以激活对应的方法, 而返回值的做法相对上面的参数解析要简单一点, 都是先获取对应的返回值处理, 然后进行处理!

6. HandlerAdapter 中的优秀设计
1. 模版模式: 比如在 AbstractHandlerMethodAdapter中的 handleInternal, 而正真的实现在RequestMappingHandlerAdapter
2. 策略模式: 根据不同的策略实现接口 HandlerAdapter, 以支持不同的"controller"
3. InitializingBean: 这是 BeanFactory 中Bean生命周期的扩展接口, 表示 Bean 的初始化方法, RequestMappingHandlerAdapter 就是通过这个接口实现工具类的初始化
4. MethodIntrospector: 这是一个对方法进行反省操作的工具类, 通过传入 classType 与 methodFilter 来过滤需要的 Method
7. 总结

HandlerAdapter 是 SpringMVC中扩展机制的非常好的一个体现, 通过 HandlerAdapter, DispatcherServlet 就可以支持任何格式的Handler(这里的可以支持指在不改变 DispatcherServlet 的情况下), 第二是HandlerAdapter 基于不同Handler实现不同实现类(可以把它理解为策略模式), 最后也是最重要的就是参数的解析与返回值的解析(这个在下面进行叙述)!

8. 参考资料

SpringMVC源码分析系列
Spring MVC源码剖析
Spring源码情操陶冶
Spring 揭秘
Spring 技术内幕
Spring 源码深度分析
看透 Spring MVC 源代码分析与实践

相关文章

网友评论

      本文标题:SpringMVC 4.3 源码分析之 HandlerAdapt

      本文链接:https://www.haomeiwen.com/subject/silcfftx.html