בנה API של REST עם Spring ו- Java Config

REST למעלה

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

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

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

מאמר זה מראה כיצד להקים REST באביב - קודי התגובה של בקר ו- HTTP, תצורה של סידור מטענים ומשא ומתן על תוכן.

2. הבנת המנוחה באביב

מסגרת האביב תומכת בשתי דרכים ליצור שירותי RESTful:

  • באמצעות MVC עם ModelAndView
  • באמצעות ממירי הודעות HTTP

ה ModelAndView הגישה ישנה ומתועדת הרבה יותר, אך גם יותר מילולית וכבדה בתצורה. היא מנסה לקצור את פרדיגמת ה- REST במודל הישן, שאינו חף מבעיות. צוות האביב הבין זאת וסיפק תמיכת REST ממדרגה ראשונה החל באביב 3.0.

הגישה החדשה, המבוססת על HttpMessageConverter והערות, הוא הרבה יותר קל וקל ליישום. התצורה היא מינימלית והיא מספקת ברירות מחדל הגיוניות למה שהיית מצפה משירות RESTful.

3. תצורת Java

@Configuration @EnableWebMvc WebConfig בכיתה ציבורית {//}

החדש @EnableWebMvc ההערה עושה כמה דברים שימושיים - באופן ספציפי, במקרה של REST, היא מגלה את קיומם של ג'קסון ו- JAXB 2 על מסלול הכיתה ויוצרת ורושמת אוטומטית ממירי JSON ו- XML ​​המוגדרים כברירת מחדל. הפונקציונליות של ההערה שווה ערך לגרסת ה- XML:

זהו קיצור דרך, ולמרות שהוא עשוי להיות שימושי במצבים רבים, זה לא מושלם. כאשר יש צורך בתצורה מורכבת יותר, הסר את ההערה והארך אותה WebMvcConfigurationSupport באופן ישיר.

3.1. שימוש במגף אביב

אם אנו משתמשים ב- @ SpringBootApplication ביאור ו אביב-webmvc הספרייה נמצאת על מסלול הכיתה ואז ה- @EnableWebMvc ההערה מתווספת אוטומטית עם תצורה אוטומטית המוגדרת כברירת מחדל.

אנו עדיין יכולים להוסיף פונקציונליות MVC לתצורה זו על ידי יישום ה- WebMvcConfigurer ממשק על @תְצוּרָה הערה בכיתה. אנו יכולים גם להשתמש ב- WebMvcRegistrationsAdapter למשל לספק משלנו RequestMappingHandlerMapping, RequestMappingHandlerAdapter, או ExceptionHandlerExceptionResolver יישומים.

לבסוף, אם אנו רוצים להשליך את תכונות ה- MVC של Spring Boot ולהצהיר על תצורה מותאמת אישית, אנו יכולים לעשות זאת באמצעות @EnableWebMvc ביאור.

4. בדיקת הקשר האביבי

החל מאביב 3.1, אנו מקבלים תמיכה בבדיקות מהשורה הראשונה @תְצוּרָה שיעורים:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (classes = {WebConfig.class, PersistenceConfig.class}, loader = AnnotationConfigContextLoader.class) class public SpringContextIntegrationTest {@Test public void contextLoads}) //

אנו מציינים את שיעורי התצורה של Java עם ה- @ContextConfiguration ביאור. החדש AnnotationConfigContextLoader טוען את הגדרות השעועית מה @תְצוּרָה שיעורים.

שימו לב שה- WebConfig מחלקת התצורה לא נכללה במבחן מכיוון שהיא צריכה לפעול בהקשר של Servlet, שאינו מסופק.

4.1. שימוש במגף אביב

Spring Boot מספק מספר הערות להגדרת האביב ApplicationContext למבחנים שלנו בצורה אינטואיטיבית יותר.

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

למשל, אנו יכולים להשתמש ב- @ SpringBootTest הערה אם אנו רוצים שנוצר את כל ההקשר מבלי להפעיל את השרת.

עם זה במקום, נוכל להוסיף את ה- @ AutoConfigureMockMvc להזריק א MockMvc למשל ולשלוח בקשות HTTP:

