Я ищу самый простой и простой способ привязать и преобразовать данные в Spring MVC. Если возможно, без настройки xml.
До сих пор я использовал PropertyEditors вот так:
public class CategoryEditor extends PropertyEditorSupport {
// Converts a String to a Category (when submitting form)
@Override
public void setAsText(String text) {
Category c = new Category(text);
this.setValue(c);
}
// Converts a Category to a String (when displaying form)
@Override
public String getAsText() {
Category c = (Category) this.getValue();
return c.getName();
}
}
и
...
public class MyController {
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Category.class, new CategoryEditor());
}
...
}
Это просто: оба преобразования определены в одном классе, и привязка проста. Если бы я хотел сделать общую привязку для всех своих контроллеров, я все равно мог бы добавить 3 строки в свою конфигурацию xml .
Но Spring 3.x представил новый способ сделать это, используя преобразователи :
В контейнере Spring эту систему можно использовать как альтернативу PropertyEditors.
Допустим, я хочу использовать конвертеры, потому что это «последняя альтернатива». Мне пришлось бы создать два конвертера:
public class StringToCategory implements Converter<String, Category> {
@Override
public Category convert(String source) {
Category c = new Category(source);
return c;
}
}
public class CategoryToString implements Converter<Category, String> {
@Override
public String convert(Category source) {
return source.getName();
}
}
Первый недостаток: мне нужно сделать два класса. Преимущество: нет необходимости кастовать благодаря универсальности.
Тогда как мне просто привязать данные к конвертерам?
Второй недостаток: я не нашел простого способа (аннотации или других программных средств) сделать это в контроллере: ничего подобного someSpringObject.registerCustomConverter(...);
.
Единственные способы, которые я нашел, были бы утомительными, не простыми и касались только общей привязки кросс-контроллера:
-
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <set> <bean class="somepackage.StringToCategory"/> <bean class="somepackage.CategoryToString"/> </set> </property> </bean>
Конфигурация Java ( только в Spring 3.1+ ):
@EnableWebMvc @Configuration public class WebConfig extends WebMvcConfigurerAdapter { @Override protected void addFormatters(FormatterRegistry registry) { registry.addConverter(new StringToCategory()); registry.addConverter(new CategoryToString()); } }
Зачем при всех этих недостатках использовать конвертеры? Я что-то упускаю ? Есть ли другие уловки, о которых я не знаю?
Я испытываю искушение продолжать использовать PropertyEditors ... Связывание намного проще и быстрее.
источник
Ответы:
Нет, я думаю, вы очень подробно описали и PropertyEditor, и Converter, как каждый из них объявляется и регистрируется.
На мой взгляд, PropertyEditors ограничены по объему - они помогают преобразовать String в тип, и эта строка обычно поступает из пользовательского интерфейса, поэтому регистрация PropertyEditor с использованием @InitBinder и использование WebDataBinder имеет смысл.
Конвертер, с другой стороны, более общий, он предназначен для ЛЮБОГО преобразования в системе, а не только для преобразований, связанных с пользовательским интерфейсом (тип String в целевой). Например, Spring Integration широко использует конвертер для преобразования полезной нагрузки сообщения в желаемый тип.
Я думаю, что для потоков, связанных с пользовательским интерфейсом, PropertyEditors по-прежнему подходят, особенно в случае, когда вам нужно сделать что-то особенное для определенного свойства команды. В других случаях я бы взял рекомендацию из справочника Spring и вместо этого написал бы конвертер (например, для преобразования из Long id в сущность, скажем, в качестве образца).
источник
источник
Самый простой (при условии, что вы используете структуру персистентности), но не идеальный способ - реализовать универсальный преобразователь сущностей через
ConditionalGenericConverter
интерфейс, который будет преобразовывать сущности с использованием их метаданных.Например, если вы используете JPA, этот преобразователь может проверять, есть ли у указанного класса
@Entity
аннотации, и использовать@Id
аннотированное поле для извлечения информации и автоматического поиска, используя предоставленное значение String в качестве идентификатора для поиска.ConditionalGenericConverter
является «абсолютным оружием» API преобразования Spring, но будет реализован, как только он сможет обрабатывать большинство преобразований сущностей, экономя время разработчика - это большое облегчение, когда вы просто указываете классы сущностей в качестве параметров вашего контроллера и никогда не думаете о реализации новый конвертер (за исключением, конечно, кастомных и не сущностных типов).источник
Вы можете обойти необходимость иметь два отдельных класса Converter, реализуя два преобразователя как статические внутренние классы.
Вам все равно придется зарегистрировать их оба по отдельности, но, по крайней мере, это сократит количество файлов, которые вам нужно изменить, если вы внесете какие-либо изменения.
источник