Привет, Хабр!

Micronaut — фреймворк для ЯП Groovy. Он предназначен для создания микросервисов и серверных приложений на JVM. Он был разработан с учетом всех недостатков и ограничений предыдущих фреймворков, таких как Spring и Grails.

В статье рассмотрим, как работать в Groovy с Micronaut на практическом примере.

Начало работы

Для работы с Micronaut требуется JDK версии 17 или выше. Можно загрузить JDK с оф. сайта Oracle или использовать одну из альтернативных дистрибуций, таких как OpenJDK.

После установки JDK желательно проверить, что переменная окружения JAVA_HOME настроена правильно:

export JAVA_HOME=/path/to/your/jdk
export PATH=$JAVA_HOME/bin:$PATH

Micronaut CLI позволяет создавать проекты и управлять ими, установим:

sdk install micronaut

Для юзеров Windows вдобавок стоит установить SDKMAN! и использовать его для установки Micronaut CLI.

Для создания нового проекта Micronaut на Groovy есть команда в Micronaut CLI:

mn create-app example.micronaut.micronautguide --lang=groovy

Команда создаст новый проект с именем example.micronaut.micronautguide, использующий Groovy в качестве основного ЯП.

После создания проекта будет следующая директория и файлы:

example.micronaut.micronautguide
├── build.gradle
├── src
│   ├── main
│   │   ├── groovy
│   │   │   └── example
│   │   │       └── micronaut
│   │   │           └── Application.groovy
│   │   └── resources
│   │       └── application.yml
│   └── test
│       ├── groovy
│       │   └── example
│       │       └── micronaut
│       │           └── ApplicationSpec.groovy
│       └── resources
├── gradle
│   └── wrapper
│       └── gradle-wrapper.properties
└── gradlew
└── gradlew.bat
  • build.gradle: файл конфигурации Gradle, в котором определяются зависимости и настройки сборки проекта.

  • src/main/groovy: основная директория для исходного кода на Groovy. Здесь находится главный класс приложения Application.groovy.

  • src/main/resources: директория для ресурсов приложения, включая файл конфигурации application.yml.

  • src/test/groovy: директория для тестового кода на Groovy. Здесь находится тестовый класс ApplicationSpec.groovy.

  • gradle и gradlew: скрипты и конфигурации для сборки проекта с помощью Gradle.

Пошаговое создание микросервиса

Откроем файл build.gradle и там убедимся, что зависимости для Groovy и Micronaut добавлены:

plugins {
    id 'groovy'
    id 'io.micronaut.application' version '3.0.0'
}

version '0.1'
group 'example.micronaut'

repositories {
    mavenCentral()
}

dependencies {
    implementation "io.micronaut:micronaut-runtime"
    implementation "io.micronaut.groovy:micronaut-runtime-groovy"
    testImplementation "io.micronaut.test:micronaut-test-spock"
    testImplementation "org.spockframework:spock-core"
}

micronaut {
    runtime "netty"
    testRuntime "spock"
    processing {
        incremental true
        annotations "example.micronaut.*"
    }
}

Здесь подключаем необходимые плагины и зависимости. Плагин groovy позволяет использовать Groovy в проекте, а io.micronaut.application предоставляет возможности для работы с Micronaut.

Создание основного приложения

Создаем файл src/main/groovy/example/micronaut/Application.groovy:

package example.micronaut

import io.micronaut.runtime.Micronaut
import groovy.transform.CompileStatic

@CompileStatic
class Application {

    static void main(String[] args) {
        Micronaut.run(Application, args)
    }
}

Файл содержит основной класс приложения, который запускает Micronaut. Аннотация @CompileStatic апдейтит производительность за счет статической компиляции Groovy-кода.

Создание контроллера

Создаем контроллер src/main/groovy/example/micronaut/HelloController.groovy:

package example.micronaut

import groovy.transform.CompileStatic
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.http.annotation.Produces
import io.micronaut.http.MediaType

@CompileStatic
@Controller("/hello")
class HelloController {

    @Get
    @Produces(MediaType.TEXT_PLAIN)
    String index() {
        "Hello World"
    }
}

