问题描述
我在 Spring 应用程序中遵循此方案.
I'm following this scheme in a Spring application.
- 请求被发送到服务器,其中包含对象的 id 和要填充到此对象中的其他一些参数
- 从数据库中加载具有此 id 的对象
- 在这个对象中调用getter和setter来填充值
- 然后存储对象
我在另一个问题中询问了在填充之前准备对象的最佳方法是什么请求的参数.答案是最好的方法是使用 转换服务 而不是在 @ModelAtribute 注释方法中或使用 initBinder 中的编辑器进行.
I asked in this other question what was the best way to prepare the object before populate the params of the request. The answer was that the best way was to use a conversion service instead of doing it in a @ModelAtribute annotated method or with an editor in the initBinder.
所以我尝试使用转换器,但我没有找到类似的例子,我有点卡住了.我编写了如下代码:在 init binder 中,我注册了转换服务.因此,在填充用户对象上的值之前,调用 convert() 方法以从数据库加载对象.问题是此配置不起作用,因为它将对象用户的 id(用户名字段)转换为对象用户,但随后它尝试使用对象创建 setUsername(),因此我得到一个java.lang.IllegalArgumentException: 参数类型不匹配".
So I have tried to use a converter, but I haven't found a similar example and I'm a little stuck. I have written a code like the one below: In the init binder I register the conversion service. So before populating the values on the User object convert() method is invoked to load the object from the database. The problem is that this configuration doen't work because it is converting the id (username field) of the Object User into an Object user, but then it tries to make a setUsername() with the object so I get a "java.lang.IllegalArgumentException: argument type mismatch".
谁能给我一个使用 ConversionService 来获得所需行为的线索或示例?
Can anyone give me a clue or an example of the way of using the ConversionService to get the desired behaviour?
谢谢.
@Autowired
private ConversionService conversionService;
@InitBinder("user")
public void initBinder(@RequestParam("username")String username, WebDataBinder binder){
binder.setConversionService(conversionService);
}
@RequestMapping(value="/user/save", method=RequestMethod.POST)
public String save(@ModelAttribute("user") User user, Model model) {
...
}
类似于:
@Component
public class UserConversionService implements ConversionService{
...
@Override
public Object convert(Object name, TypeDescriptor arg1, TypeDescriptor arg2) {
return userService.find((String)name);
}
}
推荐答案
您正在尝试实现一个 ConversionService
以在字符串和用户对象之间进行转换.但是,执行此部分的是 Converter
实现.你想要做的是:
You're trying to implement a ConversionService
to do the conversion between Strings and User objects. However, it's Converter
implementations that do this part. What you want to do is:
- 编写转换器
- 使用 ConversionService 注册该转换器
- 利用 ConversionService.
您的转换器类似于:
final class UserConverter implements Converter<String, User> {
...
public User convert(String username) {
return userService.find(username);
}
}
然后您需要注册该转换器.您可以编写自己的 ConversionServiceFactoryBean 或覆盖默认值:
You then need to register that converter. You can either write your own ConversionServiceFactoryBean or override the default:
<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="example.UserConverter"/>
</list>
</property>
</bean>
如果你想显式地使用 ConversionService,就像你所拥有的那样,把它留作可以自动装配的东西.Spring 和那个 factorybean 定义将负责其余的工作.
If you want to use the ConversionService explicitly, as you have, just leave it as something that can be autowired. Spring and that factorybean definition will take care of the rest.
但是,如果您已经在上下文中使用了 <mvc:annotation-driven>
标记,则可以使用其 conversion-service
属性来引用您的 ConversionServiceFactoryBean.然后,您根本不需要在您的类中使用 InitBinder 或 ConversionService:只需让 @RequestMapping 的参数具有您的目标类型 User,转换将在您无需干预的情况下进行.
If, however, you're already using the <mvc:annotation-driven>
tag in your context, you can use its conversion-service
attribute to reference your ConversionServiceFactoryBean. You then don't need to have InitBinder or ConversionService in your class at all: by simply having a parameter of a @RequestMapping have your target type, User, the conversion will take place without you having to intervene.
这篇关于Spring 中的转换服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!