f:convertDateTime支持Java8 LocalDate/LocalDateTime?

alf*_*onx 7 java jsf java-8 jsf-2.2

JSF核心标记f:convertDateTime可以格式化java.util.Date对象.Date类有许多不推荐使用的方法,Java 8提供了新类来显示本地日期和时间:LocalDateTimeLocalDate.

f:convertDateTime无法格式化LocalDateTimeLocalDate.

有没有人知道,如果有一个等价的JSF核心标记convertDateTime可以处理LocalDateTime对象?计划是为将来的版本提供支持,还是提供替代标签?

hin*_*nks 8

只需编写自己的Converter并扩展javax.faces.convert.DateTimeConverter-即可重新使用所有<f:convertDateTime>支持的属性。同样,它也会照顾本地化。不幸的是,编写带有属性的Converter有点复杂。

创建组件
首先编写您自己的扩展转换器javax.faces.convert.DateTimeConverter-只需让超级调用完成所有工作(包括locale-stuff),然后将结果从LocalDate转换为LocalDate。

@FacesConverter(value = LocalDateConverter.ID)
public class LocalDateConverter extends DateTimeConverter {
    public static final String ID = "com.example.LocalDateConverter";

    @Override
    public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String value) {
        Object o = super.getAsObject(facesContext, uiComponent, value);

        if (o == null) {
            return null;
        }

        if (o instanceof Date) {
            Instant instant = Instant.ofEpochMilli(((Date) o).getTime());
            return LocalDateTime.ofInstant(instant, ZoneId.systemDefault()).toLocalDate();
        } else {
            throw new IllegalArgumentException(String.format("value=%s could not be converted to a LocalDate, result super.getAsObject=%s", value, o));
        }
    }

    @Override
    public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object value) {
        if (value == null) {
            return super.getAsString(facesContext, uiComponent,value);
        }

        if (value instanceof LocalDate) {
            LocalDate lDate = (LocalDate) value;
            Instant instant = lDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
            Date date = Date.from(instant);
            return super.getAsString(facesContext, uiComponent, date);
        } else {
            throw new IllegalArgumentException(String.format("value=%s is not a instanceof LocalDate", value));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后创建一个文件LocalDateConverter-taglib.xmlMETA-INF

<facelet-taglib version="2.2"
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facelettaglibrary_2_2.xsd">

    <namespace>http://example.com/LocalDateConverter</namespace>
    <tag>
        <tag-name>convertLocalDate</tag-name>
        <converter>
            <converter-id>com.example.LocalDateConverter</converter-id>
        </converter>
    </tag>
</facelet-taglib>
Run Code Online (Sandbox Code Playgroud)

最后,在web.xml以下位置注册taglib :

<context-param>
    <param-name>facelets.LIBRARIES</param-name>
    <param-value>/META-INF/LocalDateConverter-taglib.xml</param-value>
</context-param>
Run Code Online (Sandbox Code Playgroud)

用法
要在JSF-Page中使用新标签,请添加新Taglib xmlns:ldc="http://example.com/LocalDateConverter"并使用该标签:

<ldc:convertLocalDate type="both" dateStyle="full"/>
Run Code Online (Sandbox Code Playgroud)

  • JSF 2.3 现在支持开箱即用的 `LocalDate` : `&lt;h:outputText value="#{yourBean.yourLocalDateVar}" &gt; &lt;f:convertDateTime type="localDate" dateStyle="long" locale="#{yourBean.yourLocale }" /&gt; &lt;/h:outputText&gt;` (5认同)
  • 如果您针对JSF 2.x Facelets,而不是Facelets 1.x,会更好。否则,您会将JSF 2.x入门程序与旧的/过时的方法混淆。 (3认同)