springcloud RestTemplate操作 笔记

0 环境

  • 系统环境: win10
  • 编辑器: IDEA

1 简介

RestTemplate

  • spring3.0开始支持
  • Http请求工具
  • 该工具与springboot或springcloud无关
  • 提供常见的REST请求模版
    • 例如支持GET、PUT、POST、DELETE
    • 通用请求方法 --> exchange和execute
  • 实现RestOperations接口
    • 该接口定义了常见的RESTful操作

2 GET操作

2.1 GET相关的2种方法介绍(重载)

 @Nullable
    <T> T getForObject(String var1, Class<T> var2, Object... var3) throws RestClientException;

    @Nullable
    <T> T getForObject(String var1, Class<T> var2, Map<String, ?> var3) throws RestClientException;

    @Nullable
    <T> T getForObject(URI var1, Class<T> var2) throws RestClientException;

    <T> ResponseEntity<T> getForEntity(String var1, Class<T> var2, Object... var3) throws RestClientException;

    <T> ResponseEntity<T> getForEntity(String var1, Class<T> var2, Map<String, ?> var3) throws RestClientException;

    <T> ResponseEntity<T> getForEntity(URI var1, Class<T> var2) throws RestClientException;
    public class ResponseEntity<T> extends HttpEntity<T>{xxxx} 
    // 属性 比如x
    public static final HttpEntity<?> EMPTY = new HttpEntity();
    private final HttpHeaders headers;
    @Nullable
    private final T body;
    private final Object status;
    
    // 用到的方法 比如
    public HttpStatus getStatusCode() {
        return this.status instanceof HttpStatus ? (HttpStatus)this.status : HttpStatus.valueOf((Integer)this.status);
    }

    public int getStatusCodeValue() {
        return this.status instanceof HttpStatus ? ((HttpStatus)this.status).value() : (Integer)this.status;
    }

这2种方法的返回值

  • getForObject返回一个对象(服务返回的具体值)
  • getForEntity不仅返回具体数据 还可以返回状态码 头信息…

2.2 首先在provider中定一个hello1接口

    /**
    * @Description: consumer访问该接口 调用RestTemplate的get请求
    * @Param: [name]
    * @return: java.lang.String
    * @Author: 水面行走
    * @Date: 2020/3/4
    */
    @GetMapping("/hello1")
    public String hello1(String name){
        return "hello provider: " + name;
    }

2.3 2种方法返回值验证

 /** 
    * @Description: 对比2种方法的不同与相同
    * @Param:  
    * @return:  
    * @Author: xxxx
    * @Date: 2020/xx/xx
    */
    @GetMapping("/useHello5")
    public void userHello5(){
        // 获取服务返回值
        String fish = restTemplateOne.getForObject("http://provider/hello1?name={1}", String.class, "love fish");
        System.out.println("getForObject --> " + fish);

        // 获取服务返回值 http响应码 头信息...
        ResponseEntity<String> milk = restTemplateOne.getForEntity("http://provider/hello1?name={1}", String.class, "milk");
        String body = milk.getBody();
        System.out.println("body --> " + body);

        HttpStatus statusCode = milk.getStatusCode();
        System.out.println("HttpStatus --> " + statusCode);

        int statusCodeValue = milk.getStatusCodeValue();
        System.out.println("getStatusCodeValue --> " + statusCodeValue);

        System.err.println("----------------------遍历heards----------------------");
        // 需要遍历
        HttpHeaders headers = milk.getHeaders();
        Set<String> strings = headers.keySet();
        for (String s : strings) {
            System.out.println(s + " => " + headers.get(s));
        }

    }

启动Eureka server provider consumer 访问consumer useHello5接口

2.4 getForObject三种重载方法

getForObject和getForEntity分别有三个重载方法(传参方式)且很类似 那么只展示一个方法即可

/** 
    * @Description:
         *     @Nullable
         *     <T> T getForObject(String var1, Class<T> var2, Object... var3) throws RestClientException;
         *
         *     @Nullable
         *     <T> T getForObject(String var1, Class<T> var2, Map<String, ?> var3) throws RestClientException;
         *
         *     @Nullable
         *     <T> T getForObject(URI var1, Class<T> var2) throws RestClientException;
         *     -------------------------------------------------------------------------------------------------------------------------------
         *     <T> ResponseEntity<T> getForEntity(String var1, Class<T> var2, Object... var3) throws RestClientException;
         *
         *     <T> ResponseEntity<T> getForEntity(String var1, Class<T> var2, Map<String, ?> var3) throws RestClientException;
         *
         *     <T> ResponseEntity<T> getForEntity(URI var1, Class<T> var2) throws RestClientException;
    * @Param:  
    * @return:  
    * @Author: xxxx
    * @Date: 2020/xx/xx
    */
    @GetMapping("/useHello6")
    public void userHello6() throws UnsupportedEncodingException {
        // getForObject与getForEntity类似(不是为了偷懒)
        // Object... var3
        System.out.println(" <---- Object... -----> ");
        String fish = restTemplateOne.getForObject("http://provider/hello1?name={1}", String.class, "love fish");
        System.out.println("fish --> " + fish);

        // Map<String, ?> var3
        System.out.println(" <---- Map<String, ?> -----> ");
        HashMap<String, Object> map = new HashMap<>();
        map.put("name", "lusi");
        String object = restTemplateOne.getForObject("http://provider/hello1?name={name}", String.class, map);
        System.out.println("map: " + object);

        // URI var1
        System.out.println(" <---- URI -----> ");
        // 汉字需要转码
        String encode = "李思思";
        String url = "http://provider/hello1?name=" + URLEncoder.encode(encode, "UTF-8");

        // string转化为URI
        URI uri = URI.create(url);

        // 装载
        String forUri = restTemplateOne.getForObject(uri, String.class);
        System.err.println("url --> " + forUri);

    }

