您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“使用RestTemplate時報錯RestClientException怎么解決”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學(xué)習(xí)“使用RestTemplate時報錯RestClientException怎么解決”吧!
使用RestTemplate時報錯RestClientException
這是自己封裝的一個發(fā)送請求的方法
這是自定義的一個http信息Converter
RestTemplate的錯誤處理
問題描述
ErrorHandler
解決辦法
public Map<String, Object> sendRequest(Map<String, Object> body,String sessionId,String url) { RestTemplate restTemplate = new RestTemplate(); restTemplate.getMessageConverters().add(new BdMappingJackson2HttpMessageConverter()); Map<String, Object> map = new HashMap<>(); try { ParameterizedTypeReference<Map<String, Object>> typeRef = new ParameterizedTypeReference<Map<String, Object>>() { }; HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); headers.set("cookie", "SESSION="+sessionId); HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(body,headers); ResponseEntity<Map<String, Object>> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity,typeRef); map = responseEntity.getBody(); log.info(map.toString()); } catch (HttpStatusCodeException e) { log.error(e.getResponseBodyAsString(), e); map = JsonUtil.toMap(e.getResponseBodyAsString()); } return map; }
public class BdMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter { public BdMappingJackson2HttpMessageConverter(){ List<MediaType> mediaTypes = new ArrayList<>(); mediaTypes.add(MediaType.TEXT_HTML); mediaTypes.add(MediaType.APPLICATION_OCTET_STREAM); setSupportedMediaTypes(mediaTypes); } }
我遇到的第一個問題是這樣的
Could not write request: no suitable HttpMessageConverter found for request type [java.util.HashMap] and content type [application/octet-stream]
意思大概是無法寫入請求:找不到適用于請求類型[java.util.HashMap]和內(nèi)容類型[application/octet stream]的HttpMessageConverter
它默認只處理application/json:JSON數(shù)據(jù)格式,這個二進制數(shù)據(jù)流格式不支持,所以我在那個自定義的Converter加上去了。
緊接著又遇到第二個問題
Could not extract response: no suitable HttpMessageConverter found for response type [java.util.Map<java.lang.String, java.lang.Object>] and content type [text/xml;charset=UTF-8]
無法提取響應(yīng):找不到適合于響應(yīng)類型[java.util.Map<java.lang.String,java.lang.Object>]和內(nèi)容類型[textml/charset=UTF-8]的HttpMessageConverter
這是那邊回調(diào)過來的Content-Type類型是text/xml它同樣解析不了,所以我把這個也加上去了,至此就ok了。
常見的Content-Type類型:
text/html
:HTML格式
text/plain
:純文本格式
image/png
:png圖片格式
application/json
:JSON數(shù)據(jù)格式
application/octet-stream
:二進制流數(shù)據(jù)
application/x-www-form-urlencoded
:表單中默認的encType,表單數(shù)據(jù)被編碼為key/value格式發(fā)送到服務(wù)器
multipart/form-data
:需要在表單中進行文件上傳時,就需要使用該格式
我們的項目屬于微服務(wù)架構(gòu),兩個基礎(chǔ)的服務(wù)分別是網(wǎng)關(guān)和認證鑒權(quán)服務(wù)。
在前端訪問后臺服務(wù)的時候,都經(jīng)過網(wǎng)關(guān)轉(zhuǎn)發(fā),轉(zhuǎn)發(fā)之前會進行鑒權(quán)認證,根據(jù)鑒權(quán)結(jié)果判斷是否可以進行相應(yīng)的請求轉(zhuǎn)發(fā)。
認證鑒權(quán)服務(wù)中,判斷Token對應(yīng)的人員是否有相應(yīng)的權(quán)限,如果沒有權(quán)限,返回401狀態(tài)碼并在響應(yīng)體中傳回錯誤信息。
網(wǎng)關(guān)與鑒權(quán)服務(wù)之間的服務(wù)調(diào)用通過RestTemplate進行(可以考慮轉(zhuǎn)為Feign做聲明式的服務(wù)調(diào)用),然而如果鑒權(quán)服務(wù)返回401的情況下,網(wǎng)關(guān)服務(wù)直接報出HttpClientErrorException,讓人一頭霧水。
實際上,答案都在源碼中,看一下RestTemplate的源碼就知曉了。
在RestTemplate中,有一個成員變量ResponseErrorHandler。
ResponseErrorHandler是一個接口,包括兩個方法:
public interface ResponseErrorHandler { boolean hasError(ClientHttpResponse var1) throws IOException; void handleError(ClientHttpResponse var1) throws IOException; }
這個接口有一個默認實現(xiàn)DefaultResponseErrorHandler。該方法中,判斷是否發(fā)生error的方法hasError最終調(diào)用的方法如下:
protected boolean hasError(HttpStatus statusCode) { return statusCode.series() == Series.CLIENT_ERROR || statusCode.series() == Series.SERVER_ERROR; }
很明顯,根據(jù)響應(yīng)狀態(tài)嗎為4xx或者5xx來認定發(fā)生了錯誤。而錯誤處理在handleError中:
public void handleError(ClientHttpResponse response) throws IOException { HttpStatus statusCode = this.getHttpStatusCode(response); switch(null.$SwitchMap$org$springframework$http$HttpStatus$Series[statusCode.series().ordinal()]) { case 1: throw new HttpClientErrorException(statusCode, response.getStatusText(), response.getHeaders(), this.getResponseBody(response), this.getCharset(response)); case 2: throw new HttpServerErrorException(statusCode, response.getStatusText(), response.getHeaders(), this.getResponseBody(response), this.getCharset(response)); default: throw new RestClientException("Unknown status code [" + statusCode + "]"); } }
可見,4xx的狀態(tài)嗎會拋出HttpClientErrorException;5xx的狀態(tài)碼會拋出HttpServerErrorException。這也就是我們一開始遇到的問題的原因所在了。而在handleError中,執(zhí)行了response.getBody(),這就導(dǎo)致我們后續(xù)獲取不到響應(yīng)體了,如果要獲取的話,需要進行自定義相關(guān)處理。
如果RestTemplate的應(yīng)用場景比較統(tǒng)一,可以自定義ResponseErorHandler(派生自DefaultResponseErrorHandler)來接管錯誤處理,進行自己想要的處理。
而我們的網(wǎng)關(guān)中,對于頁面跳轉(zhuǎn)類的請求和Rest API類的請求,處理辦法顯然是不一樣的。所以最終處理是catch異常,然后進行重定向的處理操作。
到此,相信大家對“使用RestTemplate時報錯RestClientException怎么解決”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進入相關(guān)頻道進行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。