RestTemplate 用法学习

本文介绍了Spring Cloud中的RestTemplate,详细讲解了GET和POST请求的多种使用方法,包括getForEntity、getForObject、postForEntity、postForObject和postForLocation,以及它们之间的区别和应用场景。

1、RestTemplate 简介

RestTemplate 是从 Spring3.0 开始支持的一个 HTTP 请求工具,它提供了常见的REST请求方案的模版,例如 GET 请求、POST 请求、PUT 请求、DELETE 请求以及一些通用的请求执行方法 exchange 以及 execute。RestTemplate 继承自 InterceptingHttpAccessor 并且实现了 RestOperations 接口,其中 RestOperations 接口定义了基本的 RESTful 操作,这些操作在 RestTemplate 中都得到了实现。接下来我们就来看看这些操作方法的使用。

GET 请求

getForEntity 和 getForObject

1、getForEntity

getForEntity 来发送 HTTP 请求,此时返回的对象是一个 ResponseEntity 的实例。这个实例中包含了响应数据以及响应头。

@RestController
public class UseHelloController {
    @Autowired
    DiscoveryClient discoveryClient;
    @Autowired
    RestTemplate restTemplate;

    @GetMapping("/hello")
    public String hello(String name) {
        List<ServiceInstance> list = discoveryClient.getInstances("provider");
        ServiceInstance instance = list.get(0);
        String host = instance.getHost();
        int port = instance.getPort();
        String url = "http://" + host + ":" + port + "/hello?name={1}";
        ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class, name);
        StringBuffer sb = new StringBuffer();
        HttpStatus statusCode = responseEntity.getStatusCode();
        String body = responseEntity.getBody();
        sb.append("statusCode:")
                .append(statusCode)
                .append("</br>")
                .append("body:")
                .append(body)
                .append("</br>");
        HttpHeaders headers = responseEntity.getHeaders();
        Set<String> keySet = headers.keySet();
        for (String s : keySet) {
            sb.append(s)
                    .append(":")
                    .append(headers.get(s))
                    .append("</br>");
        }
        return sb.toString();
    }
}

在返回的 ResponseEntity 中,可以获取响应头中的信息,其中 getStatusCode 方法用来获取响应状态码, getBody 方法用来获取响应数据, getHeaders 方法用来获取响应头。

另外两个重载的请求方式

1、使用map来传递参数

Map<String, Object> map = new HashMap<>();
String url = "http://" + host + ":" + port + "/hello?name={name}";
map.put("name", name);
ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class, map);

2、使用uri而非url

String url = "http://" + host + ":" + port + "/hello?name="+ URLEncoder.encode(name,"UTF-8");
URI uri = URI.create(url);
ResponseEntity<String> responseEntity = restTemplate.getForEntity(uri, String.class);

2、getForObject

getForObject 方法和 getForEntity 方法类似,getForObject 方法也有三个重载的方法,参数和 getForEntity 一样。
这里主要说下 getForObject 和 getForEntity 的差异,这两个的差异主要体现在返回值的差异上, getForObject 的返回值就是服务提供者返回的数据,使用 getForObject 无法获取到响应头。

String url = "http://" + host + ":" + port + "/hello?name=" + URLEncoder.encode(name, "UTF-8");
URI uri = URI.create(url);
String s = restTemplate.getForObject(uri, String.class);

注意,这里返回的 s 就是 provider 的返回值,如果开发者只关心 provider 的返回值,并不关系 HTTP 请求的响应头,那么可以使用该方法。

Post 请求

post 请求的方法类型除了 postForEntity 和 postForObject 之外,还有一个 postForLocation

1、postForEntity

在 POST 请求中,参数的传递可以是 key/value 的形式,也可以是 JSON 数据
postForEntity 方法第一个参数是请求地址第二个参数 map 对象中存放着请求参数 key/value第三个参数则是返回的数据类型。当然这里的第一个参数 url 地址也可以换成一个 Uri 对象,效果是一样的。这种方式传递的参数是以 key/value 形式传递的,在 post 请求中,也可以按照 get 请求的方式去传递 key/value 形式的参数,传递方式和 get 请求的传参方式基本一致,只须传入的参数列表map为null。

@GetMapping("/hello5")
public String hello5(String name) {
    List<ServiceInstance> list = discoveryClient.getInstances("provider");
    ServiceInstance instance = list.get(0);
    String host = instance.getHost();
    int port = instance.getPort();
    String url = "http://" + host + ":" + port + "/hello2";
    MultiValueMap map = new LinkedMultiValueMap();
    map.add("name", name);
    ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, map, String.class);
    return responseEntity.getBody();
}

也可以传入object对象,会被自动转换成json传出,接收的时候又自动转回Object对象

@GetMapping("/hello7")
public User hello7() {
    List<ServiceInstance> list = discoveryClient.getInstances("provider");
    ServiceInstance instance = list.get(0);
    String host = instance.getHost();
    int port = instance.getPort();
    String url = "http://" + host + ":" + port + "/user";
    User u1 = new User();
    ResponseEntity<User> responseEntity = restTemplate.postForEntity(url, u1, User.class);
    return responseEntity.getBody();
}

2、postForObject

postForObject 和 postForEntity 基本一致,就是返回类型不同而已,这里不再赘述

3、postForLocation

postForLocation 方法的返回值是一个 Uri 对象,因为 POST 请求一般用来添加数据,有的时候需要将刚刚添加成功的数据的 URL 返回来,此时就可以使用这个方法,一个常见的使用场景如用户注册功能,用户注册成功之后,可能就自动跳转到登录页面了,此时就可以使用该方法。例如在 provider 中提供一个用户注册接口,再提供一个用户登录接口,如下:

@RequestMapping("/register")
public String register(User user) throws UnsupportedEncodingException {
    return "redirect:/loginPage?username=" + URLEncoder.encode(user.getUsername(),"UTF-8") + "&address=" + URLEncoder.encode(user.getAddress(),"UTF-8");
}
@GetMapping("/loginPage")
@ResponseBody
public String loginPage(User user) {
    return "loginPage:" + user.getUsername() + ":" + user.getAddress();
}

这里一个注册接口,一个是登录页面,不过这里的登录页面我就简单用一个字符串代替了。然后在 consumer 中来调用注册接口,如下:

@GetMapping("/hello8")
public String hello8() {
    List<ServiceInstance> list = discoveryClient.getInstances("provider");
    ServiceInstance instance = list.get(0);
    String host = instance.getHost();
    int port = instance.getPort();
    String url = "http://" + host + ":" + port + "/register";
    MultiValueMap map = new LinkedMultiValueMap();
    map.add("username", "牧码小子");
    map.add("address", "深圳");
    URI uri = restTemplate.postForLocation(url, map);
    String s = restTemplate.getForObject(uri, String.class);
    return s;
}

这里首先调用 postForLocation 获取 Uri 地址,然后再利用 getForObject 请求 Uri。
注意:这个方法返回的其实是head中的Location 字段,所以如果没有Location 字段则会返回null。(因此这个方法只能获取到返回重定向的接口)

学习参考:https://blog.youkuaiyun.com/jinjiniao1/article/details/100849237

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值