spring框架提供的RestTemplate类可用于在应用中调用rest服务,它简化了与http服务的通信方式,统一了RESTful的标准,封装了http链接, 我们只需要传入url及返回值类型即可。相较于之前常用的HttpClient,RestTemplate是一种更优雅的调用RESTful服务的方式。
RestTemplate默认依赖JDK提供http连接的能力(HttpURLConnection),如果有需要的话也可以通过setRequestFactory方法替换为例如 Apache HttpComponents、Netty或OkHttp等其它HTTP library。
本篇介绍如何使用RestTemplate,以及在SpringBoot里面的配置和注入。
实现逻辑
RestTemplate包含以下几个部分:
HttpMessageConverter 对象转换器
ClientHttpRequestFactory 默认是JDK的HttpURLConnection
ResponseErrorHandler 异常处理
ClientHttpRequestInterceptor 请求拦截器
用一张图可以很直观的理解:
发送GET请求
// 1-getForObject()
User user1 = this.restTemplate.getForObject(uri, User.class);
// 2-getForEntity() ResponseEntity responseEntity1 = this.restTemplate.getForEntity(uri, User.class); HttpStatus statusCode = responseEntity1.getStatusCode(); HttpHeaders header = responseEntity1.getHeaders(); User user2 = responseEntity1.getBody(); // 3-exchange() RequestEntity requestEntity = RequestEntity.get(new URI(uri)).build(); ResponseEntity responseEntity2 = this.restTemplate.exchange(requestEntity, User.class); User user3 = responseEntity2.getBody();
发送POST请求
// 1-postForObject()
User user1 = this.restTemplate.postForObject(uri, user, User.class);
// 2-postForEntity() ResponseEntity responseEntity1 = this.restTemplate.postForEntity(uri, user, User.class); // 3-exchange() RequestEntity requestEntity = RequestEntity.post(new URI(uri)).body(user); ResponseEntity responseEntity2 = this.restTemplate.exchange(requestEntity, User.class);
设置HTTP Header
// 1-Content-Type
RequestEntity requestEntity = RequestEntity
.post(new URI(uri))
.contentType(MediaType.APPLICATION_JSON) .body(user); // 2-Accept RequestEntity requestEntity = RequestEntity .post(new URI(uri)) .accept(MediaType.APPLICATION_JSON) .body(user); // 3-Other RequestEntity requestEntity = RequestEntity .post(new URI(uri)) .header("Authorization", "Basic " + base64Credentials) .body(user);
捕获异常
捕获HttpServerErrorException
try {
responseEntity = restTemplate.exchange(requestEntity, String.class);
} catch (HttpServerErrorException e) {
// log error }
自定义异常处理器
public class CustomErrorHandler extends DefaultResponseErrorHandler {
然后设置下异常处理器:
配置类
创建RestClientConfig
类,设置连接池大小、超时时间、重试机制等。配置如下:
注意,如果没有apache的HttpClient类,需要在pom文件中添加:
<dependency>
<groupId>org.apache.httpcomponentsgroupId> <artifactId>httpclientartifactId> <version>4.5.3version> dependency>
发送文件
MultiValueMap multiPartBody = new LinkedMultiValueMap<>();
multiPartBody.add("file", new ClassPathResource("/tmp/user.txt")); RequestEntity> requestEntity = RequestEntity .post(uri) .contentType(MediaType.MULTIPART_FORM_DATA) .body(multiPartBody);
下载文件
// 小文件
RequestEntity requestEntity = RequestEntity.get(uri).build();
ResponseEntity<byte[]> responseEntity = restTemplate.exchange(requestEntity, byte[].class); byte[] downloadContent = responseEntity.getBody(); // 大文件 ResponseExtractor> responseExtractor = new ResponseExtractor>() {
Service注入
实际使用例子
// 开始推送消息
logger.info("解绑成功后推送消息给对应的POS机");
LoginParam loginParam = new LoginParam(); loginParam.setUsername(managerInfo.getUsername()); loginParam.setPassword(managerInfo.getPassword()); HttpBaseResponse r = restTemplate.postForObject( p.getPosapiUrlPrefix() + "/notifyLogin", loginParam, HttpBaseResponse.class); if (r.isSuccess()) { logger.info("推送消息登录认证成功"); String token = (String) r.getData(); UnbindParam unbindParam = new UnbindParam(); unbindParam.setImei(pos.getImei()); unbindParam.setLocation(location); // 设置HTTP Header信息 URI uri; try { uri = new URI(p.getPosapiUrlPrefix() + "/notify/unbind"); } catch (URISyntaxException e) { logger.error("URI构建失败", e); return 1; } RequestEntity requestEntity = RequestEntity .post(uri) .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) .header("Authorization", token) .body(unbindParam); ResponseEntity responseEntity = restTemplate.exchange(requestEntity, HttpBaseResponse.class); HttpBaseResponse r2 = responseEntity.getBody(); if (r2.isSuccess()) { logger.info("推送消息解绑网点成功"); } else { logger.error("推送消息解绑网点失败,errmsg = " + r2.getMsg()); } } else { logger.error("推送消息登录认证失败"); }
GitHub源码
springboot-resttemplate