Spring Web MVC - validate individual request params
我在SpringWebMVC 3.0中运行一个webapp,我有许多控制器方法,它们的签名大致如下:
1 2 3 4 5
| @RequestMapping (value ="/{level1}/{level2}/foo", method = RequestMethod. POST)
public ModelAndView createFoo (@PathVariable long level1,
@PathVariable long level2,
@RequestParam ("foo_name") String fooname,
@RequestParam (value ="description", required = false) String description ); |
我想增加一些验证——例如,description应该限制在某个长度,或者fooname应该只包含某些字符。如果验证失败,我希望向用户返回一条消息,而不只是抛出一些未经检查的异常(如果让数据渗透到DAO层,这无论如何都会发生)。我知道JSR303,但还没有使用它,也不太了解如何在Spring环境中应用它。
据我所知,另一种选择是将@RequestBody绑定到整个域对象,并在其中添加验证约束,但目前我的代码设置为接受上面所示的单个参数。
使用这种方法对输入参数应用验证的最直接的方法是什么?
- 我会尝试在那里使用javax.validation注释,看看它是否有效。我不知道是不是:)
- 你能详细解释一下吗?我会像处理@RequestParam那样使用参数声明本身的注释吗?
- 而且,这不是JavaEE应用程序,而不是运行在JavaEE容器中,它只是运行在servlet容器中的一个简单动态Web应用程序。
- @RequestParam @Regex(..) String foo。没关系,只要有javax.validation提供者和mvc:annotation-driven就不是javae了。
这似乎是可能的(尝试使用Spring4.1.2),请参见https://raymondhlee.wordpress.com/2015/08/29/validating-spring-mvc-request-mapping-method-parameters/
摘自上页:
将methodValidationPostProcessor添加到spring@configuration类:
1 2 3 4
| @Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
} |
。
将@validated添加到控制器类
在@requestparam之前使用@size
1 2 3
| @RequestMapping ("/hi")
public String sayHi (@Size (max = 10, message ="name should at most 10 characters long") @RequestParam ("name") String name ) {
return"Hi" + name ; |
}
@exceptionhandler方法中的handle constraintviolationexception
- 我想补充一下,@Size注释也可以用于验证集合、数组和映射大小。
- 我正在使用Spring引导,但不知怎么的,这个设置对我不起作用。从不调用验证。
- 在2017年,我尝试使用SpringBoot1.5.3,如果控制器上有一个@Validated,它就会工作。我不需要添加Hibernate验证器依赖项,也不需要配置MethodValidationPostProcessor。
- 这个方法的问题是我们不能忽略或更正验证错误。异常情况下,我们被迫退出控制器方法。
- @Jarekczek这就是验证的意义所在。您如何更正来自用户输入的验证错误?如果字段之间存在依赖关系,则必须构建自定义验证器,或者使用我有时使用的小hack(at)来自Hibernate的scriptAssert注释。
- 弹簧防尘套2.1.3:不工作
根本就没有什么内在的东西可以做到这一点,至少现在还没有。对于当前版本,如果希望自动验证,您仍然需要使用WebDataBinder将参数绑定到对象上。如果你在使用SpringMVC,这是值得学习的,即使它不是你完成这项任务的第一选择。
看起来像这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public ModelAndView createFoo (@PathVariable long level1,
@PathVariable long level2,
@Valid @ModelAttribute () FooWrapper fooWrapper,
BindingResult errors ) {
if (errors. hasErrors() {
//handle errors, can just return if using Spring form:error tags.
}
}
public static class FooWrapper {
@NotNull
@Size (max =32)
private String fooName ;
private String description ;
//getset
} |
如果类路径上有Hibernate验证程序4或更高版本,并且使用默认的调度程序设置,那么它应该"正常工作"。
编辑,因为评论越来越大:
方法签名中的任何对象不是Spring知道如何注入的"预期"对象,如HttpRequest、ModelMap等,都将得到数据绑定。对于简单的情况,只需将请求参数名与bean属性名和调用setter进行匹配,就可以实现这一点。@ModelAttribute只是一种个人风格的东西,在这种情况下,它什么都不做。JSR-303与@valid on a方法参数的集成通过WebDataBinder连接。如果您使用@RequestBody,那么您使用的是基于Spring为请求主体确定的内容类型的对象封送器(通常仅从HTTP头)。调度程序servlet(AnnotationMethodHandlerAdapterreally)无法为任意封送器"翻转验证开关"。它只是将Web请求内容传递给消息转换器,并返回一个对象。没有生成bindingresult对象,因此无论如何都无法设置错误。
您仍然可以将验证程序注入控制器并在得到的对象上运行它,它只是没有在为您填充BindingResult的请求参数上与@Valid进行神奇的集成。
- 对于映射我的输入bean,@ModelAttribute和@RequestBody有什么区别?
- @modelattribute专门使用Web数据绑定器将HTTP参数映射到POJO。@ RequestBody用于使用调度器中定义的任意映射/反序列化技术将请求的实际内容序列化为Java对象。@requestbody最常见的例子是您的post-body包含一个json字符串,并使用jackson将其转换为pojo
- 好的,@modelattribute是如何工作的?单个命名参数只映射到POJO中的属性名称中?另外,为什么不能使用@requestbody进行验证?
- @modelattribute实际上并不需要。我本可以把它省去的,它也会起到同样的作用。把它明确地标记在活页夹的运行位置只是个人的爱好。默认情况下,它只是将HTTP参数名与bean属性名匹配,并调用setter。
- 将评论折叠成答案
- 开始的时候有些失误,但这让我走上了正确的道路。谢谢。
- 如何从application.properties设置@size(max="max.value")?
- @ LukSmir注释属性是Java中的编译时常数。如果一个问题不存在,那么提供运行时验证参数可能是一个新问题的主题。
- 你好,我想问一个与上面相关的问题。如果我有来自validate类属性的请求参数差异,我们如何映射它?例如:request param=foo_name,我想在类public static class FooWrapper { @NotNull @Size(max=32) private String fooName; private String description; //getset }中映射fooname。
- @SOCHY本帖7岁,请使用"提问"按钮提出新问题;)
如果有多个请求参数需要验证(使用HTTP GET或POST)。您也可以创建一个自定义模型类,并使用@valid和@modelattribute来验证参数。通过这种方式,您可以使用Hibernate验证程序或javax.validator API来验证参数。就像这样:
请求方法:
1 2 3 4 5 6 7 8 9 10 11 12 13
| @RequestMapping(value="/doSomething", method=RequestMethod.GET)
public Model dosomething(@Valid @ModelAttribute ModelRequest modelRequest, BindingResult result, Model model) {
if (result.hasErrors()) {
throw new SomeException("invalid request params");
}
//to access the request params
modelRequest.getFirstParam();
modelRequest.getSecondParam();
...
} |
号
ModelRequest类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class ModelRequest {
@NotNull
private String firstParam ;
@Size (min = 1, max = 10, message ="You messed up!")
private String secondParam ;
//Setters and getters
public void setFirstParam (String firstParam ) {
this. firstParam = firstParam ;
}
public String getFirstParam () {
return firstParam ;
}
...
} |
希望有帮助。
- 这是否意味着我必须为不同的请求创建许多自定义模型类?