原创大叔问题定位分享(34)Spring的RestTemplate请求json数据后内容被修改

Posted barneywill

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了原创大叔问题定位分享(34)Spring的RestTemplate请求json数据后内容被修改相关的知识,希望对你有一定的参考价值。

先看代码

org.springframework.web.client.RestTemplate

    public RestTemplate() 
        this.messageConverters = new ArrayList();
        this.errorHandler = new DefaultResponseErrorHandler();
        this.headersExtractor = new RestTemplate.HeadersExtractor();
        this.messageConverters.add(new ByteArrayHttpMessageConverter());
        this.messageConverters.add(new StringHttpMessageConverter());
        this.messageConverters.add(new ResourceHttpMessageConverter(false));

        try 
            this.messageConverters.add(new SourceHttpMessageConverter());
         catch (Error var2) 
            ;
        

        this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
        if(romePresent) 
            this.messageConverters.add(new AtomFeedHttpMessageConverter());
            this.messageConverters.add(new RssChannelHttpMessageConverter());
        

        if(jackson2XmlPresent) 
            this.messageConverters.add(new MappingJackson2XmlHttpMessageConverter());
         else if(jaxb2Present) 
            this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
        

        if(jackson2Present) 
            this.messageConverters.add(new MappingJackson2HttpMessageConverter());
         else if(gsonPresent) 
            this.messageConverters.add(new GsonHttpMessageConverter());
         else if(jsonbPresent) 
            this.messageConverters.add(new JsonbHttpMessageConverter());
        

        if(jackson2SmilePresent) 
            this.messageConverters.add(new MappingJackson2SmileHttpMessageConverter());
        

        if(jackson2CborPresent) 
            this.messageConverters.add(new MappingJackson2CborHttpMessageConverter());
        

        this.uriTemplateHandler = initUriTemplateHandler();
    

构造函数中会根据各种boolean标志添加很多MessageConverter,而这些boolean标志来自

    static 
        ClassLoader classLoader = RestTemplate.class.getClassLoader();
        romePresent = ClassUtils.isPresent("com.rometools.rome.feed.WireFeed", classLoader);
        jaxb2Present = ClassUtils.isPresent("javax.xml.bind.Binder", classLoader);
        jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) && ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader);
        jackson2XmlPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", classLoader);
        jackson2SmilePresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.smile.SmileFactory", classLoader);
        jackson2CborPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.cbor.CBORFactory", classLoader);
        gsonPresent = ClassUtils.isPresent("com.google.gson.Gson", classLoader);
        jsonbPresent = ClassUtils.isPresent("javax.json.bind.Jsonb", classLoader);
    

在发请求时

    public <T> ResponseEntity<T> postForEntity(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables) throws RestClientException 
        RequestCallback requestCallback = this.httpEntityCallback(request, responseType);
        ResponseExtractor<ResponseEntity<T>> responseExtractor = this.responseEntityExtractor(responseType);
        return (ResponseEntity)nonNull(this.execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables));
    

会创建一个ResponseExtractor

    private class ResponseEntityResponseExtractor<T> implements ResponseExtractor<ResponseEntity<T>> 
        @Nullable
        private final HttpMessageConverterExtractor<T> delegate;

        public ResponseEntityResponseExtractor(@Nullable Type responseType) 
            if(responseType != null && Void.class != responseType) 
                this.delegate = new HttpMessageConverterExtractor(responseType, RestTemplate.this.getMessageConverters(), RestTemplate.this.logger);
             else 
                this.delegate = null;
            

        

可见是根据responseType创建了一个代理,然后代理中包含了所有添加过的MessageConverter

 

而在execute中会调用

    protected <T> T doExecute(URI url, @Nullable HttpMethod method, @Nullable RequestCallback requestCallback, @Nullable ResponseExtractor<T> responseExtractor) throws RestClientException 
        Assert.notNull(url, "URI is required");
        Assert.notNull(method, "HttpMethod is required");
        ClientHttpResponse response = null;

        Object var14;
        try 
            ClientHttpRequest request = this.createRequest(url, method);
            if(requestCallback != null) 
                requestCallback.doWithRequest(request);
            

            response = request.execute();
            this.handleResponse(url, method, response);
            var14 = responseExtractor != null?responseExtractor.extractData(response):null;

即responseExecutor.extractData,来看下这个函数

    public T extractData(ClientHttpResponse response) throws IOException 
        MessageBodyClientHttpResponseWrapper responseWrapper = new MessageBodyClientHttpResponseWrapper(response);
        if(responseWrapper.hasMessageBody() && !responseWrapper.hasEmptyMessageBody()) 
            MediaType contentType = this.getContentType(responseWrapper);

            try 
                Iterator var4 = this.messageConverters.iterator();

                while(var4.hasNext()) 
                    HttpMessageConverter<?> messageConverter = (HttpMessageConverter)var4.next();
                    if(messageConverter instanceof GenericHttpMessageConverter) 
                        GenericHttpMessageConverter<?> genericMessageConverter = (GenericHttpMessageConverter)messageConverter;
                        if(genericMessageConverter.canRead(this.responseType, (Class)null, contentType)) 
                            if(this.logger.isDebugEnabled()) 
                                ResolvableType resolvableType = ResolvableType.forType(this.responseType);
                                this.logger.debug("Reading to [" + resolvableType + "]");
                            

                            return genericMessageConverter.read(this.responseType, (Class)null, responseWrapper);
                        
                    

                    if(this.responseClass != null && messageConverter.canRead(this.responseClass, contentType)) 
                        if(this.logger.isDebugEnabled()) 
                            String className = this.responseClass.getName();
                            this.logger.debug("Reading to [" + className + "] as \"" + contentType + "\"");
                        

                        return messageConverter.read(this.responseClass, responseWrapper);
                    
                
             catch (HttpMessageNotReadableException | IOException var8) 
                throw new RestClientException("Error while extracting response for type [" + this.responseType + "] and content type [" + contentType + "]", var8);
            

            throw new RestClientException("Could not extract response: no suitable HttpMessageConverter found for response type [" + this.responseType + "] and content type [" + contentType + "]");
         else 
            return null;
        
    

 

所以当你发现使用RestTemplate发请求后数据被修改的时候,要检查相应的content type,要检查RestTemplate中有哪些MessageConverter(包括各个boolean标志),

如果确定数据不需要被修改时,可以调用RestTemplate.setMessageConverters方法,传入默认的StringHttpMessageConverter即可;

 

以上是关于原创大叔问题定位分享(34)Spring的RestTemplate请求json数据后内容被修改的主要内容,如果未能解决你的问题,请参考以下文章

原创大叔问题定位分享(38)impala报错内存不足

原创大叔问题定位分享(29)datanode启动报错:50020端口被占用

原创大叔问题定位分享(33)oozie提交任务报错ArithmeticException: / by zero

原创大叔问题定位分享(36)openresty(nginx+lua)中获取不到post数据,ngx.req.get_body_data返回nil

原创大叔经验分享(57)hue启动coordinator时报错

原创大叔经验分享(114)git大面积修改问题