探索SpringMVC-九大组件之HandlerAdapter

前言

上回我们知道,SpringMVC有九大组件。今天我们聊聊负责Handler调用的HandlerAdapter。

Handler

在讨论HandlerAdapter之前,我们需要先看看明白什么是Handler。Handler在SpringMVC中,可以说是一个逻辑概念。这或许也是他没有出现在官方的Special Bean Types章节中的原因吧。他的作用就是,用来处理特定请求。
在5.3.22版本中,共有5种Handler。

  • Controller接口
    是的,你没有看错,SpringMVC有专门的Contorller接口。不过他年纪有点大。是最早的接口,那个年代他还用来对标Struts的Action

    @FunctionalInterface
    public interface Controller {
    	@Nullable
    	ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception;
    }
    
  • Servlet
    没错,Servlet也可以作为DispatcherServlet的Handler的。这样的话,tomcat是不知道这个Servlet的,也不需要在web.xml中配置。另外,如果想要保持对自身的声明周期函数的调用,对ServletContext的感知和联系,则需要额外声明一个后置处理器SimpleServletPostProcessor。
    他也是早期SpringMVC的Handler

    public interface Servlet {
        void init(ServletConfig var1) throws ServletException;
    
        ServletConfig getServletConfig();
    
        void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
    
        String getServletInfo();
    
        void destroy();
    }
    
  • HttpRequestHandler

    @FunctionalInterface
    public interface HttpRequestHandler {
    	void handleRequest(HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException;
    }
    

    眼尖的同学可能看出来了,相比于Controller接口,他没有返回值。从这点看,他的作用应该和Servlet差不多。Controller可以选择自己通过response完成请求,返回null。也可以返回一个视图对象,交给DispatcherServlet继续执行后续的视图逻辑。但是HttpRequestHandler则只能自己处理请求,因此这点跟Servlet是很相似的。
    另外,他是SpringMVC 2.0的产物。

  • HandlerFunction
    他是SpringMVC最近的新生儿,于5.2版本才出现的。
    不知道大家有没有发现Spring推出了WebFlux(响应式web框架),流式编程看起来就很高大上。而实现流式编程依赖于ReactiveX,而ReactiveX会将模板代码进行封装,这就有函数式编程。搭载上Java8的lambda表达式,高大上的感觉就来了嘛。而HandlerFunction就是为了在SpringMVC也能用上这么高大上的功能引入了。

    @FunctionalInterface
    public interface HandlerFunction<T extends ServerResponse> {
    
    	/**
    	 * Handle the given request.
    	 * @param request the request to handle
    	 * @return the response
    	 */
    	T handle(ServerRequest request) throws Exception;
    
    }
    

    详细介绍大家可以看官方文档,这里不扩展了,不是我们的重点。
    webmvc-fn-overview

  • @Controller/@RequestMapping
    带有@Controller/@RequestMapping注解的对象都是Handler。这个也不用多说,大家应该都是使用@Controller搭配@RequestMapping来声明接口的。这里当然包括他们的派生注解@RestController@GetMapping@PostMapping等。就不多说了。

    PS: @RequestMapping可以在类上注解,大家知道吧。但是如果不带@Controller,而是@Component,那么这个类同样也会被识别为Handler的。

    HandlerMethod
    不知道大家有没有发现@Controller这种handler比较特别,可以处理多个URL的请求。但是在实际使用中,我们发现,如果不能知道具体执行的是哪个方法,在使用拦截器时就会犯难。例如,前阵子,我在SpringMVC 3.1.1的老版本项目中想要使用拦截器做幂等控制,发现先要针对特定请求进行拦截处理根本不可能。因为不知道是哪个方法处理的,也就无从获取方法上的注解,也就拿不到注解上的配置。因此,有必要抽象出来一个新的概念来适应这种场景。我觉得这可能是HandlerMethod诞生的背景。而尴尬的是,HandlerMethod却是在3.1版本就出现了,真是造化弄人。
    言归正传,HandlerMethod,意思是Handler的方法,这个名字简直不能再清楚了,就不过多解释了。该类是对目标处理方法的封装,包括目标对象、目标方法。
    实际上,如果不看源代码,你压根不会知道他,似乎是官方有意隐藏他的存在。或许因为他只是一个中间桥梁,将@RequestMapping方法与HandlerMapping、HandlerAdapter进行衔接。不管是RequestMappingHandlerMapping、还是RequestMappingHandlerAdapter都是在强调@RequestMapping,而不是HandlerMethod。虽然有点尴尬,但真是深藏功与名!

HandlerAdpater

说完了Handler,我们发现他太花里胡哨了,这DispatcherServlet要适配他,也太累了吧。别急,上设计模式——适配器。
为了适配这五种Handler,SpringMVC给他们分别设计了一个HandlerApdapter。这样DispatcherServlet就可以统一调度他们了。

public interface HandlerAdapter {
	/**
	 * 是否可以适配handler
	 * 一般而言,会通过处理器的类型来判断。一个HandlerAdatper只能支持一个类型的handler
	 */
	boolean supports(Object handler);
	
	/**
	 * 使用给定的handler处理请求。处理流程可能大不相同。
	 * 
	 * @param request 当前HTTP请求
	 * @param response 当前HTTP响应
	 * @param handler 处理器. 该对象必须通过{@code supports}方法确认可以适配。
	 * @return 一个ModelAndView对象,包含视图名称和必要的视图数据。如果请求被直接处理完成,则返回null
	 * @throws Exception 任何可能发生的错误
	 */
	@Nullable
	ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}

DispatcherServlet在处理请求时,会遍历所有的适配器,找到可以适配的HandlerAdapter并调用他的handle方法进行处理。
OK。继续,上面我们说了是分别设计一个HandlerAdapter进行适配,也就意味着,HandlerAdapter与Handler是一一对应的。

处理器处理器适配器备注
@Controller的@RequestMappingRequestMappingHandlerAdapter实际上该适配并不是直接适配@RequestMapping的,中间的桥梁是HandlerMethod
Controller接口SimpleControllerHandlerAdapter
HttpRequestHandler接口HttpRequestHandlerAdapter
ServletSimpleServletHandlerAdapter
HandlerFunctionSimpleServletHandlerAdapterSpringMVC 5.2之后提供的FunctionalInterface接口

小结

  1. SpringMVC通过适配器模式,对Handler进行适配,对上层组件隐藏了实际调用逻辑。
  2. Handler与HandlerAdapter是一一对应的。
  3. HandlerMethod是@RequestMapping与RequestMappingHandlerAdapter的桥梁。RequestMappingHandlerAdapter实际上是对HandlerMethod的适配。

后记

搞清楚HandlerAdapter的作用之后,我们下面重点关注最常用,也是最重要的RequestMappingHandlerAdapter是怎么实现的。

上一篇:
探索SpringMVC-九大组件
下一篇:
探索SpringMVC-HandlerAdapter之RequestMappingHandlerAdapter-参数解析
第一篇:
探索SpringMVC-web上下文

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值