HandlerAdapter 介绍 HandlerAdapter
是Handler
的适配器,每种类型的Handler
都对应一个HandlerAdapter
。
分析 在顶层接口HandlerAdapter
的实现中,基本上都是直接具体的实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public interface HandlerAdapter {boolean supports (Object handler) ;@Nullable ModelAndView handle (HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception ;long getLastModified (HttpServletRequest request, Object handler) ;}
这里以AbstractHandlerMethodAdapter
为例进行分析。这个抽象类也比较简答,仅仅是将顶层接口中的参数进行具象化,再调用本类的模板方法,供子类直接使用,所以子类就不需要在进行类型装换等操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @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); } @Nullable protected abstract ModelAndView handleInternal (HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception ;
具体实现RequestMappingHandlerAdapter
RequestMappingHandlerAdapter
是HandlerAdapter
体系中最复杂的类,包含了具体Handler
执行前后需要特殊处理或者是一些开放的扩展点的处理。比如有参数处理器、参数名称处理器、HttpMessageConverter
、结果处理器等等。
1.初始化
RequestMappingHandlerAdapter
的初始化分为两步,一步是在构造函数中进行默认HttpMessageConvert
的添加,另一步是通过afterPropertiesSet
进行一些全局处理的缓存和一些组件的初始化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 public RequestMappingHandlerAdapter () { this .messageConverters = new ArrayList<>(4 ); this .messageConverters.add(new ByteArrayHttpMessageConverter()); this .messageConverters.add(new StringHttpMessageConverter()); try { this .messageConverters.add(new SourceHttpMessageConverter<>()); }catch (Error err) { } this .messageConverters.add(new AllEncompassingFormHttpMessageConverter()); } @Override public void afterPropertiesSet () { initControllerAdviceCache(); if (this .argumentResolvers == null ) { List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers(); this .argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers); } 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); } } private void initControllerAdviceCache () { if (getApplicationContext() == null ) { return ; } List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext()); List<Object> requestResponseBodyAdviceBeans = new ArrayList<>(); for (ControllerAdviceBean adviceBean : adviceBeans) { Class<?> beanType = adviceBean.getBeanType(); if (beanType == null ) { throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean); } Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS); if (!attrMethods.isEmpty()) { this .modelAttributeAdviceCache.put(adviceBean, attrMethods); } Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS); if (!binderMethods.isEmpty()) { this .initBinderAdviceCache.put(adviceBean, binderMethods); } if (RequestBodyAdvice.class.isAssignableFrom(beanType) || ResponseBodyAdvice.class.isAssignableFrom(beanType)) { requestResponseBodyAdviceBeans.add(adviceBean); } } if (!requestResponseBodyAdviceBeans.isEmpty()) { this .requestResponseBodyAdvice.addAll(0 , requestResponseBodyAdviceBeans); } }
2.实际处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 @Override protected ModelAndView handleInternal (HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ModelAndView mav; checkRequest(request); if (this .synchronizeOnSession) { HttpSession session = request.getSession(false ); if (session != null ) { Object mutex = WebUtils.getSessionMutex(session); synchronized (mutex) { mav = invokeHandlerMethod(request, response, handlerMethod); } }else { mav = invokeHandlerMethod(request, response, handlerMethod); } }else { mav = invokeHandlerMethod(request, response, handlerMethod); } if (!response.containsHeader(HEADER_CACHE_CONTROL)) { if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) { applyCacheSeconds(response, this .cacheSecondsForSessionAttributeHandlers); }else { prepareResponse(response); } } return mav; } @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); ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod); if (this .argumentResolvers != null ) { invocableMethod.setHandlerMethodArgumentResolvers(this .argumentResolvers); } if (this .returnValueHandlers != null ) { 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); } invocableMethod.invokeAndHandle(webRequest, mavContainer); if (asyncManager.isConcurrentHandlingStarted()) { return null ; } return getModelAndView(mavContainer, modelFactory, webRequest); }finally { webRequest.requestCompleted(); } }
ServletInvocableHandlerMethod
就是具体的HandlerMethod
的实现,所以在最后通过invocableMethod.invokeAndHandle(webRequest, mavContainer)
调用到具体的实现。以下基本上就是具体Handler
的调用前最后一步了,返回执行结果之后,由结果处理器进行处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public void invokeAndHandle (ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { 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 { this .returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest); }catch (Exception ex) { if (logger.isTraceEnabled()) { logger.trace(formatErrorForReturnValue(returnValue), ex); } throw ex; } }
这里想简要说明一下异步调用的场景:Servlet3.0
支持服务器异步操作,在springmvc
中也添加了响应的支持。整个请求的过程与同步类似,只是在具体的handler
调用之后,如果是异步方式,假设是使用Callable
,则这里获取到的返回值处理器就是CallableMethodReturnValueHandler
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 @Override public void handleReturnValue (@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { if (returnValue == null ) { mavContainer.setRequestHandled(true ); return ; } Callable<?> callable = (Callable<?>) returnValue; WebAsyncUtils.getAsyncManager(webRequest).startCallableProcessing(callable, mavContainer); } public void startCallableProcessing (final WebAsyncTask<?> webAsyncTask, Object... processingContext) throws Exception { Assert.notNull(webAsyncTask, "WebAsyncTask must not be null" ); Assert.state(this .asyncWebRequest != null , "AsyncWebRequest must not be null" ); Long timeout = webAsyncTask.getTimeout(); if (timeout != null ) { this .asyncWebRequest.setTimeout(timeout); } AsyncTaskExecutor executor = webAsyncTask.getExecutor(); if (executor != null ) { this .taskExecutor = executor; }else { logExecutorWarning(); } List<CallableProcessingInterceptor> interceptors = new ArrayList<>(); interceptors.add(webAsyncTask.getInterceptor()); interceptors.addAll(this .callableInterceptors.values()); interceptors.add(timeoutCallableInterceptor); final Callable<?> callable = webAsyncTask.getCallable(); final CallableInterceptorChain interceptorChain = new CallableInterceptorChain(interceptors); this .asyncWebRequest.addTimeoutHandler(() -> { if (logger.isDebugEnabled()) { logger.debug("Async request timeout for " + formatRequestUri()); } Object result = interceptorChain.triggerAfterTimeout(this .asyncWebRequest, callable); if (result != CallableProcessingInterceptor.RESULT_NONE) { setConcurrentResultAndDispatch(result); } }); this .asyncWebRequest.addErrorHandler(ex -> { if (!this .errorHandlingInProgress) { if (logger.isDebugEnabled()) { logger.debug("Async request error for " + formatRequestUri() + ": " + ex); } Object result = interceptorChain.triggerAfterError(this .asyncWebRequest, callable, ex); result = (result != CallableProcessingInterceptor.RESULT_NONE ? result : ex); setConcurrentResultAndDispatch(result); } }); this .asyncWebRequest.addCompletionHandler(() -> interceptorChain.triggerAfterCompletion(this .asyncWebRequest, callable)); interceptorChain.applyBeforeConcurrentHandling(this .asyncWebRequest, callable); startAsyncProcessing(processingContext); try { Future<?> future = this .taskExecutor.submit(() -> { Object result = null ; try { interceptorChain.applyPreProcess(this .asyncWebRequest, callable); result = callable.call(); }catch (Throwable ex) { result = ex; }finally { result = interceptorChain.applyPostProcess(this .asyncWebRequest, callable, result); } setConcurrentResultAndDispatch(result); }); interceptorChain.setTaskFuture(future); }catch (RejectedExecutionException ex) { Object result = interceptorChain.applyPostProcess(this .asyncWebRequest, callable, ex); setConcurrentResultAndDispatch(result); throw ex; } }