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)
    @ResponseBody
    public 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)
    @ResponseBody
    public 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 对象不符合校验规则,会抛出 MethodArgumentNotValidException
        return 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 分组的校验规则,会抛出 MethodArgumentNotValidException
        return 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> {
        @Override
        public 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中完成参数校验功能了!感谢大家的收看 如果感觉有帮助请留下小星星

  • 11
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Spring Boot 是基于 Spring 框架的快速开发框架,它大量使用了注解来简化开发流程,提升开发效率。下面是一些常用的 Spring Boot 注解的详解: 1. @SpringBootApplication:标注一个类,表示这是一个 Spring Boot 应用,相当于同时加上了 @Configuration、@EnableAutoConfiguration 和 @ComponentScan 这三个注解。 2. @RestController:标注一个类,表示这是一个控制器类,相当于同时加上了 @Controller 和 @ResponseBody 这两个注解。 3. @GetMapping、@PostMapping、@PutMapping、@DeleteMapping:分别表示 HTTP 请求中的 GET、POST、PUT、DELETE 方法,用于处理请求。 4. @PathVariable:用于获取 URL 路径中占位符的值。 5. @RequestParam:用于获取请求参数的值。 6. @RequestBody:用于获取请求体中的内容。 7. @Validated:用于参数校验,通常与 @RequestParam 或 @RequestBody 一起使用。 8. @Autowired:自动注入依赖,可以注入 Spring 容器中的 Bean。 9. @Service、@Repository、@Controller、@Component:用于标注服务类、持久层类、控制器类和普通组件类,让 Spring Boot 自动扫描并注入到 Spring 容器中。 10. @ConfigurationProperties:用于将配置文件中的属性值注入到类中。 11. @Conditional:用于根据条件决定是否注册 Bean。 12. @Scheduled:用于定时任务,指定方法会定时执行。 13. @Async:用于异步方法调用,可以让方法在另一个线程中执行。 14. @EnableScheduling:开启定时任务。 15. @EnableAsync:开启异步方法调用。 这些注解只是 Spring Boot 中比较常用的一部分,还有很多其他的注解,需要根据具体的开发需求来选择使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进阶的疯狗der

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值