能否让@Min校验注解message中的${id}获取Person类的id字段值?
Great question! Unfortunately, standard JSR-380 (Bean Validation) annotations like @Min don't support directly referencing other fields of the same object in their message attribute using ${id} out of the box. The EL expressions available in default validation messages only have access to a limited set of context variables (like ${validatedValue} for the current field's value, or ${value} for the annotation's parameter), not other properties of the bean being validated.
But don't worry—there are two solid workarounds to achieve what you want:
1. Create a custom field-level validator
This approach gives you full control over the validation logic and error message customization. Here's how to implement it:
Step 1: Define the custom validation annotation
import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.*; @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = AgeValidator.class) public @interface ValidAge { String message() default "Age of person id '{id}' must be greater than 0."; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
Step 2: Implement the validator logic
import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; public class AgeValidator implements ConstraintValidator<ValidAge, Integer> { @Override public boolean isValid(Integer age, ConstraintValidatorContext context) { if (age == null || age <= 0) { // Access the root bean (your Person instance) Object rootBean = context.getRootBean(); if (rootBean instanceof Person) { Person person = (Person) rootBean; // Replace the {id} placeholder with the actual id value String originalMessage = context.getDefaultConstraintMessageTemplate(); String customizedMessage = originalMessage.replace( "{id}", person.getId() != null ? person.getId() : "unknown" ); // Disable the default message and add our customized one context.disableDefaultConstraintViolation(); context.buildConstraintViolationWithTemplate(customizedMessage) .addConstraintViolation(); } return false; } return true; } }
Step 3: Update your Person class
public class Person { private String id; @ValidAge private int age; // Don't forget to add getters (the validator needs access to id) public String getId() { return id; } public void setId(String id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
2. Use Hibernate Validator's @ScriptAssert (class-level validation)
If you're using Hibernate Validator (the most common Bean Validation implementation), you can use the @ScriptAssert annotation to add class-level validation. This lets you reference other fields via the _this variable in the message:
import org.hibernate.validator.constraints.ScriptAssert; @ScriptAssert( lang = "javascript", script = "_this.age > 0", message = "Age of person id '{_this.id}' must be greater than 0." ) public class Person { private String id; private int age; // Getters and setters are required here too public String getId() { return id; } public void setId(String id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
Note that @ScriptAssert is a Hibernate-specific extension, so it won't work with other Bean Validation implementations.
Key Notes
- Make sure your bean has getters for the fields you want to reference—validators need access to those values.
- Handle null values gracefully (like we did with "unknown" if
idis null) to avoid NullPointerExceptions.
内容的提问来源于stack exchange,提问作者Anna

