[英]How can I get real http code and response body using restTemplate?
I have following code: 我有以下代码:
LinkedMultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
FileSystemResource fileSystemResource = new FileSystemResource(fileNameWithPath);
map.add("file", fileSystemResource);
map.add("type", fileType);
map.add("org_id", systemSettingsService.getSystemSettings().getOrganizationId());
map.add("stone_id", stoneId);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<LinkedMultiValueMap<String, Object>> requestEntity = new HttpEntity<>(map, headers);
restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class)
If I provide all parameters correct - enpoint returns 200 http stsatus code as expected as a Postman application. 如果我提供所有正确的参数 - enpoint返回200 http stsatus代码,如预期的Postman应用程序。
But if I provide wrong url - I see exception: 但如果我提供了错误的网址 - 我看到异常:
org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://external_server/api/v1/push_file1": Broken pipe (Write failed); nested exception is java.net.SocketException: Broken pipe (Write failed)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:666)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:613)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:531)
at com.pack.GenericDataServiceImpl.pushAttachment(GenericDataServiceImpl.java:311)
at com.pack.FailedAttachmentPushReSender.retryFailedPushes(FailedAttachmentPushReSender.java:24)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
at java.util.concurrent.Executors$RunnableAdapter.call$$$capture(Executors.java:511)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java)
at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)
at java.util.concurrent.FutureTask.run(FutureTask.java)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748) Caused by: java.net.SocketException: Broken pipe (Write failed)
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)
at java.net.SocketOutputStream.write(SocketOutputStream.java:155)
at sun.security.ssl.OutputRecord.writeBuffer(OutputRecord.java:431)
at sun.security.ssl.OutputRecord.write(OutputRecord.java:417)
at sun.security.ssl.SSLSocketImpl.writeRecordInternal(SSLSocketImpl.java:886)
at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:857)
at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123)
at org.apache.http.impl.io.SessionOutputBufferImpl.streamWrite(SessionOutputBufferImpl.java:124)
at org.apache.http.impl.io.SessionOutputBufferImpl.write(SessionOutputBufferImpl.java:160)
at org.apache.http.impl.io.ContentLengthOutputStream.write(ContentLengthOutputStream.java:113)
at org.apache.http.entity.ByteArrayEntity.writeTo(ByteArrayEntity.java:114)
at org.apache.http.impl.DefaultBHttpClientConnection.sendRequestEntity(DefaultBHttpClientConnection.java:156)
at org.apache.http.impl.conn.CPoolProxy.sendRequestEntity(CPoolProxy.java:160)
at org.apache.http.protocol.HttpRequestExecutor.doSendRequest(HttpRequestExecutor.java:238)
at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:123)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:272)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56)
at org.springframework.http.client.HttpComponentsClientHttpRequest.executeInternal(HttpComponentsClientHttpRequest.java:89)
at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48)
at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:652) ... 20 more
But when I modify url in postman at the same manner - I see 404 error: 但是当我以相同的方式修改postman中的url时 - 我看到404错误:
I want to have response like in postman and response as in postman. 我希望像邮递员一样得到回复,像邮递员一样回应。
In case if I provide File
instead of FileSystemResource
I get the correct HttpStatusException
where I can extract data I want: 如果我提供
File
而不是FileSystemResource
我会得到正确的HttpStatusException
,我可以在其中提取我想要的数据:
catch (HttpStatusCodeException e) {
String response = e.getResponseBodyAsString();
logger.error("Error during attachment push for file: {}, responseText: {}", fileNameWithPath, response, e);
}
How can I write universal code which will extract response
and httpStatusCode
? 如何编写将提取
response
和httpStatusCode
通用代码?
RestTemplate initialization: RestTemplate初始化:
CloseableHttpClient httpClient
= HttpClients.custom()
.setSSLHostnameVerifier(new NoopHostnameVerifier())
.build();
HttpComponentsClientHttpRequestFactory requestFactory
= new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
restTemplate = new RestTemplate(requestFactory);
I've read RestTemplate ClientHttpResponse.getBody() throws I/O Error but looks like already use suggested factory 我已经读过RestTemplate ClientHttpResponse.getBody()抛出I / O错误,但看起来已经使用了建议的工厂
I tried this: 我试过这个:
CloseableHttpClient client = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(buildAttachmentPushUrl());
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addBinaryBody("file", fileSystemResource.getFile(), ContentType.APPLICATION_OCTET_STREAM, fileSystemResource.getFilename());
builder.addTextBody("type", fileType);
builder.addTextBody("org_id", systemSettingsService.getSystemSettings().getOrganizationId());
builder.addTextBody("stone_id", stoneId);
HttpEntity multipart = builder.build();
httpPost.setEntity(multipart);
CloseableHttpResponse response = client.execute(httpPost);
logger.info("response code {}", response.getStatusLine().getStatusCode());
client.close();
} catch (IOException e) {
e.printStackTrace();
}
But result the same - socket write error
但结果相同 -
socket write error
How can I get real http code and response body using restTemplate? 如何使用restTemplate获取真正的http代码和响应正文?
The short answer is you cannot, because there isn't one. 简短的回答是你不能,因为没有一个。
org.springframework.web.client.ResourceAccessException: I/O error on POST request for " https://external_server.ventures/api/v1/push_file1 ": Software caused connection abort: socket write error;
org.springframework.web.client.ResourceAccessException:对“ https://external_server.ventures/api/v1/push_file1 ”的POST请求的I / O错误:软件导致连接中止:套接字写入错误; nested exception is java.net.SocketException: Software caused connection abort: socket write error
嵌套异常是java.net.SocketException:软件导致连接中止:套接字写入错误
Read the exception message. 阅读异常消息。 The cause (for which you have omitted the stacktrace) is a
java.net.SocketException
with an underlying socket write error
. 原因(您已省略堆栈跟踪)是一个带有底层
socket write error
的java.net.SocketException
。
You never received a response because you probably never finished sending a request. 您从未收到过回复,因为您可能从未完成过发送请求。 See the linked question for some reasons why.
由于某些原因,请参阅链接的问题。
RestClientResponseException
is what you want to catch. RestClientResponseException
是你想要捕获的。 It covers all errors related to responses that you may receive, and provides access to the status, headers and body. 它涵盖了与您可能收到的响应相关的所有错误,并提供对状态,标题和正文的访问权限。 What you've got being thrown is
ResourceAccessException
, which covers all the I/O errors that can happen and don't have any response. 你抛出的是
ResourceAccessException
,它涵盖了可能发生的所有I / O错误,并且没有任何响应。
I normally use this pattern, may be it works for you 我通常使用这种模式,可能适合你
try{
ResponseEntity<String> responseEntity = restTemplate.exchange(url, httpMethod, httpEntity, String.class);
HttpStatus.Series responseSeries = responseEntity.getStatusCode().series();
if(!HttpStatus.Series.SERVER_ERROR.equals(responseSeries)){
return responseEntity;
}
}
catch(HttpClientErrorException e){
//handle exception here
//Response received from server: {} ", e.getResponseBodyAsString());
}
catch (RestClientException e) {
//handle exception here
}
catch (Exception e) {
//handle exception here
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.