SpringMVC源码(七)- doDispatch - RequestMappingHandlerAdapter的handle(方法的调用)

目录

一、RequestMappingHandlerAdapter结构

1、完成ControllerAdvice注解相关初始化

2、各种类型的解析器站初始化

1)、argumentResolvers 初始化:

2)、initBinderArgumentResolvers(数据绑定解析器列表)初始化:

3)、returnValueHandlers 初始化:

二、RequestMappingHandlerAdapter的handle方法

1、invokeHandlerMethod

2、invokeForRequest(调用真实请求方法)

1)、getMethodArgumentValues(参数解析)

2)、doInvoke(真正的Controller方法调用)

3、handleReturnValue(解析方法调用的结果)

总结


一、RequestMappingHandlerAdapter结构

    从层级结构看,主要实现了BeanFactoryAware、ApplicationContextAware、HandlerAdapter和InitializingBean。其他回调方法都是常规赋值,主要准备工作在afterPropertiesSet回调方法中完成。

@Override
public void afterPropertiesSet() {
    // Do this first, it may add ResponseBody advice beans 初始化ControllerAdvice注解相关
    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);
    }
}

1、完成ControllerAdvice注解相关初始化

    @InitBind、@ModelAttribute、@ExceptionHandler相关初始化。后续专门分析。

2、各种类型的解析器站初始化

    初始化了非常多各种类型的解析器,也能想象还是会按照HandlerMapping和HandlerAdaptor一样挨个去在各个阶段进行适配。工程量非常庞大,只能按照最常用的进行分析。

1)、argumentResolvers 初始化:

private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
    List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();

    // Annotation-based argument resolution
    resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
    resolvers.add(new RequestParamMapMethodArgumentResolver());
    resolvers.add(new PathVariableMethodArgumentResolver());
    resolvers.add(new PathVariableMapMethodArgumentResolver());
    resolvers.add(new MatrixVariableMethodArgumentResolver());
    resolvers.add(new MatrixVariableMapMethodArgumentResolver());
    resolvers.add(new ServletModelAttributeMethodProcessor(false));
    resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
    resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice));
    resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
    resolvers.add(new RequestHeaderMapMethodArgumentResolver());
    resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
    resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
    resolvers.add(new SessionAttributeMethodArgumentResolver());
    resolvers.add(new RequestAttributeMethodArgumentResolver());

    // Type-based argument resolution
    resolvers.add(new ServletRequestMethodArgumentResolver());
    resolvers.add(new ServletResponseMethodArgumentResolver());
    resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
    resolvers.add(new RedirectAttributesMethodArgumentResolver());
    resolvers.add(new ModelMethodProcessor());
    resolvers.add(new MapMethodProcessor());
    resolvers.add(new ErrorsMethodArgumentResolver());
    resolvers.add(new SessionStatusMethodArgumentResolver());
    resolvers.add(new UriComponentsBuilderMethodArgumentResolver());

    // Custom arguments
    if (getCustomArgumentResolvers() != null) {
        resolvers.addAll(getCustomArgumentResolvers());
    }

    // Catch-all
    resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
    resolvers.add(new ServletModelAttributeMethodProcessor(true));

    return resolvers;
}

2)、initBinderArgumentResolvers(数据绑定解析器列表)初始化:

private List<HandlerMethodArgumentResolver> getDefaultInitBinderArgumentResolvers() {
    List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();

    // Annotation-based argument resolution
    resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
    resolvers.add(new RequestParamMapMethodArgumentResolver());
    resolvers.add(new PathVariableMethodArgumentResolver());
    resolvers.add(new PathVariableMapMethodArgumentResolver());
    resolvers.add(new MatrixVariableMethodArgumentResolver());
    resolvers.add(new MatrixVariableMapMethodArgumentResolver());
    resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
    resolvers.add(new SessionAttributeMethodArgumentResolver());
    resolvers.add(new RequestAttributeMethodArgumentResolver());

    // Type-based argument resolution
    resolvers.add(new ServletRequestMethodArgumentResolver());
    resolvers.add(new ServletResponseMethodArgumentResolver());

    // Custom arguments
    if (getCustomArgumentResolvers() != null) {
        resolvers.addAll(getCustomArgumentResolvers());
    }

    // Catch-all
    resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));

    return resolvers;
}

