springMVC源码分析--HttpMessageConverter参数read操作(二)

转载 https://blog.csdn.net/qq924862077/article/details/55271569

上一篇博客 springMVC源码分析--HttpMessageConverter数据转化(一)中我们简单介绍了一下HttpMessageConverter接口提供的几个方法,主要有以下几个方法:

(1)canRead 是否可以读

(2)canWrite 是否可以写

(3)read() 读数据

(4)write() 写数据

接下来我们介绍一下读取数据的处理操作。

首先要去重温一下参数处理器需要做的操作springMVC源码分析--RequestParamMethodArgumentResolver参数解析器(三),AbstractNamedValueMethodArgumentResolver中的resolveArgument方法,解析参数值
 

public final Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
		.......
		Object arg = resolveName(namedValueInfo.name, parameter, webRequest);
		......
	}

简单的提交数据的示例:

 @RequestMapping(value="/save")
    public String saveProduct( String name,@RequestBody String description,@RequestBody float price, Model model)
   .......
}

我们可以在HandlerMethodArgumentResolver的子类RequestResponseBodyMethodProcessor的方法resolveArgument看到如下处理,这里就是对提交的参数的处理

public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
 
		Object arg = readWithMessageConverters(webRequest, parameter, parameter.getGenericParameterType());
		.........
	}

接下来在readWithMessageConverters中的处理如下:

