本文介绍了@FacesConverter(forClass = Clazz.class)和p:calendar的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基本Joda时间转换器(该线程的上下文中的代码绝对是多余的):

Basic Joda Time converter (the code is absolutely superfluous for the context of this thread) :

@Named
@ApplicationScoped
@FacesConverter(forClass = DateTime.class)
public class DateTimeConverter implements Converter {

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        if (value == null || value.isEmpty()) {
            return null;
        }

        try {
            return DateTimeFormat.forPattern("dd-MMM-yyyy hh:mm:ss aa Z").parseDateTime(value).withZone(DateTimeZone.UTC);
        } catch (IllegalArgumentException | UnsupportedOperationException e) {
            throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, null, "Message"), e);
        }
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        if (value == null) {
            return "";
        }

        if (!(value instanceof DateTime)) {
            throw new ConverterException("Error");
        }

        try {
            return DateTimeFormat.forPattern("dd-MMM-yyyy hh:mm:ss aa Z").print(((DateTime) value).withZone(DateTimeZone.forID("zoneId")));
        } catch (IllegalArgumentException e) {
            throw new ConverterException("Error", e); // Not required.
        }
    }
}

为什么不起作用< p:calendar> ,除非/直到使用 converter 属性明确指定?

Why does it not work with a <p:calendar> unless/until it is explicitly specified by using the converter attribute?

<p:calendar converter="#{dateTimeConverter}" value="{bean.dateTimeValue}" .../>

与其他组件一样,它可以正常工作而无需提及转换器属性,因为转换器用

Like other components, it is expected to work without mentioning the converter attribute because the converter is decorated with

@FacesConverter(forClass = DateTime.class)

< p:calendar> 不支持此功能吗?

使用PrimeFaces 5.2和JSF 2.2.12。

Using PrimeFaces 5.2 and JSF 2.2.12.

推荐答案

基于在5.2的,它使用获取输出值。实际上,它不会通过(如果有按类别分类的转换器)。

Based on 5.2's CalendarRenderer#encodeEnd(), it uses CalendarUtils#getValueAsString() to obtain the value for output. It indeed doesn't consult via Application#createConverter(Class) if there's a converter by class.

51          //first ask the converter
52          if(calendar.getConverter() != null) {
53              return calendar.getConverter().getAsString(context, calendar, value);
54          }
55          //Use built-in converter
56          else {
57              SimpleDateFormat dateFormat = new SimpleDateFormat(calendar.calculatePattern(), calendar.calculateLocale(context));
58              dateFormat.setTimeZone(calendar.calculateTimeZone());
59              
60              return dateFormat.format(value);
61          }

这可以确认您观察到的行为。最好向PrimeFaces家伙创建一个问题报告,要求添加一个 instanceof Date 支票,在相反的情况下,请从应用程序中按类获取转换器,如下所示: :

That confirms the behavior you observed. You'd best create an issue report to PrimeFaces guys which requests adding an instanceof Date check in place, and in the opposite case obtain the converter by class from the application something like below:

Converter converter = context.getApplication().createConverter(value.getClass());
if (converter != null) {
    return converter.getAsString(context, calendar, value);
}
else {
    throw new IllegalArgumentException(value.getClass());
}                    

鉴于Java8越来越多地使用 java.time API。顺便说一下,在 CalendarRenderer CalendarUtils 中还有一些其他地方可以/应该实现(以及在哪里实际上是在执行 instanceof 检查,但没有按类将其委派给转换器(如果有的话)。

This would indeed make sense given the increasing use of Java8's java.time API. There are by the way a few other places in CalendarRenderer and CalendarUtils where this could/should be implemented (and where they are actually performing an instanceof check, but not delegating it to the converter by class, if any).

这篇关于@FacesConverter(forClass = Clazz.class)和p:calendar的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-19 02:31