java response 401_关于java:ClientHttpResponse.getBody()在响应代码为401时引发ResourceAccessException...

我正在尝试记录每个请求的请求-响应对。 问题是,当响应代码为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 error on

POST request for"https://example.com/api/sessions": Server returned

HTTP response code: 401 for URL: https://example.com/api/sessions;

nested exception is java.io.IOException: Server returned HTTP response

code: 401 for URL: 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 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);

}

}

您期望401的响应主体是什么?

实际上,服务器是否发送响应正文都没有关系。 ,如果它没有发送任何响应正文,我想将responseString设置为null。 但这会引发异常。

您是否看到了这个答案stackoverflow.com/a/47467572/4545442? 可能会有所帮助。

在错误消息Server returned HTTP response code: 401 for URL: https:example.com.11apisessions中。 这个网址是错字还是实际更改了要请求的网址?

另外,@ SalihErikci您确定response.getBody()而不是ByteStreams.toByteArray(..)引发异常吗? 因为如果引发了I / O异常,则rest模板倾向于将其包装为ResourceAccessException

使用HttpComponentsClientHttpRequestFactory代替SimpleClientHttpRequestFactory。

还向'org.apache.httpcomponents:httpclient添加依赖项。

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

我尝试了您的解决方案,但它给了我以下异常:sun.security.provider.certpath.SunCertPathBuilderException:无法找到到请求目标的有效证书路径

现在您还有另一个问题,与您的第一个问题并不严格相关。现在,您必须导入证书。也许有用的是这个stackoverflow.com/questions/33497874/

我不认为ResourceAccessException被response.getBody()抛出,相反,似乎是ByteStreams.toByteArray(...)正在发送null流作为响应。

如果response.getBody()是null或ByteStreams.toByteArray(),可以请尝试调试。 因为发生I / O错误时会引发RescourceAccessException。

当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配置样本

class="org.springframework.http.converter.StringHttpMessageConverter">

class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />

class="org.springframework.http.converter.ResourceHttpMessageConverter" />

class="org.springframework.http.converter.xml.SourceHttpMessageConverter" />

class="org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter" />

class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter" />

class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />

class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />                                                

         

Java配置

@Config

public class restTemplConfig {

@Bean

public RestTemplate restTempl() {

RestTemplate result = new RestTemplate();

//Add converters

//Add custom error handler

result.setErrorHandler(new SimpleRestErrorHandler());

}

}

我希望它有用

我已经有一个自定义处理程序并映射错误状态代码。但是在点击自定义错误处理程序之前,我在拦截器中得到了异常。

您可以发布resttemplate配置吗?

添加了resttemplate配置。

我看不到将ErrorHanlder添加到RestTemplate的位置

忘记添加该行。添加

这很奇怪..您也可以添加RequestErrorHandler吗?

我看到的是,当httpstatus代码不是2xx时,您总是会生成错误。这意味着在您的方案中,当服务发出401作为状态代码时,您将收到错误。我猜你应该改用hasError方法

但是代码甚至都没有转到代码的那部分。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java的世界里,HttpClient 是一个功能强大的Http请求库,然而接口非常复杂,设计上遵从正交性,简单的请求也需要写比较多的代码,更不要说隐藏在各种细节里面的高级用法了。Requests,  是一个模仿python requests 模块来设计的Http lib,拥有简单而灵活的API,在容易使用的同,又能够满足各种高级定制的使用,可是说是当前最好用的Java Http Client Lib。 简单的请求示例:String url = ...; Response resp = Requests.get(url).text(); // post 和其他方法 resp = Requests.post(url).text(); resp = Requests.head(url).text(); //读取Http Response  int statusCode = resp.getStatusCode(); Headers headers = resp.getHeaders(); Cookies cookies = resp.getCookies(); String body = resp.getBody(); //response 返回其他类型 resp = Requests.get(url).text("UTF-8"); // get response as bytes Response resp1 = Requests.get(url).bytes(); // save response as file  Response resp2 = Requests.get(url).file("/path/to/save/file"); // url 参数: Map map = new HashMap(); map.put("k1", "v1"); map.put("k2", "v2"); Response resp = Requests.get(url).param("key1", "value1").params(map)         //.params(new Parameter(...), new Parameter(...))         .text(); // 请求头 Response resp = Requests.get(url).header("key1", "value1").headers(map)         //.headers(new Header(...), new Header(...))         .text(); // 添加Cookie: Map cookies = new HashMap(); Response resp = Requests.get(url).cookie("key1", "value1").cookies(map)         //.cookies(new Cookie(...), new Cookie(...))         .text(); //  设置 userAgent Response resp = Requests.get(url).userAgent(userAgent).text(); // 增加请求数据(post, put, patch方法) // send form-encoded data. x-www-form-urlencoded header will be send automatically Response resp = Requests.post(url).data(map).text(); // send string data String str = ...; resp = Requests.post(url).data(str, "UTF-8").text(); // send from inputStream InputStream in = ... resp = Requests.post(url).data(in).text(); // multipart 请求, 用于文件上传: Response resp = Requests.post(url).data(map).multiPart("ufile", "/path/to/file")         .multiPart(..., ...).text();请求设置://禁止自动重定向

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值