מבוא לרחוק באביב עם זומני ​​HTTP

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

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

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

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

2. הגדרת שירות

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

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

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

2.1. ממשק שירות

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

ממשק ציבורי CabBookingService {הזמנת bookRide (מחרוזת pickUpLocation) זורק BookingException; }

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

הזמנת מחלקה ציבורית מיישמת באמצעות Serializable {private String bookingCode; @ עקירה ציבורית מחרוזת toString () {פורמט החזרה ("נסיעה מאושרת: קוד '% s'.", BookingCode); } // גטרים / סטרים סטנדרטיים ובנאי}

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

מעמד ציבורי BookingException מרחיב חריג {public BookingException (הודעת מחרוזת) {super (הודעה); }}

2.2. אריזת השירות

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

בואו נכניס את כל הקוד למודול ייעודי של Maven, שנקרא "api"; נשתמש בקואורדינטות הבאות של Maven לדוגמא זו:

com.baeldung api 1.0-SNAPSHOT

3. יישום שרת

בואו לבנות את יישום מנוע ההזמנות כדי לחשוף את השירות באמצעות Spring Boot.

3.1. תלות Maven

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

 org.springframework.boot spring-boot-starter-parent 2.2.2.RELEASE 

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

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

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

 com.baeldung api 1.0-SNAPSHOT 

3.2. יישום שירות

ראשית אנו מגדירים מחלקה המיישמת את ממשק השירות:

מחלקה ציבורית CabBookingServiceImpl מיישמת את CabBookingService {@Override public Booking bookPickUp (מחרוזת pickUpLocation) זורק BookingException {אם (אקראי () <0.3) זורק BookingException חדש ("מונית לא זמינה"); החזר הזמנה חדשה (randomUUID (). toString ()); }}

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

3.3. חשיפת השירות

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

@Configuration @ComponentScan @ EnableAutoConfiguration שרת מחלקה ציבורית {@Bean (name = "/ booking") HttpInvokerServiceExporter accountService () {HttpInvokerServiceExporter exporter = new HttpInvokerServiceExporter (); exporter.setService (CabBookingServiceImpl חדש ()); exporter.setServiceInterface (CabBookingService.class); יצואן החזרה; } ראשי סטטי ציבורי ריק (String [] args) {SpringApplication.run (Server.class, args); }}

ראוי לציין את זה של האביב מזמין HTTP משתמש בשם ה- HttpInvokerServiceExporter שעועית כנתיב יחסי לכתובת ה- URL של נקודת הקצה HTTP.

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

4. יישום לקוח

בואו נכתוב כעת את יישום הלקוח.

4.1. תלות Maven

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

 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-tomcat 

4.2. יישום לקוח

בואו ניישם את הלקוח:

@Configuration class class לקוח {@Bean public HttpInvokerProxyFactoryBean invoker () {HttpInvokerProxyFactoryBean invoker = new HttpInvokerProxyFactoryBean (); invoker.setServiceUrl ("// localhost: 8080 / booking"); invoker.setServiceInterface (CabBookingService.class); מזמין חוזר; } ראשי ריק סטטי ציבורי (String [] args) זורק BookingException {CabBookingService service = SpringApplication .run (Client.class, args) .getBean (CabBookingService.class); out.println (service.bookRide ("13 Seagate Blvd, Key Largo, FL 33037")); }}

ה @אפונה מזמין ביאורים() השיטה יוצרת מופע של HttpInvokerProxyFactoryBean. עלינו לספק את כתובת ה- URL שהשרת המרוחק מגיב אליה דרך ה- setServiceUrl () שיטה.

בדומה למה שעשינו עבור השרת, עלינו לספק גם את ממשק השירות שאנו רוצים להפעיל מרחוק באמצעות setServiceInterface () שיטה.

HttpInvokerProxyFactoryBean מיישם את האביב FactoryBean. א FactoryBean מוגדר כשעועית, אך מיכל ה- IoC של Spring יזריק את האובייקט שהוא יוצר, ולא את המפעל עצמו. תוכל למצוא פרטים נוספים אודות FactoryBean במאמר שעועית המפעל שלנו.

ה רָאשִׁי() השיטה מאתחלת את היישום העצמאי ומקבלת מופע של CabBookingService מההקשר. מתחת למכסה המנוע, אובייקט זה הוא רק פרוקסי שנוצר על ידי HttpInvokerProxyFactoryBean הדואג לכל הטכניקות המעורבות בביצוע ההפעלה מרחוק. הודות לכך אנו יכולים כעת להשתמש בשרת ה- proxy בקלות כפי שהיינו עושים אם יישום השירות היה זמין באופן מקומי.

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

5. סף אזהרה

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

5.1. היזהר מחריגים הקשורים לרשת

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

נניח שהלקוח מזמין את השרת בזמן שלא ניתן להגיע אליו - לא בגלל בעיית רשת או בגלל שהשרת אינו פעיל - ואז Spring Remoting יעלה RemoteAccessException זה חריגת זמן ריצה.

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

5.2. אובייקטים מועברים לפי ערך, ולא לפי הפניה

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

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

5.3. היזהר מממשקי דק

הפעלת שיטה מעבר לגבולות הרשת היא איטית משמעותית מאשר הפעלת אותה על אובייקט באותו תהליך.

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

6. מסקנה

בדוגמה זו ראינו כמה קל לעשות עם Spring Remoting להפעיל תהליך מרוחק.

הפיתרון מעט פחות פתוח ממנגנונים נרחבים אחרים כמו REST או שירותי אינטרנט, אך בתרחישים בהם כל הרכיבים מפותחים עם Spring, הוא יכול לייצג אלטרנטיבה קיימא ומהירה בהרבה.

כרגיל, תוכלו למצוא את המקורות ב- GitHub.


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