Giới thiệu về Micronaut Framework

1. Micronaut là gì

Micronaut là một khuôn khổ dựa trên JVM để xây dựng các ứng dụng mô-đun, nhẹ. Được phát triển bởi OCI, cùng một công ty đã tạo ra Grails, Micronaut là khuôn khổ mới nhất được thiết kế để giúp tạo các dịch vụ vi mô nhanh chóng và dễ dàng .

Mặc dù Micronaut chứa một số tính năng tương tự như các khuôn khổ hiện có như Spring, nhưng nó cũng có một số tính năng mới tạo nên sự khác biệt. Và với sự hỗ trợ cho Java, Groovy và Kotlin, nó cung cấp nhiều cách khác nhau để tạo ứng dụng.

2. Các tính năng chính

Một trong những tính năng thú vị nhất của Micronaut là cơ chế tiêm phụ thuộc vào thời gian biên dịch của nó. Hầu hết các khung công tác sử dụng phản chiếu và proxy để thực hiện chèn phụ thuộc vào thời gian chạy. Micronaut, tuy nhiên, xây dựng dữ liệu tiêm phụ thuộc của nó tại thời điểm biên dịch. Kết quả là khởi động ứng dụng nhanh hơn và dấu chân bộ nhớ nhỏ hơn.

Một tính năng khác là hỗ trợ lớp đầu tiên cho lập trình phản ứng, cho cả máy khách và máy chủ. Việc lựa chọn triển khai phản ứng cụ thể được để cho nhà phát triển vì cả RxJava và Project Reactor đều được hỗ trợ.

Micronaut cũng có một số tính năng làm cho nó trở thành một khuôn khổ tuyệt vời để phát triển các ứng dụng gốc đám mây. Nó hỗ trợ nhiều công cụ khám phá dịch vụ như Eureka và Consul, đồng thời cũng hoạt động với các hệ thống truy tìm phân tán khác nhau như Zipkin và Jaeger.

Nó cũng cung cấp hỗ trợ tạo các hàm AWS lambda, giúp dễ dàng tạo các ứng dụng không máy chủ.

3. Bắt đầu

Cách dễ nhất để bắt đầu là sử dụng SDKMAN:

> sdk install micronaut 1.0.0.RC2

Điều này sẽ cài đặt tất cả các tệp nhị phân mà chúng tôi cần để xây dựng, kiểm tra và triển khai các ứng dụng Micronaut. Nó cũng cung cấp công cụ Micronaut CLI, cho phép chúng tôi dễ dàng bắt đầu các dự án mới.

Các tạo tác nhị phân cũng có sẵn trên Sonatype và GitHub.

Trong các phần sau, chúng ta sẽ xem xét một số tính năng của khung.

4. Tiêm phụ thuộc

Như đã đề cập trước đó, Micronaut xử lý việc tiêm phụ thuộc vào thời điểm biên dịch, điều này khác với hầu hết các vùng chứa IoC.

Tuy nhiên, nó vẫn hỗ trợ đầy đủ các chú thích JSR-330 nên việc làm việc với bean cũng tương tự như các framework IoC khác.

Để tự động chuyển một bean vào mã của chúng tôi, chúng tôi sử dụng @Inject:

@Inject private EmployeeService service;

Các @Inject chú thích hoạt động giống như @Autowired và có thể được sử dụng trên các lĩnh vực, phương pháp, nhà thầu, và các thông số.

Theo mặc định, tất cả các hạt đậu được xác định phạm vi như một nguyên mẫu. Chúng ta có thể nhanh chóng tạo các hạt đậu đơn bằng cách sử dụng @Singleton. Nếu nhiều lớp triển khai cùng một giao diện bean, thì @Primary có thể được sử dụng để loại bỏ chúng:

@Primary @Singleton public class BlueCar implements Car {}

Các @Requires chú thích có thể được sử dụng khi đậu là không bắt buộc, hoặc chỉ thực hiện autowiring khi điều kiện nhất định được đáp ứng.

Về mặt này, nó hoạt động giống như chú thích 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. Xây dựng một máy chủ HTTP

Bây giờ chúng ta hãy xem xét việc tạo một ứng dụng máy chủ HTTP đơn giản. Để bắt đầu, chúng tôi sẽ sử dụng SDKMAN để tạo một dự án:

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

