看前必讀
HandlerMapping、HandlerExecutionChain、HandlerAdapter之間的關係
幾種RequestMapping的使用方法
HandlerAdapter的作用
HandlerAdapter
接口很簡單,代碼如下
public interface HandlerAdapter {
boolean supports(Object handler);
@Nullable
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}
其中,supports
方法判斷當前該適配器Adapter
能是否支持該處理器handler
,handle
方法是實際完成請求處理的方法,並返回一個ModelAndView
對象。
幾種常見的HandlerAdapter
springboot
會默認註冊幾種常見的HandlerAdapter
:HttpRequestHandlerAdapter
,SimpleControllerHandlerAdapter
,SimpleServletHandlerAdapter
,RequestMappingHandlerAdapter
,接下來就兩種HandlerAdapter
進行說明,它們的關係如下圖所示:
最常用的 RequestMappingHandlerAdapter
它繼承了AbstractHandlerMethodAdapter
,而AbstractHandlerMethodAdapter
實現了HandlerAdapter
。我們來看AbstractHandlerMethodAdapter
的具體實現:
public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter, Ordered {
@Override
public final boolean supports(Object handler) {
return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}
protected abstract boolean supportsInternal(HandlerMethod handlerMethod);
@Override
@Nullable
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return handleInternal(request, response, (HandlerMethod) handler);
}
}
從supports
方法可以看出,它支持HandlerMethod
類型的處理器。那麼我們怎麼知道當前的handler
是否是一個HandlerMethod
呢?我們知道,handler
是由HandlerMapping
獲得的,因此,不同的HandlerMapping
獲得的handler
類型不同。這個HandlerMethod
類型的處理器就是由RequestMappingHandlerMapping
得到的,部分源碼如下:
public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping
implements MatchableHandlerMapping, EmbeddedValueResolverAware {
.........
@Override
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
try {
return super.getHandlerInternal(request);
}
finally {
ProducesRequestCondition.clearMediaTypesAttribute(request);
}
}
.........
}
舉個栗子,對於如下的Controller
:
@Controller
@RequestMapping("/test")
public class TestController{
@RequestMapping("/index")
public String index(){
return "index";
}
}
假設端口是80
,當我們訪問localhost/test/index
,就會進入該控制器的index
方法,這其中的流程是:RequestMappingHandlerMapping
會根據當前請求的request
返回一個HandlerMethod
類型的處理器handler
,之後進入到實際請求處理階段時,由於RequestMappingHandlerAdapter
的supports
返回true
,即代表它支持該handler
,最後由它對該handler
進行適配處理,返回一個ModelAndView
對象。
由這個處理流程我們可以知道HandlerMapping
與HandlerAdapter
之間必須存在對應關係,否則處理流程會出錯。
SimpleControllerHandlerAdapter
直接看這個類的supports
方法,可以看到,它能適配的處理器是Controller
類型的處理器,需要注意的是該Controller
不是註解的Controller
類org.springframework.stereotype.Controller
,而是org.springframework.web.servlet.mvc.Controller
。
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
@Override
public boolean supports(Object handler) {
return (handler instanceof Controller);
}
@Override
@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return ((Controller) handler).handleRequest(request, response);
}
}
對於如下例子,訪問localhost/mappingTest3
,它的實際處理就是由SimpleControllerHandlerAdapter
@Component("/mappingTest3")
public class MappingTest3 implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
response.getWriter().write("BeanNameUrlHandlerMapping test!");
return null;
}
}
與它對應的HandlerMapping
是BeanNameUrlHandlerMapping
。
結語
花了好長時間看了這部分的源碼,自己勉強能明白其中一些原理,但想寫清楚發現還是涉及的東西太多,不能簡要的總結出來。