我想确保只通过WebUI输入1.1.1900和31.12.2100之间的日期值。因此,我创建了@Date
注释和相应的验证器实现DateValidator.java
。
在我的实体类中,日期字段用@Date
注释。每当我输入无效的日期值时,@Date
注释中的默认消息将显示在全局<p:messages .../>
中,但输入字段未标记为无效,因为输入空值时会执行此操作!
当我输入一个空值时,@ {No .NotNull验证在PROCESS_VALIDATION
阶段失败,显示错误消息,输入字段突出显示,然后执行RENDER_RESPONSE
阶段。
如果日期值无效,则会显示错误消息,但同时会执行UPDATE_MODEL_VALUES
,UPDATE_MODEL_VALUES
和RENDER_RESPONSE
!
Date.java
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.ANNOTATION_TYPE,ElementType.CONSTRUCTOR,ElementType.PARAMETER})
@Retention(value = RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {DateValidator.class})
@Documented
public @interface Date {
String message() default "Invalid Date";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.ANNOTATION_TYPE,ElementType.CONSTRUCTOR,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface List {
Date[] value();
}
}
DateValidator.java
public class DateValidator implements ConstraintValidator<Date, Calendar> {
@Override
public void initialize(Date date) {}
/**
* Returns {@code true}, if Date of Calendar is between 1.1.1900 and 31.12.2100
*
* @param calendar
* @param constraintValidatorContext
* @return
*/
@Override
public boolean isValid(Calendar calendar, ConstraintValidatorContext constraintValidatorContext) {
if (Optional.ofNullable(calendar).isPresent()) {
if (calendar.compareTo(minDate) == -1) {
return false;
}
if (calendar.compareTo(maxDate) == 1) {
return false;
}
}
return true;
}
private static Calendar minDate = new GregorianCalendar(1900, 0, 1);
private static Calendar maxDate = new GregorianCalendar(2100, 11, 31);
}
Entity.java
public class Entity {
private java.util.Calendar date;
@NotNull
@Date
@Temporal(TemporalType.TIMESTAMP)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = MisEntity.DATETIME_PATTERN)
@Column(name = "date", nullable = false)
public java.util.Calendar getDate() {
return date;
}
}
page.xhtml
<p:messages id="messages" autoUpdate="true" closable="true" showDetail="true"/>
<p:outputLabel for="date" ="#{bundle['date']}"/>
<p:calendar id="date" showButtonPanel="true" showOn="button"
required="true"
value="#{bean.date}"
mask="true" pattern="dd.MM.yyyy HH:mm">
<f:convertDateTime pattern="#{component.pattern}"/>
</p:calendar>
当我实现FacesValidator
并对输入字段使用此验证器时,验证将失败PROCESS_VALIDATIONS
中的无效值,
显示错误消息,突出显示无效字段,RENDER_RESPONSE
是下一阶段。
DateValidator2.java
@FacesValidator("my.company.web.validation.DateValidator")
public class DateValidator implements Validator {
@Override
public void validate(FacesContext facesContext, UIComponent uiComponent, Object value) throws ValidatorException {
boolean valid = false;
if (Optional.ofNullable(value).isPresent() && value instanceof Date) {
Calendar calendar = GregorianCalendar.getInstance();
calendar.setTime((Date) value);
valid = calendar.compareTo(minDate) != -1 && calendar.compareTo(maxDate) != 1;
}
if (!valid) {
FacesMessage msg = new FacesMessage("Invalid date");
msg.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(msg);
}
}
private static Calendar minDate = new GregorianCalendar(1900, 0, 1);
private static Calendar maxDate = new GregorianCalendar(2100, 11, 31);
}
page2.xhtml
<p:messages id="messages" autoUpdate="true" closable="true" showDetail="true"/>
<p:outputLabel for="date" ="#{bundle['date']}"/>
<p:calendar id="date" showButtonPanel="true" showOn="button"
required="true"
value="#{bean.date}"
mask="true" pattern="dd.MM.yyyy HH:mm">
<f:convertDateTime pattern="#{component.pattern}"/>
<f:validator validatorId="my.company.web.validation.DateValidator"/>
</p:calendar>
所以问题是,如何使用也突出显示无效输入字段的ConstraintValidator
- 这应该是可能的,因为@NotNull
会按预期执行此操作!
我有一个很大的域模型,我希望使用Calendar
为每个@Date
字段添加注释,我不希望使用<f:validator validatorId=".."/>