Spring Web MVC - 验证个人请求参数

Dan*_*Dan 48 java validation spring spring-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);
Run Code Online (Sandbox Code Playgroud)

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

根据我的理解,另一种选择是绑定@RequestBody到整个域对象并在那里添加验证约束,但是目前我的代码被设置为接受如上所示的各个参数.

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

anr*_*nre 38

这似乎是现在可能的(尝试使用Spring 4.1.2),请参阅https://raymondhlee.wordpress.com/2015/08/29/validating-spring-mvc-request-mapping-method-parameters/

从上页摘录:

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

    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor() {
        return new MethodValidationPostProcessor();
    }
    
    Run Code Online (Sandbox Code Playgroud)
  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;
    
    Run Code Online (Sandbox Code Playgroud)

    }

  4. 在@ExceptionHandler方法中处理ConstraintViolationException

  • 我正在使用Spring Boot,不知怎的,这个设置对我来说不起作用.永远不会调用恶意. (4认同)
  • 在2017年,我尝试使用Spring Boot 1.5.3,如果我在控制器上有一个`@ Validated`它就可以工作.我没有添加hibernate-validators依赖,也没有配置`MethodValidationPostProcessor`. (4认同)
  • 这种方法的问题在于我们不能忽略或纠正验证错误。由于异常,我们被迫退出控制器方法。 (2认同)

Aff*_*ffe 29

没有什么内置做到这一点,不是 尚未反正.对于当前发行版本,如果需要自动验证,仍需要使用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
}
Run Code Online (Sandbox Code Playgroud)

如果你的类路径上有Hibernate Validator 4或更高版本并使用默认的调度程序设置它应该"正常工作".

编辑自评论变得有点大:

这是在这不是"预期"的人Spring知道如何注入,如一个你的方法签名的任何对象HttpRequest,ModelMap等等,将得到的数据绑定.这只是通过将请求参数名称与bean属性名称和调用setter匹配来实现的.该@ModelAttribute存在的仅仅是个人风格的东西,在这种情况下,它没有做任何事情.JSR-303与方法参数的@Valid集成通过WebDataBinder.如果你使用@RequestBody,你正在使用一个对象编组器,它基于spring为请求体确定的内容类型(通常只是来自http头).调度程序servlet(AnnotationMethodHandlerAdapter真的)没有办法'翻转验证开关'任何任意的编组员.它只是将Web请求内容传递给消息转换器并获取一个Object.没有生成BindingResult对象,因此无论如何都无法设置错误.

您仍然可以将验证器注入控制器并在您获得的对象上运行它,它只是没有与@Valid填充BindingResult为您的请求参数上的魔术集成.

  • @ModelAttribute专门使用Web数据绑定器将http参数映射到POJO.@RequestBody用于使用调度程序中定义的任意映射/反序列化技术将请求的实际内容序列化为java对象.@RequestBody最常见的例子是你的POST主体包含一个JSON字符串,你使用Jackson把它变成一个POJO (3认同)

Mas*_*erV 17

如果您有多个需要验证的请求参数(使用Http GETPOST).您也可以创建一个自定义模型类,并使用@ Valid和@ ModelAttribute来验证参数.这样您就可以使用Hibernate Validatorjavax.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();

    ...   
}
Run Code Online (Sandbox Code Playgroud)

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

    ...
}
Run Code Online (Sandbox Code Playgroud)

希望有所帮助.