Spring

Swagger 를 통한 Spring Rest API 자동화

기록만이살길 2020. 6. 10. 23:39
반응형

Swagger 를 통한 Spring Rest API 자동화

1. 개요

오늘날 프론트 엔드 및 백엔드 구성 요소는 종종 웹 애플리케이션을 분리합니다. 일반적으로 프런트 엔드 구성 요소 또는 타사 앱 통합을위한 API를 백 엔드 구성 요소로 노출합니다.

이러한 시나리오에서는 백엔드 API에 대한 적절한 스펙이 있어야합니다. 동시에, API 문서는 정보를 제공하고 읽기 쉽고 따르기 쉬워야합니다.

또한 참조 문서는 API의 모든 변경 사항을 동시에 설명해야합니다. 이 작업을 수동으로 수행하는 것은 지루한 작업이므로 프로세스 자동화는 필수입니다.

이 튜토리얼에서는 Swagger 2 사양의 Springfox 구현을 사용하여 Spring REST 웹 서비스 용 Swagger 2를 살펴 봅니다 .

2. 목표

예제에서 사용할 REST 서비스 작성은이 기사의 범위에 포함되지 않습니다. 적합한 프로젝트가 이미 있다면 사용하십시오. 그렇지 않은 경우 다음 링크를 시작하는 것이 좋습니다.

3. Maven 의존성 추가

위에서 언급했듯이 Swagger 사양의 Springfox 구현을 사용합니다. 최신 버전은 Maven Central 에서 찾을 수 있습니다 .

Maven 프로젝트에 추가하려면 pom.xml 파일 에 대한 종속성이 필요 합니다.

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>

4. Swagger 2를 프로젝트에 통합

4.1. 자바 구성

Swagger의 구성은 주로 Docket Bean을 중심으로합니다 .

@Configuration
@EnableSwagger2
public class SpringFoxConfig {                                    
    @Bean
    public Docket api() { 
        return new Docket(DocumentationType.SWAGGER_2)  
          .select()                                  
          .apis(RequestHandlerSelectors.any())              
          .paths(PathSelectors.any())                          
          .build();                                           
    }
}

Swagger 2는 @ EnableSwagger2 주석을 통해 활성화됩니다 .

애프터 도켓 빈을 정의하고, 그것의 선택 () 메소드의 인스턴스를 반환 ApiSelectorBuilder 자신감 의해 노출 된 엔드 포인트를 제어하는 방법을 제공한다.

RequestHandler 선택을위한 술어 는 RequestHandlerSelectorsPathSelectors 의 도움으로 구성 될 수 있습니다 . 둘 다에 any () 를 사용하면 Swagger를 통해 전체 API에 대한 문서를 사용할 수 있습니다.

이 구성은 Swagger 2를 기존 Spring Boot 프로젝트에 통합하기에 충분합니다. 다른 Spring 프로젝트의 경우 추가 조정이 필요합니다.

4.2. 스프링 부트없는 구성

Spring Boot가 없으면 리소스 핸들러의 고급 자동 구성 기능이 없습니다. Swagger UI는 WebMvcConfigurerAdapter 를 확장하고 @EnableWebMvc 로 주석이 달린 클래스의 일부로 구성해야하는 자원 세트를 추가합니다 .

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("swagger-ui.html")
      .addResourceLocations("classpath:/META-INF/resources/");

    registry.addResourceHandler("/webjars/**")
      .addResourceLocations("classpath:/META-INF/resources/webjars/");
}

4.3. 확인

Springfox가 작동하는지 확인하려면 브라우저에서 다음 URL을 방문하십시오.

http : // localhost : 8080 / spring-security-rest / api / v2 / api-docs

그 결과 많은 키-값 쌍이 포함 된 JSON 응답이 생성되므로 사람이 쉽게 읽을 수는 없습니다. 다행히 Swagger는 이러한 목적으로 Swagger UI 를 제공합니다 .

5. 스와 거 UI

Swagger UI는 Swagger 생성 API 문서와의 사용자 상호 작용을 훨씬 쉽게하는 내장 솔루션입니다.

5.1. Springfox의 Swagger UI 활성화

Swagger UI를 사용하려면 하나의 추가 Maven 종속성이 필요합니다.

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>

이제 http : // localhost : 8080 / your-app-root / swagger-ui.html 을 방문하여 브라우저에서 테스트 할 수 있습니다 .

우리의 경우, 정확한 URL은 다음과 같습니다. http : // localhost : 8080 / spring-security-rest / api / swagger-ui.html

결과는 다음과 같아야합니다.

https://www.baeldung.com/wp-content/uploads/2016/07/Screenshot_11.png

5.2. Swagger 문서 탐색

Swagger의 응답에는 응용 프로그램에 정의 된 모든 컨트롤러 목록이 있습니다. 이들 중 하나를 클릭하면 유효한 HTTP 메소드 ( DELETE , GET , HEAD , OPTIONS , PATCH , POST , PUT ) 가 나열됩니다 .

각 방법을 확장하면 응답 상태, 내용 유형 및 매개 변수 목록과 같은 유용한 데이터가 추가로 제공됩니다. UI를 사용하여 각 방법을 시도 할 수도 있습니다.

Swagger의 코드 기반과의 동기화 기능은 매우 중요합니다. 이를 설명하기 위해 애플리케이션에 새 컨트롤러를 추가 할 수 있습니다.

이제 Swagger 문서를 새로 고치면 컨트롤러 목록에 사용자 정의 컨트롤러 가 표시 됩니다. 아시다시피 Swagger의 응답 에는 하나의 메소드 ( POST ) 만 표시됩니다.

@RestController
public class CustomController {

    @RequestMapping(value = "/custom", method = RequestMethod.POST)
    public String custom() {
        return "custom";
    }
}

6. 스프링 데이터 REST

Springfox는 springfox-data-rest 라이브러리를 통해 Spring Data REST 를 지원합니다 .

springfox 데이터-나머지 라이브러리의 2.9.2 버전은 봄 부팅이 봄 데이터 REST API와 원활한 통합을 제공하지 않습니다.

따라서 Springfox 라이브러리의 3.0.0-SNAPSHOT 버전을 사용합니다.

스냅 샷 저장소 및 필요한 Maven 종속성을 pom.xml에 추가하십시오 .

<repositories>
    <repository>
        <id>jcenter-snapshots</id>
        <name>jcenter</name>
        <url>http://oss.jfrog.org/artifactory/oss-snapshot-local/</url>
    </repository>
</repositories>

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>3.0.0-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-data-rest</artifactId>
    <version>3.0.0-SNAPSHOT</version>
</dependency>

이제 User 라는 엔터티를 만듭니다 .

@Entity
public class User {
    @Id
    private Long id;
    private String firstName;
    private int age;
    private String email;

    // getters and setters
}

그런 다음 User 엔티티 에 CRUD 오퍼레이션을 추가하기 위해 UserRepository 를 작성합니다 .

@Repository
public interface UserRepository extends CrudRepository<User, Long> {
}

마지막으로, 우리는 가져올 수 있습니다 SpringDataRestConfiguration을 받는 클래스를 SpringFoxConfig의 클래스 :

@EnableSwagger2WebMvc
@Import(SpringDataRestConfiguration.class)
public class SpringFoxConfig {
    //...
}

참고 : @ EnableSwagger2WebMvc 주석을 사용 하여 라이브러리 버전 3의 @ EnableSwagger2 주석을 대체했기 때문에 Swagger를 활성화했습니다 .

Spring Data REST API에 대한 스펙을 생성하기 위해 애플리케이션을 다시 시작하자.

https://www.baeldung.com/wp-content/uploads/2015/12/springdatarest-1024x705-1.png

Springfox가 GET , POST, PUT, PATCHDELETE 와 같은 HTTP 메소드 를 사용하여 User 엔티티 의 스펙을 생성했음을 알 수 있습니다 .

7. 빈 검증

Springfox는 또한 springfox-bean-validators 라이브러리를 통해 bean 유효성 검사 주석을 지원합니다 .

먼저 Maven 의존성을 pom.xml에 추가합니다 :

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-bean-validators</artifactId>
    <version>2.9.2</version>
</dependency>

그런 다음 @NotNull@Min 과 같은 몇 가지 유효성 검사 주석 을 사용자 엔터티에 추가하겠습니다 .

@Entity
public class User {
    //...

    @NotNull(message = "First Name cannot be null")
    private String firstName;

    @Min(value = 15, message = "Age should not be less than 15")
    @Max(value = 65, message = "Age should not be greater than 65")
    private int age;
}

마지막으로, 우리는 가져올 수 있습니다 BeanValidatorPluginsConfiguration을 받는 클래스 SpringFoxConfig의 클래스를 :

@EnableSwagger2
@Import(BeanValidatorPluginsConfiguration.class)
public class SpringFoxConfig {
    //...
}

API 사양의 변경 사항을 살펴 보겠습니다.

https://www.baeldung.com/wp-content/uploads/2015/12/beanValidation3-1024x709-1.png

여기서 우리는 User 모델이 firstName* 필수 가 있음을 알 수 있습니다 . 또한 연령에 대한 최소값최대 값이 정의됩니다 .

8. 플러그인

API 사양에 특정 기능을 추가하기 위해 Springfox 플러그인을 만들 수 있습니다. 플러그인은 모델 및 속성 강화에서 사용자 정의 API 목록 및 기본값에 이르기까지 다양한 기능을 제공 할 수 있습니다.

Springfox는 spi 모듈을 통한 플러그인 생성을 지원합니다 . spi 모듈은 ModelBuilderPlugin , ModelPropertyBuilderPluginApiListingBuilderPlugin 과 같은 몇 가지 인터페이스를 제공 하여 사용자 정의 플러그인을 구현하기위한 확장 성 후크 역할을합니다.

기능을 시연하기 위해 사용자 모델 의 전자 메일 속성 을 강화하는 플러그인을 만들어 봅시다 . ModelPropertyBuilderPlugin 인터페이스를 사용하여 patternexample 의 값을 설정합니다 .

먼저 EmailAnnotationPlugin 클래스를 만들고 supports 메소드를 재정 의하여 Swagger 1.2 및 Swagger 2와 같은 문서 유형 을 허용하도록 하겠습니다 .

@Component
@Order(Validators.BEAN_VALIDATOR_PLUGIN_ORDER)
public class EmailAnnotationPlugin implements ModelPropertyBuilderPlugin {
    @Override
    public boolean supports(DocumentationType delimiter) {
        return true;
    }
}

그런 다음 ModelPropertyBuilderPluginapply 메소드를 재정 의하여 빌더 특성 값을 설정합니다.

@Override
public void apply(ModelPropertyContext context) {
    Optional<Email> email = annotationFromBean(context, Email.class);
    if (email.isPresent()) {
        context.getBuilder().pattern(email.get().regexp());
        context.getBuilder().example("email@email.com");
    }
}

따라서 API 사양 에는 @Email 주석으로 주석이 달린 속성 의 패턴예제 값 이 표시 됩니다.

다음으로 @Email 주석을 User 엔터티에 추가합니다 .

@Entity
public class User {
    //...

    @Email(regexp=".@.\\..*", message = "Email should be valid")
    private String email;
}

마지막 으로 Bean으로 등록 하여 SpringFoxConfig 클래스 에서 EmailAnnotationPlugin 을 활성화합니다 .

@Import({BeanValidatorPluginsConfiguration.class})
public class SpringFoxConfig {
    //...

    @Bean
    public EmailAnnotationPlugin emailPlugin() {
        return new EmailAnnotationPlugin();
    }
}

작동 중인 EmailAnnotationPlugin 을 확인하십시오 .

https://www.baeldung.com/wp-content/uploads/2015/12/emailAnnotationPlugin4-1024x706-1.png

패턴 의 값 이 User 엔터티 의 전자 메일 속성과 동일한 정규식 ( . @. \ .. *) 임을 알 수 있습니다.

마찬가지로 예제 ( email@email.com ) 의 값은 EmailAnnotationPlugin 의 apply 메소드에 정의 된 것과 같습니다 .

9. 고급 구성

API 문서 생성 프로세스를보다 강력하게 제어 할 수 있도록 애플리케이션 의 Docket Bean을 구성 할 수 있습니다.

9.1. Swagger의 응답을위한 필터링 API

전체 API에 대한 문서를 항상 공개하는 것은 바람직하지 않습니다. Docket 클래스 의 apis ()paths () 메서드에 매개 변수를 전달하여 Swagger의 응답을 제한 할 수 있습니다 .

위에서 본 것처럼 RequestHandlerSelectorsany 또는 none 술어 사용을 허용 하지만 기본 패키지, 클래스 주석 및 메소드 주석에 따라 API를 필터링하는 데 사용될 수도 있습니다.

PathSelectors 는 애플리케이션의 요청 경로를 스캔하는 술어를 사용하여 추가 필터링을 제공합니다. 당신이 사용할 수 있는 () , 없음 (), 정규식 () , 또는 개미 () .

아래 예제에서는 ant () 조건 자를 사용하여 특정 경로의 특정 패키지의 컨트롤러 만 포함하도록 Swagger에 지시 합니다.

@Bean
public Docket api() {                
    return new Docket(DocumentationType.SWAGGER_2)          
      .select()                                       
      .apis(RequestHandlerSelectors.basePackage("com.baeldung.web.controller"))
      .paths(PathSelectors.ant("/foos/*"))                     
      .build();
}

9.2. 맞춤 정보

Swagger는 또한 응답에 "Api 문서", "연락처 이메일로 작성", "Apache 2.0"과 같이 사용자 정의 할 수있는 일부 기본값을 제공합니다.

이 값을 변경하려면 apiInfo (ApiInfo apiInfo) 메소드를 사용하십시오. API에 대한 사용자 정의 정보가 포함 된 ApiInfo 클래스입니다.

@Bean
public Docket api() {                
    return new Docket(DocumentationType.SWAGGER_2)          
      .select()
      .apis(RequestHandlerSelectors.basePackage("com.example.controller"))
      .paths(PathSelectors.ant("/foos/*"))
      .build()
      .apiInfo(apiInfo());
}

private ApiInfo apiInfo() {
    return new ApiInfo(
      "My REST API", 
      "Some custom description of API.", 
      "API TOS", 
      "Terms of service", 
      new Contact("John Doe", "www.example.com", "myeaddress@company.com"), 
      "License of API", "API license URL", Collections.emptyList());
}

9.3. 사용자 정의 방법 응답 메시지

Swagger는 DocketglobalResponseMessage () 메소드를 통해 HTTP 메소드의 응답 메시지를 전체적으로 대체 할 수 있습니다 . 먼저 Swagger에 기본 응답 메시지를 사용하지 않도록 지시해야합니다.

모든 GET 메소드에 대해 500403 응답 메시지 를 대체한다고 가정하십시오 . 이를 위해 Docket 의 초기화 블록에 일부 코드를 추가해야합니다 (명확성을 위해 원래 코드는 제외됨).

.useDefaultResponseMessages(false)                                   
.globalResponseMessage(RequestMethod.GET,                     
  newArrayList(new ResponseMessageBuilder()   
    .code(500)
    .message("500 message")
    .responseModel(new ModelRef("Error"))
    .build(),
    new ResponseMessageBuilder() 
      .code(403)
      .message("Forbidden!")
      .build()));

https://www.baeldung.com/wp-content/uploads/2016/07/Screenshot_2.png

11. 결론

이 학습서에서는 Spring REST API에 대한 문서를 생성하도록 Swagger 2를 설정했습니다. 또한 Swagger의 출력을 시각화하고 사용자 정의하는 방법도 살펴 보았습니다.

참고

https://www.baeldung.com/swagger-2-documentation-for-spring-rest-api

반응형