• eureka 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上查看结果

    启动项目(三个服务)

    作者:以罗伊
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文链接,否则保留追究法律责任的权利。
  • 相关阅读:
    清除陷入CLOSE_WAIT的进程
    Eclipse
    远程连接elasticsearch遇到的问题
    Linux环境Nginx安装
    CentOS安装mysql
    py2exe使用方法
    Python3.4如何读写Excel
    getPhysicalNumberOfCells 与 getLastCellNum的区别
    浅析MySQL中exists与in的使用
    【MongoDB for Java】Java操作MongoDB
  • 原文地址:https://www.cnblogs.com/my-ordinary/p/12408805.html
Copyright © 2020-2023  润新知