SpringMVC源码系列(五)HandlerAdapter中handle方法的调用过程

1.写在前面

笔者前面已经介绍过了如何获取对应的Handler,以及如何获取对应的HandlerAdapter,也就是从Url和方法的映射到找到对应的适配器,笔者已经讲完了。接下笔者讲的是如何调用,以及视图的解析。今天这篇博客要讲的就是HandlerAdapter的调用

2.HandlerAdapter的调用

笔者还是带大家看下原来的代码,具体的内容如下:

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);

			// Determine handler for the current request.
			mappedHandler = getHandler(processedRequest);
			if (mappedHandler == null) {
				noHandlerFound(processedRequest, response);
				return;
			}

			// Determine handler adapter for the current request.
			HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

			// Process last-modified header, if supported by the handler.
            //判断这个方法是get还是其他的方法
			String method = request.getMethod();
			boolean isGet = "GET".equals(method);
            //若是get或者head执行下面的操作
			if (isGet || "HEAD".equals(method)) {
                //默认的情况下都是返回-1
				long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                //一般的情况下不会进入
				if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
					return;
				}
			}

            //处理拦截器的方法,调用拦截器的preHandle方法,如果被拦截就直接返回
			if (!mappedHandler.applyPreHandle(processedRequest, response)) {
				return;
			}

			// Actually invoke the handler.
             // 本篇博客的重点
			mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
			
            //省略一部分代码
        }
    }
}

上面的代码先是调用拦截器的方法,如果被拦截下来了,就直接结束这个方法,如果没有被拦截,就执行对应的HandlerAdapter的中的handle方法。同样这儿也是有四个HandlerAdapter的方法要看。

2.1HttpRequestHandlerAdapter

这个类结构,笔者在上篇博客已经介绍,笔者在这里就不赘述了。我们还是看核心的handle方法,具体的代码如下:

public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
		throws Exception {

    //调用对应的实现类中handleRequest方法
	((HttpRequestHandler) handler).handleRequest(request, response);
    //返回值为空
	return null;
}

笔者再来带大家看下测试代码,具体的如下:

package com.ys.controller;

import org.springframework.stereotype.Component;
import org.springframework.web.HttpRequestHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component("/httpRequest.do")
public class HttpRequestHandlerController implements HttpRequestHandler {
    @Override
    public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.getWriter().write("hello");
    }
}

所以这种就很简单,就直接调用对应实现HttpRequestHandler接口的handleRequest()方法。

2.2SimpleControllerHandlerAdapter

废话不多说,直接看SimpleControllerHandlerAdapter这个类的handle方法,具体的代码如下:

public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

    //调用对应类的handleRequest方法
	return ((Controller) handler).handleRequest(request, response);
}

再来看下测试的代码,具体的如下:

package com.ys.controller;


import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component("/beanName.do")
public class BeanNameController implements Controller {

    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        return new ModelAndView("index");
    }
}

所以这种就很简单,就直接调用对应实现Controller接口的handleRequest()方法,同时这个方法的方法的返回值ModelAndView对象

2.3HandlerFunctionAdapter

这个类的handle()方法的代码如下:

public ModelAndView handle(HttpServletRequest servletRequest,
			HttpServletResponse servletResponse,
			Object handler) throws Exception {


	HandlerFunction<?> handlerFunction = (HandlerFunction<?>) handler;

	ServerRequest serverRequest = getServerRequest(servletRequest);
	ServerResponse serverResponse = handlerFunction.handle(serverRequest);

	return serverResponse.writeTo(servletRequest, servletResponse,
			new ServerRequestContext(serverRequest));
}

这块是webflux的知识,笔者后面会专门写一篇博客来介绍这块的内容,这儿暂且跳过吧。我们来看最后一个HandlerAdapter

2.4RequestMappingHandlerAdapter

照例还是先看handle()方法,具体的代码如下:

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

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

发现直接调用的是handleInternal()方法,具体的代码如下:

protected ModelAndView handleInternal(HttpServletRequest request,
		HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

	ModelAndView mav;
    //检查请求的会话是否支持
	checkRequest(request);

	// Execute invokeHandlerMethod in synchronized block if required.
    //默认的情况下这个值是false,所以会执行else中的代码
	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;
}

上面会调用Url映射的方法,主要是invokeHandlerMethod(request, response, handlerMethod);具体的代码如下:

protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
		HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

    //将request和response包装成ServletWebRequest对象
	ServletWebRequest webRequest = new ServletWebRequest(request, response);
	try {
        //返回Web数据绑定器工厂
		WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
        //返回模型工厂
		ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

        //返回要调用的方法
		ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
        //设置参数的解析器
		if (this.argumentResolvers != null) {
            //之前在调用afterPropertiesSet方法初始化的
			invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
		}
        //设置方法的返回类型参数
		if (this.returnValueHandlers != null) {
			invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
		}
        //设置对应的Web数据绑定器工厂
		invocableMethod.setDataBinderFactory(binderFactory);
        //设置对应的方法参数名发现器,就是用来查找方法的参数的名称的,因为jdk自带只会返回arg0
		invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);

        //创建模型和视图的容器
		ModelAndViewContainer mavContainer = new ModelAndViewContainer();
        //设置只读的input的属性
		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 {
		webRequest.requestCompleted();
	}
}

上面就进行一系列的参数的赋值,最后真正调用方法的是invokeAndHandle(webRequest, mavContainer);方法,具体的代码如下:

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

上面的代码最终调用映射的方法处理逻辑主要是在invokeForRequest(webRequest, mavContainer, providedArgs);具体的代码如下:

public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {

    //处理参数
	Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
	if (logger.isTraceEnabled()) {
		logger.trace("Arguments: " + Arrays.toString(args));
	}
    //通过反射调用方法
	return doInvoke(args);
}

上面的代码主要是通过getMethodArgumentValues(request, mavContainer, providedArgs);方法来获取参数,以及设置对应的参数,最后调用doInvoke(args);来执行对应的方法,主要是通过反射来调用。笔者先带大家看下处理参数的方法,具体的代码如下:

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);
        //这儿一般的情况下会返回null
		args[i] = findProvidedArgument(parameter, providedArgs);
		if (args[i] != null) {
			continue;
		}
        //查找对应的参数的处理器,主要是遍历所有的参数的处理器,调用处理中的support方法,只要满足就返回true
		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) {
			// Leave stack trace for later, exception may actually be resolved and handled...
			if (logger.isDebugEnabled()) {
				String exMsg = ex.getMessage();
				if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
					logger.debug(formatArgumentError(parameter, exMsg));
				}
			}
			throw ex;
		}
	}
	return args;
}

我们可以看下resolvers.supportsParameter(parameter),这个方法主要是查找指定的参数匹配器。具体的代码如下:

public boolean supportsParameter(MethodParameter parameter) {
	return getArgumentResolver(parameter) != null;
}
private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
    //先获取一篇参数的处理器
	HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
    //如果参数的处理器为空
	if (result == null) {
        //遍历所有的参数处理器,调用每一个参数处理器的supportsParameter方法,直达返回的结果为true为止
		for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) {
			if (resolver.supportsParameter(parameter)) {
				result = resolver;
				this.argumentResolverCache.put(parameter, result);
				break;
			}
		}
	}
	return result;
}

这个参数处理器的列表初始化,笔者在上篇博客中已经讲了,主要是通过调用afterPropertiesSet方法中来初始化的,具体的代码如下:

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

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

注意上面是加了两个RequestParamMethodArgumentResolver对象,只不过第一次的参数的值是false,第二次参数的值为true。那么这个两个值的区别是啥?我们还需要看RequestParamMethodArgumentResolver类的supportsParameter方法,具体的代码如下:

public boolean supportsParameter(MethodParameter parameter) {
	if (parameter.hasParameterAnnotation(RequestParam.class)) {
		if (Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType())) {
			RequestParam requestParam = parameter.getParameterAnnotation(RequestParam.class);
			return (requestParam != null && StringUtils.hasText(requestParam.name()));
		}
		else {
			return true;
		}
	}
	else {
		if (parameter.hasParameterAnnotation(RequestPart.class)) {
			return false;
		}
		parameter = parameter.nestedIfOptional();
		if (MultipartResolutionDelegate.isMultipartArgument(parameter)) {
			return true;
		}
        //区别在这,如果是true的话,基本的类型是会返回true,如果不是true,就直接跳过
		else if (this.useDefaultResolution) {
			return BeanUtils.isSimpleProperty(parameter.getNestedParameterType());
		}
		else {
			return false;
		}
	}
}

