How to deal with parameter verification exceptions from the front end in SpringBoot

1. Prerequisite

  • Import dependencies
	 <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>2.0.1.Final</version>
        </dependency>

2. Check directly and return the error message given to you by the system

  • The encapsulated object passed from the front end, the attributes of the object bean(BrandEntity as an example) you have added validation annotations ( @NotNull, @NotEmptyetc.).
  • @ValidcontrollerThe request body marked inside tells Spring that the attributes of the entity class need to be verified, and then once the verification fails, an error message will be returned to the front end
    @RequestMapping("/save")
    public R save(@Valid @RequestBody BrandEntity brand ){
    
    

3, use BindingResult

  @RequestMapping("/save")
    public R save(@Valid @RequestBody BrandEntity brand , BindingResult result){
    
    
  • BindingResultThe verification result of the corresponding entity class encapsulated inside
  • 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];
    }
}

  • It inherits fromErrors
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);
}
  • Package again into the data you want to return
  • RIt is another example of my article used to encapsulate the front-end data. R example
        if (result.hasErrors()){
    
    
            // 获取错误结果
            Map<String,String> map = new HashMap<>();
            result.getFieldErrors().forEach((item)->{
    
    
                // FieldError 获取错误提示
                String message = item.getDefaultMessage();
                String field = item.getField();
                map.put(field,message);
            });
           return R.error(400,"提交数据不合法").put("data",map);
        }

4. Centralized processing

  • Unified exception handling, using SpringMVC providedControllerAdvice
  • Extract classes that handle exceptions ExcExceptionControllerAdvice
  • @RestControllerAdvice 的basePackagesSpecify the controller you need to handle
  • @ExceptionHandler(value = MethodArgumentNotValidException.class) value: what kind of exception you need to handle
@Slf4j
//@ControllerAdvice(basePackages = "")
@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());
    }
}
  • When using this centralized processing, the controller must throw an exception, so if you remove it from the request parameter, the BindingResultexception will be sensed in the processing class.
  @RequestMapping("/save")
    public R save(@Valid @RequestBody BrandEntity brand){
    
    
  • Canonical system error code
/**
	错误码和错误信息定义类
	1 错误码定义规则为5个数字
	2 前两位代表错误场景,后三位代码错误码,例如10001.10代表通用,001系统异常
	3 维护错误码后需要维护错误描述,将他们定义为枚举形式
*/
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. Enhanced (JSR303 packet check)

public @interface NotBlank {
    
    
    String message() default "{javax.validation.constraints.NotBlank.message}";
    Class<?>[] groups() default {
    
    };
  • So we define an interface as a logo, without doing anything
  • E.g
public interface AddGroup {
    
    
}

  • Mark above the comment
	@NotBlank(groups = AddGroup.class)
	private String brandName;
  • And write it in the corresponding method, then the name will only be saveverified at the time of the method
  • @ValidatedIt is different from the above useless grouping @Valid, here you need to pay attention
    @RequestMapping("/save")
    public R save(@Validated({
    
     AddGroup.class }) @RequestBody BrandEntity brand ){
    
    /

Guess you like

Origin blog.csdn.net/JISOOLUO/article/details/105584217