Einrichten von Swagger 2 mit einer Spring-REST-API

Einrichten von Swagger 2 mit einer Spring REST-API

1. Überblick

Bei der Erstellung einer REST-API ist eine gute Dokumentation von entscheidender Bedeutung.

Darüber hinaus sollte jede Änderung der API gleichzeitig in der Referenzdokumentation beschrieben werden. Dies manuell durchzuführen ist eine mühsame Aufgabe, weshalb eine Automatisierung des Prozesses unvermeidlich war.

In diesem Tutorial werden wir uns mitSwagger 2 for a Spring REST web service. befassen. In diesem Artikel verwenden wir dieSpringfox-Implementierung der Swagger 2-Spezifikation.

Wenn Sie mit Swagger nicht vertraut sind, sollten Sieits web page besuchen, um mehr zu erfahren, bevor Sie mit diesem Artikel fortfahren.

Weitere Lektüre:

Generieren Sie einen Spring Boot REST Client mit Swagger

Erfahren Sie, wie Sie mit dem Swagger-Code-Generator einen Spring Boot-REST-Client generieren können.

Read more

Einführung in Spring REST Docs

In diesem Artikel wird Spring REST Docs vorgestellt, ein testgesteuerter Mechanismus zum Generieren einer Dokumentation für RESTful-Services, die genau und lesbar ist.

Read more

Einführung in Asciidoctor in Java

Erfahren Sie, wie Sie mit AsciiDoctor Dokumente erstellen.

Read more

2. Zielprojekt

Die Erstellung des REST-Service, den wir in unseren Beispielen verwenden, fällt nicht in den Geltungsbereich dieses Artikels. Wenn Sie bereits ein geeignetes Projekt haben, verwenden Sie es. Wenn nicht, sind die folgenden Links ein guter Ausgangspunkt:

3. Hinzufügen der Maven-Abhängigkeit

Wie oben erwähnt, verwenden wir die Springfox-Implementierung der Swagger-Spezifikation. Die neueste Version finden Sie unteron Maven Central.

Um es unserem Maven-Projekt hinzuzufügen, benötigen wir eine Abhängigkeit in der Dateipom.xml.


    io.springfox
    springfox-swagger2
    2.9.2

4. Integration von Swagger 2 in das Projekt

4.1. Java-Konfiguration

Die Konfiguration von Swagger konzentriert sich hauptsächlich auf dieDocket-Bohne.

@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 wird durch die Annotation@EnableSwagger2aktiviert.

Nachdem dieDocket-Bean definiert wurde, gibt ihreselect()-Methode eine Instanz vonApiSelectorBuilder zurück, mit der die von Swagger bereitgestellten Endpunkte gesteuert werden können.

Prädikate für die Auswahl vonRequestHandlers können mit Hilfe vonRequestHandlerSelectors undPathSelectors konfiguriert werden. Wenn Sieany() für beide verwenden, wird die Dokumentation für Ihre gesamte API über Swagger verfügbar.

This configuration is enough to integrate Swagger 2 into an existing Spring Boot project. Für andere Spring-Projekte ist eine zusätzliche Optimierung erforderlich.

4.2. Konfiguration ohne Spring Boot

Ohne Spring Boot haben Sie nicht den Luxus, Ihre Ressourcenhandler automatisch zu konfigurieren. Die Swagger-Benutzeroberfläche fügt eine Reihe von Ressourcen hinzu, die Sie als Teil einer Klasse konfigurieren müssen, dieWebMvcConfigurerAdapter, erweitert und mit@EnableWebMvc. versehen ist

@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. Nachprüfung

Um zu überprüfen, ob Springfox funktioniert, können Sie die folgende URL in Ihrem Browser aufrufen:

Das Ergebnis ist eine JSON-Antwort mit einer großen Anzahl von Schlüssel-Wert-Paaren, die nicht sehr gut lesbar ist. Glücklicherweise stellt Swagger zu diesem ZweckSwagger UI zur Verfügung.

5. Swagger UI

Die Swagger-Benutzeroberfläche ist eine integrierte Lösung, die die Benutzerinteraktion mit der von Swagger generierten API-Dokumentation erheblich vereinfacht.

5.1. Aktivieren der Swagger-Benutzeroberfläche von Springfox

