Skip to content

Swagger2 Configuration

정명주(myeongju.jung) edited this page Apr 30, 2018 · 6 revisions

Dependencies

pom.xml

    <properties>
        ...
        <swagger2.version>2.9.0</swagger2.version>
    </properties>

    <dependencies>
        ...
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>${swagger2.version}</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>${swagger2.version}</version>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            ...
            <dependency>
                <groupId>com.google.guava</groupId>
                <artifactId>guava</artifactId>
                <version>24.1-jre</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
  • 2.9.0 버전으로 추가 시 guava 버전 충돌이 발생하므로 의존성 재정의 요망

build.gradle

ext['springfoxVersion'] = '2.7.0'

dependencies {
    compile "io.springfox:springfox-swagger2:${springfoxVersion}"
    compile "io.springfox:springfox-swagger-ui:${springfoxVersion}"
//    compile "io.springfox.ui:springfox-swagger-ui-rfc6570:1.0.0"   // incubating
}

Swagger2Configuration.java

/**
 * Swagger2 Configuration
 *
 * @author myeongju.jung
 */
@SuppressWarnings("Guava")
@Configuration
@ConditionalOnWebApplication
@EnableSwagger2
public class Swagger2Configuration {

    @Bean
    public Docket allApi() {
        return globalConfiguration(
            new Docket(DocumentationType.SWAGGER_2)
                .groupName("Example SNS API - All")
                .apiInfo(apiInfo())
                .select()
                .paths(allApiPaths())
                .build());

    }

    private Docket globalConfiguration(Docket docket) {
        return docket
            .directModelSubstitute(ZonedDateTime.class, Long.class)
            .ignoredParameterTypes(Pageable.class, UriComponentsBuilder.class, Model.class, UserDetails.class)
            .genericModelSubstitutes(ResponseEntity.class)
            .useDefaultResponseMessages(false)
            .globalResponseMessage(RequestMethod.GET, newArrayList(
                new ResponseMessageBuilder()
                    .code(400)
                    .message("인자가 유효하지 않는 경우")
                    .build(),
                new ResponseMessageBuilder()
                    .code(404)
                    .message("조회할 자원을 찾을 수 없는 경우")
                    .build(),
                new ResponseMessageBuilder()
                    .code(500)
                    .message("Internal Server Error")
                    .build()
                                                                  ))
            .globalResponseMessage(RequestMethod.POST, newArrayList(
                new ResponseMessageBuilder()
                    .code(400)
                    .message("인자가 유효하지 않는 경우")
                    .build(),
                new ResponseMessageBuilder()
                    .code(404)
                    .message("연관된 자원을 찾을 수 없는 경우")
                    .build(),
                new ResponseMessageBuilder()
                    .code(500)
                    .message("Internal Server Error")
                    .build()
                                                                     ))
            .globalResponseMessage(RequestMethod.PUT, newArrayList(
                new ResponseMessageBuilder()
                    .code(400)
                    .message("인자가 유효하지 않는 경우")
                    .build(),
                new ResponseMessageBuilder()
                    .code(404)
                    .message("변경할 자원을 찾을 수 없는 경우")
                    .build(),
                new ResponseMessageBuilder()
                    .code(500)
                    .message("Internal Server Error")
                    .build()
                                                                  ))
            .globalResponseMessage(RequestMethod.DELETE, newArrayList(
                new ResponseMessageBuilder()
                    .code(400)
                    .message("인자가 유효하지 않는 경우")
                    .build(),
                new ResponseMessageBuilder()
                    .code(404)
                    .message("삭제할 자원을 찾을 수 없는 경우")
                    .build(),
                new ResponseMessageBuilder()
                    .code(500)
                    .message("Internal Server Error")
                    .build()
                                                                  ))
            ;
    }

    private Predicate<String> allApiPaths() {
        return not(or(
            regex("/management.*"),
            regex("/error.*")
                     ));
    }

