[技术资料]Spring Boot参数校验:@Valid和@Validated注解使用详解

1. Controller参数校验简介

Spring Boot为Web开发提供了强大的参数校验机制。通过整合JSR 303(Bean Validation),可以确保请求参数的合法性,防止诸如空指针异常、参数越界等常见错误。通过注解的方式,在Controller中对请求参数进行验证,是提升应用程序稳定性和安全性的重要手段。

2. 如何在Spring Boot中实现参数校验

在Spring Boot中,@Valid 和 @Validated 注解可用于触发参数校验。通过 javax.validation.constraints 包中的注解,我们可以对Java Bean对象的属性进行详细的校验。

示例:控制器层参数校验
@PostMapping("/user")
public String addUser(@Valid @RequestBody User user, BindingResult result) {
    if (result.hasErrors()) {
        return "error";
    }
    userService.addUser(user);
    return "success";
}

  • @Valid: 在方法参数上,表示对参数对象进行校验。
  • BindingResult: 用于捕获校验错误。
示例:User类参数校验
public class User {
    @NotNull(message = "用户名不能为空")
    private String username;
    
    @NotBlank(message = "密码不能为空")
    private String password;
    
    @Email(message = "邮箱格式不正确")
    private String email;
    
    // Getter 和 Setter
}

这些注解包括:

  • @NotNull: 确保字段非空。
  • @NotBlank: 确保字段非空并且不为空格。
  • @Email: 校验邮箱格式是否正确。

通过这样的验证,Spring Boot确保了参数的正确性,避免了潜在的错误。

3. Maven依赖配置

为了启用验证功能,你需要在pom.xml中添加如下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

你还可以选择添加其他验证相关依赖,具体视项目需求而定。

4. 常用校验注解
  • @size (min=6, max=20, message="密码长度只能在6-20之间")
  • @pattern (regexp="[a-za-z0-9._%+-]+@[a-za-z0-9.-]+\.[a-za-z]{2,4}", message="请输入正确的邮件格式")
  • @Length(min = 5, max = 20, message = "用户名长度必须位于5到20之间")
  • @Email(message = "请输入正确的邮箱")
  • @NotNull(message = "用户名称不能为空")
  • @Max(value = 100, message = "年龄不能大于100岁")
  • @Min(value= 18 ,message= "必须年满18岁!" )
  • @AssertTrue(message = "bln4 must is true")
  • @AssertFalse(message = "blnf must is falase")
  • @DecimalMax(value="100",message="decim最大值是100")
  • @DecimalMin(value="100",message="decim最小值是100")
  • @NotNull(message = "身份证不能为空")
  • @Pattern(regexp="^(\d{18,18}|\d{15,15}|(\d{17,17}[x|X]))$", message="身份证格式错误")

这些注解能够灵活地对字段进行格式、大小、范围等方面的校验。

5. @Valid与@Validated的区别及使用场景
  • @Valid: 主要用于嵌套校验,即对于对象中的属性值(可能是另一个对象)进行校验。
  • @Validated: 支持校验分组,可以对同一实体类在不同场景下应用不同的校验规则。
示例:嵌套校验
@Data
public class TeamDTO {

    @Valid
    private List<MemberDTO> list; // 对成员列表进行嵌套校验
}

6. 分组校验与自定义分组

当需要对同一对象进行不同场景下的校验时,可以通过分组校验来实现。

示例:定义分组接口
public interface TestValidGroup {

    interface Insert {}

    interface Update {}
}

示例:指定分组校验
@PostMapping("/post")
public BaseResponse testValidPostRequest(@Validated(value = {TestValidGroup.Update.class}) @RequestBody ProjectDTO testAnnotationDto) {
    return new BaseResponse(testAnnotationDto);
}

通过@Validatedvalue参数,我们可以选择不同的校验分组。

7. @GroupSequence指定校验顺序

为了确保参数校验顺序的可控性,可以使用@GroupSequence注解来指定校验顺序,这对于某些严格的自动化测试场景非常有用。

@GroupSequence(value = {Id.class, StrValue.class})
interface Update {}

8. 快速失败机制

Hibernate Validator支持快速失败机制,即一旦发现校验失败,就立即抛出异常,避免进一步的校验开销。

@Configuration
public class ValidConfig {
    @Bean
    public Validator validator() {
        ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
                .configure()
                .failFast(true)
                .buildValidatorFactory();
        return validatorFactory.getValidator();
    }
}

 9. 异常处理

Spring 提供了多种方式来处理校验失败的异常,常见的方式是使用 @ExceptionHandler 来捕获异常并返回自定义的错误响应。

 @ExceptionHandler({MethodArgumentNotValidException.class,ConstraintViolationException.class,BindException.class})
    public Result<?> handleValidationException(Throwable e) {
        String errorMessage = e.getMessage();

        if (e instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException ex = (MethodArgumentNotValidException) e;
            errorMessage = ex.getBindingResult().getAllErrors().stream()
                    .map(ObjectError::getDefaultMessage)
                    .collect(Collectors.joining("; "));
        } else if (e instanceof ConstraintViolationException) {
            ConstraintViolationException ex = (ConstraintViolationException) e;
            errorMessage = ex.getConstraintViolations().stream()
                            .map(ConstraintViolation::getMessage)
                            .collect(Collectors.joining("; "));
        } else if (e instanceof BindException) {
            BindException ex = (BindException) e;
            errorMessage =  ex.getAllErrors().stream()
                    .map(ObjectError::getDefaultMessage)
                    .collect(Collectors.joining("; "));
        }
        return Result.failed(errorMessage);
    }
10. 总结

通过整合Spring Boot和JSR 303规范中的@Valid@Validated注解,我们可以实现灵活的参数校验机制。这种方式不仅提高了系统的可靠性,也确保了应用程序中参数的有效性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值