Dokumentieren einer Spring REST-API mit OpenAPI 3.0

REST Top

Ich habe gerade den neuen Learn Spring- Kurs angekündigt , der sich auf die Grundlagen von Spring 5 und Spring Boot 2 konzentriert:

>> Überprüfen Sie den Kurs

1. Übersicht

Die Dokumentation ist ein wesentlicher Bestandteil beim Erstellen von REST-APIs. In diesem Tutorial werfen wir einen Blick auf SpringDoc - ein Tool, das die Generierung und Wartung von API-Dokumenten basierend auf der OpenAPI 3-Spezifikation für Spring Boot 1.x- und 2.x-Anwendungen vereinfacht.

2. Einrichten von springdoc-openapi

Damit springdoc-openapi automatisch die OpenAPI 3-Spezifikationsdokumente für unsere API generiert, fügen wir einfach die Abhängigkeit springdoc-openapi-ui zu unserer pom.xml hinzu :

 org.springdoc springdoc-openapi-ui 1.5.2 

Wenn wir dann unsere Anwendung ausführen, sind die OpenAPI-Beschreibungen standardmäßig im Pfad / v3 / api-docs verfügbar - zum Beispiel:

//localhost:8080/v3/api-docs/

Um einen benutzerdefinierten Pfad zu verwenden, können Sie in der Datei application.properties Folgendes angeben :

springdoc.api-docs.path=/api-docs

Jetzt können wir auf die Dokumente zugreifen unter:

//localhost:8080/api-docs/

Die OpenAPI-Definitionen befinden sich in JSONStandardmäßig formatieren. Für das Yaml- Format erhalten wir die Definitionen unter:

//localhost:8080/api-docs.yaml

3. Einrichten von springdoc-openapi mit Swagger UI

Neben der Generierung der OpenAPI 3-Spezifikation selbst können wir springdoc-openapi in die Swagger-Benutzeroberfläche integrieren, damit wir mit unserer API-Spezifikation interagieren und die Endpunkte trainieren können.

3.1. Maven-Abhängigkeit

Alles, was wir tun müssen, um springdoc-openapi mit der Swagger-Benutzeroberfläche einzurichten, ist, die Abhängigkeit springdoc-openapi-ui zur pom.xml des Projekts hinzuzufügen :

 org.springdoc springdoc-openapi-ui 1.5.2 

Wir können jetzt auf die API-Dokumentation zugreifen unter:

//localhost:8080/swagger-ui.html

3.2. Unterstützung für swagger-ui- Eigenschaften

Springdoc-openapi unterstützt auch Swagger-UI-Eigenschaften. Diese können als Spring Boot-Eigenschaften mit dem Präfix springdoc.swagger-ui verwendet werden .

Passen wir beispielsweise den Pfad unserer API-Dokumentation an. Wir können dies tun, indem wir unsere application.properties so ändern, dass sie Folgendes enthalten:

springdoc.swagger-ui.path=/swagger-ui-custom.html

Unsere API-Dokumentation ist jetzt unter //localhost:8080/swagger-ui-custom.html verfügbar .

Als weiteres Beispiel können wir hinzufügen, um die API-Pfade nach ihren HTTP-Methoden zu sortieren:

springdoc.swagger-ui.operationsSorter=method

3.3. Beispiel-API

Angenommen, unsere Anwendung verfügt über einen Controller zum Verwalten von Büchern :

@RestController @RequestMapping("/api/book") public class BookController { @Autowired private BookRepository repository; @GetMapping("/{id}") public Book findById(@PathVariable long id) { return repository.findById(id) .orElseThrow(() -> new BookNotFoundException()); } @GetMapping("/") public Collection findBooks() { return repository.getBooks(); } @PutMapping("/{id}") @ResponseStatus(HttpStatus.OK) public Book updateBook( @PathVariable("id") final String id, @RequestBody final Book book) { return book; } } 

Wenn wir dann unsere Anwendung ausführen, können wir die Dokumentation unter folgender Adresse anzeigen:

//localhost:8080/swagger-ui-custom.html

Lassen Sie uns einen Drilldown zum Endpunkt / api / book durchführen und die Details für die Anforderung und Antwort anzeigen:

4. Integration von springdoc-openapi in Spring WebFlux

Wir können springdoc-openapi und Swagger UI in ein Spring WebFlux-Projekt integrieren, indem wir springdoc-openapi-webflux-ui hinzufügen :

 org.springdoc springdoc-openapi-webflux-ui 1.5.2 

Und wie zuvor sind die Dokumente verfügbar unter:

//localhost:8080/swagger-ui.html

Um den Pfad anzupassen, können wir auch hier die Eigenschaft springdoc.swagger-ui.path in unsere application.properties einfügen .

5. Offenlegung von Paginierungsinformationen

Spring Data JPA lässt sich nahtlos in Spring MVC integrieren. Ein Beispiel für solche Integrationen ist die Pageable- Unterstützung:

@GetMapping("/filter") public Page filterBooks(Pageable pageable) { return repository.getBooks(pageable); }

Zunächst könnte erwarten wir SpringDoc hinzufügen Seite , Größe und Art Abfrageparameter an die generierte Dokumentation. Standardmäßig erfüllt SpringDoc diese Erwartung jedoch nicht. Um diese Funktion freizuschalten, sollten wir die Abhängigkeit springdoc-openapi-data-rest hinzufügen :

 org.springdoc springdoc-openapi-data-rest 1.5.2 

Jetzt werden die erwarteten Abfrageparameter zur Dokumentation hinzugefügt:

6. Verwenden des springdoc-openapi Maven Plugins

Die springdoc-openapi-Bibliothek bietet ein Maven-Plugin springdoc-openapi-maven-plugin zum Generieren von OpenAPI-Beschreibungen in den Formaten json und yaml .

Das Plugin springdoc-openapi-maven-plugin funktioniert mit dem Plugin spring-boot-maven . Maven führt das openapi- Plugin während der Integrationstestphase aus .

Mal sehen, wie wir das Plugin in unserer pom.xml konfigurieren können :

 org.springframework.boot spring-boot-maven-plugin 2.3.3.RELEASE   pre-integration-test  start    post-integration-test  stop      org.springdoc springdoc-openapi-maven-plugin 0.2   integration-test  generate    

Außerdem können wir das Plugin so konfigurieren, dass benutzerdefinierte Werte verwendet werden:

  .........   //localhost:8080/v3/api-docs openapi.json ${project.build.directory}   

Schauen wir uns die Parameter genauer an, die wir für das Plugin konfigurieren können:

  • apiDocsUrl - URL, über die auf die Dokumente im JSON-Format zugegriffen werden kann, mit dem Standardwert // localhost: 8080 / v3 / api-docs
  • outputFileName - Der Name der Datei, in der die Definitionen gespeichert sind, ist standardmäßig openapi.json
  • outputDir - Absoluter Pfad für das Verzeichnis, in dem die Dokumente gespeichert sind - standardmäßig $ {project.build.directory}

7. Automatische Dokumentgenerierung mit JSR-303 Bean Validation

Wenn unser Modell Anmerkungen zur Validierung von JSR-303-Beans enthält, z. B. @NotNull , @NotBlank , @Size , @Min und @Max , verwendet die springdoc-openapi-Bibliothek diese, um zusätzliche Schemadokumentationen für die entsprechenden Einschränkungen zu generieren.

Sehen wir uns ein Beispiel mit unserer Book Bean an:

public class Book { private long id; @NotBlank @Size(min = 0, max = 20) private String title; @NotBlank @Size(min = 0, max = 30) private String author; }

Die für die Book Bean generierte Dokumentation ist nun etwas informativer:

8. Generieren Sie die Dokumentation mit @ControllerAdvice und @ResponseStatus

Die Verwendung von @ResponseStatus für Methoden in einer @ RestControllerAdvice- Klasse generiert automatisch eine Dokumentation für die Antwortcodes. In dieser @ RestControllerAdvice- Klasse werden die beiden Methoden mit @ResponseStatus kommentiert :

