spring中的HandlerAdapter工作原理

看前必讀

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,之後進入到實際請求處理階段時,由於RequestMappingHandlerAdaptersupports返回true,即代表它支持該handler,最後由它對該handler進行適配處理,返回一個ModelAndView對象。

由這個處理流程我們可以知道HandlerMappingHandlerAdapter之間必須存在對應關係,否則處理流程會出錯。


SimpleControllerHandlerAdapter

直接看這個類的supports方法,可以看到,它能適配的處理器是Controller類型的處理器,需要注意的是該Controller不是註解的Controllerorg.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;
    }
}

與它對應的HandlerMappingBeanNameUrlHandlerMapping

結語

花了好長時間看了這部分的源碼,自己勉強能明白其中一些原理,但想寫清楚發現還是涉及的東西太多,不能簡要的總結出來。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章