2017-05-24 36 views
0

比方說,我有兩個servlet,A和B.在Servlet的AI創建一個HashMap和存儲到在初始化servlet上下文()像這樣:ServletContext的變量不會出現在其他的servlet可見

ServletContext context = getServletContext(); 
context.setAttribute("otable", someObject); 

現在Servlet的B的的init()我初始化的本地引用servlet上下文對象(我指定誰首先創建servlet上下文對象通過web.xml中首先啓動的servlet):

// get and set reference to object cache 
oc = (ObjectCache)getServletContext().getAttribute("otable"); 

然後插入和大小轉到1.當再次調用Servlet A並檢查Servlet上下文HashMa時p,大小仍然爲0.

將本地引用存儲到servlet上下文對象是不是一個好主意?我也嘗試直接從servlet上下文獲取對象,但獲得了相同的結果。我在這裏錯過了什麼?

誰創建的共享對象該servlet首先開始在我的web.xml下列要求:

<servlet> 
<servlet-name>ServletA</servlet-name> 
<servlet-class>package.ServletA</servlet-class> 
<load-on-startup>0</load-on-startup> 
</servlet> 
+0

啊我明白了。感謝Markus,只是好奇,但在這種情況下,servlet的局部變量不會與servlet上下文相同嗎?或者是用於同一個servlet的多個實例的servlet上下文?使用併發哈希映射獲取和放入兩個servlet時的任何問題? – fobius

+0

我刪除了我的評論,因爲它是錯的,對不起! –

+0

你確定你的servlets已經初始化了嗎?您可以在啓動時設置加載。否則,他們將不會被初始化,直到第一個請求到達。是的,當你期望併發訪問時絕對不要使用HashMap。它可能最終處於競賽狀態! –

回答

0

存儲交叉的servlet又名在ServletContext應用範圍的對象的想法是完全可行的。我重新測試了你的方法,它工作得很好。你必須遺漏你忘記發佈的代碼。

我能使其工作如下:

ServletA(中略):

public void init() throws ServletException { 
    Map<String, String> map = new ConcurrentHashMap<>(); 
    getServletContext().setAttribute("map", map); 
    System.out.println("Servlet A Mapsize: " + map.size()); 
    map.put("foo", "bar"); 
    System.out.println("Servlet A Mapsize: " + map.size()); 
} 

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
    Map<String, String> map = (Map<String, String>) getServletContext().getAttribute("map"); 
    System.out.println("Servlet A Mapsize: " + map.size()); 
} 

ServletB(中略):

public void init() throws ServletException { 
    Map<String, String> map = (Map<String, String>) getServletContext().getAttribute("map"); 
    System.out.println("Servlet B Mapsize: " + map.size()); 
    map.put("foo", "bar"); 
    System.out.println("Servlet B Mapsize: " + map.size()); 
} 

web.xml中(中略):

<servlet> 
    <servlet-name>ServletA</servlet-name> 
    <servlet-class>mypackage.ServletA</servlet-class> 
    <load-on-startup>0</load-on-startup> 
</servlet> 
<servlet> 
    <servlet-name>ServletB</servlet-name> 
    <servlet-class>mypackage.ServletB</servlet-class> 
    <load-on-startup>1</load-on-startup> 
</servlet> 
<servlet-mapping> 
    <servlet-name>ServletA</servlet-name> 
    <url-pattern>/a</url-pattern> 
</servlet-mapping> 

啓動應用程序給出你以下輸出:

的Servlet甲Mapsize:0

的Servlet甲Mapsize:1

的Servlet乙Mapsize:1

的Servlet乙Mapsize:1

作爲你可以看到,地圖是正確填充的。

現在您可以調用servletA來檢查一切是否正常。

開啓在瀏覽器(我的設置):

http://localhost:8080/servtest/a

將產生如下輸出

的Servlet甲Mapsize:1

順便說一句,與CDI可用,你可以寫你的applicationScoped緩存生產者爲更可維護的代碼。