Spring Boot et Kotlin

Botte de printemps et Kotlin

1. Vue d'ensemble

Une grande annonce a été faite en janvier dans l'écosystème Spring:Kotlin support is coming to Spring Framework 5. Cela signifie que Spring Boot 2.x aura un support de première classe pour Kotlin.

Ceci n’est bien sûr pas surprenant, car l’équipe de Pivotal est connue pour l’acceptation des langages JVM tels que Scala et Groovy.

Créons une application Kotlin à l'aide de l'application Spring Boot 2.x!

2. Installer

2.1. Environnement

Kotlin prend en charge le développement dansIntelliJ,Eclipse et sur lescommand line. Suivez les instructions pour configurer votre environnement en fonction de vos préférences.

2.2. Installer

Tout d'abord, créons un projet Spring Boot 2 et modifions le POM pour contenir des entrées spécifiant les versions de Java et Kotlin avec les dépendances:


    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

Notez que nous spécifions les emplacements de fichiers pour nos fichiers source et de test Kotlin:

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

Si nos fichiers Kotlin se trouvent à des emplacements différents, vous devrez modifier ces entrées dans le POM.

Pour compiler les modules et les sources Kotlin, nous devons utiliserkotlin-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
        
    

Bon, nous avons maintenant tout ce dont nous avons besoin pour construire notre application Kotlin. Pour référence: vous pouvez trouver les dernières versions deMaven Central (spring-boot-starter-web,kotlin-stdlib-jre8,kotlin-reflect,jackson-module-kotlin,test).

Ensuite, configurons notre contexte d'application.

3. Contexte d'application

Passons au code Kotlin et écrivons notre contexte familier d'application Spring Boot:

@SpringBootApplication
class KotlinDemoApplication

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

Nous voyons notre annotation familière@SpringBootApplication. C'est la même annotation que nous utiliserions dans une classe Java.

En dessous, nous avons une définition de classe pour notre classeKotlinDemoApplication. Dans Kotlin, la portée par défaut des classes est publique, ce qui permet de l'omettre. De plus, si une classe n'a pas de variables ni de fonctions, elle peut être déclarée sans accolades. Donc, en substance, nous venons de définir une classe.

Passons à la méthode. Il s'agit de la méthode de point d'entrée Java standard, en Java:public static void main(String[] args).

Encore une fois, les méthodes ou fonctions sont publiques par défaut, nous n’avons donc pas à le déclarer ici. De plus,functions that do not return anything do not need to specify a void return type.

Et enfin,any function defined outside the body of a class is automatically static. Cela rend cette fonction éligible pour l'exécution de démarrage.

Maintenant, exécutons notre application à partir du répertoire racine en utilisantmvn spring-boot: run. L'application devrait démarrer et notre application devrait s'exécuter sur le port 8080.

Ensuite, créons un contrôleur.

4. Manette

Jetons un coup d'œil à l'ajout d'un contrôleur à notre service:

@RestController
class HelloController {

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

Pas très différent d'un contrôleur Spring standard mais certainement moins de code. Ajoutons une classe de test et un cas pour ce contrôleur afin de valider notre travail:

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

Ce test montre l'une des fonctionnalités très puissantes de Kotlin: la sécurité nulle! Les variables Kotlin pouvant être nulles doivent être déclarées à l'aide de '?'. Le compilateur sait alors que le codage défensif est requis avant d'accéder à cette propriété.

Dans notre test,TestRestTemplate est défini comme un type Nullable, et chaque fois que nous y accédons, nous le faisons en utilisant l'opérateur de fusion nul «?». - qui renverra null si l'objet appelé est nul.

Cela clarifie l'utilisation des valeurs NULL dans le programme et oblige les développeurs à écrire du code sécurisé lorsqu'ils travaillent avec eux.

Ensuite, ajoutons un service et intégrons-le dans notre contrôleur.

5. Un service

Comme vous pouvez probablement le deviner, notre service sera assez facile à ajouter à notre projet. Faisons-le maintenant:

@Service
class HelloService {

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

Service assez simple ici avec une seule fonction renvoyant une chaîne. Ensuite, connectons notre service au contrôleur et utilisons-le pour renvoyer une valeur:

@RestController
class HelloController(val helloService: HelloService) {

    // ...

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

Ahh, ça a l'air bien! Dans Kotlin, le constructeur principal peut être défini en ligne avec la déclaration de classe. Nous avons omis l’annotation@Autowired de notre constructeur car elle n’est pas obligatoire depuis un certain temps.

Ces paramètres sont automatiquement convertis en champs de la classe. Kotlin, ils sont appelés propriétés. Il n'y a pas de getters ou setters définis; ils sont créés automatiquement. Vous pouvez bien sûr remplacer ces valeurs par défaut si vous le souhaitez.

Dans Kotlin, les propriétés dans les classes et les variables dans les fonctions peuvent être définies à l'aide devar ouval. Var indicates a mutable property, and val indicates a final one. Cela permet au compilateur de vérifier les accès illégaux. Puisque notreHelloService est un singleton, nous le connectons en tant queval pour éviter la mutation.

Ensuite, ajoutons un test pour cette méthode de contrôleur:

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

Enfin, voyons à quoi ressemble un POJO à Kotlin.

6. Classe de données Kotlin

En Java, nous représentons des objets de données avec de vieux objets Java, le POJO. Dans Kotlin, nous avons quelque chose qui nous permet d’exprimer ce type d’objet de manière plus concise: une classe de données.

Écrivons un objet de données à renvoyer dans notre contrôleur:

data class HelloDto(val greeting: String)

Ce n'était pas un truc. Je n’omets rien de notre classe. Avec le modificateur de données, nous obtenons de nombreux avantages. Ce mot-clé crée automatiquement une paireequals/hashcode, une fonctiontoString et une fonction de copie. Tout cela à partir d'une ligne unique de 53 personnages!

Ajoutons maintenant une méthode pour renvoyer notre nouvelle classe de données:

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

Le modificateur de données n'ajoute pas de constructeur par défaut, ce qui est important pour certaines bibliothèques comme Jackson. Pour prendre en charge ce type de classe, nous avons ajouté lesjackson-module-kotlin à notre fichier POM pour prendre en charge le marshaling. Cela a été fait au cours de la section 2, et vous pouvez voir la dépendance ici.

Enfin, ajoutons un test pour cette fonction de contrôleur:

@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

Dans cet article, nous avons examiné la prise en charge de Kotlin dans Spring Boot 2.x. Nous avons vu dans des exemples que Kotlin pourrait simplifier et améliorer nos applications en nous obligeant à écrire un code plus court et plus sûr.

Kotlin prend également en charge certaines fonctionnalités étonnantes telles que la classe de données, les extensions de classe et est entièrement compatible avec le code Java existant. Cela signifie que vous pouvez écrire du code Kotlin et l'appeler à partir de vos classes Java et inversement. En outre, Kotlin a été conçu dès le départ pour offrir un support fantastique dans un environnement de développement intégré.

Il y a beaucoup de raisons d'essayer Kotlin, et avec Google et Spring qui le soutiennent, le moment est venu de l'examiner. Dites-nous ce que vous avez décidé de construire en l'utilisant!

Toujours, vous pouvez trouver le code sourceover on GitHub.