返回

揭开参数验证的优雅秘诀:SpringBoot中的@Valid与全局处理器

后端

SpringBoot中@Valid注解+Exception全局处理器优雅处理参数验证

引言

在SpringBoot应用程序开发中,参数验证是必不可少的环节,它确保了请求数据的准确性和有效性。Spring提供了强大的参数验证注解@Valid,搭配Exception全局处理器,我们可以优雅地处理验证失败的情况,让代码更加简洁和可维护。

一、为什么使用@Valid来验证参数

参数验证至关重要,因为它:

  • 确保数据完整性: 验证请求参数的有效性,防止脏数据污染系统。
  • 提高代码可维护性: 集中管理参数验证逻辑,避免在不同方法中重复代码。
  • 简化异常处理: 当验证失败时,触发异常并通过全局处理器统一处理。

二、@Valid注解的作用

@Valid注解应用于方法参数或实体类字段上,用于验证传入的参数是否符合指定的约束。它支持以下验证类型:

  • 基本类型验证:@NotNull@Min@Max
  • 复杂类型验证: 使用自定义注解或javax.validation包中提供的注解,如@Pattern@Email

三、@Valid的相关注解

除了@Valid注解,还有一些相关的注解可增强参数验证功能:

  • @Validated 应用于控制器类或方法上,开启参数验证功能。
  • @RequestBody 用于验证请求体中JSON或XML等复杂类型的参数。
  • @PathVariable 用于验证URI路径变量。
  • @RequestParam 用于验证请求参数(Query String)。

四、使用@Valid进行参数效验步骤

1. 实体类中添加@Valid相关注解

在要验证的实体类中,添加@Valid及其相关的约束注解。例如:

public class User {

    @NotBlank
    private String name;

    @Email
    private String email;
}

2. 接口类中添加

在控制器接口中,使用@Validated注解开启参数验证功能,并使用@RequestBody注解指定要验证的请求体参数。例如:

@RestController
@RequestMapping("/api/users")
@Validated
public class UserController {

    @PostMapping
    public User createUser(@RequestBody @Valid User user) {
        // ...
    }
}

3. 全局异常处理

为了优雅地处理参数验证失败的情况,我们需要定义一个全局异常处理器。例如:

@ControllerAdvice
public class ValidationExceptionHandler implements ExceptionHandler {

    @Override
    public ResponseEntity<Object> handleException(MethodArgumentNotValidException ex, WebRequest request) {
        List<String> errors = ex.getBindingResult().getAllErrors().stream()
                .map(ObjectError::getDefaultMessage)
                .collect(Collectors.toList());
        return ResponseEntity.badRequest().body(new ApiError("Validation failed", errors));
    }
}

五、示例代码

@RestController
@RequestMapping("/api/articles")
@Validated
public class ArticleController {

    @PostMapping
    public Article createArticle(@RequestBody @Valid Article article) {
        // ...
    }
}

public class Article {

    @NotBlank
    private String title;

    @Min(10)
    private int contentLength;
}

@ControllerAdvice
public class ValidationExceptionHandler implements ExceptionHandler {

    @Override
    public ResponseEntity<Object> handleException(MethodArgumentNotValidException ex, WebRequest request) {
        List<String> errors = ex.getBindingResult().getAllErrors().stream()
                .map(ObjectError::getDefaultMessage)
                .collect(Collectors.toList());
        return ResponseEntity.badRequest().body(new ApiError("Validation failed", errors));
    }
}