Um die Swagger-Benutzeroberfläche zu verwenden, ist eine zusätzliche Maven-Abhängigkeit erforderlich:


    io.springfox
    springfox-swagger-ui
    2.9.2

Jetzt können Sie es in Ihrem Browser testen, indem Siehttp://localhost:8080/your-app-root/swagger-ui.html besuchen

In our case, by the way, the exact URL will be:http://localhost:8080/spring-security-rest/api/swagger-ui.html

Das Ergebnis sollte ungefähr so ​​aussehen:

Screenshot_1

5.2. Erkundung der Swagger-Dokumentation

In der Antwort von Swagger ist einlist of all controllersin Ihrer Anwendung definiert. Wenn Sie auf eine dieser Methoden klicken, werden die gültigen HTTP-Methoden aufgelistet (DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT).

Das Erweitern der einzelnen Methoden bietet zusätzliche nützliche Daten, z. B. den Antwortstatus, den Inhaltstyp und eine Liste von Parametern. Es ist auch möglich, jede Methode über die Benutzeroberfläche auszuprobieren.

Die Fähigkeit von Swagger, mit Ihrer Codebasis synchronisiert zu werden, ist entscheidend. Um dies zu demonstrieren, können Sie Ihrer Anwendung einen neuen Controller hinzufügen.

@RestController
public class CustomController {

    @RequestMapping(value = "/custom", method = RequestMethod.POST)
    public String custom() {
        return "custom";
    }
}

Wenn Sie nun die Swagger-Dokumentation aktualisieren, wirdcustom-controller in der Liste der Controller angezeigt. Wie Sie wissen, wird in Swaggers Antwort nur eine Methode (POST) angezeigt.

6. Erweiterte Konfiguration

DieDocket-Bean Ihrer Anwendung kann so konfiguriert werden, dass Sie mehr Kontrolle über den Generierungsprozess der API-Dokumentation haben.

6.1. Filter-API für die Antwort von Swagger

Es ist nicht immer wünschenswert, die Dokumentation für Ihre gesamte API bereitzustellen. Sie können die Antwort von Swagger einschränken, indem Sie Parameter an die Methodenapis() undpaths()der KlasseDocketübergeben.

Wie oben gezeigt, ermöglichtRequestHandlerSelectors die Verwendung der Prädikateany odernone, kann jedoch auch zum Filtern der API nach Basispaket, Klassenanmerkung und Methodenanmerkungen verwendet werden.

PathSelectors bietet zusätzliche Filterung mit Prädikaten, die die Anforderungspfade Ihrer Anwendung scannen. Sie könnenany(),none(),regex() oderant() verwenden.

Im folgenden Beispiel weisen wir Swagger an, nur Controller aus einem bestimmten Paket mit bestimmten Pfaden unter Verwendung des Prädikatsant()einzuschließen.

@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. Benutzerdefinierte Informationen

Swagger bietet auch einige Standardwerte in seiner Antwort, die Sie anpassen können, wie z. B. "Api-Dokumentation", "Erstellt von Kontakt-E-Mail", "Apache 2.0".

Um diese Werte zu ändern, können Sie die MethodeapiInfo(ApiInfo apiInfo)verwenden. DieApiInfo-Klasse, die benutzerdefinierte Informationen zur API enthält.

@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. Antwortnachrichten für benutzerdefinierte Methoden

Swagger erlaubt dieglobally overriding response messages of HTTP methods bisDocketglobalResponseMessage()Methode. Zunächst müssen Sie Swagger anweisen, keine Standardantwortnachrichten zu verwenden.

Angenommen, Sie möchten die Antwortnachrichten von500 und403für alle Methoden vonGETüberschreiben. Um dies zu erreichen, muss dem Initialisierungsblock vonDocketein Teil des Codes hinzugefügt werden (der ursprüngliche Code ist aus Gründen der Übersichtlichkeit ausgeschlossen):

.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()));

Screenshot_2

7. Swagger-Benutzeroberfläche mit einer OAuth-gesicherten API

Die Swagger-Benutzeroberfläche bietet eine Reihe sehr nützlicher Funktionen, die wir hier bisher ausführlich behandelt haben. Die meisten davon können wir jedoch nicht wirklich verwenden, wenn unsere API gesichert und nicht zugänglich ist.

Lassen Sie uns sehen, wie wir Swagger den Zugriff auf eine OAuth-gesicherte API ermöglichen können - in diesem Beispiel mithilfe des Berechtigungstyps Grant.

