java - Spring Controller 预处理@ModelAttribute请求参数

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

在我的 Spring 4 驱动的 portlet 中,我有一个包含日期字段的数据对象。在 JSP View 中,我有两个单独的字段:日期 (dd/mm/yyyy) 和时间 (hh/mm)。我的 Controller 中的操作处理程序使用 @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
}

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

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

结论

我认为 Controller 的 myObject 和作为实际模型对象的 myObject 之间存在很大差异。一旦经过验证和“映射”,myObject 就应该是一个模型对象。

这是我的问题:

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

最佳答案

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

我不知道框架是否可以开箱即用地执行您想要的操作(N 个字段 -> 1 个属性),而无需进入绑定(bind)管道。

以下是解决该问题的两个简单解决方案:

  • 按照旧的“Struts”方式进行操作,创建一个将在 View 中专用的 MyObjectForm 对象,然后在 Controller 中将其转换为 MyObject。 您仍然可以在服务层 MyObjectService 使用您的 @Valid,这在技术上是合理的。

  • 如果MyObject不包含几十个属性,请忘记@ModelAttribute + Controller 层验证,只需使用@RequestParam每个领域。服务层验证仍在进行中。

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

关于java - Spring Controller 预处理@ModelAttribute请求参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22906565/

相关文章:

java - 从子流返回后调用 flowRedirect 会引发异常

c - 从重定向为输入的文件中验证日期

java - @Valid 不适用于嵌套对象(Java/Spring Boot)

java - Akka : How to assign an Actor an alias path

java - 单元测试 Spring Cloud Gateway RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder)

java - 使用线程捕获进程输出

json - Spring Boot 在 json 中包含 ID 字段

validation - 如何使用 p :growl only for confirmation not validation jsf2 primefaces

java - Android 14 及更高版本是否可以使用 Java 8 功能Optional 和 Stream

java - 在jpa hibernate中使用存储库查询sql时无限递归