LoginSignup
58
70

More than 3 years have passed since last update.

REST通信には、げきつよRestTemplateを使うべし

Posted at

RestTemplate

RestTemplateって?

RestTemplateは、REST API(Web API)を呼び出すためのメソッドを提供するクラス。
Spring Frameworkが提供するHTTPクライアント(HttpClientをラップしている)。

まとめると、、、REST通信が簡単にできる便利部品。

DTOからJson形式のリクエストに変換する処理や、Json形式のレスポンスをDTOにバインドする処理をしてくれる。
データ形式はJson以外にXmlやFormなど様々対応していて、カスタマイズも可能!!

DTO => Json

DTO
@Getter // (1)
@Setter // (1)
public class SomeRequestResource {
    private String message; // (2)
}

(1) ライブラリのlombockを使用してGetter, Setterを自動生成
(2) Json変換を後に反映されるフィールド

Json
{
  "messsage": "test message"
}

DTOのフィールド名と値がJson形式に変換される

Json => DTO

Json
{
  "messsage": "test message"
}
DTO
@Getter
@Setter
public class SomeRequestResource {
    private String message; // (1)
}

(1) Jsonの値がバインドされるフィールド

RestTemplateの使い方

「きほん」のき

とりあえずインジェクション

@Service
public class XxxxServiceImpl implements XxxxService {

    @Autowired
    RestTemplate restTemplate;

    // ...

}

今回のメインRestTemplateをインジェクション。このRestTemplateの中にREST通信に使うパーツがいっぱい詰まってる。

GET送信してみる

@Getter
@Setter
public class TestResponseResource {
    private String id;      // (1)
    private String message; // (1)
}

(1) レスポンスをバインドするフィールド

@Service
public class XxxxServiceImpl implements XxxxService {

    @Autowired
    RestTemplate restTemplate;

    public static final String URL = "http://com.example.rest/test";

    public TestResponseResource getTestResponse() {
      // (1)
      return restTemplate.getForObject(URL, TestResponseResource.class);
    }

}

(1) GET送信する。
(1) getForObjectの引数

引数順 説明
1 String 送信先のURL
2 Class<T> 送信先から返却されたResponseBodyをバインドするクラス

POST送信してみる

@Getter
@Setter
public class TestRequestResource {
    private String message;  // (1)
}

(1) 送信する値

@Getter
@Setter
public class TestResponseResource {
    private String id;      // (1)
    private String message; // (1)
}

(1) レスポンスをバインドするフィールド

@Service
public class XxxxServiceImpl implements XxxxService {

    @Autowired
    RestTemplate restTemplate;

    public static final String URL = "http://com.example.rest/test";

    public TestResponseResource getTestResponse() {
      // (1)
      TestRequestResource request = new TestRequestResource();
      request.setMessage("test message");

      // (2)
      return restTemplate.postForObject(URL,request,TestResponseResource.class);
    }

}

(1) 送信データを設定する
(2) POST送信
(2) postForObjectの引数

引数順 説明
1 String 送信先のURL
2 Object 送信する値
3 Class<T> 送信先から返却されたResponseBodyをバインドするクラス

「きほん」のほ

送信URLを動的に変更する

REST通信の場合、URLからResourceのid情報を取得する場合がある。
例) http://com.example.rest/book/1

RestTemplateの場合、複数パターンで実装が可能。

順番にPathParameterつめつめパターン
@Getter
@Setter
public class BookResponseResource {
    private String id;
    private String message;
}
@Service
public class XxxxServiceImpl implements XxxxService {

    @Autowired
    RestTemplate restTemplate;

    // (1)
    public static final String URL = "http://com.example.rest/book/{id}";

    public TestResponseResource getTestResponse() {
      // (2)
      return restTemplate.getForObject(URL, BookResponseResource.class, "1");
    }

}

(1) {id}の箇所にパラメータがバインドされる
(2) 引数の最後にパラメータにバインドしたい文字列を渡す。可変長引数で取るため、複数指定可能。

明示的につめつめパターン
@Getter
@Setter
public class BookResponseResource {
    private String id;
    private String message;
}
@Service
public class XxxxServiceImpl implements XxxxService {

    @Autowired
    RestTemplate restTemplate;

    // (1)
    public static final String URL = "http://com.example.rest/book/{id}";

    public BookResponseResource getTestResponse() {
      // (2)
      Map<String, String> params = new HashMap<String, String>();
      params.put("id", "1");
      // (3)
      return restTemplate.getForObject(URL, BookResponseResource.class, params);
    }
}

(1) {id}の箇所にパラメータがバインドされる
(2) パラメータにバインドする値を設定
(2) 引数の最後にパラメータにバインドしたい値のMap<String, String>を渡す。

送信するHeader情報を変更する

送信するデータ形式をXMLなどの変更した場合や、文字コードを変更した場合、特殊なHeaderを送信したい場合など臨機応変に変更可能。

Content-Typeを変更

Content-Typeのみを変更する場合
public BookResponseResource getTestResponse(BookRequestResource request) {
    RequestEntity<BookRequestResource> requestEntity = 
        RequestEntity
          .post(new URI(URL))
          .contentType(MediaType.APPLICATION_XML) // (1)
          .body(request);

    return restTemplate.getForObject(requestEntity, BookResponseResource.class);
}

(1) Content-Typeを変更

charsetも変更する場合
public BookResponseResource getTestResponse(BookRequestResource request) {
    // (1)
    Map<String, String> prop = new HashMap<String, String>();
    prop.put("charset", "shift_jis");
    // (2)
    MediaType mediaType = new MediaType(MediaType.APPLICATION_XML, param);

    RequestEntity<BookRequestResource> requestEntity = 
        RequestEntity
          .post(new URI(URL))
          .contentType(mediaType)
          .body(request);

    return restTemplate.getForObject(requestEntity, BookResponseResource.class);
}

(1) MediaTypeのプロパティ(charset)を設定
(2) プロパティを元にMediaTypeを生成

「きほん」のん

通信先でのエラーをハンドリングする

public TestResponseResource getTestResponse() {
    // (1)
    try {
        return restTemplate.getForObject(URL, TestResponseResource.class);
    }
    catch (HttpClientErrorException e) { // (1)
        logger.error("400系エラー発生");
        throw e;
    }
    catch (HttpServerErrorException e) { // (2)
        logger.error("500系エラー発生");
        throw e;
    }
}

(1) レスポンスのHttpStatusコードが400系の場合に発生する。
(2) レスポンスのHttpStatusコードが500系の場合に発生する。

58
70
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
58
70