2011-06-01 60 views
33

我和Spring Web MVC 3.0上运行web应用程序,我有许多的控制器方法,其特征大致如下:Spring Web MVC框架 - 验证个人请求参数

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

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

+0

我会尝试使用javax.validation注释那里,看看它是否工作@RequestParam

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

}

  • 手柄ConstraintViolationException。我不知道它是否:) – Bozho 2011-06-01 15:49:44

  • +0

    你能详细说明吗?我会像使用'@ RequestParam'一样使用参数声明本身的注释吗? – Dan 2011-06-01 16:30:40

    +0

    另外,这不是Java EE应用程序,也不是在Java EE容器中运行,它只是运行在Servlet容器中的普通动态Web应用程序。 – Dan 2011-06-01 16:46:46

    回答

    23

    没有什么可以做到的,notyet无论如何。使用当前版本的版本,如果您需要自动验证,仍然需要使用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 
    } 
    

    如果你在classpath有Hibernate验证4或更高版本,并使用默认设置调度它应该“只是工作。”

    编辑,因为意见都拿到那种大:

    任何对象在你的方法签名,这不是的“预期”的人Spring知道如何注入,如HttpRequestModelMap等,会得到一个数据绑定。只需通过将请求参数名称与bean属性名称和调用设置器进行匹配,即可完成此操作。 @ModelAttribute只是个人风格的东西,在这种情况下,它没有做任何事情。通过WebDataBinder将JSR-303与方法参数上的@Valid集成在一起。如果你使用@RequestBody,你正在使用一个基于内容类型的对象编组器,这个编码器是为请求体确定的(通常来自http头)。调度器servlet(AnnotationMethodHandlerAdapter真的)没有办法'翻转验证切换'任意任意编组。它只是将Web请求内容传递给消息转换器并获取一个Object。没有生成BindingResult对象,所以无论如何都无处设置错误。

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

    +1

    用于映射我的输入bean的'@ ModelAttribute'和'@ RequestBody'有什么区别? – Dan 2011-06-01 19:27:03

    +2

    @ModelAttribute特别使用Web数据绑定器将http参数映射到POJO上。 @RequestBody用于使用调度程序中定义的任意映射/反序列化技术将请求的实际内容序列化为java对象。 @RequestBody最常见的例子是你的POST body包含一个JSON字符串,并且你使用Jackson把它变成POJO – Affe 2011-06-01 20:20:43

    +0

    好的,那么@ModelAttribute是如何工作的呢?个人命名参数只是映射到POJO中的属性名称?另外,为什么我不能在验证时使用@RequestBody? – Dan 2011-06-01 20:57:55

    13

    如果您有多个需要验证的请求参数(使用Http GETPOST)。您也可以创建自定义模型类并使用@有效以及@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(); 
    
        ... 
    } 
    

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

    希望有所帮助。

    +0

    是否意味着我必须为不同的请求创建许多自定义模型类? – yuxh 2017-04-19 09:26:04

    25

    这似乎现在是可能的(试图与Spring 4.1.2),看到网页上面https://raymondhlee.wordpress.com/2015/08/29/validating-spring-mvc-request-mapping-method-parameters/

    提取物:

    1. 添加MethodValidationPostProcessor春@Configuration类:

      @Bean 
      public MethodValidationPostProcessor methodValidationPostProcessor() { 
          return new MethodValidationPostProcessor(); 
      } 
      
    2. 添加@控制器类别验证

    3. 使用@Size之前在@ExceptionHandler方法

    +0

    我想补充说'@ Size'注解可以用来验证集合,数组和大小。 – naXa 2017-05-25 11:11:59

    +2

    我使用的是Spring Boot,不知怎的,这个设置对我来说不起作用。验证永远不会被调用。 – 2017-06-01 10:38:21

    +0

    在2017年,我尝试使用Spring Boot 1.5.3,如果我在控制器上有'@ Validated',它就会正常工作。我不必添加hibernate-validators依赖项,也不需要配置'MethodValidationPostProcessor'。 – adarshr 2017-06-19 09:22:44