@RestControllerAdvice public class GlobalControllerExceptionHandler { @ExceptionHandler(ConversionFailedException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public ResponseEntity handleConnversion(RuntimeException ex) { return new ResponseEntity(ex.getMessage(), HttpStatus.BAD_REQUEST); } @ExceptionHandler(BookNotFoundException.class) @ResponseStatus(HttpStatus.NOT_FOUND) public ResponseEntity handleBookNotFound(RuntimeException ex) { return new ResponseEntity(ex.getMessage(), HttpStatus.NOT_FOUND); } }

Als Ergebnis können wir jetzt die Dokumentation für die Antwortcodes 400 und 404 sehen:

9. Generieren Sie eine Dokumentation mit @Operation und @ApiResponses

Als nächstes wollen wir sehen, wie wir unserer API mithilfe einiger OpenAPI-spezifischer Anmerkungen eine Beschreibung hinzufügen können.

Dazu versehen wir den Endpunkt / api / book / {id} unseres Controllers mit @Operation und @ApiResponses :

@Operation(summary = "Get a book by its id") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Found the book", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = Book.class)) }), @ApiResponse(responseCode = "400", description = "Invalid id supplied", content = @Content), @ApiResponse(responseCode = "404", description = "Book not found", content = @Content) }) @GetMapping("/{id}") public Book findById(@Parameter(description = "id of book to be searched") @PathVariable long id) { return repository.findById(id).orElseThrow(() -> new BookNotFoundException()); }

Und hier ist der Effekt:

Wie wir sehen können, wird der Text, den wir zu @Operation hinzugefügt haben, auf der API-Operationsebene platziert. In ähnlicher Weise ist auch die Beschreibung sichtbar , die verschiedenen @ ApiResponse- Elementen in der @ AnniResponses- Containeranmerkung hinzugefügt wurde, was unseren API-Antworten Bedeutung verleiht .

Offensichtlich erhalten wir kein Schema für die obigen Antworten 400 und 404. Da wir für sie einen leeren @ -Inhalt definiert haben, werden nur deren Beschreibungen angezeigt.

10. Kotlin-Unterstützung

Since Spring Boot 2.x has first-class support for Kotlin, SpringDoc supports this JVM language out of the box for Boot 2.x applications.

To see this in action, we'll create a simple Foo API in Kotlin.

After the initial setup, we'll add a data class and a controller. We'll add them in a sub-package of our Boot App so that when it's run, it picks our FooController up along with the earlier BookController:

@Entity data class Foo( @Id val id: Long = 0, @NotBlank @Size(min = 0, max = 50) val name: String = "" ) @RestController @RequestMapping("/") class FooController() { val fooList: List = listOf(Foo(1, "one"), Foo(2, "two")) @Operation(summary = "Get all foos") @ApiResponses(value = [ ApiResponse(responseCode = "200", description = "Found Foos", content = [ (Content(mediaType = "application/json", array = ( ArraySchema(schema = Schema(implementation = Foo::class)))))]), ApiResponse(responseCode = "400", description = "Bad request", content = [Content()]), ApiResponse(responseCode = "404", description = "Did not find any Foos", content = [Content()])] ) @GetMapping("/foo") fun getAllFoos(): List = fooList }

Now when we hit our API documentation URL, we'll see the Foo API as well:

To enhance the support of Kotlin types, we can add this dependency:

 org.springdoc springdoc-openapi-kotlin

After that, our Foo schema will look more informative. Similar to as it did when we had added JSR-303 Bean Validation:

11. Conclusion

In this article, we learned to set up springdoc-openapi in our projects. Then, we saw how to integrate springdoc-openapi with the Swagger UI. We also saw how to do this with Spring Webflux projects.

Next, we used the springdoc-openapi Maven Plugin to generate OpenAPI definitions for our APIs, and we saw how to expose paging and sorting information from Spring Data. After that, we looked at how springdoc-openapi generates documentation automatically using JSR 303 bean validation annotations and the @ResponseStatus annotations in @ControllerAdvice class.

Then we learned how to add a description to our API using a few OpenAPI-specific annotations. Finally, we took a peek at OpenAPI's support of Kotlin.

The springdoc-openapi generates API documentation as per OpenAPI 3 specification. Moreover, it also handles the Swagger UI configuration for us, making API document generation a fairly simple task.

As always, the code is available over on GitHub.

REST bottom

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE