Перейти к основному содержимому

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

· 4 мин. чтения

1. Введение

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

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

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

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

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

Давайте теперь рассмотрим практический пример привязки свойств.

В нашем сценарии мы передадим номер кредитной карты в качестве переменной пути в URL-адресе запроса и привяжем это значение как объект 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 . Это реализует бизнес-логику для преобразования номера кредитной карты, заданного в виде строки , в объект 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() вызывается при сериализации объекта в строку, а setAsText() используется для преобразования строки в другой объект.

Так как эти классы находятся в одном пакете, нам больше ничего не нужно делать для привязки 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 не может обнаружить редактор свойств, нам понадобится метод с аннотацией @InitBinder в нашем классе Controller , который регистрирует редактор:

@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. Вывод

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

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