使用 Postman 與 Kotlin 交互REST API接口數據

在前面2篇文章使用 Kotlin 和Spring Boot 2.0快速開發REST API接口使用 Kotlin 和Spring Boot 2.0快速開發REST API客戶端介紹瞭如何使用簡單代碼快速實現REST API的服務端接口及客戶端應用。java

此文簡單介紹如何使用Postman快速完成REST API接口的數據交互及調試工做,Postman的下載地址:https://www.getpostman.com/git

就像其主頁上說明的同樣,Postman能讓API的開發工做更加簡單高效,建議作API開發尚未用過Postman的同窗嚐嚐鮮。數組

回到正題,實現數據交互,咱們須要在REST API服務端實現針對不一樣類型HTTP請求的響應機制,其中常見的HTTP請求類型包括GET,POST,DELETE,PUT等,前面咱們的接口僅實現了針對不帶參數的GET類型請求的響應機制,如今咱們先看看含參數的GET請求如何處理。服務器

GET類型HTTP請求傳遞參數有以下2種方式,可分別經過request.pathVariable("id")或者request.queryParam("id")獲取到傳入的參數值:app

請求路徑格式參考框架

傳參方式函數

Kotlin響應函數post

「/get/XXX」 URL路徑變量 GET("/get/{id}")
{ request -> ServerResponse.ok().body(bookRepository.findById(request.pathVariable("id")))}
「/get?id=XXX」 FORM表單參數 GET("/get")
{ request ->
     val id = request.queryParam("id")
     ServerResponse.ok().body(bookRepository.findById(id.get()))
}

實現以上接口函數的方法後,能夠簡單經過Postman提交以下2個測試請求:測試

http://localhost:8080/book/get/5b976f860dded66908723462spa

http://localhost:8080/book/get?id=5b976f860dded66908723462

兩次請求獲取到的結果相同,具體參考以下截圖:

POST類型HTTP請求傳遞參數有以下2種方式,獲取參數值的方法參見下表:

請求路徑格式參考

傳參方式

Kotlin獲取參數值的方法

「/add?name=XXX」 FORM表單參數 request.queryParam("name")
"/add" Request Body 獲取多個同類型Java對象參數值:request.bodyToFlux(Book::class.java) 
獲取單個Java對象參數值:request.bodyToMono(Book::class.java)

以上2種傳參方式的區別在於FORM表單參數僅支持簡單類型參數傳值,而Request Body可經過JSON格式傳遞複雜類型數據到服務端,Spring WebFlux框架會自動將JSON格式的入參轉化爲指定類型的實體bean,若是傳入的是多個Book類型對象的數組,能夠用request.bodyToFlux(Book::class.java)將其轉化爲Book類型元素的Flux流再作後續處理,若是傳入的是單個Book類型對象,能夠用request.bodyToMono(Book::class.java)將其轉化爲Book類型元素的Mono流作後續處理。

如下咱們聲明一個RestBookHandler對象來受理來自REST API的POST請求:

@Component
class RestBookHandler(val bookRepository: BookRepository) {
    fun saveBook(request: ServerRequest): Mono<ServerResponse> = request.bodyToMono(Book::class.java)
            .flatMap { bookRepository.save(it) }
            .flatMap { it ->
                ServerResponse.ok().body(fromObject(it))
            }
}

受理POST請求的動做分解以下:

步驟1:request.bodyToMono(Book::class.java), 將傳入的Request Body 中的JSON字符串轉化爲Book類型的Mono流;

步驟2:flatMap { bookRepository.save(it) },保存Mono流內的Book對象;

步驟3:flatMap { it -> ServerResponse.ok().body(fromObject(it)) },將保存後的Book對象返回給調用者。

在主函數的beans框架內添加以下部分聲明一個名稱爲postHandler的bean處理來自/add路徑的POST請求,接收到的請求交給bookResthandler對象的saveBook方法進行處理:

bean("postHandler") {
    val bookRestHandler = ref<RestBookHandler>()
    router {
        POST("/add", bookRestHandler::saveBook)
    }
}

經過Postman提交以下測試請求:

請求類型 HTTP POST
請求URL http://localhost:8080/add
Request Body(JSON格式串) {
    "name":"Postman提交書籍",
    "author":"Michael Chen",
    "publish":"2018-09-11T13:49:00.000+0000"
}

服務器接受到Postman提交的請求後,正常執行相應過程返回的結果以下:

彙總以上實現的GET及POST方法,不帶參數和帶參數的方法,整個KotlinAppApplication.kt文件的代碼以下:

@SpringBootApplication
class KotlinAppApplication

interface BookRepository : ReactiveMongoRepository<Book, String>

@Document
data class Book(val id: ObjectId?, val name: String, val author: String, val publish: Date)

fun main(args: Array<String>) {
    runApplication<KotlinAppApplication>(*args) {
        addInitializers(
                beans {

                    bean("postHandler") {
                        val bookRestHandler = ref<RestBookHandler>()
                        router {
                            POST("/add", bookRestHandler::saveBook)
                        }
                    }

                    bean {
                        val bookRepository = ref<BookRepository>()
                        val interval = Flux.interval(Duration.ofMillis(100))
                        router {
                            (accept(TEXT_HTML) and "/book").nest {
                                GET("/list")
                                {
                                    ServerResponse.ok().contentType(MediaType.TEXT_EVENT_STREAM)
                                            .body(Flux.zip(interval, bookRepository.findAll()).map { entry -> entry.t2 })
                                }
                                GET("/get/{id}")
                                { request ->
                                    ServerResponse.ok().body(bookRepository.findById(request.pathVariable("id")))
                                }
                                GET("/get")
                                { request ->
                                    val id = request.queryParam("id")
                                    ServerResponse.ok().body(bookRepository.findById(id.get()))
                                }
                            }
                        }
                    }

                    bean {
                        val bookRepository = ref<BookRepository>()
                        ApplicationRunner {
                            bookRepository.deleteAll()
                                    .thenMany(Flux.fromStream(Stream.generate { ObjectId.get() }.limit(10)))
                                    .map { Book(it, "Spring 空間", "Michael Chen", Date()) }
                                    .flatMap { bookRepository.save(it) }
                                    .thenMany(bookRepository.findAll())
                                    .subscribe { println(it) }
                        }
                    }
                }
        )
    }
}

經過以上樣例能夠看出,在結合Kotlin和Spring Boot 2.0的基礎上,開發一個REST API接口能夠有更多靈活的方案,而不用拘泥於@RestController的方式。

以上示例代碼下載地址:https://gitee.com/chenbichao/kotlin-app

相關文章
相關標籤/搜索