Spring Boot + Kotlin для Kotlin: полное руководство с примерами
1. Что это и зачем нужна
Spring Boot + Kotlin — это комбинация фреймворка Spring Boot и языка программирования Kotlin, которая позволяет создавать современные, надёжные и производительные серверные приложения с минимальным шаблонным кодом. Spring Boot — это популярный Java-фреймворк для создания микросервисов и веб-приложений, а Kotlin — современный статически типизированный язык, полностью совместимый с Java. Вместе они образуют мощный стек для разработки backend-систем.
Зачем это нужно? Во-первых, Kotlin значительно сокращает объём кода по сравнению с Java благодаря таким фичам, как data class, nullable types, extension functions и coroutines. Во-вторых, Spring Boot предоставляет готовые решения для типовых задач: конфигурация через аннотации, встроенный сервер (Tomcat, Netty), работа с базами данных (Spring Data JPA, R2DBC), безопасность (Spring Security) и создание REST API. В-третьих, Kotlin идеально вписывается в экосистему Spring: все аннотации и API работают «из коробки», а компилятор Kotlin генерирует байт-код, совместимый с JVM.
Эта библиотека (точнее, набор библиотек и инструментов) используется для построения высоконагруженных веб-сервисов, микросервисной архитектуры, обработки событий, работы с сообщениями (Kafka, RabbitMQ) и многого другого. Благодаря реактивному стеку Spring WebFlux и корутинам Kotlin, можно создавать неблокирующие приложения с отличной производительностью.
spring-boot-starter-web, spring-boot-starter-data-jpa, spring-boot-starter-webflux и другие. Установка происходит через систему сборки Gradle или Maven.
2. Установка
Поскольку Spring Boot — это Java/Kotlin фреймворк, установка производится через систему сборки Gradle (рекомендуется) или Maven. Ниже приведены точные команды для инициализации проекта с помощью Gradle (Kotlin DSL).
2.1. Инициализация проекта через Gradle (Kotlin DSL)
Создайте файл build.gradle.kts в корне проекта:
plugins {
kotlin("jvm") version "1.9.22"
kotlin("plugin.spring") version "1.9.22"
kotlin("plugin.jpa") version "1.9.22"
id("org.springframework.boot") version "3.2.2"
id("io.spring.dependency-management") version "1.1.4"
}
group = "com.example"
version = "0.0.1-SNAPSHOT"
java {
sourceCompatibility = JavaVersion.VERSION_17
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-validation")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
runtimeOnly("com.h2database:h2")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}
kotlin {
jvmToolchain(17)
}
После создания файла выполните команду для загрузки зависимостей:
./gradlew build
Если вы используете Maven, создайте pom.xml с соответствующими зависимостями. Однако для Kotlin-проектов Gradle является стандартом де-факто.
3. Быстрый старт — минимальный рабочий пример
Создадим простое REST приложение, которое возвращает «Hello, Kotlin!».
3.1. Структура проекта
src/
└── main/
└── kotlin/
└── com/
└── example/
└── demo/
├── DemoApplication.kt
└── HelloController.kt
3.2. Главный класс приложения
package com.example.demo
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
@SpringBootApplication
class DemoApplication
fun main(args: Array<String>) {
runApplication<DemoApplication>(*args)
}
3.3. Контроллер
package com.example.demo
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController
@RestController
class HelloController {
@GetMapping("/hello")
fun sayHello(): String {
return "Hello, Kotlin!"
}
}
3.4. Запуск
Выполните команду:
./gradlew bootRun
Откройте браузер по адресу http://localhost:8080/hello. Вы увидите: Hello, Kotlin!
@JvmStatic для main-функции — Spring Boot автоматически распознаёт runApplication<DemoApplication>().
4. Основные методы/функции/классы
Рассмотрим ключевые компоненты Spring Boot + Kotlin, которые вы будете использовать ежедневно. Для каждого приведена сигнатура, описание и рабочий пример.
4.1. @SpringBootApplication
Сигнатура: @Target(AnnotationTarget.CLASS) annotation class SpringBootApplication
Что делает: Помечает главный класс конфигурации Spring Boot. Объединяет @Configuration, @EnableAutoConfiguration и @ComponentScan.
@SpringBootApplication
class Application
fun main(args: Array<String>) {
runApplication<Application>(*args)
}
4.2. @RestController
Сигнатура: @Target(AnnotationTarget.CLASS) annotation class RestController
Что делает: Указывает, что класс является контроллером REST, где каждый метод возвращает данные (JSON/XML) напрямую, без представления.
@RestController
class UserController {
@GetMapping("/user")
fun getUser(): Map<String, Any> {
return mapOf("name" to "Alice", "age" to 30)
}
}
4.3. @GetMapping, @PostMapping, @PutMapping, @DeleteMapping
Сигнатура: @Target(AnnotationTarget.FUNCTION) annotation class GetMapping(val value: String = "", ...)
Что делает: Сопоставляет HTTP-методы с методами контроллера. @GetMapping для GET, @PostMapping для POST и т.д.
@RestController
class ItemController {
@GetMapping("/items")
fun getAllItems(): List<String> = listOf("item1", "item2")
@PostMapping("/items")
fun createItem(@RequestBody item: String): String {
return "Created: $item"
}
}
4.4. @RequestBody
Сигнатура: @Target(AnnotationTarget.VALUE_PARAMETER) annotation class RequestBody
Что делает: Связывает тело HTTP-запроса с параметром метода. Автоматически десериализует JSON в объект Kotlin.
data class Product(val id: Long, val name: String, val price: Double)
@PostMapping("/products")
fun createProduct(@RequestBody product: Product): Product {
// сохраняем product в БД
return product
}
4.5. @PathVariable
Сигнатура: @Target(AnnotationTarget.VALUE_PARAMETER) annotation class PathVariable(val value: String = "")
Что делает: Извлекает значение из шаблона URI.
@GetMapping("/users/{id}")
fun getUserById(@PathVariable id: Long): String {
return "User with id: $id"
}
4.6. @Service
Сигнатура: @Target(AnnotationTarget.CLASS) annotation class Service
Что делает: Помечает класс как сервис (бизнес-логика). Spring автоматически создаёт бин этого класса.
@Service
class UserService(private val userRepository: UserRepository) {
fun findUser(id: Long): User? {
return userRepository.findById(id).orElse(null)
}
}
4.7. @Repository и JpaRepository
Сигнатура: interface JpaRepository<T, ID> : PagingAndSortingRepository<T, ID>
Что делает: @Repository помечает DAO-класс. JpaRepository предоставляет готовые CRUD-методы (save, findById, findAll, delete).
@Repository
interface UserRepository : JpaRepository<User, Long> {
fun findByName(name: String): List<User>
}
// Использование в сервисе:
@Service
class UserService(private val userRepository: UserRepository) {
fun saveUser(user: User): User = userRepository.save(user)
}
4.8. @ConfigurationProperties
Сигнатура: @Target(AnnotationTarget.CLASS) annotation class ConfigurationProperties(val prefix: String = "")
Что делает: Связывает свойства из application.properties или application.yml с классом Kotlin.
@ConfigurationProperties(prefix = "app")
@ConstructorBinding
data class AppProperties(
val name: String,
val version: String,
val features: List<String>
)
// application.yml:
// app:
// name: MyApp
// version: 1.0
// features:
// - auth
// - logging
4.9. @ExceptionHandler
Сигнатура: @Target(AnnotationTarget.FUNCTION) annotation class ExceptionHandler(vararg val value: KClass<out Throwable>)
Что делает: Обрабатывает исключения, выбрасываемые в контроллере. Позволяет вернуть кастомный HTTP-ответ.
@RestControllerAdvice
class GlobalExceptionHandler {
@ExceptionHandler(NoSuchElementException::class)
fun handleNotFound(ex: NoSuchElementException): ResponseEntity<Map<String, String>> {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(mapOf("error" to ex.message ?: "Resource not found"))
}
}
4.10. @Transactional
Сигнатура: @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) annotation class Transactional
Что делает: Управляет транзакциями базы данных. Метод выполняется в рамках
Также в библиотеке
Интернационализация (i18n) в JavaScript (Node.js): библиотека i18next
Мониторинг Node.js: инструменты и библиотеки для отслеживания производительности
Геолокация и карты в C++: обзор библиотек и инструментов