消費REST服務,即調用API

Spring 應用 可以 採用 多種 方式 來 消費 REST API, 包括 以下 三種 方式:

RestTemplate: Spring 核心 框架 提供 的 簡單、 同步 REST 客戶 端。

Traverson: Spring HATEOAS 提供 的 支持 超 鏈接、 同步的 REST 客戶 端, 其 靈感 來源於 同名 的 JavaScript 庫。

WebClient: Spring 5 所 引入 的反應式、 異步 REST 客戶 端。

RestTemplate的使用:

要 使用 RestTemplate, 你 可以 在 需要 的 地方 創建 一個 實例:

RestTemplate rest = new RestTemplate();

也可以 將其 聲明 爲 一個 bean 並 注入 到 需要 的 地方:

@Bean
public RestTemplate restTemplate() {
return new RestTemplate(); 
}
package tacos.web.api;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
import tacos.Ingredient;

import java.net.URI;
import java.util.HashMap;
import java.util.Map;

/*
*消費REST服務的API
 */
@RestController
@RequestMapping(path = "/rest",produces = "application/json")
@CrossOrigin(origins = "*")
@Slf4j
public class RestTemplateController {

    private RestTemplate rest=new RestTemplate();
    //以下是RestTemplate的get的三種調用方法:
    //1.接收一個String類型的URL並使用可變列表來指定 URL 變量。
    @GetMapping("/{id}")
    public Ingredient getIngredientById(@PathVariable String id){
        return rest.getForObject("http://localhost:8080/ingredient/{id}",Ingredient.class,id);
    }
    //2. 使用 Map 來 指定 URL 變量:
    @GetMapping("/map/{id}")
    public Ingredient getIngredientById2(@PathVariable String id) {
        Map<String, String> urlVariables = new HashMap<>();
        urlVariables.put("id", id);
        return rest.getForObject("http://localhost:8080/ingredient/{id}", Ingredient.class, urlVariables);
    }

    //  3.使用 URL 參數
    @GetMapping("/uri/{id}")
    public Ingredient getIngredientById3(@PathVariable String id) {
        Map<String, String> urlVariables = new HashMap<>();
        urlVariables.put("id", id);
        URI url= UriComponentsBuilder.fromHttpUrl("http://localhost:8080/ingredient/{id}")
                .build(urlVariables);
        return rest.getForObject(url,Ingredient.class);
    }

    //通過getForEntity()方法得到ResponseEntity對象
    @GetMapping("/entity/{id}")
    public Ingredient getIngredientById4(@PathVariable String id) {
        ResponseEntity<Ingredient> responseEntity = rest.getForEntity("http://localhost:8080/ingredient/entity/{id}", Ingredient.class, id);
        log.info("Fetched time:" + responseEntity.getHeaders().getDate());
        return responseEntity.getBody();
    }
//  提示: getForEntity() 有 與 getForObject() 方法 相同 參數 的 重載 形式,
//    所以 我們 既可以 以 可變 列表 參數 的 形式 提供 URL 變量,
//    也可以 以 URI 對象 的 形式 調用 getForEntity()。

    @PutMapping("/update")
    public void updateIngredient(@RequestBody Ingredient ingredient){
        rest.put("http://localhost:8080/ingredient",ingredient,ingredient.getId());
    }

    @DeleteMapping("/delete/{id}")
    public void deleteIngredient(@PathVariable String id){
        rest.delete("http://localhost:8080/ingredient/{id}",id);
    }

    //POST請求之後得到 新 創建 的 Ingredient 資源,
    @PostMapping
    public Ingredient createIngredient(@RequestBody Ingredient ingredient){
        return rest.postForObject("http://localhost:8080/ingredient",ingredient,Ingredient.class);
    }

    //POST請求之後得到 新創建 資源 的 地址,
    @PostMapping("/create")
    public  URI createIngredient2(@RequestBody Ingredient ingredient){
        return rest.postForLocation("http://localhost:8080/ingredient",ingredient);
    }

    //POST請求之後同時得到,資源地址和響應本身
    @PostMapping("createall")
    public Ingredient createIngredient3(@RequestBody Ingredient ingredient){
        ResponseEntity<Ingredient> responseEntity=rest.postForEntity("http://localhost:8080/ingredient",ingredient,Ingredient.class);
        log.info("New resource created at "+responseEntity.getHeaders().getLocation());;
        return responseEntity.getBody();
    }





}

使用Traverson來消費帶有超鏈接的REST API資源

要 使用 Traverson, 首先 我們 要用 API 的 基礎 URI 來 實例 化 一個 Traverson 對象:

 Traverson traverson=new Traverson(URI.create("http://localhost:8080/api"),MediaTypes.HAL_JSON);

例子:

ParameterizedTypeReference< Resources< Taco>> tacoType =
new ParameterizedTypeReference< Resources< Taco>>() {}; Resources< Taco> tacoRes = traverson .follow(" tacos") .follow(" recents") .toObject( tacoType); Collection< Taco> tacos = tacoRes. getContent();

當你 既要 導航 API 又要 更新 或 刪除 資源 時, 你需要組合 使用 RestTemplate 和 Traverson。 Traverson 仍然 可以 導航 至 創建 新 資源 的 鏈接。 然後, 可以 將 這個 鏈接 傳遞 給 RestTemplate 來 執行 POST、 PUT、 DELETE 或 任何 其他 需要 的 HTTP 請求。

private Ingredient addIngredient( Ingredient ingredient) {
 String ingredientsUrl = traverson .follow(" ingredients") .asLink() .getHref();
 return rest. postForObject( ingredientsUrl, ingredient, Ingredient. class);
 } 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章