אביב REST Docs לעומת OpenAPI

REST למעלה

רק הכרזתי על החדש למד אביב קורס, המתמקד ביסודות האביב 5 ומגף האביב 2:

>> בדוק את הקורס

1. סקירה כללית

Spring REST Docs ו- OpenAPI 3.0 הן שתי דרכים ליצור תיעוד API ל- API של REST.

במדריך זה נבחן את היתרונות והחסרונות היחסיים שלהם.

2. סיכום קצר של מקורות

Spring REST Docs היא מסגרת שפותחה על ידי קהילת Spring במטרה ליצור תיעוד מדויק עבור ממשקי API של RESTful. נדרשת גישה מונחית-מבחן, שבו התיעוד כתוב כמבחני MVC של Spring, של Spring Webflux WebTestClient, או מבטיח מנוחה.

הפלט של הפעלת הבדיקות נוצר כקבצי AsciiDoc אותם ניתן להרכיב באמצעות Asciidoctor כדי ליצור דף HTML המתאר את ממשקי ה- API שלנו. מכיוון שהיא פועלת בשיטת TDD, Spring REST Docs מביא אוטומטית את כל היתרונות שלה כגון קוד פחות נוטה לשגיאות, עיבוד חוזר מופחת ומחזורי משוב מהירים יותר, עד כמה שם.

לעומת זאת OpenAPI הוא מפרט שנולד מתוך Swagger 2.0. הגרסה האחרונה שלה נכון לכתיבת שורות אלה היא 3.0 ויש לה יישומים ידועים רבים.

כמו כל מפרט אחר, OpenAPI מציבה כללי יסוד מסוימים להטמעתם. במילים פשוטות, הכל יישומי OpenAPI אמורים לייצר את התיעוד כאובייקט JSON, בפורמט JSON או YAML.

ישנם גם כלים רבים שמכניסים את ה- JSON / YAML הזה ויורקים ממשק משתמש כדי לדמיין ולנווט בממשק ה- API. זה שימושי במהלך בדיקות קבלה, למשל. בדוגמאות הקוד שלנו כאן נשתמש springdoc - ספרייה עבור OpenAPI 3 עם Spring Boot.

לפני שנסתכל בפירוט על השניים, בואו נקבע במהירות API שיתועד.

3. ממשק ה- API של REST

בואו נרכיב CRUD API בסיסי באמצעות Spring Boot.

3.1. המאגר

כאן המאגר בו נשתמש הוא עצמות חשופות PagingAndSortingRepository ממשק, עם הדגם פו:

