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

SpringBoot参数校验详解

前言

在web开发时,对于请求参数,一般上都需要进行参数合法性校验的,原先的写法时一个个字段一个个去判断,这种方式太不通用了,Hibernate Validator 是 Bean Validation 规范的参考实现,用于在 Java 应用中进行对象的校验。以下是如何在 Spring Boot 项目中安装和使用 Hibernate Validator 的详细步骤。

一、Hibernate Validator参数校验依赖的安装

SpringBoot 2.3以前版本

<!-- Spring Boot Starter Web 包含了 Spring MVC 和 Bean Validation 等常用依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>

Springboot从2.3以后,spring-boot-starter-web中不再引入hibernate-validator,需要手动引入。

<!-- Spring Boot Starter Web 包含了 Spring MVC 和 Bean Validation 等常用依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Hibernate Validator 是 Bean Validation 的默认实现 --><dependency><groupId>org.hibernate.validator</groupId><artifactId>hibernate-validator</artifactId></dependency>

二、SpringBoot参数校验异常返回结果类封装

在使用 Spring Boot 进行参数校验时,如果参数不符合要求,会抛出校验异常。为了更好地处理这些异常并返回统一的错误格式,可以通过以下方式进行封装:

1. 使用 @ControllerAdvice 全局异常处理

创建一个全局异常处理类,捕获 MethodArgumentNotValidExceptionConstraintViolationException,并将其转换为统一的响应格式。

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;@ControllerAdvice
public class GlobalExceptionHandler {// 处理 @Valid 校验异常@ExceptionHandler(MethodArgumentNotValidException.class)@ResponseStatus(HttpStatus.BAD_REQUEST)@ResponseBodypublic Map<String, Object> handleValidationException(MethodArgumentNotValidException ex) {Map<String, Object> errors = new HashMap<>();errors.put("status", HttpStatus.BAD_REQUEST.value());errors.put("message", "Validation failed");Map<String, String> fieldErrors = new HashMap<>();for (FieldError error : ex.getBindingResult().getFieldErrors()) {fieldErrors.put(error.getField(), error.getDefaultMessage());}errors.put("errors", fieldErrors);return errors;}// 处理 @Validated 校验异常@ExceptionHandler(ConstraintViolationException.class)@ResponseStatus(HttpStatus.BAD_REQUEST)@ResponseBodypublic Map<String, Object> handleConstraintViolationException(ConstraintViolationException ex) {Map<String, Object> errors = new HashMap<>();errors.put("status", HttpStatus.BAD_REQUEST.value());errors.put("message", "Validation failed");Map<String, String> fieldErrors = new HashMap<>();Set<ConstraintViolation<?>> violations = ex.getConstraintViolations();for (ConstraintViolation<?> violation : violations) {fieldErrors.put(violation.getPropertyPath().toString(), violation.getMessage());}errors.put("errors", fieldErrors);return errors;}
}

2. 自定义返回结果格式

在返回结果中包含自定义的状态码、错误信息和字段错误列表。

例如:

{"status": 400,"message": "Validation failed","errors": {"fieldName1": "Error message 1","fieldName2": "Error message 2"}
}

3. 参数校验示例

控制器中可以使用 @Valid@Validated 注解进行参数校验:

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;import javax.validation.Valid;@RestController
public class UserController {@PostMapping("/users")public ResponseEntity<String> createUser(@Valid @RequestBody UserRequest userRequest) {// 业务逻辑return ResponseEntity.ok("User created successfully");}
}

4. 校验注解

在请求对象中使用 JSR-303/JSR-380 提供的校验注解,例如 @NotNull, @Size, @Email 等。

import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;public class UserRequest {@NotBlank(message = "Username is mandatory")@Size(min = 3, max = 20, message = "Username must be between 3 and 20 characters")private String username;@NotBlank(message = "Email is mandatory")@Email(message = "Email should be valid")private String email;// getters and setters
}

通过以上方法,可以将参数校验异常统一封装成一个标准格式的响应结果,便于前端处理。

三、@Valid 和 @Validated之间的区别

@Valid@Validated 是 Spring 框架中用于进行参数验证的两个注解,尽管它们的作用相似,但在使用场景和功能上有一些区别:

1. @Valid

