美文网首页
SpringMVC框架的HandlerAdapter

SpringMVC框架的HandlerAdapter

作者: 一根线条 | 来源:发表于2021-05-09 17:48 被阅读0次

    前面有讲到当请求到来时Springmvc是怎么查找Handler的,此时可能最配的Handler是一个继承自Controller接口的对象,可能是HttpRequestHandler的实现类,也可能是一个Servlet,或者是一个Method。有了这些匹配的Handler,接着还需要考虑如何让其被执行。

    在springmvc中抽象出了HandlerAdapter来完成各种类型的Handler的执行,当然,不同类型的Handler也会有一个与之对应的HandlerAdapter,毕竟不用的Handler其被执行的方法是不一样的。

    DispatcherServlet在初始化时会完成对HandlerAdapters的创建

        /**
         * Initialize the HandlerAdapters used by this class.
         * <p>If no HandlerAdapter beans are defined in the BeanFactory for this namespace,
         * we default to SimpleControllerHandlerAdapter.
         */
        private void initHandlerAdapters(ApplicationContext context) {
            this.handlerAdapters = null;
    
            if (this.detectAllHandlerAdapters) {
                // Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.
                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");
                }
            }
        }
    

    首先其会从ApplicationContext中获取HandlerAdapter类型的bean,如果没有找到则使用在spring-webmvc包下的DispatcherServlet.properties文件中配置的默认HandlerAdapter,如下所示:

    org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
        org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
        org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\
        org.springframework.web.servlet.function.support.HandlerFunctionAdapter
    

    在DispatcherServlet中,当找到对应的Handler后会通过以下代码来得到匹配的HandlerAdapter

        /**
         * Return the HandlerAdapter for this handler object.
         * @param handler the handler object to find an adapter for
         * @throws ServletException if no HandlerAdapter can be found for the handler. This is a fatal error.
         */
        protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
            if (this.handlerAdapters != null) {
                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");
        }
    

    可见,是将Handler最为参数来执行HandlerAdapter的supports方法来完成判断的,当找到后就会立即返回。

    接着我们来看下默认的这几个HandlerAdapter大致的实现

    1,HttpRequestHandlerAdapter

    public class HttpRequestHandlerAdapter implements HandlerAdapter {
    
        @Override
        public boolean supports(Object handler) {
            //只处理HttpRequestHandler的子类
            return (handler instanceof HttpRequestHandler);
        }
    
        @Override
        @Nullable
        public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
            //直接执行HttpRequestHandler的handleRequest方法来完成处理
            ((HttpRequestHandler) handler).handleRequest(request, response);
            return null;
        }
    
        @Override
        public long getLastModified(HttpServletRequest request, Object handler) {
            if (handler instanceof LastModified) {
                return ((LastModified) handler).getLastModified(request);
            }
            return -1L;
        }
    }
    

    2,SimpleControllerHandlerAdapter

    public class SimpleControllerHandlerAdapter implements HandlerAdapter {
    
        @Override
        public boolean supports(Object handler) {
            //只处理Controller的子类
            return (handler instanceof Controller);
        }
    
        @Override
        @Nullable
        public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
            //直接执行Controller的handleRequest方法来完成处理
            return ((Controller) handler).handleRequest(request, response);
        }
    
        @Override
        public long getLastModified(HttpServletRequest request, Object handler) {
            if (handler instanceof LastModified) {
                return ((LastModified) handler).getLastModified(request);
            }
            return -1L;
        }
    }
    

    3,RequestMappingHandlerAdapter

    针对Method为Handler的情况会复杂很多,里面涉及到参数的解析、返回值的处理、消息的转换(MessageConverter)等,后面可以针对该HandlerAdapter进行单独的分析,其最终的执行代码如下所示:

        /**
         * Invoke the {@link RequestMapping} handler method preparing a {@link ModelAndView}
         * if view resolution is required.
         * @since 4.2
         * @see #createInvocableHandlerMethod(HandlerMethod)
         */
        @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();
            }
        }
    

    不管如何,通过执行HandlerAdapter的handle方法最终返回了ModelAndView对象,有了ModelAndView对象后我们就可以找到对应的视图进行渲染并响应给客户端了。当然其实在执行handle的前后,HandlerExecutionChain中的拦截器就会被执行了。

    接下来就是View类型的对象可以登场的时候了。

    相关文章

      网友评论

          本文标题:SpringMVC框架的HandlerAdapter

          本文链接:https://www.haomeiwen.com/subject/tefvdltx.html