Membina Perkhidmatan Mikro dengan Eclipse MicroProfile

1. Gambaran keseluruhan

Dalam artikel ini, kami akan memfokuskan diri untuk membina perkhidmatan mikro berdasarkan Eclipse MicroProfile.

Kami akan melihat bagaimana menulis aplikasi web RESTful menggunakan API JAX-RS, CDI dan JSON-P.

2. Senibina Mikro Perkhidmatan

Ringkasnya, perkhidmatan mikro adalah gaya seni bina perisian yang membentuk sistem lengkap sebagai kumpulan beberapa perkhidmatan bebas.

Masing-masing memusatkan perhatian pada satu perimeter fungsional dan berkomunikasi dengan yang lain dengan protokol bahasa-agnostik, seperti REST.

3. Eclipse MicroProfile

Eclipse MicroProfile adalah inisiatif yang bertujuan untuk mengoptimumkan Enterprise Java untuk seni bina perkhidmatan mikro. Ini berdasarkan subkumpulan API Jakarta EE WebProfile, jadi kami dapat membuat aplikasi MicroProfile seperti yang kami buat di Jakarta EE.

Matlamat MicroProfile adalah untuk menentukan API standard untuk membina perkhidmatan mikro dan menyampaikan aplikasi mudah alih merentasi beberapa waktu runcit MicroProfile.

4. Pergantungan Maven

Semua pergantungan yang diperlukan untuk membina aplikasi Eclipse MicroProfile disediakan oleh pergantungan BOM (Bill Of Materials) ini:

 org.eclipse.microprofile microprofile 1.2 pom provided  

Ruang lingkup ditetapkan seperti yang disediakan kerana runtime MicroProfile sudah termasuk API dan implementasinya.

5. Model Perwakilan

Mari mulakan dengan membuat kelas sumber cepat:

