Spring Custom Property Editor

1. Einleitung

Einfach ausgedrückt, verwendet Spring in hohem Maße Eigenschaftseditoren, um die Konvertierung zwischen Zeichenfolgenwerten und benutzerdefinierten Objekttypen zu verwalten . Dies basiert auf Java Beans PropertyEditor.

In diesem Tutorial werden zwei verschiedene Anwendungsfälle behandelt, um die automatische Bindung des Eigenschafteneditors und die Bindung des benutzerdefinierten Eigenschafteneditors zu demonstrieren .

2. Automatische Bindung des Eigenschafteneditors

Die Standard- JavaBeans- Infrastruktur erkennt PropertyEditor- Klassen automatisch, wenn sie sich im selben Paket wie die Klasse befinden, die sie verarbeiten. Außerdem müssen diese denselben Namen wie diese Klasse sowie das Editor- Suffix haben.

Wenn wir beispielsweise eine CreditCard- Modellklasse erstellen , sollten wir die Editorklasse CreditCardEditor benennen.

Lassen Sie uns nun ein praktisches Beispiel für die Bindung von Eigenschaften durchgehen .

In unserem Szenario übergeben wir eine Kreditkartennummer als Pfadvariable in der Anforderungs-URL und binden diesen Wert als CreditCard- Objekt.

Erstellen wir zunächst die CreditCard- Modellklasse, in der die Felder rawCardNumber, Bankidentifikationsnummer (die ersten 6 Ziffern), Kontonummer (Ziffern von 7 bis 15) und Scheckcode (letzte Ziffer) definiert werden:

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

Als Nächstes erstellen wir die CreditCardEditor- Klasse. Dies implementiert die Geschäftslogik zum Konvertieren der als String angegebenen Kreditkartennummer in ein CreditCard- Objekt.

Die Eigenschaftseditorklasse sollte PropertyEditorSupport erweitern und die Methoden getAsText () und setAsText () implementieren :

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); } } }

Die Methode getAsText () wird aufgerufen, wenn ein Objekt in einen String serialisiert wird , während setAsText () verwendet wird, um einen String in ein anderes Objekt zu konvertieren .

Da sich diese Klassen im selben Paket befinden, müssen wir nichts weiter tun, um den Editor für den Typ CreditCard zu binden .

Wir können dies jetzt als Ressource in einer REST-API verfügbar machen. Bei der Operation wird eine Kreditkartennummer als Anforderungspfadvariable verwendet, und Spring bindet diesen Textwert als CrediCard- Objekt und übergibt ihn als Methodenargument:

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

Für eine Beispielanforderungs-URL / Eigenschaftseditor / Kreditkarte / 1234-1234-1111-0019 erhalten wir beispielsweise die Antwort:

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

3. Bindung des benutzerdefinierten Eigenschafteneditors

Wenn wir nicht die erforderliche Typklasse und die Eigenschaftseditorklasse im selben Paket oder mit den erwarteten Namenskonventionen haben, müssen wir eine benutzerdefinierte Bindung zwischen dem erforderlichen Typ und dem Eigenschaftseditor definieren.

In unserem benutzerdefinierten Eigenschaftseditor Bindungsszenario, ein String wird Wert in der URL als Pfad - Variable übergeben werden, und wir werden diesen Wert als binden ExoticType Objekt , das lediglich den Wert als Attribut hält.

Erstellen Sie wie in Abschnitt 2 zunächst eine Modellklasse ExoticType:

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

Und unsere benutzerdefinierte Eigenschaftseditor-Klasse CustomExoticTypeEditor, die PropertyEditorSupport erneut erweitert :

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); } }

Da Spring den Eigenschaftseditor nicht erkennen kann, benötigen wir eine mit @InitBinder kommentierte Methode in unserer Controller- Klasse, die den Editor registriert:

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

Dann können wir die Benutzereingaben an das ExoticType- Objekt binden :

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

Für die Beispielanforderungs-URL / den Eigenschaftseditor / den exotischen Typ / die Passionsfrucht erhalten wir die Beispielantwort:

{ "name": "PASSION-FRUIT" }

4. Fazit

In diesem kurzen Artikel haben wir gesehen, wie wir mithilfe der automatischen und benutzerdefinierten Bindung des Eigenschaftseditors lesbare Zeichenfolgenwerte in komplexe Java-Typen konvertieren können.

Der vollständige Quellcode unserer Beispiele hier ist wie immer auf GitHub verfügbar.