JSF定制转换器日期 - 线程安全吗?
-
09-10-2019 - |
题
我创建了一个自定义 Converter
在JSF 1.2中转换 Date
对象。日期具有非常特殊的格式。我已经使用Core Java实现了转换器 SimpleDateFormat
使用下面的代码注释中显示的格式字符串进行转换。这一切都很好。
我的问题是关于线程安全的。这 SimpleDateFormat
API文档指出它不是线程安全的。因此,我为转换器对象的每个实例创建了一个单独的日期格式对象实例。但是,我不确定这是否足够。我的 DateFormat
对象作为成员存储 DTGDateConverter
.
问题:每个线程是否同时访问JSF中转换器对象的相同实例?
如果答案是肯定的,那么我的转换器可能有风险。
/**
* <p>JSF Converter used to convert from java.util.Date to a string.
* The SimpleDateFormat format used is: ddHHmm'Z'MMMyy.</p>
*
* <p>Example: October 31st 2010 at 23:59 formats to 312359ZOCT10</p>
*
* @author JTOUGH
*/
public class DTGDateConverter implements Converter {
private static final Logger logger =
LoggerFactory.getLogger(DTGDateConverter.class);
private static final String EMPTY_STRING = "";
private static final DateFormat DTG_DATE_FORMAT =
MyFormatterUtilities.createDTGInstance();
// The 'format' family of core Java classes are NOT thread-safe.
// Each instance of this class needs its own DateFormat object or
// runs the risk of two request threads accessing it at the same time.
private final DateFormat df = (DateFormat)DTG_DATE_FORMAT.clone();
@Override
public Object getAsObject(
FacesContext context,
UIComponent component,
String stringValue)
throws ConverterException {
Date date = null;
// Prevent ParseException when an empty form field is submitted
// for conversion
if (stringValue == null || stringValue.equals(EMPTY_STRING)) {
date = null;
} else {
try {
date = df.parse(stringValue);
} catch (ParseException e) {
if (logger.isDebugEnabled()) {
logger.debug("Unable to convert string to Date object", e);
}
date = null;
}
}
return date;
}
@Override
public String getAsString(
FacesContext context,
UIComponent component,
Object objectValue)
throws ConverterException {
if (objectValue == null) {
return null;
} else if (!(objectValue instanceof Date)) {
throw new IllegalArgumentException(
"objectValue is not a Date object");
} else {
// Use 'toUpperCase()' to fix mixed case string returned
// from 'MMM' portion of date format
return df.format(objectValue).toUpperCase();
}
}
}
解决方案
每个线程是否同时访问JSF中转换器对象的同一实例?
取决于您如何使用转换器。如果您使用
<h:inputWhatever>
<f:converter converterId="converterId" />
</h:inputWhatever>
然后,将为视图中的每个输入元素创建一个新实例,即ThreadSafe(期望Eddeuser在同一会话中的两个浏览器选项卡中具有两个相同的视图,并同时在两种视图上发出回发)) 。
但是,如果您使用
<h:inputWhatever converter="#{applicationBean.converter}" />
然后,将在整个应用程序的所有视图中共享相同的实例,因此不是线程保护。
但是,您要克隆静态 DataFormat
实例每次创建转换器时。该部分已经不是线程安全。您可能会在更改其内部状态时将实例克隆起来,因为它已被其他地方使用。同样,克隆现有实例不一定比创建新实例便宜。
我建议只声明它的螺纹插座(即方法块内部),无论您如何使用转换器。如果创建 DateFormat
每次都是一个主要问题(您介绍了吗?),然后考虑通过 Jodatime.
其他提示
日期格式不同步。建议为每个线程创建单独的格式实例。如果多个线程同时访问格式,则必须在外部同步。
是的,这里不是线程的安全。
将其放置到方法并创建每个线程实例