Vejledning til forårstypekonvertering

1. Introduktion

I denne artikel vil vi se på Spring's type konverteringer.

Spring giver out-of-the-box forskellige konvertere til indbyggede typer; det betyder at konvertere til / fra grundlæggende typer som String, Integer, Boolean og en række andre typer.

Bortset fra dette giver Spring også en solid type konverterings-SPI til udvikling af vores tilpassede konvertere.

2. Indbygget Konverters

Vi starter med de tilgængelige konvertere uden for kassen i foråret; lad os se på Snor til Heltal konvertering:

@Autowired ConversionService conversionService; @Test offentlig ugyldig nårConvertStringToIntegerUsingDefaultConverter_thenSuccess () {assertThat (conversionService.convert ("25", Integer.class)). Er EqualTo (25); }

Det eneste, vi skal gøre her, er at autoledning af ConversionService leveret af Spring og ring til konvertere() metode. Det første argument er den værdi, som vi vil konvertere, og det andet argument er den måltype, som vi vil konvertere til.

Udover dette Snor til Heltal for eksempel er der mange forskellige andre kombinationer tilgængelige for os.

3. Oprettelse af en brugerdefineret Konverter

Lad os se på et eksempel på konvertering af en Snor repræsentation af en Medarbejder til en Medarbejder eksempel.

Her er den Medarbejder klasse:

