Введение в Micronaut Framework

Введение в Micronaut Framework

1. Что такое Микронавт

Micronaut - это фреймворк на основе JVM для создания легких модульных приложений. Разработано OCI, той же компанией, которая создала Grails,Micronaut is the latest framework designed to make creating microservices quick and easy.

Хотя Micronaut содержит некоторые функции, которые похожи на существующие фреймворки, такие как Spring, он также имеет некоторые новые функции, которые выделяют его. А благодаря поддержке Java, Groovy и Kotlin он предлагает различные способы создания приложений.

2. Основные характеристики

Одна из самых интересных особенностей Micronaut - это механизм внедрения зависимости от времени компиляции. Большинство фреймворков используют отражение и прокси-серверы для выполнения внедрения зависимостей во время выполнения. Micronaut, however, builds its dependency injection data at compile time. Результат - более быстрый запуск приложения и меньший объем памяти.

Another feature is its first class support for reactive programming, for both clients and servers. Выбор конкретной реактивной реализации оставлен на усмотрение разработчика, поскольку поддерживаются как RxJava, так и Project Reactor.

Micronaut также имеет несколько функций, которые делают его отличной платформой для разработки облачных приложений. It supports multiple service discovery tools such as Eureka and Consul, and also works with different distributed tracing systems such as Zipkin and Jaeger.с

Он также предоставляет поддержку для создания лямбда-функций AWS, что упрощает создание безсерверных приложений.

3. Начиная

Самый простой способ начать - использоватьSDKMAN:

> sdk install micronaut 1.0.0.RC2

При этом будут установлены все двоичные файлы, которые понадобятся нам для создания, тестирования и развертывания приложений Micronaut. Он также предоставляет инструмент CLI Micronaut, который позволяет нам легко начинать новые проекты.

Бинарные артефакты также доступны наSonatype иGitHub.

В следующих разделах мы рассмотрим некоторые особенности фреймворка.

4. Внедрение зависимости

Как упоминалось ранее, Micronaut обрабатывает внедрение зависимостей во время компиляции, которое отличается от большинства контейнеров IoC.

Тем не менее, это все ещеfully supports JSR-330 annotations, поэтому работа с bean-компонентами аналогична другим фреймворкам IoC.

Чтобы автоматически подключить компонент к нашему коду, мы используем@Inject:

@Inject
private EmployeeService service;

Аннотация@Inject работает так же, как@Autowired, и может использоваться для полей, методов, конструкторов и параметров.

По умолчанию все компоненты определены как прототип. Мы можем быстро создать одноэлементные bean-компоненты, используя@Singleton. . Если несколько классов реализуют один и тот же интерфейс bean-компонентов,@Primary можно использовать для их устранения:

@Primary
@Singleton
public class BlueCar implements Car {}

Аннотация@Requires может использоваться, когда bean-компоненты являются необязательными, или для выполнения автосоединения только при соблюдении определенных условий.

В этом отношении он очень похож на аннотации Spring Boot@Conditional:

@Singleton
@Requires(beans = DataSource.class)
@Requires(property = "enabled")
@Requires(missingBeans = EmployeeService)
@Requires(sdk = Sdk.JAVA, value = "1.8")
public class JdbcEmployeeService implements EmployeeService {}

5. Построение HTTP-сервера

Теперь давайте посмотрим на создание простого приложения HTTP-сервера. Для начала воспользуемся SDKMAN для создания проекта:

> mn create-app hello-world-server -build maven

Это создаст новый проект Java с использованием Maven в каталоге с именемhello-world-server.. Внутри этого каталога мы найдем исходный код нашего основного приложения, файл Maven POM и другие вспомогательные файлы для проекта.

Приложение по умолчанию, которое очень просто:

public class ServerApplication {
    public static void main(String[] args) {
        Micronaut.run(ServerApplication.class);
    }
}

5.1. Блокировка HTTP

Само по себе это приложение мало что дает. Давайте добавим контроллер с двумя конечными точками. Оба вернут приветствие, но один будет использовать HTTP-глаголGET, а другой -POST:

@Controller("/greet")
public class GreetController {

    @Inject
    private GreetingService greetingService;

    @Get("/{name}")
    public String greet(String name) {
        return greetingService.getGreeting() + name;
    }

    @Post(value = "/{name}", consumes = MediaType.TEXT_PLAIN)
    public String setGreeting(@Body String name) {
        return greetingService.getGreeting() + name;
    }
}

5.2. Реактивный ввод-вывод

По умолчанию Micronaut реализует эти конечные точки, используя традиционный блокирующий ввод / вывод. Однакоwe can quickly implement non-blocking endpoints by merely changing the return type to any reactive non-blocking type.

Например, с RxJava мы можем использоватьObservable. Аналогично, при использовании Reactor мы можем возвращать типы данныхMono илиFlux:

