1. 개요

문서는 REST API를 빌드하는 데 필수적인 부분입니다. 이 자습서에서는 Spring Boot 1.x 및 2.x 애플리케이션 용 OpenAPI 3 사양을 기반으로 API 문서의 생성 및 유지 관리를 단순화하는 도구 인 SpringDoc을 살펴 보겠습니다.

2. springdoc-openapi 설정

가지고 springdoc - OpenAPI를을 자동으로 우리의 API에 대한 OpenAPI를 3 사양 문서를 생성, 우리는 간단하게 추가 springdoc - OpenAPI를-UI를 우리에게 종속 의 pom.xml :

<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-ui</artifactId>
    <version>1.5.2</version>
</dependency>

그런 다음 애플리케이션을 실행할 때 기본적으로 / v3 / api-docs 경로에서 OpenAPI 설명을 사용할 수 있습니다 .

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

사용자 지정 경로를 사용하려면 application.properties 파일에 다음 과 같이 나타낼 수 있습니다 .

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

이제 다음 위치에서 문서에 액세스 할 수 있습니다.

http://localhost:8080/api-docs/

OpenAPI 정의는 기본적으로 JSON 형식입니다. 들어 YAML의 형식으로, 우리는 정의를에서 얻을 수 있습니다 :

http://localhost:8080/api-docs.yaml

3. Swagger UI로 springdoc-openapi 설정

OpenAPI 3 사양 자체를 생성하는 것 외에도 springdoc-openapi를 Swagger UI와 통합하여 API 사양과 상호 작용하고 엔드 포인트를 실행할 수 있습니다.

3.1. Maven 의존성

Swagger UI로 springdoc-openapi를 설정하기 위해해야 ​​할 일은 프로젝트의 pom.xml에 springdoc-openapi-ui 의존성을 추가하는 것입니다 .

<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-ui</artifactId>
    <version>1.5.2</version>
</dependency>

이제 다음 위치에서 API 문서에 액세스 할 수 있습니다.

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

3.2. swagger-ui 속성 지원

Springdoc-openapi는 swagger-ui 속성 도 지원 합니다 . 접두사 springdoc.swagger-ui를 사용하여 Spring Boot 속성으로 사용할 수 있습니다 .

예를 들어 API 문서의 경로를 사용자 지정해 보겠습니다. 다음을 포함하도록 application.properties수정하여이를 수행 할 수 있습니다.

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

이제 API 문서는 http : // localhost : 8080 / swagger-ui-custom.html 에서 사용할 수 있습니다 .

또 다른 예로, HTTP 메서드 순서대로 API 경로를 정렬하려면 다음을 추가 할 수 있습니다.

springdoc.swagger-ui.operationsSorter=method

3.3. 샘플 API

애플리케이션에 Book 을 관리하기위한 컨트롤러가 있다고 가정합니다 .

@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<Book> findBooks() {
        return repository.getBooks();
    }

    @PutMapping("/{id}")
    @ResponseStatus(HttpStatus.OK)
    public Book updateBook(
      @PathVariable("id") final String id, @RequestBody final Book book) {
        return book;
    }
}

그런 다음 응용 프로그램을 실행할 때 다음 위치에서 설명서를 볼 수 있습니다.

http://localhost:8080/swagger-ui-custom.html
Swagger UI

/ api / book 엔드 포인트 로 드릴 다운 하고 요청 및 응답에 대한 세부 정보를 살펴 보겠습니다 .
Swagger UI API 세부 사항

4. springdoc-openapi를 Spring WebFlux와 통합하기

springdoc-openapi-webflux-ui 를 추가하여 Spring WebFlux 프로젝트에서 springdoc-openapi와 Swagger UI를 통합 할 수 있습니다 .

<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-webflux-ui</artifactId>
    <version>1.5.2</version>
</dependency>

이전과 마찬가지로 다음 위치에서 문서에 액세스 할 수 있습니다.

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

경로를 정의하기 위해, 우리는 다시 추가 할 수 있습니다 springdoc.swagger - ui.path의 우리의 재산을 application.properties .

5. 페이지 매김 정보 노출

SpringData JPA는 Spring MVC와 매우 원활하게 통합됩니다. 이러한 통합의 한 가지 예는 Pageable  지원입니다.

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

처음에는 SpringDoc 이 생성 된 문서 page , size정렬 쿼리 매개 변수를 추가 할 것으로 예상 할 수 있습니다 . 그러나 기본적으로 SpringDoc은 이러한 기대를 충족하지 않습니다. 이 기능을 잠금 해제하려면 springdoc-openapi-data-rest  의존성을 추가해야합니다 .

<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-data-rest</artifactId>
    <version>1.5.2</version>
</dependency>

이제 예상되는 쿼리 매개 변수를 문서에 추가합니다.

6. springdoc-openapi Maven 플러그인 사용

springdoc-openapi 라이브러리는 jsonyaml 형식으로 OpenAPI 설명을 생성하기위한 Maven 플러그인 springdoc-openapi-maven-plugin제공합니다.

springdoc - OpenAPI를-Maven은-플러그인 와 플러그인 작동 스프링 부팅 받는다는 플러그인을. Maven은 통합 테스트 단계 에서 openapi 플러그인을 실행합니다  .

pom.xml 에서 플러그인을 구성하는 방법을 살펴 보겠습니다 .

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>2.3.3.RELEASE</version>
    <executions>
        <execution>
            <id>pre-integration-test</id>
            <goals>
                <goal>start</goal>
            </goals>
        </execution>
        <execution>
            <id>post-integration-test</id>
            <goals>
                <goal>stop</goal>
            </goals>
        </execution>
    </executions>
</plugin>
<plugin>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-maven-plugin</artifactId>
    <version>0.2</version>
    <executions>
        <execution>
            <phase>integration-test</phase>
            <goals>
                <goal>generate</goal>
            </goals>
        </execution>
    </executions>
</plugin>

사용자 정의 값을 사용하도록 플러그인을 구성 할 수도 있습니다.

<plugin>
    <executions>
        .........
    </executions>
    <configuration> 
        <apiDocsUrl>http://localhost:8080/v3/api-docs</apiDocsUrl> 
        <outputFileName>openapi.json</outputFileName> 
        <outputDir>${project.build.directory}</outputDir> 
    </configuration>
</plugin>

플러그인에 대해 구성 할 수있는 매개 변수를 자세히 살펴 보겠습니다.

  • apiDocsUrlhttp : // localhost : 8080 / v3 / api-docs 의 기본값을 사용하여 JSON 형식으로 문서에 액세스 할 수있는 URL
  • outputFileName – 정의가 저장된 파일의 이름, 기본값은 openapi.json입니다.
  • outputDir – 문서가 저장된 디렉토리의 절대 경로 (기본값 : $ {project.build.directory})

7. JSR-303 Bean 유효성 검사를 사용한 자동 문서 생성

모델에 @NotNull , @NotBlank , @Size , @Min@Max 와 같은 JSR-303 빈 유효성 검사 어노테이션이 포함 된  경우 springdoc-openapi 라이브러리는이를 사용하여 해당 제약 조건에 대한 추가 스키마 문서를 생성합니다.

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;

}

이제 Book bean에 대해 생성 된 문서 가 좀 더 유익합니다.
빈 검증 추가 후 책 스키마

8. @ControllerAdvice@ResponseStatus를 사용하여 문서 생성

@RestControllerAdvice 클래스의 메소드에서 @ResponseStatus사용 하면 응답 코드에 대한 문서가 자동으로 생성됩니다. @RestControllerAdvice 클래스에서 두 메서드는 @ResponseStatus 로 어노테이션 처리됩니다 .

@RestControllerAdvice
public class GlobalControllerExceptionHandler {

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

결과적으로 이제 응답 코드 400 및 404에 대한 문서를 볼 수 있습니다.
@ControllerAdvice 및 @ResponseStatus에 대한 문서

9. @Operation@ApiResponses를 사용하여 문서 생성

다음으로 몇 가지 OpenAPI 관련 어노테이션을 사용하여 API에 설명을 추가하는 방법을 살펴 보겠습니다 .

이를 위해 컨트롤러의 / api / book / {id}  엔드 포인트에 @Operation@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());
}

효과는 다음과 같습니다.

보시다시피 @Operation에 추가 한 텍스트는 API 작업 수준에 배치됩니다. 마찬가지로 @ApiResponses 컨테이너 어노테이션 다양한 @ApiResponse 요소에 추가 된 설명 도 여기에 표시되어 API 응답에 의미를 추가합니다.

분명히 위의 응답 400 및 404에 대한 스키마를 얻지 못했습니다. @Content정의 했으므로 설명 만 표시됩니다.

10. Kotlin 지원

Spring Boot 2.x는 Kotlin에 대한 최고 수준의 지원을 제공하므로 SpringDoc은 Boot 2.x 애플리케이션에 대해이 JVM 언어를 즉시 지원합니다.

이를 확인하기 위해 Kotlin에서 간단한 Foo API를 만들겠습니다 .

초기 설정데이터 클래스와 컨트롤러를 추가합니다. Boot App의 하위 패키지에 추가하여 실행될 때 이전 BookController 와 함께 FooController선택합니다 .

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

이제 API 문서 URL을 입력하면 Foo API도 볼 수 있습니다.

Kotlin 유형의 지원을 강화하기 위해 다음 의존성을 추가 할 수 있습니다.

<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-kotlin</artifactId
    <version>1.3.9</version>
</dependency>

그 후, Foo 스키마는 JSR-303 Bean 유효성 검사를 추가했을 때처럼 더 많은 정보를 제공합니다.

11. 결론

이 기사에서는 프로젝트에서 springdoc-openapi를 설정하는 방법을 배웠습니다. 그런 다음 springdoc-openapi를 Swagger UI와 통합하는 방법을 보았습니다. 또한 Spring Webflux 프로젝트로이를 수행하는 방법도 보았습니다.

다음으로 springdoc-openapi Maven Plugin을 사용하여 API에 대한 OpenAPI 정의를 생성하고 SpringData에서 페이징 및 정렬 정보를 노출하는 방법을 살펴 보았습니다. 그 후 springdoc-openapi가 JSR 303 빈 유효성 검사 어노테이션과 @ControllerAdvice 클래스 @ResponseStatus 어노테이션을 사용하여 문서를 자동으로 생성하는 방법을 살펴 보았습니다 .

또한 몇 가지 OpenAPI 관련 어노테이션을 사용하여 API에 설명을 추가하는 방법도 배웠습니다. 마지막으로 OpenAPI의 Kotlin 지원을 살펴 보았습니다.

springdoc-openapi는 OpenAPI 3 사양에 따라 API 문서를 생성합니다. 또한 Swagger UI 구성도 처리하므로 API 문서 생성이 매우 간단합니다.

항상 그렇듯이 코드는 GitHub에서 사용할 수 있습니다 .