2010-12-03 48 views
25

我在Spring应用程序中遵循这个方案。ConversionService in Spring

  1. 请求被发送到服务器与该对象的ID和其他一些PARAMS在此对象
  2. 与此ID的对象中填充从数据库加载
  3. getter和setter在调用这个对象来填充值
  4. ,则对象存储

我问this other question什么之前,向得到目标物填充请求的PARAMS的最佳途径。答案是最好的方法是使用conversion service而不是在@ModelAtribute注释方法中使用它,或者在initBinder中使用编辑器。

所以我试图使用一个转换器,但我还没有找到一个类似的例子,我有点卡住了。我写了如下所示的代码:在init binder中,我注册了转换服务。因此,在填充User对象上的值之前,将调用convert()方法以从数据库加载对象。问题是这个配置不起作用,因为它将对象用户的id(用户名字段)转换为Object用户,但是随后它试图用对象创建一个setUsername(),所以我得到一个“java.lang .IllegalArgumentException:参数类型不匹配“。

任何人都可以给我一个线索或使用ConversionService获取所需行为的方式示例吗?

谢谢。

@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); 
    } 
} 
+0

另请参见:http://stackoverflow.com/a/10240927/59087 – 2015-02-10 20:24:38

回答

39

你试图实现一个ConversionService做字符串和用户对象之间的转换。但是,这是执行此部分的Converter实现。你想要做的是:

  1. 写转换器
  2. 注册该转换器带有ConversionService
  3. 利用ConversionService的。

你的转换器会是这样的:

final class UserConverter implements Converter<String, User> { 
    ... 
    public User convert(String username) { 
     return userService.find(username); 
    } 

} 

然后,您需要注册该转换器。您可以编写自己的ConversionServiceFactoryBean或覆盖默认:

<bean id="conversionService" 
     class="org.springframework.context.support.ConversionServiceFactoryBean"> 
    <property name="converters"> 
     <list> 
      <bean class="example.UserConverter"/> 
     </list> 
    </property> 
</bean> 

如果你想明确地使用ConversionService,因为你,只要把它的东西,可以自动装配。 Spring和factorybean的定义将关注其余的部分。

但是,如果您已在上下文中使用<mvc:annotation-driven>标记,则可以使用其属性来引用您的ConversionServiceFactoryBean。然后,您根本不需要在您的类中拥有InitBinder或ConversionService:只需通过@RequestMapping的参数获得您的目标类型User,就可以在无需介入的情况下进行转换。

+0

我已经成功地注册了转换服务,就像您在中所说的那样,我可以调用binder.convertIfNecessary (用户名,User.class),并调用转换器。但是在填充用户之前不会调用它。我没有在映射方法之前调用它。 “你的意思是”通过简单地拥有@RequestMapping的参数来获得你的目标类型,用户,转换就会发生“。我试图在方法中添加这样的参数:(@RequestParam(“username”)字符串用户名,@ModelAttribute(“userTest”)用户用户)但它似乎不工作。 – Javi 2010-12-04 00:17:11

+0

尝试我已经意识到,如果我在我的方法公共字符串保存(@RequestParam(“用户名”)用户用户)它调用转换器,但我不想删除@ModelAttribute注释,因为我想要填充值(我不能用@ModelAttribute和@RequestParam注解来注释相同的参数)。任何想法? – Javi 2010-12-04 00:34:50

4

我做了什么加里上面说,它的工作:

我想一些信息添加到解决方案。根据Spring文档here,使用Converter/ConversionService将URI模板变量转换为目标对象。我尝试使用@RequestParam("id") @ModelAttribute("contact") Contact contact,但我在我的视图edit.jsp中没有模型对象contact,因此得到了IllegalStateException: Neither BindingResult nor plain target object for bean name 'contact' available as request attribute。这可以通过声明Model modelmodel.addAttribute(contact);来轻松解决。但是,还有更好的办法。使用URI模板变量。很奇怪为什么@RequestParam不起作用。

没有工作

@RequestMapping("edit") //Passing id as .. edit?id=1 
public String editWithConverter(@RequestParam("id") @ModelAttribute("contact") Contact contact){ 
    logger.info("edit with converter"); 
    return "contact/edit"; 
} 

什么工作

@RequestMapping("edit/{contact}") //Passing id as .. edit/1 
public String editWithConverter(@PathVariable("contact") @ModelAttribute("contact") Contact contact){ // STS gave a warning for using {contact} without @PathVariable 
    logger.info("edit with converter"); 
    return "contact/edit"; 
} 

那么,是什么这样的事..喜欢...edit/1链接隐式调用字符串“1”为ID的联系“转换器1 '转换,并将该联系人对象引入该视图。 没有需要@InitBinder,因为它的Converter注册ConversionService我可以使用此我想要的任何地方 - 隐式或明确