/ / Convertidor bidireccional en primavera - java, spring-3

Convertidor de dos vías en primavera - java, spring-3

Spring 3 tiene una característica tan agradable como la conversión de tipos. Proporciona un convertidor SPI (Converter<S, T>) que se utilizará para implementar la conversión denet diferentelógica. La subclase de tipo Convertidor permite definir la conversión unidireccional (solo de S a T), por lo que si quiero que también se realice una conversión de T a S, necesito definir otra clase de convertidor que implemente Converter<T, S>. Si tengo muchas clases que están sujetas aconversión, necesito definir muchos convertidores. ¿Existe alguna posibilidad de definir la lógica de conversión bidireccional (de S a T y de T a S) en un convertidor? y como se usará

PD. ahora estoy usando mis convertidores a través de ConversionServiceFactoryBean definiéndolos / inyectándolos en el archivo de configuración

Respuestas

8 para la respuesta № 1

Tienes razón, si quieres usar el org.springframework.core.convert.converter.Converter interfaz directamente, deberá implementar dos convertidores, uno para cada dirección.

Pero la primavera 3 tiene un par de otras opciones:

  1. Si su conversión no es de objeto a objeto, sino de objeto a cadena (y viceversa), puede implementar un org.springframework.format.Formatter en lugar. Los formateadores se registran como convertidores genéricos (ver http://static.springsource.org/spring-webflow/docs/2.3.x/reference/html/ch05s07.html#converter-upgrade-to-spring-3)

  2. De lo contrario, podría implementar su propio org.springframework.core.convert.converter.GenericConverter, lo que facilita la creación de implementaciones de TwoWayConverter mediante la reflexión.

    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 para la respuesta № 2

Spring tiene una interfaz para este propósito: TwoWayConverter. ver lo siguiente: http://static.springsource.org/spring-webflow/docs/2.0.x/javadoc-api/org/springframework/binding/convert/converters/TwoWayConverter.html


0 para la respuesta № 3

Puedes usar Formateador de primavera para formatear objetos de tipo T a String y viceversa.

package org.springframework.format;

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

Usando esta interfaz puede lograr lo mismo queel Barry Pitman dice pero con menos código y esta es la forma preferible por la documentación de Spring si desea formatear a String y viceversa. Entonces la clase UserIdConverter de Barry se verá así:

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();
}
}

Para registrar este formateador debe incluir esto en su configuración 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>
...

! NOTA que esta clase solo se puede usar paraformateo de algún tipo T a String y viceversa. No puede formatear desde el tipo T a otro tipo T1, por ejemplo. Si tiene este caso, debe utilizar el convertidor genérico de Spring y utilizar la respuesta de 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();
}
}

Y agregue a su configuración 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>
...