参数校验
参数校验概述
在 Web 应用三层架构体系中,表述层负责接收浏览器提交的数据,业务逻辑层负责数据的处理。为了能够让业务逻辑层基于正确的数据进行处理,我们需要在表述层对数据进行检查,将错误的数据隔绝在业务逻辑层之外。
JSR 303 是 Java 为 Bean 数据合法性校验提供的标准框架,它已经包含在 JavaEE 6.0 标准中。JSR 303 通过在 Bean 属性上标注类似于 @NotNull、@Max 等标准的注解指定校验规则,并通过标准的验证接口对Bean进行验证。
JSR 303 标准的校验注解和对应规则如下:
| 注解 | 规则 |
|---|---|
| @Null | 标注值必须为 null |
| @NotNull | 标注值不可为 null |
| @NotEmpty | 对于 CharSequence、Collection、Map 或者数组对象类型的属性会校验引用不能为null,且size() .length 不能为0; 对于 String 类型,不能为null,且不能为 ""(不会去前后空格)。 |
| @AssertTrue | 标注值必须为 true |
| @AssertFalse | 标注值必须为 false |
| @Min(value) | 标注值必须大于或等于 value |
| @Max(value) | 标注值必须小于或等于 value |
| @DecimalMin(value) | 标注值必须大于或等于 value |
| @DecimalMax(value) | 标注值必须小于或等于 value |
| @Size(max,min) | 标注值大小必须在 max 和 min 限定的范围内。 用在String上length()必需在此范围内(不会去前后空格)。 |
| @Digits(integer,fratction) | 标注值值必须是一个数字,且必须在可接受的范围内;指定整数部分和小数部分的最大位数。 |
| @Past | 标注值只能用于日期型,且必须是过去的日期 |
| @Future | 标注值只能用于日期型,且必须是将来的日期 |
| @Pattern(value) | 标注值必须符合指定的正则表达式 |
- 包装类为了避免默认值参与运算,通常使用 @NotNull 注解
- 数组/集合 通常使用 @NotEmpty 来判空
JSR 303 只是一套标准,并没有给出对应的实现。Hibernate Validator 是 JSR 303 的一个参考实现,除支持所有标准的校验注解外,它还支持以下的扩展注解:
| 注解 | 规则 |
|---|---|
| 标注值必须是格式正确的 Email 地址 | |
| @Length | 标注值字符串大小必须在指定的范围内 |
| @NotBlank | 只能用于字符串类型的校验,String 不能为null,且去除首尾空格后,length() 不能为0(即不能为"") |
| @Range | 标注值必须在指定的范围内 |
- String 通常使用 @NotBlank 来判空
SpringMVC 参数校验
Spring 4.0 版本已经拥有自己独立的数据校验框架,同时支持 JSR 303 标准的校验框架。Spring 在进行数据绑定时,可同时调用校验框架完成数据校验工作。
在SpringMVC 中,Spring 的 LocalValidatorFactoryBean 既实现了 Spring 的 Validator 接口,也实现了 JSR 303 的 Validator 接口。只要在Spring容器中装入一个LocalValidatorFactoryBean,即可将其注入到需要数据校验的 Bean中。Spring本身并没有提供JSR 303的实现,所以必须将JSR 303的实现者的jar包放到类路径下。
配置 @EnableWebMvc 后,SpringMVC 会默认装配好一个 LocalValidatorFactoryBean,通过在handler方法的入参上标注 @Validated 注解即可让 SpringMVC 在完成数据绑定后执行数据校验的工作。
导入依赖
<!-- 校验注解 --> <dependency> <groupId>jakarta.platform</groupId> <artifactId>jakarta.jakartaee-web-api</artifactId> <version>9.1.0</version> <scope>provided</scope> </dependency> <!-- Hibernate 校验注解实现--> <!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator --> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>8.0.0.Final</version> </dependency> <!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator-annotation-processor --> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator-annotation-processor</artifactId> <version>8.0.0.Final</version> </dependency>在pojo上应用校验注解
通常通用的参数校验才会在pojo类中使用校验注解,如果是特定的校验,则一般在handler中自行编写校验逻辑。
import jakarta.validation.constraints.Email; import jakarta.validation.constraints.Min; import org.hibernate.validator.constraints.Length; /** * projectName: com.atguigu.pojo */ public class User { //age 1 <= age < = 150 @Min(10) private int age; //name 3 <= name.length <= 6 @Length(min = 3,max = 10) private String name; //email 邮箱格式 @Email private String email; // getter setter }需要参数校验的hander中让校验注解生效
在pojo形参前或后一个形参位置上声明
Errors或BindingResult类型形参,则可以接收校验注解的错误或校验结果。/** * @Validated 代表应用校验注解! 必须添加! */ @PostMapping("save") public Object save(@Validated @RequestBody User user, //在实体类参数和 BindingResult 之间不能有任何其他参数, BindingResult可以接受错误信息,避免信息抛出! BindingResult result){ //判断是否有信息绑定错误! 有可以自行处理! if (result.hasErrors()){ System.out.println("错误"); String errorMsg = result.getFieldError().toString(); return errorMsg; } //没有,正常处理业务即可 System.out.println("正常"); return user; }
