当前位置: 首页 > news >正文

Spring Boot 参数验证

在日常的开发过程之中,前端都是调用 API 接口,访问后端接口,后端接收到请求,进行业务处理的起点,一定是 ”参数验证“,这也是保证系统健壮性的必要条件。

一、 快速上手

比如我们现在的业务场景是:用户建立项目,项目必须要关联负责人,请求参数示例如下:

@Data
public class ProjectReq {private Long id;private String name;private UserReq groupReq;
}
@Data
public class UserReq {private Long id;private String role;
}

现在所有的字段都是必填的,后端验证的时候,可能会写大部分的 if 判断,进行验证,这样写当然没有问题,但是如果说增加了字段,需要同步在自定义方法中补充对应的验证规则。并且排查问题较为麻烦,需要核对每个字段,是否都在自定义的验证方法之中存在。

在 JDK 内部实际上已经存在这样的验证体系,可以替换大部分场景之下的自定义验证规则,这也是:JSR-303 规范。用来实现这个规范的实际上是:hibernate-validator。

不过在 Spring Boot 的验证包中,已经引入了这个依赖,这里我直接导入 Spring Boot 的验证包

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId>
</dependency>
@PostMapping("/create")
public Result<Void> createUser(@Valid @RequestBody ProjectReq projectReq, BindingResult bindingResult) {if (bindingResult.hasFieldErrors()) {String defaultMessage = bindingResult.getFieldError().getDefaultMessage();return Result.error(500, defaultMessage);}log.info("---> {}", projectReq);return new Result<>();
}
import javax.validation.Valid;
import javax.validation.constraints.NotNull;@Data
public class ProjectReq {@NotNull(message = "用户 ID 不能为空")private Long id;@NotNull(message = "用户名称不能为空")private String name;@Valid@NotNull(message = "user Req 不能为空")private UserReq userReq;
}

但是这样做,对于每个接口都进行验证,较为复杂,我们可以通过接入全局异常拦截器进行处理,例如:

@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {@ExceptionHandler(MethodArgumentNotValidException.class)public Result<Void> MethodArgumentNotValidException(MethodArgumentNotValidException ex) {BindingResult bindingResult = ex.getBindingResult();FieldError fieldError = bindingResult.getFieldError();String errorDefaultMessage = fieldError.getDefaultMessage();return Result.error(500 ,errorDefaultMessage);}}

通过这样实现,我们就可以替换原有一大部分的非空,格式不正确验证。

二、常用注解

2.1 字符串类

注解 判断
@NotBlank 不能为空,也不能是空字符串
@NotEmpty 不能为空,可以是空字符串
@Size 判断字符串的长度
@Pattern 正则表达式验证

2.2 数字类

注解 判断
@Min 最小值,如果是 null ,不进行验证
@Max 最大值
@Positive 只能是正数
@PositiveOrZero 不能是非负数

2.1 集合类

注解 判断
@NotEmpty 集合不能为空,这里包含集合是 null 和 空集合两种情况
@Size 判断集合的长度, @Size(min = 2, max = 3) 集合的最小数量是 2,最大数量是 3

三、自定义验证注解

在日常的开发之中,对于前端传递的参数,如果值是一个枚举值,为防止恶意参数,需要对参数验证,满足业务需求。

这里首先定义一个接口,用来做验证

public interface ArrayValuable<T> {T[] array();
}
@Getter
@AllArgsConstructor
public enum ProjectStatusEnum implements ArrayValuable<String>{running("running", "运行中"),stop("stop", "停止");private final String code;private final String desc;public static final String[] ARRAYS = Arrays.stream(values()).map(ProjectStatusEnum::getCode).toArray(String[]::new);@Overridepublic String[] array() {return ARRAYS;}
}

接下来,我们创建自定义注解,加在字段上面,就可以快速的实现枚举类型参数的快速验证