public class Book { private String id; private String name; private String author; private Integer pages; // ... }

Seperti yang kita lihat, tidak ada penjelasan pada kelas Buku ini.

6. Menggunakan CDI

Secara sederhana, CDI adalah API yang menyediakan suntikan ketergantungan dan pengurusan kitaran hidup. Ini mempermudah penggunaan kacang Enterprise dalam Aplikasi Web.

Sekarang mari kita buat kacang CDI sebagai kedai untuk perwakilan buku:

@ApplicationScoped public class BookManager { private ConcurrentMap inMemoryStore = new ConcurrentHashMap(); public String add(Book book) { // ... } public Book get(String id) { // ... } public List getAll() { // ... } } 

Kami memberi anotasi kelas ini dengan @ApplicationScoped kerana kami hanya memerlukan satu contoh yang keadaannya dikongsi oleh semua pelanggan. Untuk itu, kami menggunakan ConcurrentMap sebagai penyimpanan data dalam memori yang selamat. Kemudian kami menambahkan kaedah untuk operasi CRUD .

Sekarang kacang kami adalah CDI bersedia dan boleh disuntik ke dalam kacang BookEndpoint menggunakan yang @Inject anotasi.

7. API JAX-RS

Untuk membuat aplikasi REST dengan JAX-RS, kita perlu membuat kelas Aplikasi yang diberi penjelasan dengan @ApplicationPath dan sumber yang diberi penjelasan dengan @Path.

7.1. Permohonan JAX RS

Aplikasi JAX-RS mengenal pasti URI asas di mana kami mendedahkan sumber dalam Aplikasi Web.

Mari buat Aplikasi JAX-RS berikut:

@ApplicationPath("/library") public class LibraryApplication extends Application { }

Dalam contoh ini, semua kelas sumber JAX-RS dalam Aplikasi Web dikaitkan dengan LibraryApplication menjadikannya di bawah jalur perpustakaan yang sama , itulah nilai anotasi ApplicationPath.

Kelas beranotasi ini memberitahu waktu operasi JAX RS bahawa ia harus mencari sumber secara automatik dan memaparkannya.

7.2. Titik Akhir JAX RS

Satu titik akhir kelas, juga dikenali sebagai Sumber kelas, perlu menentukan satu sumber walaupun banyak jenis yang sama secara teknikal mungkin.

Setiap kelas Java dianotasi dengan @Path , atau mempunyai sekurang-kurangnya satu kaedah yang dianotasi dengan @Path atau @HttpMethod adalah Titik Akhir.

Sekarang, kami akan membuat Titik Akhir JAX-RS yang memperlihatkan perwakilan itu:

@Path("books") @RequestScoped public class BookEndpoint { @Inject private BookManager bookManager; @GET @Path("{id}") @Produces(MediaType.APPLICATION_JSON) public Response getBook(@PathParam("id") String id) { return Response.ok(bookManager.get(id)).build(); } @GET @Produces(MediaType.APPLICATION_JSON) public Response getAllBooks() { return Response.ok(bookManager.getAll()).build(); } @POST @Consumes(MediaType.APPLICATION_JSON) public Response add(Book book) { String bookId = bookManager.add(book); return Response.created( UriBuilder.fromResource(this.getClass()) .path(bookId).build()) .build(); } } 

Pada ketika ini, kita dapat mengakses Sumber BukuEndpoint di bawah jalur / perpustakaan / buku dalam aplikasi web.

7.3. Jenis Media JAX RS JSON

JAX RS menyokong banyak jenis media untuk berkomunikasi dengan klien REST, tetapi Eclipse MicroProfile menyekat penggunaan JSON kerana menentukan penggunaan JSOP-P API. Oleh itu, kita perlu memberi penjelasan kaedah kami dengan @Consumes (MediaType.APPLICATION_JSON) dan @ Produces (MediaType.APPLICATION_JSON ).

The @Consumes anotasi menghadkan format diterima - dalam contoh ini, hanya format data JSON Diterima. Tajuk permintaan HTTP Content-Type mestilah application / json .

Idea yang sama ada di sebalik anotasi @Produces . JAX RS Runtime harus mengumpulkan respons terhadap format JSON. Permintaan HTTP header Accept mestilah application / json.

8. JSON-P

JAX RS Runtime menyokong JSON-P di luar kotak sehingga kita dapat menggunakan JsonObject sebagai parameter input kaedah atau jenis pengembalian.

Tetapi di dunia nyata, kita sering bekerjasama dengan kelas POJO. Oleh itu, kita memerlukan kaedah untuk melakukan pemetaan antara JsonObject dan POJO. Di sinilah penyedia entiti JAX RS bermain.

Untuk aliran input JSON ke Buku POJO, yang menggunakan kaedah sumber dengan parameter jenis Buku, kita perlu membuat kelas BookMessageBodyReader:

@Provider @Consumes(MediaType.APPLICATION_JSON) public class BookMessageBodyReader implements MessageBodyReader { @Override public boolean isReadable( Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { return type.equals(Book.class); } @Override public Book readFrom( Class type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, InputStream entityStream) throws IOException, WebApplicationException { return BookMapper.map(entityStream); } } 

Kami melakukan proses yang sama untuk membuang aliran output Buku ke JSON, yang menggunakan kaedah sumber yang jenis pengembaliannya adalah Buku, dengan membuat BookMessageBodyWriter:

@Provider @Produces(MediaType.APPLICATION_JSON) public class BookMessageBodyWriter implements MessageBodyWriter { @Override public boolean isWriteable( Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { return type.equals(Book.class); } // ... @Override public void writeTo( Book book, Class type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException { JsonWriter jsonWriter = Json.createWriter(entityStream); JsonObject jsonObject = BookMapper.map(book); jsonWriter.writeObject(jsonObject); jsonWriter.close(); } } 

Oleh kerana BookMessageBodyReader dan BookMessageBodyWriter diberi anotasi dengan @Provider , ia didaftarkan secara automatik oleh JAX RS runtime.

9. Membangun dan Menjalankan Aplikasi

Aplikasi MicroProfile mudah alih dan harus dijalankan pada masa berjalan MicroProfile yang mematuhi. Kami akan menerangkan cara membina dan menjalankan aplikasi kami di Open Liberty, tetapi kami dapat menggunakan Eclipse MicroProfile yang mematuhi.

Kami mengkonfigurasi runtime Open Liberty melalui server file config.xml :

  jaxrs-2.0 cdi-1.2 jsonp-1.0     

Mari tambahkan plugin liberty-maven-plugin ke pom.xml kami:

  net.wasdev.wlp.maven.plugins liberty-maven-plugin 2.1.2   io.openliberty openliberty-runtime 17.0.0.4 zip  ${basedir}/src/main/liberty/config/server.xml ${package.file} ${packaging.type} false project  / ${project.artifactId}-${project.version}.war 9080 9443     install-server prepare-package  install-server create-server install-feature    package-server-with-apps package  install-apps package-server    

Plugin ini boleh dikonfigurasi melemparkan satu set sifat:

  library ${project.build.directory}/${app.name}-service.jar runnable 

The exec goal above produces an executable jar file so that our application will be an independent microservice which can be deployed and run in isolation. We can also deploy it as Docker image.

To create an executable jar, run the following command:

mvn package 

And to run our microservice, we use this command:

java -jar target/library-service.jar

This will start the Open Liberty runtime and deploy our service. We can access to our Endpoint and getting all books at this URL:

curl //localhost:9080/library/books

The result is a JSON:

[ { "id": "0001-201802", "isbn": "1", "name": "Building Microservice With Eclipse MicroProfile", "author": "baeldung", "pages": 420 } ] 

To get a single book, we request this URL:

curl //localhost:9080/library/books/0001-201802

And the result is JSON:

{ "id": "0001-201802", "isbn": "1", "name": "Building Microservice With Eclipse MicroProfile", "author": "baeldung", "pages": 420 }

Now we'll add a new Book by interacting with the API:

curl -H "Content-Type: application/json" -X POST -d '{"isbn": "22", "name": "Gradle in Action","author": "baeldung","pages": 420}' //localhost:9080/library/books 

As we can see, the status of the response is 201, indicating that the book was successfully created, and the Location is the URI by which we can access it:

< HTTP/1.1 201 Created < Location: //localhost:9080/library/books/0009-201802

10. Conclusion

Artikel ini menunjukkan cara membina perkhidmatan mikro sederhana berdasarkan Eclipse MicroProfile, membincangkan JAX RS, JSON-P dan CDI.

Kod boleh didapati di Github; ini adalah projek berasaskan Maven, jadi mudah untuk diimport dan dijalankan sebagaimana adanya.