offentlig klassemedarbejder {privat lang id; privat dobbelt løn // standard konstruktører, getters, setters}

Det Snor vil være et komma-adskilt par, der repræsenterer id og løn. For eksempel “1.50000.00”.

For at skabe vores brugerdefinerede Konverter, er vi nødt til at implementere Konverter interface og implementere konvertere() metode:

offentlig klasse StringToEmployeeConverter implementerer Converter {@Override public Employee convert (String from) {String [] data = from.split (","); returner ny medarbejder (Long.parseLong (data [0]), Double.parseDouble (data [1])); }}

Vi er ikke færdige endnu. Vi er også nødt til at fortælle Spring om denne nye konverter ved at tilføje StringToEmployeeConverter til FormatterRegistry. Dette kan gøres ved at implementere WebMvcConfigurer og overordnet addFormatters () metode:

@Configuration public class WebConfig implementerer WebMvcConfigurer {@Override public void addFormatters (FormatterRegistry registry) {registry.addConverter (new StringToEmployeeConverter ()); }}

Og det er det. Vores nye Konverter er nu tilgængelig for ConversionService og vi kan bruge det på samme måde som enhver anden indbygget Konverter:

@Test offentlig ugyldig nårConvertStringToEmployee_thenSuccess () {Medarbejdermedarbejder = conversionService .convert ("1.50000,00", Employee.class); Medarbejder faktisk Medarbejder = ny medarbejder (1, 50000,00); assertThat (conversionService.convert ("1,50000,00", Employee.class)) .isEqualToComparingFieldByField (actualEmployee); }

3.1. Implicit konvertering

Ud over disse eksplicitte konvertering ved hjælp af ConversionService, Spring er også i stand til implicit at konvertere værdier lige ind Controller metoder for alle registrerede omformere:

@RestController offentlig klasse StringToEmployeeConverterController {@GetMapping ("/ streng-til-medarbejder") offentlig ResponseEntity getStringToEmployee (@RequestParam ("medarbejder") Medarbejderansat) {return ResponseEntity.ok (medarbejder); }}

Dette er en mere naturlig måde at bruge Konverters. Lad os tilføje en test for at se den i aktion:

@Test offentlig ugyldighed getStringToEmployeeTest () kaster undtagelse {mockMvc.perform (get ("/ string-to-employee? Medarbejder = 1.2000")) .og gør (udskriv ()). Og forvent (jsonPath ("$. Id", er (1)) .andExpect (jsonPath ("$. løn", er (2000.0)))}

Som du kan se, vil testen udskrive alle detaljerne i anmodningen samt svaret. Her er Medarbejder objekt i JSON-format, der returneres som en del af svaret:

{"id": 1, "løn": 2000.0}

4. Oprettelse af en ConverterFabrik

Det er også muligt at oprette en ConverterFabrik der skaber Konverters på forespørgsel. Dette er især nyttigt ved oprettelse Konverters for Enums.

Lad os se på en virkelig enkel Enum:

offentlige enumtilstande {ALPHA, BETA; }

Lad os derefter oprette en StringToEnumConverterFactory der kan generere Konverters til konvertering af a Snor til enhver Enum:

@Komponent offentlig klasse StringToEnumConverterFactory implementerer ConverterFactory {privat statisk klasse StringToEnumConverter implementerer Converter {privat klasse enumType; public StringToEnumConverter (Class enumType) {this.enumType = enumType; } offentlig T-konvertering (String source) {return (T) Enum.valueOf (this.enumType, source.trim ()); }} @ Override public Converter getConverter (Class targetType) {returner ny StringToEnumConverter (targetType); }}

Som vi kan se, bruger fabriksklassen internt en implementering af Konverter interface.

En ting at bemærke her er, at selvom vi bruger vores Tilstande Enum For at demonstrere brugen har vi ikke nævnt Enum hvor som helst i StringToEnumConverterFactory. Vores fabriksklasse er generisk nok til at generere Konverters efter behov for enhver Enum type.

Det næste trin er at registrere denne fabriksklasse, når vi registrerede vores Konverter i det foregående eksempel:

@Override public void addFormatters (FormatterRegistry registry) {registry.addConverter (new StringToEmployeeConverter ()); registry.addConverterFactory (ny StringToEnumConverterFactory ()); }

Nu er det ConversionService er klar til at konvertere Snors til Enums:

@Test offentligt ugyldigt nårConvertStringToEnum_thenSuccess () {assertThat (conversionService.convert ("ALPHA", Modes.class)) .isEqualTo (Modes.ALPHA); }

5. Oprettelse af en GenericConverter

EN GenericConverter giver os mere fleksibilitet til at skabe en Konverter til en mere generisk brug på bekostning af at miste en slags sikkerhed.

Lad os overveje et eksempel på konvertering af en Heltal, Dobbelt, eller a Snor til en BigDecimal værdi. Vi behøver ikke at skrive tre Konverters for dette. En simpel GenericConverter kunne tjene formålet.

Det første trin er at fortælle Spring, hvilke typer konvertering der understøttes. Vi gør dette ved at oprette en Sæt af ConvertiblePair:

offentlig klasse GenericBigDecimalConverter implementerer GenericConverter {@Override public Set getConvertibleTypes () {ConvertiblePair [] pairs = new ConvertiblePair [] {new ConvertiblePair (Number.class, BigDecimal.class), new ConvertiblePair (String.class, BigDecimal.class)}; returner ImmutableSet.copyOf (par); }}

Det næste trin er at tilsidesætte konvertere() metode i samme klasse:

@ Override offentlig Objektkonvertering (Objektkilde, TypeDescriptor sourceType, TypeDescriptor targetType) {if (sourceType.getType () == BigDecimal.class) {return source; } hvis (sourceType.getType () == String.class) {String number = (String) source; returner nyt BigDecimal (tal); } andet {Number number = (Number) kilde; BigDecimal konverteret = ny BigDecimal (number.doubleValue ()); returnere convert.setScale (2, BigDecimal.ROUND_HALF_EVEN); }}

Det konvertere() metoden er så enkel som den kan være. Men den TypeDescriptor giver os stor fleksibilitet med hensyn til at få detaljerne om kilden og måletypen.

Som du måske allerede har gættet, er det næste trin at registrere dette Konverter:

@Override public void addFormatters (FormatterRegistry registry) {registry.addConverter (new StringToEmployeeConverter ()); registry.addConverterFactory (ny StringToEnumConverterFactory ()); registry.addConverter (ny GenericBigDecimalConverter ()); }

Brug af dette Konverter svarer til de andre eksempler, som vi allerede har set:

@Test offentlig ugyldig nårConvertingToBigDecimalUsingGenericConverter_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. Konklusion

I denne vejledning har vi set, hvordan man bruger og udvider Spring's type konverteringssystem med forskellige eksempler.

Som altid kan den fulde kildekode til denne artikel findes på GitHub.


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