Spring-绑定到对象,而不是字符串或基元


问题内容

假设我有以下命令对象:

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

如何从列表中用早餐填充春天的“ selectedBreakfast”?

我当时想在jsp中做这样的事情:

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

但这似乎不起作用。有任何想法吗?

谢谢,

-摩根


问题答案:

所有这些的关键是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();
    }
}

注意,您将需要进行一些null检查等,但是您知道了。在您的控制器中:

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

需要注意的事情:

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

希望这可以帮助。

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

根据DAO对象的实现方式,两次调用它们或尝试两次加载同一实体实际上并不意味着您将获得两个SQL语句。这尤其适用于Hibernate,它保证它将为给定的标识符返回会话中的同一对象,因此Breakfast即使没有改变选择,绑定操作也可以尝试加载该选择,这不会导致任何不必要的后果。高架。