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.