    @Bean
    public Docket postApi() {
        return globalConfiguration(
            new Docket(DocumentationType.SWAGGER_2)
                .groupName("Example SNS API - Post")
                .apiInfo(apiInfo())
                .select()
                .paths(postApiPaths())
                .build());
    }

    private Predicate<String> postApiPaths() {
        return or(
            regex("/posts.*"),
            regex("/recommend-posts.*"),
                 );
    }

    @Bean
    public Docket userApi() {
        return globalConfiguration(
            new Docket(DocumentationType.SWAGGER_2)
                .groupName("Example SNS API - User")
                .apiInfo(apiInfo())
                .select()
                .paths(userApiPaths())
                .build());
    }

    private Predicate<String> userApiPaths() {
        return or(
            regex("/user.*"),
            regex("/post\\-users.*")
                 );
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
            .title("Example SNS API")
            .description("적절한 설명 블라블라. html 태그는 사용할 수 없음")
            .termsOfServiceUrl("http://example-sns.co.kr")
            .contact(new Contact("Example SNS 개발팀", "http://corp.example-sns.co.kr", "dev@example-sns.co.kr"))
            .build();
    }
}

UserController.java

@Api(tags = "user", description = "사용자")
@RestController
@RequestMapping("/users")
public class UserRestController {
    @Autowired
    private UserService userService;

    /**
     * 사용자들 페이징 조회
     */
    @ApiOperation("사용자들 페이징 조회")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "page", value = "페이지 번호(0base)", required = false, defaultValue = "0", dataType = "number", paramType = "query"),
        @ApiImplicitParam(name = "size", value = "페이지 당 사이즈", required = false, defaultValue = "10", dataType = "number", paramType = "query")
    })
    @GetMapping("")
    public Page<UserRowDto> list(UserSearch search,
                                 @PageableDefault Pageable pageable) {
        return userService.getUserRows(search, pageable);
    }

    /**
     * 사용자 1건 상세 조회
     */
    @ApiOperation(value = "사용자 상세 조회")
    @GetMapping("/{userId}")
    public UserDetail detail(@ApiParam(value = "사용자아이디", required = true) @PathVariable("userId") String userId) {
        return userService.getUserDetail(userId);
    }

    /**
     * 사용자 소개글 변경
     */
    @ApiOperation(value = "사용자 소개글 변경")
    @PutMapping("/{userId}/introduction")
    public void modifyIntroduction(@ApiParam(value = "사용자아이디", required = true) @PathVariable("userId") String userId,
                                   @Valid @RequestBody UserIntroduction input) {
        userService.modifyIntroduction(userId, input.getValue());
    }

    /**
     * 페이지 신청
     */
    @ApiOperation(value = "페이지 신청", notes = "추후 페이지가 승인하면 정식 관리자로써 활성화. 복수 신청해도 멱등성으로 인해 페이지 신청이 인가된다.")
    @ApiResponses({
        @ApiResponse(code = 403, message = "페이지를 신청할 수 없는 상태인 경우 (휴면, 블랙 등)", response = ErrorModel.class),
        @ApiResponse(code = 404, message = "회원이 존재하지 않거나 탈퇴된 경우 발생", response = ErrorModel.class),
        @ApiResponse(code = 409, message = "일반적으로 이미 존재하는 페이지인 경우", response = ErrorModel.class)
    })
    @PostMapping("/pages")
    public ResponseEntity createPage(PageCreateRequest param, UriComponentsBuilder uriComponentsBuilder,
                                     @AuthenticationPrincipal UserDetails) {
        Page page = pageService.request(param, userDetails);
        URI location = getLocation(page, uriComponentsBuilder);
        return ResponseEntity.created(location).build();
    }

    private URI getLocation(Page page, UriComponentsBuilder uriComponentsBuilder) {
        return uriComponentsBuilder.path("/pages/{pageId}/")
                                   .buildAndExpand(page.getPageId())
                                   .toUri();
    }
}
Clone this wiki locally