Editor de propriedades personalizadas da primavera

Editor de propriedades personalizadas da primavera

1. Introdução

Simplificando, o Spring usa editores de propriedade intensamente para gerenciar a conversão entre os valoresString e os tiposObject personalizados; isso é baseado emJava Beans PropertyEditor.

Neste tutorial, examinaremos dois casos de uso diferentes para demonstrarautomatic property editor binding and custom property editor binding.

2. Vinculação do Editor de Propriedade Automática

A infraestruturaJavaBeans padrão descobrirá automaticamente as classesPropertyEditor se elas estiverem no mesmo pacote que a classe que manipulam. Além disso, eles precisam ter o mesmo nome daquela classe mais o sufixoEditor.

Por exemplo, se criarmos uma classe de modeloCreditCard, devemos nomear a classe do editorCreditCardEditor.

Vamos agora passar pora practical property binding example.

Em nosso cenário, passaremos um número de cartão de crédito como uma variável de caminho no URL de solicitação e vincularemos esse valor como objetoa CreditCard.

Vamos primeiro criar a classe de modeloCreditCard definindo os camposrawCardNumber, Número de identificação do banco (os primeiros 6 dígitos), número da conta (dígitos de 7 a 15) e código de verificação (último dígito):

public class CreditCard {

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

    // standard constructor, getters, setters
}

A seguir, criaremos a classeCreditCardEditor. Isso implementa a lógica de negócios para converter o número do cartão de crédito fornecido comoString em um objetoCreditCard.

A classe do editor de propriedade deve estenderPropertyEditorSupporte implementar os métodosgetAsText()esetAsText():

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

O métodogetAsText() é chamado ao serializar um objeto emString,, enquantosetAsText() é usado para converterString em outro objeto.

Como essas classes estão localizadas no mesmo pacote, não precisamos fazer mais nada para vincularEditor para o tipoCreditCard.

Agora podemos expor isso como um recurso em uma API REST; a operação leva um número de cartão de crédito como uma variável de caminho de solicitação e Spring vinculará esse valor de texto como um objetoCrediCard e o passará como um argumento de método:

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

Por exemplo, para um exemplo de URL de solicitação/property-editor/credit-card/1234-1234-1111-0019,, obteremos a resposta:

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

3. Vinculação do editor de propriedade personalizada

Se não tivermos a classe de tipo necessária e a classe do editor de propriedade no mesmo pacote ou com as convenções de nomenclatura esperadas, teremos que definir uma ligação personalizada entre o tipo necessário e o editor de propriedade.

Em nosso cenário de vinculação do editor de propriedade customizada, um valorString será passado no URL como uma variável de caminho e vincularemos esse valor como um objetoExoticType que apenas mantém o valor como um atributo.

Como na seção 2, vamos primeiro criar uma classe de modeloExoticType:

public class ExoticType {
    private String name;

    // standard constructor, getters, setters
}

E nossa classe de editor de propriedade customizadaCustomExoticTypeEditor que novamente estendePropertyEditorSupport: 

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

Como o Spring não pode detectar o editor de propriedades,we’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());
}

Então, podemos vincular a entrada do usuário ao objetoExoticType:

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

Para o URL de solicitação de amostra/property-editor/exotic-type/passion-fruit, , swe obterá a resposta de amostra:

{
    "name": "PASSION-FRUIT"
}

4. Conclusão

Neste artigo rápido, vimos como poderíamos usar a vinculação automática e customizada do editor de propriedade para converter valoresString legíveis por humanos em tipos Java complexos.

O código-fonte completo de nossos exemplos aqui é, como sempre,over on GitHub.