[ばね動作]7RESTサービスの使用


  • 本章学習内容
    RestTemplateを使用してRest APIを使用
    TraversonモバイルスーパーメディアAPI
  • を使用

    REST端点を7.1 RestTemplateとして使用


    RestTemplateはRestリソースを使用する手間を処理できます.
    41種類のRESTリソースと対話する方法が提供される.

    固有の操作を実行する方法は12種類あり、残りの方法はこれらの方法のオーバーロードバージョンである.
    TRACE以外の標準HTTPメソッドでは、各メソッドには少なくとも1つのメソッドがある.
    execute()およびexchange()は、すべてのHTTPメソッド要求を送信するために低レベルの汎用メソッドを提供する.
    上の表の方法には3つの形式があります.
  • 可変パラメータリストで指定されたURLパラメータには、URL文字列(Stringタイプ)がパラメータとして受け入れられる.
  • Mapで指定したURLパラメータは、URL文字列をパラメータとして受け入れます.
  • java.net.URLのパラメータとしてURIを受信し、パラメトリックURLはサポートされません.
  • RestTemplateを使用するには、必要に応じてRestTemplateインスタンスを作成するか、空と宣言して必要に応じて注入します.
    RestTemplateインスタンスの作成
    RestTemplate rest = new RestTemplate();
    
    宣言が空で、必要に応じて注入
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    7.1.1リソースの取得(GET)


    次のコードはRestTemplateを使用して特定のIDを持つIngredientオブジェクトをインポートします.
    HATEOASがアクティブでない場合はgetForObject()を使用して食材(成分)を導入できます.
    public Ingredient getIngredientById(String ingredientId) {
        return rest.getForObject("http://localhost:8080/ingredients/{id}",
                                 Ingredient.class, ingredientId);
    }
    getForObject()に渡されるIngreedintIdパラメータは、URLの表示ボックスを指定するために使用されます.
    この例では、変数は1つしかありませんが、これらのパラメータは所定の順序で表示ボックスに指定されます.
    getForObject()の2番目のパラメータは、バインド応答のタイプです.
    ここで、JSON形式の応答データは、逆シーケンス化されてオブジェクトに戻される.
    Mapを使用してURL変数を指定できます.
    public Ingredient getIngredientById(String ingredientId) {
        Map<String, String> urlVariables = new HashMap<>();
        urlVariables.put("id", ingredientId);
        return rest.getForObject("http://localhost:8080/ingredients/{id}",
                                 Ingredient.class, urlVariables);
    }
    要求が実行されると、{id}プレースホルダは、プライマリ・キーがidのMapアイテム値(IngreedintId値)に置き換えられます.
    URIパラメータを使用する場合は、getForObject()を呼び出すためにURIオブジェクトを構成する必要があります.
    public Ingredient getIngredientById(String ingredientId) {
        Map<String, String> urlVariables = new HashMap<>();
        urlVariables.put("id", ingredientId);
        URI url = UriComponentsBuilder
                  .fromHttpUrl("http://localhost:8080/ingredients/{id}")
                  .build(urlVariables);
        return rest.getForObject(url, Ingredient.class);
    }
    URIオブジェクトはURL文字列として作成され、その文字列の{id}プレースホルダはMapアイテム値に置き換えられます.
    getForObject()メソッドは、リソースとしてドメインオブジェクトをインポートし、応答結果を返します.
    クライアントに他に必要なものがある場合は、getForEntityを使用します.
    getForEntity()
    getForEntity()はgetForObject()と同じように動作しますが、応答結果を表すドメインオブジェクトではなく、ドメインオブジェクトを含むResponseEntityオブジェクトを返します.
    応答エンティティは、応答ヘッダなどのより詳細な応答内容を含んでもよい.
    public Ingredient getIngredientById(String ingredientId) {
        ResponseEntity<Ingredient> responseEntity =
            rest.getForEntity("http://localhost:8080/ingredients/{id}",
                              Ingredient.class, ingredientId);
        log.info("Fetched time: " + 
                 responseEntity.getHeaders().getDate());
        return responseEntity.getBody();
    }
    getForEntity()メソッドは、getForObject()と同じパラメータを得るために上書きされます.
    したがって、getForEntity()は、URL変数を可変パラメータリストまたはURIオブジェクトに渡すことによって呼び出すことができる.

    7.1.2書き込みリソース(PUT)


    次のコードはRestTemplateを使用して特定のIDを持つIngredientオブジェクトをインポートします.
    put()メソッドには、3つのオーバーロードバージョンがあり、シリアル化を受け入れて指定したURLに送信されるオブジェクトタイプをパラメータとして使用します.
    // 특정 식자재 리소스를 새로운 Ingredient 객체의 데이터로 교체
    public void updateIngredientById(Ingredient ingredientId) {
        rest.put("http://localhost:8080/ingredients/{id}",
                 ingredient,
                 ingredient.getId());
    }
    ここで、URLは文字列として指定され、パラメータとして渡されるIngredientオブジェクトのid属性値に置き換えられるため、プレースホルダが1つある.
    put()メソッドはIngredientオブジェクト自体を転送し,戻りタイプはvoidであり,戻り値を処理する必要はない.

    7.1.3リソースの削除(DELETE)

    // 특정 식자재 삭제
    public void deleteIngredient(Ingredient ingredientId) {
        rest.delete("http://localhost:8080/ingredients/{id}",
                    ingredient.getId());
    }
    文字列で指定されたURLとURL変数値のみがdelete()のパラメータとして渡されます.
    他の方法と同様に、URLはMapのURLパラメータまたはURLオブジェクトとして指定することができる.

    7.1.4リソースデータの追加(POST)

    public Ingredient createIngredient(Ingredient ingredientId) {
        return rest.postForObject("http://localhost:8080/ingredients/{id}",
                                  ingredient, Ingredient.class);
    }
    POST要求が実行されると、新たに生成された中間リソースを返すことができる.
    文字列URLとサーバに送信するオブジェクト、およびこれらのオブジェクトのタイプ(リソースボディのデータに関連)を利息として使用します.
    URL変数値を持つMapまたはURLの可変パラメータリストを4番目のパラメータとして渡すことができます.
    public URI createIngredient(Ingredient ingredient) {
        return rest.postForLocation("http://localhost:8080/ingredients",
                                    ingredient, Ingredient.class);
    postForObject()と同じですが、リソースオブジェクトではなく、新しく作成したリソースのURIを返します.
    返されるURIは、応答する位置ヘッダから取得される.
    
    public Ingredient createIngredient(Ingredient ingredient) {
        ResponseEntity<Ingredient> responseEntity =
            rest.postForEntity("http://localhost:8080/ingredients",
                               ingredient, Ingredient.class);
        log.info("New resource created at " +
                 responseEntity.getHeaders().getLocation());
        return responseEntity.getBody();
    }
    リソースオブジェクトと新しく作成したリソースのURIは、必要に応じて使用できます.
    APIにハイパーリンクを含める必要がある場合、RestTempateは役立ちません.
    (より詳細なリソースデータをインポートし、そのコンテンツとリンクを使用できますが、これは簡単ではありません)
    ?? 質問:社内でrestTemplateを使わないのはなぜですか.

    REST APIを7.2 Traversonとして使用


    TraversonはSpring Data HATEOASとともに提供され、SpringアプリケーションがスーパーメディアAPIを使用するソリューションです.
    「遍歴」(Traverse on)の意味では、リレーショナル名に必要なAPIを使用します.
    Transversionを使用する場合は、まず、APIのデフォルトURIを持つオブジェクトを作成する必要があります.
    Traverson traverson = new Traverson(
        URI.create("http://localhost:8080/api"), MediaTypes.HAL_JSON);
    TraversonのURLを指定し、各リンクの関係名としてAPIを使用するだけです.
    Traversonジェネレータは、このAPIがHALスタイルハイパーリンクを有するJSON応答をパラメータとして生成することを指定することができる.
    このパラメータを指定した理由は、受信したリソースデータの分析方法をTraversonに知らせるためです.
    Transversonオブジェクトは、Transversonが必要なときに任意の場所で作成することも、注入された空のオブジェクトとして宣言することもできます.
    // 모든 식자재 리스트 가져오기
    public Iterable<Ingredient> getAllIngredientsWithTraverson() {
        ParameterizedTypeReference<Resources<Ingredient>> ingredientType =
            new ParameterizedTypeReference<Resources<Ingredient>>() {};
    
        Resources<Ingredient> ingredientRes = traverson
                                              .follow("ingredients")
                                              .toObject(ingredientType);
    	
        Collection<Ingredient> ingredients = ingredientRes.getContent();
    	
        return ingredients;
    }
    各成分リンクには、食材資源をリンクするhref属性があるため、リンクに従うことができる.
    follow()メソッドを呼び出すことで、リソースリンクの関係名をコンポーネントとしてのリソースに移動できます.
    クライアントがコンポーネントに移動するため、リソースのコンテンツを取得するためにtoObject()を呼び出す必要があります.
    toObject()パラメータは、データを取得するオブジェクトのタイプを指定する必要があります.
    Resourcesタイプのオブジェクトとして取得する必要がありますが、Javaは実行時にJENNERICタイプのタイプ情報()をクリアするため、リソースタイプを指定するのは難しいです.
    ParameterizedType Referenceを作成することで、リソースタイプを指定できます.
    
    // 가장 최근에 생성된 타코들 가져오기
    public Iterable<Taco> getRecentTacosWithTraverson() {
        ParameterizedTypeReference<Resources<Taco>> tacoType =
            new ParameterizedTypeReference<Resources<Taco>>() {};
    
        Resources<Taco> tacoRes = traverson
                                  .follow("tacos")
                                  .follow("recents")
                                  .toObject(tacoType);
    
    //  Alternatively, list the two paths in the same call to follow()
    //  Resources<Taco> tacoRes = traverson
    //                            .follow("tacos", "recents")
    //                            .toObject(tacoType);
    
        return tacoRes.getContent();
    }
    tacosリンクは次のrecentsリンクに従います.
    Traversonを使用すると、HATEOASのAPIを移動して有効にすると、APIのリソースを簡単に取得できます.
    Transversonは、APIにリソースを書き込みまたは削除する方法を提供しない(RestTemplateは、リソースを書き込みまたは削除することができるが、APIを移動するのは難しい).
    APIの移動とリソースの変更または削除を同時に行う必要がある場合は、RestTemplateとTraversonを同時に使用します.
    Transversonはまた、新しいリソースを作成するリンクにナビゲートし、RestTemplateにリンクを割り当てることでHTTPを要求することもできます.
    
    // 새로운 식자재(Ingredient 객체) 추가
    public Ingredient addIngredient(Ingredient ingredient) {
        String ingredientsUrl = traverson
                                .follow("ingredients")
                                .asLink()
                                .getHref();
        return rest.postForObject(ingredientsUrl,
                                  ingredient,
                                  Ingredient.class);
    }
    原料リンクに従って移動した後、asLink()を呼び出して原料リンク自体を要求します.
    gethref()を呼び出して、このリンクのURLを取得します.
    読み込んだURLをパラメータとしてRestTempateインスタンスのPostForObject()を呼び出し、新しい食材を追加することができます.

    サマリ

  • クライアントはRestTemplateを使用してRest APIに対してHTTP要求を発行することができる.
  • Traversonを使用すると、クライアントは応答に含まれるハイパーリンクを使用して必要なAPIにナビゲートできます.