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

探索Spring Validation:优雅实现后端数据验证的艺术

在现代Web应用开发中,数据验证是一项至关重要的任务,确保应用程序接收到的用户输入符合预期规范,不仅能够提高系统的健壮性,也能有效防止潜在的安全漏洞。Spring Framework通过其内置的Spring Validation模块,为我们提供了强大的数据验证功能,本文将带你深入了解Spring Validation的实现原理及其最佳实践。

一、Spring Validation简介

Spring Validation是基于Java Bean Validation规范(JSR 303/349 for Java EE 6/7,JSR 380 for Java EE 8)实现的,主要依赖的是Hibernate Validator作为默认的实现引擎。它允许我们在Java Bean的属性上声明验证注解,从而在运行时对这些属性进行条件性验证。

在实际项目我们需要对客户端传递到服务端的参数进行校验,用于判定请求参数的合法性,假如请求参 数不合法则不可以再去执行后续的业务了。那如何校验呢?

一种方式是我们在控制层方法中每次都自己进行参数有效值的判断,不合法可以抛出异常,但是工作量 和代码复杂度会比较高;

第二种方式就是采用市场上主流的 Spring Validation 框架去实现校验,所以 Spring Validation 框架的主要作用是 检查参数的基本有效性。

二、集成与配置

1. 引入依赖

在Maven或Gradle构建项目中,我们需要引入Hibernate Validator的相关依赖,例如在Maven的pom.xml文件中添加:

Xml

1<dependency>
2    <groupId>org.springframework.boot</groupId>
3    <artifactId>spring-boot-starter-validation</artifactId>
4</dependency>

2.使用注解

Spring Validation提供了丰富的预定义注解,如@NotNull,@NotEmpty,@NotBlank,@Size,@Range等,可以直接应用于实体类的字段上:

@NotNull注解

作用:用于验证对象是否为 null

用法: @NotNull 注解用于对象类型上

示例

@NotNull(message = "用户名不能为null")
private String username;

@NotEmpty注解

作用:用于验证字符串是否为空,并且会检查是否为 null 值(为null值时报错)

用法:用于字符串类型上

示例

@NotEmpty(message = "用户名不能为空")
private String username;

@NotBlank注解

作用:不允许为空白,即不允许是“仅由空格、TAB等空白值组成的字符串”,也不允许为空字符串,也不允许为空值null

用法:用于字符串类型上

示例

@NotBlank(message = "用户名不能为空白串")
private String username;

@Size注解

作用:可以指定最小值和最大值限制字符串的长度串,也不允许为空值null

用法:用于字符串类型参数

示例

@Size(min = 6, max = 20, message = "用户名长度必须在6到20之间")
private String username;

@Range 注解

作用:用于验证数字类型字段的取值范围,通过配置min和max属性来限制数值类型参数的值区间 包括最小值和最大值

用法:用于数值类型参数

示例

@Range(min = 1, max = 10, message = "年龄必须在1-10岁之间")
private int age;

@Range(min = 0.1, max = 1.0, message = "成绩必须在0.1到1.0之间")
private double score;

三、验证流程与控制器处理

  1. 控制器层处理: 在Spring MVC的Controller中,我们可以使用@Valid注解来触发模型对象的验证,紧接着一个BindingResult对象用于捕获验证结果:

    1@PostMapping("/users")
    2public ResponseEntity<?> createUser(@Valid @RequestBody User user, BindingResult bindingResult) {
    3    if (bindingResult.hasErrors()) {
    4        // 处理验证错误
    5        return handleValidationError(bindingResult);
    6    } else {
    7        // 验证通过,继续处理业务逻辑
    8        userService.createUser(user);
    9        return ResponseEntity.ok().build();
    10    }
    11}
  2. 自定义注解与验证器: 对于更复杂或特定的验证需求,Spring Validation允许我们自定义注解并编写相应的验证器实现javax.validation.ConstraintValidator接口:

    1@Target({ElementType.FIELD})
    2@Retention(RetentionPolicy.RUNTIME)
    3@Constraint(validatedBy = EncryptedIdValidator.class)
    4public @interface EncryptedId {
    5    String message() default "加密ID格式不正确";
    6    Class<?>[] groups() default {};
    7    Class<? extends Payload>[] payload() default {};
    8}
    9
    10public class EncryptedIdValidator implements ConstraintValidator<EncryptedId, String> {
    11    // 实现自定义的验证逻辑
    12    ...
    13}

 四、快速入门

1. 在处理请求的方法的参数列表中,在POJO类型的参数上添加 @Validated 注解,表示需要通过 Spring Validation框架检查此参数,例如UserController中注册功能:

@ApiOperation(value = "注册功能")
@PostMapping("reg")
public JsonResult reg(@RequestBody @Validated UserRegDTO userRegDTO){}

2. 在此POJO类中的属性上,添加对应的检查注解,以配置检查规则, 例如,添加 @NotNull 注解,就表示“不允许为 null ”的规则!

在 UserRegDTO 类

