简体   繁体   English

如何使用restTemplate获取真正的http代码和响应正文?

[英]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 ? 如何编写将提取responsehttpStatusCode通用代码?

PS1. PS1。

RestTemplate initialization: RestTemplate初始化:

CloseableHttpClient httpClient
                = HttpClients.custom()
                .setSSLHostnameVerifier(new NoopHostnameVerifier())
                .build();
        HttpComponentsClientHttpRequestFactory requestFactory
                = new HttpComponentsClientHttpRequestFactory();
        requestFactory.setHttpClient(httpClient);
        restTemplate = new RestTemplate(requestFactory);

PS2 PS2

I've read RestTemplate ClientHttpResponse.getBody() throws I/O Error but looks like already use suggested factory 我已经读过RestTemplate ClientHttpResponse.getBody()抛出I / O错误,但看起来已经使用了建议的工厂

PS3 PS3

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 errorjava.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错误,并且没有任何响应。

RestClientException和子类的UML图

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.

相关问题 如何以字符串形式获取 HTTP 响应正文? - How can I get an HTTP response body as a string? 如何使用 selenium java 读取 http 响应正文? - How can I read http response body using selenium java? 对于复杂的 RestTemplate Body Object 需要帮助。 如何使用 RestTemplate 构建它? - Need help for complicated RestTemplate Body Object. How can I build this using RestTemplate? 如何在HTTP响应体(使用Spark)中发送QR码的PNG? - How can I send a PNG of a QR-code in a HTTP response body (with Spark)? 获取 http 响应代码和所有可用的正文 - Get http response code and all available body 当 java 中的请求失败时,如何获取 http 响应正文? - How can I get http response body when request is failed in java? 如何通过Spring RestTemplate更改获取请求中的响应http标头? - How to change response http header in get request by spring RestTemplate? 使用Http请求在单个请求中获取响应代码和响应正文 - Get Response Code and Response Body ina a single request using Http-request 如何使用 Spring 中的 restTemplate 使用请求正文发出 GET 请求 - How to make a GET request with request body using restTemplate in Spring RestTemplate:如何获取原始响应 - RestTemplate: How to get the raw response
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM