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.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='SpringMVC系列'}]