在基于Spring 3的Web(portlet)应用程序中,我有一个控制器,其方法如下:
@RenderMapping
public ModelAndView handleRenderRequest(...,@RequestParam MyClass myObject)
{
...
}
现在我想知道:我如何告诉spring如何将请求参数转换为MyClass。我找到了有关属性编辑器和Converter接口的信息,似乎有一些影响,转换器是属性编辑器的继承者,但似乎没有人愿意明确它。
我实现了String到MyClass转换的转换器接口。但是我如何告诉Spring呢?我尽可能使用基于注释的配置,所以我检查spring是否会自动从类路径中检测到Converter,但事实并非如此。
所以认为手册中的Configuring a 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)这样的东西会很棒。
好的,我刚刚收到了文档:
在客户端环境中工作时使用Formatter SPI, 例如Web应用程序,需要解析和打印本地化字段 值
所以我想这意味着我应该使用Formatter SPI,然后是属性编辑器和转换器旁边的第三种可能性(我想我可以使用比较表等)。我也实现了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方法中设置了一个调试断点,该方法在使用list时没有触发,但它确实触发了使用set。
另外我添加了
<mvc:annotation-driven conversion-service="conversionService"/>
我的applicationContext的mvc-prefix的命名空间。但我仍然得到转换不支持的异常。
我还尝试回到转换器方法,并在applicationContext.xml文件中更改了从列表到设置的转换器的参数列表,但这也没有改变任何内容。
正如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中为每个人设置它,不是吗?很高兴知道我可以覆盖默认,如果我需要(毕竟我要求),但我仍然想设置默认值。
那格式化程序的东西呢。我不应该使用它而不是转换器吗?
答案 0 :(得分:3)
Spring Portlet MVC 3.0不支持
<mvc:annotation-driven conversion-service="conversionService"/>
访问https://jira.springsource.org/browse/SPR-6817了解更多相关信息。
但是,您可以将此添加到常用的applicationContext
<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 :(得分:1)
您认为Converter(和ConverterFactory)是属性编辑器的后继者是正确的。您的问题可能是您没有接受适当的类型作为转换器的参数,但如果没有看到转换器代码,很难说。如果您期望Long或Integer,您可能实际上是从Spring获取字符串并且需要首先自己执行该键转换。
至于配置,我相信你需要列出xml中bean配置中的所有转换器。如果使用@Component注释转换器实现,则可能可以通过bean名称而不是完全限定的路径来引用它,但我只尝试使用ConverterFactory,而不是转换器。
最后,在特定转换器上,看起来您可以在控制器级别配置转换服务(请参阅Javi在Setting up a mixed configuration for annotation-based Spring MVC controllers上的答案),然后您可以放置该方法(以及其他需要该方法的方法)控制器)进入一个使用二级转换服务的控制器,您应该能够通过@Resource注释按名称注入。
答案 2 :(得分:1)
实施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>
这有效,甚至可以允许基于多个方法参数的参数转换。
答案 3 :(得分:0)
为了实现类似于你正在做的事情,我发现this blog entry很有用。
答案 4 :(得分:-1)
我认为你需要使用像
这样的东西public ModelAndView handleRenderRequest(...,@ModelAttribute("myObject") MyClass myObject)