享读SpringMVC源码3-既有HandlerMapping 何生HandlerAdapter

简介: 享读SpringMVC源码3-既有HandlerMapping 何生HandlerAdapter

1.既生瑜何生亮


通过前几篇文章,我们知道根据url可以从HandlerMapping中,获取到我们需要的handler了。有了handler不就可以处理程序了吗。

为啥有了HandlerMapping ,还需要HandlerAdapter?

来看看DispatcherServlet#doDispatch(request, response) 与 handler之间的问题

  1. Servlet入参就2个,但是handler 里各种各样的入参。尤其是我们常用的@RequestMapping这种方式定义的,参数有个根据开发人员心情定
  2. handler返回类型多种多样,返回各种格式的数据类型。
  3. 4种handler定义方式,如何选择?

这种固定的Servlet规范与灵活的Handler之间就产生了冲突。

于是乎伟大的设计模式上场,适配器模式的存在就是解决这种不兼容双方的。HandlerAdapter就是这个适配器

1.入参的匹配,返回值的复杂处理交给适配器去处理

2.Handler的选择问题,交给适配器去操心

这也为我们使用适配器模式提供了好的范本。

public interface HandlerAdapter {
    boolean supports(Object handler);
    ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
    long getLastModified(HttpServletRequest request, Object handler);
}

HandlerAdapter中定义了三个方法:

  • supports: 用于判断当前适配器是否支持是否能够支持当前的handler的适配。也就是解决了Handler的选择问题
  • handle() :真正调用Handler,适配的核心。帮我们解决参数,返回值等一些列周边问题
  • getLastModified():获取当前请求的最后更改时间,主要用于供给浏览器判断当前请求是否修改过,从而判断是否可以直接使用之前缓存的结果


2.HandlerAdapter实现


针对不同的Handler,HandlerAdapter的实现也不同。


HttpRequestHandlerAdapter
public class HttpRequestHandlerAdapter implements HandlerAdapter {
    @Override
    public boolean supports(Object handler) {
        return (handler instanceof HttpRequestHandler);
    }
    @Override
    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        ((HttpRequestHandler) handler).handleRequest(request, response);
        return null;
    }
    @Override
    public long getLastModified(HttpServletRequest request, Object handler) {
        if (handler instanceof LastModified) {
            return ((LastModified) handler).getLastModified(request);
        }
        return -1L;
    }
}

看HttpRequestHandlerAdapter.supports 判断其是否是HttpRequestHandler接口类型,也就说HttpRequestHandlerAdapter适配org.springframework.web.HttpRequestHandler这种Handler

handle处理方法直接调用HttpRequestHandler实例的handleRequest方法


SimpleControllerHandlerAdapter

从supports方法可以看出适配的是实现Controller接口这种handler,handle处理方法也是直接调用Controller实例的handleRequest方法

public class SimpleControllerHandlerAdapter implements HandlerAdapter {
    @Override
    public boolean supports(Object handler) {
        return (handler instanceof Controller);
    }
    @Override
    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        return ((Controller) handler).handleRequest(request, response);
    }
}


SimpleServletHandlerAdapter

从supports方法可以看出适配的是Servlet这种handler,handle处理方法也是直接调用Servlet实例的service方法

public class SimpleServletHandlerAdapter implements HandlerAdapter {
    @Override
    public boolean supports(Object handler) {
        return (handler instanceof Servlet);
    }
    @Override
    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        ((Servlet) handler).service(request, response);
        return null;
    }
}


RequestMappingHandlerAdapter

最重要的HandlerAdapter,之所以说重要,因为他是最复杂,也是SpringMVC的核心功能之一。

看上文的其他三种handler适配器。都很简单。SpringMVC适配器的重头戏其实就在RequestMappingHandlerAdapter

我们先来看看其supports方法,其实现在父类AbstractHandlerMethodAdapter