3)、returnValueHandlers 初始化:

private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
    List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>();

    // Single-purpose return value types
    handlers.add(new ModelAndViewMethodReturnValueHandler());
    handlers.add(new ModelMethodProcessor());
    handlers.add(new ViewMethodReturnValueHandler());
    handlers.add(new ResponseBodyEmitterReturnValueHandler(getMessageConverters(),
            this.reactiveAdapterRegistry, this.taskExecutor, this.contentNegotiationManager));
    handlers.add(new StreamingResponseBodyReturnValueHandler());
    handlers.add(new HttpEntityMethodProcessor(getMessageConverters(),
            this.contentNegotiationManager, this.requestResponseBodyAdvice));
    handlers.add(new HttpHeadersReturnValueHandler());
    handlers.add(new CallableMethodReturnValueHandler());
    handlers.add(new DeferredResultMethodReturnValueHandler());
    handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));

    // Annotation-based return value types
    handlers.add(new ModelAttributeMethodProcessor(false));
    handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(),
            this.contentNegotiationManager, this.requestResponseBodyAdvice));

    // Multi-purpose return value types
    handlers.add(new ViewNameMethodReturnValueHandler());
    handlers.add(new MapMethodProcessor());

    // Custom return value types
    if (getCustomReturnValueHandlers() != null) {
        handlers.addAll(getCustomReturnValueHandlers());
    }

    // Catch-all
    if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) {
        handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers()));
    } else {
        handlers.add(new ModelAttributeMethodProcessor(true));
    }

    return handlers;
}

二、RequestMappingHandlerAdapter的handle方法

    继续回到DispatcherServlet#doDispatch方法,会适配到RequestMappingHandlerAdapter执行handle方法,在父类AbstractHandlerMethodAdapter中实现:

@Override
@Nullable
public final ModelAndView handle(HttpServletRequest request, 
    HttpServletResponse response, Object handler) throws Exception {

    return handleInternal(request, response, (HandlerMethod) handler);
}

    再调用到RequestMappingHandlerAdapter自己实现:

@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;
}

    1、验证请求

    2、判断是否要在synchronized 关键字中执行该调用(默认为false,这样会很影响性能,不好控制)

    3、真实的方法调用(invokeHandlerMethod)

    4、对Header的处理(Cache-ControlPragmaExpires等)

 

1、invokeHandlerMethod

@Nullable
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
    HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
    // 将request和response放到一个对象中进行请求
    ServletWebRequest webRequest = new ServletWebRequest(request, response);
    try {
        // 数据绑定工厂(处理@InitBinder)、和Model工厂(处理@ModelAttribute)
        WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
        ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
        // 组装调用方法,afterPropertiesSet时初始化的解析器
        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;
        }
        // 获取ModelAndView,返回
        return getModelAndView(mavContainer, modelFactory, webRequest);
    } finally {
        // 执行回调,http session相关处理
        webRequest.requestCompleted();
    }
}

    为方法的真实调用进行了各种准备,真实的调用方法为ServletInvocableHandlerMethodinvokeAndHandle方法:

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
                            Object... providedArgs) throws Exception {
    // 真是的Controller方法调用
    Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
    // 设置response状态(200、404、500等)
    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);
    // 省略try catch代码; 解析返回值
    this.returnValueHandlers.handleReturnValue(
        returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}

    1、Controller中的真实方法的调用

    2、Http返回编码设置

    3、返回值短路解析

    4、返回值适配解析

 

2、invokeForRequest(调用真实请求方法)

@Nullable
public Object invokeForRequest(NativeWebRequest request, 
    @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
    // 参数解析(将原始参数进行解析绑定等操作,后续详细分析)
    Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
    // 进行真实Controller方法调用,返回结果
    return doInvoke(args);
}

