ממירי הודעות Http עם מסגרת האביב

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

מאמר זה מתאר כיצד להגדיר HttpMessageConverters באביב.

במילים פשוטות, אנו יכולים להשתמש בממירי הודעות למרשל ולא לבטל את הרישום של אובייקטי Java אל וממנו JSON, XML וכו '- באמצעות HTTP.

2. היסודות

2.1. אפשר MVC באינטרנט

ראשית, יישום האינטרנט צריך להיות מוגדר עם תמיכה באביב MVC. דרך נוחה מאוד להתאמה אישית לעשות זאת היא להשתמש ב- @EnableWebMvc ביאור:

@EnableWebMvc @Configuration @ComponentScan ({"com.baeldung.web"}) WebConfig בכיתה ציבורית מיישם את WebMvcConfigurer {...}

שים לב כי מחלקה זו מיישמת WebMvcConfigurer - מה שיאפשר לנו לשנות את רשימת ברירת המחדל של Http Converters משלנו.

2.2. ממירי ההודעות המוגדרים כברירת מחדל

כברירת מחדל, הבא HttpMessageConverter המקרים מופעלים מראש:

  • ByteArrayHttpMessageConverter - ממיר מערכי בתים
  • StringHttpMessageConverter - ממיר מיתרים
  • ResourceHttpMessageConverter - חוזר בתשובה org.springframework.core.io. משאבים לכל סוג של זרם אוקטט
  • SourceHttpMessageConverter - חוזר בתשובה javax.xml.transform.Source
  • FormHttpMessageConverter - ממיר נתוני טופס אל / מ- a MultiValueMap.
  • Jaxb2RootElementHttpMessageConverter - ממיר אובייקטים של Java ל / מ- XML ​​(נוסף רק אם JAXB2 קיים על מסלול הכיתה)
  • MappingJackson2HttpMessageConverter - ממיר את JSON (נוסף רק אם ג'קסון 2 נמצא על מסלול הכיתה)

  • MappingJacksonHttpMessageConverter - ממיר את JSON (נוסף רק אם ג'קסון נוכח על מסלול הכיתה)
  • AtomFeedHttpMessageConverter - ממיר הזנות אטום (נוסף רק אם רומא נמצאת על מסלול הכיתה)
  • RssChannelHttpMessageConverter - ממיר עדכוני RSS (נוסף רק אם רומא נמצאת על מסלול הכיתה)

3. תקשורת לקוח-שרת - JSON בלבד

3.1. משא ומתן על תוכן ברמה גבוהה

כל אחד HttpMessageConverter ליישום יש סוג MIME משויך אחד או כמה.

בעת קבלת בקשה חדשה, האביב ישתמש ב"לְקַבֵּלכותרת "כדי לקבוע את סוג המדיה עליו הוא צריך להגיב.

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

התהליך דומה לקבלת בקשה המכילה מידע על JSON. המסגרת תהיה להשתמש ב "סוג תוכןכותרת "לקביעת סוג המדיה של גוף הבקשה.

לאחר מכן הוא יחפש א HttpMessageConverter שיכול להמיר את הגוף שנשלח על ידי הלקוח לאובייקט Java.

הבה נבהיר זאת בדוגמה מהירה:

  • הלקוח שולח בקשת GET אל / foos עם ה לְקַבֵּל כותרת כותרת יישום / json - להשיג הכל פו משאבים כמו JSON
  • ה פו בקר האביב נפגע ומחזיר את המקביל פו ישויות ג'אווה
  • לאחר מכן, אביב משתמש באחד מממירי ההודעות של ג'קסון כדי לנהל את הישויות ל- JSON

בואו נסתכל כעת על הפרטים של איך זה עובד - וכיצד אנו יכולים למנף את @ResponseBody ו- @RequestBody ביאורים.

3.2. @ResponseBody

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

בואו נסתכל על דוגמה פשוטה:

@GetMapping ("/ {id}") ציבורי @ResponseBody Foo findById (@PathVariable מזהה ארוך) {return fooService.findById (id); }

כעת הלקוח יציין את הכותרת "קבל" ל- יישום / json בבקשה - דוגמא סִלְסוּל פקודה:

תלתל - כותרת "קבל: יישום / json" // localhost: 8080 / spring-boot-rest / foos / 1

ה פו מעמד:

מחלקה ציבורית Foo {מזהה פרטי ארוך; שם מחרוזת פרטי; }

וגוף התגובה Http:

{"id": 1, "name": "Paul",}

3.3. @ בקשת גוף

אנחנו יכולים להשתמש ב- @ בקשת גוף ביאור על הטיעון של שיטת בקר לציין שגוף בקשת ה- HTTP מבטל הערכה מחדש לאותה ישות Java מסוימת. כדי לקבוע את הממיר המתאים, Spring ישתמש בכותרת "סוג התוכן" מבקשת הלקוח.

בואו נסתכל על דוגמה:

@PutMapping ("/ {id}") עדכון חלל @ResponseBody ציבורי (@RequestBody Foo foo, @PathVariable מחרוזת מזהה) {fooService.update (foo); }

לאחר מכן, בואו נצרוך את זה עם אובייקט JSON - אנו מציינים "סוג תוכן להיות יישום / json:

תלתל -i -X ​​PUT -H "סוג תוכן: יישום / json" -d '{"id": "83", "name": "klik"}' // localhost: 8080 / spring-boot-rest / foos / 1

אנו מחזירים 200 בסדר - תגובה מוצלחת:

HTTP / 1.1 200 שרת אישור: אפאצ'י-זאב ערבות / 1.1 אורך תוכן: 0 תאריך: יום ו ', 10 בינואר 2014 11:18:54 GMT

4. תצורת ממירים מותאמים אישית

אנחנו יכולים גם התאמה אישית של ממירי ההודעות על ידי יישום ה- WebMvcConfigurer מִמְשָׁק ועוקף את configureMessageConverters שיטה:

@EnableWebMvc @Configuration @ComponentScan ({"com.baeldung.web"}) WebConfig בכיתה ציבורית מיישמת WebMvcConfigurer {@Override public void configureMessageConverter (List ממירים) {messageConverters.add (createXmlHttpMessageConverter ()); messageConverters.add (חדש MappingJackson2HttpMessageConverter ()); } HttpMessageConverter פרטי createXmlHttpMessageConverter () {MarshallingHttpMessageConverter xmlConverter = חדש MarshallingHttpMessageConverter (); XStreamMarshaller xstreamMarshaller = XStreamMarshaller חדש (); xmlConverter.setMarshaller (xstreamMarshaller); xmlConverter.setUnmarshaller (xstreamMarshaller); להחזיר xmlConverter; }}

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

שים לב כי דוגמה זו מחייבת הוספת ספריית XStream לשביל הכיתה.

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

אנו יכולים כמובן לעשות זאת גם עבור ג'קסון - על ידי הגדרת משלנו MappingJackson2HttpMessageConverter. כעת אנו יכולים להגדיר מנהג ObjectMapper בממיר זה והגדרו אותו כנדרש לנו.

במקרה זה, XStream היה יישום ה- marshaller / unmarshaller שנבחר, אך אחרים כמו CastorMarshaller יכול לשמש גם כן.

בשלב זה - כאשר XML מופעל בחלק האחורי - אנו יכולים לצרוך את ה- API עם ייצוגי XML:

תלתל - כותרת "קבל: יישום / xml" // localhost: 8080 / spring-boot-rest / foos / 1

4.1. תמיכה במגף האביב

אם אנו משתמשים באביב אתחול, אנו יכולים להימנע מיישום ה- WebMvcConfigurer והוספת כל ממירי ההודעות באופן ידני כפי שעשינו לעיל.

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

@Bean ציבור HttpMessageConverter createXmlHttpMessageConverter () {MarshallingHttpMessageConverter xmlConverter = חדש MarshallingHttpMessageConverter (); // ... להחזיר xmlConverter; }

5. שימוש בספרינגס RestTemplate עם ממירי הודעות Http

כמו גם בצד השרת, ניתן להגדיר המרת הודעות Http בצד הלקוח באביב RestTemplate.

אנו מתכוונים להגדיר את התבנית עם "לְקַבֵּל"ו"סוג תוכןכותרות כשמתאים. ואז ננסה לצרוך את ה- API של REST עם התארגנות מלאה ואי-מרסנות של ה- פו משאבים - גם עם JSON וגם עם XML.

5.1. אחזור המשאב ללא לְקַבֵּל כּוֹתֶרֶת

@Test ציבורי בטל testGetFoo () {מחרוזת URI = "// localhost: 8080 / spring-boot-rest / foos / {id}"; RestTemplate restTemplate = RestTemplate חדש (); Foo foo = restTemplate.getForObject (URI, Foo. class, "1"); Assert.assertEquals (מספר שלם חדש (1), foo.getId ());}

5.2. אחזור משאב באמצעות יישום / xml קבל כותרת

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

מכיוון שאנו צורכים XML, אנו נשתמש באותו מרשלר XStream כמו קודם:

@ מבחן חלל ציבורי givenConsumingXml_whenReadingTheFoo_thenCorrect () {String URI = BASE_URI + "foos / {id}"; RestTemplate restTemplate = RestTemplate חדש (); restTemplate.setMessageConverters (getMessageConverters ()); כותרות HttpHeaders = HttpHeaders חדשות (); headers.setAccept (Arrays.asList (MediaType.APPLICATION_XML)); ישות HttpEntity = HttpEntity חדש (כותרות); ResponseEntity response = restTemplate.exchange (URI, HttpMethod.GET, ישות, Foo.class, "1"); Foo resource = response.getBody (); assertThat (resource, notNullValue ()); } רשימה פרטית getMessageConverters () {Marshmaller XStreamMarshaller = XStreamMarshaller חדש (); MarshallingHttpMessageConverter marshallingConverter = חדש MarshallingHttpMessageConverter (marshaller); רשימה ממירים = ArrayList(); converters.add (marshallingConverter); ממירי החזרה; }

5.3. אחזור משאב באמצעות יישום / json קבל כותרת

באופן דומה, בואו נצרוך את ה- REST API על ידי בקשת JSON:

@ מבחן בטל פומבי שניתןConsumingJson_whenReadingTheFoo_thenCorrect () {String URI = BASE_URI + "foos / {id}"; RestTemplate restTemplate = RestTemplate חדש (); restTemplate.setMessageConverters (getMessageConverters ()); כותרות HttpHeaders = HttpHeaders חדשות (); headers.setAccept (Arrays.asList (MediaType.APPLICATION_JSON)); ישות HttpEntity = HttpEntity חדש (כותרות); ResponseEntity response = restTemplate.exchange (URI, HttpMethod.GET, ישות, Foo.class, "1"); Foo resource = response.getBody (); assertThat (resource, notNullValue ()); } רשימה פרטית getMessageConverters () {רשימה ממירים = ArrayList חדש(); converters.add (חדש MappingJackson2HttpMessageConverter ()); ממירי החזרה; }

5.4. עדכן משאב באמצעות XML סוג תוכן

לבסוף, בואו גם נשלח נתוני JSON לממשק ה- REST ונציין את סוג המדיה של הנתונים באמצעות ה- סוג תוכן כּוֹתֶרֶת:

@ מבחן חלל ציבורי givenConsumingXml_whenWritingTheFoo_thenCorrect () {String URI = BASE_URI + "foos / {id}"; RestTemplate restTemplate = RestTemplate חדש (); restTemplate.setMessageConverters (getMessageConverters ()); משאב Foo = Foo חדש (4, "jason"); כותרות HttpHeaders = HttpHeaders חדשות (); headers.setAccept (Arrays.asList (MediaType.APPLICATION_JSON)); headers.setContentType ((MediaType.APPLICATION_XML)); ישות HttpEntity = HttpEntity חדש (משאב, כותרות); תגובה ResponseEntity = restTemplate.exchange (URI, HttpMethod.PUT, ישות, Foo.class, resource.getId ()); Foo fooResponse = response.getBody (); Assert.assertEquals (resource.getId (), fooResponse.getId ()); }

מה שמעניין כאן הוא שאנחנו מסוגלים לערבב בין סוגי המדיה - אנו שולחים נתוני XML אך אנו מחכים לנתוני JSON בחזרה מהשרת. זה מראה עד כמה חזק באמת מנגנון ההמרה של אביב.

6. מסקנה

במדריך זה בדקנו כיצד Spring MVC מאפשר לנו לציין ולהתאים אישית את ממירי Http הודעות באופן מלא באופן אוטומטי / לבטל את התוכנה של ישויות Java אל XML או JSON וממנו. זו, כמובן, הגדרה פשטנית, ויש כל כך הרבה יותר שמנגנון המרת המסרים יכול לעשות - כפי שאנו יכולים לראות מהדוגמה האחרונה של הבדיקה.

בדקנו גם כיצד למנף את אותו מנגנון חזק עם ה- RestTemplate לקוח - מה שמוביל לדרך בטוחה לחלוטין של צריכת ה- API.

כמו תמיד, הקוד המוצג במאמר זה זמין באתר Github.


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