Opsætning af Swagger 2 med en Spring REST API

Sikkerhedstop

Jeg annoncerede netop det nye Learn Spring Security-kursus, inklusive det fulde materiale med fokus på den nye OAuth2-stak i Spring Security 5:

>> KONTROLLER KURSEN REST Top

Jeg har lige annonceret det nye Lær foråret kursus med fokus på det grundlæggende i Spring 5 og Spring Boot 2:

>> KONTROLLER KURSEN

1. Oversigt

I dag adskiller front-end og back-end-komponenter ofte en webapplikation. Normalt udsætter vi API'er som en back-end-komponent til front-end-komponenten eller tredjeparts-appintegrationer.

I et sådant scenario er det vigtigt at have de rette specifikationer til back-end API'erne. Samtidig skal API-dokumentationen være informativ, læsbar og let at følge.

Desuden skal referencedokumentation samtidig beskrive enhver ændring i API'en. At udføre dette manuelt er en kedelig øvelse, så automatisering af processen var uundgåelig.

I denne vejledning ser vi på Swagger 2 for en Spring REST-webservice, ved hjælp af Springfox-implementeringen af ​​Swagger 2-specifikationen.

Hvis du ikke er fortrolig med Swagger, skal du besøge dens webside for at lære mere, inden du fortsætter med denne vejledning.

2. Målprojekt

Oprettelsen af ​​den REST-tjeneste, vi vil bruge, er ikke inden for anvendelsesområdet for denne artikel. Hvis du allerede har et passende projekt, skal du bruge det. Hvis ikke, er disse links et godt sted at starte:

  • Byg en REST API med Spring 4 og Java Config-artikel
  • Opbygning af en RESTful Web Service

3. Tilføjelse af Maven-afhængighed

Som nævnt ovenfor vil vi bruge Springfox-implementeringen af ​​Swagger-specifikationen. Den seneste version kan findes på Maven Central.

For at tilføje det til vores Maven-projekt har vi brug for en afhængighed i pom.xml fil:

 io.springfox springfox-swagger2 2.9.2 

3.1. Spring Boot afhængighed

For Spring Boot-baserede projekter det er nok at tilføje en enkelt springfox-boot-starter afhængighed:

 io.springfox springfox-boot-starter 3.0.0 

4. Integrering af Swagger 2 i projektet

4.1. Java-konfiguration

Konfigurationen af ​​Swagger centrerer hovedsageligt omkring Docket bønne:

@Configuration public class SpringFoxConfig {@Bean public Docket api () {return new Docket (DocumentationType.SWAGGER_2) .select () .apis (RequestHandlerSelectors.any ()) .paths (PathSelectors.any ()) .build (); }}

Efter at have defineret Docket bønne, dens Vælg() metoden returnerer en forekomst af ApiSelectorBuilder, som giver en måde at kontrollere de endepunkter, der er udsat for Swagger.

Vi kan konfigurere prædikater til valg RequestHandlers ved hjælp af RequestHandlerSelectors og PathSelectors. Ved brug af nogen() for begge gør dokumentation for hele vores API tilgængelig via Swagger.

4.2. Konfiguration uden fjedersko

I almindelige forårsprojekter er vi nødt til at aktivere Swagger 2 eksplicit. For at gøre det, vi er nødt til at bruge @ EnableSwagger2WebMvc på vores konfigurationsklasse:

@Configuration @ EnableSwagger2WebMvc offentlig klasse SpringFoxConfig {}

Derudover uden Spring Boot har vi ikke luksusen med automatisk konfiguration af vores ressourcehåndterere.

Swagger UI tilføjer et sæt ressourcer, som vi skal konfigurere som en del af en klasse, der udvides WebMvcConfigurerAdapter og er kommenteret med @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. Verifikation

For at bekræfte, at Springfox fungerer, kan vi besøge denne URL i vores browser:

// localhost: 8080 / spring-security-rest / api / v2 / api-docs

Resultatet er et JSON-svar med et stort antal nøgleværdipar, hvilket ikke er særlig menneskeligt læsbart. Heldigvis leverer Swagger Swagger UI til dette formål.

5. Swagger UI

Swagger UI er en indbygget løsning, der gør brugerinteraktion med den Swagger-genererede API-dokumentation meget lettere.

5.1. Aktivering af Springfoxs Swagger UI

For at bruge Swagger UI er vi nødt til at tilføje en ekstra Maven-afhængighed:

 io.springfox springfox-swagger-ui 2.9.2 

Nu kan vi teste det i vores browser ved at besøge:

