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

上一篇文章 springMVC源码分析--HttpMessageConverter(一)之数据转化中我们简单介绍了一下HttpMessageConverter接口提供的几个方法,主要有以下几个方法:
(1)canRead 是否可以读
(2)canWrite 是否可以写
(3)read() 读数据
(4)write() 写数据
接下来我们介绍一下读取数据的处理操作。

springmvc读写数据的处理过程.png

首先要去重温一下参数处理器需要做的操作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看到如下处理,这里就是对提交的参数的处理

    @Override  
    protected  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  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 targetClass = (targetType instanceof Class ? (Class) targetType : null);  
        if (targetClass == null) {  
            ResolvableType resolvableType = (param != null ?  
                    ResolvableType.forMethodParameter(param) : ResolvableType.forType(targetType));  
            targetClass = (Class) resolvableType.resolve();  
        }  
  
        HttpMethod httpMethod = ((HttpRequest) inputMessage).getMethod();  
        Object body = NO_VALUE;  
  
        try {  
            inputMessage = new EmptyBodyCheckingHttpInputMessage(inputMessage);  
            //选择适合的消息处理器来处理参数  
            for (HttpMessageConverter converter : this.messageConverters) {  
                Class> converterType = (Class>) 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) 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
(8)AllEncompassingFormHttpMessageConverter

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

你可能感兴趣的:(springMVC源码分析--HttpMessageConverter(二)之参数read操作)