JSF benutzerdefinierter Konverter für Datum - I ist Thread-sicher?
-
09-10-2019 - |
Frage
Ich habe eine benutzerdefinierte Converter
in JSF 1.2 erstellt Date
Objekte zu konvertieren. Die Termine haben ein ganz besonderes Format. Ich habe meinen Konverter mit der Kern Java SimpleDateFormat
Klasse implementiert, um die Konvertierung zu tun, die Formatierungszeichenfolge in meinem Code Kommentar unten gezeigt. Das alles funktioniert gut.
Meine Frage ist über Thread-Sicherheit. Die SimpleDateFormat
API-Dokumente feststellen, dass es nicht sicher ist Thread. Aus diesem Grund habe ich für jede Instanz von meinem Konverter Objekt eine separate Instanz des Datumsformat-Objekt erstellt. Allerdings bin ich mir nicht sicher, ob dies genug. Mein DateFormat
Objekt als Mitglied des DTGDateConverter
gespeichert wird.
FRAGE: Will zwei Threads Zugriff auf alle gleichzeitig dieselbe Instanz eines Converter Objekt in JSF
Wenn die Antwort Ja ist, dann mein Converter ist wahrscheinlich gefährdet.
/**
* <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();
}
}
}
Lösung
Will zwei Threads Zugriff auf alle gleichzeitig dieselbe Instanz eines Converter Objekt in JSF?
Abhängig von, wie Sie den Konverter. Wenn Sie
<h:inputWhatever>
<f:converter converterId="converterId" />
</h:inputWhatever>
dann eine neue Instanz wird für jedes Eingabeelement in Sicht erstellt werden, der THREAD (erwartet von dem sehr seltenen Rande Fall ist, dass der Enduser zwei identische Ansichten in zwei Browser-Tabs in der gleichen Sitzung hat und gibt gleichzeitig eine Postbacks auf dem beide Ansichten).
Wenn Sie jedoch verwenden
<h:inputWhatever converter="#{applicationBean.converter}" />
dann die gleiche Instanz über alle Blick auf die gesamte Anwendung gemeinsam genutzt werden, was somit nicht THREAD.
Sie sind das Klonen jedoch eine statische DataFormat
Instanz jedes Mal wenn Sie den Konverter erstellen. Dieser Teil ist bereits nicht THREAD. Sie können das Risiko, dass Sie eine Instanz klonen, während sein interner Zustand geändert worden, weil es irgendwo anders verwendet worden ist. Auch eine vorhandene Instanz Klonen ist nicht unbedingt billiger als eine neue Instanz zu schaffen.
würde ich empfehlen, nur es Thread zu erklären (das heißt innerhalb des Verfahrens Block), unabhängig davon, wie Sie den Konverter verwenden. Wenn die Kostspieligkeit der DateFormat
jedes Mal zu schaffen, ist ein wichtiges Anliegen (hast du das Profil?), Dann erwägen, sie zu ersetzen durch JodaTime .
Andere Tipps
Datumsformate werden nicht synchronisiert. Es wird empfohlen, getrennt zu erstellen Format-Instanzen für jeden Thread. Wenn mehrere Threads zugreifen ein Format Gleichzeitig muss sie synchronisiert werden nach außen.
Ja, es ist nicht sicher hier fädeln.
Legen Sie es auf ein Verfahren vor Ort und erstellen Instanz pro Thread