// localhost: 8080 / din-app-rod / swagger-ui /

I vores tilfælde er den nøjagtige URL forresten:

// localhost: 8080 / spring-security-rest / api / swagger-ui /

Resultatet skulle se sådan ud:

5.2. Udforskning af Swagger-dokumentation

Inden for Swaggers svar er en liste over alle controllere defineret i vores ansøgning. Ved at klikke på en af ​​dem vises de gyldige HTTP-metoder (SLET, , HOVED, MULIGHEDER, LAPPE, STOLPE, SÆTTE).

Udvidelse af hver metode giver yderligere nyttige data, såsom svarstatus, indholdstype og en liste over parametre. Det er også muligt at prøve hver metode ved hjælp af brugergrænsefladen.

Swaggers evne til at blive synkroniseret med vores kodebase er afgørende. For at demonstrere dette kan vi tilføje en ny controller til vores applikation:

@RestController offentlig klasse CustomController {@RequestMapping (værdi = "/ brugerdefineret", metode = RequestMethod.POST) offentlig streng brugerdefineret () {returner "brugerdefineret"; }}

Nu hvis vi opdaterer Swagger-dokumentationen, ser vi det brugerdefineret controller på listen over controllere. Som vi ved, er der kun en metode (STOLPE) vist i Swagger's svar.

6. Forårsdata REST

Springfox yder support til Spring Data REST gennem dets springfox-data-rest bibliotek.

Spring Boot tager sig af den automatiske konfiguration, hvis den opdager spring-boot-starter-data-rest på klassestien.

Lad os nu oprette en enhed med navnet Bruger:

