Андроида много не бывает, но пора взглянуть, как Kotlin может работать в других средах. Например, в таком классическом Enterprise-решении, как Rest-сервис

Для начала, вот мой сборочный файл (я решил использовать gradle):

buildscript {
	ext {
		kotlinVersion = '1.2.71'
		springBootVersion = '2.0.5.RELEASE'
	}
	repositories {
		mavenCentral()
	}
	dependencies {
		classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
		classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
		classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}")
                classpath("org.jetbrains.kotlin:kotlin-noarg:${kotlinVersion}")
	}
}

apply plugin: 'kotlin'
apply plugin: 'kotlin-spring'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: "kotlin-jpa"

group = 'com.criticalgnome'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
compileKotlin {
	kotlinOptions {
		freeCompilerArgs = ["-Xjsr305=strict"]
		jvmTarget = "1.8"
	}
}
compileTestKotlin {
	kotlinOptions {
		freeCompilerArgs = ["-Xjsr305=strict"]
		jvmTarget = "1.8"
	}
}

repositories {
	mavenCentral()
}


dependencies {
	compile('org.springframework.boot:spring-boot-starter-data-jpa')
	compile('org.springframework.boot:spring-boot-starter-mustache')
	compile('org.springframework.boot:spring-boot-starter-web')
	compile('com.fasterxml.jackson.module:jackson-module-kotlin')
	compile("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
	compile("org.jetbrains.kotlin:kotlin-reflect")
	runtime('com.h2database:h2')
	testCompile('org.springframework.boot:spring-boot-starter-test')
}

Пара замечаний: используется SpringBoot с плагинами Web, Mustache и H2 database. Применил плагин kotlin-jpa для создания пустых конструкторов в entity-объектах. Без этого не заведётся Hibernate.

Теперь к главному. Стартовый класс донельзя лаконичен:

@SpringBootApplication
class SpringBootKotlinDemoApplication

fun main(args: Array<String>) {
    runApplication<SpringBootKotlinDemoApplication>(*args)
}

Теперь на очереди entity-объект. Для теста он будет очень простым, но поддерживаются все возможные зависимости, сколь угодно сложные:

@Entity
data class User(
        @Id @GeneratedValue val id: Long,
        val firstName: String,
        val lastName: String
)

Теперь время добавить repository. Как и при использовании Java, он очень минималистичен (по крайней мере, при использовании только стандартных CRUD-операций):

@Repository
interface UserRepository: JpaRepository<User, Long>

Настало время для слоя бизнес-логики. Я зачем-то решил сделать по уму и сразу вынес стандартные операции в отдельный базовый класс. Вот эти ребята:

open class BaseService<T>(private val repository: JpaRepository<T, Long>) {
    fun getOne(id: Long): T = repository.getOne(id)
    fun getAll(pageable: Pageable): Page<T> = repository.findAll(pageable)
    fun save(t: T): T = repository.save(t)
    fun delete(id: Long) = repository.deleteById(id)
    fun count(): Long = repository.count()
}
@Service
class UserService(@Autowired private val userRepository: UserRepository): BaseService<User>(userRepository)

Теперь добавлю контроллер. Раз уж пустился во все тяжкие с базовым классом у сервиса, проделаю тот же трюк и здесь:

open class BaseController<T>(private val service: BaseService<T>) {
    @GetMapping("{id}")    fun getOne(@PathVariable id: Long): T = service.getOne(id)
    @GetMapping            fun getAll(pageable: Pageable): Page<T> = service.getAll(pageable)
    @PostMapping           fun create(@RequestBody t: T): T = service.save(t)
    @PutMapping            fun update(@RequestBody t: T): T = service.save(t)
    @DeleteMapping("{id}") fun delete(@PathVariable id: Long) = service.delete(id)
    @GetMapping("count")   fun count(): Long = service.count()
}
@RestController
@RequestMapping("users")
class UserController(@Autowired private val userService: UserService): BaseController<User, Long>(userService)

И это всё. Можно запускать и развлекаться. Весь код как всегда положил на свой GitLab, а то GitHub сегодня ведёт себя странно 🙁

Добавить комментарий

Закрыть меню