重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
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()
等方法。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));
}
}
使用RestTemplateBuilder
构造类,添加自定义拦截器,构造带有自定义拦截器的RestTemplate
实例
@Configuration
public class WebConfiguration {@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder){return builder
.additionalInterceptors(new CustomClientHttpRequestInterceptor())
//构建
.build();
}
}
测试请求确实经过了拦截器,注册成功(注意请求和响应的流只会被读取一次,这里我们读取了response后返回的response就读取不到刚刚读过的内容了)
使用RestTemplate
构造方法构造一个RestTemlate
,虽然不能像RestTemplate
构造类那样更详细、更多样的配置参数,但是RestTemplate
构造方法在一般情况是够用的。
ClientHttpRequestFactory
的构造方法可以指定自己实现的ClientHttpRequestFactory
(客户端http
请求工厂)其他的与无参构造相同。ClientHttpRequestFactory
List>
的构造方法可以指定自己是实现的HttpMessageConverter
(Http
消息转换器)传入其他与无参构造相同。@Configuration
public class WebConfiguration {@Bean
public RestTemplate restTemplate(){return new RestTemplate();
}
}
两者方法都可使用,前者提供了多样的自定义参数的选择,可以将RestTemplate
配置的更为完善,后者则简化了配置虽然配置多样性不如前者,但是日常使用调用些API
还是足以使用
RestTemplate API
使用 在使用RestTemplate
前先让我们看看RestTemplate
有哪些API
相信大家看到这么多方法,一定很头大,但是我们仔细看上述的方法,我们可以提取出主要的几种方法是(这里只讨论Http请求的):
GET
POST
PUT
DELETE
HEAD
OPTIONS
EXCHANGE
EXECUTE
这里我给大家安利一个一个网站,它提供免费的RESTFul api的样例测试。httpbin A simple HTTP Request & Response Service.
通过上图我们可以发现RestTemlate
发送GET
请求的方法有两种
public
T getForObject(...) public
ResponseEntity getForEntity(...)
getForEntity()
后缀带有Entity
的方法都代表返回一个ResponseEntity
,ResponseEntity
是Spring对HTTP
请求响应的封装,包括了几个重要的元素,如响应码,contentType、contentLength
、响应消息体等
通过它继承父类(HttpEntity
)的getHeader()
方法我们可以获取contentType、contentLength
、响应消息体等。比如下面这个例子。
public void queryWeather() {ResponseEntity
该例子中getForEntity()
方法的第一个参数为我要调用服务的URL
,第二个参数则为响应内容的类的类型(Java嘛 万物皆对象)还可以添加第三个参数,第三个参数为一个可变参数 代表着调用服务时的传参。
第三个参数可以使用key-value的map来传入参数
get请求也可通过向在url上添加查询参数来发送带有请求的参数
getForObject()
相比于前者getForEntity()
该方法则是,更偏向于直接获取响应内容的,因为他直接返回响应实体的body
(响应内容),。比如下面这个例子
public void queryWeather() {
Object body = restTemplate.getForObject("https://restapi.amap.com/v3/weather/weatherInfo?city=510100&key=e7a5fa943f706602033b6b329c49fbc6", Object.class);
System.out.println(body);
}
方法参数签名与`getForEntity()`基本一致。
当你只需要返回的响应内容时,使用getForObject()
是一个很好的选择,但当你需要获得更详细的响应信息,如响应头中的信息,你就只能选择getForEntity()
了。
POST
请求有如下三种方法
public URI postForLocation(...)
public
T postForObject(...) public
ResponseEntity postForEntity(...)
后两种用法与GET
基本一致不做详细介绍,这里着重介绍postForLocation()
postForEntity()
该方法有三个参数,第一个为调用服务的地址(URL)
第二个参数表示上传的参数(json格式提交)
第三个表示返回响应内容的具体类型
第四个参数也用于指定参数(在URL中添加)
@Override
public void queryWeather() {User user = new User();
user.setName("鲁大师");
ResponseEntity
postForObject()
使用方法与getForObject
类似只是多了一个传入对象参数(传入方式与postForEntity()
相同)
public void queryWeather() {User user = new User();
user.setName("鲁大师");
ResponseEntity
postForLocation()
postForLocation
传参用法与前两者一致,只不过返回从实体变成了一个URL
,因此它不需要指定返回响应内容的类型。
public void queryWeather() {User user = new User();
user.setName("鲁大师");
URI uri = restTemplate.postForLocation("https://httpbin.org/post", user);
System.out.println(uri);
}
这个只需要服务提供者返回一个 URI 即可,该URI
返回值体现的是:用于提交完成数据之后的页面跳转,或数据提交完成之后的下一步数据操作URI
。
这里我们着重说一下,如何自己封装一个请求体。
我们需要用到如下几个类
HttpHeaders
MultiValueMap
HttpEntity
HttpHeaders
故名思意,就是用来封装Http请求的请求头的,这里我们要设置他的ContentType
为**MediaType.APPLICATION_FORM_URLENCODED
**以使得我们提交的参数是以Form(表单)的形式提交。
//设置请求头, x-www-form-urlencoded格式的数据
HttpHeaders httpHeaders = new HttpHeaders();
//这里指定参数以UTF-8编码格式传输
MediaType mediaType = new MediaType(MediaType.APPLICATION_FORM_URLENCODED, UTF_8);
httpHeaders.setContentType(mediaType);
//提交参数设置
MultiValueMapmap = new LinkedMultiValueMap<>();
map.add("name","鲁大师");
MultiValueMap
该类是用来封装请求参数的,是以key-value
的形式封装但是以单个key对应多个value的格式传输(也就是是以单个key:[value...]
的格式传输的)。
//提交参数设置
MultiValueMapmap = new LinkedMultiValueMap<>();
map.add("name","鲁大师");
如果像传输单个key
对应单个value
使用普通的Map
传参即可
HttpEntity
该类是用来封装请求的,主要作用就是将请求头和请求体封装在一起成为一个请求实体 T用来指定用来封装参数的容器的类型。
//组装请求体
HttpEntity>request = new HttpEntity<>(map, httpHeaders);
通过上述介绍后,我们就可以自己封装一个以form形式提交参数的POST
请求了。
@Test
void contextLoads() {//请求地址
String url = "https://httpbin.org/post";
//设置请求头, x-www-form-urlencoded格式的数据
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
//提交参数设置
MultiValueMapmap = new LinkedMultiValueMap<>();
map.add("name","鲁大师");
//组装请求体
HttpEntity>request = new HttpEntity<>(map, httpHeaders);
//发送post请求并打印结果 以String类型接收响应结果JSON字符串
String s = restTemplate.postForObject(url, request, String.class);
System.out.println(s);
}
通过拦截器拦截了请求并对请求头进行拆包,可以发现ContentType
已经被修改成了x-www-form-urlencoded
格式了。
PUT
请求的方法只有一类
void put()
PUT()
使用方法与postForEntity()
参数基本一致,只是put
方法没有返回值(也就不必去设置响应内容的类型了)。
@Test
void contextLoads() {//请求地址
String url = "http://httpbin.org/put";
User user = new User();
user.setName("鲁大师");
restTemplate.put(url,user);
}
与PUT
一样,DELETE
方法只有一类
void delete()
delete()
delete()
可以指定url
中的中的参数,但是RestTemplate
的delete()
方法是不支持上传requestBody
的。
void contextLoads() {//请求地址
String url = "http://httpbin.org/delete";
restTemplate.delete(url);
}
HEADER
也只有一类方法
public HttpHeaders headForHeaders()
主要用来发送请求获取响应头部信息,但是像DELETE
、PUT
这类没有响应的方法,是不能使用该方法的(因为没有响应也就没有响应头了)。
@Test
void contextLoads() {//请求地址
String url = "http://httpbin.org/get";
HttpHeaders httpHeaders = restTemplate.headForHeaders(url);
System.out.println(httpHeaders);
}
public Set
optionsForAllow()
该方法的主要用来判断该服务地址,能够使用那种方法去执行
@Test
void contextLoads() {//请求地址
String url = "http://httpbin.org/get";
SethttpMethods = restTemplate.optionsForAllow(url);
System.out.println(httpMethods);
}
ResponseEntity exchange()
该接口与其他接口不同
- 该方法允许用户指定请求的方法(
get,post,put
等)- 可以在请求中增加body以及头信息,其内容通过参数
HttpEntity>requestEntity
描述exchange
支持’含参数的类型(即泛型)'作为返回类型,该特性通过ParameterizedTypeReferenceresponseType
描述
该方法支持五个参数
- 第一个是服务地址
- 第二个是请求方法
- 第三个是写入的请求实体
- 第四个是响应内容的类型
- 第五个是扩展模板的变量或包含
URI
模板变量的映射
@Test
void contextLoads() {//请求地址
String url = "http://httpbin.org/post";
User user = new User();
user.setName("彭于晏");
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntityuserHttpEntity = new HttpEntity<>(user, httpHeaders);
ResponseEntity
上述代码模拟了一个简单的POST
请求 可以理解为可以动态的指定请求方法和请求实体的一个方法。
响应实体
T execute()
该方法就是执行请求的方法,我们可以发现上述的所有方法的最后执行都是调用的该方法执行,所以他在RestTemplate
中十分重要
该方法有五个参数
- 服务地址
- 请求的方法
- 准备请求的对象(
requestCallback
)- 从响应中提取返回值的对象
- 扩展模板的变量或包含
URI
模板变量的映射
execute()
@Override
@Nullable
publicT execute(String url, HttpMethod method, @Nullable RequestCallback requestCallback,
@Nullable ResponseExtractorresponseExtractor, Object... uriVariables) throws RestClientException {URI expanded = getUriTemplateHandler().expand(url, uriVariables);
return doExecute(expanded, method, requestCallback, responseExtractor);
}
通过上述源码我们可以发现execute()
方法只是将我们传入的String
类型的URL
转换为了URL
类型,最后执行请求是由doExecute()
方法
doExecute()
这里需要了解两个类:RequestCallback
和ResPonseExtractor
RequestCallback
: 用于操作请求头和body,在请求发出前执行。不需要关心关闭请求或处理错误:这都将由RestTemplate处理。
该接口有两个实现类:
ResPonseExtractor
: 解析HTTP响应的数据,而且不需要担心异常和资源的关闭。
该接口在RestTemplate
中同样有两个实现类:
HeadersExtractor | 提取响应HttpHeaders 的响应提取器。直接提取响应体中的响应头 | |
---|---|---|
ResponseEntityResponseExtractor | HttpEntity 的响应提取器。可以获取响应实体里面包括响应头,响应体等。具体请查看HttpEntity |
@Test
void contextLoads() {//请求地址
String url = "http://httpbin.org/post";
User user = new User();
user.setName("彭于晏");
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntityuserHttpEntity = new HttpEntity<>(user, httpHeaders);
ResponseEntity
URI
模板变量的映射我们来简单看一下这个参数,我们知道请求传参可以通过url
拼接参数的方式传参,拼接参数也分为两种:
- 路径中嵌入占位的格式(
http://httpbin.org/{1}/post
)也叫模板映射- 末尾添加
Key-value
格式(http://httpbin.org/post?name="彭于晏"
)即扩展模板的变量
key-value
的格式拼接在URL
后(通俗的说就是这样设置的变量会跟着URL
路径后面)http://httpbin.org/post?name="彭于晏"
@Test
void contextLoads() {//请求地址
String url = "http://httpbin.org/get";
HashMapmap = new HashMap<>();
map.put("name","彭于晏");
Object forObject = restTemplate.getForObject(url, Object.class, map);
System.out.println(forObject);
}
@Test
void contextLoads() {//请求地址
String url = "http://httpbin.org/{2}/get";
HashMapmap = new HashMap<>();
Object forObject = restTemplate.getForObject(url, Object.class, 99);
System.out.println(forObject);
}
spring cloud 做微服务时关于RestTemplate中的各种请求方法的使用总结_DWT_CCFK的博客-博客
RestTemplate 详解 - 知乎 (zhihu.com)
RestTemplate使用教程 - 简书 (jianshu.com)
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