Spring-RestTemplate
前言
Java中常用的Http工具:HttpURLConnection(java.net)、HttpClients(Apache)、OkHttp(安卓常用)、RestTemplate(Spring Web中集成)
使用SpringBoot开发web应用,一般使用RestTemplate,不需要额外引入三方依赖,并且使用方便
Spring Boot Web项目一般需要引用spring boot starter web依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring.boot.version}</version>
</dependency>
其依赖结构图如下,RestTemplate在spring web的jar包中

RestTemplate是按照Rest规范发送Http请求的一个工具类,所以工具类中需要制定接口类型:Get、Post等
常用方法
Get请求
例如发送Get请求,可以使用getForEntity、exchange,getForEntity只能发送Get请求,exchange可以设置请求类型:例如Get、Post等
其中getForEntity包含六种方法

按照接口返回类型:分为两种,一种是返回默认对象ResponseEntity<T>,其中T是接口的具体返回内容;另外一种是自定义的返回类型;一般我们不需要自定义返回类型,所以这里选择前三种方法即可
前三中方法按照接口url类型可以分为两类,一种是字符串类型;另一种是通过URI(java.net)对象构造请求地址;一般使用字符串类型即可
使用字符串url的方法有两个:一种是使用数组类型的参数,数组参数顺序和url中数字序号一致;另外一种是使用Map类型的参数,按照Map中key匹配url中参数名称;具体使用如下
public class NormalTest {
@Test
public void printId() {
RestTemplate restTemplate = new RestTemplate();
// url中使用{1}数字作为占位符,数字序号对应数组参数中的顺序
String url = "https://8def7b1e-e53c-41d5-9a62-6189850f699c.mock.pstmn.io/basicInfo/get?name={1}";
ResponseEntity<JSONObject> hulei = restTemplate.getForEntity(url, JSONObject.class, "zhangsan");
System.out.println(Optional.ofNullable(hulei.getBody()).map(JSONAware::toJSONString).orElse("null"));
// url中使用{key}作为占位符,key即Map中key
String url1 = "https://8def7b1e-e53c-41d5-9a62-6189850f699c.mock.pstmn.io/basicInfo/get?name={name}";
Map<String, Object> map = new HashMap<>();
map.put("name", "zhangsan");
ResponseEntity<JSONObject> hulei1 = restTemplate.getForEntity(url1, JSONObject.class, map);
System.out.println(Optional.ofNullable(hulei1.getBody()).map(JSONAware::toJSONString).orElse("null"));
}
}
如果需要携带特殊的请求头,则需要使用exchange方法
exchange方法的六个重载方法如下,这里我们关注前两个方法

下面以第一个方法为例发送get请求,具体如下,请求中可以指定请求头以及请求体参数
@Test
public void testRest(){
RestTemplate restTemplate = new RestTemplate();
// 设置请求头,请求头标准字段可以使用setXxx字段设置,自定义请求头可以指定请求头Key字段名称
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
httpHeaders.set("Authorization", "xxx");
httpHeaders.put(HttpHeaders.COOKIE, new ArrayList<>());
// 设置请求体,get请求不可以设置请求体,post请求则可以设置请求体
HashMap<String, String> map = new HashMap<>();
map.put("name", "zhangsan");
HttpEntity<Map<String, String>> httpEntity = new HttpEntity<>(map, httpHeaders);
String url1 = "https://8def7b1e-e53c-41d5-9a62-6189850f699c.mock.pstmn.io/basicInfo/get?name={0}";
// 请求地址,请求方式,请求实体(请求头+请求体参数),响应接受类型,url参数(如果url中存在占位符)
ResponseEntity<JSONObject> zhangsan = restTemplate.exchange(url1, HttpMethod.GET, httpEntity, JSONObject.class, "zhangsan");
System.out.println(Optional.ofNullable(zhangsan.getBody()).map(JSONAware::toJSONString).orElse("null"));
}
扩展
并发安全
一般而言,RestTtemplate通过new生成新的对象,生成的实例中存在默认的配置:例如超时响应时间设置等。
对于同一项目中,对于超时响应时间这种基础配置一般有固定值,并且每个项目有自己的固定值;因此一般需要配置一个RestTemplate的Bean,并进行基础参数的配置。如下
@Configuration
public class RestConfig {
@Bean
public RestTemplate restTemplate(){
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
// 设置超时时间
requestFactory.setConnectTimeout(30 * 1000);
requestFactory.setReadTimeout(30 * 1000);
return new RestTemplateBuilder()
.requestFactory(() -> requestFactory)
.build();
}
}
对于上述注入Spring的单实例RestTemplate,如果配置中都是公共的参数配置,则不存在并发的问题;
当一个特定的http请求需要设置连接超时时间5s,则不能使用上述注入的实例,否则在使用过程中如果修改了超时配置,则会影响系统中所有使用此RestTempalte实例的请求
代理
RestTemplate工具也支持代理配置,具体配置参考博主另一篇笔记。
URI简述
URI: schema://schema specific part, 模式:模式明细
模式即协议,例如:http、https、file、ftp、magnet等
模式明细包含://authority/path?query, authority = ip:port
java.net中可以将字符串url解析为URI对象
@Test
@SneakyThrows
public void testURI(){
// schema://userinfo@authority[host:port]/path?query#fragment
// 模式://用户信息[账号:密码]@授权主机[ip:port]/路径?路径参数#片段[网页的一部分]
URI resolve = URI.create("https://zhangsan:admin123@8def7b1e-e53c-41d5-9a62-6189850f699c.mock.pstmn.io:80/basicInfo/get?name=zhangsan#home");
System.out.println("");
}
解析出来的URI对象各字段如下

java.net.URI中的构造方法,其中ssp为schema specific part, 其余参数含义参考以上描述


浙公网安备 33010602011771号