如何验证 Spring MVC @PathVariable 值?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19419234/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to validate Spring MVC @PathVariable values?
提问by Grover
For a simple RESTful JSON api implemented in Spring MVC, can I use Bean Validation (JSR-303) to validate the path variables passed into the handler method?
对于在 Spring MVC 中实现的简单 RESTful JSON api,我可以使用 Bean Validation (JSR-303) 来验证传递给处理程序方法的路径变量吗?
For example:
例如:
@RequestMapping(value = "/number/{customerNumber}")
@ResponseBody
public ResponseObject searchByNumber(@PathVariable("customerNumber") String customerNumber) {
...
}
Here, I need to validate the customerNumber variables's length using Bean validation. Is this possible with Spring MVC v3.x.x? If not, what's the best approach for this type of validations?
在这里,我需要使用 Bean 验证来验证 customerNumber 变量的长度。Spring MVC v3.xx 可以做到这一点吗?如果没有,这种类型的验证的最佳方法是什么?
Thanks.
谢谢。
回答by Sotirios Delimanolis
Spring does not support @javax.validation.Validon @PathVariableannotated parameters in handler methods. There was an Improvement request, but it is still unresolved.
Spring不支持@javax.validation.Valid对@PathVariable在处理注释的方法参数。有一个改进请求,但仍未解决。
Your best bet is to just do your custom validation in the handler method body or consider using org.springframework.validation.annotation.Validatedas suggested in other answers.
最好的办法是在处理程序方法主体中进行自定义验证,或者考虑org.springframework.validation.annotation.Validated按照其他答案中的建议使用。
回答by BeeNoisy
You can use like this:
use org.springframework.validation.annotation.Validatedto valid RequestParamor PathVariable.
您可以这样使用:用于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.
*
step.1 init ValidationConfig
step.1 初始化 ValidationConfig
@Configuration
public class ValidationConfig {
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
MethodValidationPostProcessor processor = new MethodValidationPostProcessor();
return processor;
}
}
step.2 Add @Validatedto your controller handler class, Like:
step.2 添加@Validated到您的控制器处理程序类,例如:
@RequestMapping(value = "poo/foo")
@Validated
public class FooController {
...
}
step.3 Add validatorsto your handler method:
step.3 添加validators到您的处理程序方法:
@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);
}
final step. Add exception resolver to your context:
最后一步。将异常解析器添加到您的上下文中:
@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 MappingHymanson2JsonView(), buildErrorModel(request, response, fieldErrors));
}
}
}
回答by Gábor Dani
The solution is simple:
解决方法很简单:
@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}"
}
And yes, PathVariables are ment to be validated, like any user input.
是的,PathVariables 需要验证,就像任何用户输入一样。
回答by Hamid Mohayeji
Instead of using @PathVariable, you can take advantage of Spring MVC ability to map path variables into a bean:
您可以利用 Spring MVC 将路径变量映射到 bean 中,而不是使用 @PathVariable:
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/{id}")
public void get(@Valid GetDto dto) {
// dto.getId() is the path variable
}
}
And the bean contains the actual validation rules:
bean 包含实际的验证规则:
@Data
public class GetDto {
@Min(1) @Max(99)
private long id;
}
Make sure that your path variables ({id}) correspond to the bean fields (id);
确保您的路径变量 ( {id}) 对应于 bean 字段 ( id);
回答by pdenti
@PathVariableis not meant to be validated in order to send back a readable message to the user. As principle a pathVariable should never be invalid. If a pathVariable is invalid the reason can be:
@PathVariable并不意味着为了向用户发回可读消息而进行验证。作为原则,pathVariable 永远不应该是无效的。如果 pathVariable 无效,原因可能是:
- a bug generated a bad url (an href in jsp for example). No
@Validis needed and no message is needed, just fix the code; - "the user" is manipulating the url.
Again, no
@Validis needed, no meaningful message to the user should be given.
- 一个错误生成了一个错误的 url(例如,jsp 中的一个 href)。不需要
@Valid也不需要消息,只需修复代码; - “用户”正在操纵网址。同样,
@Valid不需要,不应向用户提供任何有意义的消息。
In both cases just leave an exception bubble up until it is catched by the usual Spring ExceptionHandlers in order to generate a nice error page or a meaningful json response indicating the error. In order to get this result you can do some validation using custom editors.
在这两种情况下,只留下一个异常冒泡,直到它被通常的 Spring ExceptionHandlers 捕获,以生成一个很好的错误页面或一个有意义的 json 响应来指示错误。为了获得此结果,您可以使用自定义编辑器进行一些验证。
Create a CustomerNumberclass, possibly as immutable (implementing a CharSequenceis not needed but allows you to use it basically as if it were a String)
创建一个CustomerNumber类,可能是不可变的(CharSequence不需要实现 a但允许您基本上像使用 a 一样使用它String)
public class CustomerNumber implements CharSequence {
private String customerNumber;
public CustomerNumber(String customerNumber) {
this.customerNumber = customerNumber;
}
@Override
public String toString() {
return customerNumber == null ? null : customerNumber.toString();
}
@Override
public int length() {
return customerNumber.length();
}
@Override
public char charAt(int index) {
return customerNumber.charAt(index);
}
@Override
public CharSequence subSequence(int start, int end) {
return customerNumber.subSequence(start, end);
}
@Override
public boolean equals(Object obj) {
return customerNumber.equals(obj);
}
@Override
public int hashCode() {
return customerNumber.hashCode();
}
}
Create an editor implementing your validation logic (in this case no whitespaces and fixed length, just as an example)
创建一个实现验证逻辑的编辑器(在这种情况下,没有空格和固定长度,仅作为示例)
public class CustomerNumberEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
if (StringUtils.hasText(text) && !StringUtils.containsWhitespace(text) && text.length() == YOUR_LENGTH) {
setValue(new CustomerNumber(text));
} else {
throw new IllegalArgumentException();
// you could also subclass and throw IllegalArgumentException
// in order to manage a more detailed error message
}
}
@Override
public String getAsText() {
return ((CustomerNumber) this.getValue()).toString();
}
}
Register the editor in the Controller
在控制器中注册编辑器
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(CustomerNumber.class, new CustomerNumberEditor());
// ... other editors
}
Change the signature of your controller method accepting CustomerNumberinstead of String(whatever your ResponseObjectis ...)
更改您的控制器方法的签名,CustomerNumber而不是接受String(无论您ResponseObject是......)
@RequestMapping(value = "/number/{customerNumber}")
@ResponseBody
public ResponseObject searchByNumber(@PathVariable("customerNumber") CustomerNumber customerNumber) {
...
}
回答by mvb13
Path variable may not be linked with any bean in your system. What do you want to annotate with JSR-303 annotations? To validate path variable you should use this approach Problem validating @PathVariable url on spring 3 mvc
路径变量可能不会与您系统中的任何 bean 链接。你想用 JSR-303 注释来注释什么?要验证路径变量,您应该使用这种方法在 spring 3 mvc 上验证 @PathVariable url 问题

