如何自定义Spring Boot Validation的HTTP响应格式?
自定义Spring Boot Validation的异常响应格式
问题场景
项目中使用Spring Boot Validation做参数校验,相关配置及现象如下:
Gradle依赖配置
implementation 'org.springframework.boot:spring-boot-starter-validation'
请求实体代码
import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import com.fasterxml.jackson.annotation.JsonInclude; @JsonInclude(JsonInclude.Include.NON_EMPTY) public class ApiTransactionRequest { private String id; @NotNull private String transaction_id; @NotNull private String apiOperation; @NotNull // 其他字段... }
异常日志及默认响应
测试时日志抛出参数校验异常:
WARN 28840 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public org.springframework.http.ResponseEntity
默认返回的HTTP响应格式:
{ "timestamp": "2022-12-05T09:58:55.011+00:00", "status": 400, "error": "Bad Request", "path": "/transactions" }
期望替换为自定义响应格式:
{ "date": "2022-12-05", "status": 400.03, "error": "Transaction id is invalid", "message": "Transaction id is not null" }
解决方法
1. 定义自定义响应实体类
创建与目标格式匹配的实体类,用于封装自定义响应数据:
import java.time.LocalDate; public class CustomValidationErrorResponse { private LocalDate date; private double status; private String error; private String message; // Getter、Setter方法 public LocalDate getDate() { return date; } public void setDate(LocalDate date) { this.date = date; } public double getStatus() { return status; } public void setStatus(double status) { this.status = status; } public String getError() { return error; } public void setError(String error) { this.error = error; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
(若项目已引入Lombok,可直接用@Data注解替代手动编写Getter/Setter)
2. 实现全局异常处理器
通过@RestControllerAdvice和@ExceptionHandler捕获参数校验异常,转换为自定义响应:
import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import java.time.LocalDate; @RestControllerAdvice public class GlobalValidationExceptionHandler { @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<CustomValidationErrorResponse> handleValidationExceptions(MethodArgumentNotValidException ex) { CustomValidationErrorResponse response = new CustomValidationErrorResponse(); // 获取首个校验失败的字段信息(如需处理多字段,可遍历getFieldErrors()集合) FieldError fieldError = ex.getBindingResult().getFieldErrors().get(0); String fieldName = fieldError.getField(); // 组装自定义响应内容 response.setDate(LocalDate.now()); response.setStatus(400.03); // 自定义业务细分状态码 response.setError(fieldName.replace("_", " ") + " is invalid"); response.setMessage(fieldName.replace("_", " ") + " is not null"); return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST); } }
3. 扩展说明
- 若需返回多字段校验错误,可将
CustomValidationErrorResponse中的error和message改为集合类型,遍历ex.getBindingResult().getFieldErrors()收集所有错误信息。 - 字段名中的下划线替换为空格是为了匹配示例格式,可根据实际业务需求调整字符串处理逻辑。
- 自定义的
400.03为业务细分状态码,HTTP响应的状态码仍保持400,符合HTTP协议规范。
内容的提问来源于stack exchange,提问作者nofomopls
相关产品推荐
相关产品推荐

