מדריך להפניות מחדש באביב

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

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

2. מדוע הפניה מחדש?

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

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

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

3. הפנה מחדש עם RedirectView

נתחיל בגישה הפשוטה הזו - וגם ללכת ישר לדוגמא:

@Controller @RequestMapping ("/") מחלקה ציבורית RedirectController {@GetMapping ("/ redirectWithRedirectView") public RedirectView redirectWithUsingRedirectView (תכונות RedirectAttributes) {attributes.addFlashAttribute ("flashAttribute", "redirectWithRedirectView) attributes.addAttribute ("attribute", "redirectWithRedirectView"); להחזיר RedirectView חדש ("redirectedUrl"); }}

מאחורי הקלעים, RedirectView יפעיל א HttpServletResponse.sendRedirect () - אשר יבצע את ההפניה מחדש בפועל.

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

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

בואו נבדוק כעת את ההפניה שלנו - בעזרת פשוט סִלְסוּל פקודה:

curl -i // localhost: 8080 / spring-rest / redirectWithRedirectView

התוצאה תהיה:

HTTP / 1.1 302 נמצא שרת: Apache-Coyote / 1.1 מיקום: // localhost: 8080 / spring-rest / redirectedUrl? Attribute = redirectWithRedirectView

4. הפנה מחדש עם הקידומת הפניה מחדש:

הגישה הקודמת - שימוש RedirectView - אינו אופטימלי מכמה סיבות.

ראשית - אנו מצמידים כעת ל- API של אביב מכיוון שאנחנו משתמשים ב- RedirectView ישירות בקוד שלנו.

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

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

הנה איך זה נראה:

@Controller @RequestMapping ("/") class public RedirectController {@GetMapping ("/ redirectWithRedirectPrefix") public ModelAndView redirectWithUsingRedirectPrefix (ModelMap Model) {model.addAttribute ("attribute", "redirectWithRedirectPrefix"); להחזיר ModelAndView חדש ("redirect: / redirectedUrl", דגם); }} 

כאשר שם תצוגה מוחזר עם הקידומת הפניה מחדש:ה UrlBasedViewResolver (וכל מחלקות המשנה שלו) יזהו בכך אינדיקציה מיוחדת לכך שההפניה מחדש צריכה לקרות. שאר שם התצוגה ישמש ככתובת האתר להפניה מחדש.

הערה מהירה אך חשובה כאן היא שכאשר אנו משתמשים בשם התצוגה ההגיונית הזו כאן - הפניה מחדש: / redirectedUrl אנחנו עושים הפניה מחדש יחסית להקשר הנוכחי של Servlet.

אנו יכולים להשתמש בשם כגון הפניה מחדש: // localhost: 8080 / spring-redirect-and-forward / redirectedUrl אם עלינו להפנות מחדש לכתובת אתר מוחלטת.

אז עכשיו, כאשר אנו מבצעים את סִלְסוּל פקודה:

curl -i // localhost: 8080 / spring-rest / redirectWithRedirectPrefix

מייד נעבור:

HTTP / 1.1 302 נמצא שרת: Apache-Coyote / 1.1 מיקום: // localhost: 8080 / spring-rest / redirectedUrl? Attribute = redirectWithRedirectPrefix

5. קדימה עם הקידומת קָדִימָה:

בואו נראה עכשיו איך לעשות משהו מעט שונה - קדימה.

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

  • הפניה מחדש יגיב באמצעות 302 וכתובת האתר החדשה ב- מקום כּוֹתֶרֶת; הדפדפן / לקוח יגיש בקשה נוספת לכתובת האתר החדשה
  • קָדִימָה קורה לחלוטין בצד השרת; מיכל Servlet מעביר את אותה בקשה לכתובת אתר היעד; כתובת האתר לא תשתנה בדפדפן

עכשיו בואו נסתכל על הקוד:

@Controller @RequestMapping ("/") class class RedirectController {@GetMapping ("/ forwardWithForwardPrefix") public ModelAndView redirectWithUsingForwardPrefix (ModelMap Model) {model.addAttribute ("attribute", "forwardWithForwardPrefix"); להחזיר ModelAndView חדש ("קדימה: / redirectedUrl", דגם); }} 

כמו הפניה מחדש:, ה קָדִימָה: הקידומת תיפתר על ידי UrlBasedViewResolver ותתי הסוגים שלה. באופן פנימי, זה ייצור תצוגה פנימית שעושה א RequestDispatcher.forward () לתצוגה החדשה.

כאשר אנו מבצעים את הפקודה עם סִלְסוּל:

curl -I // localhost: 8080 / spring-rest / forwardWithForwardPrefix 

נקבל HTTP 405 (שיטה אסורה):

HTTP / 1.1 405 שיטה לא מותרת שרת: Apache-Coyote / 1.1 אפשר: GET סוג תוכן: text / html; charset = utf-8

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

6. תכונות עם מאפייני הפניה מחדש

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

@GetMapping ("/ redirectWithRedirectAttribute") ציבורי RedirectView redirectWithRedirectAttributes (תכונות RedirectAttributes) {attributes.addFlashAttribute ("flashAttribute", "redirectWithRedirectAttribute") attributes.addAttribute ("attribute", "redirectWithRedirectAttributes"); להחזיר RedirectView חדש ("redirectedUrl"); } 

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

שימו לב גם לכך אנו מוסיפים גם תכונת פלאש - זו תכונה שלא תגיע לכתובת האתר. מה שאנו יכולים להשיג בעזרת תכונה מסוג זה הוא - מאוחר יותר נוכל לגשת לתכונת הפלאש באמצעות @ModelAttribute ("flashAttribute")רק בשיטה שהיא היעד הסופי להפניה מחדש:

@GetMapping ("/ redirectedUrl") הפניה מחדש של ModelAndView (ModelMap Model, @ModelAttribute ("flashAttribute") אובייקט flashAttribute) {model.addAttribute ("redirectionAttribute", flashAttribute); להחזיר ModelAndView חדש ("ניתוב מחדש", מודל); } 

אז, לסיכום - אם נבדוק את הפונקציונליות עם סִלְסוּל:

curl -i // localhost: 8080 / spring-rest / redirectWithRedirectAttributes

אנו יופנו למיקום החדש:

HTTP / 1.1 302 שרת נמצא: Apache-Coyote / 1.1 Set-Cookie: JSESSIONID = 4B70D8FADA2FD6C22E73312C2B57E381; נתיב = / קפיץ-מנוחה /; HttpOnly מיקום: // localhost: 8080 / spring-rest / redirectedUrl; jsessionid = 4B70D8FADA2FD6C22E73312C2B57E381? attribute = redirectWithRedirectAttributes

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

7. תצורה חלופית ללא הקידומת

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

כדי להשיג זאת, עלינו להשתמש ב- org.springframework.web.servlet.view.XmlViewResolver:

  /WEB-INF/spring-views.xml 

במקום org.springframework.web.servlet.view.InternalResourceViewResolver השתמשנו בתצורה הקודמת:

עלינו גם להגדיר א RedirectView שעועית בתצורה:

עכשיו אנחנו יכולים הפעל את ההפניה מחדש על ידי הפניה של שעועית חדשה זו לפי מזהה:

@Controller @RequestMapping ("/") מחלקה ציבורית RedirectController {@GetMapping ("/ redirectWithXMLConfig") public ModelAndView redirectWithUsingXMLConfig (ModelMap Model) {model.addAttribute ("attribute", "redirectWithXMLConfig"); להחזיר ModelAndView חדש ("RedirectedUrl", דגם); }} 

וכדי לבדוק זאת, נשתמש שוב ב- סִלְסוּל פקודה:

curl -i // localhost: 8080 / spring-rest / redirectWithRedirectView

התוצאה תהיה:

HTTP / 1.1 302 נמצא שרת: Apache-Coyote / 1.1 מיקום: // localhost: 8080 / spring-rest / redirectedUrl? Attribute = redirectWithRedirectView

8. הפניית בקשת HTTP POST

במקרים לשימוש כמו תשלומים בנקאיים, ייתכן שנצטרך להפנות מחדש בקשת HTTP POST. בהתאם לקוד סטטוס ה- HTTP שהוחזר, ניתן להפנות בקשת POST ל- HTTP GET או POST.

בהתאם להפניית פרוטוקול HTTP 1.1, קודי המצב 301 (הועבר לצמיתות) ו- 302 (נמצא) מאפשרים לשנות את שיטת הבקשה מ- POST ל- GET. המפרט מגדיר גם את קודי הסטטוס המקבילים 307 (הפניה זמנית) ו- 308 (הפניה קבועה) שאינם מאפשרים לשנות את שיטת הבקשה מ- POST ל- GET.

עכשיו בואו נסתכל על הקוד להפניית בקשת פרסום לבקשת פרסום אחרת:

@PostMapping ("/ redirectPostToPost") ModelAndView ציבורי redirectPostToPost (בקשת HttpServletRequest) {request.setAttribute (View.RESPONSE_STATUS_ATTRIBUTE, HttpStatus.TEMPORARY_REDIRECT); להחזיר ModelAndView חדש ("redirect: / redirectedPostToPost"); }
@PostMapping ("/ redirectedPostToPost") ציבורי ModelAndView redirectedPostToPost () {להחזיר ModelAndView חדש ("ניתוב מחדש"); }

עכשיו, בואו נבדוק את הפניה מחדש של POST באמצעות ה- סִלְסוּל פקודה:

תלתל -L --verbose -X POST // localhost: 8080 / spring-rest / redirectPostToPost

אנו מנותבים למיקום המיועד:

> POST / redirectedPostToPost HTTP / 1.1> מארח: localhost: 8080> User-Agent: curl / 7.49.0> Accept: * / *> <HTTP / 1.1 200 <Type Content: application / json; charset = UTF-8 < קידוד העברה: chunked <תאריך: יום שלישי, 08 באוגוסט 2017 07:33:00 GMT {"id": 1, "content": "הפניה מחדש הושלמה"}

9. מסקנה

מאמר זה מודגם שלוש גישות שונות ליישום הפניה מחדש באביב, כיצד לטפל / להעביר תכונות בעת ביצוע הפניות אלה וכן כיצד לטפל בהפניות מחדש של בקשות HTTP POST.