春季双向转换器(Two-way converter in spring)

2019-09-18 01:40发布

春季3有这样一个很好的功能类型转换。 它提供了一个转换器SPI( Converter<S, T>以用于实现differenet转换逻辑。 转换器类型的子类允许定义单向转换(仅从S到T),因此,如果想转换也在T被执行以SI需要定义实现另一个转换器类Converter<T, S> 如果我有很多类,其受到的转换,我需要定义许多转换。 是否有任何在posibility一个变换器,以限定双向转换逻辑(从S到T和从T到S)? 以及它将如何使用?

PS。 现在我用我的转换器通过ConversionServiceFactoryBean定义/配置文件注入其中

Answer 1:

你是正确的,如果你想使用org.springframework.core.convert.converter.Converter直接接口,你需要实现两个转换器,每个方向一个。

但弹簧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. 否则,你可以实现自己的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(); } } 


Answer 2:

新春例如用于此目的的接口:TwoWayConverter。 看到以下内容: http://static.springsource.org/spring-webflow/docs/2.0.x/javadoc-api/org/springframework/binding/convert/converters/TwoWayConverter.html



Answer 3:

您可以使用弹簧格式化 T类型的对象格式化为String,反之亦然。

package org.springframework.format;

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

使用这个接口可以实现相同巴里皮特曼说,但用更少的代码,这是由Spring文档的最好方式,如果你啥子格式化为String,反之亦然。 所以巴里的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();
    }
}

要注册此格式 ,你应该在你的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为字符串,并且反之亦然格式化使用。 您无法从T型格式化为一些其他类型的T1为例。 如果你有这样的情况下,你应该使用Spring 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配置:

...
<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>
...


文章来源: Two-way converter in spring
标签: java spring-3