PrimeFaces:p:inputText日期自定义验证的输入触发与转换问题
解决方案
1. 将验证触发时机改为失去焦点
修改页面中的<p:ajax>标签,把事件从change替换为blur,同时添加process="@this"明确只处理当前组件,这样只有当输入框失去焦点时才会触发验证和后续更新操作:
<p:ajax event="blur" process="@this" update=":contentform:tabView:milestoneWarningPanel messageMilestoneTarget" />
2. 重构验证器,修复ClassCastException
废弃Date类的过时方法,改用更安全的日期处理逻辑,避免不同日历实现(如Julian和Gregorian)导致的类型转换异常:
方案A(Java 8+ 推荐)
@Named @FacesValidator("futureOrPresentIgnoreTimeValidator") public class FutureOrPresentIgnoreTimeValidator implements Validator<Date> { @Override public void validate(FacesContext context, UIComponent component, Date value) throws ValidatorException { Boolean adminMode = context.getApplication().evaluateExpressionGet(context, "#{indexController.adminMode}", Boolean.class); if (Boolean.TRUE.equals(adminMode)) { return; } if (value == null) { return; } ZoneId cetZone = ZoneId.of("CET"); LocalDate inputDate = value.toInstant().atZone(cetZone).toLocalDate(); LocalDate today = LocalDate.now(cetZone); if (inputDate.isBefore(today)) { throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Das Datum darf nicht in der Vergangenheit liegen", null)); } } }
方案B(兼容Java 7及以下)
@Named @FacesValidator("futureOrPresentIgnoreTimeValidator") public class FutureOrPresentIgnoreTimeValidator implements Validator<Date> { @Override public void validate(FacesContext context, UIComponent component, Date value) throws ValidatorException { Boolean adminMode = context.getApplication().evaluateExpressionGet(context, "#{indexController.adminMode}", Boolean.class); if (Boolean.TRUE.equals(adminMode)) { return; } if (value == null) { return; } TimeZone cetTimeZone = TimeZone.getTimeZone("CET"); Calendar inputCal = Calendar.getInstance(cetTimeZone); inputCal.setTime(value); // 重置时间部分,只保留日期信息 inputCal.set(Calendar.HOUR_OF_DAY, 0); inputCal.set(Calendar.MINUTE, 0); inputCal.set(Calendar.SECOND, 0); inputCal.set(Calendar.MILLISECOND, 0); Calendar todayCal = Calendar.getInstance(cetTimeZone); todayCal.set(Calendar.HOUR_OF_DAY, 0); todayCal.set(Calendar.MINUTE, 0); todayCal.set(Calendar.SECOND, 0); todayCal.set(Calendar.MILLISECOND, 0); if (inputCal.before(todayCal)) { throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Das Datum darf nicht in der Vergangenheit liegen", null)); } } }
额外说明
- 当用户输入无效的中间日期(如
06.06.0002)时,<f:convertDateTime>会先触发转换错误,此时验证器不会执行,页面会自动显示转换相关的错误提示,无需额外处理。 - 若使用方案A,需确保项目环境支持Java 8及以上版本。
内容的提问来源于stack exchange,提问作者Hypernia
相关产品推荐
相关产品推荐