Контроллер обрабатывает GET-запросы на /hello и возвращает строку "Hello World". Аннотация @Controller указывает, что этот класс является контроллером, а аннотация @Get указывает, что метод index обрабатывает GET-запросы.

Настроим конфигурацию приложения

Открываем файл src/main/resources/application.yml и добавляем конфигурацию:

micronaut:
  application:
    name: micronautguide

Файл конфигурации задает имя приложения.

Создание теста для контроллера

Создаем файл src/test/groovy/example/micronaut/HelloControllerSpec.groovy:

package example.micronaut

import io.micronaut.http.HttpRequest
import io.micronaut.http.client.HttpClient
import io.micronaut.http.client.annotation.Client
import io.micronaut.test.extensions.spock.annotation.MicronautTest
import spock.lang.Specification

import jakarta.inject.Inject

@MicronautTest
class HelloControllerSpec extends Specification {

    @Inject
    @Client("/")
    HttpClient client

    void "test hello world response"() {
        when:
        HttpRequest request = HttpRequest.GET('/hello')
        String rsp = client.toBlocking().retrieve(request)

        then:
        rsp == "Hello World"
    }
}

Тст проверяет, что контроллер возвращает строку "Hello World" при GET-запросе на /hello. Аннотация @MicronautTest указывает, что это тест для Micronaut-приложения.

Добавим новый контроллер для работы с книгами и расширим функционал микросервиса.

Создаем файл src/main/groovy/example/micronaut/BookController.groovy:

package example.micronaut

import groovy.transform.CompileStatic
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.http.annotation.Produces
import io.micronaut.http.MediaType

@CompileStatic
@Controller("/books")
class BookController {

    @Get
    @Produces(MediaType.APPLICATION_JSON)
    List<Book> listBooks() {
        [
            new Book("The Stand", "Stephen King"),
            new Book("The Hobbit", "J.R.R. Tolkien")
        ]
    }
}

@CompileStatic
class Book {
    String title
    String author

    Book(String title, String author) {
        this.title = title
        this.author = author
    }
}

Контроллер обрабатывает GET-запросы на /books и возвращает список книг в формате JSON. Также создали класс Book для представления книги.

Создаем файл src/test/groovy/example/micronaut/BookControllerSpec.groovy:

package example.micronaut

import io.micronaut.http.HttpRequest
import io.micronaut.http.client.HttpClient
import io.micronaut.http.client.annotation.Client
import io.micronaut.test.extensions.spock.annotation.MicronautTest
import spock.lang.Specification

import jakarta.inject.Inject

@MicronautTest
class BookControllerSpec extends Specification {

    @Inject
    @Client("/")
    HttpClient client

    void "test list books response"() {
        when:
        HttpRequest request = HttpRequest.GET('/books')
        List books = client.toBlocking().retrieve(request, List)

        then:
        books.size() == 2
        books[0].title == "The Stand"
        books[1].title == "The Hobbit"
    }
}

Тест проверяет, что контроллер возвращает список из двух книг.

Запуск и тестирование приложения

Сборка и запуск приложения:

./gradlew run

Запуск тестов:

./gradlew test

После выполнения всех шагов приложение будет запущено и доступно по адресу http://localhost:8080/hello, возвращая текст "Hello World", а также по адресу http://localhost:8080/books, возвращая список книг. Тесты проверят правильность работы контроллеров.


Micronaut и Groovy — мощное сочетание для создания микросервисов. Подробнее с библиотекой можно ознакомиться здесь.

Материал подготовлен в рамках онлайн‑курса «Groovy Developer».

Комментарии (2)


  1. PrinceKorwin
    11.07.2024 04:54
    +3

    Вот вы показали Hello World на этом фреймворке и он вообще никак не отличается от того, что предлагает Spring / Grails.

    Он был разработан с учетом всех недостатков и ограничений предыдущих фреймворков, таких как Spring и Grails.

    Можете показать что это за недостатки и ограничения и как их учел Micronaut?


  1. marknefedov
    11.07.2024 04:54

    Расскажите пожалуйста в чем смысл Groovy? Последний раз я его трогал, только в качестве DSL в Jenkins и как язык он показался достаточно неказистым.

    Что он может, что не сделать в том же Kotlin?