Spring Custom Property Editor

Spring-Editor für benutzerdefinierte Eigenschaften

1. Einführung

Einfach ausgedrückt, verwendet Spring in hohem Maße Eigenschaftseditoren, um die Konvertierung zwischen den Werten vonStringund den benutzerdefinierten Typen vonObjectzu verwalten. Dies basiert aufJava Beans PropertyEditor.

In diesem Tutorial werden zwei verschiedene Anwendungsfälle zur Demonstration vonautomatic property editor binding and custom property editor binding behandelt.

2. Automatische Bindung des Eigenschafteneditors

Die Standardinfrastruktur vonJavaBeanserkennt automatisch die Klassen vonPropertyEditor, wenn sie sich im selben Paket befinden wie die Klasse, die sie verarbeiten. Außerdem müssen diese denselben Namen wie diese Klasse sowie das SuffixEditorhaben.

Wenn wir beispielsweise eine ModellklasseCreditCarderstellen, sollten wir die EditorklasseCreditCardEditor. benennen

Lassen Sie uns nuna practical property binding example. durchgehen

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

Erstellen wir zunächst die ModellklasseCreditCard, in der die FelderrawCardNumber, Bankidentifikationsnummer (die ersten 6 Ziffern), Kontonummer (Ziffern von 7 bis 15) und Prüfcode (letzte Ziffer) definiert sind:

public class CreditCard {

    private String rawCardNumber;
    private Integer bankIdNo;
    private Integer accountNo;
    private Integer checkCode;

    // standard constructor, getters, setters
}

Als Nächstes erstellen wir dieCreditCardEditor-Klasse. Dies implementiert die Geschäftslogik zum Konvertieren der alsString angegebenen Kreditkartennummer in einCreditCard-Objekt.

Die Eigenschaftseditorklasse solltePropertyEditorSupport erweitern und die MethodengetAsText() undsetAsText() 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 MethodegetAsText() wird aufgerufen, wenn ein Objekt inString, serialisiert wird, währendsetAsText() verwendet wird, umString in ein anderes Objekt zu konvertieren.

Da sich diese Klassen im selben Paket befinden, müssen wir nichts anderes tun, um dieEditor für den TypCreditCard zu binden.

Wir können dies jetzt als Ressource in einer REST-API verfügbar machen. Die Operation verwendet eine Kreditkartennummer als Anforderungspfadvariable, und Spring bindet diesen Textwert alsCrediCard-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/property-editor/credit-card/1234-1234-1111-0019,erhalten wir beispielsweise die Antwort:

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

3. Benutzerdefinierte Eigenschaftseditorbindung

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 Bindungsszenario für den benutzerdefinierten Eigenschafteneditor wird der Wert vonStringin der URL als Pfadvariable übergeben, und dieser Wert wird als Objekt vonExoticTypegebunden, das den Wert lediglich als Attribut beibehält.

Erstellen Sie wie in Abschnitt 2 zunächst eine ModellklasseExoticType:

public class ExoticType {
    private String name;

    // standard constructor, getters, setters
}

Und unser benutzerdefinierter Eigenschaftseditor KlasseCustomExoticTypeEditor, der wiederumPropertyEditorSupport:  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 Eigenschafteneditor nicht erkennen kann, werdenwe’ll need a method annotated with @InitBinder in our Controller class that registers the editor:

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

Dann können wir die Benutzereingabe an das Objekt vonExoticTypebinden:

@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/property-editor/exotic-type/passion-fruit, erhalten Sie die Beispielantwort:

{
    "name": "PASSION-FRUIT"
}

4. Fazit

In diesem kurzen Artikel haben wir gesehen, wie wir mithilfe der automatischen und benutzerdefinierten Eigenschaftseditor-Bindung von Menschen lesbareString-Werte in komplexe Java-Typen konvertieren können.

Der vollständige Quellcode unserer Beispiele hier ist wie immerover on GitHub.