Jaa*_*tum 10 validation spring spring-mvc spring-boot spring-restcontroller
当我有以下模型与JSR-303(验证框架)注释:
public enum Gender {
MALE, FEMALE
}
public class Profile {
private Gender gender;
@NotNull
private String name;
...
}
Run Code Online (Sandbox Code Playgroud)
以及以下JSON数据:
{ "gender":"INVALID_INPUT" }
Run Code Online (Sandbox Code Playgroud)
在我的REST控制器中,我想处理绑定错误(gender
属性的无效枚举值)和验证错误(name
属性不能为null).
以下控制器方法不起作用:
@RequestMapping(method = RequestMethod.POST)
public Profile insert(@Validated @RequestBody Profile profile, BindingResult result) {
...
}
Run Code Online (Sandbox Code Playgroud)
这会com.fasterxml.jackson.databind.exc.InvalidFormatException
在绑定或验证发生之前产生序列化错误.
经过一番摆弄后,我想出了这个自定义代码,它可以满足我的需求:
@RequestMapping(method = RequestMethod.POST)
public Profile insert(@RequestBody Map values) throws BindException {
Profile profile = new Profile();
DataBinder binder = new DataBinder(profile);
binder.bind(new MutablePropertyValues(values));
// validator is instance of LocalValidatorFactoryBean class
binder.setValidator(validator);
binder.validate();
// throws BindException if there are binding/validation
// errors, exception is handled using @ControllerAdvice.
binder.close();
// No binding/validation errors, profile is populated
// with request values.
...
}
Run Code Online (Sandbox Code Playgroud)
基本上这个代码的作用是序列化为通用映射而不是模型,然后使用自定义代码绑定到模型并检查错误.
我有以下问题:
@Validated
注释如何工作?如何创建自己的自定义注释,@Validated
以便封装我的自定义绑定代码?通常当 Spring MVC 无法读取 http 消息(例如请求正文)时,它会抛出一个HttpMessageNotReadableException
异常实例。因此,如果 spring 无法绑定到您的模型,它应该抛出该异常。此外,如果您没有BindingResult
在方法参数中定义每个待验证模型之后,则在验证错误的情况下,spring 将抛出MethodArgumentNotValidException
异常。有了这一切,您可以创建ControllerAdvice
捕获这两个异常并以您想要的方式处理它们。
@ControllerAdvice(annotations = {RestController.class})
public class UncaughtExceptionsControllerAdvice {
@ExceptionHandler({MethodArgumentNotValidException.class, HttpMessageNotReadableException.class})
public ResponseEntity handleBindingErrors(Exception ex) {
// do whatever you want with the exceptions
}
}
Run Code Online (Sandbox Code Playgroud)
这是我在一个项目中用于在春季启动时验证REST api的代码,这与您的要求不同,但是相同。
@RequestMapping(value = "/person/{id}",method = RequestMethod.PUT)
@ResponseBody
public Object updatePerson(@PathVariable Long id,@Valid Person p,BindingResult bindingResult){
if (bindingResult.hasErrors()) {
List<FieldError> errors = bindingResult.getFieldErrors();
List<String> message = new ArrayList<>();
error.setCode(-2);
for (FieldError e : errors){
message.add("@" + e.getField().toUpperCase() + ":" + e.getDefaultMessage());
}
error.setMessage("Update Failed");
error.setCause(message.toString());
return error;
}
else
{
Person person = personRepository.findOne(id);
person = p;
personRepository.save(person);
success.setMessage("Updated Successfully");
success.setCode(2);
return success;
}
Run Code Online (Sandbox Code Playgroud)
成功.java
public class Success {
int code;
String message;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
Run Code Online (Sandbox Code Playgroud)
错误.java
public class Error {
int code;
String message;
String cause;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getCause() {
return cause;
}
public void setCause(String cause) {
this.cause = cause;
}
}
Run Code Online (Sandbox Code Playgroud)
您也可以在这里看看:Spring REST Validation
你不能用@RequestBody 得到 BindException。不在带有Errors
方法参数的控制器中,如此处所述:
Errors, BindingResult用于访问来自命令对象(即@ModelAttribute 参数)的验证和数据绑定的错误或来自@RequestBody 或@RequestPart 参数的验证的错误。您必须在经过验证的方法参数之后立即声明 Errors 或 BindingResult 参数。
它指出,@ModelAttribute
您会收到绑定和验证错误,而您只会@RequestBody
收到验证错误。
https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-methods
并在这里讨论:
对我来说,从用户的角度来看,这仍然没有意义。获取 BindExceptions 以向用户显示正确的错误消息通常非常重要。论点是,无论如何您都应该进行客户端验证。但如果开发人员直接使用 API,则情况并非如此。
假设您的客户端验证基于 API 请求。您想根据保存的日历检查给定日期是否有效。您将日期和时间发送到后端,但它失败了。
您可以使用 ExceptionHANdler 对 HttpMessageNotReadableException 做出反应来修改您获得的异常,但由于此异常,我无法像 BindException 那样正确访问哪个字段引发错误。我需要解析异常消息才能访问它。
所以我没有看到任何解决方案,这有点糟糕,因为@ModelAttribute
它很容易出现绑定和验证错误。
归档时间: |
|
查看次数: |
32132 次 |
最近记录: |