Spring REST APIを使用したSwagger 2のセットアップ
1. 概要
REST APIを作成するときは、適切なドキュメントが役立ちます。
さらに、APIのすべての変更は、リファレンスドキュメントで同時に説明する必要があります。 これを手動で達成するのは退屈な作業であるため、プロセスの自動化は避けられませんでした。
このチュートリアルでは、Swagger 2 for a Spring REST web service.について説明します。この記事では、Swagger 2仕様のSpringfox実装を使用します。
Swaggerに慣れていない場合は、この記事を続ける前に、its web pageにアクセスして詳細を確認する必要があります。
参考文献:
Swaggerを使用してSpring Boot RESTクライアントを生成する
Swagger Code Generatorを使用してSpring Boot RESTクライアントを生成する方法を学びます。
Spring RESTドキュメントの概要
この記事では、正確で読みやすいRESTfulサービスのドキュメントを生成するテスト駆動メカニズムであるSpring REST Docsを紹介します。
2. 対象プロジェクト
例で使用するRESTサービスの作成は、この記事の範囲内ではありません。 適切なプロジェクトが既にある場合は、それを使用します。 そうでない場合は、次のリンクを開始するのに適した場所です。
3. Maven依存関係の追加
前述のように、Swagger仕様のSpringfox実装を使用します。 最新バージョンはon Maven Centralにあります。
これをMavenプロジェクトに追加するには、pom.xmlファイルに依存関係が必要です。
io.springfox
springfox-swagger2
2.9.2
4. Swagger2をプロジェクトに統合する
4.1. Java設定
Swaggerの構成は、主にDocketBeanを中心にしています。
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
}
}
Swagger 2は、@EnableSwagger2アノテーションによって有効になります。
Docket Beanが定義された後、そのselect()メソッドはApiSelectorBuilderのインスタンスを返します。これは、Swaggerによって公開されるエンドポイントを制御する方法を提供します。
RequestHandlersを選択するための述語は、RequestHandlerSelectorsおよびPathSelectorsを使用して構成できます。 両方にany()を使用すると、API全体のドキュメントがSwaggerから利用できるようになります。
This configuration is enough to integrate Swagger 2 into an existing Spring Boot project.他のSpringプロジェクトでは、追加の調整が必要です。
4.2. SpringBootなしの構成
Spring Bootがないと、リソースハンドラーを自動構成するという贅沢はありません。 Swagger UIは、WebMvcConfigurerAdapter,を拡張し、@EnableWebMvc.で注釈が付けられたクラスの一部として構成する必要があるリソースのセットを追加します
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
4.3. 検証
Springfoxが機能していることを確認するには、ブラウザで次のURLにアクセスします。
その結果、多数のキーと値のペアを持つJSON応答が生成されますが、これは人間が判読できるほどではありません。 幸い、Swaggerはこの目的のためにSwagger UIを提供します。
5. Swagger UI
Swagger UIは、Swaggerで生成されたAPIドキュメントとのユーザーの対話をはるかに簡単にする組み込みソリューションです。
5.1. SpringfoxのSwaggerUIを有効にする
Swagger UIを使用するには、追加のMaven依存関係が1つ必要です。
io.springfox
springfox-swagger-ui
2.9.2
これで、http://localhost:8080/your-app-root/swagger-ui.htmlにアクセスして、ブラウザでテストできます。
In our case, by the way, the exact URL will be:http://localhost:8080/spring-security-rest/api/swagger-ui.html
結果は次のようになります。
5.2. Swaggerドキュメントの探索
Swaggerの応答には、アプリケーションで定義されたlist of all controllersが含まれます。 それらのいずれかをクリックすると、有効なHTTPメソッド(DELETE、GET、HEAD、OPTIONS、PATCH、POST、PUT)。
各メソッドを展開すると、応答ステータス、コンテンツタイプ、パラメータのリストなどの追加の有用なデータが提供されます。 UIを使用して各メソッドを試すこともできます。
Swaggerのコードベースとの同期機能は非常に重要です。 これを実証するために、アプリケーションに新しいコントローラーを追加できます。
@RestController
public class CustomController {
@RequestMapping(value = "/custom", method = RequestMethod.POST)
public String custom() {
return "custom";
}
}
ここで、Swaggerのドキュメントを更新すると、コントローラーのリストにcustom-controllerが表示されます。 ご存知のように、Swaggerの応答に表示されるメソッドは1つ(POST)のみです。
6. 高度な構成
アプリケーションのDocket Beanは、APIドキュメントの生成プロセスをより細かく制御できるように構成できます。
6.1. Swaggerの応答用のフィルタリングAPI
API全体のドキュメントを公開することが常に望ましいとは限りません。 Docketクラスのapis()およびpaths()メソッドにパラメーターを渡すことにより、Swaggerの応答を制限できます。
上記のように、RequestHandlerSelectorsではanyまたはnone述語を使用できますが、基本パッケージ、クラスアノテーション、およびメソッドアノテーションに従ってAPIをフィルタリングするためにも使用できます。
PathSelectorsは、アプリケーションのリクエストパスをスキャンする述語による追加のフィルタリングを提供します。 any()、none(),regex()、またはant()を使用できます。
以下の例では、ant()述語を使用して、特定のパスを持つ特定のパッケージのコントローラーのみを含めるようにSwaggerに指示します。
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("org.example.web.controller"))
.paths(PathSelectors.ant("/foos/*"))
.build();
}
6.2. カスタム情報
Swaggerは、「Api Documentation」、「Created by Contact Email」、「Apache 2.0」など、カスタマイズ可能な応答のデフォルト値も提供します。
これらの値を変更するには、apiInfo(ApiInfo apiInfo)メソッドを使用できます。 APIに関するカスタム情報を含むApiInfoクラス。
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.example.controller"))
.paths(PathSelectors.ant("/foos/*"))
.build()
.apiInfo(apiInfo());
}
private ApiInfo apiInfo() {
return new ApiInfo(
"My REST API",
"Some custom description of API.",
"API TOS",
"Terms of service",
new Contact("John Doe", "www.example.com", "[email protected]"),
"License of API", "API license URL", Collections.emptyList());
}
6.3. カスタムメソッドの応答メッセージ
Swaggerでは、globally overriding response messages of HTTP methodsからDocketのglobalResponseMessage()メソッドを使用できます。 最初に、デフォルトの応答メッセージを使用しないようにSwaggerに指示する必要があります。
すべてのGETメソッドの500および403応答メッセージをオーバーライドしたいとします。 これを実現するには、Docketの初期化ブロックにいくつかのコードを追加する必要があります(わかりやすくするために、元のコードは除外されています)。
.useDefaultResponseMessages(false)
.globalResponseMessage(RequestMethod.GET,
newArrayList(new ResponseMessageBuilder()
.code(500)
.message("500 message")
.responseModel(new ModelRef("Error"))
.build(),
new ResponseMessageBuilder()
.code(403)
.message("Forbidden!")
.build()));
7. OAuthで保護されたAPIを使用したSwaggerUI
Swagger UIは、非常に便利な機能をいくつか提供します。これまで、ここで詳しく説明しました。 ただし、APIが保護されていてアクセスできない場合、これらのほとんどを実際に使用することはできません。
この例の認証コード付与タイプを使用して、SwaggerがOAuthで保護されたAPIにアクセスできるようにする方法を見てみましょう。
SecuritySchemeおよびSecurityContextのサポートを使用してセキュリティで保護されたAPIにアクセスするようにSwaggerを構成します。
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2).select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
.securitySchemes(Arrays.asList(securityScheme()))
.securityContexts(Arrays.asList(securityContext()));
}
7.1. セキュリティ構成
Swagger構成でSecurityConfiguration Beanを定義し、いくつかのデフォルトを設定します。
@Bean
public SecurityConfiguration security() {
return SecurityConfigurationBuilder.builder()
.clientId(CLIENT_ID)
.clientSecret(CLIENT_SECRET)
.scopeSeparator(" ")
.useBasicAuthenticationWithAccessCodeGrant(true)
.build();
}
7.2. SecurityScheme
次に、SecuritySchemeを定義します。これは、APIがどのように保護されているかを説明するために使用されます(基本認証、OAuth2など)。
ここでは、Resource Serverを保護するために使用されるOAuthスキームを定義します。
private SecurityScheme securityScheme() {
GrantType grantType = new AuthorizationCodeGrantBuilder()
.tokenEndpoint(new TokenEndpoint(AUTH_SERVER + "/token", "oauthtoken"))
.tokenRequestEndpoint(
new TokenRequestEndpoint(AUTH_SERVER + "/authorize", CLIENT_ID, CLIENT_SECRET))
.build();
SecurityScheme oauth = new OAuthBuilder().name("spring_oauth")
.grantTypes(Arrays.asList(grantType))
.scopes(Arrays.asList(scopes()))
.build();
return oauth;
}
認可コード付与タイプを使用したことに注意してください。これには、トークンエンドポイントとOAuth2認可サーバーの認可URLを提供する必要があります。
そして、ここに定義する必要があるスコープがあります:
private AuthorizationScope[] scopes() {
AuthorizationScope[] scopes = {
new AuthorizationScope("read", "for read operations"),
new AuthorizationScope("write", "for write operations"),
new AuthorizationScope("foo", "Access foo API") };
return scopes;
}
これらは、/foos APIについて、アプリケーションで実際に定義したスコープと同期します。
7.3. セキュリティコンテキスト
最後に、サンプルAPIのセキュリティコンテキストを定義する必要があります。
private SecurityContext securityContext() {
return SecurityContext.builder()
.securityReferences(
Arrays.asList(new SecurityReference("spring_oauth", scopes())))
.forPaths(PathSelectors.regex("/foos.*"))
.build();
}
ここで使用した名前–spring_oauth –が、以前に使用したSecuritySchemeの名前とどのように同期するかに注意してください。
7.4. Test
さて、すべての設定が完了し、準備ができたので、Swagger UIを見て、FooAPIにアクセスしてみましょう。
Swagger UIにローカルでアクセスできます。
http://localhost:8082/spring-security-oauth-resource/swagger-ui.html
セキュリティ設定により、新しいボタン「Authorize」が存在することがわかります。
「Authorize」ボタンをクリックすると、次のポップアップが表示されます。SwaggerUIがセキュアなAPIにアクセスすることを許可します。
ご了承ください:
-
CLIENT_IDとCLIENT_SECRETは、以前に事前構成したので、すでに確認できます(ただし、変更することはできます)。
-
必要なスコープを選択できるようになりました
保護されたAPIがマークされる方法は次のとおりです。
そして、ついに、APIを使用できるようになりました!
もちろん、このセキュリティ構成がアクティブになったため、Swagger UIを外部に公開する方法に注意する必要があることはほとんど言うまでもありません。
8. 結論
このチュートリアルでは、Swagger 2を設定して、Spring REST APIのドキュメントを生成します。 また、Swaggerの出力を視覚化およびカスタマイズする方法についても検討しました。 そして最後に、Swaggerの簡単なOAuth構成を見ました。
このチュートリアルのfull implementationは、the Github projectにあります。これはEclipseベースのプロジェクトであるため、そのままインポートして実行するのは簡単です。 Bootプロジェクトでの設定を確認するには、this GitHub moduleを確認してください。
OAuthセクションの場合、コードはspring-security-oauthリポジトリで入手できます。
また、学生のof REST With Springの場合は、モジュール7のレッスン1に進んで、SpringとSpringBootを使用したSwaggerの設定について詳しく説明します。