SpringBoot使用validation-api實作對列舉類引數校驗
前言
之前寫了一個博客是關于使用SpringBoot使用validation-api實作引數校驗,當時使用的注解都是validation-api自帶的注解只能完成對空值、長度等簡單的校驗,在我們日常的使用當中會遇到對引數是否在列舉值類的校驗,針對這種情況我們怎么來實作呢?
SpringBoot使用validation-api實作引數校驗可參考我的博客:SpringBoot使用validation-api實作引數校驗
正文
SpringBoot使用validation-api實作對列舉類引數校驗
ValidationApi框架就是用來解決引數校驗中代碼冗余問題,ValidationApi框架提供一些注解用來幫助我們對請求引數進行校驗,
Maven依賴
<!--引數校驗-->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<!--提供一些字串操作-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.2</version>
<optional>true</optional>
</dependency>
<!--knife4j介面-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>2.0.4</version>
</dependency>
EnumValidate:用于對列舉校驗的介面
/**
* 用于實作列舉類的校驗
*/
public interface EnumValidate<T> {
/**
* 校驗列舉值是否存在
*/
boolean existValidate(T value);
}
ActionTypeEnumValid:用于對列舉類校驗的自定義注解
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {ActionTypeEnumValidator.class})
@Documented
public @interface ActionTypeEnumValid {
String message() default "";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
Class<?>[] target() default {};
/**
* 允許的列舉
*
* @return
*/
Class<? extends Enum<?>> enumClass();
}
ActionTypeEnumValidator:列舉校驗器
/**
* 用于校驗ActionTypeEnumValidator
*/
public class ActionTypeEnumValidator implements ConstraintValidator<ActionTypeEnumValid,String> {
private Class<? extends Enum> enumClass;
@Override
public void initialize(ActionTypeEnumValid actionTypeEnumValid) {
enumClass = actionTypeEnumValid.enumClass();
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null || "".equals(value)) {
return true;
}
EnumValidate[] enums = (EnumValidate[]) enumClass.getEnumConstants();
if(enums ==null || enums.length == 0){
return false;
}
return enums[0].existValidate(value);
}
}
ActionTypeEnum:列舉類
@Getter
public enum ActionTypeEnum implements EnumValidate<String> {
ACTION_INVOKR("invoke", "invoke"),
UNKNOWN_ERROR("no", "no");
/**
* 狀態值
*/
private String couponType;
/**
* 狀態描述
*/
private String couponTypeDesc;
ActionTypeEnum(String couponType, String couponTypeDesc) {
this.couponType = couponType;
this.couponTypeDesc = couponTypeDesc;
}
public static String getDescByType(String couponType) {
for (ActionTypeEnum type : ActionTypeEnum.values()) {
if (type.couponType.equals(couponType) ) {
return type.couponTypeDesc;
}
}
return null;
}
/**
* 判斷是否在列舉類當中
* @param value
* @return
*/
@Override
public boolean existValidate(String value) {
if (value == null || "".equals(value)) {
return false;
}
for (ActionTypeEnum testEnum : ActionTypeEnum.values()) {
if (testEnum.getCouponType().equalsIgnoreCase(value)) {
return true;
}
}
return false;
}
public String getcouponTypeStr() {
return String.valueOf(this.couponType);
}
}
GlobalExceptionHandler:使用SpringMVC提供的例外處理機制,對ValidationApi的例外進行封裝
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
/**
* 忽略引數例外處理器
*
* @param e 忽略引數例外
* @return Response
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MissingServletRequestParameterException.class)
public ResponseResult parameterMissingExceptionHandler(MissingServletRequestParameterException e) {
log.error("引數例外", e);
return new ResponseResult(CouponTypeEnum.PARAMETER_ERROR.getcouponTypeStr(), "請求引數 " + e.getParameterName() + " 不能為空");
}
/**
* 缺少請求體例外處理器
*
* @param e 缺少請求體例外
* @return Response
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(HttpMessageNotReadableException.class)
public ResponseResult parameterBodyMissingExceptionHandler(HttpMessageNotReadableException e) {
log.error("缺少請求體例外", e);
return new ResponseResult(CouponTypeEnum.PARAMETER_ERROR.getcouponTypeStr(), "引數體不能為空");
}
/**
* 引數效驗例外處理器
*
* @param e 引數驗證例外
* @return ResponseInfo
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseResult parameterExceptionHandler(MethodArgumentNotValidException e) {
log.error("引數驗證例外", e);
// 獲取例外資訊
BindingResult exceptions = e.getBindingResult();
// 判斷例外中是否有錯誤資訊,如果存在就使用例外中的訊息,否則使用默認訊息
if (exceptions.hasErrors()) {
List<ObjectError> errors = exceptions.getAllErrors();
if (!errors.isEmpty()) {
// 這里列出了全部錯誤引數,按正常邏輯,只需要第一條錯誤即可
FieldError fieldError = (FieldError) errors.get(0);
return new ResponseResult(CouponTypeEnum.PARAMETER_ERROR.getcouponTypeStr(), fieldError.getDefaultMessage());
}
}
return new ResponseResult(CouponTypeEnum.PARAMETER_ERROR);
}
/**
* 自定義引數錯誤例外處理器
*
* @param e 自定義引數
* @return ResponseInfo
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler({BusinessException.class})
public ResponseResult paramExceptionHandler(BusinessException e) {
log.error("業務例外", e);
// 判斷例外中是否有錯誤資訊,如果存在就使用例外中的訊息,否則使用默認訊息
if (!StringUtils.isEmpty(e.getMessage())) {
return new ResponseResult(CouponTypeEnum.PARAMETER_ERROR.getcouponTypeStr(), e.getMessage());
}
return new ResponseResult(CouponTypeEnum.PARAMETER_ERROR);
}
/**
* 其他例外
*
* @param e
* @return
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler({Exception.class})
public ResponseResult otherExceptionHandler(Exception e) {
log.error("其他例外", e);
// 判斷例外中是否有錯誤資訊,如果存在就使用例外中的訊息,否則使用默認訊息
if (!StringUtils.isEmpty(e.getMessage())) {
return new ResponseResult(CouponTypeEnum.UNKNOWN_ERROR.getcouponTypeStr(), e.getMessage());
}
return new ResponseResult(CouponTypeEnum.UNKNOWN_ERROR);
}
}
驗證
請求的封裝類
/**
* 指令的封裝類
*/
@Getter
@Setter
@ToString
public class CommandPOJO implements Serializable {
private static final long serialVersionUID = -8497328408069586664L;
//指令
@NotNull(message = "指令為必填項,不得為空")
@ActionTypeEnumValid(message = "該指令暫不支持,暫時只支持invoke", enumClass = ActionTypeEnum.class)
private String action ="invoke";
}
請求介面
@Valid用于開啟請求引數校驗
@RestController
@Slf4j
@Api(value = "遠程呼叫模塊")
@RequestMapping("/xiyuanrpc")
public class RPCController {
@PostMapping("/rpcNettybyInvoke")
@ApiOperation(value = "rpc遠程呼叫")
@InvokeParameterCheck
@MethodLogPrint
public ResponseResult rpcNettybyInvoke(@Valid @RequestBody CommandPOJO pojo) {
return NettyClientUtil.rpcNetty(pojo);
}
}
通過Knife4j訪問對應介面

原始碼
專案原始碼可從的我的github中獲取:github原始碼地址

CSDN認證博客專家
Java
Redis
架構
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/199802.html
標籤:其他
上一篇:估值一億的AI核心代碼 PTA
下一篇:排序演算法
