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

作者:溪源的奇思妙想 时间:2021-09-22 19:21:32 

前言

之前写了一个博客是关于使用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访问对应接口

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

源码

项目源码可从的我的github中获取:github源码地址

来源:https://blog.csdn.net/weixin_40990818/article/details/109434581

标签:SpringBoot,validation-api,参数校验
0
投稿

猜你喜欢

  • SpringBoot整合Mybatis,解决TypeAliases配置失败的问题

    2023-11-28 14:59:24
  • 50 道Java 线程面试题(经典)

    2023-11-23 19:47:37
  • Java 开启多线程常见的4种方法

    2023-11-23 02:30:10
  • springboot异常处理的基本规范

    2023-11-23 15:48:19
  • 详解java 中Spring jsonp 跨域请求的实例

    2023-11-19 02:48:18
  • 基于Java数组实现循环队列的两种方法小结

    2023-06-30 16:09:01
  • springboot返回图片流的实现示例

    2023-11-23 17:30:08
  • Android WindowManger实现桌面悬浮窗功能

    2023-08-01 02:16:10
  • android TextView实现跑马灯效果

    2023-07-27 16:35:31
  • Java设计模式之备忘录模式

    2023-08-24 06:17:05
  • java中Class.forName的作用浅谈

    2023-11-11 12:30:26
  • Spring MVC接口防数据篡改和重复提交

    2023-11-29 15:02:11
  • Java中BigDecimal的舍入模式解析(RoundingMode)

    2021-10-16 15:28:16
  • Java应用多机器部署解决大量定时任务问题

    2023-10-28 17:07:17
  • Java多线程之ThreadLocal原理总结

    2023-11-02 22:58:36
  • VS2019配置opencv详细图文教程和测试代码的实现

    2023-07-17 13:49:31
  • Java读取.properties配置文件方法示例

    2023-08-24 16:32:56
  • ReadWriteLock接口及其实现ReentrantReadWriteLock方法

    2023-11-24 01:46:52
  • 使用开源项目JAVAE2 进行视频格式转换

    2023-11-08 07:18:24
  • Jaxb2实现JavaBean与xml互转的方法详解

    2023-11-25 11:51:38
  • asp之家 软件编程 m.aspxhome.com