Spring MVC之HandlerAdapter

1. 前言

Spring MVC没有限制Handler的类型,Handler可以以任何形式存在,内置的Handler就有四种类型:

  • HandlerMethod
  • Controller
  • HttpRequestHandler
  • Servlet

开发者还可以自定义Handler,面对各种各样类型的Handler,Spring MVC再也不能简单直接的面向接口编程了。于是Spring MVC采用了适配器模式,通过不同的适配器去协调不同的Handler工作,适配器本身是很容易抽象成接口的,所以Spring MVC又可以愉快的面向接口编程了。

2. HandlerAdapter

public interface HandlerAdapter {
   
    /**
     * 适配器是否支持给定的Handler?
     */
    boolean supports(Object handler);

    /**
     * 协调Handler处理请求,返回结果
     */
    @Nullable
    ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;

    /**
     * 获取资源最后修改的时间戳,以确定是否返回304让浏览器使用缓存
     */
    long getLastModified(HttpServletRequest request, Object handler);

}

HandlerAdapter接口定义很简单,Spring MVC首先会遍历所有的HandlerAdapter,依次通过supports()判断当前适配器是否支持处理给定的Handler?如果支持,那么就调用handle()让适配器去协调Handler处理请求,返回结果。

DispatcherServlet获取Handler对应的适配器:

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
   
    if (this.handlerAdapters != null) {
   
        for (HandlerAdapter adapter : this.handlerAdapters) {
   
            if (adapter.supports(handler)) {
   
                return adapter;
            }
        }
    }
    throw new ServletException("No adapter for handler [" + handler +
            "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}

让适配器去处理请求,返回ModelAndView:

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

3. 内置适配器

Spring MVC内置了四种类型的Handler,对应的也就存在四种HandlerAdapter**。**

Handler HandlerAdapter
HandlerMethod RequestMappingHandlerAdapter
Controller SimpleControllerHandlerAdapter
HttpRequestHandler HttpRequestHandlerAdapter
Servlet SimpleServletHandlerAdapter

对于后面三个适配器,实现上都很简单,因为只需要把HttpServletRequestHttpServletResponse对象透传下去,让子类自己去处理请求就好了,适配器本身并不需要处理过多复杂的事情。以SimpleControllerHandlerAdapter为例:

public class SimpleControllerHandlerAdapter implements HandlerAdapter {
   

    @Override
    public boolean supports(Object handler) {
   
        // 只要Handler是Controller类型,就支持处理
        return (handler instanceof Controller);
    }

    @Override
    @Nullable
    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
   
        // 转换类型,把request和response透传给Handler处理即可
        return ((Controller) handler).handleRequest(request, response);
    }

    @Override
    public long getLastModified(HttpServletRequest request, Object handler) {
   
        if (handler instanceof LastModified) {
   
            return ((LastModified) handler).getLastModified(request);
        }
        return -1L;
    }
}
  • supports()判断很简单,只要Handler属于Controller类型即可。
  • handle()更简单了,把request和response透传给Handler处理即可。

真正复杂的是RequestMappingHandlerAdapter,也就是被@RequestMapping注解标记的方法,Handler对应的类是org.springframework.web.method.HandlerMethod。它的处理过程主要有三步:

  1. 准备HandlerMethod需要的参数。
  2. 反射调用目标方法,处理请求。
  3. 将返回结果封装成ModelAndView。

都使用Spring MVC了,相信大家也不会自己去操作HttpServletRequest获取请求参数了,更多的是使用@RequestParam@PathVariable@RequestHeader@RequestBody等注解让Spring MVC绑定参数,所以光是第一步准备参数就非常复杂,值得另起篇幅单独记录;第二步反而是最简单的,直接反射调用目标方法即可;第三步将返回结果封装成ModelAndView,现在基本都前后端分离了,一般通过@ResponseBody直接响应JSON即可。

相关推荐

  1. Spring MVCHandlerAdapter

    2024-01-07 16:48:01       57 阅读
  2. SpringMVC处理响应

    2024-01-07 16:48:01       51 阅读
  3. SpringMVC参数获取

    2024-01-07 16:48:01       62 阅读
  4. SpringMVC异常处理

    2024-01-07 16:48:01       65 阅读
  5. SpringMVCRESTful案例

    2024-01-07 16:48:01       48 阅读
  6. SpringMVCREST风格

    2024-01-07 16:48:01       61 阅读
  7. SpringMVC文件的下载

    2024-01-07 16:48:01       62 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-01-07 16:48:01       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-01-07 16:48:01       106 阅读
  3. 在Django里面运行非项目文件

    2024-01-07 16:48:01       87 阅读
  4. Python语言-面向对象

    2024-01-07 16:48:01       96 阅读

热门阅读

  1. 神经网络中的重要概念

    2024-01-07 16:48:01       50 阅读
  2. hyperf 十九 数据库 二 模型

    2024-01-07 16:48:01       53 阅读
  3. 【SQL】加快SQL查询的九种优秀实践

    2024-01-07 16:48:01       58 阅读
  4. 38 调优kafka

    2024-01-07 16:48:01       62 阅读