Spring Boot e Kotlin

1. Panoramica

A gennaio è stato fatto un grande annuncio nell'ecosistema Spring: il supporto di Kotlin sta arrivando per Spring Framework 5 . Ciò significa che Spring Boot 2.x avrà il supporto di prima classe per Kotlin.

Questo ovviamente non è inaspettato, poiché il team di Pivotal è noto per l'accettazione di linguaggi JVM come Scala e Groovy.

Creiamo un'app Kotlin utilizzando l'app Spring Boot 2.x!

2. Configurazione

2.1. Ambiente

Kotlin supporta lo sviluppo in IntelliJ, Eclipse e sulla riga di comando. Segui le indicazioni per configurare il tuo ambiente, in base alle tue preferenze.

2.2. Impostare

Per prima cosa, creiamo un progetto Spring Boot 2 e modifichiamo il POM per contenere voci che specificano le versioni di Java e Kotlin con le dipendenze:

 org.jetbrains.kotlin kotlin-stdlib-jre8 1.2.71   org.jetbrains.kotlin kotlin-reflect 1.2.71   com.fasterxml.jackson.module jackson-module-kotlin 2.9.9 

Tieni presente che stiamo specificando i percorsi dei file per i nostri file sorgente e di test Kotlin:

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

Se i nostri file Kotlin si trovano in posizioni diverse, sarà necessario modificare queste voci nel POM.

Per compilare moduli e sorgenti Kotlin, dobbiamo usare 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   

Bene, ora abbiamo tutto ciò di cui abbiamo bisogno per creare la nostra applicazione Kotlin. Per riferimento: puoi trovare le ultime versioni di Maven Central (spring-boot-starter-web, kotlin-stdlib-jre8, kotlin-reflection, jackson-module-kotlin, test).

Successivamente, configuriamo il nostro contesto dell'applicazione.

3. Contesto dell'applicazione

Facciamo un salto in un po 'di codice Kotlin e scriviamo il nostro familiare contesto dell'applicazione Spring Boot:

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

Vediamo la nostra nota annotazione @SpringBootApplication . Questa è la stessa annotazione che useremmo in una classe Java.

Di seguito abbiamo una definizione di classe per la nostra classe KotlinDemoApplication . In Kotlin l'ambito predefinito per le classi è pubblico, quindi possiamo ometterlo. Inoltre, se una classe non ha variabili e funzioni, può essere dichiarata senza parentesi graffe. Quindi, in sostanza, abbiamo appena definito una classe.

Passiamo al metodo. Questo è il metodo standard del punto di ingresso di Java, in Java: public static void main (String [] args).

Di nuovo, i metodi o le funzioni sono pubblici per impostazione predefinita, quindi non è necessario dichiararlo qui. Inoltre, le funzioni che non restituiscono nulla non devono specificare un tipo di ritorno void.

Infine, qualsiasi funzione definita al di fuori del corpo di una classe è automaticamente statica . Ciò rende questa funzione idonea per l'esecuzione all'avvio.

Ora eseguiamo la nostra applicazione dalla directory principale utilizzando mvn spring-boot: run . L'applicazione dovrebbe avviarsi e dovremmo vedere la nostra applicazione in esecuzione sulla porta 8080.

Quindi, costruiamo un controller.

4. Controller

Diamo un'occhiata all'aggiunta di un controller al nostro servizio:

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

Non molto diverso da un controller Spring standard ma sicuramente meno codice. Aggiungiamo una classe di test e un caso per questo controller per convalidare il nostro lavoro:

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

Questo test mostra una delle caratteristiche molto potenti di Kotlin: la sicurezza nulla! Le variabili di Kotlin che possono essere nulle devono essere dichiarate utilizzando "?". Il compilatore sa quindi che è necessaria una codifica difensiva prima di accedere a quella proprietà.

Nel nostro test, TestRestTemplate è definito come un tipo nullable e ogni volta che vi accediamo, lo facciamo utilizzando l'operatore di coalescenza null "?". - che restituirà null se l'oggetto chiamato è null.

Ciò chiarisce l'uso dei valori nulli nel programma e obbliga gli sviluppatori a scrivere codice sicuro quando lavorano con essi.

Successivamente, aggiungiamo un servizio e lo integriamo nel nostro controller.

5. Servizio

Come probabilmente puoi intuire ora, il nostro servizio sarà abbastanza facile da aggiungere al nostro progetto. Facciamolo ora:

@Service class HelloService { fun getHello(): String { return "hello service" } }

Servizio piuttosto semplice qui con una singola funzione che restituisce una stringa. Successivamente, colleghiamo il nostro servizio al controller e usiamolo per restituire un valore:

@RestController class HelloController(val helloService: HelloService) { // ... @GetMapping("/hello-service") fun helloKotlinService(): String { return helloService.getHello() } }

Ahh, sembra carino! In Kotlin il costruttore principale può essere definito in linea con la dichiarazione della classe. Abbiamo omesso l' annotazione @Autowired dal nostro costruttore perché non è obbligatoria da un po 'di tempo.

Questi parametri vengono convertiti automaticamente in campi nella classe. Kotlin si chiamano proprietà. Non ci sono getter o setter definiti; vengono creati automaticamente. Ovviamente puoi sovrascrivere queste impostazioni predefinite se lo desideri.

In Kotlin, properties in classes and variables in functions can be defined using var or val. Var indicates a mutable property, and val indicates a final one. This allows the compiler to check for illegal access. Since our HelloService is a singleton, we wire it up as a val to prevent mutation.

Next, let's add a test for this controller method:

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

Lastly, let's look at what a POJO looks like in Kotlin.

6. Kotlin Data Class

In Java, we represent data objects with plain old Java objects, the POJO. In Kotlin we have something that lets us express this type of object more concisely – a data class.

Let's write a data object to return in our controller:

data class HelloDto(val greeting: String)

That was no trick. I'm not omitting anything from our class. With the data modifier, we get a lot of benefits. This keyword automatically creates an equals/hashcode pair, a toString function, and a copy function. All that from a 53 character one-liner!

Now let's add a method to return our new data class:

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

The data modifier does not add a default constructor, which is important for certain libraries like Jackson. To support this type of class we have added the jackson-module-kotlin to our POM file to support marshaling. This was done during section 2, and you can see the dependency there.

Finally, let's add a test for this controller function:

@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. Conclusion

In questo articolo, abbiamo esaminato il supporto di Kotlin in Spring Boot 2.x. Abbiamo visto dagli esempi che Kotlin potrebbe semplificare e migliorare le nostre applicazioni costringendoci a scrivere codice più breve e più sicuro.

Kotlin supporta anche alcune funzionalità sorprendenti come la classe di dati, le estensioni di classe ed è completamente compatibile con il codice Java esistente. Ciò significa che puoi scrivere codice Kotlin e chiamarlo dalle tue classi Java e viceversa. Inoltre, Kotlin è stato costruito da zero per avere un supporto fantastico in un IDE, e lo fa.

Ci sono molti motivi per provare Kotlin e, con Google e Spring che lo supportano, ora è il momento di provarlo. Facci sapere cosa hai deciso di costruire usandolo!

Puoi sempre trovare il codice sorgente su GitHub.