关于java:Spring Web MVC – 验证个人请求参数

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绑定到整个域对象,并在其中添加验证约束,但目前我的代码设置为接受上面所示的单个参数。

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


这似乎是可能的(尝试使用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


  • 根本就没有什么内在的东西可以做到这一点,至少现在还没有。对于当前版本,如果希望自动验证,您仍然需要使用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知道如何注入的"预期"对象,如HttpRequestModelMap等,都将得到数据绑定。对于简单的情况,只需将请求参数名与bean属性名和调用setter进行匹配,就可以实现这一点。@ModelAttribute只是一种个人风格的东西,在这种情况下,它什么都不做。JSR-303与@valid on a方法参数的集成通过WebDataBinder连接。如果您使用@RequestBody,那么您使用的是基于Spring为请求主体确定的内容类型的对象封送器(通常仅从HTTP头)。调度程序servlet(AnnotationMethodHandlerAdapterreally)无法为任意封送器"翻转验证开关"。它只是将Web请求内容传递给消息转换器,并返回一个对象。没有生成bindingresult对象,因此无论如何都无法设置错误。

    您仍然可以将验证程序注入控制器并在得到的对象上运行它,它只是没有在为您填充BindingResult的请求参数上与@Valid进行神奇的集成。


    如果有多个请求参数需要验证(使用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;
        }

        ...
    }

    希望有帮助。