文末可以领取所有系列高清 pdf。
大家好,我是路人,这是 SpringMVC 系列第 21 篇。
本文介绍 Spring web 中特别牛逼的一个类 RestTemplate。
目录
-
1、RestTemplate 概述
-
2、案例代码
-
2.1、git 地址
-
2.2、关键代码位置
-
2.3、如何运行测试用例?
-
-
3、发送 Get 请求
-
3.1、普通请求
-
3.2、url 中含有动态参数
-
3.3、接口返回值为泛型
-
3.4、下载小文件
-
3.5、下载大文件
-
3.6、传递头
-
3.7、综合案例:含头、url 动态参数
-
-
4、POST 请求
-
4.1、post 请求常见的 3 种类型
-
4.2、普通表单请求
-
4.3、上传本地文件
-
4.4、通过流或字节数组的方式上传文件
-
4.5、复杂表单:多个普通元素+多文件上传
-
4.6、发送 json 格式数据:传递 java 对象
-
4.7、发送 json 格式数据:传递 java 对象,返回值为泛型
-
4.8、发送 json 字符串格式数据
-
-
5、DELETE、PUT、OPTION 请求
-
5.1、DELETE 请求
-
5.2、PUT 请求
-
5.3、OPTIONS 请求
-
-
6、集成 HttpClient
-
7、集成 okhttp
-
8、总结
-
9、SpringMVC 系列目录
-
10、更多好文章
-
11、【路人甲 Java】所有系列高清 PDF
1、RestTemplate 概述
发送 http 请求,估计很多人用过 httpclient 和 okhttp,确实挺好用的,而 Spring web 中的 RestTemplate 和这俩的功能类似,也是用来发送 http 请求的,不过用法上面比前面的 2 位要容易很多。
spring 框架提供的 RestTemplate 类可用于在应用中调用 rest 服务,它简化了与 http 服务的通信方式,统一了 RESTful 的标准,封装了 http 链接, 我们只需要传入 url 及返回值类型即可。相较于之前常用的 HttpClient,RestTemplate 是一种更优雅的调用 RESTful 服务的方式。
在 Spring 应用程序中访问第三方 REST 服务与使用 Spring RestTemplate 类有关。RestTemplate 类的设计原则与许多其他 Spring 模板类(例如 JdbcTemplate、JmsTemplate)相同,为执行复杂任务提供了一种具有默认行为的简化方法。
RestTemplate 默认依赖 JDK 提供 http 连接的能力(HttpURLConnection),如果有需要的话也可以通过 setRequestFactory 方法替换为例如 Apache HttpComponents、Netty 或 OkHttp 等其它 HTTP library。
考虑到 RestTemplate 类是为调用 REST 服务而设计的,因此它的主要方法与 REST 的基础紧密相连就不足为奇了,后者是 HTTP 协议的方法:HEAD、GET、POST、PUT、DELETE 和 OPTIONS。例如,RestTemplate 类具有 headForHeaders()、getForObject()、postForObject()、put()和 delete()等方法。
下面给大家上案例,案例是重点,通过案例,把我知道的用法都给盘出来。
2、案例代码
2.1、git 地址
https://gitee.com/javacode2018/springmvc-series
2.2、关键代码位置
文中的所有 controller 代码,在RestTemplateTestController
类中。
所有@Test 用例的代码,在RestTemplateTest
。
2.3、如何运行测试用例?
-
拉取项目
-
将 chat16-RestTemplate 模块发布到 tomcat9 中
-
运行 RestTemplateTest 中对应的用例即可
下面咱们来看 RestTemplate 常见的用法汇总。
3、发送 Get 请求
3.1、普通请求
接口代码
@GetMapping("/test/get")
@ResponseBody
public?BookDto?get()?{
????return?new?BookDto(1,?"SpringMVC系列");
}
使用 RestTemplate 调用上面这个接口,通常有 2 种写法,如下
@Test
public?void?test1()?{
????RestTemplate?restTemplate?=?new?RestTemplate();
????String?url?=?"http://localhost:8080/chat16/test/get";
????//getForObject方法,获取响应体,将其转换为第二个参数指定的类型
????BookDto?bookDto?=?restTemplate.getForObject(url,?BookDto.class);
????System.out.println(bookDto);
}
@Test
public?void?test2()?{
????RestTemplate?restTemplate?=?new?RestTemplate();
????String?url?=?"http://localhost:8080/chat16/test/get";
????//getForEntity方法,返回值为ResponseEntity类型
????//?ResponseEntity中包含了响应结果中的所有信息,比如头、状态、body
????ResponseEntity<BookDto>?responseEntity?=?restTemplate.getForEntity(url,?BookDto.class);
????//状态码
????System.out.println(responseEntity.getStatusCode());
????//获取头
????System.out.println("头:"?+?responseEntity.getHeaders());
????//获取body
????BookDto?bookDto?=?responseEntity.getBody();
????System.out.println(bookDto);
}
test1 输出
BookDto{id=1,?name='SpringMVC系列'}
test2 输出
200?OK
头:[Content-Type:"application/json;charset=UTF-8",?Transfer-Encoding:"chunked",?Date:"Sat,?02?Oct?2021?07:05:15?GMT",?Keep-Alive:"timeout=20",?Connection:"keep-alive"]
BookDto{id=1,?name='SpringMVC系列'}
3.2、url 中含有动态参数
接口代码
@GetMapping("/test/get/{id}/{name}")
@ResponseBody
public?BookDto?get(@PathVariable("id")?Integer?id,?@PathVariable("name")?String?name)?{
????return?new?BookDto(id,?name);
}
使用 RestTemplate 调用上面这个接口,通常有 2 种写法,如下
@Test
public?void?test3()?{
????RestTemplate?restTemplate?=?new?RestTemplate();
????//url中有动态参数
????String?url?=?"http://localhost:8080/chat16/test/get/{id}/{name}";
????Map<String,?String>?uriVariables?=?new?HashMap<>();
????uriVariables.put("id",?"1");
????uriVariables.put("name",?"SpringMVC系列");
????//使用getForObject或者getForEntity方法
????BookDto?bookDto?=?restTemplate.getForObject(url,?BookDto.class,?uriVariables);
????System.out.println(bookDto);
}
@Test
public?void?test4()?{
????RestTemplate?restTemplate?=?new?RestTemplate();
????//url中有动态参数
????String?url?=?"http://localhost:8080/chat16/test/get/{id}/{name}";
????Map<String,?String>?uriVariables?=?new?HashMap<>();
????uriVariables.put("id",?"1");
????uriVariables.put("name",?"SpringMVC系列");
????//getForEntity方法
????ResponseEntity<BookDto>?responseEntity?=?restTemplate.getForEntity(url,?BookDto.class,?uriVariables);
????BookDto?bookDto?=?responseEntity.getBody();
????System.out.println(bookDto);
}
test3 输出
BookDto{id=1,?name='SpringMVC系列'}
test4 输出
BookDto{id=1,?name='SpringMVC系列'}
3.3、接口返回值为泛型
接口代码
@GetMapping("/test/getList")
@ResponseBody
public?List<BookDto>?getList()?{
????return?Arrays.asList(
????????????new?BookDto(1,?"Spring高手系列"),
????????????new?BookDto(2,?"SpringMVC系列")
????);
}
当接口的返回值为泛型的时候,这种情况比较特殊,使用 RestTemplate 调用上面这个接口,代码如下,需要用到restTemplate.exchange
的方法,这个方法中有个参数是ParameterizedTypeReference
类型,通过这个参数类指定泛型类型
@Test
public?void?test5()?{
????RestTemplate?restTemplate?=?new?RestTemplate();
????//返回值为泛型
????String?url?=?"http://localhost:8080/chat16/test/getList";
????//若返回结果是泛型类型的,需要使用到exchange方法,
????//这个方法中有个参数是ParameterizedTypeReference类型,通过这个参数类指定泛型类型
????ResponseEntity<List<BookDto>>?responseEntity?=
????????????restTemplate.exchange(url,
????????????????????HttpMethod.GET,
????????????????????null,
????????????????????new?ParameterizedTypeReference<List<BookDto>>()?{
????????????????????});
????List<BookDto>?bookDtoList?=?responseEntity.getBody();
????System.out.println(bookDtoList);
}
输出
[BookDto{id=1,?name='Spring高手系列'},?BookDto{id=2,?name='SpringM