看板 java 關於我們 聯絡資訊
※ 引述《JeremyJoung (J.J.)》之銘言: : 狀況描述 : 於JSP中 以<%! %> 宣告CLASS Cart : 相同頁面內運作正常也可以刪改 : 但是 當我以session+HashMap 保存Cart並於其他頁面載入Cart時發生 : java.lang.ClassCastException: : org.apache.jsp.login_jsp$Cart cannot be cast to org.apache.jsp.index_jsp$Cart : 問題碼是 : Cart c=cartL2.get(pdt); : 從map中叫出來時就出錯了 : cartL2 是LinkedHashMap<String, Cart>(); : 狀況看起來是 login_jsp$Cart 不可以在index中使用 : 就算是使用(Cart)強轉也無效 : 請問 為什麼會有這樣的狀況? 我盡量長話短說。 1. 可以的話,請不要在JSP裡宣告class。 2. 如果你在JSP裡宣告class,請記得這個class(注意,是class,不是instance)只能在 該JSP當中使用。 3. 更正確的講法,甚至下一次request進到同一頁,你從session裡把東西取出來,是 不是還能用都不保證。 4. 以上,最保險的in JSP class用法,就是只在那個request的當下,在那頁裡面用, 或是不要用。 原因: JSP會被JSP Compiler(如果你用Tomcat,那個Jasper Engine就是了。) compile 成 Servlet,然後跑在Container上,你在<% %>裡宣告的class會成為一個inner class。 好,現在有幾個問題: 1. 請問JSP是什麼時間點被Compile 成Servlet? 答案是: 看設定、看Container,有時是啟動時會Compile,有時是request來才Compile 2. 請問Container如果突然覺得JSP應該重新Compile 一次,我們能保證他Compile 出 來的『新的』JspServlet,仍然跟舊的名稱一樣、記憶體結構一樣嗎? 答案是: 不能保證,JSP Engine高興做啥就做啥,有些高級Java Web Server,為了支援線上 動態編輯JSP,然後直接動態掛載執行,會把改過的JSP Compile 成不同的servlet Name但是吃同樣的servlet path,這是因為在多緒執行環境裡,可能某些User 已經在存取使用該JSP前一版的servlet class instance了,所以不可以直接下線 ,得要先把新版的準備好,把流量導過去後才把舊的版本從classLoader裡卸載。 那如果你在前一版的時候create 了一個Cart存Session,然後好死不死,user前腳 剛剛結束一個request,Container就把第二版給上了,結果user再發一個request 的時候連到的是第二版JSP,className都不一樣了。 而你的程式碼這時想從session裡把Cart拿出來,想要cast成Cart...糗了。 my_JspServlet.Cart跟my_JspServlet2.Cart可是不同的class。 事實上,你Session裡的cart物件,很有可能再也找不到正確的class可以處理了。 (如果session是被Serialize到disc再被load回來,那此時會噴error,甚至根本就 serialize 不出去) : 是JSP間禁止引用不同頁面間所宣告的物件嗎? : 這問題該如何迴避? : 感謝解答. ...好,我的廢話還是太多了,Anyway,如果上面的有任何地方你看不懂,你就沒有資格 在JSP裡宣告class,你用了會動,很可能只是運氣好沒碰上而已。 你不懂卻用了但沒事,只是沙灘上的城堡碰上退潮而已,該來的還是會來的。 請乖乖的宣告一個Cart.java在你的project src裡,compile它,然後用它。 -- 生命起源於簡單的化學反應,靈魂是腦神經上頭的火花。 掌紋沒有含意,不過是具有止滑功用的紋路。 而神不存在,死去的人們只是等待細菌分解的腐肉而已。 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 123.193.164.59
PsMonkey:長話短說是違反版規的 [指] [完全誤] 08/29 12:08