Spring表单ModelAttribute字段验证以避免400 Bad Request Error
Posted
技术标签:
【中文标题】Spring表单ModelAttribute字段验证以避免400 Bad Request Error【英文标题】:Spring form ModelAttribute field validation to avoid 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` 之类的内容,并使用一些自定义或现有注释将其验证为数字。然后,当您需要将其用作双精度时,您必须转换字符串。
【参考方案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。问另一个问题可能会对您有所帮助。以上是关于Spring表单ModelAttribute字段验证以避免400 Bad Request Error的主要内容,如果未能解决你的问题,请参考以下文章
如何使用modelAttribute在ajax(jquery)中提交spring表单
@ModelAttribute注解与spring的表单标签库form
@ModelAttribute注解与spring的表单标签库form