Spring BootとKotlinを使ってCRUD操作のできるAPIを作成します。
環境
Docker: 18.09.2
Springboot: 2.1.5
Kotlin: 1.3.31
MySQL: 5.7.26
プロジェクトの作成
まずはSpring Bootのプロジェクトを作成しましょう。
1.Sprin Initializrにアクセスします。
2.ProjectはMavenかGradleかお好みで、LanguageはKotlin、Spring Bootのバージョンは2.X以降のものを選びましょう。
3.Project Metadataは必要に応じて変更してください。今回はArtifactをsample_qiita
にしています。
4.DependenciesはWeb
,JPA
,MySQL
を選択します。
5.最後にGenerate Projectをクリックして設定の終わったプロジェクトをダウンロードし、ローカルで開きます。
ローカルのIDEなどで開くとディレクトリ構造は次のようになっていると思います。
sample_qiita
├ .idea
├ .gradle
├ src
│ ├ main
│ │ ├ kotlin
│ │ │ └ com.example.sample_qiita
│ │ │ └ SampleQiitaAppllication.kt
│ │ └ resources
│ │ ├ static
│ │ ├ templates
│ │ └ application.properties
│ └ test
│ └ kotlin
│ └ com.example.sampleqiita
│ └ SampleQiitaAppllicationTests
├ .gitignore
├ build.gradle.kt
・
・
・
└ External Libraries
MySQLの接続設定
今回はDockerコンテナを立てて、その中のMySQLを使用したいので、こちらの記事を参考にsample_qiita
直下にdocker-compose.yml
を作成します。
db:
image: mysql:5.7
ports:
- "3306:3306"
environment:
MYSQL_DATABASE: sample_qiita_db
MYSQL_ROOT_USER: root
MYSQL_ROOT_PASSWORD: root
次にSpring Bootがデータソースを作成できるようにMySQLのURL、ユーザー名、パスワードを設定する必要があります。
src/main/resources/application.properties
を編集します。
## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.url = jdbc:mysql://127.0.0.1:3306/sample_qiita_db?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false
spring.datasource.username = root
spring.datasource.password = root
## Hibernate Properties
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = update
これでDockerコンテナ上のMySQLと接続できるようになりました。
Modelの作成
Entityを作成していきましょう。
com.example.sample_qiita
内にmodel
というパッケージを作成し、その中にQiita.kt
というファイルを作成しましょう。
package com.example.sample_qiita.model
import javax.persistence.Entity
import javax.persistence.GeneratedValue
import javax.persistence.GenerationType
import javax.persistence.Id
import javax.validation.constraints.NotBlank
@Entity
data class Qiita (
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long = 0,
@get: NotBlank
val title: String = "",
@get: NotBlank
val content: String = ""
)
今回はQiitaクラスの全てのフィールドにデフォルト値を設定しています。
これはHibernateが引数のないコンストラクタを持つEntityを必要とするためです。
全てのフィールドにデフォルト値を割り当てると、Hibernateは引数を渡さずにQiitaをインスタンス化できるようになります。
Repositoryの作成
con.example.sample_qiita
内にrepository
パッケージを作成し、その中にQiitaRepository.kt
を作成しましょう。
package com.example.sample_qiita.repository
import com.example.sample_qiita.model.Qiita
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository
@Repository
interface QiitaRepository: JpaRepository<Qiita, Long>
これによりJpaRepository
からQiitaRepository
を拡張したので、Qiitaエンティティを用いた全てのCRUDメソッドが使えるようになりました。
Controllerの作成
最後にQiitaエンティティに対するCRUD操作をするためのコントローラを作成します。
com.example.sample_qiita
パッケージ内にcontroller
というパッケージを作成し、その中にQiitaController.kt
を作成します。
package com.example.sample_qiita.controller
import com.example.sample_qiita.model.Qiita
import com.example.sample_qiita.repository.QiitaRepository
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
import javax.validation.Valid
@RestController
@RequestMapping("/api")
class QiitaController(private val qiitaRepository: QiitaRepository) {
@GetMapping("/qiitas")
fun getAllQiitas(): List<Qiita> =
qiitaRepository.findAll()
@PostMapping("/qiitas")
fun createNewQiita(@Valid @RequestBody qiita: Qiita): Qiita =
qiitaRepository.save(qiita)
@GetMapping("/qiitas/{id}")
fun getQiitaBiId(@PathVariable(value = "id") qiitaed: Long): ResponseEntity<Qiita> {
return qiitaRepository.findById(qiitaed).map { qiita ->
ResponseEntity.ok(qiita)
}.orElse(ResponseEntity.notFound().build())
}
@PutMapping("/qiitas/{id}")
fun updateQiitaById(@PathVariable(value = "id") qiitaed: Long,
@Valid @RequestBody newQiita: Qiita): ResponseEntity<Qiita> {
return qiitaRepository.findById(qiitaed).map { existingQiita ->
val updateQiita: Qiita = existingQiita
.copy(title = newQiita.title, content = newQiita.content)
ResponseEntity.ok().body(qiitaRepository.save(updateQiita))
}.orElse(ResponseEntity.notFound().build())
}
@DeleteMapping("/qiitas/{id}")
fun deleteQiitaById(@PathVariable(value = "id") qiitaed: Long): ResponseEntity<Void> {
return qiitaRepository.findById(qiitaed).map { qiita ->
qiitaRepository.delete(qiita)
ResponseEntity<Void>(HttpStatus.OK)
}.orElse(ResponseEntity.notFound().build())
}
}
以上でアプリは完成したので、早速動かしてみましょう。
起動方法
まずはDockerkコンテナを立ち上げます。
$ docker-compose up -d
次に作成したsample_qiitaをRunしましょう。
http://localhost:8080/api/qiitasにアクセスして、[]
が表示されていたら成功です。
Rest APIの動作確認
curl
コマンドを使って正しい反応が返ってくるか試してみましょう。
Qiitaの作成
/api/articles
へPOSTして送信して新しくQiita
が作成されるかの確認をします。
以下の内容をコマンドラインで叩いてみましょう。
curl -i -H "Content-Type: application/json" -X POST \
-d '{"title": "Create API by Spring Boot and Kotlin", "content": "Text of creating API"}' \
http://localhost:8080/api/qiitas
これを実行すると、以下のように反応が返ってくると思います。
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Wed, 05 Jun 2019 06:21:52 GMT
{"id":1,"title":"Create API by Spring Boot and Kotlin","content":"Text of creating API"}
これで新しくデータベースにQiitaデータが保存されました。
確認するにはhttp://localhost:8080/api/qiitasにアクセスするか、次の方法を試してみましょう。
全データを取得する。
さっそく次の1行目のコマンドを打ってみましょう。
curl -i -H 'Accept: application/json' http://localhost:8080/api/qiitas
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Fri, 06 Oct 2017 03:25:29 GMT
{"id":1,"title":"Create API by Spring Boot and Kotlin","content":"Text of creating API"}
ちゃんと返ってきていますね!
作成したQiitaデータが全て返ってくると思います。
Idで指定したQiitaを取得する。
指定したIdのデータだけを取得するコマンドになります。
curl -i -H 'Accept: application/json' http://localhost:8080/api/qiitas/1
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Wed, 05 Jun 2019 06:33:27 GMT
{"id":1,"title":"Create API by Spring Boot and Kotlin","content":"Text of creating API"}
URL(localhost:8080/api/qiitas/{id}
)の最後に指定した数字と同じIDのQiitaデータを取得します。
もちろん、存在しないIDの番号を指定すると404エラーが返ってくるので注意しましょう。
作成したQiitaデータの更新
既に登録してあるデータの更新を行うにはPUT
メソッドを使用します。
curl -i -H "Content-Type: application/json" -X PUT \
-d '{"title": "How to learn Spring boot and Kotlin", "content": "Resources to learn Spring boot and Kotlin"}' \
http://localhost:8080/api/qiitas/1
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Wed, 05 Jun 2019 06:45:18 GMT
{"id":1,"title":"How to learn Spring boot and Kotlin","content":"Resources to learn Spring boot and Kotlin"}
Qiitaデータの削除
削除するにはDELETE
メソッドを使用します。
curl -i -X DELETE http://localhost:8080/api/qiitas/1
HTTP/1.1 200
Content-Length: 0
Date: Wed, 05 Jun 2019 06:47:21 GMT
参考文献
Building Restful APIs with Kotlin, Spring Boot, Mysql, JPA and Hibernate
Kotlin × Spring Boot で REST API サンプルアプリケーション作ってみた。
Dockerを使ったSpringboot/KotlinとMySQLの一番シンプルな接続方法
Kotlin Webアプリケーション 新しいサーバサイドプログラミング