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

公众号后台回复 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 请求,一共有如下两大类方法:

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

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 接口。

可以看到,这里的 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 视频教程喜迎大结局,西交大的老师竟然都要来一套!

1. 全栈架构之打包推荐【建议收藏,常读】

2. 探讨确保消息消费幂等性的几种方式

3. 分布式系统中Session共享的常用方案

4Java语言“坑爹”排行榜TOP 10

5. 我是一个Java类(附带精彩吐槽)

6. mysql索引失效,差点我的工作凉了

7. 既生synchronized,何生volatile?

8. 微服务一直火,为什么服务化要搞懂?

9. MySQL的COUNT语句,不简单!

10. 漫画:HashSet和TreeSet实现与原理

扫码二维码关注我

·end·

—如果本文有帮助,请分享到朋友圈吧—

我们一起愉快的玩耍!

你点的每个赞,我都认真当成了喜欢

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值