1. Einführung in die Prahlerei
Im vorherigen Artikel haben wir die Unterstützung von Spring Boot für Pastful eingeführt. In diesem Artikel diskutieren wir dieses Thema weiter. Wir werden jedoch nicht mehr diskutieren, wie die erholsame API implementiert wird, sondern die Aufrechterhaltung der erholsamen API -Dokumentation.
In der täglichen Arbeit müssen wir häufig Schnittstellen für das Front-End (Web End, iOS, Android) oder Dritte bereitstellen. Zu diesem Zeitpunkt müssen wir ihnen eine detaillierte API -Dokumentation zur Verfügung stellen. Die Aufrechterhaltung eines detaillierten Dokuments ist jedoch keine leichte Aufgabe. Erstens ist das Schreiben eines detaillierten Dokuments eine zeitaufwändige und mühsame Aufgabe. Da der Code und das Dokument getrennt sind, ist es jedoch einfach, Inkonsistenzen zwischen dem Dokument und dem Code zu verursachen. In diesem Artikel werden wir eine Möglichkeit zur Aufrechterhaltung von API -Dokumenten teilen, dh automatisch restaurierende API -Dokumente über Swagger generieren.
Also, was ist Prahlerei? Wir können die offizielle Beschreibung direkt lesen:
Die weltweit beliebteste API -Toolingswagger ist der weltweit größte Rahmen für API -Entwickler -Tools für die OpenAPI -Spezifikation (OAS) und ermöglicht die Entwicklung des gesamten API -Lebenszyklus von Design und Dokumentation bis zum Testen und Bereitstellen.
In dieser Passage wird zunächst angezeigt, dass Swagger das beliebteste API -Tool der Welt ist, und der Zweck der Prahlerei besteht darin, die Entwicklung des gesamten API -Lebenszyklus zu unterstützen, einschließlich Design, Dokumentation, Test und Bereitstellung. In diesem Artikel werden wir Swaggers Dokumentenmanagement- und Testfunktionen verwenden.
Nachdem wir ein grundlegendes Verständnis der Rolle der Prahlerei erhalten haben, schauen wir uns an, wie Sie sie verwenden können.
2. Integration von Prahlerei und Springstiefel
Schritt 1: Führen Sie das entsprechende JAR -Paket ein:
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.6.0</version></dependency><dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.6.0</version></dependency>
Schritt 2: Grundlegende Informationskonfiguration:
@Configuration@EnableSwagger2public class Swagger2Config { @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.pandy.blog.rest")) .Paths (PathSelectors.regex ("/rest /.*") .build (); } private apiInfo apiinfo () {Neue apiinfobuilder () .Title ("Blog -System restful api") .Description ("Blog -System restful api") .termsofServiceUrl ("http://127.0.0.1:8080/"). .bauen(); }}Die grundlegende Konfiguration ist eine Beschreibung des gesamten API -Dokuments und einiger globaler Konfigurationen, die für alle Schnittstellen funktionieren. Hier sind zwei Anmerkungen beteiligt:
@Configuration bedeutet, dass es sich um eine Konfigurationsklasse handelt, die von JDK bereitgestellt wurde und im vorherigen Artikel erläutert wurde.
@EnableWagger2s Funktion besteht darin, Swagger2-bezogene Funktionen zu aktivieren.
In dieser Konfigurationsklasse habe ich ein Docket -Objekt instanziiert, das hauptsächlich drei Aspekte von Informationen enthält:
(1) Die Beschreibungsinformationen der gesamten API, dh den im APIInfo -Objekt enthaltenen Informationen, werden dieser Teil der Informationen auf der Seite angezeigt.
(2) Geben Sie den Paketamen an, um das API -Dokument zu generieren.
(3) Geben Sie den Pfad an, um die API zu erzeugen. Die Pfad-basierte API kann vier Modi unterstützen, mit denen sich der Quellcode beziehen kann:
public class pathSelectors {private pathSelectors () {neue nicht unterstützte OperationException () werfen; } öffentliches statisches Prädikat <string> Any () {return predicate.alwayStrue (); } öffentliches statisches Prädikat <string> none () {return predicate.alwaysFalse (); } public static Predicate <String> regex (endgültig String pathregex) {return New Predicate <String> () {public boolean anwenden (String input) {return input.matches (pathreegex); }}; } öffentliches statisches Prädikat <string> Ant (endgültige String -Antpattern) {Neues Prädikat <string> () {public boolean anwenden (String Input) {AntpathMatcher Matcher = new AntpathMatcher (); return Matcher.Match (Antpattern, Input); }}; }}Wie aus dem Quellcode hervorgeht, unterstützt Swagger vier Möglichkeiten: Erzeugung eines Pfades, die Nichtgenerierung eines beliebigen Pfades sowie die regelmäßige Matching- und Ameisenmuster-Matching. Möglicherweise sind Sie mit den ersten drei Typen vertraut, dem letzten von Ameisenübereinstimmungen. Wenn Sie mit Ameisen nicht vertraut sind, ignorieren Sie es einfach. Die ersten drei Typen sollten ausreichen, damit jeder in der täglichen Arbeit verwenden kann.
Mit der obigen Konfiguration können wir den Effekt sehen. Ich habe eine ArticlerestController -Klasse unter dem Paket com.pandy.blog.rest. Der Quellcode lautet wie folgt:
Starten Sie Spring Boot und besuchen Sie dann: http://127.0.0.1:8080/swagger-ui.html, um die folgenden Ergebnisse anzuzeigen:
Auf dieser Seite sehen Sie, dass die anderen Schnittstellen mit Ausnahme der letzten Schnittstelle /test /{id} entsprechende Dokumente generieren. Da die letzte Schnittstelle den von uns konfigurierten Pfad nicht erfüllt - "/rest/.*", wird kein Dokument generiert.
Wir können auch klicken, um jede bestimmte Schnittstelle anzuzeigen. Nehmen wir die Schnittstelle "Post /Rest /Artikel" als Beispiel:
Wie Sie sehen können, generiert Swagger Beispiele für Rückgabeergebnisse und Anforderungsparameter für jede Schnittstelle und kann direkt über die unten stehende Schnittstelle auf die Schnittstelle zugreifen. In Bezug auf die Schnittstelle testet jeder die Schnittstelle. Insgesamt ist die Prahlerei immer noch sehr leistungsfähig und die Konfiguration ist relativ einfach.
@RestControllerPublic Class ArticlerestController {@autowired Private Artikelservice Artikelservice; @RequestMapping (value = "/rest/article", method = post, produziert = "application/json") public webeResponse <map <String, Objekt >> Savearticle (@RequestBody Artikel) {article.setUserid (1L); Artikelservice.Savearticle (Artikel); Karte <String, Object> ret = new HashMap <> (); ret.put ("id", article.getId ()); Webesponse <map <String, Objekt >> response = webesponse.getSuccessResponse (ret); Rücksendemantwort; } @RequestMapping (value = "/rest/article/{id}", method = delete, produziert = "application/json") public webResponse <?> DeleteArticle (@PathVariable Long id) {article articleService.getById (id); Artikel.SetStatus (-1); Artikelservice.UpDATETICL (Artikel); Webesponse <elofthob> response = webesponse.getSuccessResponse (null); Rücksendemantwort; } @RequestMapPing (value = "/rest/article/{id}", method = put, produziert = "application/json") public webResponse <Object> updatearticle (@PathVariable Long ID, @RequestBody Artikel) {article.setid (id); Artikelservice.UpDATETICL (Artikel); Webesponse <elofthob> response = webesponse.getSuccessResponse (null); Rücksendemantwort; } @RequestMapping (value = "/rest/article/{id}", method = get, procies = "application/json") public webresponse <Actage> getArticle (@PathVariable Long id) {article article = artikelService.getById (id); Webresponse <Aktion> response = webesponse.getSuccessResponse (Artikel); Rücksendemantwort; } @RequestMapping (value = "/test/{id}", method = get, produces = "application/json") public webresponse <?> GetNoAPi () {WebebResponse <?> Response = webresponse.getSuccessResponse (null); Rücksendemantwort; }}3. detaillierte Konfiguration der Swagger -API
Aber Sie werden auf jeden Fall einige Fragen haben, wenn Sie dies sehen:
Die erste Frage: Es gibt keine wörtliche Beschreibung des Rückgabeergebnisses und der Anfrageparameter. Kann dies konfiguriert werden?
Die zweite Frage: Dieser Anforderungsparameter sollte direkt auf der Grundlage des Objekts reflektiert werden, aber nicht jede Eigenschaft des Objekts ist erforderlich, und der Wert des Parameters entspricht möglicherweise nicht unseren Anforderungen. Kann dies konfiguriert werden?
Die Antwort ist sicherlich in Ordnung. Lassen Sie uns nun diese beiden Probleme lösen und direkt auf den Konfigurationscode suchen:
Paket com.pandy.blog.rest; import com.pandy.blog.dto.webresponse; import com.pandy.blog.po.Article; import com.pandy.blog.Service.articleservice; import IO.Swagger.Antariclictaric; io.swagger.Annotations.apioperation; import io.swagger.Annotations.apiresponse; import io.swagger.Annotations.apiresponse; Import io.swagger.Annotations.apirept; org.springframework.context.annotation.profile; import org.springframework.web.bind.annotation org.springframework.web.bind.annotation.restcontroller; import Java.util.hashMap; Import Java.util.List; Import Java.util.map; org.springframework.web.bind.annotation.requestMethod.get; statische org.springframework.web.bind.annotation.requestMethod.Post; ArticlerestController {@autowired Private Artikelservice Artikelservice; @RequestMapping(value = "/article", method = POST, produces = "application/json") @ApiOperation(value = "Add article", notes = "Add new article", tags = "Article",httpMethod = "POST") @ApiImplicitParams({ @ApiImplicitParam(name = "title", value = "Article title", required = true, dataType = "String"), @ApiImplicitParam(name = "summary", value = "Article summary", required = true, dataType = "String"), @ApiImplicitParam(name = "status", value = "Publish status", required = true, dataType = "Integer") }) @ApiResponses({ @ApiResponse(code=200,message="Success",response=WebResponse.class), }) public Webresponse <map <String, Objekt >> savearticle (@RequestBody Artikel) {Artikelservice.savearticle (Artikel); Karte <String, Object> ret = new HashMap <> (); ret.put ("id", article.getId ()); Webesponse <map <String, Objekt >> response = webesponse.getSuccessResponse (ret); Rücksendemantwort; } @ApiOperation(value = "Delete article", notes = "Delete article by ID", tags = "Article",httpMethod = "DELETE") @ApiImplicitParams({ @ApiImplicitParam(name = "id", value = "Article ID", required = true, dataType = "Long") }) @RequestMapping(value = "/{id}",method = Delete, procuses = "application/json") public webespesponse <?> Deletearticle (@PathVariable Long id) {article article = articleService.getById (id); Artikel.SetStatus (-1); Artikelservice.Savearticle (Artikel); return webesponse.getSuccessResponse (neuer Hashmap <> ()); } @ApiOperation(value = "Get the article list", notes = "Full query according to the title", tags = "Article",httpMethod = "GET") @ApiImplicitParams({ @ApiImplicitParam(name = "title", value = "Article title", required = false, dataType = "String"), @ApiImplicitParam(name = "pageSize", value = "Number of Artikel pro Seite ", benötigt = false, DataType =" Integer "), @APiimPlictaram (name =" pagenum ", value =" PagePage -Nummer ", erforderlich = false, DataType =" Integer ")}) @RequestMapping (Value ="/artike/list ", method = applyes =" application/json). Integer pagenum) {if (pageSize == null) {pageSize = 10; } if (pagenum == null) {pagenum = 1; } int offset = (pagenum - 1) * pageSize; Liste <artikels> Artikel = Artikelservice.getArticles (Titel, 1L, Offset, PageSize); return webesponse.getSuccessResponse (Artikel); } @Apioperation (value = "article aktualisieren", Notes = "Artikelinhalte aktualisieren", Tags = "Artikel", httpMethod = "put") @APIimPlictParams ({@APIimPlictParam (name = "id", value = "article id", forders true = acies = "String"), @ApiImplicitParam(name = "summary", value = "Article summary", required = false, dataType = "String"), @ApiImplicitParam(name = "status", value = "Publish status", required = false, dataType = "Integer") }) @RequestMapping(value = "/article/{id}", method = PUT, produces = "application/json") public webresponse <?> updatearticle (@PathVariable Long ID,@RequestBody Artikel Artikel) {article.setId (id); Artikelservice.UpDATETICL (Artikel); return webesponse.getSuccessResponse (neuer Hashmap <> ()); }}Erläutern wir die spezifischen Funktionen mehrerer Anmerkungen und verwandter Attribute im Code:
@Apioperation, die gesamte Schnittstellenattributkonfiguration:
Wert: Schnittstellenbeschreibung, angezeigt in der Schnittstellenliste.
Hinweise: Detaillierte Beschreibung der Schnittstelle, angezeigt auf der Seite Schnittstellendetails.
Tags: Das Tag der Schnittstelle. Die Schnittstelle mit demselben Tag wird unter einer Registerkartenseite angezeigt.
HTTPMethod: unterstützte HTTP -Methode.
@APIImplicitParams, ein Container für @apiimplicitParam, kann mehrere @APiimPlicticParam -Annotationen enthalten
@APIImplicitParam, Request Parameter Attributkonfiguration:
Name: Parametername
Wert: Parameterbeschreibung
Erforderlich: Ist es notwendig?
Datentyp: Datentyp
@APIResponses, @APIResponse -Container, können mehrere @APIResponse -Anmerkungen enthalten
@APIREPPONSE geben die Konfiguration des Ergebnisattributs zurück:
Code: Gibt die Codierung des Ergebnisses zurück.
Nachricht: Gibt die Beschreibung des Ergebnisses zurück.
Antwort: Gibt die entsprechende Klasse des Ergebnisses zurück.
Schauen wir uns nach Abschluss der obigen Konfiguration den Seiteneffekt an:
Listenseite:
Wie Sie sehen können, befinden sich die Schnittstellen jetzt unter dem Artikel -Tag, und es gibt auch Anweisungen für unsere Konfiguration hinter der Schnittstelle. Schauen wir uns die Detail -Seite der Schnittstelle "Post /REST /ARTIKEL" an:
Das Bild ist zu groß, und nur die Anzeige des Titelattributs wird abgefangen, und die anderen Parameter sind ähnlich. Auf der Seite können wir sehen, dass es Anweisungen für Anforderungsparameter gibt, dies ist jedoch nicht der Effekt, den wir erwartet haben. Wenn unsere Parameter nur einfache Typen sind, sollte diese Methode in Ordnung sein, aber das Problem ist nun, dass unsere Anforderungsparameter ein Objekt sind. Wie konfigurieren Sie sie also? Dies beinhaltet zwei weitere Anmerkungen: @apimodel und @apimodelProperty. Schauen wir uns zuerst den Code an und erklären Sie ihn dann, was leichter zu verstehen ist:
@Apimodel (value = "article Object", Beschreibung = "Artikel hinzufügen und aktualisieren Artikel Objekt Beschreibung") public class Artikel {@id @generatedValue @APimodelProperty (name = "id", value = "article id", fordert = false, example = "1") Private Long ID; @ApimodelProperty (name = "title", value = "article title", fordert = true, example = "testen article title") private String -Titel; @ApimodelProperty (name = "summary", value = "article summary", fordert = true, Beispiel = "Zusammenfassung der Artikel testen") private String -Zusammenfassung; @ApimodelProperty (hidden = true) Private Datum CreateTime; @ApimodelProperty (hidden = true) Private Datum Publictime; @ApimodelProperty (hidden = true) Private Datum Updatetime; @ApimodelProperty (hidden = true) private long userId; @ApimodelProperty (name = "status", value = "Artikelfreigabestatus", fordert = true, example = "1") privater Ganzzahlstatus; @ApimodelProperty (name = "type", value = "Artikelkategorie", fordert = true, example = "1") privater Ganzzahl -Typ;}@APImodel ist die Konfiguration der Eigenschaften der gesamten Klasse:
Wert: Beschreibung der Klasse
Beschreibung: Detaillierte Beschreibung
@APimodelProperty ist die Konfiguration der Eigenschaften jedes Feldes im Detail:
Name: Feldname
Wert: Feld Beschreibung
Erforderlich: Ist es notwendig?
Beispiel: Beispielwert
versteckt: Ob angezeigt werden
Schauen wir uns nach Abschluss der obigen Konfiguration den Effekt an:
Jetzt können wir sehen, dass die Feldbeschreibung gezeigt wurde und der Wert des Feldes im Beispiel auch zum entsprechenden Wert der von uns konfigurierten Beispieleigenschaft geworden ist. Auf diese Weise wird ein vollständiges API -Dokument generiert und das Dokument ist eher mit dem Code verbunden und nicht mit den beiden isolierten Teilen. Darüber hinaus können wir es auch leicht über dieses Dokument testen. Wir müssen nur unter dem Beispielwert auf das gelbe Feld klicken, und der Inhalt im Inhalt wird automatisch in das entsprechende Wertschiffe des Artikels kopiert und klicken Sie dann auf "Probieren Sie es aus", um eine HTTP -Anforderung zu initiieren.
Nachdem Sie es klicken, können wir das zurückgegebene Ergebnis sehen:
Der Betrieb ist immer noch sehr bequem. Im Vergleich zu Junit und Postman ist das Testen durch die SWAGE bequemer. Natürlich können die Tests von Swagger die Unit -Tests nicht ersetzen, hat jedoch immer noch einen sehr wichtigen Effekt beim gemeinsamen Debuggen.
4. Zusammenfassung
Insgesamt ist die Konfiguration von Swagger relativ einfach, und die Fähigkeit von Swagger, Dokumente automatisch zu generieren, hat uns in der Tat viel Arbeit gespart und für die anschließende Wartung eine große Hilfe geleistet. Darüber hinaus kann Swagger automatisch Testdaten für uns entsprechend der Konfiguration generieren und entsprechende HTTP-Methoden bereitstellen, was auch für unsere Selbsttest- und gemeinsamen Debugging-Arbeiten hilfreich ist. Daher empfehle ich weiterhin, dass Sie Sprist in der täglichen Entwicklung verwenden, um Ihre Arbeitseffizienz in gewissem Maße zu verbessern. Lassen Sie mich schließlich eine Frage für Sie überlassen, über die Sie nachdenken können, dh auf das Dokument kann direkt über die Seite zugegriffen werden, sodass wir die Schnittstelle nicht direkt in die Produktionsumgebung aussetzen können, insbesondere Systeme, die externe Dienste anbieten müssen. Wie können wir diese Funktion im Produktionsprozess ausschalten? Es gibt viele Methoden, Sie können es selbst ausprobieren.
Das obige ist der tatsächliche Kampf des vom Herausgeber vorgestellten Spring Boot Integrated Swagger2 -Projekts. Ich hoffe, es wird Ihnen hilfreich sein. Wenn Sie Fragen haben, hinterlassen Sie mir bitte eine Nachricht und der Editor wird Ihnen rechtzeitig antworten. Vielen Dank für Ihre Unterstützung auf der Wulin.com -Website!