Весенний ботинок и котлин

Весенний ботинок и котлин

1. обзор

Еще в январе в экосистеме Spring было сделано большое объявление:Kotlin support is coming to Spring Framework 5. Это означает, что Spring Boot 2.x будет иметь первоклассную поддержку Kotlin.

Это, конечно, не является неожиданностью, так как команда в Pivotal известна принятием таких языков JVM, как Scala и Groovy.

Давайте создадим приложение Kotlin, используя приложение Spring Boot 2.x!

2. Настроить

2.1. Среда

Kotlin поддерживает разработку вIntelliJ,Eclipse иcommand line. Следуйте инструкциям по настройке среды, исходя из ваших предпочтений.

2.2. Настроить

Во-первых, давайте создадим проект Spring Boot 2 и изменим POM, чтобы он содержал записи, определяющие версии Java и Kotlin с зависимостями:


    org.jetbrains.kotlin
    kotlin-stdlib-jre8
    1.1.2


    org.jetbrains.kotlin
    kotlin-reflect
    1.1.2


    com.fasterxml.jackson.module
    jackson-module-kotlin
    1.1.2

Обратите внимание, что мы указываем расположение файлов для нашего исходного и тестового файлов Kotlin:

${project.basedir}/src/main/kotlin
${project.basedir}/src/test/kotlin

Если наши файлы Kotlin находятся в разных местах, вам нужно будет изменить эти записи в POM.

Для компиляции модулей и исходников Kotlin нам нужно использоватьkotlin-maven-plugin:


    kotlin-maven-plugin
    org.jetbrains.kotlin
    1.1.2
    
        
            spring
        
        1.8
    
    
        
            compile
            compile
            
                compile
            
        
        
            test-compile
            test-compile
            
                test-compile
            
        
    
    
        
            org.jetbrains.kotlin
            kotlin-maven-allopen
            1.1.2
        
    

Хорошо, теперь у нас есть все необходимое для создания нашего приложения Kotlin. Для справки: вы можете найти последние версииMaven Central (spring-boot-starter-web,kotlin-stdlib-jre8,kotlin-reflect,jackson-module-kotlin,test).

Затем давайте настроим контекст нашего приложения.

3. Контекст приложения

Давайте перейдем к некоторому коду Kotlin и напишем наш знакомый контекст приложения Spring Boot:

@SpringBootApplication
class KotlinDemoApplication

fun main(args: Array) {
    SpringApplication.run(KotlinDemoApplication::class.java, *args)
}

Мы видим знакомую нам аннотацию@SpringBootApplication. Это та же самая аннотация, которую мы использовали бы в классе Java.

Ниже у нас есть определение класса для нашего классаKotlinDemoApplication. В Kotlin область видимости по умолчанию для классов является общедоступной, поэтому мы можем опустить это. Кроме того, если у класса нет переменных и функций, он может быть объявлен без фигурных скобок. Итак, по сути, мы только что определили класс.

Переходя к методу. Это стандартный метод точки входа Java в Java:public static void main(String[] args).

Опять же, методы или функции общедоступны по умолчанию, поэтому нам не нужно объявлять это здесь. Дополнительноfunctions that do not return anything do not need to specify a void return type.

И, наконец,any function defined outside the body of a class is automatically static. Это делает эту функцию пригодной для запуска при запуске.

Теперь давайте запустим наше приложение из корневого каталога, используяmvn spring-boot: run. Приложение должно запуститься, и мы должны увидеть, что наше приложение работает на порту 8080.

Теперь давайте создадим контроллер.

4. контроллер

Давайте посмотрим, как добавить контроллер в нашу службу:

@RestController
class HelloController {

    @GetMapping("/hello")
    fun helloKotlin(): String {
        return "hello world"
    }
}

Не слишком сильно отличается от стандартного контроллера Spring, но, конечно, меньше кода. Давайте добавим тестовый класс и кейс для этого контроллера, чтобы проверить нашу работу:

