Proljetni REST Docs vs OpenAPI

OSTALO Vrh

Upravo sam najavio novo Uči proljeće tečaj, usredotočen na osnove Spring 5 i Spring Boot 2:

>> PROVJERITE TEČAJ

1. Pregled

Spring REST Docs i OpenAPI 3.0 dva su načina za stvaranje API dokumentacije za REST API.

U ovom uputstvu ispitat ćemo njihove relativne prednosti i nedostatke.

2. Kratki sažetak podrijetla

Spring REST Docs je okvir koji je razvila Spring zajednica kako bi se stvorila točna dokumentacija za RESTful API-je. Potreban je testni pristup, pri čemu je dokumentacija napisana ili kao Spring MVC testovi, Spring Webflux WebTestClient, ili REST-Assured.

Rezultat izvođenja testova kreira se kao AsciiDoc datoteke koje se mogu sastaviti pomoću Asciidoctora za generiranje HTML stranice koja opisuje naše API-je. Budući da slijedi TDD metodu, Spring REST Docs automatski donosi sve svoje prednosti kao što su kôd podložan pogreškama, smanjena prerada i brži ciklusi povratnih informacija, da nabrojimo nekoliko.

S druge strane, OpenAPI je specifikacija rođena iz Swaggera 2.0. Njegova najnovija verzija od pisanja ovog teksta je 3.0 i ima mnoge poznate implementacije.

Kao i bilo koja druga specifikacija, OpenAPI postavlja određena osnovna pravila kako bi se njihove implementacije slijedile. Jednostavno rečeno, sve Implementacije OpenAPI trebale bi proizvesti dokumentaciju kao JSON objekt, bilo u JSON ili YAML formatu.

Postoje i mnogi alati koji uvode ovaj JSON / YAML i ispljuju korisničko sučelje za vizualizaciju i navigaciju API-jem. To vam dobro dođe, na primjer, tijekom ispitivanja prihvaćanja. U našim primjerima kodova ovdje ćemo ih koristiti springdoc - knjižnica za OpenAPI 3 s Spring Bootom.

Prije nego što ih detaljno pogledamo, postavimo brzo API koji će se dokumentirati.

3. REST API

Sastavimo osnovni CRUD API koristeći Spring Boot.

3.1. Spremište

Ovdje je spremište koje ćemo upotrebljavati gola kost PagingAndSortingRepository sučelje, s modelom Foo:

