스프링 MVC 타입 변환 : PropertyEditor 또는 Converter?
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());
}
...
}
간단합니다. 두 변환 모두 동일한 클래스에 정의되어 있으며 바인딩은 간단합니다. 모든 컨트롤러에서 일반 바인딩을 원한다면 여전히 xml config에 3 줄을 추가 할 수 있습니다 .
그러나 Spring 3.x는 Converters를 사용하여 새로운 방법을 도입했습니다 .
스프링 컨테이너 내에서이 시스템은 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(...);
.
내가 찾은 유일한 방법은 지루하고 단순하지 않으며 일반적인 크로스 컨트롤러 바인딩에만 관한 것입니다.
XML 설정 :
<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()); } }
이러한 단점을 모두 갖춘 이유는 무엇입니까? 뭔가 빠졌습니까? 내가 모르는 다른 트릭이 있습니까?
I am tempted to go on using PropertyEditors... Binding is much easier and quicker.
With all these drawbacks, why using Converters ? Am I missing something ? Are there other tricks that I am not aware of ?
No, I think you have very comprehensively described both PropertyEditor and Converter, how each one is declared and registered.
In my mind, PropertyEditors are limited in scope - they help convert String to a type, and this string typically comes from UI, and so registering a PropertyEditor using @InitBinder and using WebDataBinder makes sense.
Converter on the other hand is more generic, it is intended for ANY conversion in the system - not just for UI related conversions(String to target type). For eg, Spring Integration uses a converter extensively for converting a message payload to a desired type.
I think for UI related flows PropertyEditors are still appropriate especially for the case where you need to do something custom for a specific command property. For other cases, I would take the recommendation from Spring reference and write a converter instead(for eg, to convert from a Long id to an entity say, as a sample).
- For to/from String conversions use formatters (implement org.springframework.format.Formatter) instead of converters. It has print(...) and parse(...) methods, so you need only one class instead of two. To register them, use FormattingConversionServiceFactoryBean, which can register both converters and formatters, instead of ConversionServiceFactoryBean.
- The new Formatter stuff has a couple of additional benefits:
- Formatter interface supplies the Locale object in its print(...) and parse(...) methods, so your string conversion can be locale-sensitive
- In addition to the pre-registered formatters, FormattingConversionServiceFactoryBean comes with a couple of handy preregistered AnnotationFormatterFactory objects, that allow you to specify additional formatting parameters via annotation. For example: @RequestParam @DateTimeFormat(pattern="MM-dd-yy") LocalDate baseDate ... It's not very difficult to create your own AnnotationFormatterFactory classes, see Spring's NumberFormatAnnotationFormatterFactory for a simple example. I think this eliminates the need in controller-specific formatters/editors. Use one ConversionService for all controllers and customize the formatting via annotations.
- I agree that if you still needs some controller-specific string conversion, the simplest way is still to use custom property editor. (I tried to call 'binder.setConversionService(...)' in my @InitBinder method, but it fails, since the binder object comes with the 'global' conversion service already set. Seems like per-controller conversion classes are discouraged in Spring 3).
The simplest (assuming that you are using a persistence framework), but not the perfect way is to implement a generic entity converter via ConditionalGenericConverter
interface that will convert entities using their metadata.
For example, if you are using JPA, this converter may look if the specified class has @Entity
annotation, and use @Id
annotated field to extract information and perform the lookup automatically using the supplied String value as an Id for lookup.
public interface ConditionalGenericConverter extends GenericConverter {
boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType);
}
ConditionalGenericConverter
is an "ultimate weapon" of Spring convertion API, but being implemented once it will be able to process most of entity convertions, saving developer time - it's a great relief when you just specify entity classes as parameters of your controller and never think about implementing a new converter(except for custom and non-entity types, of course).
You can sort of work around the need for having two separate Converter classes by implementing the two Converters as static inner classes.
public class FooConverter {
public static class BarToBaz implements Converter<Bar, Baz> {
@Override public Baz convert(Bar bar) { ... }
}
public static class BazToBar implements Converter<Baz, Bar> {
@Override public Bar convert(Baz baz) { ... }
}
}
You would still need to register both of them separately, but at least this cuts down on the number of files you need to modify if you make any changes.
참고URL : https://stackoverflow.com/questions/12544479/spring-mvc-type-conversion-propertyeditor-or-converter
'IT story' 카테고리의 다른 글
케이스 클래스에 스칼라 열거가 포함 된 경우 MongoCaseClassField와 함께 Rogue를 사용하여 몽고 레코드를 업데이트하는 방법 (0) | 2020.07.04 |
---|---|
Chrome 웹킷 검사기에서 '안전하지 않은 자바 스크립트가 URL로 프레임에 액세스하려고합니다…'오류가 계속 발생 함 (0) | 2020.07.04 |
매번 완전한 코드를 재 컴파일하는 Xcode 8 (0) | 2020.07.04 |
"단일 페이지"JS 웹 사이트 및 SEO (0) | 2020.07.04 |
Eclipse 패키지 탐색기와 Eclipse 프로젝트 탐색기의 차이점은 무엇입니까? (0) | 2020.07.04 |