Mendokumentasikan Spring REST API Menggunakan OpenAPI 3.0

REST Teratas

Saya baru sahaja mengumumkan kursus Learn Spring yang baru , yang berfokus pada asas-asas Spring 5 dan Spring Boot 2:

>> SEMAK KURSUS

1. Gambaran keseluruhan

Dokumentasi adalah bahagian penting dalam membina API REST. Dalam tutorial ini, kita akan melihat SpringDoc - alat yang mempermudah penghasilan dan penyelenggaraan dokumen API, berdasarkan spesifikasi OpenAPI 3, untuk aplikasi Spring Boot 1.x dan 2.x.

2. Menyiapkan springdoc-openapi

Untuk mempunyai springdoc-openapi secara automatik menghasilkan dokumen spesifikasi OpenAPI 3 untuk API kami, kami hanya menambahkan ketergantungan springdoc-openapi-ui ke pom.xml kami :

 org.springdoc springdoc-openapi-ui 1.5.2 

Kemudian, semasa kami menjalankan aplikasi kami, keterangan OpenAPI akan tersedia di path / v3 / api-docs secara lalai - misalnya:

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

Untuk menggunakan jalan khusus, kita dapat menunjukkan dalam fail application.properties :

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

Sekarang, kami dapat mengakses dokumen di:

//localhost:8080/api-docs/

Definisi OpenAPI terdapat dalam JSONformat secara lalai. Untuk format yaml , kita dapat memperoleh definisi di:

//localhost:8080/api-docs.yaml

3. Menyiapkan springdoc-openapi Dengan Swagger UI

Selain menghasilkan spesifikasi OpenAPI 3 itu sendiri, kami dapat mengintegrasikan springdoc-openapi dengan Swagger UI sehingga kami dapat berinteraksi dengan spesifikasi API kami dan menggunakan titik akhir.

3.1. Ketergantungan Maven

Yang harus kita lakukan untuk menyiapkan springdoc-openapi dengan Swagger UI adalah menambahkan kebergantungan springdoc-openapi-ui ke pom.xml projek :

 org.springdoc springdoc-openapi-ui 1.5.2 

Kami kini dapat mengakses dokumentasi API di:

//localhost:8080/swagger-ui.html

3.2. Sokongan untuk swagger-ui Properties

Springdoc-openapi juga menyokong sifat swagger-ui. Ini boleh digunakan sebagai sifat Spring Boot, dengan awalan springdoc.swagger-ui .

Sebagai contoh, mari sesuaikan jalan dokumentasi API kami. Kami boleh melakukan ini dengan mengubahsuai aplikasi kami .

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

Jadi sekarang dokumentasi API kami akan tersedia di //localhost:8080/swagger-ui-custom.html .

Sebagai contoh lain, untuk menyusun laluan API mengikut kaedah HTTP mereka, kita dapat menambahkan:

springdoc.swagger-ui.operationsSorter=method

3.3. Contoh API

Andaikan aplikasi kita mempunyai alat kawalan untuk menguruskan Buku :

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

Kemudian, semasa menjalankan aplikasi, kita dapat melihat dokumentasi di:

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

Mari kita lihat ke titik akhir / api / buku dan melihat perincian permintaan dan responsnya:

4. Mengintegrasikan springdoc-openapi dengan Spring WebFlux

Kita dapat mengintegrasikan springdoc-openapi dan Swagger UI dalam projek Spring WebFlux dengan menambahkan springdoc-openapi-webflux-ui :

 org.springdoc springdoc-openapi-webflux-ui 1.5.2 

Dan, seperti sebelumnya, dokumen akan dapat diakses di:

//localhost:8080/swagger-ui.html

Untuk menyesuaikan jalan, di sini sekali lagi kita dapat menambahkan properti springdoc.swagger-ui.path di application.properties kami .

5. Mendedahkan Maklumat Penomboran

Spring Data JPA berintegrasi dengan Spring MVC dengan lancar. Salah satu contoh integrasi tersebut ialah sokongan Pageable :

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

Pada mulanya, kami mungkin mengharapkan SpringDoc menambahkan halaman , ukuran , dan menyusun parameter pertanyaan ke dokumentasi yang dihasilkan. Walau bagaimanapun, secara lalai, SpringDoc tidak memenuhi jangkaan ini. Untuk membuka kunci ciri ini, kita harus menambahkan pergantungan springdoc-openapi-data-rest :

 org.springdoc springdoc-openapi-data-rest 1.5.2 

Sekarang, ia menambahkan parameter pertanyaan yang diharapkan pada dokumentasi:

6. Menggunakan springdoc-openapi Maven Plugin

Perpustakaan springdoc-openapi menyediakan plugin Maven springdoc-openapi-maven-plugin untuk menghasilkan keterangan OpenAPI dalam format json dan 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