SpringMVC实现参数校验配置方法
在 Web 应用的三层架构中,确保在表述层(Presentation Layer)对数据进行检查和校验是非常重要的。正确的数据校验可以确保业务逻辑层(Business Logic Layer)基于有效和合法的数据进行处理,同时将错误的数据隔离在业务逻辑层之外。这有助于提高系统的健壮性、安全性和可维护性。
校验概述
JSR-303是Java EE 6中的一项子规范,也被称为Bean Validation。这个规范主要用于对Java Bean中的字段值进行验证。JSR-303提供了一套注解和API,方便开发者在实体类中对字段进行验证,以确保数据的合法性。
在JSR-303中,内置了许多常用的约束规则,如@NotNull(非空验证)、@Size(长度验证)、@Range(范围验证)等。这些注解可以直接应用于实体类的字段上,以声明验证规则。同时,JSR-303还提供了验证器(Validator)接口,用于执行验证操作。开发者可以通过注入Validator实例,或者使用Validation工具类来触发验证。
在Spring MVC中,JSR-303得到了很好的支持。开发者可以在控制器的方法参数上使用JSR-303的注解,以实现表单数据的自动验证。如果参数不满足约束条件,Spring MVC会抛出MethodArgumentNotValidException
异常,并将错误信息绑定到相应的字段上。
常用注解
@NotNull
:确保字段值不为null。@NotBlank
:用于String类型参数校验,检查字符串不能为null且去除首尾空格后长度大于0。@NotEmpty
:主要用于集合校验,校验集合不能为null且size大于0,也可以用于String的校验,确保字@Null
:确保字段值为null。@AssertTrue 和 @AssertFalse
:用于boolean字段,确保字段值为true或false。@Min 和 @Max
:用于Number和String字段,确保字段值在指定的范围内。@DecimalMin 和 @DecimalMax
:用于BigDecimal,BigInteger,String,byte,short,int,long字段,确保字段值在指定的小数范围内。需要注意的是,小数验证存在精度问题。@Size
:用于Collection,Map,Array,String字段,确保字段的长度(或大小)在指定的范围内。@Digits
:用于BigDecimal,BigInteger,String,byte,short,int,long字段,验证值的数字构成是否合法。它有两个参数,integer表示整数部分的数字的位数,fraction表示小数部分的数字的位数。@Email
:用于String字段,验证字段值是否为有效的电子邮件地址。@Past 和 @Future
:用于日期和时间字段,确保日期在过去或未来。@Pattern
:用于String字段,验证字段值是否匹配指定的正则表达式。@Range
:控制一个数值的范围,如数字、日期等。@Valid
:递归地对关联对象进行校验,如果关联对象是个集合或者数组,那么对其中的元素进行递归校验;如果是一个map,则对其中的值部分进行校验。@CreditCardNumber
:信用卡验证。@URL
:验证一个字符串是否符合URL格式。@ScriptAssert
:使用脚本语言进行自定义验证。
@NotNull、@NotEmpty和@NotBlank注解说明
@NotNull、@NotEmpty和@NotBlank
都是Java中的注解,用于在运行时检查属性值是否符合特定条件。它们的使用场景如下:
@NotNull:这个注解用于基本数据类型和它们的包装类(如Integer、Long、Double等),以及String类型。当它被用在String类型上时,表示该数据不能为null,但可以为空字符串。这个注解一般用在基本数据类型的非空校验上,如果被其标注的字段使用了@Size、@Max或@Min等注解,那么还可以对字段的数值大小进行控制。此外,@NonNull是JSR 305(缺陷检查框架)的注解,用于方法或构造函数的参数上,表明所修饰的参数不能为null。它会在代码检查(静态检查)时给出一个风险警告,但运行时不会报错。
@NotEmpty:这个注解用于String、Collection集合、Map、数组等类型。加了@NotEmpty注解的参数不能为null,而且长度或大小必须大于0。这个注解一般用在集合类上。
@NotBlank:这个注解只能用于String类型。加了@NotBlank注解的字符串不能为null,而且去除两端空白字符后的长度(trimmed length)必须大于0。这个注解通常用于前端发送过来的数据,先进行校验处理,再进行逻辑判断。
总结来说,@NotNull、@NotEmpty和@NotBlank的使用场景主要取决于你想要验证的数据类型和约束条件。@NotNull主要用于基本数据类型和String的非空检查,@NotEmpty主要用于集合类,而@NotBlank则主要用于String类型,要求字符串不为null且去除空白字符后的长度大于0。在实际开发中,一定要根据具体需求选择合适的注解,否则可能会导致验证逻辑出错。
操作演示
1.导入依赖
<!--validation-api接口的实现--> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.1.5.Final</version> </dependency> <!--Java Bean Validation 的规范接口--> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>2.0.1.Final</version> </dependency> <!--Java 注解处理器,它用于在编译时检查 JSR-303 注解的正确性和一致性--> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator-annotation-processor</artifactId> <version>6.2.5.Final</version> </dependency>
2.校验实体对象参数
实体类
@Data public class User { @NotBlank private String name; @NotNull(message = "年龄最小1岁,最大100岁") @Range(min = 1 , max = 100) private Integer age; @NotNull(message = "邮箱不能为空,并且要符合规范") @Email private String email; @NotNull @Size(min = 2,max = 50) private String address; @Past private Date birthday; @NotEmpty private List<String> users; }
controller
//实体对象校验 //在实体类参数和 BindingResult 之间不能有任何其他参数, BindingResult可以接受错误信息,避免信息抛出! //@Validated 或 @Valid 代表应用校验注解! @PostMapping("validateObject") private String validateObject(@Valid @RequestBody User user, BindingResult result) { //判断是否有信息绑定错误! 有可以自行处理! if (result.hasErrors()) { String errorMsg = Objects.requireNonNull(result.getFieldError()).toString(); System.out.println(errorMsg); return "error"; } System.out.println("user=" + user); return "success"; }
说明:
@Validated注解是SpringMVC提供的。
@Valid注解是JSR-303提供的。
3.基本类型校验
//基本类型校验 @GetMapping("validate") public String validateBasic(@RequestBody @Min(18) Integer age, @RequestBody @NotBlank String name) { return "success"; }
配置校验器
说明:一般情况下不需要配置,SpringMVC已经配置好默认校验器
基于xml配置方式
LocalValidatorFactoryBean 是 Spring 框架提供的一个类,它实现了 ValidatorFactory 接口。在 Spring 环境中,LocalValidatorFactoryBean 通常被用作 Bean Validation 的默认实现。Spring 的自动配置通常会为你创建一个 LocalValidatorFactoryBean 实例,并将其配置为应用的默认 ValidatorFactory。这意味着,当你在 Spring 控制器或服务中使用 @Valid 或 @Validated 注解时,背后实际上是 LocalValidatorFactoryBean 在执行验证逻辑。
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/> <mvc:annotation-driven validator="validator"/>
基于配置类方式构建 ValidatorFactory 实例。
ValidatorFactory 是一个工厂类,用于生产 Validator 实例,这些 Validator 实例用于执行实际的验证逻辑。当你需要在非 Spring 环境中进行 Bean Validation,或者当 Spring 的自动配置不能满足你的需求时,你可以使用这个方法手动配置和获取 Validator。
@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Bean public Validator validator() { ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); return factory.getValidator(); } }
结论:
Validation.buildDefaultValidatorFactory():这是 Bean Validation API 的标准方法,用于在非 Spring 环境中创建 ValidatorFactory。在 Spring 中,除非你有特殊需求需要绕过 Spring 的自动配置,否则通常不会直接使用这个方法。
LocalValidatorFactoryBean:这是 Spring 框架特有的类,用于在 Spring 应用中作为默认的 ValidatorFactory。在 Spring 应用中,你通常不需要直接操作 LocalValidatorFactoryBean,因为 Spring 会自动为你配置和注入它。但是,如果你需要自定义验证器的配置(例如,更改消息插值器、遍历提供者等),你可以创建一个 LocalValidatorFactoryBean 的 Bean 并进行相应的配置。
4.集合校验
//集合校验 @PostMapping("validateList") public Object validateList(@Valid @RequestBody List<@Positive User> users, BindingResult result) { if (result.hasErrors()) { Map<String,Object> map = new HashMap<>(); map.put("code","400"); map.put("msg","参数校验失败,不符合规则"); return map; } System.out.println(users); return users; }
自定义校验注解
1.定义一个注解类,并使用@interface关键字。
2.在注解类上添加@Constraint注解,并指定校验器类。
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = MyCustomValidator.class) public @interface MyCustomValidation { String message() default "该字段不能为空"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
3.创建一个实现ConstraintValidator接口的校验器类,实现校验逻辑。
public class MyCustomValidator implements ConstraintValidator<MyCustomValidation,String> { @Override public void initialize(MyCustomValidation constraintAnnotation) { //可以在这里进行一些初始化操作 } @Override public boolean isValid(String value, ConstraintValidatorContext context) { // 自定义校验逻辑:检查字符串是否为空或仅包含空白字符 return value != null && !value.trim().isEmpty(); } }
4.在需要校验的字段上应用自定义注解。
public class CustomValidationEntity { @MyCustomValidation private String customField; }
全局异常校验配置
为了优雅地处理校验失败的情况,你可以实现一个全局异常处理器来捕获MethodArgumentNotValidException
异常,并从中提取错误信息。这个异常是如果控制器方法形参不满足约束条件,Spring MVC会抛出MethodArgumentNotValidException
异常,并将错误信息绑定到相应的字段上。例如:
@ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<Object> handleValidationExceptions(MethodArgumentNotValidException ex) { BindingResult bindingResult = ex.getBindingResult(); Map<String, String> errors = new HashMap<>(); for (FieldError fieldError : bindingResult.getFieldErrors()) { errors.put(fieldError.getField(), fieldError.getDefaultMessage()); } return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST); } }
在这个例子中,GlobalExceptionHandler类使用@ControllerAdvice注解标记为一个全局异常处理器。handleValidationExceptions方法则用于处理MethodArgumentNotValidException异常。它从BindingResult中提取错误信息,并将这些信息作为响应返回给客户端。
这样,当客户端发送一个包含无效数据的请求时,服务器会返回一个包含错误信息的响应,而不是直接抛出异常。
到此这篇关于SpringMVC实现参数校验的文章就介绍到这了,更多相关SpringMVC参数校验内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
最新评论