spring boot DispatcherServlet(三)handler执行

本文深入探讨了Spring Boot DispatcherServlet中handler的执行过程,包括handle方法、参数解析与执行、@RequestBody处理以及结果转换的详细步骤。文章剖析了HandlerAdapter如何调用handleInternal方法,进而触发handler方法的执行,解析请求参数,使用HandlerMethodArgumentResolverComposite进行转换,并通过RequestResponseBodyMethodProcessor将请求体转换为Java对象。最后,文章还介绍了结果转换的流程,涉及HandlerMethodReturnValueHandler的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

handler 执行

之前的文章介绍到,当根据请求找到对应的handler之后,会根据这个handler找到对应的HandlerAdapter,解析来会调用handle方法来处理请求

// DispatcherServlet.java
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

handle

接下来看下HandlerAdapter是如何执行的
当调用handle时,主要会调用handleInternal方法

// RequestMappingHandlerAdapter.java
protected ModelAndView handleInternal(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

	ModelAndView mav;
	checkRequest(request);

	// Execute invokeHandlerMethod in synchronized block if required.
	// 判断是否设置了synchronizeOnSession
	// 如果设置了,那么对于同一个session,会同步执行
	// 默认这个是关闭的
	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;
}

接下来看下invokeHandlerMethod
handler处理请求返回ModelAndView就是在这个地方进行的

// RequestMappingHandlerAdapter.java
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

	ServletWebRequest webRequest = new ServletWebRequest(request, response);
	try {
		// WebDataBinder的工厂, WebDataBinder用来将web请求中的参数绑定到java对象上
		WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
		ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
		ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
		// 如果指定了HandlerMethodArgumentResolverComposite,那么设置到invocableMethod上
		if (this.argumentResolvers != null) {
			invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
		}
		// 如果指定了HandlerMethodReturnValueHandlerComposite,那么设置到invocableMethod上
		if (this.returnValueHandlers != null) {
			invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
		}
		invocableMethod.setDataBinderFactory(binderFactory);
		invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);

		ModelAndViewContainer mavContainer = new ModelAndViewContainer();
		mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
		// 这里会将通过使用@SessionAttributes注解指定的session属性,设置到model中
		// 另外会执行@ModelAttributes注解的方法,在真正执行处理逻辑之前,将一些属性添加到model中
		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();
	}
}

getDataBinderFactory

// RequestMappingHandlerAdapter.java
private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception {
	// 返回handler的类型
	Class<?> handlerType = handlerMethod.getBeanType();
	// 获取当前handler可以使用的属性编辑器,包括全局的和当前handler自有的
	// @InitBinder用来为当前handler指定使用的属性编辑器,即如何将请求中的参数转换为java对象
	Set<Method> methods = this.initBinderCache.get(handlerType);
	if (methods == null) {
		methods = MethodIntrospector.selectMethods(handlerType, INIT_BINDER_METHODS);
		this.initBinderCache.put(handlerType, methods);
	}
	List<InvocableHandlerMethod> initBinderMethods = new ArrayList<>();
	// Global methods first
	// 首先会获取全局的InitBinder,即在使用了@ControllerAdvice注解的类中使用了@InitBinder注解的方法,将这些InitBinder添加到initBinderMethods集合中
	this.initBinderAdviceCache.forEach((controllerAdviceBean, methodSet) -> {
		// 判断指定的ControllerAdvice是否能够作用到当前类
		// 通过@ControllerAdvice注解的basePackage basePackageClass assignableType annontation等属性来判断
		if (controllerAdviceBean.isApplicableToBeanType(handlerType)) {
			Object bean = controllerAdviceBean.resolveBean();
			for (Method method : methodSet) {
				initBinderMethods.add(createInitBinderMethod(bean, method));
			}
		}
	});
	// 处理当前handler中使用了@InitBinder注解的方法
	for (Method method : methods) {
		Object bean = handlerMethod.getBean();
		initBinderMethods.add(createInitBinderMethod(bean, method));
	}
	return createDataBinderFactory(initBinderMethods);
}

接着看下createInitBinderMethod方法,该方法用来对当前bean和待执行的方法创建一个InvocableHanderMethod

