Spring - 绑定到对象而不是String或primitive

时间:2009-02-05 16:30:25

标签: spring data-binding spring-mvc

假设我有以下命令对象:

class BreakfastSelectCommand{
    List<Breakfast> possibleBreakfasts;
    Breakfast selectedBreakfast;
}

如何从名单中选择一份含早餐的“selectedBreakfast”?

我想知道我会在jsp中做这样的事情:

<form:radiobuttons items="${possibleBreakfasts}" path="selectedBreakfast"  />

但这似乎不起作用。有什么想法吗?

感谢,

-Morgan

1 个答案:

答案 0 :(得分:8)

所有这一切的关键是PropertyEditor。

您需要为Breakfast类定义PropertyEditor,然后使用控制器的initBinder方法中的registerCustomEditor配置ServletDataBinder。

示例:

public class BreakfastPropertyEditor extends PropertyEditorSupport{
    public void setAsText(String incomming){
        Breakfast b = yourDao.findById( Integer.parseInt(incomming));
        setValue(b);
    }
    public String getAsText(){
        return ((Breakfast)getValue()).getId();
    }
}

请注意,您将需要一些空检查等,但您明白了。在您的控制器中:

public BreakfastFooBarController extends SimpleFormController {
    @Override
    protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) {
        binder.registerCustomEditor(Breakfast.class, new BreakfastPropertyEditor(yourDao));
    }
}

需要注意的事项:

  • PropertyEditor不是线程安全的
  • 如果您需要弹簧豆,可以手动注射它们,也可以在弹簧中将它们定义为原型范围并使用方法注入控制器
  • 抛出IllegalArgumentException如果入站参数无效/未找到,spring会将此转换为正确的绑定错误

希望这会有所帮助。

编辑(回应评论): 在给定的例子中看起来有点奇怪,因为BreakfastSelectCommand看起来不像一个实体,我不确定你的实际情况是什么。假设它是一个实体,例如Person具有breakfast属性,那么formBackingObject()方法将从PersonDao加载Person对象并将其作为命令返回。然后,绑定阶段将根据所选值更改早餐属性,以便到达onSubmit的命令都会设置早餐属性。

根据DAO对象的实现,调用它们两次或尝试两次加载同一个实体,实际上并不意味着您将运行两个SQL语句。这特别适用于Hibernate,它保证它将返回给定标识符在其会话中的同一对象,从而运行允许绑定尝试加载Breakfast选择,即使它已经没有改变也不应该'导致任何过度的开销。