You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
140 lines
4.5 KiB
140 lines
4.5 KiB
[[kotlin-web]] |
|
= Web |
|
|
|
|
|
|
|
[[router-dsl]] |
|
== Router DSL |
|
|
|
Spring Framework comes with a Kotlin router DSL available in 3 flavors: |
|
|
|
* WebMvc.fn DSL with {docs-spring-framework}/kdoc-api/spring-webmvc/org.springframework.web.servlet.function/router.html[router { }] |
|
* WebFlux.fn <<web-reactive#webflux-fn, Reactive>> DSL with {docs-spring-framework}/kdoc-api/spring-webflux/org.springframework.web.reactive.function.server/router.html[router { }] |
|
* WebFlux.fn <<Coroutines>> DSL with {docs-spring-framework}/kdoc-api/spring-webflux/org.springframework.web.reactive.function.server/co-router.html[coRouter { }] |
|
|
|
These DSL let you write clean and idiomatic Kotlin code to build a `RouterFunction` instance as the following example shows: |
|
|
|
[source,kotlin,indent=0] |
|
---- |
|
@Configuration |
|
class RouterRouterConfiguration { |
|
|
|
@Bean |
|
fun mainRouter(userHandler: UserHandler) = router { |
|
accept(TEXT_HTML).nest { |
|
GET("/") { ok().render("index") } |
|
GET("/sse") { ok().render("sse") } |
|
GET("/users", userHandler::findAllView) |
|
} |
|
"/api".nest { |
|
accept(APPLICATION_JSON).nest { |
|
GET("/users", userHandler::findAll) |
|
} |
|
accept(TEXT_EVENT_STREAM).nest { |
|
GET("/users", userHandler::stream) |
|
} |
|
} |
|
resources("/**", ClassPathResource("static/")) |
|
} |
|
} |
|
---- |
|
|
|
NOTE: This DSL is programmatic, meaning that it allows custom registration logic of beans |
|
through an `if` expression, a `for` loop, or any other Kotlin constructs. That can be useful |
|
when you need to register routes depending on dynamic data (for example, from a database). |
|
|
|
See https://github.com/mixitconf/mixit/[MiXiT project] for a concrete example. |
|
|
|
|
|
|
|
[[mockmvc-dsl]] |
|
== MockMvc DSL |
|
|
|
A Kotlin DSL is provided via `MockMvc` Kotlin extensions in order to provide a more |
|
idiomatic Kotlin API and to allow better discoverability (no usage of static methods). |
|
|
|
[source,kotlin,indent=0] |
|
---- |
|
val mockMvc: MockMvc = ... |
|
mockMvc.get("/person/{name}", "Lee") { |
|
secure = true |
|
accept = APPLICATION_JSON |
|
headers { |
|
contentLanguage = Locale.FRANCE |
|
} |
|
principal = Principal { "foo" } |
|
}.andExpect { |
|
status { isOk } |
|
content { contentType(APPLICATION_JSON) } |
|
jsonPath("$.name") { value("Lee") } |
|
content { json("""{"someBoolean": false}""", false) } |
|
}.andDo { |
|
print() |
|
} |
|
---- |
|
|
|
|
|
|
|
[[kotlin-script-templates]] |
|
== Kotlin Script Templates |
|
|
|
Spring Framework provides a |
|
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/view/script/ScriptTemplateView.html[`ScriptTemplateView`] |
|
which supports https://www.jcp.org/en/jsr/detail?id=223[JSR-223] to render templates by using script engines. |
|
|
|
By leveraging `scripting-jsr223` dependencies, it |
|
is possible to use such feature to render Kotlin-based templates with |
|
https://github.com/Kotlin/kotlinx.html[kotlinx.html] DSL or Kotlin multiline interpolated `String`. |
|
|
|
`build.gradle.kts` |
|
[source,kotlin,indent=0] |
|
---- |
|
dependencies { |
|
runtime("org.jetbrains.kotlin:kotlin-scripting-jsr223:${kotlinVersion}") |
|
} |
|
---- |
|
|
|
Configuration is usually done with `ScriptTemplateConfigurer` and `ScriptTemplateViewResolver` beans. |
|
|
|
`KotlinScriptConfiguration.kt` |
|
[source,kotlin,indent=0] |
|
---- |
|
@Configuration |
|
class KotlinScriptConfiguration { |
|
|
|
@Bean |
|
fun kotlinScriptConfigurer() = ScriptTemplateConfigurer().apply { |
|
engineName = "kotlin" |
|
setScripts("scripts/render.kts") |
|
renderFunction = "render" |
|
isSharedEngine = false |
|
} |
|
|
|
@Bean |
|
fun kotlinScriptViewResolver() = ScriptTemplateViewResolver().apply { |
|
setPrefix("templates/") |
|
setSuffix(".kts") |
|
} |
|
} |
|
---- |
|
|
|
See the https://github.com/sdeleuze/kotlin-script-templating[kotlin-script-templating] example |
|
project for more details. |
|
|
|
|
|
|
|
[[kotlin-multiplatform-serialization]] |
|
== Kotlin multiplatform serialization |
|
|
|
As of Spring Framework 5.3, https://github.com/Kotlin/kotlinx.serialization[Kotlin multiplatform serialization] is |
|
supported in Spring MVC, Spring WebFlux and Spring Messaging (RSocket). The builtin support currently targets CBOR, JSON, and ProtoBuf formats. |
|
|
|
To enable it, follow https://github.com/Kotlin/kotlinx.serialization#setup[those instructions] to add the related dependency and plugin. |
|
With Spring MVC and WebFlux, both Kotlin serialization and Jackson will be configured by default if they are in the classpath since |
|
Kotlin serialization is designed to serialize only Kotlin classes annotated with `@Serializable`. |
|
With Spring Messaging (RSocket), make sure that neither Jackson, GSON or JSONB are in the classpath if you want automatic configuration, |
|
if Jackson is needed configure `KotlinSerializationJsonMessageConverter` manually. |
|
|
|
|
|
|
|
|
|
|