ממשק ציבורי @ מאגר FooRepository מרחיב את PagingAndSortingRepository {} @Entity class Foo {@Id @GeneratedValue (אסטרטגיה = GenerationType.IDENTITY) מזהה פרטי ארוך; @Column (nullable = false) כותרת מחרוזת פרטית; @Column () גוף מחרוזת פרטי; // קונסטרוקטור, גטרים וקובעים}

נטען את המאגר באמצעות a schema.sql ו data.sql.

3.2. הבקר

לאחר מכן, בואו נסתכל על הבקר, ודלג על פרטי היישום שלו בקיצור:

@RestController @RequestMapping ("/ foo") FooController בכיתה ציבורית {@ מאגר FooRepository אוטומטי; @GetMapping תגובה ציבורית getAllFoos () {// יישום} @ GetMapping (value = "{id}") תגובה ResponseEntity ציבורית getFooById (@PathVariable ("id") מזהה ארוך) {// יישום} @ PostMapping הציבור ResponseEntity addFoo (@RequestBody @ Valid Foo foo ) {// implementation} @DeleteMapping ("/ {id}") ResponseEntity public deleteFoo (@PathVariable ("id") מזהה ארוך) {// implementation} @PutMapping ("/ {id}") ResponseEntity ציבורי updateFoo (@ מזהה ארוך PathVariable ("id"), @RequestBody Foo foo) {// יישום}}

3.3. היישום

ולסיום, אפליקציית האתחול:

@SpringBootApplication () יישום מחלקה ציבורית {public public static void (String [] args) {SpringApplication.run (Application.class, args); }}

4. OpenAPI / Springdoc

עכשיו בואו נראה איך springdoc יכול להוסיף תיעוד שלנו פו ממשק API של REST.

נזכיר את זה זה ייצור אובייקט JSON והדמיית ממשק משתמש של ממשק ה- API בהתבסס על אובייקט זה.

4.1. ממשק משתמש בסיסי

ראשית, רק נוסיף כמה תלות של Maven - springdoc-openapi-data-rest להפקת ה- JSON, ו- springdoc-openapi-ui לעיבוד ממשק המשתמש.

הכלי יבחן את הקוד עבור ה- API שלנו ויקרא את ההערות של שיטות הבקר. על בסיס זה, הוא ייצור את ה- API JSON אשר יהיה פעיל ב // localhost: 8080 / api-docs /. זה ישרת גם ממשק משתמש בסיסי בשעה //localhost:8080/swagger-ui-custom.html:

כפי שאנו רואים, מבלי להוסיף קוד בכלל, השגנו הדמיה יפה של ה- API שלנו, ממש עד ל- פו סכֵימָה. משתמש ב נסה את זה אנו יכולים אפילו לבצע את הפעולות ולראות את התוצאות.

עַכשָׁיו, מה אם נרצה להוסיף קצת תיעוד אמיתי ל- API? במונחים של מה ממשק ה- API, מה המשמעות של כל פעולותיו, מה צריך להזין, ואילו תגובות לצפות?

אנו נסתכל על זה בחלק הבא.

4.2. ממשק משתמש מפורט

בואו נראה תחילה כיצד להוסיף תיאור כללי ל- API.

לשם כך נוסיף OpenAPI שעועית לאפליקציית האתחול שלנו:

@Bean OpenAPI פומבית customOpenAPI (@Value ("$ {springdoc.version}") appVersion מחרוזת) {להחזיר OpenAPI חדש (). מידע (מידע חדש () .title ("Foobar API") .version (appVersion). תיאור ( "זהו שרת Foobar לדוגמא שנוצר באמצעות Springdocs -" + "ספרייה עבור OpenAPI 3 עם אתחול קפיץ.") .TermsOfService ("// swagger.io/terms/") .license (רישיון חדש (). Name (" אפאצ'י 2.0 ") .url (" // springdoc.org "))); } 

לאחר מכן, כדי להוסיף קצת מידע לפעולות ה- API שלנו, נקשט את המיפויים שלנו בכמה הערות ספציפיות ל- OpenAPI.

בואו נראה איך נוכל לתאר getFooById. נעשה זאת בתוך בקר אחר, FooBarController, הדומה לשלנו FooController:

@RestController @RequestMapping ("/ foobar") @Tag (name = "foobar", תיאור = "ה- API של foobar עם הערות תיעוד") FooBarController בכיתה ציבורית {@ מאגר FooRepository אוטומטי; @Operation (סיכום = "קבל foo לפי foo id") @ApiResponses (value = {@ApiResponse (responseCode = "200", תיאור = "מצא את foo", content = {@Content (mediaType = "application / json") , סכמה = @Schema (יישום = Foo.class))}), @ApiResponse (responseCode = "400", תיאור = "מסופק מזהה לא חוקי", content = @Content), @ApiResponse (responseCode = "404", תיאור = "Foo לא נמצא", content = @Content)}) @ GetMapping (value = "{id}") ResponseEntity ציבורי getFooById (@Parameter (תיאור = "id של foo לחיפוש") @ PathVariable ("id") מחרוזת id) {// יישום הושמט לקיצור הדרך} // מיפויים אחרים, שהוסרו באופן דומה ל- @Operation ו- @ApiResponses} 

בואו נראה את ההשפעה על ממשק המשתמש:

אז עם התצורות המינימליות האלה, המשתמש של ה- API שלנו יכול כעת לראות על מה מדובר, כיצד להשתמש בו ואילו תוצאות לצפות. כל מה שהיינו צריכים לעשות היה לאסוף את הקוד ולהפעיל את אפליקציית האתחול.

5. מסמכי REST באביב

מסמכי REST הם שינוי שונה לחלוטין בתיעוד ה- API. כפי שתואר קודם לכן, התהליך מונע על ידי בדיקה, והפלט הוא בצורת דף HTML סטטי.

בדוגמה שלנו כאן, נשתמש בבדיקות MVC באביב ליצירת קטעי תיעוד.

בהתחלה, נצטרך להוסיף את ה- spring-restdocs-mockmvc תלות ו asciidoc תוסף Maven שלנו פום.

5.1. מבחן JUnit5

עכשיו בואו נסתכל על מבחן JUnit5 הכולל את התיעוד שלנו:

@ExtendWith ({RestDocumentationExtension.class, SpringExtension.class}) @SpringBootTest (classes = Application.class) מחלקה ציבורית SpringRestDocsIntegrationTest {private MockMvc mockMvc; @MobjectMapper אובייקט פרטי אוטומטי; @ לפני כל הגדרת חלל ציבורי (WebApplicationContext webApplicationContext, RestDocumentationContextProvider restDocumentation) {this.mockMvc = MockMvcBuilders.webAppContextSetup (webApplicationContext). החל (documentConfiguration (restDocumentation)). } @Test ציבורי בטל כאשר GetFooById_thenSuccessful () זורק חריג {ConstraintDescriptions desc = ConstraintDescriptions חדש (Foo.class); this.mockMvc.perform (get ("/ foo / {id}", 1)). andExpect (status (). isOk ()). andDo (document ("getAFoo", preprocessRequest (prettyPrint ()), preprocessResponse (prettyPrint ()), pathParameters (parameterWithName ("id"). תיאור ("id של foo שיש לחפש")), responseFields (fieldWithPath ("id") .description ("ID של foo" + collectionToDelimitedString (desc.descriptionsForProperty) ("id"), ".")), fieldWithPath ("title"). תיאור ("כותרת foo"), fieldWithPath ("body"). תיאור ("body of the foo")))) ; } // שיטות בדיקה נוספות לכיסוי מיפויים אחרים

}

לאחר הפעלת בדיקה זו, אנו מקבלים מספר קבצים ב- יעדים / קטעי שנוצר ספריה עם מידע על פעולת ה- API הנתונה. בִּמְיוּחָד, whenGetFooById_thenSuccessful ייתן לנו שמונה אדוקs ב getAFoo בתיקיה.

הנה דוגמא http-response.adoc, כמובן המכיל את גוף התגובה:

[source, http, options = "nowrap"] ---- HTTP / 1.1 200 OK סוג תוכן: application / json אורך תוכן: 60 {"id": 1, "title": "Foo 1", "body ":" Foo body 1 "} ----

5.2. fooapi.adoc

כעת אנו זקוקים לקובץ מאסטר שישזור את כל התמציות הללו יחד כדי ליצור HTML מובנה היטב.

בוא נקרא לזה fooapi.adoc וראה חלק קטן ממנו:

=== גישה ל- foo GET בקשה `GET` משמשת לגישה לקריאת foo. ==== מבנה הבקשה כולל :: {snippets} /getAFoo/http-request.adoc [] ==== פרמטרי הנתיב כוללים :: {snippets} /getAFoo/path-parameters.adoc [] ==== תגובה לדוגמא לכלול :: {snippets} /getAFoo/http-response.adoc [] ==== בקשת CURL כוללים :: {snippets} /getAFoo/curl-request.adoc []

לאחר ביצוע ה- תוסף asciidoctor-maven, אנו מקבלים את קובץ ה- HTML הסופי fooapi.html בתוך ה מטרה / מסמכים שנוצרו תיקיה.

וככה זה ייראה כשנפתח בדפדפן:

6. Takeaways מפתח

כעת, לאחר שבחנו את שתי היישומים, נסכם את היתרונות והחסרונות.

עם springdoc, ההערות שהיינו צריכים להשתמש עמוסו בקוד בקר המנוחה שלנו והפחיתו את הקריאה שלו. כמו כן, התיעוד הוצמד היטב לקוד ויעשה את דרכו לייצור.

מיותר לציין ששמירה על התיעוד היא כאן אתגר נוסף - אם משהו בממשק ה- API ישתנה, האם המתכנת תמיד יזכור לעדכן את ההערה המקבילה של OpenAPI?

מצד שני, REST Docs לא נראה קליט כמו ממשק המשתמש האחר וגם לא ניתן להשתמש בו לבדיקת קבלה. אבל יש לזה יתרונות.

יש לציין שההשלמה המוצלחת של מבחן ה- MVC של Spring לא רק נותן לנו את קטעי המידע, אלא גם מאמת את ה- API שלנו כמו כל בדיקת יחידה אחרת. זה מאלץ אותנו לבצע שינויים בתיעוד המתאימים לשינויים בממשק ה- API, אם בכלל. כמו כן, קוד התיעוד נפרד לחלוטין מההטמעה.

אבל שוב, מצד שני, היינו צריכים לכתוב קוד נוסף כדי ליצור את התיעוד. ראשית, המבחן עצמו שניתן לטעון באופן מילולי כמו ההערות OpenAPI, והשני, המאסטר אדוק.

זה גם זקוק לשלבים נוספים כדי ליצור את ה- HTML הסופי - מריצים תחילה את הבדיקה ואז את התוסף. ספרינגדוק רק דרש מאיתנו להפעיל את אפליקציית האתחול.

7. מסקנה

במדריך זה בדקנו את ההבדלים בין המבוסס על OpenAPI springdoc ומסמכי REST באביב. ראינו גם כיצד ליישם את השניים כדי ליצור תיעוד עבור CRUD API בסיסי.

לסיכום, לשניהם היתרונות והחסרונות שלהם, וההחלטה להשתמש בזה אחר זה כפופה לדרישות הספציפיות שלנו.

כמו תמיד, קוד המקור זמין ב- GitHub.

REST תחתון

רק הכרזתי על החדש למד אביב קורס, המתמקד ביסודות האביב 5 ומגף האביב 2:

>> בדוק את הקורס

$config[zx-auto] not found$config[zx-overlay] not found