Bota de Primavera e Kotlin

Bota de Primavera e Kotlin

1. Visão geral

Um grande anúncio foi feito em janeiro no ecossistema Spring:Kotlin support is coming to Spring Framework 5. Isso significa que o Spring Boot 2.x terá suporte de primeira classe ao Kotlin.

Obviamente, isso não é inesperado, pois a equipe do Pivotal é conhecida pela aceitação de idiomas da JVM, como Scala e Groovy.

Vamos construir um aplicativo Kotlin usando o aplicativo Spring Boot 2.x!

2. Configuração

2.1. Meio Ambiente

Kotlin oferece suporte ao desenvolvimento emIntelliJ,Eclipse e emcommand line. Siga as instruções para configurar seu ambiente, com base em suas preferências.

2.2. Configuração

Primeiro, vamos criar um projeto Spring Boot 2 e modificar o POM para conter entradas que especificam as versões de Java e Kotlin com as dependências:


    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

Observe que estamos especificando os locais dos arquivos de origem e de teste do Kotlin:

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

Se nossos arquivos Kotlin estiverem em locais diferentes, você precisará modificar essas entradas no POM.

Para compilar módulos e fontes Kotlin, precisamos usarkotlin-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
        
    

Tudo bem, agora temos tudo o que precisamos para criar nosso aplicativo Kotlin. Para referência: você pode encontrar as versões mais recentes deMaven Central (spring-boot-starter-web,kotlin-stdlib-jre8,kotlin-reflect,jackson-module-kotlin,test).

A seguir, vamos configurar nosso contexto de aplicativo.

3. Contexto do Aplicativo

Vamos pular para algum código Kotlin e escrever nosso contexto de aplicativo Spring Boot familiar:

@SpringBootApplication
class KotlinDemoApplication

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

Vemos nossa anotação familiar@SpringBootApplication. Essa é a mesma anotação que usamos em uma classe Java.

Abaixo disso, temos uma definição de classe para nossa classeKotlinDemoApplication. No Kotlin, o escopo padrão para as classes é público, para que possamos omitir isso. Além disso, se uma classe não tiver variáveis ​​e funções, ela poderá ser declarada sem chaves. Então, em essência, acabamos de definir uma classe.

Passando para o método Este é o método de ponto de entrada Java padrão, em Java:public static void main(String[] args).

Novamente, métodos ou funções são públicos por padrão, portanto, não precisamos declarar isso aqui. Além disso,functions that do not return anything do not need to specify a void return type.

E finalmente,any function defined outside the body of a class is automatically static. Isso torna essa função qualificada para execução de inicialização.

Agora vamos executar nosso aplicativo a partir do diretório raiz usandomvn spring-boot: run. O aplicativo deve iniciar e devemos ver nosso aplicativo em execução na porta 8080.

A seguir, vamos construir um controlador.

4. Controlador

Vamos dar uma olhada em como adicionar um controlador ao nosso serviço:

@RestController
class HelloController {

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

Não muito diferente de um controlador Spring padrão, mas certamente menos código. Vamos adicionar uma classe de teste e um caso para este controlador para validar nosso trabalho:

@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")
    }
}

Este teste mostra um dos recursos muito poderosos do Kotlin - segurança nula! Variáveis ​​Kotlin que podem ser nulas devem ser declaradas usando ‘? '. O compilador então sabe que a codificação defensiva é necessária antes de acessar essa propriedade.

Em nosso teste,TestRestTemplate é definido como um tipo anulável, e cada vez que o acessamos, o fazemos usando o operador de coalescência nulo “?”. - que retornará nulo se o objeto chamado for nulo.

Isso esclarece o uso de valores nulos no programa e força os desenvolvedores a escrever código seguro ao trabalhar com eles.

A seguir, vamos adicionar um serviço e integrá-lo ao nosso controlador.

5. Serviço

Como você provavelmente já deve adivinhar agora, nosso serviço será muito fácil de adicionar ao nosso projeto. Vamos fazer isso agora:

@Service
class HelloService {

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

Serviço bastante simples aqui com uma única função retornando uma String. A seguir, vamos conectar nosso serviço ao controlador e usá-lo para retornar um valor:

@RestController
class HelloController(val helloService: HelloService) {

    // ...

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

Ahh, isso parece legal! No Kotlin, o construtor principal pode ser definido em linha com a declaração da classe. Omitimos a anotação@Autowired de nosso construtor porque ela não é obrigatória há algum tempo.

Esses parâmetros são automaticamente convertidos em campos na classe. Kotlin eles são chamados de propriedades. Não há getters ou setters definidos; eles são criados automaticamente. Obviamente, você pode substituir esses padrões, se desejar.

No Kotlin, propriedades em classes e variáveis ​​em funções podem ser definidas usandovar ouval. Var indicates a mutable property, and val indicates a final one. Isso permite que o compilador verifique se há acesso ilegal. Como nossoHelloService é um singleton, conectamos como umval para evitar a mutação.

A seguir, vamos adicionar um teste para este método de controlador:

@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")
}

Por fim, vejamos como é um POJO em Kotlin.

6. Classe de dados Kotlin

Em Java, representamos objetos de dados com objetos Java simples e antigos, o POJO. No Kotlin, temos algo que nos permite expressar esse tipo de objeto de forma mais concisa - uma classe de dados.

Vamos escrever um objeto de dados para retornar em nosso controlador:

data class HelloDto(val greeting: String)

Isso não foi truque. Não estou omitindo nada da nossa aula. Com o modificador de dados, obtemos muitos benefícios. Esta palavra-chave cria automaticamente um parequals/hashcode, uma funçãotoString e uma função de cópia. Tudo isso em uma única linha de 53 caracteres!

Agora vamos adicionar um método para retornar nossa nova classe de dados:

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

O modificador de dados não adiciona um construtor padrão, o que é importante para determinadas bibliotecas como Jackson. Para oferecer suporte a esse tipo de classe, adicionamosjackson-module-kotlin ao nosso arquivo POM para oferecer suporte ao empacotamento. Isso foi feito durante a seção 2 e você pode ver a dependência lá.

Finalmente, vamos adicionar um teste para esta função do controlador:

@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. Conclusão

Neste artigo, vimos o suporte ao Kotlin no Spring Boot 2.x. Vimos a partir de exemplos que o Kotlin poderia simplificar e aprimorar nossos aplicativos, forçando-nos a escrever código mais curto e seguro.

O Kotlin também suporta alguns recursos incríveis, como a classe de dados, extensões de classe e é totalmente compatível com o código Java existente. Isso significa que você pode escrever o código Kotlin e chamá-lo de suas classes Java e vice-versa. Além disso, o Kotlin foi construído desde o início para oferecer suporte fantástico em um IDE, e ele possui.

Existem muitas razões para experimentar o Kotlin, e com o Google e o Spring fazendo o backup, agora é a hora de conferir. Deixe-nos saber o que você decidiu construir usando-o!

Sempre, você pode encontrar o código-fonteover on GitHub.