Spring中HandlerAdapter接口源碼解析
HandlerAdapter接口源碼
HandlerAdapter是一個(gè)適配器接口類,適配器模式是指兩個(gè)不兼容接口之間的橋梁,要想讓一個(gè)接口使用另外一個(gè)接口的實(shí)現(xiàn)中間可以加一層適配器類;舉個(gè)例子:筆記本沒有網(wǎng)線接口,那我想連接網(wǎng)線接通網(wǎng)絡(luò)如何實(shí)現(xiàn)呢?我可以買一個(gè)以太網(wǎng)轉(zhuǎn)換器,網(wǎng)線插入轉(zhuǎn)換器上,轉(zhuǎn)換器插入筆記本上就實(shí)現(xiàn)了連接網(wǎng)絡(luò)的功能,那這個(gè)轉(zhuǎn)換器起到的就是一個(gè)適配器的作用;在接口訪問控制器方法的時(shí)候是通過HandlerAdapter接口的實(shí)現(xiàn)類來進(jìn)行的,本文以最常用的RequestMappingHandlerAdapter適配器類為主線索來講解。
接口的源碼如下:
public interface HandlerAdapter {
/**
* 判定是否支持傳入的handler
*/
boolean supports(Object handler);
/**
* 使用給定的handler來處理當(dāng)前request請求
*/
@Nullable
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
/**
* 返回handler最后修改的時(shí)間
*/
long getLastModified(HttpServletRequest request, Object handler);
}HandlerAdapter的實(shí)現(xiàn)類有多個(gè),我們以RequestMappingHandlerAdapter適配器類為主線索,而此類又是AbstractHandlerMethodAdapter抽象類的子類;
如下是RequestMappingHandlerAdapter適配器類的關(guān)系圖

