一、简介
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);