Как сделать преобразование параметров запроса весны - PullRequest
14 голосов
/ 26 июля 2011

В веб-приложении на основе Spring 3 (портлет) у меня есть контроллер с методом, подобным следующему:

@RenderMapping
public ModelAndView handleRenderRequest(...,@RequestParam MyClass myObject)
{
    ...
}

Теперь мне интересно: как мне сказать Spring, как преобразовать параметр запроса в MyClass.Я нашел информацию о редакторах свойств и об интерфейсе Converter, и, похоже, есть некоторые следствия того, что Converter является преемником редактора свойств, но никому, похоже, не нравится быть откровенным об этом.

Я реализовал интерфейс конвертера дляПреобразование строки в MyClass.Но как мне рассказать об этом Spring?Я использую конфигурацию на основе аннотаций везде, где это возможно, поэтому я проверил, будет ли Spring автоматически обнаруживать конвертер из моего пути к классам, но это не так.

Так думал, что деталь Настройка ConversionService изРуководство хочет сказать мне, что я должен добавить следующее в мой applicationContext.xml, что я и сделал:

<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <list>
            <bean class="some.package.MyConverter"/>
        </list>
    </property>
</bean>

Бит еще:

org.springframework.beans.ConversionNotSupportedException: не удалось преобразовать значение [...]

Так чего мне не хватает?И есть ли способ, просто настроить пакет и позволить Spring сканировать этот пакет на наличие конвертеров и автоматически регистрировать их?И сказать, что в одном определенном методе я хочу использовать другой конвертер, чем во всех других методах.Например, я хочу, чтобы целое число с проверочной суммой Luhn-Checksum и контрольная сумма были удалены, как я могу это сделать?Было бы замечательно что-то вроде @RequestParam (converter = some.package.MyConverter.class).

EDIT

Хорошо, я только что поймал документацию:

Используйте SPI Formatter, когда вы работаете в клиентской среде, такой как веб-приложение, и вам необходимо проанализировать и распечатать локализованные значения полей

Так что я предполагаю, что это означает, что я должен использовать SPI Formatter,еще одна третья возможность рядом с редакторами свойств и конвертерами (я думаю, что я мог бы действительно с таблицей сравнения или тому подобным).Я также реализовал интерфейс Parser и попытался зарегистрировать свой конвертер, используя:

<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="some.package.SortOrderEnumConverterSpring"/>
        </set>
    </property>
</bean> 

Как вы можете видеть, я использовал «set» вместо «list» для определения конвертеров.Я установил точку останова отладки в методе FormattingConversionServiceFactoryBean.setConverters, который не срабатывал при использовании списка, но он срабатывал при использовании set.

Дополнительно я добавил

<mvc:annotation-driven conversion-service="conversionService"/>

И пространство имен дляmvc-префикс для моего приложения контекста.Но все же я получаю исключение, не поддерживающее преобразование.

Я также попытался вернуться к подходу преобразователя и изменил в своем файле applicationContext.xml список параметров для преобразователей из списка в набор, но это тоже ничего не изменило.

EDIT2

Как указал digitaljoel, можно установить разные преобразователи на контроллер, используя метод initBinder.Я применил это к своему контроллеру:

@Autowired
private ConversionService conversionService;

@InitBinder
public void initBinder(WebDataBinder binder)
{
    binder.setConversionService(conversionService);
}

И в моем applicationContext.xml:

<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="some.package.with.MyConverter"/>
        </set>
    </property>
</bean>

И все вдруг конвертация работает просто отлично :-).Но я не совсем доволен тем, что мне приходится применять это к каждому контроллеру.Должен быть способ просто установить его в моем applicationContext для всех, не так ли?Хорошо знать, что я могу переопределить значение по умолчанию, если мне нужно (после всего, что я просил об этом), но я все еще хочу установить значения по умолчанию.

А что насчет вещей Formatter.Разве я не должен использовать это вместо Converter?

Ответы [ 5 ]

3 голосов
/ 20 ноября 2012

Spring Portlet MVC 3.0 не поддерживает

<mvc:annotation-driven conversion-service="conversionService"/>

Посетите https://jira.springsource.org/browse/SPR-6817 для получения дополнительной информации об этом.

Однако вы можете добавить это в свое общее приложение. Текст

<bean
    class="org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="webBindingInitializer">
        <bean
            class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
            <property name="conversionService">
                <list>
                    <ref bean="conversionService" />
                </list>
            </property>
        </bean>
    </property>
</bean>

Таким образом, вам не нужно добавлять @InitBinder для каждого контроллера

и, конечно,

<bean id="conversionService"
    class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <property name="converters">
        <list>
            <!-- converter implementations here -->
        </list>
    </property>
</bean>
1 голос
/ 17 июня 2012

Реализация WebArgumentResolver:

public class MyArgumentResolver implements WebArgumentResolver
{
    @Override
    public Object resolveArgument(MethodParameter methodParameter,
            NativeWebRequest webRequest) throws Exception
    {
        Class<?> paramType = methodParameter.getParameterType();
        if (paramType == MyClass.class)
        {
            String parameterName = methodParameter.getParameterName();
            String stringParameter = webRequest.getParameter(parameterName);
            return convert(stringParameter);
        }
        return UNRESOLVED;
    }
}

и регистрация его в вашем applicationContext.xml:

<bean class="org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="customArgumentResolver">
        <bean class="com.dshs.eakte.util.MyArgumentResolver" />
    </property>
</bean>

Это работает и даже имеет преимущество, заключающееся в возможности преобразования параметров, основанного на несколькихпараметры метода.

1 голос
/ 27 июля 2011

Вы правы, что Converter (и ConverterFactory) являются наследниками редакторов свойств. Ваша проблема может заключаться в том, что вы не принимаете соответствующий тип в качестве параметра для вашего преобразователя, но это трудно сказать, не видя код преобразователя. Если вы ожидаете Long или Integer, возможно, вы на самом деле получаете String от Spring и вам нужно сначала выполнить преобразование этого ключа самостоятельно.

Что касается конфигурации, я считаю, что вам нужно перечислить все ваши конвертеры в конфигурации bean-компонентов в xml. Если вы аннотируете реализацию конвертера с помощью @Component, вы можете ссылаться на него по имени компонента, а не по полному пути, но я пробовал это только для ConverterFactory, а не для Converter.

Наконец, на определенных конвертерах похоже, что вы можете настроить службу конвертации на уровне контроллера (см. Ответ Javi на Настройка смешанной конфигурации для контроллеров Spring MVC на основе аннотаций ) и тогда вы можете просто поместить этот метод (и другие, которым требуется этот контроллер) в контроллер, который использует вторичную службу преобразования, которую вы должны иметь возможность внедрять по имени с помощью аннотации @Resource.

0 голосов
/ 08 июня 2012

Я думаю, вам нужно использовать что-то вроде

public ModelAndView handleRenderRequest(...,@ModelAttribute("myObject") MyClass myObject)
0 голосов
/ 13 апреля 2012

Чтобы добиться чего-то похожего на то, что вы делаете, я нашел эту запись в блоге полезной.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...