Saya baru sahaja mengumumkan kursus Learn Spring yang baru , yang berfokus pada asas-asas Spring 5 dan Spring Boot 2:
>> SEMAK KURSUS1. Gambaran keseluruhan
Spring REST Docs dan OpenAPI 3.0 adalah dua cara untuk membuat dokumentasi API untuk REST API.
Dalam tutorial ini, kita akan mengkaji kelebihan dan kekurangannya.
2. Ringkasan Ringkas Asal
Spring REST Docs adalah kerangka yang dikembangkan oleh komuniti Spring untuk membuat dokumentasi yang tepat untuk RESTful API. Ia memerlukan pendekatan berdasarkan ujian, di mana dokumentasi ditulis sama ada sebagai ujian Spring MVC, Spring Webflux's WebTestClient, atau REST-Assured.
Output menjalankan ujian dibuat sebagai fail AsciiDoc yang dapat disatukan menggunakan Asciidoctor untuk menghasilkan halaman HTML yang menggambarkan API kami. Oleh kerana ia mengikuti kaedah TDD, Spring REST Docs secara automatik membawa semua kelebihannya seperti kod yang kurang ralat, pengurangan kerja semula, dan kitaran maklum balas yang lebih pantas, untuk menyebut beberapa.
OpenAPI, sebaliknya, adalah spesifikasi yang lahir dari Swagger 2.0. Versi terbaharu untuk menulis ini adalah 3.0 dan mempunyai banyak pelaksanaan yang diketahui.
Seperti spesifikasi lain, OpenAPI menetapkan peraturan dasar tertentu agar implementasinya dapat diikuti. Ringkasnya, semua implementasi OpenAPI seharusnya menghasilkan dokumentasi sebagai objek JSON, baik dalam format JSON atau YAML .
Terdapat juga banyak alat yang menggunakan JSON / YAML ini dan mengeluarkan UI untuk memvisualisasikan dan menavigasi API. Contohnya, ini sangat berguna semasa ujian penerimaan. Dalam contoh kod kami di sini, kami akan menggunakan springdoc - perpustakaan untuk OpenAPI 3 dengan Spring Boot.
Sebelum melihat keduanya secara terperinci, mari cepat siapkan API untuk didokumentasikan.
3. API REST
Mari mengumpulkan API CRUD asas menggunakan Spring Boot.
3.1. Repositori
Di sini, repositori yang akan kita gunakan adalah antara muka PagingAndSortingRepository tanpa tulang , dengan model Foo :
@Repository public interface FooRepository extends PagingAndSortingRepository{} @Entity public class Foo { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; @Column(nullable = false) private String title; @Column() private String body; // constructor, getters and setters }
Kami juga akan memuatkan repositori menggunakan schema.sql dan data.sql .
3.2. Pengawal
Seterusnya, mari kita lihat pengawal, melewatkan butiran pelaksanaannya untuk singkat:
@RestController @RequestMapping("/foo") public class FooController { @Autowired FooRepository repository; @GetMapping public ResponseEntity
getAllFoos() { // implementation } @GetMapping(value = "{id}") public ResponseEntity getFooById(@PathVariable("id") Long id) { // implementation } @PostMapping public ResponseEntity addFoo(@RequestBody @Valid Foo foo) { // implementation } @DeleteMapping("/{id}") public ResponseEntity deleteFoo(@PathVariable("id") long id) { // implementation } @PutMapping("/{id}") public ResponseEntity updateFoo(@PathVariable("id") long id, @RequestBody Foo foo) { // implementation } }
3.3. Permohonan
Dan akhirnya, Aplikasi Boot:
@SpringBootApplication() public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
4. OpenAPI / Springdoc
Sekarang mari kita lihat bagaimana springdoc dapat menambahkan dokumentasi ke Foo REST API kami.
Ingat bahawa ia akan menghasilkan objek JSON dan visualisasi UI API berdasarkan objek itu .
4.1. UI asas
Sebagai permulaan, kami hanya akan menambahkan beberapa kebergantungan Maven - springdoc-openapi-data-rest untuk menghasilkan JSON, dan springdoc-openapi-ui untuk membuat UI.
Alat ini akan memeriksa kod untuk API kami, dan membaca penjelasan kaedah pengawal. Atas dasar itu, ia akan menghasilkan API JSON yang akan disiarkan secara langsung di // localhost: 8080 / api-docs / . Ia juga akan menyediakan UI asas di //localhost:8080/swagger-ui-custom.html :

Seperti yang dapat kita lihat, tanpa menambahkan kod sama sekali, kita memperoleh visualisasi API yang indah, hingga ke skema Foo . Dengan menggunakan butang Cubalah , kita bahkan dapat menjalankan operasi dan melihat hasilnya.
Sekarang, bagaimana jika kita ingin menambahkan beberapa dokumentasi sebenar ke API? Dari segi apa itu API, apa maksud semua operasinya, apa yang harus dimasukkan, dan apa tanggapan yang diharapkan?
Kami akan melihatnya di bahagian seterusnya.
4.2. UI terperinci
Mari kita lihat terlebih dahulu cara menambahkan keterangan umum ke API.
Untuk itu, kami akan menambahkan kacang OpenAPI ke Aplikasi Boot kami:
@Bean public OpenAPI customOpenAPI(@Value("${springdoc.version}") String appVersion) { return new OpenAPI().info(new Info() .title("Foobar API") .version(appVersion) .description("This is a sample Foobar server created using springdocs - " + "a library for OpenAPI 3 with spring boot.") .termsOfService("//swagger.io/terms/") .license(new License().name("Apache 2.0") .url("//springdoc.org"))); }
Seterusnya, untuk menambahkan beberapa maklumat ke operasi API kami, kami akan menghiasi pemetaan kami dengan beberapa anotasi khusus OpenAPI.
Mari lihat bagaimana kita dapat menerangkan getFooById. Kami akan melakukan ini di dalam pengawal lain, FooBarController , yang serupa dengan FooController kami :
@RestController @RequestMapping("/foobar") @Tag(name = "foobar", description = "the foobar API with documentation annotations") public class FooBarController { @Autowired FooRepository repository; @Operation(summary = "Get a foo by foo id") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "found the foo", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = Foo.class))}), @ApiResponse(responseCode = "400", description = "Invalid id supplied", content = @Content), @ApiResponse(responseCode = "404", description = "Foo not found", content = @Content) }) @GetMapping(value = "{id}") public ResponseEntity getFooById(@Parameter(description = "id of foo to be searched") @PathVariable("id") String id) { // implementation omitted for brevity } // other mappings, similarly annotated with @Operation and @ApiResponses }
Sekarang mari kita lihat kesannya pada UI:

Oleh itu, dengan konfigurasi minimum ini, pengguna API kami kini dapat melihat apa yang ada, bagaimana menggunakannya, dan apa hasil yang diharapkan. Yang harus kami buat ialah menyusun kod dan menjalankan Boot App.
5. Dokumen REST Spring
Dokumen REST adalah dokumentasi API yang berbeza sekali. Seperti yang dijelaskan sebelumnya, proses ini didorong oleh ujian, dan outputnya dalam bentuk halaman HTML statis.
Dalam contoh kami di sini, kami akan menggunakan Spring MVC Tests untuk membuat coretan dokumentasi .
Pada mulanya, kita perlu menambahkan pergantungan spring-restdocs-mockmvc dan plugin asciidoc Maven ke pom kami .
5.1. Ujian JUnit5
Sekarang mari kita lihat ujian JUnit5 yang merangkumi dokumentasi kami:
@ExtendWith({ RestDocumentationExtension.class, SpringExtension.class }) @SpringBootTest(classes = Application.class) public class SpringRestDocsIntegrationTest { private MockMvc mockMvc; @Autowired private ObjectMapper objectMapper; @BeforeEach public void setup(WebApplicationContext webApplicationContext, RestDocumentationContextProvider restDocumentation) { this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext) .apply(documentationConfiguration(restDocumentation)) .build(); } @Test public void whenGetFooById_thenSuccessful() throws Exception { ConstraintDescriptions desc = new ConstraintDescriptions(Foo.class); this.mockMvc.perform(get("/foo/{id}", 1)) .andExpect(status().isOk()) .andDo(document("getAFoo", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()), pathParameters(parameterWithName("id").description("id of foo to be searched")), responseFields(fieldWithPath("id") .description("The id of the foo" + collectionToDelimitedString(desc.descriptionsForProperty("id"), ". ")), fieldWithPath("title").description("The title of the foo"), fieldWithPath("body").description("The body of the foo")))); } // more test methods to cover other mappings
}
Setelah menjalankan ujian ini, kami mendapat beberapa fail di direktori target / dihasilkan-potongan dengan maklumat mengenai operasi API yang diberikan. Terutama, apabilaGetFooById_thenSuccessful akan memberi kita lapan adoc dalam folder getAFoo dalam direktori.
Berikut adalah contoh http-respons.adoc , tentu saja mengandungi badan tindak balas:
[source,http,options="nowrap"] ---- HTTP/1.1 200 OK Content-Type: application/json Content-Length: 60 { "id" : 1, "title" : "Foo 1", "body" : "Foo body 1" } ----
5.2. fooapi.adoc
Sekarang kita memerlukan fail induk yang akan menyusun semua coretan ini untuk membentuk HTML yang tersusun dengan baik.
Mari namakan fooapi.adoc dan lihat sebahagian kecilnya:
=== Accessing the foo GET A `GET` request is used to access the foo read. ==== Request structure include::{snippets}/getAFoo/http-request.adoc[] ==== Path Parameters include::{snippets}/getAFoo/path-parameters.adoc[] ==== Example response include::{snippets}/getAFoo/http-response.adoc[] ==== CURL request include::{snippets}/getAFoo/curl-request.adoc[]
Selepas melaksanakan asciidoctor-Maven-plugin , kita akan mendapat akhir fail HTML fooapi.html dalam target / dijana-dokumen folder .
Dan ini akan kelihatan apabila dibuka di penyemak imbas:

