1、简介
- RestTemplate是由Spring框架提供的一个可用于应用中调用rest服务的类它简化了与http服务的通信方式,统一了RESTFul的标准,封装了http连接,我们只需要传入url及其返回值类型即可。相较于之前常用的HttpClient,RestTemplate是一种更为优雅的调用RESTFul服务的方式。
- 在Spring应用程序中访问第三方REST服务与使用Spring RestTemplate类有关。RestTemplate类的设计原则与许多其他Spring的模板类(例如JdbcTemplate)相同,为执行复杂任务提供了一种具有默认行为的简化方法。
- RestTemplate默认依赖JDK提供了http连接的能力(HttpURLConnection),如果有需要的话也可以通过setRequestFactory方法替换为例如Apache HttpCompoent、Netty或OKHttp等其他Http libaray。
- 考虑到了RestTemplate类是为了调用REST服务而设计的,因此它的主要方法与REST的基础紧密相连就不足为奇了,后者时HTTP协议的方法:HEAD、GET、POST、PUT、DELETE、OPTIONS例如,RestTemplate类具有headForHeaders()、getForObject()、putForObject(),put()和delete()等方法。
- delete() 在特定的URL上对资源执行HTTP DELETE操作
- exchange() 在URL上执行特定的HTTP方法,返回包含对象的ResponseEntity,这个对象是从响应体中 映射得到的
- execute() 在URL上执行特定的HTTP方法,返回一个从响应体映射得到的对象
- getForEntity() 发送一个HTTP GET请求,返回的ResponseEntity包含了响应体所映射成的对象
- getForObject() 发送一个HTTP GET请求,返回的请求体将映射为一个对象
- postForEntity() POST 数据到一个URL,返回包含一个对象的ResponseEntity,这个对象是从响应体中映射得到的
- postForObject() POST 数据到一个URL,返回根据响应体匹配形成的对象
- headForHeaders() 发送HTTP HEAD请求,返回包含特定资源URL的HTTP头
- optionsForAllow() 发送HTTP OPTIONS请求,返回对特定URL的Allow头信息
- postForLocation() POST 数据到一个URL,返回新创建资源的URL
- put() PUT 资源到特定的URL
2、创建RestTemplate
因为RestTemplate是Spirng框架提供的所以只要是一个Springboot项目就不用考虑导包的问题,这些都是提供好的。但是Spring并没有将其加入SpringBean容器中,需要我们手动加入,因为我们首先创建一个Springboot配置类,再在配置类中将我们的RestTemlate注册到Bean容器中
- 自定义一些连接参数
使用Springboot
提供的RestTemplateBuilder
构造类来构造一个RestTemplate
,可以自定义一些连接参数,如:连接超时时间,读取超时时间,还有认证信息等
@Configuration
public class WebConfiguration {
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder){
return builder
//设置连接超时时间
.setConnectTimeout(Duration.ofSeconds(5000))
//设置读取超时时间
.setReadTimeout(Duration.ofSeconds(5000))
//设置认证信息
.basicAuthentication("username","password")
//设置根路径
.rootUri("https://api.test.com/")
//构建
.build();
}
}
- 自定义拦截器
@Slf4j
public class CustomClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
//打印请求明细
logRequestDetails(request,body);
ClientHttpResponse response = execution.execute(request, body);
//打印响应明细
logResponseDetails(response);
return response;
}
private void logRequestDetails(HttpRequest request, byte[] body){
log.debug("Headers:{}",request.getHeaders());
log.debug("body:{}",new String(body, StandardCharsets.UTF_8));
log.debug("{}:{}",request.getMethod(),request.getMethodValue());
}
private void logResponseDetails(ClientHttpResponse response) throws IOException {
log.debug("Status code : {}",response.getStatusCode());
log.debug("Status text : {}",response.getStatusText());
log.debug("Headers : {}",response.getHeaders());
log.debug("Response body: {}", StreamUtils.copyToString(response.getBody(),StandardCharsets.UTF_8));
}
}
@Configuration
public class WebConfiguration {
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder){
return builder
.additionalInterceptors(new CustomClientHttpRequestInterceptor())
//构建
.build();
}
}
3、RestTemplate API
使用
3.1、GET
public <T> T getForObject(...)
public <T> ResponseEntity<T> getForEntity(...)
getForEntity()
getForEntity()
方法
第一个参数为我要调用服务的URL
,
第二个参数则为响应内容的类的类型,还可以添加第三个参数,
第三个参数为一个可变参数 代表着调用服务时的传参,第三个参数可以使用key-value的map来传入参数
public void queryGet() {
ResponseEntity<Object> responseEntity = restTemplate.getForEntity(
"https://com.test.api/v3?city=510100&key=222", Object.class);
// 获取状态对象
HttpStatus httpStatus = responseEntity.getStatusCode();
// 获取状态码
int statusCodeValue = responseEntity.getStatusCodeValue();
// 获取headers
HttpHeaders httpHeaders = responseEntity.getHeaders();
// 获取body
TempUser result = responseEntity.getBody();
}
getForObject()
相比于前者getForEntity()
该方法则是,更偏向于直接获取响应内容的,因为他直接返回响应实体的body
(响应内容)
public void queryGet() {
JSONObject body = restTemplate.getForObject(
"https://www.test.com/v3?city=510100&key=111", JSONObject.class);
System.out.println(body);
}
3.2、POST
public URI postForLocation(...)
public <T> T postForObject(...)
public <T> ResponseEntity<T> postForEntity(...)
postForEntity()
该方法有三个参数,
第一个为调用服务的地址(URL)
第二个参数表示上传的参数(json格式提交)
第三个表示返回响应内容的具体类型
第四个参数也用于指定参数(在URL中添加)
@Override
public void queryPost() {
JSONObject json = new JSONObject();
json.put("aaa","111");
ResponseEntity<Object> responseEntity = restTemplate.postForEntity(
"https://www.test.com/v3?city=510100", json, Object.class);
System.out.println("消息响应内容:"+responseEntity.getBody());
// 获取状态对象
HttpStatus httpStatus = responseEntity.getStatusCode();
// 获取状态码
int statusCodeValue = responseEntity.getStatusCodeValue();
// 获取headers
HttpHeaders httpHeaders = responseEntity.getHeaders();
// 获取body
TempUser result = responseEntity.getBody();
}
postForObject()
public void queryPost() {
JSONObject json = new JSONObject();
json.put("aaa","111");
JSONObject result = restTemplate.postForObject(
"https://www.test.com/post", json, JSONObject.class);
System.out.println("消息响应内容:"+result);
}
postForLocation()
postForLocation
传参用法与前两者一致,只不过返回从实体变成了一个URL
,因此它不需要指定返回响应内容的类型。
public void queryPost() {
JSONObject json = new JSONObject();
json.put("aaa","111");
URI uri = restTemplate.postForLocation(
"https://www.test.com/post", json);
System.out.println(uri);
}
这个只需要服务提供者返回一个 URI 即可,该URI
返回值体现的是:用于提交完成数据之后的页面跳转,或数据提交完成之后的下一步数据操作URI
。