自定義註解實現引數校驗
阿新 • • 發佈:2020-12-23
技術標籤:工具方法
自定義註解實現引數校驗
一.定義註解類
/**
* 使用者驗證狀態是否在指定範圍內的註解
*/
@Documented
// JVM會讀取註解,同時會儲存到class檔案中
@Retention(RetentionPolicy.RUNTIME)
// 用於欄位或者方法引數
@Target({ElementType.FIELD,ElementType.PARAMETER})
// 指定檢驗處理類
@Constraint(validatedBy = FlagValidatorClass.class)
public @interface FlagValidator {
// 校驗引數是否在某個int 陣列中
int[] value() default {};
// 出現檢驗失敗的錯誤訊息
String message() default "flag is not found";
// 分組
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
二.定義校驗類
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
/**
* 狀態標記校驗器 校驗 FlagValidator 註解的地方
*
* ConstraintValidator<FlagValidator, Integer>
* FlagValidator : 校驗的註解
* Integer : 前端傳的值
*/
public class FlagValidatorClass implements ConstraintValidator<FlagValidator, Integer> {
private int[] values;
// 初始化方法
@Override
public void initialize(FlagValidator flagValidator) {
// 獲取到 設定了 FlagValidator 註解引數中的 value 範圍
this.values = flagValidator.value();
}
// 校驗
@Override
public boolean isValid(Integer value, ConstraintValidatorContext constraintValidatorContext) {
boolean isValid = false;
// 如果引數沒有傳值則預設是true, 不做檢驗
if(value==null){
//當狀態為空時使用預設值
return true;
}
// 否則遍歷改引數的 value 看引數值是否在範圍內
for (int item : values) {
if (item == value) {
isValid = true;
break;
}
}
return isValid;
}
}
三.統一異常處理
//如果返回的為json資料或其它物件,新增該註解
@RestControllerAdvice
//@ControllerAdvice
public class GlobalExceptionHandler {
/**
* 前端引數提交是json格式時校驗丟擲的異常
* json格式提交時,採用json資料的資料轉換器進行處理,錯誤時丟擲MethodArgumentNotValidException異常
*/
// 攔截對應的異常
@ExceptionHandler(MethodArgumentNotValidException.class)
// 指明 400 異常碼
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Result handlerNotValidException(MethodArgumentNotValidException exception) throws Exception {
return handlerNotValidException(exception);
}
/**
* 僅對於表單提交有效
* 如果是表單型別的提交,進行引數校驗錯誤時會丟擲BindException異常
*/
// 攔截對應的異常
@ExceptionHandler(BindException.class)
// 指明 400 異常碼
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Result handlerBindException(BindException exception) {
return handlerNotValidException(exception);
}
private ResultDTO handlerNotValidException(Exception e){
BindingResult result;
if (e instanceof BindException) {
BindException exception = (BindException) e;
// 獲取驗證失敗的結果
result = exception.getBindingResult();
} else {
MethodArgumentNotValidException exception = (MethodArgumentNotValidException) e;
// 獲取驗證失敗的結果
result = exception.getBindingResult();
}
StringBuilder errorMsg =new StringBuilder("校驗失敗:");
for (FieldError fieldError : result.getFieldErrors()) {
errorMsg.append(fieldError.getDefaultMessage()).append(", ");
}
// 這裡自定義了一個異常碼的列舉,其實值就是一個狀態碼字串
//return Result.fail(CoreConstants.E_PARAMETER,errorMsg.toString());
return Result.fail("5002",errorMsg.toString());
}
}
其中Result是返給前端的封裝類
public class Result<T extends Object>{
private static final long serialVersionUID = -7387542509934814087L;
// 成功標誌
private boolean success;
// 狀態碼
private String code;
// 異常訊息
private String message;
// 資料
private T data;
// xxx 這裡一些方法省略寫了
public static ResultDTO fail(String code, String msg) {
ResultDTO result = new ResultDTO(false, null,code, msg);
return result;
}
public ResultDTO(boolean success, Object data, String code, String message) {
this.data = (T) data;
this.success = success;
this.code = code;
this.message = message;
}
}
四.效果圖
這裡的message格式可以根據自己的需求進行改造