1. Что такое Микронавт
Micronaut — это платформа на основе JVM для создания легких модульных приложений. Micronaut, разработанный OCI, той же компанией, которая создала Grails, представляет собой новейшую платформу, предназначенную для быстрого и простого создания микросервисов .
Хотя Micronaut содержит некоторые функции, похожие на существующие фреймворки, такие как Spring, он также имеет некоторые новые функции, которые отличают его от других. А благодаря поддержке Java, Groovy и Kotlin он предлагает множество способов создания приложений.
2. Основные характеристики
Одной из самых интересных особенностей Micronaut является механизм внедрения зависимостей во время компиляции. Большинство фреймворков используют отражение и прокси-серверы для внедрения зависимостей во время выполнения. Однако Micronaut создает данные для внедрения зависимостей во время компиляции. Результатом является более быстрый запуск приложений и меньший объем памяти.
Еще одна особенность — первоклассная поддержка реактивного программирования как для клиентов, так и для серверов. Выбор конкретной реактивной реализации остается за разработчиком, поскольку поддерживаются как RxJava, так и Project Reactor.
Micronaut также имеет несколько функций, которые делают его отличной средой для разработки облачных приложений. Он поддерживает несколько инструментов обнаружения сервисов, таких как Eureka и Consul, а также работает с различными системами распределенной трассировки, такими как Zipkin и Jaeger.
Он также поддерживает создание лямбда-функций AWS, упрощая создание бессерверных приложений.
3. Начало работы
Самый простой способ начать работу — использовать SDKMAN :
> sdk install micronaut 1.0.0.RC2
Это установит все двоичные файлы, которые нам понадобятся для сборки, тестирования и развертывания приложений Micronaut. Он также предоставляет инструмент командной строки Micronaut, который позволяет нам легко начинать новые проекты.
Двоичные артефакты также доступны на Sonatype и GitHub .
В следующих разделах мы рассмотрим некоторые особенности фреймворка.
4. Внедрение зависимостей
Как упоминалось ранее, Micronaut обрабатывает внедрение зависимостей во время компиляции, что отличается от большинства контейнеров IoC.
Однако он по-прежнему полностью поддерживает аннотации JSR-330 , поэтому работа с bean-компонентами аналогична другим платформам IoC.
Чтобы автоматически связать bean-компонент с нашим кодом, мы используем @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 реализует эти конечные точки, используя традиционный блокирующий ввод-вывод. Однако мы можем быстро реализовать неблокирующие конечные точки, просто изменив тип возвращаемого значения на любой реактивный неблокирующий тип .
Например, с RxJava мы можем использовать Observable
. Точно так же при использовании Reactor мы можем возвращать типы данных Mono
или Flux :
@Get("/{name}")
public Mono<String> 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<String> req = HttpRequest.GET("/greet/" + name);
return httpClient.retrieve(req).blockingFirst();
}
public Single<String> greetAsync(String name) {
HttpRequest<String> req = HttpRequest.GET("/async/greet/" + name);
return httpClient.retrieve(req).first("An error as occurred");
}
}
HTTP-клиент по умолчанию использует RxJava, поэтому может легко работать с блокирующими или неблокирующими вызовами.
7. Интерфейс командной строки Микронавта
Мы уже видели инструмент 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 для изменения существующих проектов. Это позволяет нам создавать bean-компоненты, клиенты, контроллеры и многое другое. Когда мы запускаем команду 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-серверы и клиенты. Кроме того, мы изучили некоторые особенности его интерфейса командной строки.
Но это лишь малая часть возможностей, которые он предлагает. Также имеется полная поддержка бессерверных функций, обнаружение сервисов, распределенная трассировка, мониторинг и метрики, распределенная конфигурация и многое другое.
И хотя многие его функции получены из существующих фреймворков, таких как Grails и Spring, он также имеет множество уникальных функций, которые выделяют его самостоятельно.
Как всегда, мы можем найти примеры кода выше в нашем репозитории GitHub .