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

1,472 阅读5分钟

永远别放弃自己,哪怕所有人都放弃了你

1.既生瑜何生亮2.HandlerAdapter实现HttpRequestHandlerAdapterSimpleControllerHandlerAdapterSimpleServletHandlerAdapterRequestMappingHandlerAdapter3.总结:

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 HandlerAdapterOrdered {

    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


如果觉得文章有用, 求点赞👍 求关注❤️ 求分享👥
如果本文任何错误,请批评指教,不胜感激 !

微信公众号:[源码行动]加我认识认识呗
我把自己写文章的定位是个人理解日记。因为每当我写文章时,我会集中注意力在知识点的理解与阐述上,这样会加深,加强对知识点的理解。

新的一年,我享读读源码,不求技术飞速提高,但求心里舒服