@RunWith (SpringRunner.class) @SpringBootTest @ AutoConfigureMockMvc בכיתה ציבורית FooControllerAppIntegrationTest {@ MowMvc mockMvc פרטית פרטית אוטומטית; @Test ציבורי בטל כאשר TestApp_thenEmptyResponse () זורק חריג {this.mockMvc.perform (get ("/ foos") .andExpect (status (). IsOk ()) .andExpect (...);}}

כדי להימנע מיצירת כל ההקשר ולבדוק רק את בקרי ה- MVC שלנו, נוכל להשתמש בו @WebMvcTest:

@RunWith (SpringRunner.class) @WebMvcTest (FooController.class) מחלקה ציבורית FooControllerWebLayerIntegrationTest {@ MowMvc פרטית MockMvc פרטית אוטומטית; שירות IFooService פרטי @MockBean; @Test () ציבורי בטל כאשר TestMvcController_thenRetrieveExpectedResult () זורק חריג {// ... this.mockMvc.perform (get ("/ foos") .andExpect (...);}}

אנו יכולים למצוא מידע מפורט בנושא זה במאמר שלנו 'Testing in Spring Boot'.

5. הבקר

ה @ RestController הוא החפץ המרכזי בכל שכבת האינטרנט של ה- API של RESTful. לצורך פוסט זה הבקר מעצב דוגמת משאב REST פשוט - פו:

@RestController @RequestMapping ("/ foos") מחלקת FooController {@ שירות IFooService פרטי מאושר; @GetMapping הרשימה הציבורית findAll () {return service.findAll (); } @ GetMapping (value = "/ {id}") Foo findById (@PathVariable ("id") מזהה ארוך) {return RestPreconditions.checkFound (service.findById (id)); } @ PostMapping @ ResponseStatus (HttpStatus.CREATED) ציבורי יצירת זמן רב (משאב Foo @ @ RequestBody) {Preconditions.checkNotNull (משאב); return service.create (משאב); } @PutMapping (value = "/ {id}") @ResponseStatus (HttpStatus.OK) עדכון חלל ציבורי (@PathVariable ("id") מזהה ארוך, משאב Foo @RequestBody) {Preconditions.checkNotNull (משאב); RestPreconditions.checkNotNull (service.getById (resource.getId ())); service.update (משאב); } @DeleteMapping (value = "/ {id}") @ResponseStatus (HttpStatus.OK) מחיקה בטלנית ציבורית (@PathVariable ("id") מזהה ארוך) {service.deleteById (id); }}

אולי שמתם לב שאני משתמש בסגנון גויאבה ישר RestPreconditions תוֹעֶלֶת:

מחלקה ציבורית RestPreconditions {ציבורי סטטי T ציבורי (משאב T) {אם (משאב == null) {זרוק MyResourceNotFoundException חדש); } להחזיר משאב; }}

יישום הבקר אינו ציבורי - זאת מכיוון שהוא אינו צריך להיות כזה.

בדרך כלל, הבקר הוא האחרון בשרשרת התלות. הוא מקבל בקשות HTTP מבקר האביב הקדמי (ה- DispatcherServlet) ופשוט מאציל אותם קדימה לשכבת שירות. אם אין מקרה שימוש בו יש להזריק או לתפעל את הבקר באמצעות הפניה ישירה, אז אני מעדיף שלא להכריז עליו כציבורי.

מיפוי הבקשות פשוט. כמו בכל בקר, בפועל ערך של המיפוי, כמו גם את שיטת HTTP, קבעו את שיטת היעד לבקשה. @RequestBody יחייב את הפרמטרים של השיטה לגוף בקשת ה- HTTP, ואילו @ResponseBody עושה את אותו הדבר לגבי סוג התגובה והחזרה.

ה @ RestController הוא קצרנות לכלול את שניהם @ResponseBody וה @בקר ביאורים בכיתה שלנו.

הם גם מבטיחים שהמשאב יופעל ולא יתבצע שימוש בממיר HTTP הנכון. משא ומתן על תוכן יתקיים כדי לבחור באיזה מממירים פעילים ישתמש, בעיקר על בסיס לְקַבֵּל כותרת, אם כי ניתן להשתמש בכותרות HTTP אחרות גם לקביעת הייצוג.

6. מיפוי קודי תגובת HTTP

קודי הסטטוס של תגובת ה- HTTP הם אחד החלקים החשובים ביותר בשירות ה- REST, והנושא יכול במהירות להיות מורכב מאוד. השגת זכות אלה יכולה להיות מה שעושה או שובר את השירות.

6.1. בקשות שלא ממופות

אם אביב MVC מקבל בקשה שאין בה מיפוי, היא רואה את הבקשה כלא מותרת ומחזירה 405 שיטה שלא מותרת בחזרה ללקוח.

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

6.2. בקשות ממפות תקפות

עבור כל בקשה שיש בה מיפוי, Spring MVC רואה את הבקשה בתוקף ומגיב עם 200 אישור אם לא צוין אחרת קוד מצב.

בגלל זה הבקר מכריז אחרת @ תגובה סטטוס בשביל ה לִיצוֹר, עדכון ו לִמְחוֹק פעולות אך לא למען לקבל, אשר אכן אמור להחזיר את ברירת המחדל 200 אישור.

6.3. שגיאת לקוח

במקרה של שגיאת לקוח, מוגדרים חריגים מותאמים אישית וממופים לקודי השגיאה המתאימים.

פשוט השלכת חריגים אלה מכל אחת משכבות שכבת הרשת תבטיח ש- Spring ממפה את קוד המצב המתאים בתגובת HTTP:

@ResponseStatus (HttpStatus.BAD_REQUEST) מחלקה ציבורית BadRequestException מרחיב RuntimeException {//} @ResponseStatus (HttpStatus.NOT_FOUND) class public ResourceNotFoundException מרחיב RuntimeException {//}

חריגים אלו הם חלק מממשק ה- API של REST, וככזה, יש להשתמש בהם רק בשכבות המתאימות המתאימות ל- REST; אם למשל קיימת שכבת DAO / DAL, היא לא צריכה להשתמש ישירות בחריגים.

שים לב גם כי אלה אינם חריגים מסומנים אלא חריגים בזמן ריצה - בהתאם לתרגילי האביב והניבים.

6.4. באמצעות @ExceptionHandler

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

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

7. תלות נוספות ב- Maven

בנוסף ל אביב-webmvc תלות הנדרשת ליישום האינטרנט הסטנדרטי, נצטרך להגדיר התארגנות תוכן ופירסום לאחסון ה- API של REST:

  com.fasterxml.jackson.core jackson-databind 2.9.8 javax.xml.bind jaxb-api 2.3.1 זמן ריצה 

אלה הספריות המשמשות להמרת הייצוג של משאב ה- REST ל- JSON או ל- XML.

7.1. שימוש במגף אביב

אם ברצוננו לאחזר משאבים בתבנית JSON, Spring Boot מספק תמיכה בספריות שונות, כלומר ג'קסון, Gson ו- JSON-B.

התצורה האוטומטית מתבצעת על ידי הכללת כל אחת מספריות המיפוי שבכיתה.

בדרך כלל, אם אנו מפתחים יישום אינטרנט, רק נוסיף את קפיץ-אתחול-רשת תלות וסמכו עליה שתכלול את כל החפצים הדרושים לפרויקט שלנו:

 org.springframework.boot spring-boot-starter-web 2.1.2.RELEASE 

Spring Boot משתמש בג'קסון כברירת מחדל.

אם אנו רוצים לסדר את המשאבים שלנו בפורמט XML, נצטרך להוסיף את סיומת ה- XML ​​של ג'קסון (jackson-dataformat-xmlלתלות שלנו, או נסיגה ליישום JAXB (המסופק כברירת מחדל ב- JDK) באמצעות ה- @XmlRootElement ביאור על המשאב שלנו.

8. מסקנה

מדריך זה המחיש כיצד ליישם ולהגדיר שירות REST באמצעות תצורה מבוססת Spring ו- Java.

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

כל הקוד של מאמר זה זמין באתר Github. זהו פרויקט מבוסס Maven, כך שיהיה קל לייבא ולהפעיל אותו כפי שהוא.

REST תחתון

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

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