You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring WebFlux中如何校验请求DTO?

Spring WebFlux中如何校验请求DTO?

很多刚接触Spring WebFlux的朋友,都会疑惑怎么校验请求DTO——毕竟在传统的Spring MVC里,只要给DTO加个@NotBlank、@Email这类校验注解,再在控制器参数上标注@Valid就搞定了,那WebFlux里是不是不一样?别慌,其实思路差不多,只是细节上有一点点区别,下面我就给你一步步说清楚。

首先先复习下传统Spring MVC的做法,方便对比:
我们会先给DTO类加上校验注解,比如:

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Size;

public class UserSignupRequestDTO {
    @NotBlank(message = "邮箱不能为空")
    @Email(message = "请输入合法的邮箱格式")
    private String email;

    @NotBlank(message = "密码不能为空")
    @Size(min = 6, max = 20, message = "密码长度需在6到20位之间")
    private String password;

    // 省略getter、setter
}

然后在控制器方法的参数前加上@Valid,Spring就会自动帮我们做校验:

@PostMapping("/signup")
public ResponseEntity<String> signup(@Valid @RequestBody UserSignupRequestDTO signupRequest) {
    // 处理注册逻辑
    return ResponseEntity.ok("注册成功");
}

那到了WebFlux里,该怎么操作呢?其实分几步就能搞定:

1. 确保引入校验依赖

首先要保证项目里有Spring Validation的依赖,如果是Spring Boot项目,直接在pom.xml(Maven)或者build.gradle(Gradle)里加入:
Maven

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

Gradle

implementation 'org.springframework.boot:spring-boot-starter-validation'

WebFlux本身不会默认包含这个依赖,所以必须手动引入,不然校验注解根本不会生效。

2. DTO类的校验注解和MVC完全一致

不用改任何东西,还是用jakarta.validation.constraints包下的那些注解,比如刚才的UserSignupRequestDTO直接复用就行,写法和MVC里一模一样。

3. 控制器里的校验写法

WebFlux里我们通常用Mono或者Flux来接收请求体,这时候要把@Valid直接标注在Mono/Flux前面,而不是泛型里面,比如:

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import jakarta.validation.Valid;
import reactor.core.publisher.Mono;

@RestController
public class UserController {

    @PostMapping("/signup")
    public Mono<ResponseEntity<String>> signup(@Valid @RequestBody Mono<UserSignupRequestDTO> signupRequestMono) {
        return signupRequestMono
                .map(dto -> {
                    // 这里写你的注册业务逻辑,比如保存用户到数据库
                    return ResponseEntity.ok("注册成功");
                });
    }
}

4. 处理校验失败的异常

当校验不通过时,WebFlux会抛出ConstraintViolationException,我们可以用两种方式处理:

方式一:在接口里单独处理

通过onErrorResume来捕获异常,返回友好的错误响应:

@PostMapping("/signup")
public Mono<ResponseEntity<String>> signup(@Valid @RequestBody Mono<UserSignupRequestDTO> signupRequestMono) {
    return signupRequestMono
            .map(dto -> ResponseEntity.ok("注册成功"))
            .onErrorResume(ConstraintViolationException.class, ex -> {
                // 提取错误信息
                String errorMsg = ex.getConstraintViolations()
                        .stream()
                        .map(violation -> violation.getMessage())
                        .findFirst()
                        .orElse("请求参数校验失败");
                return Mono.just(ResponseEntity.badRequest().body(errorMsg));
            });
}

方式二:全局异常处理器(更推荐)

如果多个接口都需要处理校验异常,写一个全局异常处理器会更优雅,不用每个接口都重复写错误处理逻辑:

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import jakarta.validation.ConstraintViolationException;
import java.util.stream.Collectors;

@RestControllerAdvice
public class GlobalValidationExceptionHandler {

    @ExceptionHandler(ConstraintViolationException.class)
    public ResponseEntity<String> handleValidationException(ConstraintViolationException ex) {
        String errorMessages = ex.getConstraintViolations()
                .stream()
                .map(violation -> violation.getMessage())
                .collect(Collectors.joining("; "));
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorMessages);
    }
}

这样一来,所有接口的校验异常都会被这个处理器捕获,统一返回格式化的错误信息。

总结一下,WebFlux里的DTO校验和MVC的核心逻辑是一致的,只是因为响应式编程的特性,在控制器参数的标注和异常处理上有一点点区别,只要跟着上面的步骤来,就能轻松搞定啦!

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 13:20:31