1.HandlerAdapter接口的初始化
容器加載時(shí)DispatcherServlet中的初始化方法initStrategies方法會被調(diào)用,里面的
/**
* 容器中HandlerAdapter接口實(shí)現(xiàn)類集合
**/
@Nullable
private List<HandlerAdapter> handlerAdapters;
/**
* 初始化handlerAdapters集合,如果在BeanFactory中沒有HandlerAdapter,那么將使用默認(rèn)
* 的SimpleControllerHandlerAdapter
*/
private void initHandlerAdapters(ApplicationContext context) {
this.handlerAdapters = null;
//判定是否檢測所有的HandlerAdapter
if (this.detectAllHandlerAdapters) {
//查看容器中所有實(shí)現(xiàn)了HandlerAdapter的bean
Map<String, HandlerAdapter> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerAdapters = new ArrayList<>(matchingBeans.values());
// We keep HandlerAdapters in sorted order.
AnnotationAwareOrderComparator.sort(this.handlerAdapters);
}
}
else {
try {
HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
this.handlerAdapters = Collections.singletonList(ha);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default HandlerAdapter later.
}
}
// Ensure we have at least some HandlerAdapters, by registering
// default HandlerAdapters if no other adapters are found.
if (this.handlerAdapters == null) {
this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
if (logger.isTraceEnabled()) {
logger.trace("No HandlerAdapters declared for servlet '" + getServletName() +
"': using default strategies from DispatcherServlet.properties");
}
}
}
上面的代碼是從容器中獲取HandlerAdapter接口實(shí)現(xiàn)類的bean集合
2.RequestMappingHandlerAdapter處理request請求
前端發(fā)送過來一個(gè)request請求首先進(jìn)入DispatcherServlet的doService方法,再進(jìn)入doDispatch方法,那我們看下doDispatch方法的源碼:
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
//通過request請求獲取HandlerExecutionChain處理器執(zhí)行程序鏈
//也即通過request獲取匹配的HandlerMapping實(shí)現(xiàn)類,通過實(shí)現(xiàn)類的getHandler
//方法獲取HandlerExecutionChain處理程序執(zhí)行器鏈類,里面包含了請求對應(yīng)的HandlerMethod
//及對應(yīng)的所有攔截器
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
//根據(jù)上面獲取到的HandlerMethod獲取匹配到的適配器類
// Determine handler adapter for the current request.
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)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
//根據(jù)適配器對象調(diào)用具體的方法(如:RequestMappingHandlerAdapter)
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
跳出本文分析的正文流程,來分析下AbstractHandlerMethodAdapter適配器類;
Abstract base class for {@link HandlerAdapter} implementations that support
handlers of type {@link HandlerMethod}.
源碼注解說明類抽象類的實(shí)現(xiàn)support方法判定是否支持HandlerMethod;
/**
* 判定適配器類是否支持HandlerMethod
**/
@Override
public final boolean supports(Object handler) {
return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}
getHandlerAdapter方法實(shí)現(xiàn)源碼:
/**
* 獲取可以處理handler的HandlerAdapter適配器類
*/
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
//判定適配器類是否支持HandlerMethod
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");
}
ha.handle(processedRequest, response, mappedHandler.getHandler());方法會調(diào)用AbstractHandlerMethodAdapter適配器類的handle方法:
@Override
@Nullable
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return handleInternal(request, response, (HandlerMethod) handler);
}
而handleInternal方法最終會調(diào)用RequestMappingHandlerAdapter類的handlerInternal方法:
@Override
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ModelAndView mav;
checkRequest(request);
// Execute invokeHandlerMethod in synchronized block if required.
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
// No HttpSession available -> no mutex necessary
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
// No synchronization on session demanded at all...
mav = invokeHandlerMethod(request, response, handlerMethod);
}
if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
}
else {
prepareResponse(response);
}
}
return mav;
}
handleInternal方法又會調(diào)用invokeHandlerMethod方法:
@Nullable
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ServletWebRequest webRequest = new ServletWebRequest(request, response);
try {
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
//創(chuàng)建HandlerMethod的子類ServletInvocableHandlerMethod的實(shí)例對象
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
if (this.argumentResolvers != null) {
//設(shè)置參數(shù)解析器
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
}
if (this.returnValueHandlers != null) {
//設(shè)置返回值處理程序
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
}
invocableMethod.setDataBinderFactory(binderFactory);
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
modelFactory.initModel(webRequest, mavContainer, invocableMethod);
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
asyncWebRequest.setTimeout(this.asyncRequestTimeout);
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.setTaskExecutor(this.taskExecutor);
asyncManager.setAsyncWebRequest(asyncWebRequest);
asyncManager.registerCallableInterceptors(this.callableInterceptors);
asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
if (asyncManager.hasConcurrentResult()) {
Object result = asyncManager.getConcurrentResult();
mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
asyncManager.clearConcurrentResult();
LogFormatUtils.traceDebug(logger, traceOn -> {
String formatted = LogFormatUtils.formatValue(result, !traceOn);
return "Resume with async result [" + formatted + "]";
});
invocableMethod = invocableMethod.wrapConcurrentResult(result);
}
//調(diào)用ServletInvocableHandlerMethod類的invokeAndHandle方法
invocableMethod.invokeAndHandle(webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
}
return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
webRequest.requestCompleted();
}
}
上面的方法會涉及到參數(shù)解析器的初始化、返回值處理程序的初始化,那這些返回值處理程序和參數(shù)解析程序如何初始化的呢?RequestMappingHandlerAdapter類實(shí)現(xiàn)了InitializingBean接口,該類加載后會調(diào)用afterPropertiesSet方法,會對這些處理程序進(jìn)行初始化;
@Override
public void afterPropertiesSet() {
// Do this first, it may add ResponseBody advice beans
initControllerAdviceCache();
//參數(shù)解析器初始化
if (this.argumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
//InitBinder的參數(shù)解析器初始化
if (this.initBinderArgumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
//返回值處理程序初始化
if (this.returnValueHandlers == null) {
List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
}
}
調(diào)用ServletInvocableHandlerMethod.invokeAndHandle方法源碼如下:
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
//調(diào)用控制器方法,獲取返回值
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
setResponseStatus(webRequest);
if (returnValue == null) {
if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
disableContentCachingIfNecessary(webRequest);
mavContainer.setRequestHandled(true);
return;
}
}
else if (StringUtils.hasText(getResponseStatusReason())) {
mavContainer.setRequestHandled(true);
return;
}
mavContainer.setRequestHandled(false);
Assert.state(this.returnValueHandlers != null, "No return value handlers");
try {
//將返回值交給HandlerMethodReturnValueHandlerComposite返回值代理類
//選擇合適的HandlerMethodReturnValueHandler實(shí)現(xiàn)類處理返回值
this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}
catch (Exception ex) {
if (logger.isTraceEnabled()) {
logger.trace(formatErrorForReturnValue(returnValue), ex);
}
throw ex;
}
}
調(diào)用InvocableHandlerMethod.invokeForRequest方法源碼:
/**
* 獲取request請求參數(shù),調(diào)用控制器方法
**/
@Nullable
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
//獲取request請求方法的參數(shù)
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
if (logger.isTraceEnabled()) {
logger.trace("Arguments: " + Arrays.toString(args));
}
return doInvoke(args);
}
調(diào)用InvocableHandlerMethod.doInvoke(Object… args)方法源碼:
/**
* 使用給定的參數(shù)調(diào)用控制器方法
**/
@Nullable
protected Object doInvoke(Object... args) throws Exception {
ReflectionUtils.makeAccessible(getBridgedMethod());
try {
//調(diào)用真實(shí)最終的控制器方法,并返回執(zhí)行后的結(jié)果
return getBridgedMethod().invoke(getBean(), args);
}
catch (IllegalArgumentException ex) {
assertTargetBean(getBridgedMethod(), getBean(), args);
String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");
throw new IllegalStateException(formatInvokeError(text, args), ex);
}
catch (InvocationTargetException ex) {
// Unwrap for HandlerExceptionResolvers ...
Throwable targetException = ex.getTargetException();
if (targetException instanceof RuntimeException) {
throw (RuntimeException) targetException;
}
else if (targetException instanceof Error) {
throw (Error) targetException;
}
else if (targetException instanceof Exception) {
throw (Exception) targetException;
}
else {
throw new IllegalStateException(formatInvokeError("Invocation failure", args), targetException);
}
}
}
到此這篇關(guān)于Spring中HandlerAdapter接口源碼解析的文章就介紹到這了,更多相關(guān)HandlerAdapter接口源碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java?SpringBoot注解@Async不生效的解決方法
大家好,本篇文章主要講的是java?SpringBoot注解@Async不生效的解決方法,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下2022-01-01
SpringMVC項(xiàng)目訪問controller時(shí)候報(bào)404的解決
這篇文章主要介紹了SpringMVC項(xiàng)目訪問controller時(shí)候報(bào)404的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09
Springboot如何配置Scheduler定時(shí)器
這篇文章主要介紹了Springboot如何配置Scheduler定時(shí)器問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-03-03
Spring?Data?Elasticsearch?5.x實(shí)現(xiàn)單詞糾錯(cuò)和自動(dòng)補(bǔ)全
這篇文章主要為大家介紹了Spring?Data?Elasticsearch?5.x實(shí)現(xiàn)單詞糾錯(cuò)和自動(dòng)補(bǔ)全示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
shiro并發(fā)人數(shù)登錄控制的實(shí)現(xiàn)代碼
在做項(xiàng)目中遇到這樣的需求要求每個(gè)賬戶同時(shí)只能有一個(gè)人登錄或幾個(gè)人同時(shí)登錄,如果是同時(shí)登錄的多人,要么不讓后者登錄,要么踢出前者登錄,怎么實(shí)現(xiàn)這樣的功能呢?下面小編給大家?guī)砹藄hiro并發(fā)人數(shù)登錄控制的實(shí)現(xiàn)代碼,一起看看吧2017-09-09
Java應(yīng)用程序CPU100%問題排查優(yōu)化實(shí)戰(zhàn)
這篇文章主要介紹了如何排查和優(yōu)化Java應(yīng)用程序CPU使用率達(dá)到100%的問題,文中通過代碼示例和圖文結(jié)合的方式講解的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下2025-02-02
Mybatis基礎(chǔ)概念與高級應(yīng)用小結(jié)
這篇文章主要介紹了Mybatis基礎(chǔ)回顧與高級應(yīng)用,本文內(nèi)容有點(diǎn)小長,希望大家耐心閱讀,此文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-06-06

