文章目录
前言
什么是RestTemplate:
RestTemplate是一个执行HTTP请求的同步阻塞式工具类,它仅仅只是在 HTTP 客户端库(例如 JDK HttpURLConnection,Apache HttpComponents,okHttp 等)基础上,封装了更加简单易用的模板方法 API,方便程序员利用已提供的模板方法发起网络请求和处理,能很大程度上提升我们的开发效率。它提供了常见的REST请求方案的模版,例如 GET 请求、POST 请求、PUT 请求、DELETE 请求以及一些通用的请求执行方法 exchange 以及 execute。
本文仅介绍简单的使用方法。
一、环境配置
如果当前项目是SpringBoot,添加如下依赖接口!
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
二、API 实践
1.常用get请求方法
通过RestTemplate发送HTTP GET协议请求,经常使用到的方法有两个:
- getForObject():返回值是HTTP协议的响应体
- getForEntity():返回的是ResponseEntity,ResponseEntity是对HTTP响应的封装,除了包含响应体,还包含HTTP状态码、contentType、contentLength、Header等信息
1.1 getForObject()请求示例
- 不带参数:
(uri, String.class) 这两个参数分别代表 请求地址、HTTP响应转换被转换成的对象类型
String uri = "http://localhost:8080/springTest/template";
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject(uri, String.class);
- 携带参数:
如果是get请求,又想要把参数封装到map里面进行传递的话,Map需要使用HashMap,且uri需要使用占位符
(uri, String.class, paramMap) 这三个参数分别代表 请求地址、HTTP响应转换被转换成的对象类型,请求参数
String uri = "http://localhost:8080/springTest/template?name={name}&age={age}";
RestTemplate restTemplate = new RestTemplate();
// 封装参数,这里是HashMap
Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put("name", "张三");
paramMap.put("age", "18");
String result = restTemplate.getForObject(uri, String.class, paramMap);
1.2 getForEntity()请求示例
上面的所有的getForObject请求传参方法,getForEntity都可以使用,使用方法上也几乎是一致的,只是在返回结果接收的时候略有差别
getForEntity使用 ResponseEntity<T> responseEntity 来接收响应结果。用responseEntity.getBody()获取响应体
- 不带参数:
(uri, String.class) 这两个参数分别代表 请求地址、HTTP响应转换被转换成的对象类型
String uri = "http://localhost:8080/springTest/template";
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate .getForEntity(uri, String.class);
// 获取响应体
System.out.println("HTTP 响应body:" + response.getBody().toString());
// 以下是getForEntity比getForObject多出来的内容
HttpStatus statusCode = response.getStatusCode();
int statusCodeValue = response.getStatusCodeValue();
HttpHeaders headers = response.getHeaders();
System.out.println("HTTP 响应状态:" + statusCode);
System.out.println("HTTP 响应状态码:" + statusCodeValue);
System.out.println("HTTP Headers信息:" + headers);
- 携带参数:
如果是get请求,又想要把参数封装到map里面进行传递的话,Map需要使用HashMap,且uri需要使用占位符
(uri, String.class, paramMap) 这三个参数分别代表 请求地址、HTTP响应转换被转换成的对象类型,请求参数
String uri = "http://localhost:8080/springTest/template?name={name}&age={age}";
RestTemplate restTemplate = new RestTemplate();
// 封装参数,这里是HashMap
Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put("name", "张三");
paramMap.put("age", "18");
ResponseEntity<String> response = restTemplate.getForEntity(uri, String.class, paramMap);
2.常用post请求方法
POST请求方法和GET请求方法上大同小异,RestTemplate的POST请求也包含两个主要方法:
- postForObject():返回body对象
- postForEntity():返回全部的信息
postForObject和postForEntity方法的区别主要在于可以在postForEntity方法中设置header的属性,当需要指定header的属性值的时候,使用postForEntity方法。
1、网上都说需要使用MultiValueMap传递参数,但是经过自己测试,发现 MultiValueMap 传递参数请求失败(JSON parse error),改为HashMap反而成功
请求示例
String uri = "http://localhost:8080/springTest/template";
RestTemplate restTemplate = new RestTemplate();
// 使用MultiValueMap调用失败,改用HashMap
// MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<String, Object>();
// paramMap.add("name", "张三");
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("name", "张三");
// 1、使用postForObject请求接口
String result = restTemplate.postForObject(uri, paramMap, String.class);
// 2、使用postForEntity请求接口
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("token", "Bearer eyJ0eXAiOiJqd3QiLC.....");
// 使用MultiValueMap调用失败,改用HashMap
// HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<MultiValueMap<String, Object>>(paramMap,headers);
String body = JSONUtil.toJsonStr(paramMap);
HttpEntity<String> httpEntity = new HttpEntity<>(body, headers);
ResponseEntity<String> response = restTemplate.postForEntity(uri, httpEntity, String.class);
2、使用这二种方法传递参数,还可以通过JSONObject或者实体类传递参数
请求示例
String uri = "http://localhost:8080/springTest/template";
RestTemplate restTemplate = new RestTemplate();
User user = new User ();
user .setName("张三")
// 1、使用postForObject请求接口
String result = restTemplate.postForObject(uri, user, String.class);
// 2、使用postForEntity请求接口
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("token", "Bearer eyJ0eXAiOiJqd3QiLC.....");
HttpEntity<String> httpEntity = new HttpEntity<String>(JSONUtil.toJsonStr(user),headers);
ResponseEntity<String> response = restTemplate.postForEntity(uri, httpEntity, String.class);
3.通用exchange请求方法
在RestTemplate工具类里面,还有一个exchange通用协议请求方法,exchange方法和postForEntity类似,但是更灵活,它可以发送GET、POST、DELETE、PUT、OPTIONS、PATCH等等HTTP方法请求
RestTemplate.exchange()方法的使用:
方法名称:exchange(String url, HttpMethod method,@Nullable HttpEntity<?> requestEntity, Class responseType, Map uriVariables)
说明:1)url: 请求地址;
2)method: 请求类型(如:POST,PUT,DELETE,GET);
3)requestEntity: 请求实体,封装请求头,请求内容
4)responseType: 响应类型,根据服务接口的返回类型决定
5)uriVariables: url中参数变量值
3.1 get请求示例
以下演示传递header和参数的情况,不需要可以传null或不传
String uri = "http://localhost:8080/springTest/template?name={name}&age={age}";
RestTemplate restTemplate = new RestTemplate();
Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put("name", "张三");
paramMap.put("age", "18");
HttpHeaders headers = new HttpHeaders();
headers.add("token", "Bearer eyJ0eXAiOiJqd3QiLC.....");
HttpEntity<String> httpEntity = new HttpEntity<>(null, headers);
ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.GET, httpEntity, String.class,paramMap);
//返回数据处理,实体接收
String responseStr = response.getBody();
JSONObject jsonObject = JSON.parseObject(responseStr);
// 返回数据
return StringUtil.isBlank(responseStr) ?
new Response(500, "返回空数据") :
JSONObject.toJavaObject(jsonObject, Response.class);
3.2 post请求示例
1、网上都说需要使用MultiValueMap传递参数,但是经过自己测试,发现 MultiValueMap 传递参数请求失败(JSON parse error),改为HashMap反而成功
请求示例:
String uri = "http://localhost:8080/springTest/template";
RestTemplate restTemplate = new RestTemplate();
// 使用MultiValueMap调用失败,改用HashMap
// MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<String, Object>();
// paramMap.add("name", "张三");
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("name", "张三");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("token", "Bearer eyJ0eXAiOiJqd3QiLC.....");
// 使用MultiValueMap调用失败,改用HashMap
// HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<MultiValueMap<String, Object>>(paramMap,headers);
String body = JSONUtil.toJsonStr(paramMap);
HttpEntity<String> httpEntity = new HttpEntity<>(body, headers);
ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.POST, httpEntity, String.class);
//返回数据处理,实体接收
String responseStr = response.getBody();
JSONObject jsonObject = JSON.parseObject(responseStr);
// 返回数据
return StringUtil.isBlank(responseStr) ?
new Response(500, "返回空数据") :
JSONObject.toJavaObject(jsonObject, Response.class);
2、使用这种方法传递参数,和postForEntity类似,还可以通过JSONObject传递参数
String uri = "http://localhost:8080/springTest/template";
RestTemplate restTemplate = new RestTemplate();
User user = new User ();
user .setName("张三")
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("token", "Bearer eyJ0eXAiOiJqd3QiLC.....");
HttpEntity<String> httpEntity = new HttpEntity<String>(JSONUtil.toJsonStr(user),headers);
ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.POST, httpEntity, String.class);
//返回数据处理,实体接收
String responseStr = response.getBody();
JSONObject jsonObject = JSON.parseObject(responseStr);
// 返回数据
return StringUtil.isBlank(responseStr) ?
new Response(500, "返回空数据") :
JSONObject.toJavaObject(jsonObject, Response.class);
三、https 请求
某些情况下需要进行https请求,需要特殊处理,下面以通用exchange请求方法为例
1.添加依赖
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
2.添加配置
package com.demo.config;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.ssl.SSLContexts;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.security.KeyStore;
public class HttpsClientHttpRequestFactory extends SimpleClientHttpRequestFactory {
@Override
protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException {
try {
if (connection instanceof HttpsURLConnection) {// https协议,修改协议版本
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
// 信任任何链接,忽略对证书的校验
TrustStrategy anyTrustStrategy = (x509Certificates, s) -> true;
//自定义SSLContext
SSLContext ctx = SSLContexts.custom().loadTrustMaterial(trustStore, anyTrustStrategy).build();
// ssl问题
((HttpsURLConnection) connection).setSSLSocketFactory(ctx.getSocketFactory());
//解决No subject alternative names matching IP address xxx.xxx.xxx.xxx found问题
((HttpsURLConnection) connection).setHostnameVerifier((s, sslSession) -> true);
HttpsURLConnection httpsConnection = (HttpsURLConnection) connection;
super.prepareConnection(httpsConnection, httpMethod);
} else { // http协议
super.prepareConnection(connection, httpMethod);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
3.请求实例
3.1 get请求示例
private Response getApi(String url) {
try {
HttpHeaders headers = new HttpHeaders();
HttpEntity<String> requestEntity = new HttpEntity<>(null, headers);
// 发送请求
RestTemplate client = new RestTemplate();
if (url.contains("https")){
client = new RestTemplateBuilder()
.requestFactory(HttpsClientHttpRequestFactory::new)
//basic认证
.basicAuthentication("username", "password")
.build();
}
ResponseEntity<String> response = client.exchange(url, HttpMethod.GET, requestEntity, String.class);
String responseStr = response.getBody();
JSONObject jsonObject = JSON.parseObject(responseStr);
// 返回数据
return StringUtil.isBlank(responseStr) ?
new Response(500, "返回空数据") :
JSONObject.toJavaObject(jsonObject, Response.class);
} catch (Exception e) {
log.error("response error:{}", e);
return new Response(500, e.toString());
}
}
3.2 post请求示例
private Response postApi(String url, Map<String, Object> paramMap) {
try {
// 请求头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
// 参数信息
String body = JSONUtil.toJsonStr(paramMap);
HttpEntity<String> requestEntity = new HttpEntity<>(body, headers);
// 发送请求
RestTemplate client = new RestTemplate();
if (url.contains("https")){
client = new RestTemplateBuilder()
.requestFactory(HttpsClientHttpRequestFactory::new)
//basic认证
.basicAuthentication("username", "password")
.build();
}
ResponseEntity<String> response = client.exchange(url, HttpMethod.POST, requestEntity, String.class);
String responseStr = response.getBody();
JSONObject jsonObject = JSON.parseObject(responseStr);
// 返回数据
return StringUtil.isBlank(responseStr) ?
new Response(500, "返回空数据") :
JSONObject.toJavaObject(jsonObject, Response.class);
} catch (Exception e) {
log.error("response error:{}", e);
return new Response(500, e.toString());
}
}
总结
本文仅仅简单介绍了RestTemplate的使用,而RestTemplate提供了大量能使我们快速便捷地处理Http请求的方法。