@Entity offentlig klasse bruger {@Id privat Lang id; privat streng fornavn; privat int alder privat streng e-mail; // getters og setters}

Så opretter vi UserRepository for at tilføje CRUD-operationer på Bruger enhed:

@Repository offentlig grænseflade UserRepository udvider CrudRepository {}

Til sidst importerer vi SpringDataRestConfiguration klasse til SpringFoxConfig klasse:

@ EnableSwagger2WebMvc @Import (SpringDataRestConfiguration.class) offentlig klasse SpringFoxConfig {// ...}

Bemærk: Vi har brugt @ EnableSwagger2WebMvc kommentar for at aktivere Swagger, da den har erstattet @ EnableSwagger2 kommentar i version 3 af bibliotekerne.

Lad os genstarte applikationen for at generere specifikationerne til Spring Data REST API'er:

Vi kan se, at Springfox har genereret specifikationerne til Bruger enhed med HTTP-metoder som f.eks , POST, PUT, PATCH, og SLET.

7. Valideringer af bønner

Springfox understøtter også bønnevalideringsanmærkningerne gennem sine springfox-bean-validatorer bibliotek.

Først tilføjer vi Maven-afhængigheden til vores pom.xml:

 io.springfox springfox-bean-validators 2.9.2 

Igen, hvis vi bruger Spring Boot, behøver vi ikke at angive ovenstående afhængighed eksplicit.

Lad os derefter tilføje et par valideringsanmærkninger som f.eks @NotNull og @Min til Bruger enhed:

@Entity public class Bruger {// ... @NotNull (message = "Fornavn kan ikke være nul") privat String firstName; @Min (værdi = 15, meddelelse = "Alder bør ikke være mindre end 15") @Max (værdi = 65, besked = "Alder bør ikke være større end 65") privat int alder; }

Endelig importerer vi BeanValidatorPluginsConfiguration klasse til SpringFoxConfig klasse:

@ EnableSwagger2 @Import (BeanValidatorPluginsConfiguration.class) offentlig klasse SpringFoxConfig {// ...}

Lad os se på ændringerne i API-specifikationerne:

Her kan vi se, at Bruger model har * påkrævet på den fornavn. Også den minimum og maksimum værdier er defineret for alder.

8. Plugin

For at tilføje specifikke funktioner til API-specifikationerne kan vi oprette et Springfox-plugin. Et plugin kan tilbyde forskellige funktioner, lige fra berigelse af modeller og egenskaber til brugerdefinerede API-lister og standardindstillinger.

Springfox understøtter oprettelsen af ​​plugin gennem sit spi-modul. SPI-modulet indeholder et par grænseflader som ModelBuilderPlugin, ModelPropertyBuilderPluginog ApiListingBuilderPlugin der fungerer som en udvidelseskrog til implementering af et brugerdefineret plugin.

Lad os oprette et plugin for at berige det for at demonstrere mulighederne e-mail ejendommen til Bruger model. Vi bruger ModelPropertyBuilderPlugin interface og indstil værdierne for mønster og eksempel.

Lad os først oprette EmailAnnotationPlugin klasse og tilsidesætte bakker op metode til at tillade enhver dokumentationstype, såsom Swagger 1.2 og Swagger 2:

@Component @Order (Validators.BEAN_VALIDATOR_PLUGIN_ORDER) offentlig klasse EmailAnnotationPlugin implementerer ModelPropertyBuilderPlugin {@Override public boolean supports (DocumentationType delimiter) {return true; }}

Så tilsidesætter vi ansøge metode til ModelPropertyBuilderPlugin for at indstille værdierne for bygherreegenskaberne:

@ Override public void apply (ModelPropertyContext context) {Valgfri e-mail = annotationFromBean (kontekst, Email.class); hvis (email.isPresent ()) {context.getSpecificationBuilder (). facetBuilder (StringElementFacetBuilder.class) .pattern (email.get (). regexp ()); context.getSpecificationBuilder (). eksempel ("[email protected]"); }}

Så API-specifikationerne viser mønster og eksempel værdier for ejendommen kommenteret med @E-mail kommentar.

Derefter tilføjer vi @E-mail kommentar til Bruger enhed:

@Entity public class User {// ... @Email (regexp = ". * @. * \ .. *", message = "E-mail skal være gyldig") privat String-mail; }

Endelig aktiverer vi EmailAnnotationPlugin i SpringFoxConfig klasse ved at registrere sig som en bønne:

@Import ({BeanValidatorPluginsConfiguration.class}) offentlig klasse SpringFoxConfig {// ... @Bean offentlig EmailAnnotationPlugin emailPlugin () {returner ny EmailAnnotationPlugin (); }}

Lad os se på EmailAnnotationPlugin i aktion:

Vi kan se værdien af mønster er den samme regex (. * @. * \ .. *) fra e-mail ejendommen til Bruger enhed.

Ligeledes værdien af eksempel ([e-mail-beskyttet]) er den samme som defineret i ansøge metode til EmailAnnotationPlugin.

9. Avanceret konfiguration

Det Docket bean af vores applikation kan konfigureres til at give os mere kontrol over API-dokumentationsgenereringsprocessen.

9.1. Filtrering API til Swagger's svar

Det er ikke altid ønskeligt at udsætte dokumentationen for hele API'en. Vi kan begrænse Swaggers svar ved at videregive parametre til apis () og stier () metoder til Docket klasse.

Som det ses ovenfor, RequestHandlerSelectors tillader brug af nogen eller ingen prædikater, men kan også bruges til at filtrere API'en i henhold til basispakken, klassebemærkning og metodebemærkninger.

PathSelectors giver yderligere filtrering med prædikater, der scanner anmodningsstierne for vores applikation. Vi kan bruge nogen(), ingen(), regex (), eller myre().

I eksemplet nedenfor vil vi instruere Swagger om kun at medtage controllere fra en bestemt pakke med specifikke stier ved hjælp af myre() predikat:

@Bean public Docket api () {return new Docket (DocumentationType.SWAGGER_2) .select () .apis (RequestHandlerSelectors.basePackage ("com.baeldung.web.controller")) .paths (PathSelectors.ant ("/ foos / * ")) .build (); }

9.2. Brugerdefineret information

Swagger giver også nogle standardværdier i sit svar, som vi kan tilpasse, såsom "Api-dokumentation", "Oprettet af kontakt-e-mail" og "Apache 2.0".

For at ændre disse værdier kan vi bruge apiInfo (ApiInfo apiInfo) metode - ApiInfo klasse, der indeholder brugerdefineret information om API:

@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 () {returner nye ApiInfo ("Min REST API", "Nogle brugerdefinerede beskrivelser af API.", "API TOS", "Servicevilkår", ny kontakt ("John Doe", "www.eksempel). com "," [email protected] "," License of API "," API licens URL ", Collections.emptyList ()); }

9.3. Beskeder om brugerdefinerede metoder

Swagger tillader det globalt tilsidesættende svarmeddelelser fra HTTP-metoder igennem Docket'S globalResponseMessage ()metode.

Først skal vi instruere Swagger om ikke at bruge standardresponsmeddelelser. Antag, at vi vil tilsidesætte 500 og 403 svarbeskeder til alle metoder.

For at opnå dette skal der tilføjes en kode til DocketInitialiseringsblok (original kode er ekskluderet for klarhedens skyld):

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

10. Skifter brugergrænseflade med en OAuth-sikret API

Swagger UI giver en række meget nyttige funktioner, som vi hidtil har dækket godt her. Men vi kan ikke rigtig bruge de fleste af disse, hvis vores API er sikret og ikke tilgængelig.

Lad os se, hvordan vi kan give Swagger adgang til en OAuth-sikret API ved hjælp af tildelingstypen Autorisationskode i dette eksempel.

Vi konfigurerer Swagger til at få adgang til vores sikrede API ved hjælp af Sikkerhedsplan og Sikkerhedskontekst support:

@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 ())); }

10.1. Sikkerhedskonfigurationen

Vi definerer en Sikkerhedskonfiguration bønne i vores Swagger-konfiguration og indstil nogle standardindstillinger:

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

10.2. Sikkerhedsplan

Dernæst definerer vi vores Sikkerhedsplan; dette bruges til at beskrive, hvordan vores API er sikret (Basic Authentication, OAuth2,…).

I vores tilfælde her definerer vi et OAuth-skema, der bruges til at sikre vores ressource server:

privat SecurityScheme securityScheme () {GrantType grantType = ny AuthorizationCodeGrantBuilder () .tokenEndpoint (nyt TokenEndpoint (AUTH_SERVER + "/ token", "oauthtoken")) .tokenRequestEndpoint (nyt TokenRequestEndpoint (AUTH_SERVER + "/ RENT)"). build (); SecurityScheme oauth = ny OAuthBuilder (). Navn ("spring_oauth") .grantTypes (Arrays.asList (grantType)) .scopes (Arrays.asList (scopes ())) .build (); vende tilbage }

Bemærk, at vi brugte tildelingstypen Autorisationskode, som vi skal angive et token-slutpunkt for og godkendelses-URL'en til vores OAuth2 autorisationsserver.

Og her er de omfang, vi skal have defineret:

private AuthorizationScope [] scopes () {AuthorizationScope [] scopes = {new AuthorizationScope ("read", "for read operations"), new AuthorizationScope ("write", "for write operations"), new AuthorizationScope ("foo", " Adgang til foo API ")}; returomfang }

Disse synkroniseres med de anvendelsesområder, vi faktisk har defineret i vores applikation til / foos API.

10.3. Sikkerhedskontekst

Endelig er vi nødt til at definere en Sikkerhedskontekst til vores eksempel API:

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

Bemærk hvordan navnet vi brugte her i referencen - spring_oauth - synkroniseres med det navn, vi tidligere brugte i Sikkerhedsplan.

10.4. Prøve

Nu hvor vi har alt klar og klar til at gå, lad os se på vores Swagger UI og prøve at få adgang til Foo API.

Vi kan få adgang til Swagger UI lokalt:

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

Som vi kan se, findes der en ny autorisationsknap på grund af vores sikkerhedskonfigurationer:

Når vi klikker på knappen Autoriser, kan vi se følgende pop op-vindue for at give vores Swagger UI adgang til at få adgang til den sikrede API:

Noter det:

  • Vi kan allerede se CLIENT_ID og CLIENT_SECRET, da vi har forudkonfigureret dem tidligere (men vi kan stadig ændre dem).
  • Vi kan nu vælge de anvendelsesområder, vi har brug for.

Sådan markeres den sikrede API:

Og nu, endelig, kan vi ramme vores API!

Selvfølgelig siger det næsten sig selv, at vi skal være forsigtige med, hvordan vi udsætter Swagger UI eksternt, nu når denne sikkerhedskonfiguration er aktiv.

11. Konklusion

I denne artikel oprettede vi Swagger 2 til at generere dokumentation til en Spring REST API. Vi undersøgte også måder at visualisere og tilpasse Swaggers output. Og endelig så vi på en simpel OAuth-konfiguration til Swagger.

Det fuld implementering af denne vejledning kan findes i GitHub-projektet. For at se opsætningen i et Boot-projekt skal du tjekke dette GitHub-modul.

For OAuth-sektionen er koden tilgængelig i vores forårssikkerhed-oauth-arkiv.

Og hvis du er studerende af REST With Spring, skal du gå til lektion 1 fra modul 7 for et dybt dykke i opsætning af Swagger med Spring and Spring Boot.

Sikkerhedsbund

Jeg annoncerede netop det nye Learn Spring Security-kursus, inklusive det fulde materiale med fokus på den nye OAuth2-stak i Spring Security 5:

>> KONTROLLER KURSEN REST bunden

Jeg har lige annonceret det nye Lær foråret kursus med fokus på det grundlæggende i Spring 5 og Spring Boot 2:

>> KONTROLLER KURSEN