区别就在于如果是true的话,基本的类型是会返回true,如果不是true,就直接跳过,所以上面在调用所有参数的处理器中的supportsParameter方法的时候,第一次RequestParamMethodArgumentResolver是匹配不成功,只有第二次的时候才能匹配成功,因为这个useDefaultResolution值第二次的时候为true。既然找对应的参数处理器的规则已经搞懂了,我们继续看原来的代码。

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);
        //这儿一般的情况下会返回null
		args[i] = findProvidedArgument(parameter, providedArgs);
		if (args[i] != null) {
			continue;
		}
        //查找对应的参数的处理器,主要是遍历所有的参数的处理器,调用处理中的support方法,只要满足就返回true
		if (!this.resolvers.supportsParameter(parameter)) {//如果这儿没有找到对应的参数处理器的话,就直接抛出异常
			throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
		}
		try {
            //找到了就直接执行参数处理器的resolveArgument方法
			args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
		}
		catch (Exception ex) {
			// Leave stack trace for later, exception may actually be resolved and handled...
			if (logger.isDebugEnabled()) {
				String exMsg = ex.getMessage();
				if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
					logger.debug(formatArgumentError(parameter, exMsg));
				}
			}
			throw ex;
		}
	}
	return args;
}

这个时候如果没有找到对应的参数处理器的话,就直接抛出异常,如果找到了就执行这个参数处理器的resolveArgument方法,具体的代码如下:

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("Unsupported parameter type [" +
				parameter.getParameterType().getName() + "]. supportsParameter should be called first.");
	}
	return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
}

然后调用这个参数处理器的resolveArgument的方法,我们继续跟进,具体的代码如下:

public final Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {

    //获取方法的参数的名称
	NamedValueInfo namedValueInfo = getNamedValueInfo(parameter);
    //获取包装的方法的参数的类型
	MethodParameter nestedParameter = parameter.nestedIfOptional();

    //解析这个字符串的值
	Object resolvedName = resolveStringValue(namedValueInfo.name);
	if (resolvedName == null) {
		throw new IllegalArgumentException(
				"Specified name must not resolve to null: [" + namedValueInfo.name + "]");
	}

    //调用子类RequestParamMethodArgumentResolver来获取参数的值
	Object arg = resolveName(resolvedName.toString(), nestedParameter, webRequest);
	if (arg == null) {//获取的值为空
		if (namedValueInfo.defaultValue != null) {//查看是否有默认值,设置默认值
			arg = resolveStringValue(namedValueInfo.defaultValue);
		}
		else if (namedValueInfo.required && !nestedParameter.isOptional()) {//判断是否是必须要值,如果是直接抛出异常
			handleMissingValue(namedValueInfo.name, nestedParameter, webRequest);
		}
        //处理空值,如果这个值的类型是Boolean类型,就设置为false,其他的情况下都是原来的默认值
		arg = handleNullValue(namedValueInfo.name, arg, nestedParameter.getNestedParameterType());
	}
	else if ("".equals(arg) && namedValueInfo.defaultValue != null) { //获取值为“”同时默认值也不为空,那么就将默认值设置进去
		arg = resolveStringValue(namedValueInfo.defaultValue);
	}

    //下面是进行对应的参数的转换,因为接受过来的一般都是string的类型
	if (binderFactory != null) {
		WebDataBinder binder = binderFactory.createBinder(webRequest, null, namedValueInfo.name);
		try {
			arg = binder.convertIfNecessary(arg, parameter.getParameterType(), parameter);
		}
		catch (ConversionNotSupportedException ex) {
			throw new MethodArgumentConversionNotSupportedException(arg, ex.getRequiredType(),
					namedValueInfo.name, parameter, ex.getCause());
		}
		catch (TypeMismatchException ex) {
			throw new MethodArgumentTypeMismatchException(arg, ex.getRequiredType(),
					namedValueInfo.name, parameter, ex.getCause());
		}
	}

    //这儿不没有重写对应的方法,所以是个空的方法。
	handleResolvedValue(arg, namedValueInfo.name, parameter, mavContainer, webRequest);
	
    //返回处理好的参数的
	return arg;
}

