8

まず第一に...私はSpringで比較的新しいので、私はSpring 3.xを使用しています.SPRINGのXML構成ファイルは好きではありません...私が行うすべてのリファクタリングで、更新のためにXMLファイルに実行する必要はありません...

ハドラーに String 以外の型の @RequestParam/@RequestBody/@PathVariable などがある場合、Spring が値をその型に正しく変換するか、null をハンドラーに配置するように、Spring を構成しようとしています。 args (ハンドラの引数にプリミティブ型を使用することはありません)。ここまでは順調ですね ...

これまで、すべてのコンバーター/コンバーターファクトリー クラスを次のように登録しました。

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

注釈付きのコンバーターを登録する方法はありますか?

Spring XML に関する何か (または単に基本的なこと) を注釈のみで実行し、XML 構成を完全に取り除くことはできますか? ... そしてどうやって?

4

7 に答える 7

9

Spring には、コンバーターの注釈サポートはありませんが、独自に構築できます。

必要なのは、カスタム修飾子アノテーション ( let と呼びます) と、すべての Spring Bean をこのアノテーション (およびこの登録サービスを登録するための xml ) に@AutoRegistered登録するある種のコンバーター/フォーマッター レジストラー (implements ) だけです。FormatterRegistrar@AutoRegistered

次に、この注釈 (およびそれを Spring Bean にするための他の注釈) でコンベターに注釈を付ける必要があり、それだけです。

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

ところで、列挙型コンバーターは必要ありません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 "";
         }
     }   
}
于 2012-12-08T14:41:07.330 に答える
6

まず、注釈を定義する必要があります: TypeConverter

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface TypeConverter {
}

次に、変換サービスを登録し、アノテーションを持つすべての Bean を追加する必要があります。これは、次のポスト プロセッサで実行されます。

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

詳細が必要な場合は、この ブログエントリを確認してください

于 2013-03-15T02:17:43.633 に答える
5

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

 }
于 2012-12-08T18:05:29.327 に答える
1

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

}

春の設定でそれを指定します。

dispatcher-servlet.xml

<mvc:annotation-driven conversion-service="conversionService"/>
于 2014-02-05T08:37:15.920 に答える