Spring RestTemplate Behavior when handling responses with a status of NO_CONTENT

前端 未结 6 1700
小蘑菇
小蘑菇 2020-12-08 11:05

Okay, I have a class NamedSystems, that has as its only field a Set of NamedSystem.

I have a method to find NamedSystems by certain criteria. That\'s not really imp

相关标签:
6条回答
  • 2020-12-08 11:39

    Here's a simple solution where you can set the default Content-Type for use if it is missing in the response. The Content-Type is added to the response header before it is handed back off to the preconfigured ResponseExtractor for extraction.

    public class CustomRestTemplate extends RestTemplate {
    
        private MediaType defaultResponseContentType;
    
        public CustomRestTemplate() {
            super();
        }
    
        public CustomRestTemplate(ClientHttpRequestFactory requestFactory) {
            super(requestFactory);
        }
    
        public void setDefaultResponseContentType(String defaultResponseContentType) {
            this.defaultResponseContentType = MediaType.parseMediaType(defaultResponseContentType);
        }
    
        @Override
        protected <T> T doExecute(URI url, HttpMethod method, RequestCallback requestCallback, final ResponseExtractor<T> responseExtractor)
                throws RestClientException {
    
            return super.doExecute(url, method, requestCallback, new ResponseExtractor<T>() {
                public T extractData(ClientHttpResponse response) throws IOException {
                    if (response.getHeaders().getContentType() == null && defaultResponseContentType != null) {
                        response.getHeaders().setContentType(defaultResponseContentType);
                    }
    
                    return responseExtractor.extractData(response);
                }
            });
        }
    }
    
    0 讨论(0)
  • 2020-12-08 11:41

    Or you could extend RestTemplate and override doExecute(..) and check the response body.

    For example here is what I implemented and works for us:

    @Override
    protected <T> T doExecute(final URI url, final HttpMethod method, final RequestCallback requestCallback, final ResponseExtractor<T> responseExtractor)
            throws RestClientException
    {
        Assert.notNull(url, "'url' must not be null");
        Assert.notNull(method, "'method' must not be null");
        ClientHttpResponse response = null;
        try
        {
            final ClientHttpRequest request = createRequest(url, method);
            if (requestCallback != null)
            {
                requestCallback.doWithRequest(request);
            }
            response = request.execute();
            if (!getErrorHandler().hasError(response))
            {
                logResponseStatus(method, url, response);
            }
            else
            {
                handleResponseError(method, url, response);
            }
            if ((response.getBody() == null) || (responseExtractor == null))
            {
                return null;
            }
            return responseExtractor.extractData(response);
        }
        catch (final IOException ex)
        {
            throw new ResourceAccessException("I/O error: " + ex.getMessage(), ex);
        }
        finally
        {
            if (response != null)
            {
                response.close();
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-08 11:43

    One more way to solve this would be to make response entity as null as shown below.

      ResponseEntity<?> response = restTemplate.exchange("http://localhost:8080/myapp/user/{userID}",
                                                                 HttpMethod.DELETE, 
                                                                 requestEntity,
                                                                 null,
                                                                 userID);
    

    If you still need response headers, try implementing the ResponseErrorHandler.

    0 讨论(0)
  • 2020-12-08 11:44

    I think you are right. I'm having a similar problem. I think we should be getting a ResponseEntity with a HttpStatus of NO_CONTENT and a null body.

    0 讨论(0)
  • 2020-12-08 11:57

    This should now be fixed in Spring 3.1 RC1.

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

    0 讨论(0)
  • 2020-12-08 11:59

    I believe you should probably look at the ResponseExtractor interface & call execute on the RestTemplate providing your implementation of the extractor. To me it looks like a common requirement to do this so have logged this:

    https://jira.springsource.org/browse/SPR-8016

    Here's one I prepared earlier:

    private class MyResponseExtractor extends HttpMessageConverterExtractor<MyEntity> {
    
        public MyResponseExtractor (Class<MyEntity> responseType,
          List<HttpMessageConverter<?>> messageConverters) {
            super(responseType, messageConverters);
        }
    
        @Override
        public MyEntity extractData(ClientHttpResponse response) throws IOException {
    
            MyEntity result;
    
            if (response.getStatusCode() == HttpStatus.OK) {
                result = super.extractData(response);
            } else {
                result = null;
            }
    
            return result;
        }
    }
    

    I've tested this & it seems to do what I want.

    To create the instance of the ResponseExtractor I call the constructor & pass the converters from a RestTemplate instance that's been injected;

    E.g.

    ResponseExtractor<MyEntity> responseExtractor =
        new MyResponseExtractor(MyEntity.class, restTemplate.getMessageConverters());
    

    Then the call is:

    MyEntity responseAsEntity =
        restTemplate.execute(urlToCall, HttpMethod.GET, null, responseExtractor);
    

    Your mileage may vary. ;-)

    0 讨论(0)
提交回复
热议问题