一尘不染

Spring RestTemplate处理状态为NO_CONTENT的响应时的行为

spring-mvc

好的,我有一个NamedSystems类,该类的唯一字段是NamedSystem集。

我有一种方法可以通过某些条件查找NamedSystems。那不是很重要。当得到结果时,一切正常。但是,当它找不到任何东西并因此返回null(或为空-
我已经尝试过两种方法)时,就会遇到问题。让我解释。

我正在使用Spring RestTemplate类,并且正在单元测试中进行如下调用:

ResponseEntity<?> responseEntity = template.exchange(BASE_SERVICE_URL + "?
  alias={aliasValue}&aliasAuthority={aliasAssigningAuthority}", 
  HttpMethod.GET, makeHttpEntity("xml"), NamedSystems.class, 
  alias1.getAlias(), alias1.getAuthority());

现在,由于通常返回200,但是我想返回204,因此我的服务中有一个拦截器,用于确定ModelAndView是否为NamedSystem以及其set是否为null。如果是这样,则将状态代码设置为NO_CONTENT(204)。

当我运行junit测试时,出现以下错误:

org.springframework.web.client.RestClientException: Cannot extract response: no Content-Type found

将状态设置为NO_CONTENT似乎会擦除content-type字段(考虑到这一点确实很有意义)。那么为什么还要看呢?

Spring的HttpMessageConverterExtractor extractData方法:

public T extractData(ClientHttpResponse response) throws IOException {
    MediaType contentType = response.getHeaders().getContentType();
    if (contentType == null) {
        throw new RestClientException("Cannot extract response: no Content-Type found");
    }
    for (HttpMessageConverter messageConverter : messageConverters) {
        if (messageConverter.canRead(responseType, contentType)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Reading [" + responseType.getName() + "] as \"" + contentType
                    +"\" using [" + messageConverter + "]");
            }
            return (T) messageConverter.read(this.responseType, response);
        }
    }
    throw new RestClientException(
        "Could not extract response: no suitable HttpMessageConverter found for response type [" +
        this.responseType.getName() + "] and content type [" + contentType + "]");
}

稍微向上看一下链,以找出在哪里设置了Extractor,我来看看我在测试中使用的RestTemplate的exchange()方法:

public <T> ResponseEntity<T> exchange(String url, HttpMethod method,
  HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables) throws RestClientException {
    HttpEntityRequestCallback requestCallback = new HttpEntityRequestCallback(requestEntity, responseType);
    ResponseEntityResponseExtractor<T> responseExtractor = new ResponseEntityResponseExtractor<T>(responseType);
    return execute(url, method, requestCallback, responseExtractor, uriVariables);
}

因此,由于交换调用提供的响应类型,它试图将什么都转换为零。如果将responseType从NamedSystems.class更改为null,它将按预期工作。它不会尝试转换任何东西。如果我试图将状态代码设置为404,它也可以正常执行。

我是否被误导了,或者这看起来像RestTemplate中的缺陷?当然,我现在正在使用junit,所以我知道会发生什么,但是如果有人使用RestTemplate调用此方法而又不知道服务调用的结果,那么他们自然会将NamedSystems作为响应类型。但是,如果他们尝试不包含任何元素的条件搜索,则会出现此讨厌的错误。

有没有办法解决此问题而不覆盖任何RestTemplate东西?我是否错误地看待这种情况?请帮忙,因为我有点困惑。


阅读 978

收藏
2020-06-01

共1个答案

一尘不染

现在应该在Spring 3.1 RC1中修复此问题。

https://jira.spring.io/browse/SPR-7911

2020-06-01