Spring Boot中如何对接口DTO而非类DTO进行参数校验?
接口DTO的校验实现方案
针对你用接口定义DTO的场景,可按以下步骤实现tableId的校验:
1. 给接口方法添加校验注解
在BillChargingListDTO接口的getTableId()方法上直接添加校验注解,同时给接口标注@Validated,让Spring识别校验规则:
import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotNull; import org.springframework.validation.annotation.Validated; @Validated public interface BillChargingListDTO { Integer getBillId(); Integer getUserId(); @NotNull(message = "tableId不能为空") @Min(value = 0, message = "tableId不能小于0") Integer getTableId(); Double getSum(); }
注:
@NotNull用于避免tableId为null的情况,若允许null但非null时必须≥0,可去掉@NotNull只保留@Min。Integer类型本身已限制只能是数字,无需额外加数字格式校验。
2. 在接口使用处触发校验
在Controller的接口方法中,给传入的BillChargingListDTO参数添加@Valid注解,触发校验逻辑:
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; @RestController public class BillController { @PostMapping("/charging") public String submitBill(@Valid @RequestBody BillChargingListDTO billDTO) { // 业务逻辑处理 return "提交成功"; } }
3. 全局捕获校验异常并返回提示
创建全局异常处理器,捕获校验失败的异常,返回自定义提示信息:
import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.validation.BindException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import jakarta.validation.ConstraintViolationException; import java.util.HashMap; import java.util.Map; @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(BindException.class) public ResponseEntity<Map<String, String>> handleBindException(BindException e) { Map<String, String> errorMap = new HashMap<>(); e.getBindingResult().getFieldErrors().forEach(error -> { errorMap.put(error.getField(), error.getDefaultMessage()); }); return new ResponseEntity<>(errorMap, HttpStatus.BAD_REQUEST); } @ExceptionHandler(ConstraintViolationException.class) public ResponseEntity<Map<String, String>> handleConstraintViolationException(ConstraintViolationException e) { Map<String, String> errorMap = new HashMap<>(); e.getConstraintViolations().forEach(violation -> { // 提取字段名,将"getTableId"转为"tableId" String fieldPath = violation.getPropertyPath().toString(); String fieldName = fieldPath.replace("get", ""); fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1); errorMap.put(fieldName, violation.getMessage()); }); return new ResponseEntity<>(errorMap, HttpStatus.BAD_REQUEST); } }
需同时处理
BindException(请求体参数绑定校验失败)和ConstraintViolationException(接口方法级校验失败),确保不同场景下都能返回正确的提示信息。
补充说明
如果你的BillChargingListDTO是通过Spring Data Projections等方式生成的代理实现类,上述方案依然有效,Spring会代理接口并识别方法上的校验注解;如果是自定义实现类,只要实现该接口,校验规则也会被继承。
内容的提问来源于stack exchange,提问作者Colony
相关产品推荐
相关产品推荐

