学习 RestTemplate 一篇文章就够了 !!!

一、RestTemplate

RestTemplate 是从 Spring3.0 开始支持的一个 Http 请求工具,这个请求工具和 Spring Boot 无关,更和 Spring Cloud 无关。

RestTemplate 提供了常见的 REST 请求方法模板,例如 GET、POST、PUT、DELETE 请求以及一些通用的请求执行方法 exchange 和 execute 方法。

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

二、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() {
        //使用 getForObject
        String forObject = restTemplate.getForObject("http://provider/hello2?name={1}",
                String.class, "Yolo");
        System.out.println(forObject);

        //使用 getForEntity,并获得其他属性
        ResponseEntity<String> forEntity = restTemplate.getForEntity("http://provider/hello2?name={1}",
                String.class, "Yolo");
        String body = forEntity.getBody();
        System.out.println(body);
        HttpStatus statusCode = forEntity.getStatusCode();
        System.out.println(statusCode);
        int statusCodeValue = forEntity.getStatusCodeValue();
        System.out.println(statusCodeValue);
        HttpHeaders headers = forEntity.getHeaders();
        System.out.println("*********  header  *********");
        for (String s : headers.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 forObject = restTemplate.getForObject("http://provider/hello2?name={1}", String.class, "Yolo");
        System.out.println(forObject);
        Map<String ,Object> map = new HashMap<>();
        map.put("name","Yolo_map");
        String 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);
        String s = restTemplate.getForObject(uri, String.class);
        System.out.println(s);
    }

在这里插入图片描述

这就是所说的三种传参方式

三、POST 方法

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

注意这里的模块需要创建为普通的 maven 模块,不可以创建为SpringBoot项目:具体原因点击参考

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("/hello7")
    public void hello7() {
        MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
        map.add("username", "yolo");
        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 中调用时会出问题

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

四、PUT 方法

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

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

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

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

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

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

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

五、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("/hello10")
    public void hello10() {
        restTemplate.delete("http://provider/user1?id={1}", 99);
        restTemplate.delete("http://provider/user2/{1}", 99);
    }

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

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南淮北安

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值