我正在使用Spring MVC框架编写REST-API 我正在使用bean验证,如:
class Person {
@NotNull
String name;
@NotNull
String email;
@Min(0)
Integer age;
}
我正在使用Person
注释向控制器验证@Valid
:
@PostMapping
public Person create(@Valid @RequestBody Person person) {return ...;}
为了使人类可读的错误,我使用spring的顶级错误处理程序:
@ControllerAdvice
public class CustomExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody String handle(MethodArgumentNotValidException ex) {
List<String> errors = ex.getBindingResult().getFieldErrors().stream()
.map(this::buildMessage)
.collect(Collectors.toList());
return errors.toString();
}
private String buildMessage(FieldError fe) {
return fe.getField() + " " + fe.getDefaultMessage();
}
}
所以我的错误看起来像是:[name may not be null, email may not be null]
现在我需要使用将由不同UI解析的语言无关error code
来实现i18n。
有没有办法构建完整的错误代码?(包含字段名称)
我看到以下解决方案:
每次使用注释时都使用自定义消息(丑陋):
class Person {
@NotNull(message="app.error.person.name.not.null")
String name;
@NotNull(message="app.error.person.email.not.null")
String email;
@Min(0)(message="app.error.person.age.below.zero")
Integer age;
}
在我的异常处理程序中构建正确的代码(不知道如何):
private String buildMessage(FieldError fe) {
return "app.error." +
fe.getObjectName() + "." +
fe.getField() + "." +
fe.getDefaultMessage().replaceAll("\\s", "");//don't know how to connect to concrete annotation
}
所以消息就像app.error.person.name.maynotbenull
重写所有注释和验证器,通过删除默认的ConstraintViolation并添加自定义(开销)来构建正确的消息
答案 0 :(得分:1)
无需在注释中指定消息。这将是一个开销
@ControllerAdvice
public class CustomExceptionHandler {
@Autowired
MessageSource messageSource;
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody String handle(MethodArgumentNotValidException ex) {
List<String> errors = ex.getBindingResult().getFieldErrors().stream()
.map(this::buildMessage)
.collect(Collectors.toList());
return errors.toString();
}
private String buildMessage(FieldError fe) {
StringBuilder errorCode = new StringBuilder("");
String localizedErrorMsg = "";
errorCode.append("error").append(".");
errorCode.append(fe.getObjectName()).append(".");
errorCode.append(fe.getField()).append(".");
errorCode.append(fe.getCode().toLowerCase());
try {
localizedErrorMsg = this.messageSource.getMessage(errorCode,(Object[]) null, LocaleContextHolder.getLocale());
} catch (Exception ex) {
localizedErrorMsg = fe.getDefaultMessage();
}
return localizedErrorMsg;
}
}
在消息文件(i18n)中使用以下格式
error.person.name.notnull = Name must not be null
error.person.email.notnull = Email must not be null
error.person.age.min= Minimum age should greater than 0.
使用此功能,您无需在注释中编写任何消息代码。 希望这会有所帮助。