我有一個servlet,我想爲Web UI提供數據。 數據存儲在一個xml文件中,我希望這個文件可以在幾天內修改一次。 我想在servlet中加載xml文件一次,併爲每個請求提供服務,並只在發送另一個「重新加載」請求時才重新加載它。如何將靜態數據存儲在servlet中並在所有會話/請求之間共享?
從我讀到的,servlet中的靜態變量是不好的做法。
我該如何實現我所需要的?
謝謝。
我有一個servlet,我想爲Web UI提供數據。 數據存儲在一個xml文件中,我希望這個文件可以在幾天內修改一次。 我想在servlet中加載xml文件一次,併爲每個請求提供服務,並只在發送另一個「重新加載」請求時才重新加載它。如何將靜態數據存儲在servlet中並在所有會話/請求之間共享?
從我讀到的,servlet中的靜態變量是不好的做法。
我該如何實現我所需要的?
謝謝。
servlet在webapp的啓動時只創建一次,並在所有請求之間共享。靜態與否,每個類/實例變量將在所有請求/會話中共享。你不想爲它們分配請求/會話範圍的數據。相反聲明/將它們分配爲methodlocal變量
只需創建一個靜態變量,你不必做任何事情,更
可以使用Singleton模式或CDI應用範圍的Bean取決於您的環境。
不要忘記線程安全。
public class ServletSingleton {
private static ServletSingleton instance = new ServletSingleton();
//Here is your data objects
private Object firstDataObject;
private Object secondDataObject;
public static Object getFirstDataObject(){
synchronized (instance){
return instance.firstDataObject;
}
}
public static Object getSecondDataObject(){
synchronized (instance){
return instance.secondDataObject;
}
}
public static void setFirstDataObject(Object dataObject){
synchronized (instance){
instance.firstDataObject = dataObject;
}
}
public static void setSecondDataObject(Object dataObject){
synchronized (instance){
instance.secondDataObject = dataObject;
}
}
}
這是不熟悉的單身人士,但它使用相同的原則。
你能指點我一個例子嗎? – user1997656 2013-05-12 10:56:59
是的,當然。我編輯了我的答案,所以現在它包含線程安全準單例的示例。 – gluckonavt 2013-05-12 11:41:58
您可以將數據放在ServletContext中,它是每個Java虛擬機的每個「Web應用程序」的上下文(意味着全局)。
您可以定義一個實例成員或存儲屬性到應用範圍,但兩者都不是線程安全的。
我真的不喜歡「壞習慣」這個詞,因爲它暗示我們可以評估是否有什麼不好的情況。如果Java語言的設計者認爲靜態字段總是不好的話,那麼這種情況很少會發生 - 或者換言之,他們不會將它們包含在語言中。
在servlet中有可變狀態是完全可以的 - 但是你必須記住,servlet容器將使用servlet的同一對象實例來(併發地)爲所有請求提供服務。
這意味着特定於請求的狀態不應該存儲在servlet中,因爲不同的請求處理線程會覆蓋彼此的狀態。在你的情況下,你希望狀態在所有請求之間共享,所以servlet中的字段是合適的。由於servlet是由併發線程訪問的,您將不得不同步訪問該可變共享狀態。
如何同步訪問servlet中的數據?只是用同步包裝的方法? – user1997656 2013-05-12 11:15:43
如何編寫正確的線程安全代碼超出了本答案的範圍。 java教程對該主題有一個[介紹](http://docs.oracle.com/javase/tutorial/essential/concurrency/sync.html)。 – meriton 2013-05-12 11:22:33
但是,如何使靜態的一個線程安全嗎? – user1997656 2013-05-12 10:57:36