public abstract class AbstractHandlerMethodAdapter {
   public final boolean supports(Object handler) {
           return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
       } 
}
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter{
   protected boolean supportsInternal(HandlerMethod handlerMethod) {
           return true;
       } 
}

可以看出,支持的是handler 是HandlerMethod类型,

handle 方法的实现在其父类AbstractHandlerMethodAdapter 中,是个模板方法,调用子类RequestMappingHandlerAdapter#handleInternal方法

public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter, Ordered {
    public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        return handleInternal(request, response, (HandlerMethod) handler);
    }
}

RequestMappingHandlerAdapter#handle方法是SpringMVC最复杂的一块。上文提到的handler入参的匹配返回值的处理等等操作都在此适配中体现。

RequestMappingHandlerAdapter#handle方法的工作原理比较复杂,单开一篇文章讲讲。


3.总结:


HandlerAdapter适配器充当servlet 与 多样性的Handler 之间的调用的桥梁,把他们之间的参数匹配,返回值处理等问题解决掉了。 兼容是HandlerAdapter的工作。

所以:

  • HandlerMapping ,负责解析登记Handler
  • HandlerAdapter,负责兼容性调用

既要HandlerMapping 又要HandlerAdapter


相关文章
|
2月前
|
Java 应用服务中间件 Spring
Spring5源码(50)-SpringMVC源码阅读环境搭建
Spring5源码(50)-SpringMVC源码阅读环境搭建
47 0
|
12月前
|
存储 前端开发 搜索推荐
(八)Spring源码解析:Spring MVC
(八)Spring源码解析:Spring MVC
62 1
|
2月前
|
Java 应用服务中间件 数据库连接
Spring5源码(51)-Servlet知识点回顾以及SpringMVC分析入口
Spring5源码(51)-Servlet知识点回顾以及SpringMVC分析入口
48 0
|
2月前
|
SQL JSON 前端开发
【源码免费下载】SpringBoot整合Spring+SpringMVC+MyBatisPlus案例:图书管理系统
【源码免费下载】SpringBoot整合Spring+SpringMVC+MyBatisPlus案例:图书管理系统
81 0
|
2月前
|
设计模式 前端开发 Java
[Spring ~源码] Spring的run方法以及SpringMVC执行流程
[Spring ~源码] Spring的run方法以及SpringMVC执行流程
|
前端开发 Java Spring
源码浅析SpringMVC请求的流转过程
Spring MVC框架使用了其”模型-视图-控制器”( Model-View-Controller )架构方式,用于开发灵活且松散耦合的 Web 应用程序。我们都使用过SpringMVC来处理信息,并渲染视图到Browser。但需要注意的是,在现在的架构中,大都采用了前后端分离的情况,而我们在使用SpringMVC的时候,只需要关注M(Model),C(Controller)这两个部分,而视图渲染的部分则交给了前端。
290 0
源码浅析SpringMVC请求的流转过程
|
Java Spring 容器
享读SpringMVC源码5-异常处理HandlerExceptionResolver(上)
享读SpringMVC源码5-异常处理HandlerExceptionResolver(上)
享读SpringMVC源码5-异常处理HandlerExceptionResolver(上)
|
Java Spring
享读SpringMVC源码4-感谢RequestMappingHandlerAdapter(下)
享读SpringMVC源码4-感谢RequestMappingHandlerAdapter(下)
享读SpringMVC源码4-感谢RequestMappingHandlerAdapter(下)
|
应用服务中间件
享读SpringMVC源码0--从Tomcat到SpringMVC
享读SpringMVC源码0--从Tomcat到SpringMVC
享读SpringMVC源码0--从Tomcat到SpringMVC
|
JSON 前端开发 Java
【小家Spring】Spring MVC容器的web九大组件之---ViewResolver源码详解---视图View详解(下)
【小家Spring】Spring MVC容器的web九大组件之---ViewResolver源码详解---视图View详解(下)
【小家Spring】Spring MVC容器的web九大组件之---ViewResolver源码详解---视图View详解(下)