1)、getMethodArgumentValues(参数解析)

protected Object[] getMethodArgumentValues(NativeWebRequest request, 
    @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
    
    MethodParameter[] parameters = getMethodParameters();
    if (ObjectUtils.isEmpty(parameters)) {
        return EMPTY_ARGS;
    }
    
    Object[] args = new Object[parameters.length];
    for (int i = 0; i < parameters.length; i++) {
        MethodParameter parameter = parameters[i];
        parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
        args[i] = findProvidedArgument(parameter, providedArgs);
        if (args[i] != null) {
            continue;
        }
        if (!this.resolvers.supportsParameter(parameter)) {
            throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
        }
        try {
            args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
        } catch (Exception ex) {
            // 省略日志打印
            throw ex;
        }
    }
    return args;
}

    当前获取的MethodParameter为我们自己传入的方法调用参数,遍历该参数数组。每个参数再去遍历resolversHandlerMethodArgumentResolverComposite)中的HandlerMethodArgumentResolver去适配。其类型是上面afterPropertiesSet方法中初始化完成的。如下:

    遍历适配,并且添加到缓存中。其实在上一步(supportsParameter方法)调用时就遍历了,添加到缓存中了。适配到后调用resolveArgument方法进行解析。

@Nullable
private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
    HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
    if (result == null) {
        for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) {
            if (resolver.supportsParameter(parameter)) {
                result = resolver;
                this.argumentResolverCache.put(parameter, result);
                break;
            }
        }
    }
    return result;
}
@Override
@Nullable
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
                              NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {

    HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
    if (resolver == null) {
        throw new IllegalArgumentException("省略");
    }
    return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
}

 

2)、doInvoke(真正的Controller方法调用)

@Nullable
protected Object doInvoke(Object... args) throws Exception {
    ReflectionUtils.makeAccessible(getBridgedMethod());
    try {
        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);
        }
    }
}

    直接使用反射调用Controller中的方法,获取返回值。调用之前先将Accessible设置为true,那样应该private的方法应该也是能反射调用的,刚才试了一下,将Controller方法修改为private确实是ok的。只是需要注意的是当前反射的getBean()获取的不一定是我们需要调用的Controller类,有可能是ExceptionHandler注解修改的方法的类。

 

3、handleReturnValue(解析方法调用的结果)

this.returnValueHandlers.handleReturnValue(
    returnValue, getReturnValueType(returnValue), mavContainer, webRequest);

    还是同样的afterPropertiesSet时初始化的类型,挨个进行适配返回值。再调用适配到的HandlerMethodReturnValueHandlerhandleReturnValue方法,并在其处理了结果时候会设置ModelAndViewContainer的requestHandled为true,表示已经处理了结果。上层的getModelAndView是会首先判断该标识,否则就解析结果。

@Override
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
                              ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {

    HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
    if (handler == null) {
        throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
    }
    handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}
@Nullable
private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {
    boolean isAsyncValue = isAsyncReturnValue(value, returnType);
    for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {
        if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) {
            continue;
        }
        if (handler.supportsReturnType(returnType)) {
            return handler;
        }
    }
    return null;
}

    

总结

    1、在handler中先是对请求参数进行了处理。也就是说时的参数已经不是我们表面上看到的参数本身了(比如各种注解综合处理后)。

    2、对具体的HandlerMethod(Controller中的具体需要调用的业务方法)方法使用反射进行调用。

    3、对返回结果进行处理(returnValueHandlers的轮训适配处理)。

    4.、如果上一步没有处理完全(根据requestHandled判断),则会在getModelAndView中处理ModelAndView

    5、最终在上层的processDispatchResult方法中完成视图解析。

 

    由于不同的返回值,处理方式完成不同。比如@ResponseBody修饰方法;返回标准的ModelAndView; 返回值只有字符串(View为字符串类型); @ControllerAdvice注解修饰;等。

    后面会基于Spring 5.2.0版本,对常用的不同情况进行分析。

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值