Éditeur de propriétés personnalisées Spring

1. Introduction

En termes simples, Spring utilise fortement les éditeurs de propriétés pour gérer la conversion entre les valeurs String et les types d' objets personnalisés ; ceci est basé sur PropertyEditor Java Beans.

Dans ce didacticiel, nous allons passer en revue deux cas d'utilisation différents pour démontrer la liaison automatique de l'éditeur de propriétés et la liaison de l'éditeur de propriétés personnalisées .

2. Liaison automatique de l'éditeur de propriétés

L' infrastructure JavaBeans standard découvrira automatiquement les classes PropertyEditor si elles sont dans le même package que la classe qu'elles gèrent. En outre, ceux-ci doivent avoir le même nom que cette classe plus le suffixe Editor .

Par exemple, si nous créons une classe de modèle CreditCard , nous devons nommer la classe d'éditeur CreditCardEditor.

Passons maintenant en revue un exemple pratique de liaison de propriété.

Dans notre scénario, nous transmettrons un numéro de carte de crédit comme variable de chemin dans l'URL de la demande, et nous lierons cette valeur en tant qu'objet CreditCard .

Commençons par créer la classe de modèle CreditCard définissant les champs rawCardNumber, Bank Identification Number (les 6 premiers chiffres), Account Number (chiffres de 7 à 15) et Check Code (dernier chiffre):

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

Ensuite, nous allons créer la classe CreditCardEditor . Cela implémente la logique métier pour convertir le numéro de carte de crédit donné sous forme de chaîne en objet CreditCard .

La classe de l'éditeur de propriétés doit étendre PropertyEditorSupport et implémenter les méthodes getAsText () et 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); } } }

La méthode getAsText () est appelée lors de la sérialisation d'un objet en String, tandis que setAsText () est utilisé pour convertir une String en un autre objet.

Étant donné que ces classes sont situées dans le même package, nous n'avons rien d'autre à faire pour lier l' éditeur pour le type CreditCard .

Nous pouvons maintenant exposer ceci en tant que ressource dans une API REST; l'opération prend un numéro de carte de crédit comme variable de chemin de demande et Spring liera cette valeur de texte en tant qu'objet CrediCard et la transmettra comme argument de méthode:

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

Par exemple, pour un exemple de requête URL / property-editor / credit-card / 1234-1234-1111-0019, nous obtiendrons la réponse:

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

3. Liaison de l'éditeur de propriétés personnalisées

Si nous n'avons pas la classe de type requise et la classe de l'éditeur de propriété dans le même package ou avec les conventions de dénomination attendues, nous devrons définir une liaison personnalisée entre le type requis et l'éditeur de propriété.

Dans notre scénario de liaison d'éditeur de propriétés personnalisées, une valeur String sera transmise dans l'URL en tant que variable de chemin, et nous lierons cette valeur en tant qu'objet ExoticType qui conserve simplement la valeur en tant qu'attribut.

Comme dans la section 2, créons d'abord une classe de modèle ExoticType:

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

Et notre classe d'éditeur de propriétés personnalisées CustomExoticTypeEditor qui étend à nouveau 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); } }

Puisque Spring ne peut pas détecter l'éditeur de propriétés, nous aurons besoin d'une méthode annotée avec @InitBinder dans notre classe Controller qui enregistre l'éditeur:

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

Ensuite, nous pouvons lier l'entrée utilisateur à l' objet ExoticType :

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

Pour l'exemple de requête URL / property-editor / exotique-type / passion-fruit, nous obtiendrons l'exemple de réponse:

{ "name": "PASSION-FRUIT" }

4. Conclusion

Dans cet article rapide, nous avons vu comment utiliser la liaison automatique et personnalisée de l'éditeur de propriétés pour convertir des valeurs String lisibles par l'homme en types Java complexes.

Le code source complet de nos exemples ici est, comme toujours, sur GitHub.