// RequestMappingHandlerAdapter.java
private InvocableHandlerMethod createInitBinderMethod(Object bean, Method method) {
	InvocableHandlerMethod binderMethod = new InvocableHandlerMethod(bean, method);
	if (this.initBinderArgumentResolvers != null) {
		binderMethod.setHandlerMethodArgumentResolvers(this.initBinderArgumentResolvers);
	}
	binderMethod.setDataBinderFactory(new DefaultDataBinderFactory(this.webBindingInitializer));
	binderMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
	return binderMethod;
}

getModelFactory

和上面相同的方法来处理@ModelAttribute注解

// RequestMappingHandlerAdapter.java
private ModelFactory getModelFactory(HandlerMethod handlerMethod, WebDataBinderFactory binderFactory) {
	SessionAttributesHandler sessionAttrHandler = getSessionAttributesHandler(handlerMethod);
	Class<?> handlerType = handlerMethod.getBeanType();
	Set<Method> methods = this.modelAttributeCache.get(handlerType);
	if (methods == null) {
		methods = MethodIntrospector.selectMethods(handlerType, MODEL_ATTRIBUTE_METHODS);
		this.modelAttributeCache.put(handlerType, methods);
	}
	List<InvocableHandlerMethod> attrMethods = new ArrayList<>();
	// Global methods first
	this.modelAttributeAdviceCache.forEach((controllerAdviceBean, methodSet) -> {
		if (controllerAdviceBean.isApplicableToBeanType(handlerType)) {
			Object bean = controllerAdviceBean.resolveBean();
			for (Method method : methodSet) {
				attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
			}
		}
	});
	for (Method method : methods) {
		Object bean = handlerMethod.getBean();
		attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
	}
	return new ModelFactory(attrMethods, binderFactory, sessionAttrHandler);
}

invokeAndHandle

// ServletInvocableHandlerMethod.java
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
	// 1. 将web请求中的参数转换成java对象,并且将这些java对象作为参数传给controller的指定方法执行
	// 主要处理逻辑就在这里
	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");
	// 2. 对方法执行的结果进行处理
	try {
		this.returnValueHandlers.handleReturnValue(
				returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
	}
	catch (Exception ex) {
		if (logger.isTraceEnabled()) {
			logger.trace(formatErrorForReturnValue(returnValue), ex);
		}
		throw ex;
	}
}
参数解析与执行
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
	// 从request中提取当前方法需要使用的参数
	Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
	if (logger.isTraceEnabled()) {
		logger.trace("Arguments: " + Arrays.toString(args));
	}
	return doInvoke(args);
}
参数转换
// InvocableHandlerMethod.java
protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
	// 获取到当前需要执行的controller方法的参数列表
	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);
		// providedArgs默认为空
		// 这里会判断当前providedArgs中是否有当前遍历的方法参数类型的实例,如果有,将providedArgs中对应的值作为参数的值
		args[i] = findProvidedArgument(parameter, providedArgs);
		if (args[i] != null) {
			continue;
		}
		// 如果providedArgs中没有当前参数类型的实例,那么会尝试通过HandlerMethodArgumentResolverComposite来从request中来解析对应的参数
		// 这里会判断resolvers是否支持当前类型参数的解析
		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;
}
Resolver的注册

从上面的代码可以看到,从request中解析参数的主要逻辑集中在使用HandlerMethodArgumentResolverComposite来从request中解析参数
那么HandlerMethodArgumentResolverComposite是从哪里来的呢?
我们知道,InvocableHandlerMethod是在RequestMappingHandlerAdapter中创建的,其中有如下的代码

// RequestMappingHandlerAdapter.java
if (this.argumentResolvers != null) {
	invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
}

可以看出InvocableHandlerMethod的HandlerMethodArgumentResolverComposite是由RequestMappingHandlerAdapter传进来的
那么RequestMappingHandlerAdapter的HandlerMethodArgumentResolverComposite又是怎么来的呢
RequestMappingHandlerAdapter实现了InitializingBean,所以我们看下afterPropertiesSet方法

// RequestMappingHandlerAdapter.java
public void afterPropertiesSet() {
	// Do this first, it may add ResponseBody advice beans
	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);
	}
}

接着看getDefaultArgumentResolvers,可以看到,默认情况下,会返回如下Resolver

// RequestMappingHandlerAdapter.java
private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
	List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>(30);

	// 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());
	if (KotlinDetector.isKotlinPresent()) {
		resolvers.add(new ContinuationHandlerMethodArgumentResolver());
	}

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

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

	return resolvers;
}
执行转换

接着看下HandlerMethodArgumentResolverComposite的resolveArgument方法

// HandlerMethodArgumentResolverComposite.java
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
	// 遍历resolver,找到能够解析当前参数的resolver
	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);
}
// HandlerMethodArgumentResolverComposite.java
private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
	// 首先会从缓存中获取支持当前参数的resolver
	HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
	if (result == null) {
		// 缓存中没有,遍历所有的resolver,找到支持当前参数的resolver,然后放到缓存中
		for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) {
			if (resolver.supportsParameter(parameter)) {
				result = resolver;
				this.argumentResolverCache.put(parameter, result);
				break;
			}
		}
	}
	return result;
}
@RequestBody的处理

这里以使用了@RequestBody的参数为例,栗子是这样的,通过@RequestBody将post body转换成一个Java对象

@RequestMapping(value = "/hello", method = RequestMethod.POST)
public String hello(@RequestBody TestParam param) {
    return String.format("name:%s,age:%d", param.getName(), param.getAge());
}

通过debug可知,此时使用的resolver是RequestResponseMethodProcessor
在这里插入图片描述
接下来详细看下这个类是如何将request转换成java对象的

supportsParameter
// RequestResponseBodyMethodProcessor.java
@Override
public boolean supportsParameter(MethodParameter parameter) {
	return parameter.hasParameterAnnotation(RequestBody.class);
}
resolveArgument

上面的代码比较简单,就是判断参数是否使用了@RequestBody注解
下面看下resolveArgument

// RequestResponseBodyMethodProcessor.java
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
	// 获取参数的真实类型
	parameter = parameter.nestedIfOptional();
	// 这里生成的arg就是最终解析好的TestParam类型的参数
	Object arg = readWithMessageConverters(webRequest, parameter, parameter.getNestedGenericParameterType());
	// 获取参数的名称
	String name = Conventions.getVariableNameForParameter(parameter);

	// 对转换后的结果进行校验
	if (binderFactory != null) {
		// 这里如果参数使用了Validated注解,那么会对该参数进行校验
		WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name);
		if (arg != null) {
			validateIfApplicable(binder, parameter);
			// 如果转换失败,会抛出异常
			if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
				throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());
			}
		}
		if (mavContainer != null) {
			mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());
		}
	}
	// 对Optional类型的参数进行处理
	return adaptArgumentIfNecessary(arg, parameter);
}

下面是获取参数真实类型的代码,主要是判断如果当前参数使用了Optional进行包裹,那么取出包裹的类型

// RequestResponseBodyMethodProcessor.java
public MethodParameter nestedIfOptional() {
    return this.getParameterType() == Optional.class ? this.nested() : this;
}

下面的代码也是对Optional类型的参数的处理,当解析完参数的值后,如果参数使用了Optional进行包裹,那么会走下面的逻辑,比较简单

// RequestResponseBodyMethodProcessor.java
protected Object adaptArgumentIfNecessary(@Nullable Object arg, MethodParameter parameter) {
	if (parameter.getParameterType() == Optional.class) {
		if (arg == null || (arg instanceof Collection && ((Collection<?>) arg).isEmpty()) ||
				(arg instanceof Object[] && ((Object[]) arg).length == 0)) {
			return Optional.empty();
		}
		else {
			return Optional.of(arg);
		}
	}
	return arg;
}
readWithMessageConverters

下面详细看下其中完成request到java对象转换的readWithMessageConverters

// RequestResponseBodyMethodProcessor.java
protected <T> Object readWithMessageConverters(NativeWebRequest webRequest, MethodParameter parameter,
			Type paramType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException {

	HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
	Assert.state(servletRequest != null, "No HttpServletRequest");
	ServletServerHttpRequest inputMessage = new ServletServerHttpRequest(servletRequest);

	Object arg = readWithMessageConverters(inputMessage, parameter, paramType);
	if (arg == null && checkRequired(parameter)) {
		throw new HttpMessageNotReadableException("Required request body is missing: " +
				parameter.getExecutable().toGenericString(), inputMessage);
	}
	return arg;
}
// RequestResponseBodyMethodProcessor.java
protected <T> Object readWithMessageConverters(HttpInputMessage inputMessage, MethodParameter parameter,
			Type targetType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException {

	MediaType contentType;
	boolean noContentType = false;
	try {
		contentType = inputMessage.getHeaders().getContentType();
	}
	catch (InvalidMediaTypeException ex) {
		throw new HttpMediaTypeNotSupportedException(ex.getMessage());
	}
	if (contentType == null) {
		noContentType = true;
		contentType = MediaType.APPLICATION_OCTET_STREAM;
	}

	// 获取当前hanler的类型,也就是Controller的类型
	Class<?> contextClass = parameter.getContainingClass();
	// 获取参数的类型
	Class<T> targetClass = (targetType instanceof Class ? (Class<T>) targetType : null);
	if (targetClass == null) {
		ResolvableType resolvableType = ResolvableType.forMethodParameter(parameter);
		targetClass = (Class<T>) resolvableType.resolve();
	}

	// 获取请求的method,get post之类的
	HttpMethod httpMethod = (inputMessage instanceof HttpRequest ? ((HttpRequest) inputMessage).getMethod() : null);
	Object body = NO_VALUE;

	EmptyBodyCheckingHttpInputMessage message;
	try {
		message = new EmptyBodyCheckingHttpInputMessage(inputMessage);

		for (HttpMessageConverter<?> converter : this.messageConverters) {
			Class<HttpMessageConverter<?>> converterType = (Class<HttpMessageConverter<?>>) converter.getClass();
			GenericHttpMessageConverter<?> genericConverter =
					(converter instanceof GenericHttpMessageConverter ? (GenericHttpMessageConverter<?>) converter : null);
			// 判断当前converter是否支持当前的读取操作
			// 最终这个例子中选择的是MappingJackson2HttpMessageConverter来进行处理
			if (genericConverter != null ? genericConverter.canRead(targetType, contextClass, contentType) :
					(targetClass != null && converter.canRead(targetClass, contentType))) {
				// 如果有请求体,那么会执行RequestBodyAdvice的aop操作,在读取body之前和读取body之后进行处理
				// RequestBodyAdvice的作用就是在解析使用了@RequestBody注解的属性时进行aop操作
				if (message.hasBody()) {
					// 读取request body之前的前置操作
					HttpInputMessage msgToUse =
							getAdvice().beforeBodyRead(message, parameter, targetType, converterType);
					body = (genericConverter != null ? genericConverter.read(targetType, contextClass, msgToUse) :
							((HttpMessageConverter<T>) converter).read(targetClass, msgToUse));
					// 读取request body之后的后置操作
					body = getAdvice().afterBodyRead(body, msgToUse, parameter, targetType, converterType);
				}
				else {
					body = getAdvice().handleEmptyBody(null, message, parameter, targetType, converterType);
				}
				break;
			}
		}
	}
	catch (IOException ex) {
		throw new HttpMessageNotReadableException("I/O error while reading input message", ex, inputMessage);
	}

	if (body == NO_VALUE) {
		if (httpMethod == null || !SUPPORTED_METHODS.contains(httpMethod) ||
				(noContentType && !message.hasBody())) {
			return null;
		}
		throw new HttpMediaTypeNotSupportedException(contentType,
				getSupportedMediaTypes(targetClass != null ? targetClass : Object.class));
	}

	MediaType selectedContentType = contentType;
	Object theBody = body;
	LogFormatUtils.traceDebug(logger, traceOn -> {
		String formatted = LogFormatUtils.formatValue(theBody, !traceOn);
		return "Read \"" + selectedContentType + "\" to [" + formatted + "]";
	});

	return body;
}

接下来看下具体的转换操作

// AbstractJackson2HttpMessageConverter.java
public Object read(Type type, @Nullable Class<?> contextClass, HttpInputMessage inputMessage)
			throws IOException, HttpMessageNotReadableException {
	// 获取参数的java类型
	JavaType javaType = getJavaType(type, contextClass);
	// 执行转换
	return readJavaType(javaType, inputMessage);
}
// AbstractJackson2HttpMessageConverter.java
private Object readJavaType(JavaType javaType, HttpInputMessage inputMessage) throws IOException {
	MediaType contentType = inputMessage.getHeaders().getContentType();
	// 获取字符集
	Charset charset = getCharset(contentType);
	// 根据参数类型和contentType来获取一个ObjectWrapper,
	ObjectMapper objectMapper = selectObjectMapper(javaType.getRawClass(), contentType);
	Assert.state(objectMapper != null, "No ObjectMapper for " + javaType);

	// 判断使用的是否是unicode
	boolean isUnicode = ENCODINGS.containsKey(charset.name()) ||
			"UTF-16".equals(charset.name()) ||
			"UTF-32".equals(charset.name());
	try {
		if (inputMessage instanceof MappingJacksonInputMessage) {
			Class<?> deserializationView = ((MappingJacksonInputMessage) inputMessage).getDeserializationView();
			if (deserializationView != null) {
				ObjectReader objectReader = objectMapper.readerWithView(deserializationView).forType(javaType);
				if (isUnicode) {
					return objectReader.readValue(inputMessage.getBody());
				}
				else {
					Reader reader = new InputStreamReader(inputMessage.getBody(), charset);
					return objectReader.readValue(reader);
				}
			}
		}
		if (isUnicode) {
			// 如果使用的是unicode会走这个分支,本例子走的也是这个分支
			return objectMapper.readValue(inputMessage.getBody(), javaType);
		}
		else {
			// 如果使用的是非unicode字符集,会创建一个指定字符集的Reader,然后进行转换
			Reader reader = new InputStreamReader(inputMessage.getBody(), charset);
			return objectMapper.readValue(reader, javaType);
		}
	}
	catch (InvalidDefinitionException ex) {
		throw new HttpMessageConversionException("Type definition error: " + ex.getType(), ex);
	}
	catch (JsonProcessingException ex) {
		throw new HttpMessageNotReadableException("JSON parse error: " + ex.getOriginalMessage(), ex, inputMessage);
	}
}

下面就是简单地使用Jackson来将body中的内容转换成指定java类型的对象

// ObjectMapper.java
public <T> T readValue(InputStream src, JavaType valueType)
        throws IOException, JsonParseException, JsonMappingException
{
    _assertNotNull("src", src);
    return (T) _readMapAndClose(_jsonFactory.createParser(src), valueType);
} 
protected Object _readMapAndClose(JsonParser p0, JavaType valueType)
        throws IOException
{
     try (JsonParser p = p0) {
         Object result;
         JsonToken t = _initForReading(p, valueType);
         final DeserializationConfig cfg = getDeserializationConfig();
         final DeserializationContext ctxt = createDeserializationContext(p, cfg);
         if (t == JsonToken.VALUE_NULL) {
             // Ask JsonDeserializer what 'null value' to use:
             result = _findRootDeserializer(ctxt, valueType).getNullValue(ctxt);
         } else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {
             result = null;
         } else {
             JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, valueType);
             if (cfg.useRootWrapping()) {
                 result = _unwrapAndDeserialize(p, ctxt, cfg, valueType, deser);
             } else {
                 result = deser.deserialize(p, ctxt);
             }
             ctxt.checkUnresolvedObjectId();
         }
         if (cfg.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)) {
             _verifyNoTrailingTokens(p, ctxt, valueType);
         }
         return result;
     }
 }