@Documented
@Retention(value = RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE
})
@Constraint(validatedBy = EnumParamValidator.class)
public @interface InEnum {/*** 枚举,标识当前值的可选值*/Class<? extends ArrayValuable<?>> value();/*** 分组*/Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};/*** 错误提示*/String message() default "当前传递值不在可选范围内";
}

创建一个:ConstraintValidator 类型的验证器,用来进行实际的验证逻辑

public class EnumParamValidator implements ConstraintValidator<InEnum, Object> {private List<Object> values = new ArrayList<>();@Overridepublic void initialize(InEnum constraintAnnotation) {ArrayValuable<?>[] enumConstants = constraintAnnotation.value().getEnumConstants();if (enumConstants.length == 0) {this.values = Collections.emptyList();} else {this.values = Arrays.asList(enumConstants[0].array());}}@Overridepublic boolean isValid(Object prepareValidParam, ConstraintValidatorContext constraintValidatorContext) {if (CollectionUtils.isEmpty(values)) {return true;}return values.contains(prepareValidParam);}
}
http://www.jsqmd.com/news/437122/

相关文章:

  • RAG-01-假设性问题索引
  • 2026年3月非标定制焊管厂家推荐,按需定制与特殊规格实力厂家 - 品牌鉴赏师
  • 2026年3月饮料灌装机厂家推荐,食品级卫生与高速灌装厂家实力 - 品牌鉴赏师
  • 深度学习的补充:神经网络处理回归困难(人脸关键点识别)自然语言处理的介绍及深度学习用于自然语言处理
  • 每日Paper | 2026年3月4日
  • 2026年3月桥式滤水管厂家推荐,水井过滤与排水专用实力厂家 - 品牌鉴赏师
  • Kimi可以做广告吗?怎么做?联系谁? - 品牌2026
  • 直接定址表学习
  • if no one works.
  • 2026年3月定尺无缝钢管厂家推荐,精准定尺切割与规格齐全厂家 - 品牌鉴赏师
  • 2026年3月不锈钢反应釜厂家推荐,耐腐蚀材质与工业级制造实力 - 品牌鉴赏师
  • 都2026年了还不会Vite插件开发?手写一个版本管理插件,5分钟包会!
  • 2026年3月15CrMoG高压锅炉管厂家推荐,合金耐高温与实力厂家 - 品牌鉴赏师
  • 给金三银四裸考前端的人一个野路子
  • 能耗数据分散难分析?这套能源监测系统源码,打通电表/水表/气表实现全局可视化
  • Linux软件编程——信号灯+共享内存
  • 昨天面了3个前端岗,都没过聊聊,被挂原因
  • VS2022:Only the invariant culture is supported in globalization-invariant mode.
  • Node.js 宣布重大调整,运行十年的规则要改了!
  • 计算机毕业设计springboot基于Vue框架的智能教研系统的设计与实现 基于SpringBoot与Vue.js的教育教学智慧管理平台设计与实现 SpringBoot结合Vue技术栈的数字化教研
  • 2026年3月水处理厂家推荐,全流程水处理解决方案与优质品牌盘点 - 品牌鉴赏师
  • 计算机毕业设计springboot同城搬家系统设计与实现 基于SpringBoot的城市短途搬迁服务平台开发 SpringBoot框架下的本地搬家业务管理系统构建
  • 从微信小程序 data-id 到 React 列表性能优化:少用闭包,多用 data-*
  • 【思维框架】霍夫斯泰德文化维度理论 是 荷兰社会心理学家吉尔特·霍夫斯泰德(Geert Hofstede)提出的 文化维度理论
  • 2026年3月压配式实心轮胎厂家推荐,压配安装稳固与专业厂家 - 品牌鉴赏师
  • 2026年03月05日热门论文
  • 3/4日博客
  • AI原生应用与知识抽取:开启智能新时代
  • SolidWorks二次开发(C#)-CustomPropertyManager.Delete自定义属性管理器-删除属性
  • SENT协议转换网关——实现ECU与PC/PLC的高效通信桥梁