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<User> 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<User> 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<User> responseEntity1 = this.restTemplate.postForEntity(uri, user, User.class); // 3-exchange()
RequestEntity<User> requestEntity = RequestEntity.post(new URI(uri)).body(user);
ResponseEntity<User> responseEntity2 = this.restTemplate.exchange(requestEntity, User.class);

设置HTTP Header

// 1-Content-Type
RequestEntity<User> requestEntity = RequestEntity
.post(new URI(uri))
.contentType(MediaType.APPLICATION_JSON)
.body(user); // 2-Accept
RequestEntity<User> requestEntity = RequestEntity
.post(new URI(uri))
.accept(MediaType.APPLICATION_JSON)
.body(user); // 3-Other
RequestEntity<User> 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 {
@Override
public void handleError(ClientHttpResponse response) throws IOException {
// todo
}
}

然后设置下异常处理器:

@Configuration
public class RestClientConfig {
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new CustomErrorHandler());
return restTemplate;
}
}

配置类
创建RestClientConfig类,设置连接池大小、超时时间、重试机制等。配置如下:

 
@Configuration
public class RestClientConfig {
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(clientHttpRequestFactory());
restTemplate.setErrorHandler(new DefaultResponseErrorHandler());
return restTemplate;
}
@Bean
public HttpComponentsClientHttpRequestFactory clientHttpRequestFactory() {
try {
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
return true;
}
}).build();
httpClientBuilder.setSSLContext(sslContext);
HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", sslConnectionSocketFactory).build();// 注册http和https请求
// 开始设置连接池
PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
poolingHttpClientConnectionManager.setMaxTotal(500); // 最大连接数500
poolingHttpClientConnectionManager.setDefaultMaxPerRoute(100); // 同路由并发数100
httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager);
httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(3, true)); // 重试次数
HttpClient httpClient = httpClientBuilder.build();
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient); // httpClient连接配置
clientHttpRequestFactory.setConnectTimeout(20000); // 连接超时
clientHttpRequestFactory.setReadTimeout(30000); // 数据读取超时时间
clientHttpRequestFactory.setConnectionRequestTimeout(20000); // 连接不够用的等待时间
return clientHttpRequestFactory;
} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
log.error("初始化HTTP连接池出错", e);
}
return null;
}
}

注意,如果没有apache的HttpClient类,需要在pom文件中添加:

 
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>

发送文件

 
MultiValueMap<String, Object> multiPartBody = new LinkedMultiValueMap<>();
multiPartBody.add("file", new ClassPathResource("/tmp/user.txt"));
RequestEntity<MultiValueMap<String, Object>> 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<ResponseEntity<File>> responseExtractor = new ResponseExtractor<ResponseEntity<File>>() {
@Override
public ResponseEntity<File> extractData(ClientHttpResponse response) throws IOException {
File rcvFile = File.createTempFile("rcvFile", "zip");
FileCopyUtils.copy(response.getBody(), new FileOutputStream(rcvFile));
return ResponseEntity.status(response.getStatusCode()).headers(response.getHeaders()).body(rcvFile);
}
};
File getFile = this.restTemplate.execute(targetUri, HttpMethod.GET, null, responseExtractor);

Service注入

 
@Service
public class DeviceService {
private static final Logger logger = LoggerFactory.getLogger(DeviceService.class); @Resource
private RestTemplate restTemplate;
}

实际使用例子

 
// 开始推送消息
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<UnbindParam> requestEntity = RequestEntity
.post(uri)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.header("Authorization", token)
.body(unbindParam);
ResponseEntity<HttpBaseResponse> 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

