Documentare un'API REST di primavera utilizzando OpenAPI 3.0

REST Top

Ho appena annunciato il nuovo corso Learn Spring , incentrato sui fondamenti di Spring 5 e Spring Boot 2:

>> SCOPRI IL CORSO

1. Panoramica

La documentazione è una parte essenziale della creazione di API REST. In questo tutorial, daremo uno sguardo a SpringDoc, uno strumento che semplifica la generazione e la manutenzione di documenti API, basati sulla specifica OpenAPI 3, per le applicazioni Spring Boot 1.xe 2.x.

2. Configurazione di springdoc-openapi

Per fare in modo che springdoc-openapi generi automaticamente i documenti delle specifiche OpenAPI 3 per la nostra API, aggiungiamo semplicemente la dipendenza springdoc-openapi-ui al nostro pom.xml :

 org.springdoc springdoc-openapi-ui 1.5.2 

Quindi, quando eseguiamo la nostra applicazione, le descrizioni OpenAPI saranno disponibili nel percorso / v3 / api-docs per impostazione predefinita, ad esempio:

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

Per utilizzare un percorso personalizzato, possiamo indicare nel file application.properties :

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

Ora saremo in grado di accedere ai documenti su:

//localhost:8080/api-docs/

Le definizioni OpenAPI sono in JSONformato per impostazione predefinita. Per il formato yaml , possiamo ottenere le definizioni in:

//localhost:8080/api-docs.yaml

3. Configurazione di springdoc-openapi con Swagger UI

Oltre a generare la specifica OpenAPI 3 stessa, possiamo integrare springdoc-openapi con Swagger UI in modo da poter interagire con la nostra specifica API ed esercitare gli endpoint.

3.1. Dipendenza da Maven

Tutto quello che dobbiamo fare per configurare springdoc-openapi con Swagger UI è aggiungere la dipendenza springdoc-openapi-ui al pom.xml del progetto :

 org.springdoc springdoc-openapi-ui 1.5.2 

Ora possiamo accedere alla documentazione API su:

//localhost:8080/swagger-ui.html

3.2. Supporto per spavalderia-ui Proprietà

Springdoc-openapi supporta anche le proprietà swagger-ui. Questi possono essere usati come proprietà Spring Boot, con il prefisso springdoc.swagger-ui .

Ad esempio, personalizziamo il percorso della nostra documentazione API. Possiamo farlo modificando il nostro application.properties per includere:

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

Quindi ora la nostra documentazione API sarà disponibile su //localhost:8080/swagger-ui-custom.html .

Come altro esempio, per ordinare i percorsi API in base ai loro metodi HTTP, possiamo aggiungere:

springdoc.swagger-ui.operationsSorter=method

3.3. API di esempio

Supponiamo che la nostra applicazione abbia un controller per la gestione dei libri :

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

Quindi, quando eseguiamo la nostra applicazione, possiamo visualizzare la documentazione su:

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

Esaminiamo l' endpoint / api / book e vediamo i dettagli per la sua richiesta e risposta:

4. Integrazione di springdoc-openapi con Spring WebFlux

Possiamo integrare springdoc-openapi e Swagger UI in un progetto Spring WebFlux aggiungendo springdoc-openapi-webflux-ui :

 org.springdoc springdoc-openapi-webflux-ui 1.5.2 

E, come prima, i documenti saranno accessibili a:

//localhost:8080/swagger-ui.html

Per personalizzare il percorso, anche qui potremmo aggiungere la proprietà springdoc.swagger-ui.path nel nostro application.properties .

5. Esposizione delle informazioni sull'impaginazione

Spring Data JPA si integra perfettamente con Spring MVC. Un esempio di tali integrazioni è il supporto Pageable :

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

All'inizio, potremmo aspettarci che SpringDoc aggiunga pagina , dimensione e parametri di query di ordinamento alla documentazione generata. Tuttavia, per impostazione predefinita, SpringDoc non soddisfa questa aspettativa. Per sbloccare questa funzione, dovremmo aggiungere la dipendenza springdoc-openapi-data-rest :

 org.springdoc springdoc-openapi-data-rest 1.5.2 

Ora aggiunge i parametri di query previsti alla documentazione:

6. Utilizzo del plug-in Maven springdoc-openapi

La libreria springdoc-openapi fornisce un plugin Maven springdoc-openapi-maven-plugin per la generazione di descrizioni OpenAPI nei formati json e yaml .

The springdoc-openapi-maven-plugin plugin works with the spring-boot-maven plugin. Maven runs the openapi plugin during the integration-test phase.

Let's see how we can configure the plugin in our pom.xml:

 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    

Also, we can configure the plugin to use custom values:

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

Let's take a closer look at the parameters that we can configure for the plugin:

  • apiDocsUrl – URL where the docs can be accessed in JSON format, with a default of //localhost:8080/v3/api-docs
  • outputFileName – Name of the file where the definitions are stored, defaults to openapi.json
  • outputDir – Absolute path for the directory where the docs are stored – by default, ${project.build.directory}

7. Automatic Document Generation Using JSR-303 Bean Validation

When our model includes JSR-303 bean validation annotations, such as @NotNull, @NotBlank, @Size, @Min, and @Max, the springdoc-openapi library uses them to generate additional schema documentation for the corresponding constraints.

Let's see an example using our Book bean:

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

Now, the documentation generated for the Book bean is a little more informative:

8. Generate Documentation Using @ControllerAdvice and @ResponseStatus

Using @ResponseStatus on methods in a @RestControllerAdvice class will automatically generate documentation for the response codes. In this @RestControllerAdvice class, the two methods are annotated with @ResponseStatus:

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

As a result, we can now see the documentation for the response codes 400 and 404:

9. Generate Documentation Using @Operation and @ApiResponses

Next, let's see how we can add some description to our API using a couple of OpenAPI-specific annotations.

In order to do that, we'll annotate our controller's /api/book/{id} endpoint with @Operation and @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()); }

And here's the effect:

As we can see, the text we added to @Operation is placed at the API operation level. Similarly, the description added to various @ApiResponse elements in the @ApiResponses container annotation is also visible here, adding meaning to our API responses.

Evidently, we do not get any schema for the responses 400 and 404 above. Because we defined an empty @Content for them, only their descriptions are displayed.

10. Kotlin Support

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