结果转换

下面看下当将转换好的参数传给指定的controller,并且返回结果后,如果对返回结果进行处理

// ServletInvocableHandlerMethod.java
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()) {
			mavContainer.setRequestHandled(true);
			return;
		}
	}
	else if (StringUtils.hasText(getResponseStatusReason())) {
		mavContainer.setRequestHandled(true);
		return;
	}

	mavContainer.setRequestHandled(false);
	try {
		this.returnValueHandlers.handleReturnValue(
				returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
	}
	catch (Exception ex) {
		if (logger.isTraceEnabled()) {
			logger.trace(getReturnValueHandlingErrorMessage("Error handling return value", returnValue), ex);
		}
		throw ex;
	}
}

下面的套路和argumentResolver类似,遍历包含的HandlerMethodReturnValueHandler,调用supportsReturnType,判断是否支持当前类型的返回值,如果支持,处理之

// HandlerMethodReturnValueHandlerComposite.java
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);
}
// HandlerMethodReturnValueHandlerComposite.java
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;
}

可以看到主要是通过returnValueHandlers来对返回结果进行处理
而returnValueHandlers是在创建ServletInvocableHandlerMethod时通过setter来设置的
在RequestMappingHandlerAdapter的invokeHandlerMethod方法时有如下一段代码

if (this.returnValueHandlers != null) {
	invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
}

可见,ServletInvocableHandlerMethod的returnValueHandlers也是通过RequestMappingHandlerAdapter设置进来的,和argumentResolvers一样,returnValueHandlers也是通过afterPropertiesSet设置的

if (this.returnValueHandlers == null) {
	List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
	this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
}
private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
	List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>(20);

	// 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 ServletModelAttributeMethodProcessor(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 ServletModelAttributeMethodProcessor(true));
	}

	return handlers;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值