A Spring Framework talán egyik legnagyobb előnye, hogy bizonyos gyakran használt funkcionalitásra egy frappáns megoldást biztosít, és ezt az egész keretrendszeren belül konzekvensen alkalmazza. Az egyik ilyen funkcionalitás a Spring Converter SPI.
Nagyon gyakran van szükség arra, hogy szöveges értékből egy objektumot gyártsunk. Szöveg szerepelhet sok helyen. Szerepelhet a Spring xml konfigurációjában, Spring Expression Language-ben (SpEL), valamint a HTTP protokoll is alapvetően szöveges. Azonban láthatjuk, hogy akár az xml konfigurációban alkalmazhatunk más, long, double, stb. típusú értékeket, valamint a Spring controllerekben is definiálhatunk ilyen típussal url paramétereket, path változókat, header bejegyzéseket, stb. A Spring a konverziót automatikusan elvégzi. De mi van akkor, ha mi nem ilyen gyakori típusokká akarjuk konvertálni a szövegeinket, hanem pl. egy saját osztály egy példányává.
A Spring nagyon könnyen bővíthető, és ezen konverziós mechanizmus mögött a Converter SPI áll, mely megengedi, hogy saját konvertereket implementáljunk. Sőt, ezeket a konvertereket igazán sok helyen használhatjuk is.
Ezen használati helyeket tekinti át ez a poszt, melyhez példaprogram is készült, és elérhető a GitHubon.
Példának vegyünk egy gázóra (GasHour) osztályt. Ennek a különlegessége, hogy 6:00 az első órája, és a nyári és téli időszámítás miatt létezik egy 23, és egy 25 órás gáznap is. Ennek szöveges reprezentációja pl. 2015-01-01 9., ami a 2015. január 1-ei gáznap 9. gázóráját jelenti.
Ez az osztály legyen valami hasonló:
Az ehhez tartozó konverter nagyon egyszerű:
A konverter használatához definiáljunk egy ConversionService objektumot, és regisztráljuk a konvertert.
Vagy akár Java kódból:
Ezután az xml konfigurációban szereplő értékeket is fel tudja oldani.
Ha a beanünk implementációja a következő:
A konvertereket egyszerűen használhatjuk a ConversionService példányon keresztül is, nem kell a konkrét konverterre hivatkoznunk.
Listákra nem kell külön konvertert írnunk, ugyanis képes a Spring kezelni, ha a listák elemeire van konverter. Azonban a Java furcsa generikus kezelése miatt ez nem triviális.
Nagyon szépen használható SpEL-ben is, az előbb említett FooService osztály esetén:
De természetesen programozottan is:
Amennyiben Spring MVC-ben is használni szeretnénk, a konvertereket regisztrálhatjuk a
WebMvcConfigurerAdapter-ben is.
Ekkor controllerben is működik az automatikus konverzió:
Még egy érdekesség, a Spring Data JPA is tudja használni, amikor egy lekérdezés eredményét, ami entitások listája, dto listákká akarjuk konvertálni. Ez akkor működik, ha a lapozást használjuk, és ehhez a visszatérési érték Page típus. Ebben a map() metódust kell hívni, a következőképpen.