由于RequestParamMethodArgumentResolver类没有实现HandlerMethodArgumentResolver接口,所以这儿调用的是父类的resolveArgument方法,但是获取对应参数的值是调用子类RequestParamMethodArgumentResolverresolveName方法,具体的代码如下:

protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
	HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class);
    
	if (servletRequest != null) {
		Object mpArg = MultipartResolutionDelegate.resolveMultipartArgument(name, parameter, servletRequest);
		if (mpArg != MultipartResolutionDelegate.UNRESOLVABLE) {
			return mpArg;
		}
	}

	Object arg = null;
    //处理文件的
	MultipartRequest multipartRequest = request.getNativeRequest(MultipartRequest.class);
	if (multipartRequest != null) {
		List<MultipartFile> files = multipartRequest.getFiles(name);
		if (!files.isEmpty()) {
			arg = (files.size() == 1 ? files.get(0) : files);
		}
	}
	if (arg == null) {
        //还是用servlet的api
		String[] paramValues = request.getParameterValues(name);
		if (paramValues != null) {
			arg = (paramValues.length == 1 ? paramValues[0] : paramValues);
		}
	}
	return arg;
}

我们终于看到对应的参数的获取的方法,就是利用了servlet的api来获取指定的参数的值的。最后返回出去。最后就是通过反射调用对应的方法,我们继续看剩下的代码

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {

	Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
    //设置响应的状态码,这儿应该没有调用完,会是null
	setResponseStatus(webRequest);

    //如果返回值为空
	if (returnValue == null) {
		if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
            //禁用缓存
			disableContentCachingIfNecessary(webRequest);
            //将这个变量设置为true
			mavContainer.setRequestHandled(true);
			return;
		}
	}
	else if (StringUtils.hasText(getResponseStatusReason())) {//这个有值
        //将这个变量设置为true
		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;
	}
}

上面的代码会调用handleReturnValue(),具体的代码如下:

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

上面的代码主要是通过selectHandler(returnValue, returnType);来查找对应的方法返回值的处理器,具体的代码如下:

private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {
    //判断是否是异步
	boolean isAsyncValue = isAsyncReturnValue(value, returnType);
    //遍历所有的方法返回值的处理器的supportsReturnType方法,只要找到匹配的就直接返回
	for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {
		if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) {
			continue;
		}
		if (handler.supportsReturnType(returnType)) {
			return handler;
		}
	}
	return null;
}

这儿原理和上面的找方法参数的处理器的机制差不多,都是遍历所有的处理器,调用对应处理器的supportsReturnType方法,一旦满足条件的话,就直接返回。至此整个方法的调用的过程就讲完了,简单总结一下:先根据方法的参数,遍历所有的参数处理器,分别调用处理器中的supportsParameter方法,如果满足了就直接返回这个参数处理器,然后调用这个参数处理器的resolveArgument方法,最后还有对方法的返回值进行处理,还是一样的先是遍历所有返回值处理器的,并且调用这些处理器中的supportsReturnType方法,如果满足的话,就直接返回这个处理器,同时会调用这个处理器的handleReturnValue方法对方法的返回值进行处理和封装。最后调用的getModelAndView()方法,具体的代码如下:

private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
			ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {

	modelFactory.updateModel(webRequest, mavContainer);
    //判断这个值是否是true,一般返回的如果不是视图的话,这个值就是true
	if (mavContainer.isRequestHandled()) {
		return null;
	}
	ModelMap model = mavContainer.getModel();
	ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());
	if (!mavContainer.isViewReference()) {
		mav.setView((View) mavContainer.getView());
	}
	if (model instanceof RedirectAttributes) {
		Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
		HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
		if (request != null) {
			RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
		}
	}
	return mav;
}

上面的代码获取的ModelAndView并不是真正的模型视图对象,这个笔者后面的博客会讲清楚。然后就返回到对应代码地方,具体的如下:

protected ModelAndView handleInternal(HttpServletRequest request,
		HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
	
    //省略一部分代码
    
	mav = invokeHandlerMethod(request, response, handlerMethod);

	if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
		if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
			applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
		}
		else {
			prepareResponse(response);
		}
	}

	return mav;
}

这个时候映射的方法调用已经结束,后面都是一些赋值,就直接跳过了,不是核心的代码。

3.写在最后

这边博客主要讲了调用几大HandlerAdapter的handle的调用的过程,已经其中的处理逻辑,后面的博客就要讲视图的解析的过程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值