2012-06-12 2 views
2

스프링 3은 타입 변환과 같은 좋은 기능을 가지고 있습니다. Differenet 변환 로직을 구현하는 데 사용할 변환기 SPI (Converter<S, T>)를 제공합니다. 변환기 유형의 하위 클래스는 단방향 변환 (S에서 T까지만)을 정의 할 수 있으므로 T에서 S 로의 변환도 수행하려면 Converter<T, S>을 구현하는 다른 변환기 클래스를 정의해야합니다. 변환 할 클래스가 많으면 많은 변환기를 정의해야합니다. 하나의 변환기에서 양방향 변환 논리 (S에서 T 및 T에서 S)를 정의 할 수 있습니까? 어떻게 사용될 것인가?스프링의 양방향 컨버터

추신. 지금은 ConversionServiceFactoryBean을 통해 설정 파일에 정의/삽입하여 변환기를 사용하고 있습니다.

답변

7

당신이 올바른지, 두 개의 컨버터, 각 방향에 대해 하나를 구현해야합니다.

그러나 봄 3는 다른 몇 가지 옵션이 있습니다

  1. 하는 전환가 객체 - 객체가 아니라 (뒤로)에 문자열 객체, 당신은 대신 org.springframework.format.Formatter를 구현할 수없는 경우를 . 포맷터는 GenericConverters (http://static.springsource.org/spring-webflow/docs/2.3.x/reference/html/ch05s07.html#converter-upgrade-to-spring-3 참조)로 등록됩니다.

  2. 그렇지 않으면 리플렉션을 사용하여 TwoWayConverter 구현을 쉽게 만들 수있는 org.springframework.core.convert.converter.GenericConverter을 구현할 수 있습니다.

    public abstract class AbstractTwoWayConverter<S, T> implements GenericConverter { 
    
        private Class<S> classOfS; 
        private Class<T> classOfT; 
    
        protected AbstractTwoWayConverter() { 
         Type typeA = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0]; 
         Type typeB = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[1]; 
         this.classOfS = (Class) typeA; 
         this.classOfT = (Class) typeB; 
        } 
    
        public Set<ConvertiblePair> getConvertibleTypes() { 
         Set<ConvertiblePair> convertiblePairs = new HashSet<ConvertiblePair>(); 
         convertiblePairs.add(new ConvertiblePair(classOfS, classOfT)); 
         convertiblePairs.add(new ConvertiblePair(classOfT, classOfS)); 
         return convertiblePairs; 
        } 
    
        public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { 
         if (classOfS.equals(sourceType.getType())) { 
          return this.convert((S) source); 
         } else { 
          return this.convertBack((T) source); 
         } 
        } 
    
        protected abstract T convert(S source); 
    
        protected abstract S convertBack(T target); 
    
    } 
    
    /** 
    * converter to convert between a userId and user. 
    * this class can be registered like so: 
    * conversionService.addConverter(new UserIdConverter (userDao)); 
    */ 
    public class UserIdConverter extends AbstractTwoWayConverter<String, User> { 
    
        private final UserDao userDao; 
    
        @Autowired 
        public UserIdConverter(UserDao userDao) { 
         this.userDao = userDao; 
        } 
    
        @Override 
        protected User convert(String userId) { 
         return userDao.load(userId); 
        } 
    
        @Override 
        protected String convertBack(User target) { 
         return target.getUserId(); 
        } 
    } 
    
2

스프링은 TwoWayConverter와 같은 인터페이스를 가지고 있습니다. 은 다음을 참조 : 직접 org.springframework.core.convert.converter.Converter 인터페이스를 사용하려는 경우 http://static.springsource.org/spring-webflow/docs/2.0.x/javadoc-api/org/springframework/binding/convert/converters/TwoWayConverter.html

+1

이 준수 스프링 2.X 스타일 :이 사건이 있다면 당신은 봄 GenericConverter에 가서 배리 피트 맨의 답변을 사용해야합니다

public abstract class AbstractTwoWayConverter<S, T> implements GenericConverter { private Class<S> classOfS; private Class<T> classOfT; protected AbstractTwoWayConverter() { Type typeA = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0]; Type typeB = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[1]; this.classOfS = (Class) typeA; this.classOfT = (Class) typeB; } public Set<ConvertiblePair> getConvertibleTypes() { Set<ConvertiblePair> convertiblePairs = new HashSet<ConvertiblePair>(); convertiblePairs.add(new ConvertiblePair(classOfS, classOfT)); convertiblePairs.add(new ConvertiblePair(classOfT, classOfS)); return convertiblePairs; } public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { if (classOfS.equals(sourceType.getType())) { return this.convert((S) source); } else { return this.convertBack((T) source); } } protected abstract T convert(S source); protected abstract S convertBack(T target); } /** * converter to convert between a userId and user. * this class can be registered like so: * conversionService.addConverter(new UserIdConverter (userDao)); */ public class UserIdConverter extends AbstractTwoWayConverter<String, User> { private final UserDao userDao; @Autowired public UserIdConverter(UserDao userDao) { this.userDao = userDao; } @Override protected User convert(String userId) { return userDao.load(userId); } @Override protected String convertBack(User target) { return target.getUserId(); } } 

을 그리고 당신의 XML의 설정에 추가 . 나는 봄 3에서이 변환기를 발견하지 못했다. – maks

0

당신은 문자열에 그 반대 타입 T의 객체의 형식을 Spring Formatter를 사용할 수 있습니다.

package org.springframework.format; 

public interface Formatter<T> extends Printer<T>, Parser<T> { 
} 

배리 피트 맨이 적은 코드를 제외한 말한다 당신이 문자열에 그 반대의 형식을 원하든 경우이 봄 문서에 의한 바람직한 방법으로 동일한을 달성 할 수있는이 인터페이스를 사용하여. 그래서 배리의 UserIdConverter 클래스는 다음과 같이 할 것입니다 :

public class UserIdConverter implements Formatter<User> { 

    private final UserDao userDao; 

    @Autowired 
    public UserIdConverter(UserDao userDao) { 
     this.userDao = userDao; 
    } 

    @Override 
    public User parse(String userId, Locale locale) { 
     return userDao.load(userId); 
    } 

    @Override 
    public String print(User target, Locale locale) { 
     return target.getUserId(); 
    } 
} 

To register this Formatter 당신이 당신의 XML의 설정이 포함되어야합니다

... 
<mvc:annotation-driven conversion-service="conversionService"/> 

<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean" > 
    <property name="formatters"> 
     <set> 
      <bean class="com.x.UserIdConverter"/> 
     </set> 
    </property> 
</bean> 
... 

을! 이 클래스는 T 형에서 String 형으로 또는 그 반대로 형식을 지정할 때만 사용할 수 있습니다. 유형 T에서 다른 유형 T1로 형식을 지정할 수 없습니다. (제네릭없이)

... 
<mvc:annotation-driven conversion-service="conversionService"/> 

<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean" > 
    <property name="converters"> 
     <set> 
      <bean class="com.x.y.UserIdConverter"/> 
     </set> 
    </property> 
</bean> 
...