春季转换服务

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

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

在另一个问题中,我问了在填充请求的参数之前准备对象的最佳方法是什么。答案是,最好的方法是使用转换服务,而不是在@ModelAtribute注释的方法中使用或在initBinder中使用编辑器。

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

任何人都可以给我一个线索或一个例子,说明如何使用转换服务来获得所需的行为?

谢谢。

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

答案 1

您正在尝试实现 一个以在字符串和用户对象之间执行转换。但是,是实现完成了这一部分。您要做的是:ConversionServiceConverter

  1. 编写转换器
  2. 向转换服务注册该转换器
  3. 利用转换服务。

您的转换器将如下所示:

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

}

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

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

如果你想像以前一样显式使用转换服务,只需将其保留为可以自动连接的东西。春天和那个工厂豆定义将负责其余的工作。

但是,如果您已经在上下文中使用该标记,则可以使用其属性来引用您的ConvertServiceFactoryBean。然后,您根本不需要在类中使用InitBinder或ConvertService:只需拥有一个@RequestMapping具有目标类型User的参数,转换即可进行,而无需您进行干预。<mvc:annotation-driven>conversion-service


答案 2

我完全按照Gary上面所说的去做,它奏效了:

我想向解决方案添加更多信息。根据此处的Spring文档使用转换器/转换服务将URI模板变量转换为目标对象。我试图使用一个,但我得到了一个,因为我的视图中没有模型对象编辑.jsp。这可以通过声明和来轻松解决。但是,还有更好的方法;使用 URI 模板变量。很奇怪为什么不起作用。@RequestParam("id") @ModelAttribute("contact") Contact contactIllegalStateException: Neither BindingResult nor plain target object for bean name 'contact' available as request attributecontactModel modelmodel.addAttribute(contact);@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";
}

那么这个东西是做什么的..类似这样的链接隐式调用字符串“1”到id“1”的联系人转换的转换器,并将此联系人对象带到视图中。不需要,因为它是一个注册的,我可以在任何我想要的地方使用它 - 隐式或显式...edit/1@InitBinderConverterConversionService


推荐