首先,...林在春天相对较新的,我用的弹簧3.x和我不喜欢Spring的XML配置文件...我不想为每个重构我这样做,碰到更新XML文件...
我想要的方式配置弹簧,对于任何要求,如果我有一些@ RequestParam / @ RequestBody / @ PathVariable等与我hadlers非字符串类型,春天将值正确地转换成该类型或把空来处理的ARGS(我从来没有在处理程序的参数使用基本类型)。 到现在为止还挺好 ...
到现在为止我已经注册的所有转换器/ converterFactory类是这样的:
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<!-- converters is a set of both converters and converterfactories -->
<bean class="controller.converters.enumConverter" />
<bean class="controller.converters.integerConverter" />
<bean class="controller.converters.objects.FooConverter" />
...
</list>
</property>
</bean>
有什么办法来注册注释器?
可什么(或只是基本的东西)春天有关XML注释与只能做,并获得一劳永逸摆脱XML配置的? ... 如何?
春天不具有转换器注解支持,但你可以建立自己的。
所有你需要的是一个自定义的限定注释(可以称之为@AutoRegistered
)和某种转换器/格式化处长(实现FormatterRegistrar
),其注册所有与此有关的Spring Bean @AutoRegistered
注释(和一些XML注册该注册服务)。
然后,你需要这个注释(和其他一些注释,使其一个Spring bean)来注释conveter,这是所有。
@AutoRegistered
注释:
@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface AutoRegistered {}
注册服务:
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.converter.Converter;
import org.springframework.format.FormatterRegistrar;
import org.springframework.format.FormatterRegistry;
public class AutoregisterFormatterRegistrar implements FormatterRegistrar {
/**
* All {@link Converter} Beans with {@link AutoRegistered} annotation.
* If spring does not find any matching bean, then the List is {@code null}!.
*/
@Autowired(required = false)
@AutoRegistered
private List<Converter<?, ?>> autoRegisteredConverters;
@Override
public void registerFormatters(final FormatterRegistry registry) {
if (this.autoRegisteredConverters != null) {
for (Converter<?, ?> converter : this.autoRegisteredConverters) {
registry.addConverter(converter);
}
}
}
}
可以由注册XML配置:
<bean id="applicationConversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="formatterRegistrars">
<set>
<bean
class="AutoregisterFormatterRegistrar"
autowire="byType" />
</set>
</property>
</bean>
BTW你的枚举转换器,你不需要ConversionFactory
-一个简单的转换就足够了:
@AutoRegistered
@Component
public class EnumConverter implements Converter<Enum<?>, String> {
/** Use the same immutable value instead of creating an new array every time. */
private static final Object[] NO_PARAM = new Object[0];
/** The prefix of all message codes. */
private static final String PREFIX = "label_";
/** The separator in the message code, between different packages
as well as between package can class. */
private static final String PACKAGE_SEPARATOR = "_";
/** The separator in the message code, between the class name
and the enum case name. */
private static final String ENUM_CASE_SEPARATOR = "_";
/** The message source. */
private MessageSource messageSource;
@Autowired
public EnumConverter(final MessageSource messageSource) {
if (messageSource == null) {
throw new RuntimeException("messageSource must not be null");
}
this.messageSource = messageSource;
}
@Override
public String convert(final Enum<?> source) {
if (source != null) {
String enumValueName = source.name();
String code = PREFIX + source.getClass().getName().toLowerCase().
replace(".", PACKAGE_SEPARATOR)
+ ENUM_CASE_SEPARATOR + enumValueName.toLowerCase();
String message = messageSource.getMessage(code, NO_PARAM, enumValueName,
LocaleContextHolder.getLocale());
return message;
} else {
return "";
}
}
}
首先,你必须定义一个注释:类型转换器
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface TypeConverter {
}
然后,你必须注册转换服务,并添加所有有注释的豆类。 这将与以下后处理器来完成:
public class ConverterRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
registry.registerBeanDefinition("conversionService", BeanDefinitionBuilder.rootBeanDefinition(ConversionServiceFactoryBean.class).getBeanDefinition());
}
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
Map<String, Object> beansWithAnnotation = beanFactory.getBeansWithAnnotation(TypeConverter.class);
Collection converters = beansWithAnnotation.values();
DefaultConversionService conversionService = (DefaultConversionService) beanFactory.getBean("conversionService");
for (Object converter : converters) {
conversionService.addConverter((Converter<?, ?>) converter);
}
}
}
如果您需要更多的细节检查这个博客条目
转换豆的自动注册时,也由Spring提供引导@EnableAutoConfiguration
看-被打开弹簧引导功能 。 看来,没有额外的说明(比标记每个转换器bean作为其他@Component
)是必需的这一点。
通过@Ralph介绍的方法是整齐的,我有+1他的答案。 让我也建议其使用的替代方法@Configuration
支持 -本质的方式使用,而不是XML的Java配置的Spring bean。 这种方法的消息转换器可以注册这种方式:
@Configuration
@EnableWebMvc
@ComponentScan(...)
public class CustomConfig extends WebMvcConfigurerAdapter {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new EnumConverter());
converters.add(new FooConverter());
...
}
}
借助于Spring MVC 3.2,您可以创建一个扩展DefaultFormattingConversionService如转换服务类
ApplicationConversionService.java
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.stereotype.Component;
@Component("conversionService")
public class ApplicationConversionService extends DefaultFormattingConversionService {
public ApplicationConversionService(){
//DefaultFormattingConversionService's default constructor
//creates default formatters and converters
super(); //no need for explicit super()?
//add custom formatters and converters
addConverter(new MyConverter());
}
}
在春天的配置如指定它
调度员servlet.xml中
<mvc:annotation-driven conversion-service="conversionService"/>
我不知道,如果这个工程在春季3但这是春季4解决方案:
@Configuration
@EnableWebMvc
class WebMvcContext extends WebMvcConfigurerAdapter {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new DateConverter("yyyy-MM-dd HH:mm:ss"));
//registry.addConverter(anotherConverter);
}
}
DateConverter是一个自定义转换器:
public class DateConverter implements Converter<String, Date>{
private static final Logger LOGGER = LoggerFactory.getLogger(DateConverter.class);
private final String dateFormat;
private final SimpleDateFormat formatter;
public DateConverter(String dateFormatPattern) {
this.dateFormat = dateFormatPattern;
this.formatter = new SimpleDateFormat(dateFormatPattern);
}
@Override
public Date convert(String source) {
Date date = null;
try {
date = formatter.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}