Spring Boot中如何校验不完整DTO属性并返回正确错误响应?
问题修复方案
核心问题与修复步骤
1. 修复Controller层的两个关键错误
- 你使用了
@GetMapping同时搭配@RequestBody,HTTP规范中GET请求不支持携带请求体,Spring Boot默认不会解析GET请求的请求体,自然无法触发参数校验。请改成@PostMapping/@PutMapping这类支持请求体的请求方法。 - 你在方法参数中添加了
BindingResult,只要加了这个参数,Spring校验失败后不会抛出MethodArgumentNotValidException,而是会把错误信息封装到BindingResult对象中,你没有做错误判断的话,方法会直接走正常返回逻辑,自然拿不到错误响应。要么直接去掉BindingResult参数让异常正常抛出被全局异常处理器捕获,要么在方法开头自行判断校验结果做处理。
修复后Controller示例代码:
@PostMapping("") public ResponseEntity<ApiSuccess> getData(@Valid @RequestBody(required = true) LiteTimeCreateDTO liteTimeCreateDTO, @RequestHeader(value = "User-Access") String header){ ApiSuccess dataError = new ApiSuccess(); dataError.setResponseCode("00"); dataError.setResponseDesc("Get Lite Time Success"); // dataError.setResponseData(datas); return new ResponseEntity<ApiSuccess>(dataError, HttpStatus.CREATED); }
2. 修复全局异常处理器的空指针隐患
你当前全局异常处理代码中apiError.setResponseDesc(ex.getBindingResult().getFieldValue("field") + " Failed");这行写死了字段名field,实际校验失败的字段是customerCode,这里会拿到null,最终返回的描述会变成null Failed,建议改成通用描述或者动态获取错误字段:
// 示例修改为通用错误描述 apiError.setResponseDesc("参数校验失败");
3. 优化DTO校验注解(非必须,建议调整)
- DTO中的
@NotFound是Hibernate ORM的数据库查询注解,和参数校验无关,可以直接删除。 - 字符串类型的非空校验只保留
@NotBlank即可,@NotNull、@NotEmpty的校验规则已经被@NotBlank包含,冗余注解会重复触发校验逻辑,优化后代码:
import javax.validation.constraints.Email; import javax.validation.constraints.NotBlank; import lombok.Data; @Data public class LiteTimeCreateDTO { @NotBlank(message = "Customer Code is required") private String customerCode; @NotBlank(message = "Customer Code2 is required") private String customerCode2; @Email private String customerCode3; }
按以上步骤修改后,缺失customerCode参数时,全局异常处理器就会正常捕获校验异常,返回你定义的ApiError格式响应。
内容的提问来源于stack exchange,提问作者Adam Abdullah
相关产品推荐
相关产品推荐

