0
点赞
收藏
分享

微信扫一扫

使用 @Valid 实现 REST 接口请求参数校验

_刘彦辉 06-22 18:00 阅读 16

为什么需要接口参数校验?

在前后端分离、微服务架构下,接口请求往往来自不可信的客户端或第三方系统,因此必须对输入进行严格验证:

❗常见问题包括:

问题

描述

空值提交

导致 NPE 异常

非法格式

如手机号、邮箱格式错误

越界数据

如年龄为负数、价格为负等

安全loudong

SQL zhuru、XSS gongji等

使用 @Valid 可以帮助我们在进入业务逻辑之前就拦截这些非法请求,提升系统健壮性。

🧱 示例目标

我们将构建一个简单的用户注册接口,并实现如下功能:

  • 使用 @Valid 对请求体进行字段校验
  • 自定义全局异常处理器捕获 MethodArgumentNotValidException
  • 返回结构化的错误信息给前端
  • 支持多语言国际化提示(可选)

⚙️ 开发环境要求

工具

版本建议

JDK

Java 8 / 11 / 17

IDE

IntelliJ IDEA / VS Code

构建工具

Maven

Spring Boot

2.6.x / 2.7.x / 3.x

🛠️ 步骤一:添加依赖(Maven)

<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Validation Starter(已包含在 web starter 中,可省略) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>
</dependencies>

💡 注意:如果你使用的是 spring-boot-starter-web,则 validation 是默认引入的,无需额外添加。

🧪 步骤二:创建请求 DTO 类

package com.example.demo.dto;

import jakarta.validation.constraints.*;

public class RegisterRequest {

    @NotBlank(message = "用户名不能为空")
    private String username;

    @Email(message = "邮箱格式不正确")
    private String email;

    @Size(min = 6, max = 20, message = "密码长度应在 6 到 20 个字符之间")
    private String password;

    @Min(value = 18, message = "年龄必须大于等于 18 岁")
    private int age;

    // Getter & Setter
}

▶️ 步骤三:编写 Controller 接口并启用校验

@RestController
@RequestMapping("/api/auth")
public class AuthController {

    @PostMapping("/register")
    public ResponseEntity<String> register(@Valid @RequestBody RegisterRequest request) {
        return ResponseEntity.ok("注册成功!");
    }
}

🧨 步骤四:统一异常处理(Global Exception Handler)

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex) {
        Map<String, String> errors = new HashMap<>();
        ex.getBindingResult().getAllErrors().forEach((error) -> {
            String fieldName = ((FieldError) error).getField();
            String errorMessage = error.getDefaultMessage();
            errors.put(fieldName, errorMessage);
        });
        return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
    }
}

📊 测试请求示例

请求体:

{
  "username": "",
  "email": "not-an-email",
  "password": "123",
  "age": 16
}

返回结果:

{
  "username": "用户名不能为空",
  "email": "邮箱格式不正确",
  "password": "密码长度应在 6 到 20 个字符之间",
  "age": "年龄必须大于等于 18 岁"
}

举报

相关推荐

0 条评论