簡體   English   中英

如何使用restTemplate獲取真正的http代碼和響應正文?

[英]How can I get real http code and response body using restTemplate?

我有以下代碼:

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)

如果我提供所有正確的參數 - enpoint返回200 http stsatus代碼,如預期的Postman應用程序。

但如果我提供了錯誤的網址 - 我看到異常:

 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 

但是當我以相同的方式修改postman中的url時 - 我看到404錯誤:

在此輸入圖像描述

我希望像郵遞員一樣得到回復,像郵遞員一樣回應。

如果我提供File而不是FileSystemResource我會得到正確的HttpStatusException ,我可以在其中提取我想要的數據:

catch (HttpStatusCodeException e) {          
            String response = e.getResponseBodyAsString();
            logger.error("Error during attachment push for file: {}, responseText: {}", fileNameWithPath, response, e);
}

如何編寫將提取responsehttpStatusCode通用代碼?

PS1。

RestTemplate初始化:

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

PS2

我已經讀過RestTemplate ClientHttpResponse.getBody()拋出I / O錯誤,但看起來已經使用了建議的工廠

PS3

我試過這個:

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();
        }

但結果相同 - socket write error

如何使用restTemplate獲取真正的http代碼和響應正文?

簡短的回答是你不能,因為沒有一個。

org.springframework.web.client.ResourceAccessException:對“ https://external_server.ventures/api/v1/push_file1 ”的POST請求的I / O錯誤:軟件導致連接中止:套接字寫入錯誤; 嵌套異常是java.net.SocketException:軟件導致連接中止:套接字寫入錯誤

閱讀異常消息。 原因(您已省略堆棧跟蹤)是一個帶有底層socket write errorjava.net.SocketException

您從未收到過回復,因為您可能從未完成過發送請求。 由於某些原因,請參閱鏈接的問題。


RestClientResponseException是你想要捕獲的。 它涵蓋了與您可能收到的響應相關的所有錯誤,並提供對狀態,標題和正文的訪問權限。 你拋出的是ResourceAccessException ,它涵蓋了可能發生的所有I / O錯誤,並且沒有任何響應。

RestClientException和子類的UML圖

我通常使用這種模式,可能適合你

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM