작업하면서 배우는 것들

SpringFox:Swagger3 사용

Jungsoomin :) 2021. 1. 5. 23:47

스웨거 사양이 3 버전으로 올라감에 따라 변경 점을 찾은 부분과 과정을 기술

 

필요의존

버전이 올라감에 따라 필요의존은 단 하나이다.

# swagger2 , swagger-ui, swagger, web, webflux 등이 모두 포함
implementation 'io.springfox:springfox-boot-starter:3.0.0'

@EnableSwagger2 어노테이션은 불필요

스프링부트의 자동설정에 의해 자동으로 설정이 마쳐진다.

 

해본 예로는 @Value 어노테이션에  SpEl 을 사용하여 기술하였다.

 

  • Api Info 는 공통적으로 기술될 문서의 버전과 설명을 의미한다.
    • apiVersion : 문서의 버전
    • apiTitle : 문서의 이름
    • apiDescription : 문서에 대한 설명
    • termOfServiceUrl : "Terms of service" 링크에 기술될 url
    • license : 라이센스링크의 <a> 태그 안에 기술될 문자
    • licenseUrl : 라이센스 링크에 기술될 url
    • contactName : "[name] - Website", "Send email to [name]" 에 기술될 이름
    • contactUrl : "Send email to [name]" 링크에 기술될 url
    • contactEmail : "Send email to [name]" 클릭시 송신할 이메일 주소
  • Docket 은 Api 구성에 반드시 필요한 Bean 이다.
    • apis()basePackage() 를 지정하여 Api 들을 검색할 수 있다. Swagger 의 어노테이션, Web 의 어노테이션을 기반으로 찾아낸다.
import java.util.Collections;

import static springfox.documentation.builders.RequestHandlerSelectors.basePackage;

@SpringBootApplication(scanBasePackages = "me.soomin")
public class ProductCompositeServiceApplication {

    @Value("${api.common.version}") String apiVersion;
    @Value("${api.common.title}") String apiTitle;
    @Value("${api.common.description}") String apiDescription;
    @Value("${api.common.termsOfServiceUrl}") String apiTermsOfServiceUrl;
    @Value("${api.common.license}") String apiLicense;
    @Value("${api.common.licenseUrl}") String apiLicenseUrl;
    @Value("${api.common.contact.name}") String apiContactName;
    @Value("${api.common.contact.url}") String apiContactUrl;
    @Value("${api.common.contact.email}") String apiContactEmail;

    /**
     *   $HOST:$PORT/swagger-ui/
     * @return
     */
    @Bean
    public Docket apiDocument() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(basePackage("me.soomin.productcompositeservice.services"))// apis 의 basePackage 는 이하 패키지까지의 Swagger 어노테이션, Web 어노테이션을 찾아 냄
                .paths(PathSelectors.any())
                .build()
                    .apiInfo(new ApiInfo(
                            apiTitle,
                            apiDescription,
                            apiVersion,
                            apiTermsOfServiceUrl,
                            new Contact(apiContactName,apiContactUrl,apiContactEmail),
                            apiLicense,
                            apiLicenseUrl,
                            Collections.emptyList()
                    ));
    }
    ...
 }

 


API 에 기술할 정보

 

인터페이스로 정의를 해놓아서 생성자에 @Value 를 넣어 ApiResponse에 넣기가 좀 모호한 것 같다. 

  • @Api 어노테이션으로 해당 API 인터페이스, 클래스에 대한 검색과 더불어 설명을 단다.
  • @ApiOperation SpEl 을 지원하여 소제목인 value , 자세한 설명인 note 를 지정할 수 있다.
  • @ApiResponsesSwagger v3 의 어노테이션이다.  
    • value@ApiResponse 의 배열을 가진다.
    • responseCode : 응답 코드
    • description : 응답코드에 대한 안내
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@Api(description = "REST API for composite product information. :)")
public interface ProductCompositeService {

    /**
     * 사용: curl $HOST:$PORT/product-composite/1
     * @param productId
     * @return
     */
    @ApiOperation(
            value = "${api.product-composite.get-composite-product.description}",
            notes = "${api.product-composite.get-composite-product.notes}"
    )
    @ApiResponses(value = {
            @ApiResponse(responseCode = "400",
                    description = "Bad Request, invalid format of the request. See response message for more information."),
            @ApiResponse(responseCode = "404",
                    description = "Not found, the specified id does not exist."),
            @ApiResponse(responseCode = "422",
                    description = "Unprocessable entity, input parameters caused the processing to fails. See response message for more information.")
    })
    @GetMapping(value = "/product-composite/{productId}",produces = "application/json")
    ProductAggregate getProduct(@PathVariable int productId);
}

 


application.yml

  • Spring Cloud Bus 에 의한 설정파일 변경에 요긴할 것 같다는 생각이 들어 속성파일로 작성했다.
  • 마크다운 문법을 지원한다.
  • yaml 문법에서       은 개행을 의미한다.
api:

  common:
    version: 1.0.0
    title: Study API
    description: Description of the Common API
    termsOfServiceUrl: MINE TERMS OF SERVICE URL
    license: License
    licenseUrl: My License Url

    contact:
      name: SooMin
      url: SooMinJung.com
      email: doli061214@gmail.com

  product-composite:
    get-composite-product:
      description: Returns a composite view of the spectified product id
      notes: |
        # Normal response
        If the requested product id is found the method will return information regarding:
        1. Base product information
        1. Reviews
        1. Recommendations
        1. Service Addresses\n(technical information regarding the addresses of the microservices that created the response)

        # Expected partial and error responses
        In the following cases, only a partial response be created (used to simplify testing of error conditions)

        ## Product id 113
        200 - Ok, but no recommendations will be returned

        ## Product id 213
        200 - Ok, but no reviews will be returned

        ## Non numerical product id
        400 - A <b>Bad Request</b> error will be returned

        ## Product id 13
        404 - A <b>Not Found</b> error will be returned

        ## Negative product ids
        422 - An <b>Unprocessable Entity</b> error wiil be returned
        
        

 


Swagger v3 사양의 엔드포인트는 /swagger-ui/ 이다.

  • 개인적으로 드는 생각은 설정면에서 많은 것이 사라지게 되었다는 점 같다.