Prilagođeni povezivač podataka u proljetnom MVC-u

1. Pregled

Ovaj će članak pokazati kako možemo koristiti Springov mehanizam vezivanja podataka kako bismo naš kôd učinili jasnijim i čitljivijim primjenom automatskih primitiva na pretvorbu objekata.

Prema zadanim postavkama Spring zna pretvoriti samo jednostavne tipove. Drugim riječima, nakon što podatke dostavimo kontroloru Int, Niz ili Booleova vrsta podataka, automatski će se vezati za odgovarajuće Java tipove.

Ali u stvarnim projektima to neće biti dovoljno kao možda bismo trebali povezati složenije vrste objekata.

2. Vezivanje pojedinačnih objekata za traženje parametara

Počnimo s jednostavnim i prvo povežemo jednostavan tip; morat ćemo osigurati prilagođenu implementaciju Konverter sučelje gdje S je tip iz kojeg se pretvaramo i T je tip u koji pretvaramo:

@Component javna klasa StringToLocalDateTimeConverter implementira Converter {@Override public LocalDateTime convert (String source) {return LocalDateTime.parse (source, DateTimeFormatter.ISO_LOCAL_DATE_TIME); }}

Sada u našem kontroleru možemo koristiti sljedeću sintaksu:

@GetMapping ("/ findbydate / {date}") public GenericEntity findByDate (@PathVariable ("date") LocalDateTime date) {return ...; }

2.1. Korištenje enuma kao parametra zahtjeva

Dalje, vidjet ćemo kako koristiti enum kao Parametar zahtjeva.

Evo, imamo jednostavan nabrajanjeNačini rada:

načini javnog popisa {ALPHA, BETA; }

Izgradit ćemo a Niz do enum pretvarač kako slijedi:

javna klasa StringToEnumConverter implementira Converter {@Override javni modus convert (String from) {return Modes.valueOf (from); }}

Zatim, moramo registrirati svoj Konverter:

@Configuration javna klasa WebConfig implementira WebMvcConfigurer {@Override public void addFormatters (Registar FormatterRegistry) {registry.addConverter (novi StringToEnumConverter ()); }}

Sada možemo koristiti naše Enum kao Parametar zahtjeva:

@GetMapping javni ResponseEntity getStringToMode (@RequestParam ("mode") način rada) {// ...}

Ili kao Promjenjiva putanja:

@GetMapping ("/ entity / findbymode / {mode}") javni GenericEntity findByEnum (@PathVariable ("mode") Načini rada) {// ...}

3. Povezivanje hijerarhije objekata

Ponekad moramo pretvoriti cijelo stablo hijerarhije objekata i ima smisla imati centraliziranije vezivanje, a ne skup pojedinačnih pretvarača.

U ovom primjeru imamo AbstractEntity naša osnovna klasa:

javni sažetak klase AbstractEntity {long id; javni AbstractEntity (dugi id) {this.id = id; }}

I podrazredi Foo i Bar:

javna klasa Foo proširuje AbstractEntity {naziv privatnog niza; // standardni konstruktori, getteri, postavljači}
traka javne klase proširuje AbstractEntity {private int vrijednost; // standardni konstruktori, getteri, postavljači}

U ovom slučaju, možemo provesti ConverterFactory gdje će S biti tip iz kojeg pretvaramo, a R osnovni tip definiranje raspona klasa u koje možemo pretvoriti:

javna klasa StringToAbstractEntityConverterFactory implementira ConverterFactory {@Override javni pretvarač getConverter (Class targetClass) {return new StringToAbstractEntityConverter (targetClass); } privatna statička klasa StringToAbstractEntityConverter implementira Converter {private class targetClass; javni StringToAbstractEntityConverter (klasa targetClass) {this.targetClass = targetClass; } @Override public T convert (izvor niza) {long id = Long.parseLong (izvor); if (this.targetClass == Foo.class) {return (T) new Foo (id); } else if (this.targetClass == Bar.class) {return (T) new Bar (id); } else {vratiti nulu; }}}}

Kao što vidimo, jedina metoda koja se mora primijeniti je getConverter () koji vraća pretvarač za potrebnu vrstu. Potom se postupak pretvorbe delegira ovom pretvaraču.

Zatim, moramo registrirati svoj ConverterFactory:

@Configuration javna klasa WebConfig implementira WebMvcConfigurer {@Override public void addFormatters (Registar FormatterRegistry) {registry.addConverterFactory (new StringToAbstractEntityConverterFactory ()); }}

Napokon, možemo ga koristiti kako želimo u našem kontroleru:

@RestController @RequestMapping ("/ string-to-abstract") javna klasa AbstractEntityController {@GetMapping ("/ foo / {foo}") javni ResponseEntity getStringToFoo (@PathVariable Foo foo) {return ResponseEntity.ok (foo); } @GetMapping ("/ bar / {bar}") javni ResponseEntity getStringToBar (@PathVariable Bar bar) {return ResponseEntity.ok (bar); }}

4. Vezivanje objekata domene

Postoje slučajevi kada podatke želimo povezati s objektima, ali oni dolaze ili na neizravan način (na primjer iz Sjednica, Zaglavlje ili Kolačić varijable) ili čak pohranjene u izvoru podataka. U tim slučajevima moramo koristiti drugačije rješenje.

4.1. Razrješivač prilagođenih argumenata

Prije svega, definirat ćemo napomenu za takve parametre:

@Retention (RetentionPolicy.RUNTIME) @Target (ElementType.PARAMETER) public @interface Version {}

Zatim ćemo primijeniti običaj HandlerMethodArgumentResolver:

javna klasa HeaderVersionArgumentResolver implementira HandlerMethodArgumentResolver {@Override public boolean supportsParameter (MethodParameter methodParameter) {return methodParameter.getParameterAnnotation (Version.class)! = null; } @Override javni objekt razriješiArgument (MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) baca izuzetak {HttpServquestRequestRebRegetRequestRebReget.ReRequest. povrat zahtjeva.getHeader ("Verzija"); }}

Posljednja stvar je davanje obavijesti Proljeću gdje ih treba potražiti:

@Configuration javna klasa WebConfig implementira WebMvcConfigurer {// ... @Override public void addArgumentResolvers (List argumentResolvers) {argumentResolvers.add (new HeaderVersionArgumentResolver ()); }}

To je to. Sada ga možemo koristiti u kontroleru:

@GetMapping ("/ entity / {id}") javni ResponseEntity findByVersion (@PathVariable Long id, verzija verzije @Version) {return ...; }

Kao što vidimo, HandlerMethodArgumentResolver‘S RiješiArgument () metoda vraća an Objekt. Drugim riječima, mogli bismo vratiti bilo koji predmet, ne samo Niz.

5. Zaključak

Kao rezultat toga, riješili smo se mnogih rutinskih pretvorbi i pustili da Proljeće učini većinu stvari umjesto nas. Na kraju, zaključimo:

  • Trebali bismo koristiti pojedinačni jednostavni tip za objektne pretvorbe Konverter provedba
  • Možemo pokušati za enkapsulaciju logike pretvorbe za niz objekata ConverterFactory provedba
  • Ako bilo koji podatak dolazi neizravno ili je potrebno primijeniti dodatnu logiku za dohvaćanje povezanih podataka, bolje ga je koristiti HandlerMethodArgumentResolver

Kao i obično, sve primjere uvijek možete pronaći u našem GitHub spremištu.


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