如何验证Spring MVC@PathVariable值?

如何验证Spring MVC@PathVariable值?,spring,validation,spring-mvc,Spring,Validation,Spring Mvc,对于在SpringMVC中实现的简单RESTfulJSONAPI,我可以使用Bean验证(JSR-303)来验证传递到处理程序方法中的路径变量吗 例如: @RequestMapping(value = "/number/{customerNumber}") @ResponseBody public ResponseObject searchByNumber(@PathVariable("customerNumber") String customerNumber) { ... } 这

对于在SpringMVC中实现的简单RESTfulJSONAPI,我可以使用Bean验证(JSR-303)来验证传递到处理程序方法中的路径变量吗

例如:

 @RequestMapping(value = "/number/{customerNumber}")
 @ResponseBody
 public ResponseObject searchByNumber(@PathVariable("customerNumber") String customerNumber) {
 ...
 }
这里,我需要使用Bean验证来验证customerNumber变量的长度。SpringMVCv3.x.x是否可以实现这一点?如果不是,这种验证的最佳方法是什么


谢谢。

路径变量可能未与系统中的任何bean链接。您想用JSR-303注释什么?
要验证路径变量,您应该使用这种方法

Spring不支持
@javax.validation。在处理程序方法中的
@PathVariable
注释参数上有效。有一个改进请求,但仍然是


<>您最好是在处理程序方法体中进行自定义验证,或者考虑使用“代码> > org .prgFrrask.Suff.Engult.Actudio.Engult/Engule>按照其他答案建议。

<代码> @ PortValue不应被验证,以便向用户发送可读消息。原则上,pathVariable不应无效。如果pathVariable无效,原因可能是:

  • 一个bug生成了一个错误的url(例如jsp中的href)。没有
    @有效的
    
    需要,无需消息,只需修复代码
    
  • “用户”正在操纵url。 同样,不需要
    @Valid
    ,也不需要向用户发送任何有意义的消息 被给予
  • 在这两种情况下,只需留下一个异常气泡,直到它被 通常使用Spring ExceptionHandler来生成 错误页面或指示错误的有意义的json响应。在里面 为了得到这个结果,您可以使用自定义编辑器进行一些验证

    创建一个
    CustomerNumber
    类,可能是不可变的(不需要实现
    CharSequence
    ,但允许您基本上像使用
    字符串一样使用它)

    创建一个实现验证逻辑的编辑器(在本例中,没有空格和固定长度,仅作为示例)

    在控制器中注册编辑器

    @InitBinder
    public void initBinder(WebDataBinder binder) {
    
        binder.registerCustomEditor(CustomerNumber.class, new CustomerNumberEditor());
        // ... other editors
    }
    
    更改接受
    CustomerNumber
    而不是
    String
    的控制器方法的签名(无论
    响应对象是什么…)

    您可以这样使用: 使用
    org.springframework.validation.annotation.Validated
    来验证
    RequestParam
    PathVariable

     *
     * Variant of JSR-303's {@link javax.validation.Valid}, supporting the
     * specification of validation groups. Designed for convenient use with
     * Spring's JSR-303 support but not JSR-303 specific.
     *
    
    步骤1初始化
    ValidationConfig

    @Configuration
    public class ValidationConfig {
        @Bean
        public MethodValidationPostProcessor methodValidationPostProcessor() {
            MethodValidationPostProcessor processor = new MethodValidationPostProcessor();
            return processor;
        }
    }
    
    步骤2将
    @Validated
    添加到控制器处理程序类,如:

    @RequestMapping(value = "poo/foo")
    @Validated
    public class FooController {
    ...
    }
    
    步骤3将
    验证器添加到处理程序方法中:

       @RequestMapping(value = "{id}", method = RequestMethod.DELETE)
       public ResponseEntity<Foo> delete(
               @PathVariable("id") @Size(min = 1) @CustomerValidator int id) throws RestException {
            // do something
            return new ResponseEntity(HttpStatus.OK);
        }
    
    @RequestMapping(value=“{id}”,method=RequestMethod.DELETE)
    公共响应删除(
    @PathVariable(“id”)@Size(min=1)@CustomerValidator int id)引发RestException{
    //做点什么
    返回新的响应状态(HttpStatus.OK);
    }
    
    最后一步。将异常解析程序添加到您的上下文:

    @Component
    public class BindExceptionResolver implements HandlerExceptionResolver {
    
        @Override
        public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
            if (ex.getClass().equals(BindException.class)) {
                BindException exception = (BindException) ex;
    
                List<FieldError> fieldErrors = exception.getFieldErrors();
                return new ModelAndView(new MappingJackson2JsonView(), buildErrorModel(request, response, fieldErrors));
            }
        }
    }
    
    @组件
    公共类BindExceptionResolver实现HandlerExceptionResolver{
    @凌驾
    公共ModelAndView resolveException(HttpServletRequest请求、HttpServletResponse响应、对象处理程序、异常示例){
    if(例如getClass().equals(BindException.class)){
    BindException=(BindException)ex;
    List fieldErrors=exception.getFieldErrors();
    返回新的ModelAndView(新的MappingJackson2JsonView(),buildErrorModel(请求、响应、字段错误));
    }
    }
    }
    
    解决方案很简单:

    @GetMapping(value = {"/", "/{hash:[a-fA-F0-9]{40}}"})
    public String request(@PathVariable(value = "hash", required = false) String historyHash)
    {
        // Accepted requests: either "/" or "/{40 character long hash}"
    }
    

    是的,与任何用户输入一样,路径变量也需要验证。

    您可以利用Spring MVC将路径变量映射到bean中,而不是使用@PathVariable:

    @RestController
    @RequestMapping("/user")
    public class UserController {
    
        @GetMapping("/{id}")
        public void get(@Valid GetDto dto) {
            // dto.getId() is the path variable
        }
    
    }
    
    bean包含实际的验证规则:

    @Data
    public class GetDto {
         @Min(1) @Max(99)
         private long id;
    }
    

    确保路径变量(
    {id}
    )对应于bean字段(
    id

    您给出的链接说:“如果PathVariable参数验证失败,那么Spring会自动将错误添加到请求的BindingResult中,您不需要自己这么做。”这是否意味着可以对@PathVariable参数进行bean验证?它没有明确说明这是否可能。可能是我误解了。我已经按照建议的方法进行了尝试,但是当验证失败时,绑定结果没有任何错误。使用相同方法的Blogpost这里的关键是在
    WebMvc上下文中显式添加
    MethodValidationPostProcessor
    ,即使它已经在
    根上下文中定义了。这将返回404而不是400我想这就是OP想要的。
    
    @GetMapping(value = {"/", "/{hash:[a-fA-F0-9]{40}}"})
    public String request(@PathVariable(value = "hash", required = false) String historyHash)
    {
        // Accepted requests: either "/" or "/{40 character long hash}"
    }
    
    @RestController
    @RequestMapping("/user")
    public class UserController {
    
        @GetMapping("/{id}")
        public void get(@Valid GetDto dto) {
            // dto.getId() is the path variable
        }
    
    }
    
    @Data
    public class GetDto {
         @Min(1) @Max(99)
         private long id;
    }