Java-Spring Web MVC-验证单个请求参数

我在Spring Web MVC 3.0中运行一个webapp,我有许多控制器方法,其签名大致如下:

@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);

我想添加一些验证-例如,@RequestBody应该限制为一定的长度,或者fooname应该仅包含某些字符。 如果验证失败,我想向用户返回一条消息,而不是抛出一些未经检查的异常(如果我让数据渗透到DAO层,无论如何都会发生这种情况)。 我知道JSR303,但尚未使用它,也不太了解如何在Spring上下文中应用它。

据我了解,另一种选择是将@RequestBody绑定到整个域对象并在其中添加验证约束,但是目前我的代码已设置为接受如上所示的各个参数。

使用这种方法将验证应用于输入参数的最直接方法是什么?

Dan asked 2020-02-22T02:00:29Z
3个解决方案
38 votes

现在似乎可以做到这一点(在Spring 4.1.2中试用),请参阅[https://raymondhlee.wordpress.com/2015/08/29/validating-spring-mvc-request-mapping-method-parameters/]

从上面的页面中提取:

  1. 将MethodValidationPostProcessor添加到Spring @Configuration类:

    @RequestMapping("/hi")
    public String sayHi(@Size(max = 10, message = "name should at most 10 characters long") @RequestParam("name") String name) {
        return "Hi " + name;
    
  2. 将@Validated添加到控制器类

  3. 在@RequestParam之前使用@Size

    @RequestMapping("/hi")
    public String sayHi(@Size(max = 10, message = "name should at most 10 characters long") @RequestParam("name") String name) {
        return "Hi " + name;
    

    }

  4. 在@ExceptionHandler方法中处理ConstraintViolationException

anre answered 2020-02-22T02:02:02Z
29 votes

到目前为止,还没有内置任何功能可以做到这一点。 在当前发行版中,如果要进行自动验证,则仍将需要使用WebDataBinder将参数绑定到对象上。 如果您使用的是SpringMVC,则值得学习,即使这不是您执行此任务的首选。

看起来像这样:

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 Validator 4或更高版本,并使用默认的分派器设置,则它应该“正常工作”。

由于评论变得越来越大,因此进行编辑:

如果方法签名中的任何Object不是Spring知道的“预期”对象之一,例如@ValidBindingResult等,都将绑定数据。对于简单的情况,只需将请求参数名称与bean属性名称进行匹配并调用setter即可实现。 @ModelAttribute只是一种个人风格的东西,在这种情况下,它什么也没做。 JSR-303与方法参数上的@Valid集成通过WebDataBinder连接。如果使用@RequestBody,则使用的是基于弹簧确定对象内容类型的对象编组器(通常仅从http标头中)。 )调度程序Servlet(实际上是AnnotationMethodHandlerAdapter)没有办法为任意编组程序“翻转验证开关”。它只是将Web请求内容传递到消息转换器,并返回一个Object。不会生成BindingResult对象,因此无论如何都无法设置错误。

您仍然可以将验证器注入控制器中,然后在获取的对象上运行它,只是它与@Valid的请求集成没有魔术集成,从而为您填充了BindingResult

Affe answered 2020-02-22T02:01:08Z
17 votes

如果您有多个需要验证的请求参数(使用Http GET或POST)。 您也可以创建一个自定义模型类,并使用@Valid和@ModelAttribute来验证参数。 这样,您可以使用Hibernate Validator或javax.validator api来验证参数。 它是这样的:

请求方法:

@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类:

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;
    }

    ...
}

希望能有所帮助。

MasterV answered 2020-02-22T02:02:36Z
translate from https://stackoverflow.com:/questions/6203740/spring-web-mvc-validate-individual-request-params