本文基于spring 5.5.2.release
前面几篇文章介绍了接口HandlerMapping,了解到该接口的作用是根据请求参数查找Handler,这个Handler并没有具体的要求,可以是一个普通的bean对象,也可以是HandlerMethod对象。这就导致DispatcherServlet不能对Handler按照统一的规则处理,因此springmvc提供了适配器HandlerAdapter,将Handler交给适配器处理,适配器对外提供统一接口,DispatcherServlet调用适配器即可。
springmvc对每种Handler都提供了对应的适配器,如果springmvc提供的适配器不符合要求,我们还可以添加自定义适配器。
文章目录
一、HandlerAdapter接口定义
下面看一下HandlerAdapter接口需要实现的方法:
public interface HandlerAdapter {
/**
* 检查当前HandlerAdapter实现类是否可以处理Handler
*/
boolean supports(Object handler);
/**
* 处理http请求的核心方法,
* 该方法里面会根据Handler对象找到Controller,然后调用Controller处理请求
*/
@Nullable
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
/**
* 返回请求内容的最后修改时间,返回值会被放入到响应报文头的Last-Modified字段中,
* 调用下面这个方法需要Handler实现LastModified接口,springmvc没有提供LastModified的实现类,需要自定义,
*/
long getLastModified(HttpServletRequest request, Object handler);
}
二、HandlerAdapter的使用
在这一小节看一下DispatcherServlet如何使用HandlerAdapter。
springmvc接收到的请求都会被转发到DispatcherServlet.doDispatch()方法,下面我们看一下这个方法。
//入参request表示http请求对象,response是响应对象
//下面方法内容有删减
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
try {
// Determine handler for the current request.
//在getHandler中遍历HandlerMapping实现类,找到合适的Handler
//该方法的返回值是HandlerExecutionChain对象,它对Handler做了封装
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
//遍历HandlerAdapter实现类,找到可以处理Handler的适配器
//在getHandlerAdapter方法里面调用了适配器的supports方法
//getHandlerAdapter方法内容见下方
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
//调用HandlerAdapter的getLastModified方法,找到请求内容的最后修改时间
//该方法要求Handler实现LastModified接口,如果没有实现,该方法可以直接返回-1
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
//checkNotModified方法将request中的If-Unmodified-Since字段时间与最后修改时间lastModified做比较,
//如果前者大,那么意味着没有修改过,那么设置报文头Last-Modified字段和状态码,不再进行后续处理,直接向客户端返回响应内容,
//如果后者大,那么表示修改过,需要调用Controller进行处理。
//如果入参lastModified小于0,checkNotModified方法认为修改过
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
//调用拦截器
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
//调用Controller或者说是Handler处理请求
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
//如果mv没有设置view属性值,那么设置默认值
applyDefaultViewName(processedRequest, mv);
//调用拦截器
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
}
}
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
//遍历适配器,找到可以处理Handler的适配器
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");
}
可以看到doDispatch()方法里面调用了HandlerAdapter接口的三个方法:第一次是调用supports方法以找到可以处理Handler的实现类;第二次是调用getLastModified方法查看最后修改时间,第三次是调用handler方法,处理http请求。
三、HandlerAdapter实现类
springmvc提供五个HandlerAdapter的实现类:
这些类中只有RequestMappingHandlerAdapter逻辑比较复杂,会在其他文章中详细介绍,剩下类的实现逻辑基本类似,比较简单,本文详细看一下SimpleControllerHandlerAdapter的实现源码,其他的类大家自行查看,不在做介绍。
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
@Override
//该适配器,要求handler必须实现Controller接口
public boolean supports(Object handler) {
return (handler instanceof Controller);
}
@Override
@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//处理请求直接调用handleRequest方法,返回ModelAndView对象
//DispatcherServlet会解析ModelAndView,找到对应的View对象,并进行渲染
return ((Controller) handler).handleRequest(request, response);
}
//如果handler没有实现LastModified接口,直接返回-1
@Override
public long getLastModified(HttpServletRequest request, Object handler) {
if (handler instanceof LastModified) {
return ((LastModified) handler).getLastModified(request);
}
return -1L;
}
}
四、总结
HandlerAdapter是沟通Handler与DispatcherServlet之间的桥梁,由于springmvc没有对Handler做强制要求,任何一个普通的bean都可以作为Handler,因此使用HandlerAdapter将Handler之间的不同屏蔽掉,DispatcherServlet使用统一的方式调用Handler处理请求。