大叔问题定位分享(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即可;
---------------------------------------------------------------- 结束啦,我是大魔王先生的分割线 :) ----------------------------------------------------------------
- 由于大魔王先生能力有限,文中可能存在错误,欢迎指正、补充!
- 感谢您的阅读,如果文章对您有用,那么请为大魔王先生轻轻点个赞,ありがとう