1

在我的 Spring 4 驱动的 portlet 中,我有一个包含日期字段的数据对象。在 JSP 视图中,我有两个单独的字段,日期 (dd/mm/yyyy) 和时间 (hh/mm)。我的控制器中的动作处理程序使用@ModelAttribute-annotation 接收表单数据:

@ActionMapping(params = "action=update")
public void onUpdate(@Valid @ModelAttribute("myObject") MyObject myObject,
   BindingResult bindingResult, ActionResponse response, SessionStatus status)
{
   if (!bindingResult.hasErrors())
      myObjectService.save(myObject);
   else
      // provide 'myObject' in the view which displays validation errors
}

onUpdate()我需要在验证表单数据和接收之前合并日期和时间myObject,因为整个可用日期MyObject只有一个字段。java.util.Calendar

解决此需求的想法 1

现在我想,我还可以将日期拆分为两个单独的字段,MyObject并提供一个 getter 来按需合并值:

@Column(name = "begin")
public Calendar getBegin()
{
   // return calendar object built from this.beginDate and this.beginTime
}

但我认为这不是一个好主意,原因有几个(请参阅这个问题:Hibernate Annotations - which is better, field or property access?)我希望模型对象成为数据库记录的镜像,因此它应该是在被分配之前进行验证。

想法 2

另一种方法是,myObject在设置日期或时间时按需创建或修改日历对象:

@Column(name = "begin")
@Temporal(TemporalType.TIMESTAMP)
private Calendar begin;

public void setBeginDate(String value)
{
    // assign a new calendar object to "begin", if "begin" is null
    // set only day, month and year components on this calendar object
}

public void setBeginTime(String value)
{
    // see "setBeginDate", do the same with hours and minutes
}

这里的问题是,如果只有“日期”或“时间”字段之一有效,则会创建一个新的日历对象。视图中的字段填充了当前日期或当前时间(取决于哪个值正确)

isValidDate什至可以通过在模型中添加另一个私有标志来解决这个问题。但我认为这是一个不干净的解决方案。

结论

myObject我认为控制器和myObject实际模型对象之间存在很大差异。myObject应该是模型对象,一旦被验证和“映射”。

所以这里是我的问题:

  • 你认为最后一点@ModelAttribute通常表明使用是一个坏主意吗?
  • MyObject或者有没有办法在创建-instance之前映射和验证表单数据?
  • 如果没有,你会建议如何解决这个问题?
4

1 回答 1

0

编辑:反过来@initBinder也可以(1个字段-> N个属性)

我不知道框架是否可以在不进入绑定管道的情况下立即执行您想要的(N 个字段 -> 1 个属性)。

这里有两个简单的解决方案来解决这个问题:

  • 使用旧的“Struts”方式并创建一个MyObjectForm您将专门在您的视图中使用的对象,然后在您的控制器中将其转换为MyObject. 您仍然可以在技术上合理@Valid的服务层使用您的。MyObjectService

  • 如果MyObject不包含几十个属性,忘记@ModelAttribute+控制器层验证,只@RequestParam为每个字段使用。服务层验证仍在发挥作用。

你当然可以破解一些东西,允许你使用 Spring MVC 的内部设施手动将表单数据“绑定”到你的对象,但最终它会像我的第二点,更令人困惑的管道。

于 2014-04-07T09:35:18.777 回答