上一篇博客 springMVC源碼分析--HttpMessageConverter數據轉化(一)中咱們簡單介紹了一下HttpMessageConverter接口提供的幾個方法,主要有如下幾個方法:web
(1)canRead 是否能夠讀spring
(2)canWrite 是否能夠寫app
(3)read() 讀數據ide
(4)write() 寫數據源碼分析
接下來咱們介紹一下讀取數據的處理操做。ui
首先要去重溫一下參數處理器須要作的操做springMVC源碼分析--RequestParamMethodArgumentResolver參數解析器(三),AbstractNamedValueMethodArgumentResolver中的resolveArgument方法,解析參數值this
public final Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
.......
Object arg = resolveName(namedValueInfo.name, parameter, webRequest);
......
}
簡單的提交數據的示例:.net
@RequestMapping(value="/save")
public String saveProduct( String name,@RequestBody String description,@RequestBody float price, Model model)
.......
}
咱們能夠在HandlerMethodArgumentResolver的子類RequestResponseBodyMethodProcessor的方法resolveArgument看到以下處理,這裏就是對提交的參數的處理debug
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
Object arg = readWithMessageConverters(webRequest, parameter, parameter.getGenericParameterType());
.........
}
接下來在readWithMessageConverters中的處理以下:orm
@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;
}
springMVC默認提供了不少參數和結果值處理器,包括以下:
(1)MappingJackson2HttpMessageConverter
(2)GsonHttpMessageConverter
(3)ByteArrayHttpMessageConverter
(4)ObjectToStringHttpMessageConverter
(5)ProtobufHttpMessageConverter
(6)ResourceHttpMessageConverter
(7)StringHttpMessageConverter