Spring MVC 返回值处理

组件

HandlerMethodReturnValueHandler

返回值处理器接口

public interface HandlerMethodArgumentResolver {
	// 是否支持处理该参数
    boolean supportsParameter(MethodParameter var1);
	// 解析返回值
    Object resolveArgument(MethodParameter var1, ModelAndViewContainer var2, NativeWebRequest var3, WebDataBinderFactory var4) throws Exception;
}

HttpMessageConverter

处理HTTP请求和响应的转换器。

public interface HttpMessageConverter<T> {
	// 对于该Media类型是否可读
	boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);
	boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);
	
	// 获得当前消息转换器支持的类型
	List<MediaType> getSupportedMediaTypes();
	// 读写转换,将request或response中的参数转换为对应类型
	T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
			throws IOException, HttpMessageNotReadableException;

	void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
			throws IOException, HttpMessageNotWritableException;
}

AbstractHttpMessageConverter

HttpMessageConverter接口的基础实现

public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConverter<T> {
	// 消息转换器支持的Content-Type
	private List<MediaType> supportedMediaTypes = Collections.emptyList();
	
	// 默认编码
	private Charset defaultCharset;
	
	
	public boolean canRead(Class<?> clazz, @Nullable MediaType mediaType) {
		// 是否支持类型和content-type
		return supports(clazz) && canRead(mediaType);
	}
	
	// 开始read时转换
	public final T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
			throws IOException, HttpMessageNotReadableException {

		return readInternal(clazz, inputMessage);
	}

}

返回值解析

  1. 经过doInvoke(args),反射调用处理器方法获得返回值
protected Object doInvoke(Object... args) throws Exception {
		ReflectionUtils.makeAccessible(getBridgedMethod());
		try {
			return getBridgedMethod().invoke(getBean(), args);
		}
		···异常处理
}		
  1. ServletInvocableHandlerMethod中invokeAndHandle初步处理返回值,选择返回值解析器,通过返回值解析器来处理返回值
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
		// 反射调用后的返回值
		Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
		// 处理返回状态
		setResponseStatus(webRequest);
		// 如果返回值为空或response状态存在证明在处理器方法已经处理的response,无需经过视图解析,所以设置requestHandled的true,表示请求已经被处理了
		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);
		}
		···抛出异常
	}
  1. HandlerMethodReturnValueHandlerComposite调用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);
}
  1. 这里分析RequestResponseBodyMethodProcessor返回值解析器,主要是通过消息转化器来转换返回值
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
			ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
			throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {

	mavContainer.setRequestHandled(true);
	ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
	ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);

	// 使用对应的消息转换器,处理返回值
	writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}
  1. 如果已被处理返回null,不走视图解析,否则根据ModelAndViewContainer生成ModelAndView返回
private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
			ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {
	modelFactory.updateModel(webRequest, mavContainer);
	// 如果已被处理返回null,不走视图解析
	if (mavContainer.isRequestHandled()) {
		return null;
	}
	ModelMap model = mavContainer.getModel();
	// 创建返回的mav
	ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());
	// 如果返回值不为string则解析为视图
	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;
}
  1. 判断if (mv != null && !mv.wasCleared()),ModelAndView不为空则进行视图渲染
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值