在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称(OpenSource Name):spring-guides/tut-spring-boot-kotlin开源软件地址(OpenSource Url):https://github.com/spring-guides/tut-spring-boot-kotlin开源编程语言(OpenSource Language):Kotlin 90.7%开源软件介绍(OpenSource Introduction):Table of Contents
This tutorial shows you how to build efficiently a sample blog application by combining the power of Spring Boot and Kotlin. If you are starting with Kotlin, you can learn the language by reading the reference documentation, following the online Kotlin Koans tutorial or just using Spring Framework reference documentation which now provides code samples in Kotlin. Spring Kotlin support is documented in the Spring Framework and Spring Boot reference documentation. If you need help, search or ask questions with the Creating a New ProjectFirst we need to create a Spring Boot application, which can be done in a number of ways. Using the Initializr WebsiteVisit https://start.spring.io and choose the Kotlin language. Gradle is the most commonly used build tool in Kotlin, and it provides a Kotlin DSL which is used by default when generating a Kotlin project, so this is the recommended choice. But you can also use Maven if you are more comfortable with it. Notice that you can use https://start.spring.io/#!language=kotlin&type=gradle-project to have Kotlin and Gradle selected by default.
The .zip file contains a standard project in the root directory, so you might want to create an empty directory before you unpack it. Using command lineYou can use the Initializr HTTP API from the command line with, for example, curl on a UN*X like system:
Add Using IntelliJ IDEASpring Initializr is also integrated in IntelliJ IDEA Ultimate edition and allows you to create and import a new project without having to leave the IDE for the command-line or the web UI. To access the wizard, go to File | New | Project, and select Spring Initializr. Follow the steps of the wizard to use the following parameters:
Understanding the Gradle BuildIf you’re using a Maven Build, you can skip to the dedicated section. PluginsIn addition to the obvious Kotlin Gradle plugin, the default configuration declares the kotlin-spring plugin which automatically opens classes and methods (unlike in Java, the default qualifier is In order to be able to use Kotlin non-nullable properties with JPA, Kotlin JPA plugin is also enabled. It generates no-arg constructors for any class annotated with
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("plugin.jpa") version "1.4.32"
id("org.springframework.boot") version "2.4.4"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
kotlin("jvm") version "1.4.32"
kotlin("plugin.spring") version "1.4.32"
} Compiler optionsOne of Kotlin’s key features is null-safety - which cleanly deals with Although Java does not allow one to express null-safety in its type-system, Spring Framework provides null-safety of the whole Spring Framework API via tooling-friendly annotations declared in the This feature can be enabled by adding the Notice also that Kotlin compiler is configured to generate Java 8 bytecode (Java 6 by default).
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "1.8"
}
} Dependencies3 Kotlin specific libraries are required for such Spring Boot web application and configured by default:
dependencies {
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-mustache")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
runtimeOnly("com.h2database:h2")
runtimeOnly("org.springframework.boot:spring-boot-devtools")
testImplementation("org.springframework.boot:spring-boot-starter-test")
} Spring Boot Gradle plugin automatically uses the Kotlin version declared via the Kotlin Gradle plugin. You can now take a deeper look at the generated application. Understanding the Maven BuildPluginsIn addition to the obvious Kotlin Maven plugin, the default configuration declares the kotlin-spring plugin which automatically opens classes and methods (unlike in Java, the default qualifier is In order to be able to use Kotlin non-nullable properties with JPA, Kotlin JPA plugin is also enabled. It generates no-arg constructors for any class annotated with
<build>
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<configuration>
<compilerPlugins>
<plugin>jpa</plugin>
<plugin>spring</plugin>
</compilerPlugins>
<args>
<arg>-Xjsr305=strict</arg>
</args>
</configuration>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-noarg</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-allopen</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build> One of Kotlin’s key features is null-safety - which cleanly deals with Although Java does not allow one to express null-safety in its type-system, Spring Framework provides null-safety of the whole Spring Framework API via tooling-friendly annotations declared in the This feature can be enabled by adding the Notice also that Kotlin compiler is configured to generate Java 8 bytecode (Java 6 by default). Dependencies3 Kotlin specific libraries are required for such Spring Boot web application and configured by default:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mustache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-kotlin</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies> Understanding the generated Application
package com.example.blog
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
@SpringBootApplication
class BlogApplication
fun main(args: Array<String>) {
runApplication<BlogApplication>(*args)
} Compared to Java, you can notice the lack of semicolons, the lack of brackets on empty class (you can add some if you need to declare beans via
fun main(args: Array<String>) {
runApplication<BlogApplication>(*args) {
setBannerMode(Banner.Mode.OFF)
}
} Writing your first Kotlin controllerLet’s create a simple controller to display a simple web page.
package com.example.blog
import org.springframework.stereotype.Controller
import org.springframework.ui.Model
import org.springframework.ui.set
import org.springframework.web.bind.annotation.GetMapping
@Controller
class HtmlController {
@GetMapping("/")
fun blog(model: Model): String {
model["title"] = "Blog"
return "blog"
}
} Notice that we are using here a Kotlin extension that allows to add Kotlin functions or operators to existing Spring types. Here we import the We also need to create the associated Mustache templates.
Start the web application by running the Testing with JUnit 5JUnit 5 now used by default in Spring Boot provides various features very handy with Kotlin, including autowiring of constructor/method parameters which allows to use non-nullable Writing JUnit 5 tests in KotlinFor the sake of this example, let’s create an integration test in order to demonstrate various features:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class IntegrationTests(@Autowired val restTemplate: TestRestTemplate) {
@Test
fun `Assert blog page title, content and status code`() {
val entity = restTemplate.getForEntity<String>("/")
assertThat(entity.statusCode).isEqualTo(HttpStatus.OK)
assertThat(entity.body).contains("<h1>Blog</h1>")
}
} Test instance lifecycleSometimes you need to execute a method before or after all tests of a given class. Like Junit 4, JUnit 5 requires by default these methods to be static (which translates to But Junit 5 allows you to change this default behavior and instantiate test classes one time per class. This can be done in various ways, here we will use a property file to change the default behavior for the whole project:
junit.jupiter.testinstance.lifecycle.default = per_class With this configuration, we can now use
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class IntegrationTests(@Autowired val restTemplate: TestRestTemplate) {
@BeforeAll
fun setup() {
println(">> Setup")
}
@Test
fun `Assert blog page title, content and status code`() {
println(">> Assert blog page title, content and status code")
val entity = restTemplate.getForEntity<String>("/")
assertThat(entity.statusCode).isEqualTo(HttpStatus.OK)
assertThat(entity.body).contains("<h1>Blog</h1>")
}
@Test
fun `Assert article page title, content and status code`() {
println(">> TODO")
}
@AfterAll
fun teardown() {
println(">> Tear down")
}
} Creating your own extensionsInstead of using util classes with abstract methods like in Java, it is usual in Kotlin to provide such functionalities via Kotlin extensions. Here we are going to add a
fun LocalDateTime.format() = this.format(englishDateFormatter)
private val daysLookup = (1..31).associate { it.toLong() to getOrdinal(it) }
private val englishDateFormatter = DateTimeFormatterBuilder()
.appendPattern("yyyy-MM-dd")
.appendLiteral(" ")
.appendText(ChronoField.DAY_OF_MONTH, daysLookup)
.appendLiteral(" ")
.appendPattern("yyyy")
.toFormatter(Locale.ENGLISH)
private fun getOrdinal(n: Int) = when {
n in 11..13 -> "${n}th"
n % 10 == 1 -> "${n}st"
n % 10 == 2 -> "${n}nd"
n % 10 == 3 -> "${n}rd"
else -> "${n}th"
}
fun String.toSlug() = toLowerCase()
.replace("\n", " ")
.replace("[^a-z\\d\\s]".toRegex(), " ")
.split(" ")
.joinToString("-")
.replace("-+".toRegex(), "-") We will leverage these extensions in the next section. Persistence with JPAIn order to make lazy fetching working as expected, entities should be With Gradle:
plugins {
...
kotlin("plugin.allopen") version "1.4.32"
}
allOpen {
annotation("javax.persistence.Entity")
annotation("javax.persistence.Embeddable")
annotation("javax.persistence.MappedSuperclass")
} Or with Maven:
专题导读
上一篇:piratax007/LaTeX_Course: Todos los contenidos del curso de introducción a LaTeX ...发布时间:2022-07-09下一篇:Kotlin/kotlin-fullstack-sample: Kotlin Full-stack Application Example发布时间:2022-07-07热门推荐
热门话题
阅读排行榜
|
请发表评论