手把手讲解Spring中的Http请求神器RestTemplate

2年前 (2022) 程序员胖胖胖虎阿
230 0 0

公众号后台回复 springboot,获取松哥独家 274 页 springboot 免费干货教程。

Java 中关于 Http 请求的工具实际上非常多,自带的 HttpUrlConnection,古老的 HttpClient,后起之秀 OkHttp 等,除了这些之外,还有一个好用的工具--RestTemplate,这是 Spring 中就开始提供的 Http 请求工具,不过很多小伙伴们可能是因为 Spring Cloud 才听说它。今天我们就来聊一聊这个 RestTemplate。

好了,一起来听听这充满魔性的声音(本视频节选自松哥自制的 Spring Cloud 视频教程第 3 章,本集基于最新的 H 版录制



GET 请求用法







POST 请求用法

6.3 视频笔记

RestTemplate 是从 Spring3.0 开始支持的一个 Http 请求工具,这个请求工具和 Spring Boot 无关,更和 Spring Cloud 无关。RestTemplate 提供了常见的 REST 请求方法模板,例如 GET、POST、PUT、DELETE 请求以及一些通用的请求执行方法 exchange 和 execute 方法。

RestTemplate 本身实现了 RestOperations 接口,而在 RestOperations 接口中,定义了常见的 RESTful 操作,这些操作在 RestTemplate 中都得到了很好的实现。

6.3.1 GET

首先我们在 provider 中定义一个 hello2 接口:

@GetMapping("/hello2")
public String hello2(String name) {
return "hello " + name;
}

接下来,我们在 consumer 去访问这个接口,这个接口是一个 GET 请求,所以,访问方式,就是调用 RestTemplate 中的 GET 请求。

可以看到,在 RestTemplate 中,关于 GET 请求,一共有如下两大类方法:

手把手讲解Spring中的Http请求神器RestTemplate

这两大类方法实际上是重载的,唯一不同的,就是返回值类型。

getForObject 返回的是一个对象,这个对象就是服务端返回的具体值。getForEntity 返回的是一个 ResponseEntity,这个ResponseEntity 中除了服务端返回的具体数据外,还保留了 Http 响应头的数据。

@GetMapping("/hello4")
public void hello4() {
String s1 = restTemplate.getForObject("http://provider/hello2?name={1}", String.class, "javaboy");
System.out.println(s1);
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://provider/hello2", String.class, "javaboy");
String body = responseEntity.getBody();
System.out.println("body:"+body);
HttpStatus statusCode = responseEntity.getStatusCode();
System.out.println("HttpStatus:"+statusCode);
int statusCodeValue = responseEntity.getStatusCodeValue();
System.out.println("statusCodeValue:"+statusCodeValue);
HttpHeaders headers = responseEntity.getHeaders();
Set<String> keySet = headers.keySet();
System.out.println("--------------header-----------");
for (String s : keySet) {
System.out.println(s+":"+headers.get(s));
}
}

这里大家可以看到,getForObject 直接拿到了服务的返回值,getForEntity 不仅仅拿到服务的返回值,还拿到 http 响应的状态码。然后,启动 Eureka Server、provider 以及 consumer ,访问 consumer 中的 hello4 接口,既可以看到请求结果。

看清楚两者的区别之后,接下来看下两个各自的重载方法,getForObject 和 getForEntity 分别有三个重载方法,两者的三个重载方法基本都是一致的。所以,这里,我们主要看其中一种。三个重载方法,其实代表了三种不同的传参方式。

@GetMapping("/hello5")
public void hello5() throws UnsupportedEncodingException {
String s1 = restTemplate.getForObject("http://provider/hello2?name={1}", String.class, "javaboy");
System.out.println(s1);
Map<String, Object> map = new HashMap<>();
map.put("name", "zhangsan");
s1 = restTemplate.getForObject("http://provider/hello2?name={name}", String.class, map);
System.out.println(s1);
String url = "http://provider/hello2?name=" + URLEncoder.encode("张三", "UTF-8");
URI uri = URI.create(url);
s1 = restTemplate.getForObject(uri, String.class);
System.out.println(s1);
}

这就是我们说的三种不同的传参方式。

6.3.2 POST

首先在 provider 中提供两个 POST 接口,同时,因为 POST 请求可能需要传递 JSON,所以,这里我们创建一个普通的 Maven 项目作为 commons 模块,然后这个 commons 模块被 provider 和 consumer 共同引用,这样我们就可以方便的传递 JSON 了。

commons 模块创建成功后,首先在 commons 模块中添加 User 对象,然后该模块分别被 provider 和 consumer 引用。

然后,我们在 provider 中,提供和两个 POST 接口:

@PostMapping("/user1")
public User addUser1(User user) {
return user;
}
@PostMapping("/user2")
public User addUser2(@RequestBody User user) {
return user;
}

这里定义了两个 User 添加的方法,两个方法代表了两种不同的传参方式。第一种方法是以 key/value 形式来传参,第二种方法是以 JSON 形式来传参。

定义完成后,接下来,我们在 consumer 中调用这两个 POST 接口。

手把手讲解Spring中的Http请求神器RestTemplate

可以看到,这里的 post 和前面的 get 非常像,只是多出来了三个方法,就是 postForLocation,另外两个 postForObject 和 postForEntiy 和前面 get 基本一致,所以这里我们主要来看 postForObject,看完之后,我们再来看这个额外的 postForLocation。

@GetMapping("/hello6")
public void hello6() {
MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.add("username", "javaboy");
map.add("password", "123");
map.add("id", 99);
User user = restTemplate.postForObject("http://provider/user1", map, User.class);
System.out.println(user);
user.setId(98);
user = restTemplate.postForObject("http://provider/user2", user, User.class);
System.out.println(user);
}

post 参数到底是 key/value 形式还是 json 形式,主要看第二个参数,如果第二个参数是 MultiValueMap ,则参数是以 key/value 形式来传递的,如果是一个普通对象,则参数是以 json 形式来传递的。

最后再看看一下 postForLocation 。有的时候,当我执行完一个 post 请求之后,立马要进行重定向,一个非常常见的场景就是注册,注册是一个 post 请求,注册完成之后,立马重定向到登录页面去登录。对于这种场景,我们就可以使用 postForLocation。

首先我们在 provider 上提供一个用户注册接口:

@Controller
public class RegisterController {
@PostMapping("/register")
public String register(User user) {
return "redirect:http://provider/loginPage?username=" + user.getUsername();
}

@GetMapping("/loginPage")
@ResponseBody
public String loginPage(String username) {
return "loginPage:" + username;
}
}

注意,这里的 post 接口,响应一定是 302,否则 postForLocation 无效。

「注意,重定向的地址,一定要写成绝对路径,不要写相对路径,否则在 consumer 中调用时会出问题」

@GetMapping("/hello7")
public void hello7() {
MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.add("username", "javaboy");
map.add("password", "123");
map.add("id", 99);
URI uri = restTemplate.postForLocation("http://provider/register", map);
String s = restTemplate.getForObject(uri, String.class);
System.out.println(s);
}

这就是 postForLocation ,调用该方法返回的是一个 Uri,这个 Uri 就是重定向的地址(里边也包含了重定向的参数),拿到 Uri 之后,就可以直接发送新的请求了。

6.3.3 PUT

PUT 请求比较简单,重载的方法也比较少。

我们首先在 provider 中提供一个 PUT 接口:

@PutMapping("/user1")
public void updateUser1(User user) {
System.out.println(user);
}
@PutMapping("/user2")
public void updateUser2(@RequestBody User user) {
System.out.println(user);
}

注意,PUT 接口传参其实和 POST 很像,也接受两种类型的参数,key/value 形式以及 JSON 形式。

在 consumer 中,我们来调用该接口:

@GetMapping("/hello8")
public void hello8() {
MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.add("username", "javaboy");
map.add("password", "123");
map.add("id", 99);
restTemplate.put("http://provider/user1", map);
User user = new User();
user.setId(98);
user.setUsername("zhangsan");
user.setPassword("456");
restTemplate.put("http://provider/user1", user);
}

consumer 中的写法基本和 post 类似,也是两种方式,可以传递两种不同类型的参数。

6.3.4 DELETE

DELETE 也比较容易,我们有两种方式来传递参数,key/value 形式或者 PathVariable(参数放在路径中),首先我们在 provider 中定义两个 DELETE 方法:

@DeleteMapping("/user1")
public void deleteUser1(Integer id) {
System.out.println(id);
}
@DeleteMapping("/user2/{id}")
public void deleteUser2(@PathVariable Integer id) {
System.out.println(id);
}

然后在 consumer 中调用这两个删除的接口:

@GetMapping("/hello9")
public void hello9() {
restTemplate.delete("http://provider/user1?id={1}", 99);
restTemplate.delete("http://provider/user2/{1}", 99);
}

delete 中参数的传递,也支持 map,这块实际上和 get 是一样的。

好了,关于这套视频,小伙伴们要是有兴趣,可以看看这篇文章:Spring Boot + Vue 视频教程喜迎大结局,西交大的老师竟然都要来一套!

精彩文章推荐:

GitHub 又掉链子,我给微人事 + Spring Boot + Spring Cloud 案例找了新家


274 页 pdf 文档,Spring Boot 教程也有离线版了

手把手讲解Spring中的Http请求神器RestTemplate


喜欢就点个"在看"呗^_^

本文分享自微信公众号 - 江南一点雨(a_javaboy)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

版权声明:程序员胖胖胖虎阿 发表于 2022年9月21日 下午11:40。
转载请注明:手把手讲解Spring中的Http请求神器RestTemplate | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...