如何从ConstraintViolationException中仅提取校验提示信息
问题描述
我编写了如下代码处理ConstraintViolationException,期望仅返回校验约束中的提示信息:
@ExceptionHandler(ConstraintViolationException.class) @ResponseStatus(BAD_REQUEST) @ResponseBody public final ResponseEntity<ErrorMessage> handleConstraintViolationException( ConstraintViolationException ex ) { ErrorMessage errorMessage = new ErrorMessage(ex.getMessage(), "400"); return new ResponseEntity<>(errorMessage, BAD_REQUEST); }
实体类代码如下:
package com.courses.restapi.entities.courses; import com.courses.restapi.entities.BaseEntity; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.Table; import jakarta.validation.constraints.DecimalMin; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import java.math.BigDecimal; @Entity @Table(name = "courses") @Setter @Getter @AllArgsConstructor @NoArgsConstructor public class Course extends BaseEntity { @NotNull @NotBlank(message = "title may not be blank") @Column( name = "title", length = 100) @Size(max = 100 ,message = " title may not be longer than 100 ") private String title; @NotNull @NotBlank(message = "description may not be blank") @Column( name = "description", length = 1000) @Size(max = 1000 ,message = " description may not be longer than 100 ") private String description; @NotNull(message = " price may not be null") @DecimalMin("1.00") private BigDecimal price; }
当尝试添加描述为空的Course时,返回响应如下:
{ "message": "Validation failed for classes [com.courses.restapi.entities.courses.Course] during persist time for groups [jakarta.validation.groups.Default, ]\nList of constraint violations:[\n\tConstraintViolationImpl{interpolatedMessage='description may not be blank', propertyPath=description, rootBeanClass=class com.courses.restapi.entities.courses.Course, messageTemplate='description may not be blank'}\n]", "code": "400" }
我希望仅返回"description may not be blank"这类提示信息,尝试替换为Exception类型处理仍未解决问题,该如何实现?
解决方案
ConstraintViolationException本身包含所有校验失败的约束信息集合,无需直接使用ex.getMessage(),而是通过ex.getConstraintViolations()提取目标提示文本即可。
场景1:仅返回第一条错误提示
如果只需要展示第一个触发的校验错误,修改异常处理器如下:
import jakarta.validation.ConstraintViolation; import java.util.stream.Collectors; @ExceptionHandler(ConstraintViolationException.class) @ResponseStatus(BAD_REQUEST) @ResponseBody public final ResponseEntity<ErrorMessage> handleConstraintViolationException(ConstraintViolationException ex) { // 获取第一条违规提示,默认值为通用错误文本 String errorMsg = ex.getConstraintViolations() .stream() .findFirst() .map(ConstraintViolation::getMessage) .orElse("参数校验失败"); ErrorMessage errorMessage = new ErrorMessage(errorMsg, "400"); return new ResponseEntity<>(errorMessage, BAD_REQUEST); }
场景2:返回所有校验错误提示
如果存在多个校验失败(比如标题和描述同时为空),可以将所有提示拼接或返回列表:
拼接成字符串返回
import jakarta.validation.ConstraintViolation; import java.util.stream.Collectors; @ExceptionHandler(ConstraintViolationException.class) @ResponseStatus(BAD_REQUEST) @ResponseBody public final ResponseEntity<ErrorMessage> handleConstraintViolationException(ConstraintViolationException ex) { // 用分号拼接所有错误提示 String errorMsg = ex.getConstraintViolations() .stream() .map(ConstraintViolation::getMessage) .collect(Collectors.joining("; ")); ErrorMessage errorMessage = new ErrorMessage(errorMsg, "400"); return new ResponseEntity<>(errorMessage, BAD_REQUEST); }
返回错误提示列表(需调整ErrorMessage结构)
如果你的ErrorMessage支持接收列表类型的消息字段,直接返回集合即可:
import jakarta.validation.ConstraintViolation; import java.util.List; import java.util.stream.Collectors; @ExceptionHandler(ConstraintViolationException.class) @ResponseStatus(BAD_REQUEST) @ResponseBody public final ResponseEntity<ErrorMessage> handleConstraintViolationException(ConstraintViolationException ex) { List<String> errorMessages = ex.getConstraintViolations() .stream() .map(ConstraintViolation::getMessage) .collect(Collectors.toList()); // 假设ErrorMessage有对应构造方法或setter接收列表参数 ErrorMessage errorMessage = new ErrorMessage(errorMessages, "400"); return new ResponseEntity<>(errorMessage, BAD_REQUEST); }
核心说明
ConstraintViolation.getMessage()会直接返回你在校验注解中定义的自定义提示(比如@NotBlank(message = "description may not be blank")的内容)- 避免使用
ex.getMessage(),它返回的是包含类信息、校验阶段的完整错误描述,并非简洁的业务提示
内容的提问来源于stack exchange,提问作者Abdulaziz Alharbi
相关产品推荐
相关产品推荐

