iT邦幫忙

2021 iThome 鐵人賽

DAY 12
0
Modern Web

使用 Kotlin 快速開發 Web 程式 -- Vaadin系列 第 12

提供 REST API / 限定欄位 / 格式化LocalDate - day12

使用 Javalin

Javalin 是個輕量型框架,在本範例程式中已有基本設定。請開啟Bootstrap.kt,最後一段

@WebServlet(urlPatterns = ["/rest/*"], name = "JavalinRestServlet", asyncSupported = false)
class JavalinRestServlet : HttpServlet() {
    val javalin: JavalinServlet = Javalin.createStandalone()
            .configureRest()
            .servlet()

    override fun service(req: HttpServletRequest, resp: HttpServletResponse) {
        javalin.service(req, resp)
    }
}

fun Javalin.configureRest(): Javalin {
    val gson: Gson = GsonBuilder().create()
    gson.configureToJavalin()
    return this
}

伺服器提供REST服務,而設定皆在 configureRest() extension function

  • 編寫自己的API。請開新檔 StudentRest.kt
package com.example.vok

import io.javalin.Javalin
import io.javalin.http.NotFoundResponse

fun Javalin.studentRest(){

    get("/rest/student/:id"){ ctx ->
        val id = ctx.pathParam("id").toLong()
        Student.findById(id)?.let { ctx.json(it) }?: throw NotFoundResponse("No student with id:$id")
    }

    get("/rest/students"){ctx ->
        ctx.json(Student.findAll())
    }

    get("/rest/student/:id/grade"){ctx->
        val id = ctx.pathParam("id").toLong()
        val student = Student.findById(id) ?: throw NotFoundResponse("No student with id:$id")
        ctx.json(student.grades.fetch())
    }

}
  • configureRest()設定提供上述api
fun Javalin.configureRest(): Javalin {
    val gson: Gson = GsonBuilder().create()
    gson.configureToJavalin()
    studentRest()
    return this
}

執行程式結果如下

https://ithelp.ithome.com.tw/upload/images/20210927/20138680oFuX4wSPRB.png

設定輸出JSON欄位

看似已經提供了json格式rest api,但實務應用時,某些欄位並不提供給外部讀取,該怎麼做呢?
configureRest()方法中已設定由Gson處理物件和json的轉換,所以可採用Gson所提供的功能,設定哪些欄位需要序列化。

  • 開啟Student.kt 在需要輸出為Json的欄位前加上 annotation @Expose,例
   @Expose
    var name: String? = null
  • 接著開啟Boostrap.kt 修改 configureRest() 加上 excludeFieldsWithoutExposeAnnotation()方法
fun Javalin.configureRest(): Javalin {
    val gson: Gson = GsonBuilder()
        .excludeFieldsWithoutExposeAnnotation()
        .create()
    gson.configureToJavalin()
    studentRest()
    return this
}

格式化 LocalDate

上述birthday 輸出為 "birthday":{"year":2001,"month":3,"day":13},筆者希望可轉成"birthday":"2001-03-13"

  • 撰寫轉換器
class LocalDateAdapter: JsonSerializer<LocalDate>{
    override fun serialize(date: LocalDate, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement =
        JsonPrimitive(date.format(DateTimeFormatter.ISO_LOCAL_DATE))
}
  • 加Gson設定
    val gson: Gson = GsonBuilder()
        .setPrettyPrinting()
        .registerTypeAdapter(LocalDate::class.java, LocalDateAdapter())
        .excludeFieldsWithoutExposeAnnotation()
        .create()

setPrettyPrinting() 將json格式為較易閱讀模式
registerTypeAdapter() 告訴GsonBuilder,只要遇到資料型態為LocalDate,就使用LocalDateAdapter()轉換

  • 執行結果如下
    https://ithelp.ithome.com.tw/upload/images/20210928/20138680yKr2BiUDLu.png

上一篇
vok-orm 刪除關連資料 - day11
下一篇
VoK 系統功能權責劃分 ( I ) - day13
系列文
使用 Kotlin 快速開發 Web 程式 -- Vaadin30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言