【问题标题】:Spring controller pre-process @ModelAttribute request parametersSpring控制器预处理@ModelAttribute请求参数
【发布时间】:2014-04-07 07:53:31
【问题描述】:

在我的 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-flag 来解决这个问题。但我认为这是一个不干净的解决方案。

结论

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

所以这里是我的问题:

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

【问题讨论】:

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


    【解决方案1】:

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

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

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

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

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

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

    【讨论】:

    • PropertyEditor 适用于一个字段,我不知道有一种方法可以同时支持日期和时间
    • 抱歉,我在第一个答案中弄错了
    猜你喜欢
    • 2016-01-27
    • 1970-01-01
    • 2016-07-19
    • 1970-01-01
    • 2021-07-09
    • 1970-01-01
    • 2015-02-13
    • 2017-03-22
    • 2011-10-16
    相关资源
    最近更新 更多