この記事は
Spring Boot
を利用したRestful APIサーバに対するリクエスト方法3パターンを書きます。
- リクエストボディのJson
- URIパラメータ(
api/user/{userId}
のようなURI) - クエリストリング(
api/user?name="hoge"
のようなURI)
の3つです。
リクエストボディ
@RequestBody
を使用します。
基本
以下のように、コントローラのメソッドの引数に@RequestBody
を付与します。引数の型には実際に受け取るJsonの型を持つクラスなどを作成しておくと自動でマッピングしてくれます。
以下のコード例の場合は, {"name":"taro", "age": 20}
といったリクエストを受け付けます。
@PostMapping("/user")
fun postByJsonBody(
@RequestBody request: UserRequestBody
): String {
return "name: ${request.name}, age: ${request.age}"
}
data class UserRequestBody(
val name: String,
val age: Int
)
実際に試してみると、以下のようになります。
$ curl http://localhost:8082/user -X POST -d '{"name":"taro", "age":"25"}' -H "Content-type:application/json"
name: taro, age: 25
独自型への変換
受け取ったJsonをなんらかの型(値オブジェクトなど)に変換する場合、以下の2つの方法が考えられます。
- コントローラ層(サービス層)で変換ロジックを直接書く
-
@JsonConverter
コンポーネントを使用してリクエストを受け取った時点で変換させる
1.の方法は簡単ですね。例えば以下のように直接コンストラクタを呼び出してしまいます。
@PostMapping("/user")
fun postByJsonBody(
@RequestBody request: UserRequestBody
): String {
// UserName()でオブジェクトを生成するコードを書く
val userName = UserName(request.name)
return "name: ${request.name}, age: ${request.age}"
}
ただし、上記の方法を用いる場合、UserName
として扱いたいJsonをリクエストされた場合に、毎度変換の必要が出てきてしまいます。
そんな時に便利なのが2.の@JsonComponent
です。
先にコードを見てしまいましょう。
@JsonComponent
class UserNameJsonConverter {
class Serializer : JsonSerializer<UserName>() {
override fun serialize(value: UserName, gen: JsonGenerator, serializers: SerializerProvider) {
return gen.writeObject(value.value)
}
}
class Deserializer : JsonDeserializer<UserName>() {
override fun deserialize(p: JsonParser, ctxt: DeserializationContext?): UserName {
return UserName(p.valueAsString)
}
}
}
上記のように、JsonSerializer<T>
とJsonDeserializer<T>
の実装クラスをそれぞれ作成することで、Jsonのシリアライズ・デシリアライズを実行してくれます。
あとは前述したUserRequestBody
のname
の型をUserName
に変更すると、コントローラ側から変換ロジックを消すことができます。
data class UserRequestBody(
- val name: String,
+ val name: UserName,
val age: Int
)
@PostMapping("/user")
fun postByJsonBody(
@RequestBody request: UserRequestBody
): String {
- val userName = UserName(request.name)
return "name: ${request.name}, age: ${request.age}"
}
URIパラメータ
@PathVariable
を使用します。
基本
@GetMapping("get/{userId}")
fun getUser(@PathVariable userId : String): String {
return "useId: $userId"
}
これも実際にcurl
で実行してみます。
$ curl http://localhost:8082/user/20 -X GET
useId: 20
独自型への変換
@PathVariable
についても、Jsonと同様に型の変換を実行する方法があります。
Converter<S, T>
を実装したコンポーネントを作成することで、String
で受け取ったパラメータを独自の型に変換してくれます。
@Component
class UserIdConverter : Converter<String, UserId> {
override fun convert(source: String): UserId {
return UserId(source)
}
}
data class UserId(
val value: UUID
)
あとは同様に、コントローラの受け取る@PathVariable
をUserId
型に変換すればOKです。
@GetMapping("user/{userId}")
fun getUserByPathVariable(
- @PathVariable userId : String
+ @PathVariable userId : UserId
): String {
return "useId: $userId"
}
クエリストリング
クエリストリングは@RequestParam
を使用します。
基本
@GetMapping("get/user")
fun getUserByQueryParams(
@RequestParam id: String
): String {
return "id: $id"
}
こちらも同様にcurl
で試してみます。
$ curl 'http://localhost:8082/get/user?id=22'
id: 22
独自型への変換
@PathVariable
と同様に、Converter<S, T>
の実装クラスのコンポーネントを作成します。
終わりに
上記の説明はごく基本的な使用方法に限りますので、より詳細な方法は公式ドキュメントなど、参考にしてください。
それでは良いSpring
ライフを!
参考