Spring Boot + SpringFoxでSwaggerを利用してソースからAPIキュメントを生成する

## SpringFoxとは
一連のSpringプロジェクトで作成されたWeb APIの仕様書を自動で生成してくれるライブラリです。Springfoxは、実行時に一度アプリケーションをスキャンして、Springの設定、クラス構造、その他様々なコンパイル時に基づくAPIのセマンティクスを推論します。ちなみに、SpringFoxはもともとswagger-springmvcという名前で名を馳せていました。

## SpringFoxとSwagger
SpringFoxはSwaggerのバージョン1.2とバージョン2.0の両方をサポートしていますが、可能であれば2.0が望ましいです。

## SpringFoxの設定
以下はmavenの例ですが、swaggerでドキュメント生成に必要な各種ツール群の依存関係を追加します。

```xml:pom.xml
<dependency>
	<groupId>io.springfox</groupId>
	<artifactId>springfox-swagger2</artifactId>
	<version>2.8.0</version>
</dependency>
<dependency>
	<groupId>io.springfox</groupId>
	<artifactId>springfox-swagger-ui</artifactId>
	<version>2.8.0</version>
</dependency>
<dependency>
	<groupId>io.springfox</groupId>
	<artifactId>springfox-core</artifactId>
	<version>2.8.0</version>
</dependency>
```

## SwaggerのJavaConfig作成
次にSwaggerの設定を行うJavaConfigクラスを作成します。

```Swagger2Config.java
package com.example.demo;

import java.util.ArrayList;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.google.common.base.Predicate;
import com.google.common.base.Predicates;

import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.service.VendorExtension;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class Swagger2Config {

	@Bean
	public Docket swaggerSpringMvcPlugin() {
		return new Docket(DocumentationType.SWAGGER_2)
				.groupName("sample-api")	// APIドキュメントをグルーピングするための識別名
				.select()
				.paths(paths())
				.build()
				.apiInfo(apiInfo());
	}

	private Predicate<String> paths() {
		// ドキュメント生成の対象とするAPIのURLを指定
		// この場合、「/user」で始まるAPIがドキュメント生成対象となる
		return Predicates.or(Predicates.containsPattern("/user"));
	}

	private ApiInfo apiInfo() {
		// http://springfox.github.io/springfox/javadoc/2.6.0/index.html?springfox/documentation/service/ApiInfo.html
		return new ApiInfo(
				  "Sample API"	// APIのタイトル
				, "このAPIは～～～～です"	// APIの説明
				, "V1"	// APIのバージョン
				, "????"	// よくわからない
				, new Contact(
						 "株式会社XXXXXXX"		// APIに関する連絡先組織・団体等
						,"http://XXXXXXXXXXX.co.jp"	// APIに関する連絡先組織・団体等のWeb Site Url
						,"XXXXXXXX@example.jp")		// APIに関する連絡先組織・団体等のメールアドレス
				, "API LICENSE"	// APIのライセンス
				, "http://XXXXXXXXXXXX.co.jp"	// APIのライセンスURL
				, new ArrayList<VendorExtension>()	// 独自に拡張したいドキュメントがあればここで作成
		);
	}
}
```

## Sample APIの作成
最後にAPIです。ここではSwaggerを利用したAPIドキュメント生成を目的としているので空実装になります。

```UserController.java
package com.example.demo.controller;

import java.util.ArrayList;
import java.util.List;

import javax.validation.Valid;

import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import com.example.demo.domain.model.User;

@RestController
public class UserController {

	@GetMapping(path = "user/{id}")
	public User getUser(@PathVariable String id) {
		return new User(id, "ichiro");
	}

	@GetMapping(path = "users")
	public List<User> getUsers() {
		return new ArrayList<User>() {
			{
				add(new User("001", "ichiro"));
				add(new User("002", "jiro"));
				add(new User("003", "saburo"));
			}
		};
	}

	@PostMapping(path = "user")
	@ResponseStatus(HttpStatus.CREATED)
	public void createUser(final @Valid @RequestBody User user, final BindingResult bindingResult) {
	}
	
	@PutMapping(path = "user/{id}")
	@ResponseStatus(HttpStatus.CREATED)
	public void updateUser(@PathVariable String id, @Valid @RequestBody User user,
			final BindingResult bindingResult) {
	}
	
	@DeleteMapping(path = "user/{id}")
	@ResponseStatus(HttpStatus.NO_CONTENT)
	public void deleteUser(@PathVariable String id) {
	}
}
```

## ドキュメント生成・確認
ここまでできたら、ビルドして以下にアクセスします。

```
http://localhost:8080/swagger-ui.html
```

すると、以下のようにドキュメントが生成されていることがわかります。
![無題.png](https://qiita-image-store.s3.amazonaws.com/0/23101/91657e27-6302-575d-6d70-e7964f543353.png)

## SpringFox(Swagger)が提供しているAPI操作に関するアノテーション

SpringFoxではAPI操作に関する情報をメタ情報としてアノテーションで指定できます。
ここでは、@ApiOperationについて紹介します。

```UserController.java
@GetMapping(path = "user/{id}")
@ApiOperation(value = "ユーザリソースを参照します", notes = "パラメータで指定したIDのユーザリソースを参照します")
public User getUser(@PathVariable String id) {
	return new User(id, "ichiro");
}
```
@ApiOperationのvalue属性にAPIの概要、notes属性にAPIの備考的なことを記述することで、以下のようにドキュメント生成されます。
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/23101/65f9d047-48ff-d503-4896-22319feb6f2e.png)




また、以下のように属性値を外部ファイルに記述しそれを指定することも可能です。

```application.properties
UserController.getUser.value=外部ファイルで定義したAPIの概要
UserController.getUser.notes=外部ファイルで定義したAPIの備考的な何か
```

```UserController.java
@GetMapping(path = "user/{id}")
@ApiOperation(value = "${UserController.getUser.value}", notes = "${UserController.getUser.notes}")
public User getUser(@PathVariable String id) {
	return new User(id, "ichiro");
}
```
![ffff.PNG](https://qiita-image-store.s3.amazonaws.com/0/23101/d4250218-ea3e-7aa4-77f1-55ab0394dc42.png)

@ApiOperationを省略するとそのメソッド名が出力されます。

```UserController.java
@PostMapping(path = "user")
@ResponseStatus(HttpStatus.CREATED)
public void createUser(final @Valid @RequestBody User user, final BindingResult bindingResult) {
}
```
![無題.png](https://qiita-image-store.s3.amazonaws.com/0/23101/79a1ca4f-1ed5-796c-18e7-af1972b1d0cf.png)

他にもSpringFox(Swagger)が提供しているアノテーションは色々あります、それらの詳細に関しては以下から確認できます。
https://github.com/swagger-api/swagger-core/wiki/Annotations

## 参考
* http://springfox.github.io/springfox/docs/current/
* https://dev.classmethod.jp/beginners/springfox_create_api_specification/