SpringBoot使用validation-api实现对枚举类参数校验
创始人
2024-11-18 06:01:18
0次

SpringBoot使用validation-api实现对枚举类参数校验

ValidationApi框架就是用来解决参数校验中代码冗余问题,ValidationApi框架提供一些注解用来帮助我们对请求参数进行校验。

Maven依赖



 javax.validation
 validation-api
 2.0.1.Final





 org.apache.commons
 commons-lang3
 3.3.2





 org.projectlombok
 lombok
 1.18.2
 true





 com.github.xiaoymin
 knife4j-spring-boot-starter
 2.0.4

EnumValidate:用于对枚举校验的接口

/**
* 用于实现枚举类的校验
*/
public interface EnumValidate {

 /**
  * 校验枚举值是否存在
  */
 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 {


 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 {


 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 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访问对应接口

SpringBoot使用validation-api实现对枚举类参数校验

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...