@Repository javno sučelje FooRepository proširuje PagingAndSortingRepository {} @Entity javnu klasu Foo {@Id @GeneratedValue (strategija = GenerationType.IDENTITY) private long id; @Column (nullable = false) naslov privatnog niza; @Column () privatno tijelo niza; // konstruktor, getteri i postavljači}

Također ćemo učitati spremište pomoću a shema.sql i a podaci.sql.

3.2. Kontroler

Dalje, pogledajmo kontroler, preskačući pojedinosti njegove implementacije radi kratkoće:

@RestController @RequestMapping ("/ foo") FooController javne klase {@Autowired FooRepository repozitorij; @GetMapping javni ResponseEntity getAllFoos () {// implementacija} @GetMapping (value = "{id}") javni ResponseEntity getFooById (@PathVariable ("id") Long id) {// implementacija} @PostMapping javni ResponseEntity addFoo (@RequestBody @Valid Foo foo ) {// implementacija} @DeleteMapping ("/ {id}") javni ResponseEntity deleteFoo (@PathVariable ("id") long id) {// implementacija} @PutMapping ("/ {id}") javni ResponseEntity updateFoo (@ PathVariable ("id") dugi ID, @RequestBody Foo foo) {// implementacija}}

3.3. Aplikacija

I na kraju, aplikacija za pokretanje:

@SpringBootApplication () aplikacija javne klase {public static void main (String [] args) {SpringApplication.run (Application.class, args); }}

4. OpenAPI / Springdoc

Sad da vidimo kako springdoc mogu dodati dokumentaciju u naš Foo REST API.

Sjetite se toga generirat će JSON objekt i vizualizaciju korisničkog sučelja API-ja na temelju tog objekta.

4.1. Osnovno korisničko sučelje

Za početak ćemo dodati samo nekoliko Mavenovih ovisnosti - springdoc-openapi-data-rest za generiranje JSON-a i springdoc-openapi-ui za prikazivanje korisničkog sučelja.

Alat će proučiti kôd našeg API-ja i pročitati napomene o metodama kontrolera. Na temelju toga generirat će API JSON koji će biti uživo na // localhost: 8080 / api-docs /. Također će služiti osnovnom korisničkom sučelju na //localhost:8080/swagger-ui-custom.html:

Kao što vidimo, bez dodavanja ikakvog koda, dobili smo prekrasnu vizualizaciju našeg API-ja, sve do Foo shema. Koristiti Isprobaj gumb, možemo čak izvršiti operacije i pregledati rezultate.

Sada, što ako bismo API-ju htjeli dodati neku stvarnu dokumentaciju? Što se tiče API-ja, što sve njegove operacije znače, što treba unijeti i kakve odgovore očekivati?

To ćemo pogledati u sljedećem odjeljku.

4.2. Detaljno korisničko sučelje

Pogledajmo prvo kako dodati općeniti opis API-ju.

Za to ćemo dodati OpenAPI grah za našu aplikaciju za pokretanje:

@Bean public OpenAPI customOpenAPI (@Value ("$ {springdoc.version}") String appVersion) {return new OpenAPI (). Info (new Info () .title ("Foobar API") .version (appVersion) .description ( "Ovo je uzorak poslužitelja Foobar stvoren pomoću springdocs -" + "biblioteke za OpenAPI 3 s proljetnim pokretanjem.") .TermsOfService ("// swagger.io/terms/") .license (nova licenca (). Name (" Apache 2.0 ") .url (" // springdoc.org ")))); } 

Dalje, da bismo dodali neke informacije našim API operacijama, ukrasit ćemo naša mapiranja s nekoliko napomena specifičnih za OpenAPI.

Pogledajmo kako to možemo opisati getFooById. To ćemo raditi u drugom kontroleru, FooBarController, koja je slična našoj FooController:

@RestController @RequestMapping ("/ foobar") @Tag (name = "foobar", description = "the foobar API s napomenama o dokumentaciji") javna klasa FooBarController {@Autowired FooRepository repozitorij; @Operation (summary = "Get foo by foo id") @ApiResponses (value = {@ApiResponse (responseCode = "200", description = "found the foo", content = {@Content (mediaType = "application / json") , schema = @Schema (implementacija = Foo.class))}), @ApiResponse (responseCode = "400", description = "Dostavljen nevažeći ID", content = @Content), @ApiResponse (responseCode = "404", description = "Foo nije pronađen", content = @Content)}) @GetMapping (value = "{id}") public ResponseEntity getFooById (@Parameter (description = "id foo-a koji se traži") @PathVariable ("id") String id) {// implementacija izostavljena zbog kratkoće} // ostala preslikavanja, slično označena s @Operation i @ApiResponses} 

Pogledajmo sada učinak na korisničko sučelje:

Dakle, s ovim minimalnim konfiguracijama, korisnik našeg API-ja sada može vidjeti o čemu se radi, kako ga koristiti i kakve rezultate očekuje. Trebalo je samo sastaviti kod i pokrenuti aplikaciju za pokretanje.

5. Proljetni REST dokumenti

REST docs potpuno je drugačiji pristup API dokumentaciji. Kao što je ranije opisano, postupak se pokreće testom, a izlaz je u obliku statičke HTML stranice.

U našem primjeru ovdje, koristit ćemo proljetne MVC testove za izradu isječaka dokumentacije.

Na početku ćemo morati dodati proljeće-restdocs-mockmvc ovisnost i asciidoc Maven dodatak za naš pom.

5.1. JUnit5 test

Sada ćemo pogledati test JUnit5 koji uključuje našu dokumentaciju:

@ExtendWith ({RestDocumentationExtension.class, SpringExtension.class}) @SpringBootTest (classes = Application.class) javna klasa SpringRestDocsIntegrationTest {private MockMvc mockMvc; @Autowired private ObjectMapper objectMapper; @BeforeEach postavljanje javne praznine (WebApplicationContext webApplicationContext, RestDocumentationContextProvider restDocumentation) {this.mockMvc = MockMvcBuilders.webAppContextSetup (webApplicationContext) .fPodatka (restConstruction). } @Test public void whenGetFooById_thenSuccessful () baca iznimku {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 foo-a koji se traži")), responseFields (fieldWithPath ("id") .description ("ID foo-a" + collectionToDelimitedString (desc.descriptionsForProperty ("id"), ".")), fieldWithPath ("title"). description ("Naslov foo"), fieldWithPath ("body"). description ("The body of the foo"))))) ; } // više metoda ispitivanja za pokrivanje ostalih mapiranja

}

Nakon pokretanja ovog testa, dobivamo nekoliko datoteka u našem ciljevi / generirani isječci direktorij s informacijama o zadanom API radu. Osobito, whenGetFooById_thenUspješno dat će nam osam adocs u a getAFoo mapu u direktoriju.

Evo uzorka http-odgovor.adoc, naravno sadrži odgovor tijelo:

[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

Sada nam treba glavna datoteka koja će sve ove isječke povezati kako bi oblikovala dobro strukturirani HTML.

Nazovimo to fooapi.adoc i vidite mali dio:

=== Pristup foo GET Zahtjev `GET` koristi se za pristup foo čitanju. ==== Struktura zahtjeva uključuje :: {snippets} /getAFoo/http-request.adoc [] ==== Parametri puta uključuju :: {snippets} /getAFoo/path-parameters.adoc [] ==== Primjer odgovora uključuju :: {snippets} /getAFoo/http-response.adoc [] ==== CURL zahtjev uključuje :: {snippets} /getAFoo/curl-request.adoc []

Nakon izvršenja asciidoctor-maven-plugin, dobivamo konačnu HTML datoteku fooapi.html u cilj / generirani-dokumenti mapu.

A ovako će izgledati kada se otvori u pregledniku:

6. Ključni za poneti

Sad kad smo pogledali obje implementacije, sažejmo prednosti i nedostatke.

S springdoc, napomene koje smo morali koristiti pretrpale su kod našeg regulatora odmora i smanjile njegovu čitljivost. Također, dokumentacija je bila čvrsto povezana s kodom i ušla bi u proizvodnju.

Nepotrebno je reći da je održavanje dokumentacije još jedan izazov ovdje - ako bi se nešto u API-ju promijenilo, bi li se programer uvijek sjetio ažurirati odgovarajuću napomenu OpenAPI?

S druge strane, OSTALI Dokumenti niti izgledaju dopadljivo kao i drugo korisničko sučelje, niti se mogu koristiti za ispitivanje prihvatljivosti. Ali ima svoje prednosti.

Značajno je uspješno dovršenje programa proljetni MVC test ne samo da nam daje isječke, već i potvrđuje naš API kao i svaki drugi jedinični test. To nas prisiljava na izmjene dokumentacije koje odgovaraju promjenama API-ja ako postoje. Također, dokumentacijski kod potpuno je odvojen od implementacije.

Ali opet, s druge strane, morali smo napisati više koda za generiranje dokumentacije. Prvo, sam test koji je vjerojatno toliko detaljan kao i OpenAPI napomene, i drugo, master adoc.

Također treba više koraka za generiranje konačnog HTML-a - prvo pokretanje testa, a zatim dodatka. Springdoc zahtijevalo je samo pokretanje aplikacije za pokretanje.

7. Zaključak

U ovom smo tutorijalu pogledali razlike između OpenAPI-a springdoc i proljetni REST dokumenti. Također smo vidjeli kako ih implementirati u generiranje dokumentacije za osnovni CRUD API.

Ukratko, oboje imaju svoje prednosti i nedostatke, a odluka da se jedno koristi nad drugim podliježe našim posebnim zahtjevima.

Kao i uvijek, izvorni kod dostupan je na GitHub-u.

OSTALO dno

Upravo sam najavio novo Uči proljeće tečaj, usredotočen na osnove Spring 5 i Spring Boot 2:

>> PROVJERITE TEČAJ

$config[zx-auto] not found$config[zx-overlay] not found