SpringBoot中使用RestTemplate的更多相关文章

  1. SpringBoot中yaml配置对象

    转载请在页首注明作者与出处 一:前言 YAML可以代替传统的xx.properties文件,但是它支持声明map,数组,list,字符串,boolean值,数值,NULL,日期,基本满足开发过程中的所 ...

  2. 如何在SpringBoot中使用JSP ?但强烈不推荐,果断改Themeleaf吧

    做WEB项目,一定都用过JSP这个大牌.Spring MVC里面也可以很方便的将JSP与一个View关联起来,使用还是非常方便的.当你从一个传统的Spring MVC项目转入一个Spring Boot ...

  3. springboot中swaggerUI的使用

    demo地址:demo-swagger-springboot springboot中swaggerUI的使用 1.pom文件中添加swagger依赖 2.从github项目中下载swaggerUI 然 ...

  4. spring-boot+mybatis开发实战:如何在spring-boot中使用myabtis持久层框架

    前言: 本项目基于maven构建,使用mybatis-spring-boot作为spring-boot项目的持久层框架 spring-boot中使用mybatis持久层框架与原spring项目使用方式 ...

  5. 由浅入深学习springboot中使用redis

    很多时候,我们会在springboot中配置redis,但是就那么几个配置就配好了,没办法知道为什么,这里就详细的讲解一下 这里假设已经成功创建了一个springboot项目. redis连接工厂类 ...

  6. Springboot中使用AOP统一处理Web请求日志

    title: Springboot中使用AOP统一处理Web请求日志 date: 2017-04-26 16:30:48 tags: ['Spring Boot','AOP'] categories: ...

  7. SpringBoot 中常用注解

    本篇博文将介绍几种SpringBoot 中常用注解 其中,各注解的作用为: @PathVaribale 获取url中的数据 @RequestParam 获取请求参数的值 @GetMapping 组合注 ...

  8. SpringBoot中关于Mybatis使用的三个问题

    SpringBoot中关于Mybatis使用的三个问题 转载请注明源地址:http://www.cnblogs.com/funnyzpc/p/8495453.html 原本是要讲讲PostgreSQL ...

  9. 在SpringBoot中配置aop

    前言 aop作为spring的一个强大的功能经常被使用,aop的应用场景有很多,但是实际的应用还是需要根据实际的业务来进行实现.这里就以打印日志作为例子,在SpringBoot中配置aop 已经加入我 ...

随机推荐

  1. 如何在vue项目中使用md5加密

    npm安装: npm install --save js-md5 1.在需要使用的项目文件中引入: import md5 from 'js-md5'; 使用: md5('hello world') / ...

  2. 牛客NOIP提高组R1 A中位数(二分)

    题意 题目链接 Sol 很神仙的题目啊,考场上只会$n^2$的暴力.. 考虑直接二分一个$mid$,我们来判断最终答案是否可能大于$x$. 判断的时候记录一下前缀最小值即可, 设$s[i]$表示$1- ...

  3. MySQL-Xtrabackup备份还原

    前言 通常我们都是使用xtrabackup工具来备份数据库,它是一个专业的备份工具,先来简单介绍下它. Xtrabackup percona提供的mysql数据库备份工具,惟一开源的能够对innodb ...

  4. JZOJ 4735. 最小圈

    Description 对于一张有向图,要你求图中最小圈的平均值最小是多少,即若一个圈经过k个节点,那么一个圈的平均值为圈上k条边权的和除以k,现要求其中的最小值 Input 第一行2个正整数,分别为 ...

  5. 2017 ACM/ICPC Shenyang Online SPFA+无向图最长路

    transaction transaction transaction Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 132768/1 ...

  6. CentOS下的Redis启动脚本

    这是一个Shell脚本,用于管理Redis进程(启动,停止,重启),如果你在使用Redis,这个脚本可供参考. #!/bin/sh # # redis - this script starts and ...

  7. Diycode开源项目 SettingActivity分析

    1.整体效果预览及布局分析 1.1.设置界面预览 1.2.主体对应关系 注意这里的线条用ImageView来实现 有一个TextView是检查更新,默认隐藏,具体出现时间还得之后确认. 最后一个Lin ...

  8. #include "*.c"文件的妙用

    在看uCOS II V2.91版本源代码时,在ucos_ii.c源文件中发现下面的代码: #include <os_core.c> #include <os_flag.c> # ...

  9. LOJ #6010. 「网络流 24 题」数字梯形

    #6010. 「网络流 24 题」数字梯形   题目描述 给定一个由 n nn 行数字组成的数字梯形如下图所示.梯形的第一行有 m mm 个数字.从梯形的顶部的 m mm 个数字开始,在每个数字处可以 ...

  10. play后面加the不加the如何分辨

    play表示“参加(某种球类运动或棋牌类的活动)”时,不需要定冠词the,后面直接加球类运动名称或棋牌类活动名称,可根据实际情况翻译成“打,踢,下”等.例如: 1) He often plays fo ...