@Data
public class UserRegDTO {
    @NotNull
    @ApiModelProperty(value = "用户名", required = true, example = "赵丽颖")
    private String username;
    @ApiModelProperty(value = "密码", required = true, example = "123456")
    private String password;
    @ApiModelProperty(value = "昵称", required = true, example = "萤火虫")
    private String nickname;
}

3. 重启工程,在Knife4j中测试,当提交请求时,如果没有提交username参数,服务器端将响应 400 错误。

同时在终端也会出现异常

五、异常处理与响应

1.处理异常

为了给前端提供友好的反馈,通常我们会统一处理验证失败时的异常,将其转换成HTTP状态码和错误信息:

第1步:全局异常处理器 GlobalExceptionHandler 中定义处理异常方法

@ExceptionHandler
public JsonResult handleBindException(MethodArgumentNotValidException ex){
    return new JsonResult(3002, "请求参数错误");
}

第2步:重启工程,在Knife4j中测试

2.明确提示信息

当提交的 username 的值为 null 时,可以发现异常已被处理!

但是,处理结果并不合适,因为,客户端得到此结果后,仍无法明确出现了什么错误!

所有的检查注解都可以配置 message 参数,用于对错误进行描述。

第1步: @NotNull 注解中添加 message 参数

@NotNull(message = "必须提交用户名")
private String username;

第2步:自定义枚举状态码 StatusCode

VALIDATE_ERROR(3002, "参数校验失败")

第3步:异常方法中获取提示信息 message

在处理异常时,需要调用 MethodArgumentNotValidException 对象的

getFieldError().getDefaultMessage() 获取以上配置的描述文本

@ExceptionHandler
public JsonResult handleBindException(MethodArgumentNotValidException ex){
    /*
        ex.getFieldError().getDefaultMessage():获取 @NotNull(message="xxx") 中
message的消息
    */
    String message = ex.getFieldError().getDefaultMessage();
    return new JsonResult(StatusCode.VALIDATE_ERROR, message);
}

第3步:重启工程,在Knife4j中测试

六、非POJO类参数校验

在 Spring Validation 中,除了对 POJO(Plain Old Java Object)进行校验的功能外,还支持对非 POJO 进行校验,比如 String、Integer、Double 等类型的参数。

1.使用流程

  • 在当前方法所在的类上添加 @Validated 注解
  • 在参数上添加对应的检查注解

2.使用示例

对于微博详情页的 id 参数进行范围校验,范围只能在1-10之间

第1步:在类 WeiboController 中添加 @Validated 注解

@Validated
public class WeiboController {}

第2步:在控制器方法参数 id 上添加对应的检查注解

public JsonResult selectById(@Range(min = 1, max=10, message = "请提交合法的ID
值!") int id)

第3步:重启工程,在Knife4j或者浏览器中测试

七、总结

Spring Validation的使用极大地简化了Java应用程序中的数据验证过程,通过标准化的注解机制实现了业务逻辑和数据验证的分离,提高了代码的可读性和可维护性。同时,它也具有良好的扩展性,让我们能够轻松应对各类复杂的验证场景,确保了系统数据质量的同时提升了用户体验。

通过深入理解和灵活运用Spring Validation,开发者能够在后端建立起坚固的数据过滤防线,为构建安全可靠的应用程序打下坚实基础。而随着RESTful API设计的流行,Spring Validation更是成为了保障API契约得到严格遵循的重要工具之一。


http://www.kler.cn/a/233371.html

相关文章:

  • Javaweb—Ajax与jQuery请求
  • Vue 的生命周期函数 和 Vuex
  • 详解基于C#开发Windows API的SendMessage方法的鼠标键盘消息发送
  • 相机光学(四十二)——sony的HDR技术
  • MySQL重难点(一)索引
  • 贪心算法入门(二)
  • 数据结构-->线性表-->单链表
  • JAVA面试题12
  • 信号——block+pending+handler表
  • C语言常见面试题:什么是常量?C语言中有哪些类型的常量?
  • Python 小白的 Leetcode Daily Challenge 刷题计划 - 20240209(除夕)
  • 初识文件包含漏洞
  • 【OpenHarmony硬件操作】风扇与温湿度模块
  • 【Spring】Spring 对 Ioc 的实现
  • kaggle实战语义分割-Car segmentation(附源码)
  • 数据库管理phpmyadmin
  • Linux C/C++ 原始套接字:打造链路层ping实现
  • 【ESLint】TypeError:this.libOptions.parse is not a function
  • 【从Python基础到深度学习】4. Linux 常用命令
  • MinMaxScaler, StandardScaler数据预处理中常用的两种缩放方法,用于将数据标准化或归一化到特定的范围或分布
  • 【CV论文精读】EarlyBird: Early-Fusion for Multi-View Tracking in the Bird’s Eye View
  • IOS破解软件安装教程
  • 达梦数据库适配Springboot+MybatisPlus+达梦数据库
  • 谷歌 DeepMind 联合斯坦福推出了主从式遥操作双臂机器人系统增强版ALOHA 2
  • 嵌入式单片机中晶振的工作原理
  • laravel distinct查询问题,laravel子查询写法