Thao tác này sẽ tạo một dự án Java mới bằng cách sử dụng Maven trong một thư mục có tên là hello-world-server. Bên trong thư mục này, chúng tôi sẽ tìm thấy mã nguồn ứng dụng chính, tệp Maven POM và các tệp hỗ trợ khác cho dự án.

Ứng dụng mặc định rất đơn giản:

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

5.1. Chặn HTTP

Riêng ứng dụng này sẽ không làm được gì nhiều. Hãy thêm một bộ điều khiển có hai điểm cuối. Cả hai sẽ trả về một lời chào, nhưng một người sẽ sử dụng động từ GET HTTP và người kia sẽ sử dụng 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. IO phản ứng

Theo mặc định, Micronaut sẽ triển khai các điểm cuối này bằng cách sử dụng I / O chặn truyền thống. Tuy nhiên, chúng tôi có thể nhanh chóng triển khai các điểm cuối không chặn chỉ bằng cách thay đổi kiểu trả về thành bất kỳ kiểu không chặn phản ứng nào .

Ví dụ, với RxJava, chúng ta có thể sử dụng Observable . Tương tự như vậy, khi sử dụng Reactor, chúng ta có thể trả về kiểu dữ liệu Mono hoặc Flux :

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

Đối với cả điểm cuối chặn và không chặn, Netty là máy chủ cơ bản được sử dụng để xử lý các yêu cầu HTTP.

Thông thường, các yêu cầu được xử lý trên nhóm luồng I / O chính được tạo khi khởi động, khiến chúng bị chặn.

Tuy nhiên, khi một kiểu dữ liệu không chặn được trả về từ điểm cuối của bộ điều khiển, Micronaut sử dụng chuỗi vòng lặp sự kiện Netty, làm cho toàn bộ yêu cầu không bị chặn.

6. Xây dựng một ứng dụng khách HTTP

Bây giờ chúng ta hãy xây dựng một máy khách để sử dụng các điểm cuối mà chúng ta vừa tạo. Micronaut cung cấp hai cách tạo máy khách HTTP:

  • Ứng dụng khách HTTP khai báo
  • Ứng dụng khách HTTP có lập trình

6.1 Ứng dụng khách HTTP khai báo

Cách đầu tiên và nhanh nhất để tạo là sử dụng cách tiếp cận khai báo:

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

Lưu ý cách chúng tôi không triển khai bất kỳ mã nào để gọi dịch vụ của chúng tôi . Thay vào đó, Micronaut hiểu cách gọi dịch vụ từ chữ ký phương thức và chú thích mà chúng tôi đã cung cấp.

To test this client, we can create a JUnit test that uses the embedded server API to run an embedded instance of our server:

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. Programmatic HTTP Client

We also have the option of writing a more traditional client if we need more control over its behavior and implementation:

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

The default HTTP client uses RxJava, so can easily work with blocking or non-blocking calls.

7. Micronaut CLI

We've already seen the Micronaut CLI tool in action above when we used it to create our sample project.

In our case, we created a standalone application, but it has several other capabilities as well.

7.1. Federation Projects

In Micronaut, a federation is just a group of standalone applications that live under the same directory. By using federations, we can easily manage them together and ensure they get the same defaults and settings.

When we use the CLI tool to generate a federation, it takes all the same arguments as the create-app command. It will create a top-level project structure, and each standalone app will be created in its sub-directory from there.

7.2. Features

When creating a standalone application or federation, we can decide which features our app needs. This helps ensure the minimal set of dependencies is included in the project.

We specify features using the -features argument and supplying a comma-separated list of feature names.

We can find a list of available features by running the following command:

> 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. Existing Projects

We can also use the CLI tool to modify existing projects. Enabling us to create beans, clients, controllers, and more. When we run the mn command from inside an existing project, we'll have a new set of commands available:

> 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. Conclusion

In this brief introduction to Micronaut, we've seen how easy it is to build both blocking and non-blocking HTTP servers and clients. Also, we explored some features of its CLI.

But this is just a small taste of the features it offers. There is also full support for serverless functions, service discovery, distributed tracing, monitoring and metrics, a distributed configuration, and much more.

And while many of its features are derived from existing frameworks such as Grails and Spring, it also has plenty of unique features that help it stand out on its own.

Như mọi khi, chúng tôi có thể tìm thấy mã mẫu ở trên trong repo GitHub của chúng tôi.