今天我們要利用Domain modeling來建構domain type,接著來實作Spring Boot的RESTful API ,就是新增,修改,刪除,查詢囉XD
我們可以使用@GetMapping來表示收到GET的Request,
@GetMapping("/api/v1/customers")
fun getAllCustomers(): List<Customer> {
val customer = Customer(Name("JW"), Phone("123"), Age(25))
val customer2 = Customer(Name("JW"), Email("myEmail"), Age(25))
return listOf(customer, customer2)
}
這邊我們回傳兩個已經寫死的Customer。在瀏覽器打上local:8080/api/v1/customers
就可以看到結果囉
[{"contactInfo":{"value":"123"},"age-KEqCl0g":25,"name-c4577c4":"JW"},{"contactInfo":{"value":"myEmail"},"age-KEqCl0g":25,"name-c4577c4":"JW"}]
發現name的後面怎麼有奇怪的字呢? 明明我們沒這樣寫呀? 這是因為我們沒有做Serialize,因此我們加上kotlinx.serialization來做Serialize,就可以看到正常的結果囉。
安裝教學
https://github.com/Kotlin/kotlinx.serialization/tree/master
package model
import kotlinx.serialization.Serializable
@JvmInline
@Serializable
value class Name(val value: String)
@Serializable
sealed interface ContactInfo
@JvmInline
@Serializable
value class Email(val value: String) : ContactInfo
@JvmInline
@Serializable
value class Phone(val value: String) : ContactInfo
@JvmInline
@Serializable
value class Age(val value: Int)
@Serializable
data class Customer(
val name: Name,
val contactInfo: ContactInfo,
val age: Age,
)
回傳的結果就會是正常的囉XD 不會出現剛剛的奇怪文字
[{"name":"JW","contactInfo":"123","age":25},{"name":"JW","contactInfo":"myEmail","age":25}]
接著來做Post function!跟GetMapping一樣,把Get換成Post
private val customerList = mutableListOf<Customer>()
@Serializable
data class CustomerVO(
val name: String,
val contactInfo: String,
val age: Int,
)
@PostMapping("/api/v1/customers")
fun createCustomer(@RequestBody newCustomer: String) {
Json.decodeFromString<CustomerVO>(newCustomer).let {
customerVOToCustomer(it)
}.let { customerList.add(it) }
}
這邊我們使用一個list來暫時當DB,儲存我們打進來的結果。並且使用CustomerVO這個物件,先將外來的Request轉成這個type,之後再轉成我們的Domain type。
這樣做可以將我們的Request隔離,讓下一個function可以吃到Domain type,不會因為外部的影響,導致後續的function出錯,有點像是驗證的概念XD
@PutMapping("/api/v1/customers")
fun updateCustomer(@RequestBody newCustomer: String) {
Json.decodeFromString<CustomerVO>(newCustomer).let {
customerVOToCustomer(it)
}.let { validatedCustomer ->
customerList.indexOfFirst { it.name == validatedCustomer.name }.takeIf { it != -1 }?.let {
customerList.set(it, validatedCustomer)
}
}
}
這裡我們先搜尋list裡面是否擁有跟輸入一樣名字的元素,接著直接改變它。
@DeleteMapping("/api/v1/customers")
fun DeleteCustomer(@RequestBody newCustomer: String) {
Json.decodeFromString<CustomerVO>(newCustomer).let {
customerVOToCustomer(it)
}.let { validatedCustomer ->
customerList.indexOfFirst { it == validatedCustomer }.takeIf { it != -1 }?.let {
customerList.removeAt(it)
}
}
}
我們今天學會了如何簡單寫出CRUD的api,但還有非常大的進步空間,比如說錯誤處理,連接真正的DB等。都是我們可以更進一步去完善的。期待明天的到來~