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上查看結果

啟動項目(三個服務)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM