Редактор пользовательских свойств Spring

Spring Custom Property Editor

1. Вступление

Проще говоря, Spring широко использует редакторы свойств для управления преобразованием между значениямиString и пользовательскими типамиObject; это основано наJava Beans PropertyEditor.

В этом руководстве мы рассмотрим два разных сценария использования для демонстрацииautomatic property editor binding and custom property editor binding.

2. Автоматическая привязка редактора свойств

Стандартная инфраструктураJavaBeans автоматически обнаруживает классыPropertyEditor, если они находятся в том же пакете, что и класс, который они обрабатывают. Кроме того, они должны иметь то же имя, что и этот класс, плюс суффиксEditor.

Например, если мы создаем класс моделиCreditCard, то мы должны назвать класс редактораCreditCardEditor.

Теперь пройдемся поa practical property binding example.

В нашем сценарии мы передадим номер кредитной карты в качестве переменной пути в URL-адресе запроса и привяжем это значение как объектa CreditCard.

Давайте сначала создадим класс моделиCreditCard, определяющий поляrawCardNumber, Идентификационный номер банка (первые 6 цифр), Номер счета (цифры от 7 до 15) и Контрольный код (последняя цифра):

public class CreditCard {

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

    // standard constructor, getters, setters
}

Затем мы создадим классCreditCardEditor. Это реализует бизнес-логику для преобразования номера кредитной карты, указанного какString, в объектCreditCard.

Класс редактора свойств должен расширятьPropertyEditorSupport и реализовывать методыgetAsText() и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);
        }
    }
}

МетодgetAsText() вызывается при сериализации объекта вString,, в то время какsetAsText() используется для преобразованияString в другой объект.

Поскольку эти классы находятся в одном пакете, нам не нужно ничего делать для привязкиEditor к типуCreditCard.

Теперь мы можем предоставить это как ресурс в REST API; операция принимает номер кредитной карты в качестве переменной пути запроса, и Spring свяжет это текстовое значение как объектCrediCard и передаст его как аргумент метода:

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

Например, на образец URL-адреса запроса/property-editor/credit-card/1234-1234-1111-0019, мы получим ответ:

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

3. Привязка редактора настраиваемых свойств

Если у нас нет требуемого класса типа и класса редактора свойств в одном пакете или с ожидаемыми соглашениями об именах, нам нужно будет определить настраиваемую привязку между требуемым типом и редактором свойств.

В нашем сценарии привязки редактора настраиваемых свойств значениеString будет передано в URL как переменная пути, и мы привяжем это значение как объектExoticType, который просто сохраняет значение как атрибут.

Как и в разделе 2, давайте сначала создадим класс моделиExoticType:

public class ExoticType {
    private String name;

    // standard constructor, getters, setters
}

И наш класс редактора настраиваемых свойствCustomExoticTypeEditor, который снова расширяет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);
    }
}

Поскольку Spring не может обнаружить редактор свойств,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());
}

Затем мы можем привязать ввод пользователя к объектуExoticType:

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

Для примера URL запроса/property-editor/exotic-type/passion-fruit, будет получен ответ:

{
    "name": "PASSION-FRUIT"
}

4. Заключение

В этой быстрой статье мы увидели, как можно использовать привязку автоматического и настраиваемого редактора свойств для преобразования удобочитаемых значенийString в сложные типы Java.

Полный исходный код наших примеров здесь, как всегда,over on GitHub.