【问题标题】:Spring form ModelAttribute field validation to avoid 400 Bad Request ErrorSpring表单ModelAttribute字段验证以避免400 Bad Request Error
【发布时间】:2013-08-21 20:15:09
【问题描述】:

我有一个 ArticleFormModel 包含由普通 html form 发送的数据,该数据由 Spring 使用 @ModelAttribute 注释注入,即

@RequestMapping(value="edit", method=RequestMethod.POST)
public ModelAndView acceptEdit(@ModelAttribute ArticleFormModel model, 
    HttpServletRequest request, BindingResult errors)
{
    //irrelevant stuff
}

在某种程度上,一切都运行良好。问题是ArticleFormModel 包含一个double 字段(protected,使用普通设置器设置)。只要用户发送的数据是数字,一切都可以正常工作。当他们输入一个单词时,我得到的只是400 Bad Request Http Error。

我已经为此控制器注册了WebDataBinder

@InitBinder
protected void initBinder(WebDataBinder binder) throws ServletException
{
    binder.setValidator(validator);
}

其中validator 是实现org.springframework.validation.Validator 接口的自定义类的实例 但我不知道下一步该做什么。我希望能够解析模型,获取有效的 HTTP 响应并在表单中显示错误消息。调用了initBinder() 方法,我可以从中调用validator.validate(),但它不会改变错误(对于那个错误的数据)。

我知道我可以使用 setter 来解析字符串,检查它是否是数字,如果不是,则将该信息存储在变量中,然后在验证期间检索该变量,但这似乎工作量太大。必须有一种更简单的方法来强制字段上的类型而不会出错。另外,问题在于数据绑定,而不是验证,所以我觉得应该放在各自的代码层。

我也在考虑实现java.beans.PropertyEditor并调用binder.registerCustomEditor(),但我缺乏可靠的知识来源。

客户端验证(通过 JavaScript 检查数据是否为数字)是不可能的。

TL;DR:

如何在不获取 400 Bad Request Http Error 的情况下强制字段为 @ModelAttribute 项目的特定类型?

【问题讨论】:

  • 显示您的ArticleFormModel 课程。
  • @Sotirios Delimanolis 这是一个普通的 Java Bean,包含自动生成的 getter 和 setter 以及一个空的构造函数。它扩展了Hibernate 实体。我正在谈论的领域是protected double price。只要price 的form 项目仅包含数字,一切正常。
  • 这是预期的 Spring 行为。如果您输入了无效格式(例如 "3.14abc" 不是双精度),则这是错误请求,无效语法错误。您始终可以为每个表单字段添加@RequestParam 并自己解析/处理错误。如果你要使用@ModelAttribute,你必须适应Spring的行为。
  • @SotiriosDelimanolis 我明白这一点,但我想向用户展示一个带有错误消息的表单(最好使用<form:error> 而不是错误页面。这可能不处理错误页面吗?跨度>
  • 你不应该那样做,@ModelAttribute 是不可能的。如果您的客户端是 html,请使用 <input type="number" .../>. Unless you change your field to String` 之类的内容,并使用一些自定义或现有注释将其验证为数字。然后,当您需要将其用作双精度时,您必须转换字符串。

标签: java spring http-status-code-400 modelattribute


【解决方案1】:

您可以使用<form:errors> 处理绑定错误。

看起来像这样:

控制器:

@RequestMapping(value="edit", method=RequestMethod.POST)
public ModelAndView acceptEdit(@ModelAttribute ArticleFormModel model, 
    BindingResult errors, HttpServletRequest request)
{
  if (errors.hasErrors()) {
    // error handling code goes here.
  }
  ...
}

errors参数需要放在模型后面的右边。

详见下文(示例 17.1):

http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-ann-methods

jsp:

<form:form modelAttribute="articleFormModel" ... >
  ...
  <form:errors path="price" />
</form:form>

消息属性文件:

typeMismatch.articleFormModel.price=customized error message

【讨论】:

  • 我从不认为参数的顺序很重要,BindingResults 必须紧跟在@ModelAttribute 之后。谢谢你,现在它工作得很好!
  • 对于记录,它之所以有效,是因为您使用了原始类型。我对 java.util.Date 属性有同样的问题,但我仍然收到 400 Bad Request。
  • @Charles Morin form:errors 也应该适用于 java.util.Date。问另一个问题可能会对您有所帮助。
猜你喜欢
  • 2017-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-23
  • 2014-12-04
  • 2019-10-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多