You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 04:52:55