Spring MVC之HandlerAdapter

1. 前言

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

  • HandlerMethod
  • Controller
  • HttpRequestHandler
  • Servlet

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

2. HandlerAdapter

java 复制代码
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对应的适配器:

java 复制代码
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:

java 复制代码
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

3. 内置适配器

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

Handler HandlerAdapter
HandlerMethod RequestMappingHandlerAdapter
Controller SimpleControllerHandlerAdapter
HttpRequestHandler HttpRequestHandlerAdapter
Servlet SimpleServletHandlerAdapter

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

java 复制代码
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即可。

相关推荐
JH30739 分钟前
SpringBoot 优雅处理金额格式化:拦截器+自定义注解方案
java·spring boot·spring
Coder_Boy_1 小时前
技术让开发更轻松的底层矛盾
java·大数据·数据库·人工智能·深度学习
invicinble2 小时前
对tomcat的提供的功能与底层拓扑结构与实现机制的理解
java·tomcat
较真的菜鸟2 小时前
使用ASM和agent监控属性变化
java
黎雁·泠崖2 小时前
【魔法森林冒险】5/14 Allen类(三):任务进度与状态管理
java·开发语言
qq_12498707533 小时前
基于SSM的动物保护系统的设计与实现(源码+论文+部署+安装)
java·数据库·spring boot·毕业设计·ssm·计算机毕业设计
Coder_Boy_3 小时前
基于SpringAI的在线考试系统-考试系统开发流程案例
java·数据库·人工智能·spring boot·后端
Mr_sun.3 小时前
Day06——权限认证-项目集成
java
瑶山3 小时前
Spring Cloud微服务搭建四、集成RocketMQ消息队列
java·spring cloud·微服务·rocketmq·dashboard
abluckyboy3 小时前
Java 实现求 n 的 n^n 次方的最后一位数字
java·python·算法