6. Pengambilan Utama
Sekarang setelah kita melihat kedua-dua pelaksanaannya, mari kita ringkaskan kelebihan dan kekurangannya.
Dengan springdoc , anotasi yang harus kita gunakan menyusun kod pengawal rehat kita dan mengurangkan pembacaannya . Juga, dokumentasi digabungkan dengan kod dan akan memasuki produksi.
Tidak perlu dikatakan, mengekalkan dokumentasi adalah satu lagi cabaran di sini - jika sesuatu dalam API berubah, adakah pengaturcara akan selalu ingat untuk mengemas kini anotasi OpenAPI yang sesuai?
On the other hand, REST Docs neither looks as catchy as the other UI did nor can it be used for acceptance testing. But it has its advantages.
Notably, the successful completion of the Spring MVC test not only gives us the snippets but also verifies our API as any other unit test would. This forces us to make documentation changes corresponding to API modifications if any. Also, the documentation code is completely separate from the implementation.
But again, on the flip side, we had to write more code to generate the documentation. First, the test itself which is arguably as verbose as the OpenAPI annotations, and second, the master adoc.
Ia juga memerlukan lebih banyak langkah untuk menghasilkan HTML akhir - menjalankan ujian terlebih dahulu dan kemudian pemalam. Springdoc hanya menghendaki kami menjalankan Aplikasi Boot.
7. Kesimpulannya
Dalam tutorial ini, kami melihat perbezaan antara Springdoc berasaskan OpenAPI dan Spring REST Docs. Kami juga melihat bagaimana melaksanakan keduanya untuk menghasilkan dokumentasi untuk API CRUD asas.
Ringkasnya, kedua-duanya mempunyai kebaikan dan keburukan, dan keputusan untuk menggunakan satu daripada yang lain adalah tertakluk kepada keperluan khusus kami.
Seperti biasa, kod sumber tersedia di GitHub.
REST bawah