Spring Foxで作ったAPI仕様書に載せたくない非公開APIがあるんだよ

全部を載せたくないんだよね

例えばこんな風にパッケージが分かれてるとして

```
controller
　├admin
　│　└AdminSampleController
　└other
　　　└OtherController
```

admin配下のAPIはドキュメントに載せたくない

つまりは非公開APIにしておきたい　っていう

# 環境

Spring Boot 2.2.3.RELEASE - 2.2.4.RELEASE
Spring Fox 2.9.2
Kotlin 1.3.61
Gradle

環境は以下の記事のまんま

https://qiita.com/ShassBeleth/items/3f3afca83b8ef0b98ede

# 誤解したとこ

```SpringBootExampleApplication.kt
@SpringBootApplication
@EnableSwagger2
@ComponentScan( basePackageClasses = [ OtherController::class ] )
class SpringBootExampleApplication
```

`@ComponentScan`で表示させるものを指定すればいいのかと思ってたけどここを指定すると確かにAPIの一覧には出てこなくなったもののAPI自体コールできなくなる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/195499/61efcc39-3648-063b-936e-9a87365286cf.png)

# 正解

適当なアノテーションを一つ作っておく
以下のアノテーションを付けたらAPI仕様書に表示しないようにしたい

```IgnoreSwaggerDocument.kt
annotation class IgnoreSwaggerDocument
```

```SwaggerConfig.kt
class SwaggerConfig {

    @Bean
    fun configurateApiDocument(): Docket {
        val apiSelectBuilder : ApiSelectorBuilder = Docket(DocumentationType.SWAGGER_2).select();

        // 全てのAPIを表示
        // apiSelectBuilder.apis(RequestHandlerSelectors.any())
        // 特定のアノテーションがクラスについているAPIのみ表示
        apiSelectBuilder.apis(not(RequestHandlerSelectors.withClassAnnotation(IgnoreSwaggerDocument::class.java)))
        // 特定のアノテーションがメソッドについているAPIのみ非表示
        apiSelectBuilder.apis(not(RequestHandlerSelectors.withMethodAnnotation(IgnoreSwaggerDocument::class.java)))
        return apiSelectBuilder.build();
    }
```
適当に印になるannotationを作って(作らなくてもいいけど)、`withClassAnnotation`と`withMethodAnnotation`で特定のアノテーションがついているクラスやメソッドを表示したり非表示にしたりできるっていうね

`com.google.common.base.Predicates.not`をimportしとくとアノテーションがついてるAPIだけ非表示とかもできるから便利

# 確認

```DocumentIgnoreController.kt
@IgnoreSwaggerDocument
@RequestMapping( "/swagger/ignore")
@RestController
class DocumentIgnoreController {
    fun getSampleController() : String = "sample"
}
```
これはクラスにアノテーションを

``` DocumentUnIgnoreController.kt
@RequestMapping( "/swagger/un-ignore")
@RestController
class DocumentUnIgnoreController {

    @GetMapping( "/sample" )
    @IgnoreSwaggerDocument
    fun getSample() : String = "sample"

    @GetMapping("/sample2")
    fun getSample2() : String = "sample2"

}
```
こっちにはメソッドにアノテーションを

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/195499/1720f3cf-77eb-f56f-e6d4-9432e75c1ed1.png)

こんな感じに作ったアノテーションがついてるクラスやメソッドは非表示になった！

パッケージ名で制御することもできるみたい

```IgnorePackageController.kt
package com.example.spring.boot.web.controller.spring.fox.example.ignore

@RestController
class IgnorePackageController {
    @GetMapping( "/api/swagger/ignore/package")
    fun getSample() : String = "sample"
}
```

```SwaggerConfig.kt
    @Bean
    fun configurateApiDocument(): Docket {
        val apiSelectBuilder : ApiSelectorBuilder = Docket(DocumentationType.SWAGGER_2).select();

        // 全てのAPIを表示
        // apiSelectBuilder.apis(RequestHandlerSelectors.any())
        // 特定のアノテーションがクラスについているAPIのみ非表示
        apiSelectBuilder.apis(not(RequestHandlerSelectors.withClassAnnotation(IgnoreSwaggerDocument::class.java)))
        // 特定のアノテーションがメソッドについているAPIのみ非表示
        apiSelectBuilder.apis(not(RequestHandlerSelectors.withMethodAnnotation(IgnoreSwaggerDocument::class.java)))
        // 特定のパッケージのAPIのみ非表示
        apiSelectBuilder.apis(not(RequestHandlerSelectors.basePackage(IgnorePackageController::class.java.packageName)))

        // 全てのAPIを表示
        // apiSelectBuilder.paths(PathSelectors.any())
        // 特定のパスのAPIのみ非表示
        apiSelectBuilder.paths(not(PathSelectors.regex("/ignore/*")))

        return apiSelectBuilder.build()
    }
```

パスでの指定もできるよ！