Spring控制器预处理@ModelAttribute请求参数

时间:2014-04-07 07:53:32

标签: java spring validation spring-mvc spring-portlet-mvc

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

接收表单数据
@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
}

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

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

结论

我认为控制器myObject与实际模型对象myObject之间存在很大差异。 <{1}}应该是模型对象,只要经过验证和“映射”即可。

所以我的问题在这里:

  • 您是否认为最后一点通常会将myObject视为一个坏主意?
  • 或者在创建@ModelAttribute - 实例之前是否有方法映射和验证表单数据?
  • 如果没有,您会如何建议解决问题?

1 个答案:

答案 0 :(得分:0)

编辑:@initBinder反之亦然(1个字段 - > N个属性)

我不知道框架是否可以开箱即用(N字段 - > 1属性),而不会进入绑定管道。

以下两个简单的解决方案可以解决这个问题:

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

  • 如果MyObject不包含许多属性,请忘记@ModelAttribute +控制器层验证,并为每个字段使用@RequestParam。服务层验证仍在使用中。

你当然可以通过使用Spring MVC的内部工具手动将你的表单数据“绑定”到你的对象上,但最终它会像我的第二点,更令人困惑的管道。