启动三个服务

2.5 小结

  1. getForObject和getForEntity返回值区别
    • getForObject返回一个对象(服务返回的具体值)
    • getForEntity不仅返回具体数据 还可以返回状态码 头信息…
  2. getForObject和getForEntity 三种重载方式的类似
    • Object… --> 占位符 (?xxx={1}, xx.class, “xxxxx”)
    • Map<String, ?> --> 占位符为自定义key(name)需要提前声明map (?xxx={key}, xx.class, 返回的map)
    • URI --> 字符串中包含中文的需要转码才能创建为URI 在被调用

3 POST操作

3.1 准备

  • 因为post请求可能是k:v或是json形式 需要提供2种接口 传参对象 需要创建一个model 为了以后方便使用 直接新建一个普通的maven项目作为commons模块 管理
  • 步骤

1.创建maven项目作为commons项目 添加依赖 也可以不添加直接get set 随意

<dependencies>
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

2.创建一个User类

@Data
@ToString
public class User {
    private Integer id;
    private String name;
    private String nickName;
}

3.provider和consumer引用commons模块

<dependency>
  <groupId>xxx你定义的gruopIdxxx</groupId>
  <artifactId>commons</artifactId>
  <version>1.0-SNAPSHOT</version>
</dependency>

3.2 provider提供接口

  • 不仅要提供2个post接口 因为还有一个postForLocation方法 需要添加类 2个接口 一个重定向和一个重定向的地址
// 在provider 提供2个post接口

    /**
    * @Description: key:value形式传参
    * @Param: [user]
    * @return: model.User
    * @Author: 
    * @Date: 2020/xx/xx
    */
    @PostMapping("/user")
    public User addUser(User user){
        return user;
    }

    /**
     * @Description: json形式传参
     * @Param: [user]
     * @return: model.User
     * @Author: 
     * @Date: 2020/xx/xx
     */
    @PostMapping("/user1")
    public User addUser1(@RequestBody User user){
        return user;
    }
  • 新建一个类存在重定向
// 为了重定向
@Controller
public class RegisterController {

    /**
    * @Description: 该post接口重定向到login页面 是为了体验postForLocation方法 所以响应一定是302 否则无效
    * @Param: [user]
    * @return: java.lang.String
    * @Author: 
    * @Date: 2020/xx/xx
    */
    @PostMapping("/register")
    public String register(User user) throws UnsupportedEncodingException {
        // 一定是绝对路径 否则consumer中会报错
        // 因为是重定向 若传参为中文 需要转换为utf-8
        return "redirect:http://provider/login?name=" + URLEncoder.encode(user.getName(), "UTF-8");
    }

    @GetMapping("/login")
    @ResponseBody
    public String login(String name){
        return "login: " + name;
    }
}    

4 consumer的使用

由于postForObject和ResponseEntity类似 写一种即可

4.1 postForObject的使用

/**
    * @Description: 测试postForObject方法 k/v还是json形式 -> 取决于看postForObject第二个参数
    * @Param:
    * @return:
    * @Author: 水面行走
    * @Date: 2020/xx/xx
    */
    @GetMapping("/useHello7")
    public void userHello7(){
        MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
        map.add("id", 77);
        map.add("name", "小明");
        map.add("nickName", "笑嘻嘻");

        // k/v形式
        User user = restTemplateOne.postForObject("http://provider/user", map, User.class);
        System.out.println(user);
        user.setId(45);
        // 普通object对象 --> json形式
        User user1 = restTemplateOne.postForObject("http://provider/user1", user, User.class);
        System.err.println(user1);
    }

4.2 postForLocation的使用

当我执行post请求完后 立马重定向(例如注册 注册完成后 立马重定向到登陆页面 postForLocation该上场了)

