@FacesConverter(forClass = Clazz.class) 和 p:calendar
@FacesConverter(forClass = Clazz.class) and p:calendar
基本 Joda 时间转换器(代码对于本线程的上下文来说绝对是多余的):
@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.
}
}
}
为什么它不能与使用 converter
属性明确指定的 <p:calendar>
unless/until 一起使用?
<p:calendar converter="#{dateTimeConverter}" value="{bean.dateTimeValue}" .../>
与其他组件一样,无需提及 converter
属性即可正常工作,因为转换器装饰有
@FacesConverter(forClass = DateTime.class)
<p:calendar>
不支持此功能吗?
使用 PrimeFaces 5.2 和 JSF 2.2.12。
如果 class 有转换器,则基于 5.2 CalendarRenderer#encodeEnd()
, it uses CalendarUtils#getValueAsString()
to obtain the value for output. It indeed doesn't consult via Application#createConverter(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
检查,在相反的情况下,通过 class 从应用程序中获取转换器,如下所示:
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
中还有其他一些地方实现了这个 could/should(并且他们实际上正在执行 instanceof
检查,但没有将其委托给转换器 class,如果有的话)。
基本 Joda 时间转换器(代码对于本线程的上下文来说绝对是多余的):
@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.
}
}
}
为什么它不能与使用 converter
属性明确指定的 <p:calendar>
unless/until 一起使用?
<p:calendar converter="#{dateTimeConverter}" value="{bean.dateTimeValue}" .../>
与其他组件一样,无需提及 converter
属性即可正常工作,因为转换器装饰有
@FacesConverter(forClass = DateTime.class)
<p:calendar>
不支持此功能吗?
使用 PrimeFaces 5.2 和 JSF 2.2.12。
如果 class 有转换器,则基于 5.2 CalendarRenderer#encodeEnd()
, it uses CalendarUtils#getValueAsString()
to obtain the value for output. It indeed doesn't consult via Application#createConverter(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
检查,在相反的情况下,通过 class 从应用程序中获取转换器,如下所示:
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
中还有其他一些地方实现了这个 could/should(并且他们实际上正在执行 instanceof
检查,但没有将其委托给转换器 class,如果有的话)。