  • 作用@Valid 是 JSR-303/JSR-380 标准中的注解,用于在 Bean Validation 中对对象进行校验。它可以用在方法参数、返回值、或者类字段上。
  • 适用范围
    • 对单个对象进行校验。
    • 当用在集合类(如 ListSet)或者数组时,它会对集合中的每个元素进行校验。
  • 典型用法
    @PostMapping("/user")
    public ResponseEntity<String> createUser(@Valid @RequestBody User user) {// 如果 user 对象不符合校验规则,会抛出 MethodArgumentNotValidExceptionreturn ResponseEntity.ok("User created");
    }
    

2. @Validated

  • 作用@Validated 是 Spring 提供的一个注解,扩展了 @Valid 的功能。除了能够进行标准的 Bean Validation 校验外,它还支持分组校验(Group Validation)。
  • 适用范围
    • 可以用来对不同的校验场景使用不同的校验规则(通过分组)。
    • 主要在 Spring 的 @Service@Controller 等类中用于方法级别的校验。
  • 典型用法
    @PostMapping("/user")
    public ResponseEntity<String> createUser(@Validated(OnCreate.class) @RequestBody User user) {// 如果 user 对象不符合 OnCreate 分组的校验规则,会抛出 MethodArgumentNotValidExceptionreturn ResponseEntity.ok("User created");
    }
    

主要区别

  1. 标准 vs. 扩展

    • @Valid 是标准的 Java Bean Validation 注解。
    • @Validated 是 Spring 提供的扩展注解,支持更多功能。
  2. 分组校验

    • @Valid 不支持分组校验,只能进行默认的校验。
    • @Validated 支持分组校验,允许根据不同的操作或场景应用不同的校验逻辑。
  3. 使用场景

    • 如果只需要基本的校验,使用 @Valid 即可。
    • 如果需要在不同的场景下应用不同的校验逻辑,使用 @Validated 并结合分组校验。

希望这些信息能帮你更好地理解这两个注解的区别。

四、常用的校验参数详解

结合 Hibernate Validator 实现。通过在实体类字段或方法参数上使用各种注解,可以轻松进行参数校验。

以下是 Spring Boot 中常用的参数校验注解及其用法详解:

1. 基本校验注解

  • @NotNull:字段不能为 null,但可以为空字符串。

    @NotNull(message = "Name cannot be null")
    private String name;
    
  • @NotEmpty:字段不能为 null,也不能为空字符串或空集合。

    @NotEmpty(message = "List cannot be empty")
    private List<String> items;
    
  • @NotBlank:字段不能为 null,且去掉首尾空格后,必须至少有一个字符。常用于校验字符串。

    @NotBlank(message = "Email cannot be blank")
    private String email;
    
  • @Size:校验字符串、集合、数组的大小或长度。

    @Size(min = 2, max = 30, message = "Name must be between 2 and 30 characters")
    private String name;
    
  • @Min@Max:校验数值型字段的最小值和最大值。

    @Min(value = 18, message = "Age must be at least 18")
    @Max(value = 60, message = "Age must be less than 60")
    private int age;
    
  • @Email:校验是否为合法的电子邮件格式。

    @Email(message = "Email should be valid")
    private String email;
    
  • @Pattern:使用正则表达式校验字符串的格式。

    @Pattern(regexp = "^\\d{10}$", message = "Phone number must be 10 digits")
    private String phoneNumber;
    
  • @Past@Future:校验日期字段是否在过去或未来。

    @Past(message = "Birthday must be in the past")
    private LocalDate birthday;@Future(message = "Appointment date must be in the future")
    private LocalDate appointmentDate;
    
  • @AssertTrue@AssertFalse:校验布尔类型字段是否为 truefalse

    @AssertTrue(message = "Must agree to terms")
    private boolean agreedToTerms;
    

2. 组合注解

可以组合多个注解来实现复杂的校验规则。例如,校验一个字段既不为空,又必须符合特定格式:

@NotBlank(message = "Username cannot be blank")
@Pattern(regexp = "^[a-zA-Z0-9]{3,}$", message = "Username must be alphanumeric and at least 3 characters long")
private String username;

3. 分组校验(@Validated)

分组校验可以根据不同场景应用不同的校验规则。需要结合 @Validated 注解来实现。

  • 定义分组接口

    public interface CreateGroup {}
    public interface UpdateGroup {}
    
  • 在实体类中应用分组

    @NotNull(groups = UpdateGroup.class, message = "Id cannot be null when updating")
    private Long id;@NotBlank(groups = CreateGroup.class, message = "Name cannot be blank when creating")
    private String name;
    
  • 在 Controller 方法中指定分组