@Override
	protected <T> Object readWithMessageConverters(NativeWebRequest webRequest, MethodParameter methodParam,
			Type paramType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException {
		HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
		ServletServerHttpRequest inputMessage = new ServletServerHttpRequest(servletRequest);
		Object arg = readWithMessageConverters(inputMessage, methodParam, paramType);
		if (arg == null) {
			if (methodParam.getParameterAnnotation(RequestBody.class).required()) {
				throw new HttpMessageNotReadableException("Required request body is missing: " +
						methodParam.getMethod().toGenericString());
			}
		}
		return arg;
	}

在父类AbstractMessageConverterMethodArgumentResolver的方法readWithMessageConverters中的处理如下:简单来说就是根据提供的实现的HttpMessageConverter来对提交的RequestBody中的数据进行转换处理。
 

@SuppressWarnings("unchecked")
	protected <T> Object readWithMessageConverters(HttpInputMessage inputMessage, MethodParameter param,
			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;
		}
 
		Class<?> contextClass = (param != null ? param.getContainingClass() : null);
		Class<T> targetClass = (targetType instanceof Class<?> ? (Class<T>) targetType : null);
		if (targetClass == null) {
			ResolvableType resolvableType = (param != null ?
					ResolvableType.forMethodParameter(param) : ResolvableType.forType(targetType));
			targetClass = (Class<T>) resolvableType.resolve();
		}
 
		HttpMethod httpMethod = ((HttpRequest) inputMessage).getMethod();
		Object body = NO_VALUE;
 
		try {
			inputMessage = new EmptyBodyCheckingHttpInputMessage(inputMessage);
			//选择适合的消息处理器来处理参数
			for (HttpMessageConverter<?> converter : this.messageConverters) {
				Class<HttpMessageConverter<?>> converterType = (Class<HttpMessageConverter<?>>) converter.getClass();
				//判断是否适合处理参数
				if (converter instanceof GenericHttpMessageConverter) {
					GenericHttpMessageConverter<?> genericConverter = (GenericHttpMessageConverter<?>) converter;
					if (genericConverter.canRead(targetType, contextClass, contentType)) {
						if (logger.isDebugEnabled()) {
							logger.debug("Read [" + targetType + "] as \"" + contentType + "\" with [" + converter + "]");
						}
						if (inputMessage.getBody() != null) {
							inputMessage = getAdvice().beforeBodyRead(inputMessage, param, targetType, converterType);
							//处理参数
							body = genericConverter.read(targetType, contextClass, inputMessage);
							body = getAdvice().afterBodyRead(body, inputMessage, param, targetType, converterType);
						}
						else {
							body = null;
							body = getAdvice().handleEmptyBody(body, inputMessage, param, targetType, converterType);
						}
						break;
					}
				}
				else if (targetClass != null) {
					if (converter.canRead(targetClass, contentType)) {
						if (logger.isDebugEnabled()) {
							logger.debug("Read [" + targetType + "] as \"" + contentType + "\" with [" + converter + "]");
						}
						if (inputMessage.getBody() != null) {
							inputMessage = getAdvice().beforeBodyRead(inputMessage, param, targetType, converterType);
							//处理数据,对于简单的String数据使用StringHttpMessageConverter进行处理
							body = ((HttpMessageConverter<T>) converter).read(targetClass, inputMessage);
							body = getAdvice().afterBodyRead(body, inputMessage, param, targetType, converterType);
						}
						else {
							body = null;
							body = getAdvice().handleEmptyBody(body, inputMessage, param, targetType, converterType);
						}
						break;
					}
				}
			}
		}
		catch (IOException ex) {
			throw new HttpMessageNotReadableException("Could not read document: " + ex.getMessage(), ex);
		}
 
		if (body == NO_VALUE) {
			if (httpMethod == null || !SUPPORTED_METHODS.contains(httpMethod) ||
					(noContentType && inputMessage.getBody() == null)) {
				return null;
			}
			throw new HttpMediaTypeNotSupportedException(contentType, this.allSupportedMediaTypes);
		}
		//最终返回处理的结果值
		return body;
	}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringMVC 是 Spring 框架的一部分,主要用于构建 Web 应用程序。它采用了基于请求的模型,通过将请求映射到控制器类和处理方法来处理请求,并使用视图解析器来渲染响应。SpringMVC 的核心是 DispatcherServlet,它充当前端控制器,负责协调处理请求,并调用适当的处理器来处理请求。 下面是 SpringMVC源码分析: 1. DispatcherServlet:DispatcherServlet 是 SpringMVC 的核心类,它充当前端控制器,负责协调处理请求,并调用适当的处理器来处理请求。DispatcherServlet 的主要任务是将请求委托给适当的处理器来处理,然后将处理结果返回给客户端。 2. HandlerMapping:HandlerMapping 是一个接口,用于将请求映射到控制器类和处理方法。SpringMVC 提供了多种 HandlerMapping 实现,例如 BeanNameUrlHandlerMapping、SimpleUrlHandlerMapping 和 RequestMappingHandlerMapping 等。 3. HandlerAdapter:HandlerAdapter 是一个接口,用于将请求委托给适当的处理器来处理。SpringMVC 提供了多种 HandlerAdapter 实现,例如 SimpleControllerHandlerAdapter、RequestMappingHandlerAdapter 和 HttpRequestHandlerAdapter 等。 4. HandlerInterceptor:HandlerInterceptor 是一个接口,用于在控制器执行之前或之后执行一些操作SpringMVC 提供了多种 HandlerInterceptor 实现,例如 LocaleChangeInterceptor、ThemeChangeInterceptor 和 HandlerInterceptorAdapter 等。 5. ViewResolver:ViewResolver 是一个接口,用于将逻辑视图名称解析为实际的视图对象。SpringMVC 提供了多种 ViewResolver 实现,例如 InternalResourceViewResolver、FreeMarkerViewResolver 和 VelocityViewResolver 等。 6. HandlerExceptionResolver:HandlerExceptionResolver 是一个接口,用于处理控制器抛出的异常。SpringMVC 提供了多种 HandlerExceptionResolver 实现,例如 SimpleMappingExceptionResolver、AnnotationMethodHandlerExceptionResolver 和 DefaultHandlerExceptionResolver 等。 7. ModelAndView:ModelAndView 是一个类,用于封装控制器处理结果和逻辑视图名称。它包含一个模型对象和一个视图名称。 总之,SpringMVC源码分析需要深入了解 Spring Framework 的各个方面,包括 IoC 容器、AOP、Servlet API 等。同时,需要对 Web 应用程序的基本概念和架构有一定的了解。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值