@RunWith(SpringRunner::class)
@SpringBootTest(classes = arrayOf(KotlinDemoApplication::class),
  webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class KotlinDemoApplicationTests {

    @Autowired
    lateinit var testRestTemplate: TestRestTemplate

    @Test
    fun whenCalled_shouldReturnHello() {
        val result = testRestTemplate
          // ...
          .getForEntity("/hello", String::class.java)

        assertNotNull(result)
        assertEquals(result?.statusCode, HttpStatus.OK)
        assertEquals(result?.body, "hello world")
    }
}

Этот тест демонстрирует одну из очень мощных функций Kotlin - нулевую безопасность! Переменные Kotlin, которые могут быть нулевыми, должны быть объявлены с помощью ‘? Затем компилятор знает, что для доступа к этому свойству требуется защитное кодирование.

В нашем тестеTestRestTemplate определяется как тип, допускающий значение NULL, и каждый раз, когда мы обращаемся к нему, мы делаем это с помощью оператора объединения с нулевым значением «?». - который вернет null, если вызываемый объект имеет значение null.

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

Затем давайте добавим службу и интегрируем ее в наш контроллер.

5. обслуживание

Как вы уже, наверное, догадались, наш сервис будет довольно легко добавить в наш проект. Давайте сделаем это сейчас:

@Service
class HelloService {

    fun getHello(): String {
        return "hello service"
    }
}

Довольно простой сервис с единственной функцией, возвращающей строку. Затем давайте подключим наш сервис к контроллеру и используем его для возврата значения:

@RestController
class HelloController(val helloService: HelloService) {

    // ...

    @GetMapping("/hello-service")
    fun helloKotlinService(): String {
        return helloService.getHello()
    }
}

Ах, это выглядит красиво! В Kotlin главный конструктор может быть определен inline с объявлением класса. Мы опускаем аннотацию@Autowired в нашем конструкторе, потому что она уже давно не является обязательной.

Эти параметры автоматически преобразуются в поля в классе. Kotlin они называются свойствами. Здесь не определены геттеры или сеттеры; они создаются автоматически. Вы можете, конечно, переопределить эти значения по умолчанию, если хотите.

В Kotlin свойства в классах и переменные в функциях могут быть определены с помощьюvar илиval. Var indicates a mutable property, and val indicates a final one. Это позволяет компилятору проверять наличие незаконного доступа. Поскольку нашHelloService - синглтон, мы подключаем его какval, чтобы предотвратить мутацию.

Затем давайте добавим тест для этого метода контроллера:

@Test
fun whenCalled_shouldReturnHelloService() {
    var result = testRestTemplate
      // ...
      .getForEntity("/hello-service", String::class.java)

    assertNotNull(result)
    assertEquals(result?.statusCode, HttpStatus.OK)
    assertEquals(result?.body, "hello service")
}

Наконец, давайте посмотрим, как выглядит POJO в Котлине.

6. Класс данных Kotlin

В Java мы представляем объекты данных с простыми старыми объектами Java, POJO. В Kotlin у нас есть нечто, что позволяет нам выразить этот тип объекта более кратко - класс данных.

Давайте напишем объект данных, который нужно вернуть в наш контроллер:

data class HelloDto(val greeting: String)

Это был не трюк. Я ничего не пропускаю в нашем классе. С модификатором данных мы получаем много преимуществ. Это ключевое слово автоматически создает паруequals/hashcode, функциюtoString и функцию копирования. И все это из однострочника из 53 символов!

Теперь давайте добавим метод для возврата нашего нового класса данных:

// ...
@GetMapping("/hello-dto")
fun helloDto(): HelloDto {
    return HelloDto("Hello from the dto")
}

Модификатор данных не добавляет конструктор по умолчанию, что важно для некоторых библиотек, таких как Джексон. Для поддержки этого типа класса мы добавилиjackson-module-kotlin в наш файл POM для поддержки маршалинга. Это было сделано в разделе 2, и вы можете увидеть зависимость там.

Наконец, давайте добавим тест для этой функции контроллера:

@Test
fun whenCalled_shoudlReturnJSON() {
    val result = testRestTemplate
      // ...
      .getForEntity("/hello-dto", HelloDto::class.java)

    assertNotNull(result)
    assertEquals(result?.statusCode, HttpStatus.OK)
    assertEquals(result?.body, HelloDto("Hello from the dto"))
}

7. Заключение

В этой статье мы рассмотрели поддержку Kotlin в Spring Boot 2.x. Из примеров мы видели, что Kotlin может упростить и улучшить наши приложения, вынуждая нас писать более короткий и безопасный код.

Kotlin также поддерживает некоторые удивительные функции, такие как класс данных, расширения классов, и полностью совместим с существующим кодом Java. Это означает, что вы можете написать код Kotlin и вызывать его из ваших классов Java, и наоборот. Кроме того, Kotlin был построен с нуля, чтобы иметь фантастическую поддержку в IDE, и это так.

Есть много причин попробовать Kotlin, и теперь, когда Google и Spring поддерживают его, настало время проверить это. Дайте нам знать, что вы решили построить с его помощью!

Всегда можно найти исходный кодover on GitHub.