一、簡介
RestTemplate是spring提供的http客戶端模版,類似JdbcTemplate,它是線程安全的,支持切換不同的http客戶端,目前支持HttpClient-4.3, OKHttp3, 基於netty4實現的http客戶端和基於java的URLConnection實現的http客戶端。
二、引入
RestTemplate默認已經包含在spring-web中,其默認採用java的URLConnection實現的http客戶端,如果想更換不同的http客戶端需要在pom增加需要的依賴,比如依賴okhttp
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.8.1</version>
</dependency>
三、構造實例
-
使用默認構造
@Bean public RestTemplate restTemplate() { return new RestTemplate(); }
-
使用okhttp
@Bean public RestTemplate restTemplate() { OkHttp3ClientHttpRequestFactory f =new OkHttp3ClientHttpRequestFactory(); f.setConnectTimeout(2000); f.setReadTimeout(1000); f.setWriteTimeout(1000); return new RestTemplate(f); }
四、參數相關
-
GET,無參或參數直接寫死到url中,返回string
String result = restTemplate.getForObject("http://vstat.v.blog.aa.com/dostat.do?method=getVideoPlayCount&v=85152140|85162109&rt=json", String.class);
-
GET,參數較多,追加到url中
String url = "http://vstat.v.blog.aa.com/dostat.do"; UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url) .queryParam("method", "getVideoPlayCount") .queryParam("v", "85152140|85162109") .queryParam("rt", "json"); String rst = restTemplate.getForObject(builder.buildAndExpand().toUri(), String.class);
-
GET,佔位符替換
String url = "http://vstat.v.a.aa.com/dostat.do?method={method}&ids={ids}&rt={rt}&test={test}"; String rst = restTemplate.getForObject(url, String.class, "getVideoPlayCount", "85152140|85162109;", "json", "測試");
注意:這裏的傳的參數會進行編碼操作,結果會是如下url:
http://vstat.v.a.aa.com/dostat.do?method=getVideoPlayCount&ids=85152140%7C85162109%3B&rt=json&test=%E6%B5%8B%E8%AF%95
-
GET,佔位符替換(與3一樣,只不過參數放到map中)
Map<String, Object> map = new HashMap<String, Object>(); map.put("method", "getVideoPlayCount"); map.put("ids", "85152140|85162109;"); map.put("rt", "json"); map.put("test", "測試"); String url = "http://vstat.v.aa.com/dostat.do?method={method}&ids={ids}&rt={rt}&test={test}"; String rst = restTemplate.getForObject(url, String.class, map);
-
GET,佔位符替換加參數追加:
Map<String, Object> map = new HashMap<String, Object>(); map.put("method", "getVideoPlayCount"); String url = "http://vstat.aa.com/dostat.do?method={method}"; UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url) .queryParam("v", "85152140|85162109") .queryParam("rt", "json"); String rst = restTemplate.getForObject(builder.buildAndExpand(map).toUri(), String.class);
-
POST與GET類似,但是涉及到POST傳參,如下:
//用於發送post請求的參數 Map<String, String> postMap = new HashMap<String, String>(); postMap.put("a", "b"); String url = "http://{domain}/dostat.do"; //用於替換路徑中的參數 Map<String, String> map = new HashMap<String, String>(); map.put("domain", "vstat.aa.com"); UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url); HttpEntity<Map<String, String>> httpEntity = new HttpEntity<Map<String, String>>(postMap); String rst = restTemplate.postForObject(builder.buildAndExpand(map).toUri(), httpEntity, String.class);
五、返回值相關
-
返回String類型
上面的例子都是返回String
-
返回對象
CountEntity countEntity = restTemplate.getForObject("http://vstat.aa.com/dostat.do?method=getVideoPlayCount&v=85152140|85162109&rt=json", CountEntity.class);
默認,RestTemplate已經具備jackson來進行反序列化json。注意:如果響應中沒有設置application/json的header,那麼會報出如下錯誤:no suitable HttpMessageConverter found for response type此時需要返回String類型,然後使用外部的json工具解析
-
只返回http響應頭:
ResponseEntity<Void> rst = restTemplate.getForEntity("http://vstat.v.aa.com/dostat.do?method=getVideoPlayCount&v=85152140|85162109&rt=json", Void.class);
六、異常處理
-
http狀態碼
默認情況下,響應頭的狀態碼爲1xx或2xx或3xx都認爲響應正常,4xx的會拋出HttpClientErrorException異常,5xx的會拋出HttpServerErrorException異常。
可以繼承org.springframework.web.client.DefaultResponseErrorHandler進行異常處理,默認的處理如下:
public void handleError(ClientHttpResponse response) throws IOException { HttpStatus statusCode = getHttpStatusCode(response); switch (statusCode.series()) { case CLIENT_ERROR: throw new HttpClientErrorException(statusCode, response.getStatusText(), response.getHeaders(), getResponseBody(response), getCharset(response)); case SERVER_ERROR: throw new HttpServerErrorException(statusCode, response.getStatusText(), response.getHeaders(), getResponseBody(response), getCharset(response)); default: throw new RestClientException("Unknown status code [" + statusCode + "]"); } }
並設置restTemplate.setErrorHandler();
-
超時等其他異常
鏈接超時或者讀取超時都會拋出ResourceAccessException,一般情況下,需要try…catch做處理,但是如果採用hystrix,千萬不要捕獲異常,因爲hystrix會捕獲異常進行降級。
七、一些配置
-
http鏈接超時和讀寫超時:需要根據不同的httpclient實現來進行具體配置,一般都在ClientHttpRequestFactory的具體子類中配置,例如okhttp:
OkHttp3ClientHttpRequestFactory f =new OkHttp3ClientHttpRequestFactory(); f.setConnectTimeout(2000); f.setReadTimeout(1000);
-
配置默認參數:如果某些參數確定是每次請求都攜帶且不變的,可以在初始化的時候就設置進去,例如:
RestTemplate restTemplate = new RestTemplate(); Map defaultUriVariables = new HashMap(); defaultUriVariables.put("host", "a.aa.com"); restTemplate.setDefaultUriVariables(defaultUriVariables);