@Get("/{name}")
public Mono greet(String name) {
    return Mono.just(greetingService.getGreeting() + name);
}

Для блокирующих и неблокирующих конечных точек Netty является базовым сервером, используемым для обработки HTTP-запросов.

Обычно запросы обрабатываются в основном пуле потоков ввода / вывода, который создается при запуске, что делает их блокированными.

Однако, когда неблокирующий тип данных возвращается из конечной точки контроллера, Micronaut использует поток цикла событий Netty, делая весь запрос неблокирующим.

6. Построение HTTP-клиента

Теперь давайте создадим клиента, который будет использовать только что созданные конечные точки. Micronaut предоставляет два способа создания HTTP-клиентов:

  • Декларативный HTTP-клиент

  • Программный HTTP-клиент

6.1 Declarative HTTP Client

Первый и самый быстрый способ создания - это использование декларативного подхода:

@Client("/greet")
public interface GreetingClient {
    @Get("/{name}")
    String greet(String name);
}

Обратите внимание, какwe don’t implement any code to call our service. Вместо этого Micronaut понимает, как вызвать службу, используя подпись метода и предоставленные нами аннотации.

Чтобы протестировать этот клиент, мы можем создать тест JUnit, который использует API встроенного сервера для запуска встроенного экземпляра нашего сервера:

public class GreetingClientTest {
    private EmbeddedServer server;
    private GreetingClient client;

    @Before
    public void setup() {
        server = ApplicationContext.run(EmbeddedServer.class);
        client = server.getApplicationContext().getBean(GreetingClient.class);
    }

    @After
    public void cleanup() {
        server.stop();
    }

    @Test
    public void testGreeting() {
        assertEquals(client.greet("Mike"), "Hello Mike");
    }
}

6.2. Программный HTTP-клиент

У нас также есть возможность написать более традиционный клиент, если нам нужно больше контролировать его поведение и реализацию:

@Singleton
public class ConcreteGreetingClient {
   private RxHttpClient httpClient;

   public ConcreteGreetingClient(@Client("/") RxHttpClient httpClient) {
      this.httpClient = httpClient;
   }

   public String greet(String name) {
      HttpRequest req = HttpRequest.GET("/greet/" + name);
      return httpClient.retrieve(req).blockingFirst();
   }

   public Single greetAsync(String name) {
      HttpRequest req = HttpRequest.GET("/async/greet/" + name);
      return httpClient.retrieve(req).first("An error as occurred");
   }
}

HTTP-клиент по умолчанию использует RxJava, поэтому может легко работать с блокирующими или неблокирующими вызовами.

7. Микронавт CLI

Мы уже видели инструмент Micronaut CLI в действии выше, когда использовали его для создания нашего образца проекта.

В нашем случае мы создали отдельное приложение, но оно также имеет несколько других возможностей.

7.1. Проекты Федерации

In Micronaut, a federation is just a group of standalone applications that live under the same directory. Используя федерации, мы можем легко управлять ими вместе и гарантировать, что они имеют одинаковые значения по умолчанию и настройки.

Когда мы используем инструмент CLI для создания федерации, он принимает те же аргументы, что и командаcreate-app. Это создаст структуру проекта верхнего уровня, и каждое отдельное приложение будет создано в его подкаталоге оттуда.

7.2. Характеристики

When creating a standalone application or federation, we can decide which features our app needs. Это помогает обеспечить минимальный набор зависимостей, включенных в проект.

Мы указываем функции с помощью-features argument и предоставляем список имен функций, разделенных запятыми.

Мы можем найти список доступных функций, выполнив следующую команду:

> mn profile-info service

Provided Features:
--------------------
* annotation-api - Adds Java annotation API
* config-consul - Adds support for Distributed Configuration with Consul
* discovery-consul - Adds support for Service Discovery with Consul
* discovery-eureka - Adds support for Service Discovery with Eureka
* groovy - Creates a Groovy application
[...] More features available

7.3. Существующие проекты

We can also use the CLI tool to modify existing projects. Позволяет нам создавать компоненты, клиенты, контроллеры и многое другое. Когда мы запускаем командуmn из существующего проекта, у нас будет доступен новый набор команд:

> mn help
| Command Name         Command Description
-----------------------------------------------
create-bean            Creates a singleton bean
create-client          Creates a client interface
create-controller      Creates a controller and associated test
create-job             Creates a job with scheduled method

8. Заключение

В этом кратком введении в Micronaut мы увидели, насколько легко создавать как блокирующие, так и неблокирующие HTTP-серверы и клиенты. Также мы изучили некоторые особенности его CLI.

Но это только небольшой вкус функций, которые он предлагает. Также имеется полная поддержка функций без серверов, обнаружение служб, распределенная трассировка, мониторинг и метрики, распределенная конфигурация и многое другое.

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

Как всегда, мы можем найти примеры кода выше в нашемGitHub repo.