Рубрики
Без рубрики

Введение в структуру Micronaut

Краткое введение в платформу Micronaut и как создать простое веб – приложение.

Автор оригинала: Michael Pratt.

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

Micronaut -это платформа на базе JVM для создания легких модульных приложений. Разработанный OCI, той же компанией, которая создала Grails, Micronaut-это новейший фреймворк, предназначенный для быстрого и легкого создания микросервисов .

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

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

Одной из самых интересных особенностей Micronaut является механизм внедрения зависимостей во время компиляции. Большинство фреймворков используют отражение и прокси для выполнения внедрения зависимостей во время выполнения. Micronaut, однако, строит свои данные внедрения зависимостей во время компиляции. Результатом является более быстрый запуск приложения и меньшие следы памяти.

Еще одной особенностью является его первоклассная поддержка реактивного программирования как для клиентов, так и для серверов. Выбор конкретной реактивной реализации остается за разработчиком, поскольку поддерживаются как RxJava, так и Project Reactor.

Micronaut также имеет несколько функций, которые делают его отличной платформой для разработки облачных приложений. Он поддерживает несколько инструментов обнаружения служб, таких как Eureka и Consul, а также работает с различными системами распределенной трассировки, такими как Zipkin и Jaeger.

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

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

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

> sdk install micronaut 1.0.0.RC2

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

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

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

4. Инъекция Зависимостей

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

Тем не менее, он по-прежнему полностью поддерживает аннотации JSR-330 , поэтому работа с бобами аналогична другим фреймворкам IoC.

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

@Inject
private EmployeeService service;

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

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

@Primary
@Singleton
public class BlueCar implements Car {}

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

В этом отношении он ведет себя очень похоже на 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

Само по себе это приложение мало что даст. Давайте добавим контроллер с двумя конечными точками. Оба вернут приветствие, но один будет использовать глагол GET HTTP, а другой – 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 реализует эти конечные точки с использованием традиционного блокирующего ввода-вывода. Однако мы можем быстро реализовать неблокирующие конечные точки, просто изменив тип возврата на любой реактивный неблокирующий тип .

Например, с 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 Декларативный HTTP-клиент

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

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

Обратите внимание, что мы не реализуем никакого кода для вызова нашей службы . Вместо этого 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. Micronaut CLI

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

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

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

В Micronaut федерация-это просто группа автономных приложений, которые находятся в одном каталоге. Используя федерации, мы можем легко управлять ими вместе и гарантировать, что они получат одинаковые значения по умолчанию и настройки.

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

7.2. Особенности

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

Мы указываем объекты, используя аргумент -features и предоставляя список имен объектов, разделенных запятыми.

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

> 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. Существующие проекты

Мы также можем использовать инструмент CLI для изменения существующих проектов. Позволяет нам создавать компоненты, клиенты, контроллеры и многое другое. Когда мы запускаем команду 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 .