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 |
对于后面三个适配器,实现上都很简单,因为只需要把HttpServletRequest
和HttpServletResponse
对象透传下去,让子类自己去处理请求就好了,适配器本身并不需要处理过多复杂的事情。以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
。它的处理过程主要有三步:
- 准备HandlerMethod需要的参数。
- 反射调用目标方法,处理请求。
- 将返回结果封装成ModelAndView。
都使用Spring MVC了,相信大家也不会自己去操作HttpServletRequest获取请求参数了,更多的是使用@RequestParam
、@PathVariable
、@RequestHeader
、@RequestBody
等注解让Spring MVC绑定参数,所以光是第一步准备参数就非常复杂,值得另起篇幅单独记录;第二步反而是最简单的,直接反射调用目标方法即可;第三步将返回结果封装成ModelAndView,现在基本都前后端分离了,一般通过@ResponseBody
直接响应JSON即可。