8

Spring 3 には、型変換などの優れた機能があります。Converter<S, T>これは、別の変換ロジックを実装するために使用されるコンバータ SPI( ) を提供します。Converter 型のサブクラスでは、一方向の変換 (S から T のみ) を定義できるため、T から SI への変換も実行する場合は、 を実装する別のコンバーター クラスを定義する必要がありますConverter<T, S>。変換の対象となるクラスが多数ある場合、多くのコンバーターを定義する必要があります。1 つのコンバーターで双方向の変換ロジック (S から T および T から S) を定義する可能性はありますか? そして、それはどのように使用されますか?

PS。現在ConversionServiceFactoryBean、構成ファイルでコンバーターを定義/挿入することでコンバーターを使用しています

4

3 に答える 3

19

インターフェイスを直接使用する場合はorg.springframework.core.convert.converter.Converter、各方向に 1 つずつ、2 つのコンバーターを実装する必要があります。

ただし、Spring 3 には他にもいくつかのオプションがあります。

  1. 変換がオブジェクトからオブジェクトではなく、オブジェクトから文字列 (およびその逆) である場合は、org.springframework.format.Formatter代わりに a を実装できます。フォーマッターは GenericConverters として登録されます ( http://static.springsource.org/spring-webflow/docs/2.3.x/reference/html/ch05s07.html#converter-upgrade-to-spring-3を参照)

  2. それ以外の場合は、独自の を実装できますorg.springframework.core.convert.converter.GenericConverter。これにより、リフレクションを使用して TwoWayConverter 実装を簡単に作成できます。

    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();
        }
    }
    
于 2012-11-12T14:15:26.910 に答える
4

Springには、この目的のためのまさにそのようなインターフェースがあります:TwoWayConverter。以下を参照してください: http ://static.springsource.org/spring-webflow/docs/2.0.x/javadoc-api/org/springframework/binding/convert/converters/TwoWayConverter.html

于 2012-06-13T05:33:09.060 に答える
1

Spring Formatterを使用して、タイプ T のオブジェクトを文字列に、またはその逆にフォーマットできます。

package org.springframework.format;

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

このインターフェースを使用すると、Barry Pitman が言うのと同じことを実現できますが、少ないコードで実現できます。これは、文字列にフォーマットしたり、その逆を行う場合に、Spring のドキュメントで推奨される方法です。Barry の 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();
    }
}

この 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 にフォーマットすることはできません。このような場合は、Spring GenericConverter を使用し、Barry Pitman の回答を使用する必要があります。

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 構成に追加します。

...
<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>
...
于 2016-02-24T12:01:53.000 に答える