当响应代码为401时,ClientHttpResponse.getBody()抛出ResourceAccessException

时间:2018-03-26 06:10:00

标签: java spring resttemplate

我正在尝试为每个请求记录请求 - 响应对。问题是当响应代码为401时,ClientHttpResponse.getBody()抛出ResourceAccessException,我无法读取响应主体。

这是RestTemplate配置

RestTemplate restTemplate = new RestTemplate();

// Added this requestFactory to make response object readable more than once.
ClientHttpRequestFactory requestFactory =
        new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory());
restTemplate.setRequestFactory(requestFactory);
restTemplate.getInterceptors().add(new RequestLoggingInterceptor(vCloudRequest.getAction(),httpHeaders));
    restTemplate.setErrorHandler(new RequestErrorHandler());

return restTemplate;

下面的拦截器的最后一行抛出以下异常。

我该如何解决这个问题?

  

org.springframework.web.client.ResourceAccessException:I / O错误   POST请求“https://example.com/api/sessions”:服务器返回   HTTP响应代码:401 for URL:https://example.com/api/sessions;   嵌套异常是java.io.IOException:服务器返回HTTP响应   代码:401为网址:https://example.com.11/api/sessions

这是拦截器的相关部分。

@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
    ClientHttpResponse response = execution.execute(request, body);

    String requestString = new String(body);

    // Calling this method because when we make a POST or PUT request and get an error
    // response.getBody() throws IOException. But if we call response.getStatusCode() it works fine.
    // I don't know the reason.
    // I asked a question on stackoverflow
    // https://stackoverflow.com/questions/47429978/resttemplate-response-getbody-throws-exception-on-4-and-5-errors-for-put-and
    response.getStatusCode();
    String responseString = new String(ByteStreams.toByteArray(response.getBody()), Charset.forName("UTF-8"));
...
}

这是自定义错误处理程序

公共类RequestErrorHandler实现ResponseErrorHandler {

@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
        if (!response.getStatusCode().is2xxSuccessful()) {
        return true;
    }
    return false;
}

@Override
public void handleError(ClientHttpResponse response) throws IOException {
    JAXBElement<ErrorType> root = null;

    try {
        JAXBContext jaxbContext = JAXBContext.newInstance(ErrorType.class);
        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

        root = jaxbUnmarshaller.unmarshal(new StreamSource(
                response.getBody()), ErrorType.class);
    } catch (JAXBException e) {
        throw new IOException("XML converting error. Cannot convert response to ErrorType");
    }

    ErrorType error = root.getValue();
    throw new VcloudException(error);
}
}

3 个答案:

答案 0 :(得分:2)

使用 HttpComponentsClientHttpRequestFactory 而不是SimpleClientHttpRequestFactory。

还要将依赖项添加到&#39; org.apache.httpcomponents:httpclient。

当状态为401时,HttpComponentsClientHttpRequestFactory可以读取正文。

答案 1 :(得分:0)

我不认为,ResourceAccessException引发了response.getBody(),而ByteStreams.toByteArray(...)似乎正在发送null流作为回应。

如果response.getBody()nullByteStreams.toByteArray(),请试试。因为发生I / O错误时会抛出RescourceAccessException

答案 2 :(得分:-1)

当httpstatus不是200时,

Spring RestTemplate默认生成错误。

在我过去的项目中,我所做的是向其余模板添加自定义org.springframework.web.client.ResponseErrorHandler。 你可以写一个这样的课:

public class SimpleRestErrorHandler implements ResponseErrorHandler
{
    private static final Logger logger = LoggerFactory.getLogger(SimpleRestErrorHandler.class.getName());
    @Override
    public boolean hasError(ClientHttpResponse response) throws IOException
    {
        int statusCode = response.getStatusCode().value();
        if( logger.isDebugEnabled() )
        {

            logger.debug("STATUS CODE ["+statusCode+"] ");
        }
        //Generate Error only when HTTP Status code is 500
        if( statusCode == 500 )
        {

            return true;
        }
        return false;
    }

    @Override
    public void handleError(ClientHttpResponse response) throws IOException
    {
      //Here you can manage the error (in this sample only the http status code = 500
    }

}

然后我将其添加到我的休息模板中:

XML配置示例

<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">        <constructor-arg ref="bufferingClientHttpRequestFactory" />         <property name="errorHandler" ref="simpleRestErrorHandler" />       <property name="messageConverters">             <list>
                <bean
                    class="org.springframework.http.converter.StringHttpMessageConverter">
                    <constructor-arg value="#{T(java.nio.charset.Charset).forName('UTF-8')}" />
                </bean>
                <bean
                    class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
                <bean
                    class="org.springframework.http.converter.ResourceHttpMessageConverter" />
                <bean
                    class="org.springframework.http.converter.xml.SourceHttpMessageConverter" />
                <bean
                    class="org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter" />
                <bean
                    class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter" />
                <bean
                    class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
                <bean
                    class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />          </list>         </property>         <property name="interceptors">          <!-- Custom interceptors -->        </property>     </bean> <bean id="bufferingClientHttpRequestFactory" name="bufferingClientHttpRequestFactory"       class="org.springframework.http.client.BufferingClientHttpRequestFactory">      <constructor-arg ref="simpleReqFact" />     </bean> <bean id="simpleRestErrorHandler" class="handlers.SimpleRestErrorHandler" />

Java配置

@Config
public class restTemplConfig {
 @Bean
 public RestTemplate restTempl() {
  RestTemplate result = new RestTemplate();
  //Add converters
  //Add custom error handler
  result.setErrorHandler(new SimpleRestErrorHandler());
 }
}

我希望它有用