提供 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

<<:  DAY 14:Simple Factory Pattern,把复杂细节隐藏的小工厂

>>:  Day13 - composition API 初次见面哩贺

Annotation 处理时机

处理 Annotation 的时机 一般来说,annotation 可以在 compile time...

[Day 28] Node thread pool 3

前言 今天的内容是整理整个 threadpool (TP) 的调用过程 回顾 在 pending 阶...

30-21 之 Domain Layer - Lazy Load ( 未完成 )

什麽是 Lazy Load 呢 ? An object that doesn’t contain a...

Day11 TailwindCSS 介绍,在 Next.js 专案安装 TailwindCSS

上一篇我们成功安装完 GraphQL client,并在首页显示出文章列表了。功能做完,接下来要来切...

[想试试看JavaScript ] 阵列一些操作阵列好用的方法

阵列一些操作阵列好用的方法 这篇整理一些常用的阵列方法 push() push 可以新增元素在阵列的...