    @PostMapping("/create")
    public ResponseEntity<String> createUser(@Validated(CreateGroup.class) @RequestBody User user) {// 校验仅针对 CreateGroup 分组return ResponseEntity.ok("User created");
    }@PutMapping("/update")
    public ResponseEntity<String> updateUser(@Validated(UpdateGroup.class) @RequestBody User user) {// 校验仅针对 UpdateGroup 分组return ResponseEntity.ok("User updated");
    }
    

4. 自定义校验注解

如果内置的校验注解不能满足需求,可以创建自定义校验注解。

  • 创建注解

    @Target({ElementType.FIELD, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Constraint(validatedBy = MyCustomValidator.class)
    public @interface MyCustomValidation {String message() default "Invalid value";Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};
    }
    
  • 实现校验逻辑

    public class MyCustomValidator implements ConstraintValidator<MyCustomValidation, String> {@Overridepublic boolean isValid(String value, ConstraintValidatorContext context) {// 校验逻辑,例如:字符串必须包含 "valid"return value != null && value.contains("valid");}
    }
    
  • 使用自定义注解

    @MyCustomValidation(message = "The value must contain 'valid'")
    private String customField;
    

通过这些校验注解和机制,可以在 Spring Boot 中高效地处理参数校验逻辑,确保应用的输入数据符合预期。

通过以上就可以正常使用注解在SpringBoot中完成参数校验功能了!感谢大家的收看 如果感觉有帮助请留下小星星

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • PyTorch 基础学习(6)- 自动微分
  • Android Studio设置 offline 模式
  • 解决 Windows 任务栏图标不更新问题:深入解析与解决方案
  • C++初阶_2:引用
  • docker中调用GPU算力(debain12系统)
  • Spring 事务机制
  • Linux中针对文件权限的解析
  • FairyGUI-egret 优化ui资源加载
  • Linux--C语言之输入输出函数及格式控制输出
  • 如何在Shopify开发中高度还原Figma设计稿
  • 操作系统信号集与信号屏蔽
  • 社交工程攻击:心理操纵的艺术与防范策略
  • Nginx 服务器配置 SSL(HTTPS)的教程
  • 【langchain学习】从零开始掌握 JSONLoader:轻松解析复杂 JSON 数据
  • 【数据结构】五、树:7.哈夫曼树、哈夫曼编码
  • 9月CHINA-PUB-OPENDAY技术沙龙——IPHONE
  • 【附node操作实例】redis简明入门系列—字符串类型
  • Android Studio:GIT提交项目到远程仓库
  • Centos6.8 使用rpm安装mysql5.7
  • CODING 缺陷管理功能正式开始公测
  • create-react-app做的留言板
  • JavaScript函数式编程(一)
  • Java面向对象及其三大特征
  • Kibana配置logstash,报表一体化
  • Laravel深入学习6 - 应用体系结构:解耦事件处理器
  • PHP面试之三:MySQL数据库
  • V4L2视频输入框架概述
  • vuex 笔记整理
  • webpack+react项目初体验——记录我的webpack环境配置
  • 从输入URL到页面加载发生了什么
  • 极限编程 (Extreme Programming) - 发布计划 (Release Planning)
  • 精益 React 学习指南 (Lean React)- 1.5 React 与 DOM
  • 开源地图数据可视化库——mapnik
  • 微信支付JSAPI,实测!终极方案
  • 一个JAVA程序员成长之路分享
  • 2017年360最后一道编程题
  • Mac 上flink的安装与启动
  • ​Distil-Whisper:比Whisper快6倍,体积小50%的语音识别模型
  • ​io --- 处理流的核心工具​
  • ​渐进式Web应用PWA的未来
  • # 利刃出鞘_Tomcat 核心原理解析(八)-- Tomcat 集群
  • #### go map 底层结构 ####
  • #Lua:Lua调用C++生成的DLL库
  • (13)[Xamarin.Android] 不同分辨率下的图片使用概论
  • (33)STM32——485实验笔记
  • (Java数据结构)ArrayList
  • (Redis使用系列) Springboot 实现Redis 同数据源动态切换db 八
  • (STM32笔记)九、RCC时钟树与时钟 第二部分
  • (九)One-Wire总线-DS18B20
  • (三)docker:Dockerfile构建容器运行jar包
  • (四)docker:为mysql和java jar运行环境创建同一网络,容器互联
  • (转)Groupon前传:从10个月的失败作品修改,1个月找到成功
  • (转)memcache、redis缓存
  • *(长期更新)软考网络工程师学习笔记——Section 22 无线局域网
  • . ./ bash dash source 这五种执行shell脚本方式 区别