Spring中的ConversionService

我在Spring应用程序中遵循此方案。

  1. 请求被发送到服务器,其中包含对象的id以及要在此对象中填充的其他一些参数
  2. 具有此id的对象从数据库加载
  3. 在此对象中调用getter和setter以填充值
  4. 然后存储该对象

我在另一个问题中询问,在填充请求的参数之前,准备对象的最佳方法是什么。 答案是最好的方法是使用转换服务而不是在@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); } } 

您正在尝试实现ConversionService以在字符串和用户对象之间进行转换。 但是,这是Converter实现的一部分。 你想要做的是:

  1. 写一个转换器
  2. 使用ConversionService注册该转换器
  3. 使用ConversionService。

你的转换器将是这样的:

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

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

        

如果您想要显式使用ConversionService,只需将其保留为可自动assembly的内容即可。 Spring和那个factorybean定义将处理其余的事情。

但是,如果您已在上下文中使用标记,则可以使用其conversion-service属性来引用您的ConversionServiceFactoryBean。 然后,您根本不需要在您的类中使用InitBinder或ConversionService:只需让@RequestMapping的参数具有您的目标类型User,就可以在不必进行干预的情况下进行转换。

我完全按照Gary的说法完成了它的工作:

我想在解决方案中添加更多信息。 根据Spring文档, URI模板变量使用Converter / ConversionService转换为目标对象。 我试图使用@RequestParam("id") @ModelAttribute("contact") Contact contact ,但是我收到了一个IllegalStateException: Neither BindingResult nor plain target object for bean name 'contact' available as request attribute模型的IllegalStateException: Neither BindingResult nor plain target object for bean name 'contact' available as request attribute我视图中的对象contact edit.jsp。 通过声明Model modelmodel.addAttribute(contact);可以很容易地解决这个问题model.addAttribute(contact); 。 但是,还有更好的方法; 使用URI模板变量。 @RequestParam奇怪的是为什么@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这样的链接隐式调用String’1’的转换器到id’1’转换的Contact,并将这个联系对象带到视图中。 不需要@InitBinder ,因为它是一个在ConversionService注册的ConversionService Converter ,我可以在任何我想要的地方使用它– 隐式或显式