/**
    * @Description: 测试postForLocation register接口 k/v传参
    * @Param:
    * @return:
    * @Author: 水面行走
    * @Date: 2020/xx/xx
    */
    @GetMapping("/useHello8")
    public void userHello8(){
        MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
        map.add("id", 77);
        map.add("name", "小明的");
        map.add("nickName", "笑哈哈");

        // 返回uri -> 重定向的地址和参数
        URI uri = restTemplateOne.postForLocation("http://provider/register", map);
        System.out.println("uri:" + uri);
        String s = restTemplateOne.getForObject(uri, String.class);
        System.out.println("打印:" + s);

    }

postForLocation调用返回uri->重定向的地址(例如http://provider/login?name=%E5%B0%8F%E6%98%8E%E7%9A%84) 拿到uri后 获取uri 发送uri请求获取值(例如 打印:login: 小明的)

4.3 小结

  • 2种传参方式 处理方式注意一下 使用postForObject 将值传给它的第二个参数上
    • k/v形式 需要new LinkedMultiValueMap add值
    • json形式 无需添加map进行处理 直接普通的对象即可 但是我们该url时 别忘了添加@RequestBody
  • post接口 响应码必须得302 不然postForLocation无效 重定向地址一定是绝对路径 相对路径 consumer调用就凉了

5 PUT操作

PUT重载方法少

5.1 provider提供接口

 /** 
    * @Description: k/v形式 因为是更新操作 put方法返回为void 所以返回值为void就行 有返回值不会报错(put和post传参很像)
    * @Param:  
    * @return:  
    * @Author: 水面行走
    * @Date: 2020/xx/xx
    */
    @PutMapping("/user")
    public void updateUser(User user){
        System.out.println("k/v形式:" + user);
    }

    /**
     * @Description: json形式 别忘了传参添加注解 因为是更新操作 put方法返回为void 所以返回值为void就行 有返回值不会报错
     * @Param:
     * @return:
     * @Author: 水面行走
     * @Date: 2020/xx/xx
     */
    @PutMapping("/user1")
    public void updateUser1(@RequestBody User user){
        System.out.println("json形式:" + user);
    }

5.2 consumer消费接口

/** 
    * @Description: 2种形式 put调用的方式 
    * @Param:  
    * @return:  
    * @Author: 水面行走
    * @Date: 2020/xx/xx
    */
    @GetMapping("/useHello9")
    public void userHello9(){
        MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
        map.add("id", 38);
        map.add("name", "不过烦恼");
        map.add("nickName", "笑哈哈");
        // k/v形式
        restTemplateOne.put("http://provider/user", map);

        User user = new User();
        user.setId(1);
        user.setName("小米是地方");
        user.setNickName("母老虎");
        restTemplateOne.put("http://provider/user1", user);
    }

5.3 在provider查看显示结果

启动项目(三个)

6 Delete操作

介绍2种传参方式 k/v形式(xx?id=xxx) PathVariable(参数放在路径中 xx/1)

6.1 provider提供接口

/**
    * @Description: k/v形式的删除 xxx?id=1
    * @Param:
    * @return:
    * @Author: 水面行走
    * @Date: 2020/xx/xx
    */
    @DeleteMapping("/user")
    public void delUser(Integer id){
        System.out.println("k/v形式:" + id);
    }

    /**
     * @Description: PathVariable(参数放在路径中 xxx/1)形式的删除
     * @Param:
     * @return:
     * @Author: 水面行走
     * @Date: 2020/xx/xx
     */
    @DeleteMapping("/user1/{id}")
    public void delUser1(@PathVariable Integer id){
        System.out.println("json形式:" + id);
    }

6.2 consumer消费接口

/** 
    * @Description:
     *     public void delete(String url, Object... uriVariables) throws RestClientException {
     *       this.execute(url, HttpMethod.DELETE, (RequestCallback)null, (ResponseExtractor)null, (Object[])uriVariables);
     *     }
     *     // 删除支持map和get类似 自己测试
     *     public void delete(String url, Map<String, ?> uriVariables) throws RestClientException {
     *         this.execute(url, HttpMethod.DELETE, (RequestCallback)null, (ResponseExtractor)null, (Map)uriVariables);
     *     }
     *
     *     public void delete(URI url) throws RestClientException {
     *         this.execute(url, HttpMethod.DELETE, (RequestCallback)null, (ResponseExtractor)null);
     *     }
    * @Param:  
    * @return:  
    * @Author: 水面行走
    * @Date: 2020/xx/xx
    */
    @GetMapping("/useHello10")
    public void useHello10(){
        // k/v --> id={1} 或是map形式 id={id},可参考getForObject中的map方式
        restTemplateOne.delete("http://provider/user?id={1}", 99);
        // PathVariable
        restTemplateOne.delete("http://provider/user1/{1}", 99);
    }

6.3 在provider上查看结果

启动项目(三个服务)

发布了76 篇原创文章 · 获赞 41 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/edtwar/article/details/104651287
今日推荐