Spring BootのREST APIにSwaggerを導入する

[Spring Boot + MySQLでシンプルなWeb REST APIサーバを実装する - Qiita](https://qiita.com/YutaKase6/items/007f6b7d12d342c1330c)

# Outline
Spring Bootで作成したREST APIにSwaggerを導入する。
<img width=512 src="https://swagger.io/swagger/media/assets/images/swagger_logo.svg">

# ライブラリの追加
```diff
buildscript {
    ext {
        springBootVersion = '2.0.2.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

+ext {
+    springfoxSwagger2Version = '2.8.0'
+    springfoxSwaggerUiVersion = '2.8.0'
+}


dependencies {
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    compile('org.springframework.boot:spring-boot-starter-web')
+    compile("io.springfox:springfox-swagger2:${springfoxSwagger2Version}")
+    compile("io.springfox:springfox-swagger-ui:${springfoxSwaggerUiVersion}")
    runtime('mysql:mysql-connector-java')
    compileOnly('org.projectlombok:lombok')
    testCompile('org.springframework.boot:spring-boot-starter-test')
}
```

# 設定クラスの追加
各設定項目はよしなに。

```SwaggerConfig.java
package com.example.springapi.swagger;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger.web.UiConfiguration;
import springfox.documentation.swagger.web.UiConfigurationBuilder;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket swaggerSpringMvcPlugin() {
        return new Docket(DocumentationType.SWAGGER_2)
                .useDefaultResponseMessages(false)
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.regex("/v1.*"))
                .build()
                .apiInfo(apiInfo());
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Spring API")
                .description("Description.")
                .version("0.0.1")
                .contact(new Contact("name", "URL", "email"))
                .license("license")
                .licenseUrl("license URL")
                .termsOfServiceUrl("")
                .build();
    }

    @Bean
    public UiConfiguration uiConfig() {
        return UiConfigurationBuilder.builder()
                .displayRequestDuration(true)
                .validatorUrl("")
                .build();
    }
}

```

# 注意点
## ベースパスについて
ControllerにベースパスつけないとUIが起動しない。  

```xxxController.java
@RequestMapping("/v1")
public class Controller {
```

## 静的リソースへのアクセスを無効にしている場合
add-mapping: falseつけちゃってるみたいな場合。
以下のように明示的にSwagger　uiへのアクセスを設定する。

```WebMvcConfig.java
package com.example.springapi.swagger;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

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

        registry.addResourceHandler("/swagger-ui.html")
                .addResourceLocations(this.getStaticLocations());
    }

    private String[] getStaticLocations() {
        return new String[]{
                "/",
                "classpath:/META-INF/resources/",
                "classpath:/resources/",
                "classpath:/static/",
                "classpath:/public/",
        };
    }
}

```

## uiは表示されるけどエラーがでちゃう
<img width="125" alt="スクリーンショット 2018-08-04 14.32.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/90526/9b2eb7f5-bb61-7948-3a8e-97ec3c109789.png">
以下を追加する。

```SwaggerCongig.java
    @Bean
    public UiConfiguration uiConfig() {
        return UiConfigurationBuilder.builder()
                .validatorUrl("")
                .build();
    }
```

# 確認
/swagger-ui.htmlをGETしてください。  
おしゃんなのがでるはず。
<img width="1285" src="https://qiita-image-store.s3.amazonaws.com/0/90526/dc58cf2f-3a99-a10d-4edd-300a8a215c73.png">


# おまけ
Controllerやモデルにアノテーションを付与することで、カスタムできます。

```java
    /**
     * ユーザ検索
     *
     * @param id 検索したいユーザID
     * @return ユーザ
     */
    @ApiResponses({
            @ApiResponse(code = 404, message = "Not Found", response = ErrorResponse.class),
            @ApiResponse(code = 500, message = "Internal Server Error", response = ErrorResponse.class),
    })
    @GetMapping("{id}")
    @ResponseStatus(HttpStatus.OK)
    public User findById(@PathVariable("id") String id) {
        return this.userService.findById(id);
    }
```