1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Kotlin】SpringBoot/JPAのはじめ方2 - Controller編

Last updated at Posted at 2022-09-25

こんにちは。こまつです。

はじめに

これの続きです。

前提

◾️REST送受信のツールが必要
API開発時にはPOSTMAN等のツールをインストールしておく必要があります。

◾️DIとは
ざっくりいうと、@Component, @RestController, @Repositoryなどのクラスアノテーションをつけておくと、
Springがオブジェクトをnewしてくれます。シングルトンなので状態は持てません。
自分でnewさえしなければテスト時に別のオブジェクトに差し替えたりできます。

コントローラを作成する

コントローラの1メソッド(Mapping)がそれぞれAPIになります。
RESTではCRUDをHTTPのメソッドに対応させて、keyをPATHパラメータで送信するのが王道かと思います。

  • 作成 = [POSTメソッド] /users/ -> 1件作成される(内容はリクエストBodyで送信)
  • 取得 = [GETメソッド] /users/1 -> 指定されたID[1]が取得される
  • 更新 = [PUTメソッド] /users/1 -> 指定されたID[1]が更新される(内容はリクエストBodyで送信)
  • 削除 = [DELETEメソッド] /users/1 -> 指定されたID[1]が削除される
  • リスト = [GETメソッド] /users/ -> ユーザが全件取得される
UserController.kt
@RestController             <- コントロラである目印
@RequestMapping("/users")   <- 以後のマッピングは/users/配下にマッピングされる
class UserController(private val userRepository: UserRepository) { <- DIされたモジュルがコンストラクタで渡される

    @PostMapping("/")       <- /users/に対するPOST
    fun create(@RequestBody request: UserPostRequest): User {
        return userRepository.save(request.toEntity())  <- ここではEntityを直接返却している。IDは採番される
    }

    @GetMapping("/{id}")    <- /users/ID に対するGet
    fun read(@PathVariable id: Int): User {
        return userRepository.findById(id)               <- 指定されたIDを検索して見つかったEntityを返却する
            .orElseThrow { NotFoundException("ない") }    <- 存在しなかったら404
    }

    @PutMapping("/{id}")    <- /users/ID に対するPUT
    fun update(@PathVariable id: Int, @RequestBody request: UserPutRequest): User { <- 更新後に更新済みEntityを返却する
        return userRepository.findById(id)                                 <- 存在したら
            .map { user -> userRepository.save(request.toEntity(user)) }   <- 更新する
            .orElseThrow { NotFoundException("ない") }                      <- 存在しなかったら404
    }

    @DeleteMapping("/{id}")  <- /users/IDに対するDELETE
    fun delete(@PathVariable id: Int) {
        userRepository.deleteById(id)       <- 指定されたIDのユザをDBから削除する
    }

    @GetMapping("/") <- /users/に対するGET
    fun list(): List<User> { 
        return userRepository.findAll();   <- ザのリスト(全件)DBから取得する
    }
}

リクエストDTO(フォーム)

Entity生成メソッドを持たせています。
DTOはEntityに依存していいですが逆はだめです。

UserRequest.kt
// ユーザ作成リクエスト
data class UserPostRequest(val name: String) {
    fun toEntity(): User {
        return User(null, name)          <- RequestDtoEntityを参照してよい。POSTならuserId=nullEntityを生成する
    }
}

// 車更新リクエスト
data class UserPutRequest(val name: String) {
    fun toEntity(user: User): User {
        return User(user.id, name)       <- <- Putならuser受信したUserIdEntityに設定する
    }
}

例外クラス

404を表現するクラスを作成します。
存在しないPathにリクエストされるとSpringが自動で404を応答します。

NotFoundException.kt
@ResponseStatus(HttpStatus.NOT_FOUND)   <- HTTP応答を指定する(404)
class NotFoundException(msg: String) : RuntimeException(msg)   

動かしてみる

起動すると localhost:8080 で待ち受けます。
作成したAPIのPathに対応するリクエストを送信します。

◾️ユーザ作成(POST)
スクリーンショット 2022-09-25 11.08.01.png

◾️ユーザ作成のPOST結果
スクリーンショット 2022-09-25 11.08.19.png

◾️Userテーブルの状態
Postしたデータが登録されています
POSTの結果(200スクリーンショット 2022-09-25 11.09.20.png

◾️Userリストを取得
スクリーンショット 2022-09-25 11.14.21.png

他のAPIも問題なく動作しているようです。

まとめ

ここまでで、Http <-> APIサーバ <-> DB までのCRUD+Listが作成できました。

◾️Controllerはリクエストを特定のPathにマッピングするクラス
◾️RESTのURI設計はどこかのベスプラにしたがう
◾️404とか401は例外クラスを作っておいてそれで返す

思っていること

フロント開発や、動的言語に慣れている人はJavaのホットリロードに不満を感じることが多いようですが、これは静的言語&サーバーサイドの開発スタイルの違いに慣れていないのが原因です。

ホットリロード(結果を見ながら開発)をしたい動機は以下と思います。
・フロント=結局見ないと正しいかわからない
・動的言語=実行時エラーがでる

サーバ開発では返却値は型で定義されていますし、型安全に作れば実行時エラーはほぼなくなりますので、上記の動機がないです。
なのでSQLレス&型安全に作って実行時例外の発生ポイントを少なくし、一発で動かす開発スタイルがいいと思います。
その上で、動作を確認したければステップ実行、仕様的な検証をしたければJUnitなどが用意されています。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?