2012-05-19 67 views
-3
HttpServletRequest request; 
    HttpServletResponse response; 

    public void doGet(HttpServletRequest request , HttpServlet response){ 
     this.request = request; 
     this.response = response; 
    } 

如果此servlet一次接收多個請求,會發生什麼情況?爲什麼apache servlet是單身人士?

我們遇到了響應不匹配問題。這是一個問題嗎?

+8

不要這樣做。真。別。 – skaffman

+1

這使得世界陷入黑洞 –

+0

瞭解servlet如何工作:http://stackoverflow.com/questions/3106452/how-do-servlets-work-instantiation-session-variables-and-multithreading/3106909#3106909 – BalusC

回答

-2

它是一個問題,絕不建議將HttpServletRequest請求/ HttpServletResponse響應聲明爲實例變量。實際上Servlet正在實現單線程模型,這意味着只有一個servlet實例被創建。併爲每個請求提供一個線程。因此,如果他們有很多請求,那麼thr必須是多個線程,並且每個共享相同的servlet實例會導致數據不匹配或數據不一致問題。線程將在相同的實例上工作。

+2

單線程模型!=單例servlet。單線程模型正是模型(沒有人使用,因爲它效率非常低),以確保只有一個線程使用給定的servlet。 –

+0

也不建議使用「單線程實現」。它已被棄用。 – verisimilitude

+0

-1;這個答案不提供任何價值。正如其他人已經表明,這是部分錯誤。 – home

2

當然這是一個問題。一個servlet是一個單身人士。同一個servlet實例用於處理對這個servlet的所有請求。並且請求當然是同時處理的。這意味着如果你這樣做,thread1將使用通常由thread2處理的請求和響應。

+0

根據定義,Servlet不是單身人士。 Servlet API不會將創建特定的Servlet類限制爲單個實例。 Container通常會爲部署描述符中的每個servlet聲明創建一個servlet實例。而單例是一種設計模式,它將其類的對象的創建限制爲1並且僅爲1. – verisimilitude

+1

它們不是在GoF模式的含義中的單例,而是它們有效地是因爲容器是**必需的** servlet規範只爲每個servlet聲明實例化一個實例。單身並不僅僅是GoF的設計模式。你有沒有使用像Spring或Guice這樣的依賴注入框架?從未見過單身人士在這方面使用? –

+0

是的,我有。我試圖將GoF的單身人士的定義聯繫起來。並加1爲你的闡述:) – verisimilitude

4

您的Web應用程序容器只加載一個servlet實例。

要編寫線程安全的servlet,幾乎不應該使用實例變量。將請求和響應設置爲實例變量顯然是錯誤的。該servlet的實例不屬於單個請求。

如果您需要使請求或響應的元素可用於其他方法,請將它們傳遞給這些方法。你不需要它們作爲實例變量。

+1

嘗試編寫一個不帶實例變量的非平凡servlet; servlet必須在某個時間點將控制委派給* something *(即服務)。你的意思是說不使用非線程安全的實例變量。 – skaffman

0

這肯定會造成問題,任何實例變量作爲servlet共享爲單例,因此併發請求和響應對象將被覆蓋。

1

引用Servlet規範

「每個請求和響應對象是有效的只有一個servlet的服務的方法的範圍內,或一個過濾器的doFilter方法的範圍之內。容器,以避免通常回收 請求對象請求對象 創建的性能開銷。開發者必須意識到,維持引用請求對象 上述範圍之外,不推薦,因爲它可能有不確定的 結果。「

+0

這與OP的問題沒有多大關係。如果他在'doGet()'末尾取消了實例變量,那麼請求和響應對象的範圍就不會在服務方法之外擴展,但他仍然會遇到很大的問題。 –

+0

合理。但仍然。如果規範保證了保存對這些對象的引用的不確定結果,爲什麼要這樣做呢? – verisimilitude

+0

它不保證這種類型。您可以保存儘可能多的引用,只要您不要在服務方法範圍之外使用這些引用。你只需要以線程安全的方式來完成。例如,許多框架在ThreadLocal變量中存儲對請求的引用。 –

0

發生什麼事是你的servlet instan tly變得不可重入,並且在第一次同時被更多的客戶端調用時肯定會失敗。你不能這樣做。