一 概述
實現如下效果代碼,且可正常獲取到返回數據:
ResponseEntity<JsonObject> resEntity = restTemplate
.exchange(url, HttpMethod.GET, requestEntity, JsonObject.class,uriVariables);
restTemplate的get和POST請求都有類型參數設置,所以可以直接返回轉換成自定義的格式.比如:
restTemplate.getForObject("http://www.baiud.com",JsonObject.class);
但是exchange是無法指定返回類型的,只能使用spring默認提供的幾種轉換器轉換的格式,定義其他格式會報錯或者返回實體body為空
restTemplate的post方法支持設置header,但是get方法不支持,假如現在有個需求,使用get方法需要設置header權限,且返回我想要的格式,那么自定義HttpMessageConverter就派上用場了
也提現了spring非常強大的可擴展性
二 步驟
新建自定義轉換類:
/** * 接口請求返回數據格式轉換處理類,只處理String->JsonObject */ public class StringToJsonObjectMessageConverter extends AbstractHttpMessageConverter<JsonObject> { public StringToJsonObjectMessageConverter() { super(StandardCharsets.UTF_8,MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML); //設置支付類型 } /** * HttpMessageConvert是否處理接受的這個類 */ @Override protected boolean supports(Class<?> aClass) { //isAssignableFrom: 判定此Class對象所表示的類或接口與指定的 Class 參數所表示的類或接口是否相同,或是否是其超類或超接口 return JsonObject.class==aClass; } //對數據進行處理並返回 @Override protected JsonObject readInternal(Class<? extends JsonObject> aClass, HttpInputMessage httpInputMessage) throws IOException, HttpMessageNotReadableException { //數據轉換 String temp = StreamUtils.copyToString(httpInputMessage.getBody(),Charset.forName("UTF-8")); return Tools.getGsonInstance().fromJson(temp, JsonObject.class); } //處理如何輸出數據到response @Override protected void writeInternal(JsonObject jsonObject, HttpOutputMessage httpOutputMessage) throws IOException, HttpMessageNotWritableException { //可繼續處理轉換后的格式數據 httpOutputMessage.getBody().write(jsonObject.getAsByte()); } }
配置修改自定義類順序:
@Bean public RestTemplate restTemplate() { HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(); httpRequestFactory.setConnectionRequestTimeout(30 * 1000); httpRequestFactory.setConnectTimeout(30 * 3000); httpRequestFactory.setReadTimeout(30 * 3000); RestTemplate restTemplate = new RestTemplate(httpRequestFactory); // 支持返回JsonObject類型數據,需要在String之前,因為String支付所有的類型會直接解析 restTemplate.getMessageConverters().set(1,new StringToJsonObjectMessageConverter()); //spring轉換默認編碼是ISO_8859_1,如果亂碼可修改支持中文編碼 restTemplate.getMessageConverters().add(new StringHttpMessageConverter(StandardCharsets.UTF_8)); return restTemplate; }
斷點查看:
三 原理
exchage方法源碼點進去,看一下就知道了
//獲取HttpMessageConverter集合 Iterator var8 = RestTemplate.this.getMessageConverters().iterator(); //按照索引順序進行迭代循環解析 while(var8.hasNext()) { HttpMessageConverter<?> messageConverter = (HttpMessageConverter)var8.next(); if (messageConverter instanceof GenericHttpMessageConverter) { GenericHttpMessageConverter<Object> genericConverter = (GenericHttpMessageConverter)messageConverter; if (genericConverter.canWrite((Type)requestBodyType, requestBodyClass, requestContentType)) { if (!requestHeadersx.isEmpty()) { requestHeadersx.forEach((key, values) -> { httpHeadersx.put(key, new LinkedList(values)); }); } if (RestTemplate.this.logger.isDebugEnabled()) { if (requestContentType != null) { RestTemplate.this.logger.debug("Writing [" + requestBody + "] as \"" + requestContentType + "\" using [" + messageConverter + "]"); } else { RestTemplate.this.logger.debug("Writing [" + requestBody + "] using [" + messageConverter + "]"); } } //解析成功直接返回,不會走后面解析器 genericConverter.write(requestBody, (Type)requestBodyType, requestContentType, httpRequest); return; } } else if (messageConverter.canWrite(requestBodyClass, requestContentType)) { if (!requestHeadersx.isEmpty()) { requestHeadersx.forEach((key, values) -> { httpHeadersx.put(key, new LinkedList(values)); }); } if (RestTemplate.this.logger.isDebugEnabled()) { if (requestContentType != null) { RestTemplate.this.logger.debug("Writing [" + requestBody + "] as \"" + requestContentType + "\" using [" + messageConverter + "]"); } else { RestTemplate.this.logger.debug("Writing [" + requestBody + "] using [" + messageConverter + "]"); } } messageConverter.write(requestBody, requestContentType, httpRequest); return; } } //如果都沒有解析成功.拋異常 String message = "Could not write request: no suitable HttpMessageConverter found for request type [" + requestBodyClass.getName() + "]"; if (requestContentType != null) { message = message + " and content type [" + requestContentType + "]"; } throw new RestClientException(message);