我怎样才能使 Wicket 7 与 Java 8 中的 java.time 一起工作?

How can I bring Wicket 7 to work with java.time from Java 8?

我有很多bean,都使用LocalDate 和LocalDateTime。 Wicket 中的 DateTextField 和所有其他小部件(如 DatePicker)仅适用于 java.util.Date。有什么方法可以注入一个转换器到 Wicket 7 中,以便它使用 LocalDate 或 LocalDateTime?

豆子长这样:

public class SomeBean {
  Long id = null;
  LocalDate since = null;
  // plus getters and setters
}

Wicket 表单当前使用 CompoundPropertyModel

CompoundPropertyModel<SomeBean> model = new CompundPropertyModel<>( bean );

您可以将 LocalDate 等模型包装在 IModel<java.util.Date> 中,例如

public static class LocalDateModel implements IModel<java.util.Date> {
    private IModel<LocalDate> localDateModel;
    public LocalDateModel(IModel<LocalDate> localDateModel){
        this.localDateModel = localDateModel;
    }


    @Override
    public Date getObject() {
        return convertLocalDateToUtilDateSomehow(localDateModel.getObject());
    }

    @Override
    public void setObject(Date object) {
        localDateModel.setObject(convertUtilDateToLocalDateSomehow(object));
    }

    @Override
    public void detach() {
        localDateModel.detach();
    }
}

如果您随后将这样的模型输入到您要使用的表单组件中,它应该可以正常工作。

如果您希望 CompoundPropertyModel 自动提供此类包装模型,您需要扩展它并覆盖它的 CompoundPropertyModel#wrapOnInheritance(Component component) 方法以推断需要包装模型。像

@Override
public <C> IWrapModel<C> wrapOnInheritance(Component component)
{
    IWrapModel<C> actualModel = super.wrapOnInheritance(component);
    if (actualModel.getObject() instanceOf LocalDate) {
        return new LocalDateModelButAlsoWrapping(actualModel);
    } else {
        return actualModel;
    }
}

毫无疑问,LocalDateModelButAlsoWrapping 只是上述 LocalDateModel 示例的扩展,但它也实现了 IWrapModel<T>

如果您使用此扩展而不是常规 CompoundPropertyModel,它将检测字段何时为 LocalDate 并为组件(例如您的 DateTextField)提供模型,这些组件被包装成看起来像java.util.Date 模型。

虽然我给你的代码片段很脏(你可能不应该让模型对象推断它的类型)因为我提供它只是为了说明一般机制,所以我建议你设计自己的方式来推断预期的对象类型(例如,您可以检查 Component 参数是否为 DateTextField),但这是我可以想象的解决方案的总体方向。

您可以注册自己的转换器:

https://ci.apache.org/projects/wicket/guide/7.x/guide/forms2.html#forms2_3

@Override
protected IConverterLocator newConverterLocator() {
    ConverterLocator defaultLocator = new ConverterLocator();

    defaultLocator.set(Pattern.class, new RegExpPatternConverter());

    return defaultLocator;
}

相关:https://issues.apache.org/jira/browse/WICKET-6200

您可以简单地从 Wicket 8 向后移植转换器 类。您会发现这些附加到此提交:https://issues.apache.org/jira/browse/WICKET-6200(AbstractJavaTimeConverter 和您需要的任何子类 LocalDate, LocalDateTime、LocalTime 等)

当然,这对 DateTextField 没有帮助,因为它具有硬编码的 Date 类型参数。为此,您可以使用上述转换器创建自己的 sub类,或者使用常规标签和 TextField,并在全局注册转换器,如下所示:

@Override
protected IConverterLocator newConverterLocator() {
    ConverterLocator converterLocator = new ConverterLocator();
    converterLocator.set(LocalDateTime.class, new LocalDateTimeConverter());
    converterLocator.set(LocalDate.class, new LocalDateConverter());
    converterLocator.set(LocalTime.class, new LocalDateConverter());
    return converterLocator;
}