1、前提
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
2、直接校验,返回系统给你的错误信息
- 从前端传来的封装对象,该对象的
bean
(BrandEntity 为例)属性你添加了校验注解(@NotNull
,@NotEmpty
等)。 @Valid
标注在controller
里面的请求体,告诉spring该实体类的属性需要校验,那么一旦校验不通过就会返回错误信息给前端
@RequestMapping("/save")
public R save(@Valid @RequestBody BrandEntity brand ){
3、利用BindingResult
@RequestMapping("/save")
public R save(@Valid @RequestBody BrandEntity brand , BindingResult result){
BindingResult
里面就封装的对应实体类的校验结果BindingResult
public interface BindingResult extends Errors {
String MODEL_KEY_PREFIX = BindingResult.class.getName() + ".";
@Nullable
Object getTarget();
Map<String, Object> getModel();
@Nullable
Object getRawFieldValue(String var1);
@Nullable
PropertyEditor findEditor(@Nullable String var1, @Nullable Class<?> var2);
@Nullable
PropertyEditorRegistry getPropertyEditorRegistry();
String[] resolveMessageCodes(String var1);
String[] resolveMessageCodes(String var1, String var2);
void addError(ObjectError var1);
default void recordFieldValue(String field, Class<?> type, @Nullable Object value) {
}
default void recordSuppressedField(String field) {
}
default String[] getSuppressedFields() {
return new String[0];
}
}
public interface Errors {
String NESTED_PATH_SEPARATOR = ".";
String getObjectName();
void setNestedPath(String var1);
String getNestedPath();
void pushNestedPath(String var1);
void popNestedPath() throws IllegalStateException;
void reject(String var1);
void reject(String var1, String var2);
void reject(String var1, @Nullable Object[] var2, @Nullable String var3);
void rejectValue(@Nullable String var1, String var2);
void rejectValue(@Nullable String var1, String var2, String var3);
void rejectValue(@Nullable String var1, String var2, @Nullable Object[] var3, @Nullable String var4);
void addAllErrors(Errors var1);
boolean hasErrors();
int getErrorCount();
List<ObjectError> getAllErrors();
boolean hasGlobalErrors();
int getGlobalErrorCount();
List<ObjectError> getGlobalErrors();
@Nullable
ObjectError getGlobalError();
boolean hasFieldErrors();
int getFieldErrorCount();
List<FieldError> getFieldErrors();
@Nullable
FieldError getFieldError();
boolean hasFieldErrors(String var1);
int getFieldErrorCount(String var1);
List<FieldError> getFieldErrors(String var1);
@Nullable
FieldError getFieldError(String var1);
@Nullable
Object getFieldValue(String var1);
@Nullable
Class<?> getFieldType(String var1);
}
- 再次封装成自己想返回的数据
R
是我另外一篇文章用来做封装给前端数据的示例R示例
if (result.hasErrors()){
Map<String,String> map = new HashMap<>();
result.getFieldErrors().forEach((item)->{
String message = item.getDefaultMessage();
String field = item.getField();
map.put(field,message);
});
return R.error(400,"提交数据不合法").put("data",map);
}
4、集中处理
- 统一异常处理,利用SpringMVC提供的
ControllerAdvice
- 抽取处理异常的类
ExcExceptionControllerAdvice
@RestControllerAdvice 的basePackages
指定你需要处理的controller@ExceptionHandler(value = MethodArgumentNotValidException.class)
value :你需要处理什么样的异常
@Slf4j
@RestControllerAdvice(basePackages = "")
public class ExcExceptionControllerAdvice {
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public R handleValidException(MethodArgumentNotValidException e){
log.error("数据校验出现问题{},异常类型,{}",e.getMessage(),e.getClass());
BindingResult bindingResult = e.getBindingResult();
Map<String,String> map = new HashMap<>();
bindingResult.getFieldErrors().forEach((fieldError)->{
map.put(fieldError.getField(),fieldError.getDefaultMessage());
});
return R.error(BizCodeEnume.VAILD_EXCEPTION.getCode(),BizCodeEnume.VAILD_EXCEPTION.getMsg()).put("data",map);
}
@ExceptionHandler(value = Throwable.class)
public R handleException(Throwable throwable){
log.error("错误:" + throwable);
return R.error(BizCodeEnume.UNKNOW_EXCEPTION.getCode(),BizCodeEnume.UNKNOW_EXCEPTION.getMsg());
}
}
- 在使用该集中处理的时候,必须要controller抛出异常,所以在请求参数中去掉
BindingResult
那么处理类中就会感知到异常。
@RequestMapping("/save")
public R save(@Valid @RequestBody BrandEntity brand){
public enum BizCodeEnume {
UNKNOW_EXCEPTION(10000,"系统未知异常"),
VAILD_EXCEPTION(10001,"参数格式检验失败");
private int code;
private String msg;
BizCodeEnume(int code, String msg) {
this.code = code;
this.msg = msg;
}
public String getMsg() {
return msg;
}
public int getCode() {
return code;
}
}
5、增强(JSR303分组校验)
public @interface NotBlank {
String message() default "{javax.validation.constraints.NotBlank.message}";
Class<?>[] groups() default {};
public interface AddGroup {
}
@NotBlank(groups = AddGroup.class)
private String brandName;
- 并在对应方法中写明,那么该名字就只会在
save
方法的时候校验 @Validated
与上面没用分组的@Valid
不一样,这里需要注意
@RequestMapping("/save")
public R save(@Validated({ AddGroup.class }) @RequestBody BrandEntity brand ){/