Wir konfigurieren Swagger für den Zugriff auf unsere gesicherte API mithilfe der Unterstützung vonSecurityScheme undSecurityContext:

@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. Sicherheitskonfiguration

Wir definieren eineSecurityConfiguration-Bean in unserer Swagger-Konfiguration - und legen einige Standardeinstellungen fest:

@Bean
public SecurityConfiguration security() {
    return SecurityConfigurationBuilder.builder()
        .clientId(CLIENT_ID)
        .clientSecret(CLIENT_SECRET)
        .scopeSeparator(" ")
        .useBasicAuthenticationWithAccessCodeGrant(true)
        .build();
}

7.2. SecurityScheme

Als nächstes definieren wir unsereSecurityScheme; Hiermit wird beschrieben, wie unsere API gesichert ist (Basisauthentifizierung, OAuth2,…).

In unserem Fall definieren wir hier ein OAuth-Schema, mit dem unsereResource Server gesichert werden:

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;
}

Beachten Sie, dass wir den Bewilligungstyp Autorisierungscode verwendet haben, für den wir einen Token-Endpunkt und die Autorisierungs-URL unseres OAuth2-Autorisierungsservers bereitstellen müssen.

Und hier sind die Bereiche, die wir definiert haben müssen:

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;
}

Diese werden mit den Bereichen synchronisiert, die wir tatsächlich in unserer Anwendung für die/foos-API definiert haben.

7.3. Sicherheitskontext

Schließlich müssen wir einen Sicherheitskontext für unsere Beispiel-API definieren:

private SecurityContext securityContext() {
    return SecurityContext.builder()
      .securityReferences(
        Arrays.asList(new SecurityReference("spring_oauth", scopes())))
      .forPaths(PathSelectors.regex("/foos.*"))
      .build();
}

Beachten Sie, wie der hier verwendete Name in der Referenz -spring_oauth - mit dem zuvor inSecurityScheme verwendeten Namen synchronisiert wird.

7.4. Test

Okay, jetzt, da wir alles eingerichtet und einsatzbereit haben, werfen wir einen Blick auf unsere Swagger-Benutzeroberfläche und versuchen, auf die Foo-API zuzugreifen:

Wir können lokal auf die Swagger-Benutzeroberfläche zugreifen:

http://localhost:8082/spring-security-oauth-resource/swagger-ui.html

Wie wir sehen können, gibt es aufgrund unserer Sicherheitskonfigurationen jetzt eine neue Schaltfläche "Autorisieren":

image

Wenn wir auf die Schaltfläche "Authorize" (Autorisieren) klicken, wird das folgende Popup angezeigt, um unsere Swagger-Benutzeroberfläche für den Zugriff auf die gesicherte API zu autorisieren:

image

Beachten Sie, dass:

  • Wir können die CLIENT_ID und CLIENT_SECRET bereits sehen - da wir sie zuvor vorkonfiguriert haben (aber wir können sie trotzdem ändern).

  • Wir können jetzt die Bereiche auswählen, die wir benötigen

So werden die gesicherten APIs markiert:

image

Und jetzt können wir endlich unsere API starten!

Natürlich ist es fast selbstverständlich, dass wir vorsichtig sein müssen, wie wir die Swagger-Benutzeroberfläche extern verfügbar machen, jetzt, da diese Sicherheitskonfiguration aktiv ist.

8. Fazit

In diesem Tutorial haben wir Swagger 2 so eingerichtet, dass Dokumentation für eine Spring-REST-API generiert wird. Wir haben auch Möglichkeiten untersucht, die Ausgabe von Swagger zu visualisieren und anzupassen. Zum Schluss haben wir uns eine einfache OAuth-Konfiguration für Swagger angesehen.

Diefull implementation dieses Tutorials finden Sie inthe Github project - dies ist ein Eclipse-basiertes Projekt, daher sollte es einfach zu importieren und auszuführen sein. Überprüfen Siethis GitHub module, um die Einrichtung in einem Boot-Projekt anzuzeigen.

Für den OAuth-Abschnitt ist der Code in unseremspring-security-oauth-Repository verfügbar.

Wenn Sie ein Schülerof REST With Springind, lesen Sie in Lektion 1 von Modul 7, wie Sie Swagger mit Spring und Spring Boot einrichten.