Editor delle proprietà personalizzate di Spring

1. Introduzione

In poche parole, Spring utilizza pesantemente editor di proprietà per la gestione della conversione tra valori String e tipi di oggetti personalizzati ; si basa su Java Beans PropertyEditor.

In questo tutorial, esamineremo due diversi casi d'uso per dimostrare l'associazione automatica dell'editor di proprietà e l'associazione dell'editor di proprietà personalizzato .

2. Binding automatico dell'editor delle proprietà

L' infrastruttura JavaBeans standard rileverà automaticamente le classi PropertyEditor se si trovano nello stesso pacchetto della classe che gestiscono. Inoltre, questi devono avere lo stesso nome di quella classe più il suffisso Editor .

Ad esempio, se creiamo una classe del modello CreditCard , dovremmo denominare la classe dell'editor CreditCardEditor.

Esaminiamo ora un esempio pratico di associazione di proprietà.

Nel nostro scenario, passeremo un numero di carta di credito come variabile di percorso nell'URL della richiesta e legheremo quel valore come oggetto CreditCard .

Creiamo prima la classe del modello CreditCard definendo i campi rawCardNumber, Bank Identification Number (le prime 6 cifre), Account Number (cifre da 7 a 15) e Check Code (ultima cifra):

public class CreditCard { private String rawCardNumber; private Integer bankIdNo; private Integer accountNo; private Integer checkCode; // standard constructor, getters, setters }

Successivamente, creeremo la classe CreditCardEditor . Ciò implementa la logica aziendale per convertire il numero di carta di credito fornito come stringa in un oggetto CreditCard .

La classe dell'editor di proprietà dovrebbe estendere PropertyEditorSupport e implementare i metodi getAsText () e setAsText () :

public class CreditCardEditor extends PropertyEditorSupport { @Override public String getAsText() { CreditCard creditCard = (CreditCard) getValue(); return creditCard == null ? "" : creditCard.getRawCardNumber(); } @Override public void setAsText(String text) throws IllegalArgumentException { if (StringUtils.isEmpty(text)) { setValue(null); } else { CreditCard creditCard = new CreditCard(); creditCard.setRawCardNumber(text); String cardNo = text.replaceAll("-", ""); if (cardNo.length() != 16) throw new IllegalArgumentException( "Credit card format should be xxxx-xxxx-xxxx-xxxx"); try { creditCard.setBankIdNo( Integer.valueOf(cardNo.substring(0, 6)) ); creditCard.setAccountNo( Integer.valueOf( cardNo.substring(6, cardNo.length() - 1)) ); creditCard.setCheckCode( Integer.valueOf( cardNo.substring(cardNo.length() - 1)) ); } catch (NumberFormatException nfe) { throw new IllegalArgumentException(nfe); } setValue(creditCard); } } }

Il metodo getAsText () viene chiamato durante la serializzazione di un oggetto in una String, mentre setAsText () viene utilizzata per convertire una String in un altro oggetto.

Poiché queste classi si trovano nello stesso pacchetto, non è necessario fare altro per associare l' Editor per il tipo CreditCard .

Ora possiamo esporlo come una risorsa in un'API REST; l'operazione accetta un numero di carta di credito come variabile del percorso della richiesta e Spring legherà quel valore di testo come un oggetto CrediCard e lo passerà come argomento del metodo:

@GetMapping(value = "/credit-card/{card-no}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) public CreditCard parseCreditCardNumber( @PathVariable("card-no") CreditCard creditCard) { return creditCard; }

Ad esempio, per un URL di richiesta di esempio / property-editor / credit-card / 1234-1234-1111-0019, otterremo la risposta:

{ "rawCardNumber": "1234-1234-1111-0011", "bankIdNo": 123412, "accountNo": 341111001, "checkCode": 9 }

3. Binding dell'editor delle proprietà personalizzate

Se non abbiamo la classe di tipo richiesta e la classe dell'editor di proprietà nello stesso pacchetto o con le convenzioni di denominazione previste, dovremo definire un'associazione personalizzata tra il tipo richiesto e l'editor di proprietà.

Nel nostro scenario di associazione dell'editor di proprietà personalizzato, un valore String verrà passato nell'URL come variabile di percorso e assoceremo quel valore come un oggetto ExoticType che si limita a mantenere il valore come un attributo.

Come nella sezione 2, creiamo prima una classe modello ExoticType:

public class ExoticType { private String name; // standard constructor, getters, setters }

E la nostra classe di editor di proprietà personalizzate CustomExoticTypeEditor che estende nuovamente PropertyEditorSupport :

public class CustomExoticTypeEditor extends PropertyEditorSupport { @Override public String getAsText() { ExoticType exoticType = (ExoticType) getValue(); return exoticType == null ? "" : exoticType.getName(); } @Override public void setAsText(String text) throws IllegalArgumentException { ExoticType exoticType = new ExoticType(); exoticType.setName(text.toUpperCase()); setValue(exoticType); } }

Poiché Spring non è in grado di rilevare l'editor delle proprietà, avremo bisogno di un metodo annotato con @InitBinder nella nostra classe Controller che registri l'editor:

@InitBinder public void initBinder(WebDataBinder binder) { binder.registerCustomEditor(ExoticType.class, new CustomExoticTypeEditor()); }

Quindi possiamo associare l'input dell'utente all'oggetto ExoticType :

@GetMapping( value = "/exotic-type/{value}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) public ExoticType parseExoticType( @PathVariable("value") ExoticType exoticType) { return exoticType; }

Per l'URL di richiesta di esempio / editor di proprietà / tipo esotico / frutto della passione, otterremo la risposta di esempio:

{ "name": "PASSION-FRUIT" }

4. Conclusione

In questo rapido articolo, abbiamo visto come è possibile utilizzare l'associazione automatica e personalizzata dell'editor di proprietà per convertire valori String leggibili dall'uomo in tipi Java complessi.

Il codice sorgente completo dei nostri esempi qui è, come sempre, su GitHub.