מדריך להמרות מסוג אביב

1. הקדמה

במאמר זה נבחן את ההמרות מסוג אביב.

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

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

2. מובנה מֵמִירס

נתחיל עם הממירים הזמינים מחוץ לקופסה באביב; בואו נסתכל על ה- חוּט ל מספר שלם הֲמָרָה:

@Autowired ConversionService conversionService; @Test הציבור בטל כאשר ConvertStringToIntegerUsingDefaultConverter_thenSuccess () {assertThat (conversionService.convert ("25", Integer.class)). IsEqualTo (25); }

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

מלבד זה חוּט ל מספר שלם לדוגמא, ישנם הרבה שילובים שונים אחרים הזמינים עבורנו.

3. יצירת מותאם אישית מֵמִיר

בואו נסתכל על דוגמה להמרת a חוּט ייצוג של עוֹבֵד ל עוֹבֵד למשל.

הנה ה עוֹבֵד מעמד:

שכבה ציבורית שכיר {מזהה פרטי ארוך; משכורת כפולה פרטית; // בונים סטנדרטיים, גטרים, סטרים}

ה חוּט יהיה זוג המופרד בפסיקים המייצג תְעוּדַת זֶהוּת ו שכר. לדוגמא, "1,50000.00".

על מנת ליצור את המנהג שלנו מֵמִיר, אנחנו צריכים ליישם את מֵמִיר ממשק ויישם את להמיר() שיטה:

מחלקה ציבורית StringToEmployeeConverter מיישם ממיר {@Override עובד ציבורי ממיר (מחרוזת מ) {String [] data = from.split (","); להחזיר עובד חדש (Long.parseLong (נתונים [0]), Double.parseDouble (נתונים [1])); }}

עדיין לא סיימנו. עלינו לספר לאביב על הממיר החדש על ידי הוספת ה- ממיר StringToEmployee אל ה פורמט רישום. ניתן לעשות זאת על ידי יישום ה- WebMvcConfigurer ועוקף addFormatters () שיטה:

@Configuration בכיתה הציבורית WebConfig מיישם את WebMvcConfigurer {@Override public void addFormatters (FormatterRegistry registry) {registry.addConverter (StringToEmployeeConverter חדש ()); }}

וזה הכל. החדש שלנו מֵמִיר זמין כעת ל ConversionService ואנחנו יכולים להשתמש בו באותו אופן כמו כל מובנה אחר מֵמִיר:

@ מבחן ציבורי בטל כאשר ConvertStringToEmployee_thenSuccess () {עובד שכיר = conversionService .convert ("1,50000.00", שכיר עובד); עובד בפועל עובד = עובד חדש (1, 50000.00); assertThat (conversionService.convert ("1,50000.00", שכיר.קלאס)) .isEqualToComparingFieldByField (עובד אמיתי); }

3.1. המרה מרומזת

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

@RestController מחלקה ציבורית StringToEmployeeConverterController {@GetMapping ("/ מחרוזת לעובד") תגובת ציבור תגובה StringToEmployee (@RequestParam ("עובד") עובד שכיר) {return ResponseEntity.ok (עובד); }}

זוהי דרך טבעית יותר להשתמש ב- מֵמִירס. בואו נוסיף מבחן כדי לראות את זה בפעולה:

@Test ציבורי בטל בטל getStringToEmployeeTest () זורק חריג {mockMvc.perform (get ("/ string-to-עובד? עובד = 1,2000")). ועשה (הדפס ()) .andExpect (jsonPath ("$. Id", הוא (1)) .andExpect (jsonPath ("$. משכורת", הוא (2000.0)))}

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

{"id": 1, "משכורת": 2000.0}

4. יצירת א ConverterFactory

אפשר גם ליצור ConverterFactory זה יוצר מֵמִירs לפי דרישה. זה מועיל במיוחד ביצירה מֵמִירs עבור Enums.

בואו נסתכל על Enum ממש פשוט:

מצבי האומה הציבוריים {ALPHA, BETA; }

לאחר מכן, בואו ליצור a StringToEnumConverterFactory שיכול ליצור מֵמִירs להמרת א חוּט לכל Enum:

מחלקה ציבורית @Component StringToEnumConverterFactory מיישם ConverterFactory {מחלקה סטטית פרטית StringToEnumConverter מיישם ממיר {Class class enumType; ציבור StringToEnumConverter (Class enumType) {this.enumType = enumType; } המרת T ציבורית (מקור מחרוזת) {return (T) Enum.valueOf (this.enumType, source.trim ()); }} @Override ממיר ציבורי getConverter (Class targetType) {להחזיר StringToEnumConverter חדש (targetType); }}

כפי שאנו רואים, מחלקת המפעל משתמשת באופן פנימי ביישום של מֵמִיר מִמְשָׁק.

דבר אחד שיש לציין כאן הוא שלמרות שנשתמש ב- שלנו מצבי Enum כדי להדגים את השימוש, לא הזכרנו את Enum בכל מקום ב StringToEnumConverterFactory. מחלקת המפעל שלנו היא גנרית מספיק כדי לייצר את מֵמִירs על פי דרישה לכל Enum סוּג.

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

@ Override public void addFormatters (FormatterRegistry registry) {registry.addConverter (חדש StringToEmployeeConverter ()); registry.addConverterFactory (חדש StringToEnumConverterFactory ()); }

עכשיו ה ConversionService מוכן להתגייר חוּטs ל Enums:

@ מבחן ציבורי בטל כאשר ConvertStringToEnum_thenSuccess () {assertThat (conversionService.convert ("ALPHA", Modes.class)) .isEqualTo (Modes.ALPHA); }

5. יצירת א GenericConverter

א GenericConverter מספק לנו יותר גמישות ליצור מֵמִיר לשימוש כללי יותר במחיר של אובדן בטיחות מסוג כלשהו.

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

השלב הראשון הוא לספר לאביב אילו סוגי המרות נתמכים. אנו עושים זאת על ידי יצירת a מַעֲרֶכֶת שֶׁל זוג להמרה:

מחלקה ציבורית GenericBigDecimalConverter מיישם את GenericConverter {@Override public Set getConvertibleTypes () {ConvertiblePair [] pair = new ConvertiblePair [] {new ConvertiblePair (Number.class, BigDecimal.class), ConvertiblePair new (String.class, BigDecimal.class)}; החזר ImmutableSet.copyOf (זוגות); }}

השלב הבא הוא לעקוף את להמיר() שיטה באותה כיתה:

@ המרה אובייקט ציבורי להמיר (מקור אובייקט, TypeDescriptor sourceType, TypeDescriptor targetType) {if (sourceType.getType () == BigDecimal.class) {מקור החזרה; } if (sourceType.getType () == String.class) {String number = (String) source; להחזיר BigDecimal חדש (מספר); } אחר {מספר מספר = (מספר) מקור; המרה של BigDecimal = BigDecimal חדש (number.doubleValue ()); החזר convert.setScale (2, BigDecimal.ROUND_HALF_EVEN); }}

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

כפי שאולי כבר ניחשתם, השלב הבא הוא לרשום זאת מֵמִיר:

@Override public void addFormatters (Registry FormatterRegistry) {registry.addConverter (StringToEmployeeConverter חדש) (); registry.addConverterFactory (StringToEnumConverterFactory חדש ()); registry.addConverter (GenericBigDecimalConverter חדש ()); }

באמצעות זה מֵמִיר דומה לשאר הדוגמאות שכבר ראינו:

@Test ציבורי בטל כאשרConvertingToBigDecimalUsingGenericConverter_thenSuccess () {assertThat (conversionService .convert (Integer.valueOf (11), BigDecimal.class)) .isEqualTo (BigDecimal.valueOf (11.00) .setScalal. assertThat (conversionService .convert (Double.valueOf (25.23), BigDecimal.class)) .isEqualByComparingTo (BigDecimal.valueOf (Double.valueOf (25.23))); assertThat (conversionService.convert ("2.32", BigDecimal.class)) .isEqualTo (BigDecimal.valueOf (2.32)); }

6. מסקנה

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

כמו תמיד, ניתן למצוא את קוד המקור המלא של מאמר זה ב- GitHub.