当前位置: 首页 > 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中完成参数校验功能了!感谢大家的收看 如果感觉有帮助请留下小星星

http://www.lryc.cn/news/426295.html

相关文章:

  • 安全基础学习-SHA-1(Secure Hash Algorithm 1)算法
  • leetcode350. 两个数组的交集 II,哈希表
  • 基于YOLOv8的缺陷检测任务模型训练
  • 【upload]-ini-[SUCTF 2019]CheckIn-笔记
  • uniapp条件编译使用教学(#ifdef、#ifndef)
  • NXP i.MX8系列平台开发讲解 - 4.1.2 GNSS 篇(二) - 卫星导航定位原理
  • 怎样在 SQL 中对一个包含销售数据的表按照销售额进行降序排序?
  • DIAdem 与 LabVIEW
  • UE虚幻引擎可以云渲染吗?应用趋势与挑战了解
  • 实战分享:DefenderUI在企业环境中的部署与应用
  • 中英双语介绍金融经济中的鹰派 (Hawkish)和鸽派 (Dovish)
  • Android 开发中常用的布局类型及其选择指南
  • 短视频SDK解决方案,降低行业开发门槛
  • 【C++】String常见函数用法
  • LeetCode49.字母异位词分组
  • Nginx日志按天分割
  • 文本摘要简介
  • 3.MySQL面试题之Redis 和 Mysql 如何保证数据一致性?
  • 浅谈TCP协议、UDP协议
  • SQL业务题: 从不订购的客户
  • 怎么直接在PDF上修改内容?随心编辑PDF内容
  • 聊天室项目测试报告
  • 语音识别(实时语音转录)——funasr的详细部署和使用教程(包括实时语音转录)
  • 【网络编程】TCP机械臂测试
  • 笔记:在WPF中如何注册控件级全局事件和应用程序级全局事件
  • 【Linux系列】telnet使用入门
  • 音视频相关知识
  • 数据结构--第七天
  • 代码随想录Day34:62.不同路径、63.不同路径II、343.整数拆分、96.不同的二叉搜索树
  • 【信息学奥赛一本通】1008:计算(a+b)/c的值