LoginSignup
1
0

More than 1 year has passed since last update.

Httpリクエストで値を渡す方法(Spring Boot)

Last updated at Posted at 2022-06-11

この記事は

Spring Bootを利用したRestful APIサーバに対するリクエスト方法3パターンを書きます。

  1. リクエストボディのJson
  2. URIパラメータ(api/user/{userId}のようなURI)
  3. クエリストリング(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つの方法が考えられます。

  1. コントローラ層(サービス層)で変換ロジックを直接書く
  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のシリアライズ・デシリアライズを実行してくれます。
あとは前述したUserRequestBodynameの型を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
) 

あとは同様に、コントローラの受け取る@PathVariableUserId型に変換すれば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ライフを!

参考

1
0
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
1
0