詳解 Tomcat: The value for the useBean class attribute is invalid 問題使用Tomcat 常見 "The value for the useBean class attribute is invalid" 錯誤。該錯誤是指 JSP 中給定的 useBean 標簽的 class 屬性的值無效(不是 Bean 的屬性值)。在說明這個問題前,先看看有關的 Tomcat 源代碼(org.apache.jasper.compiler.Generator):
可見錯誤可能的原因包括:
1. 在編譯 JSP 時(不是運行時),指定的 Bean 類沒找到2. Bean 雖然找到了,但是它不是 public 的,或者找到的 class 文件是 interface 或抽象類 3. Bean 類中沒有 public 的默認構建函數
第二點很明顯,不用多解釋,最經常發生的情況是 Bean 類忘了聲明為 public 。
第三點中需要注意的是,如果你的 Bean 類沒有提供任何構造函數,將自動生成一個默認構建函數,這沒有問題。但是,如果你有構造函數,則不會自動生成該默認構造函數。經常被忽略的問題是寫了默認構造函數卻不是 public 的。
第一點看起來簡單,不過卻最令人頭痛,尤其是在開發環境里。這里需要注意的是,"在編譯 JSP 時",意味著引用 Bean 的 JSP 是新的,或者剛剛更新過,或者 TOMCAT_HOME/work 中的編譯結果被清除了。此時,Tomcat 將自動(重新)編譯該 JSP,此時如果發現 Bean 沒找到,就會報這個錯。情況因為 JSP 或者 Bean 類正在開發而變得復雜,一一列舉所有情況沒有意義,這里我舉一些典型例子,借此應該可以舉一反三: 如果 JSP 編譯結果存在,且 JSP 沒有更新,Tomcat 不會重新編譯 JSP,同時默認情況也不會自動重新加載更新過的 Bean 類(參考 http://jakarta.apache.org/tomcat/tomcat-5.5-doc/config/context.html 中的 reloadable)。所以,你會發現此時即使刪除了 Bean 類都沒有問題,當然,更新 Bean 類也不會有什么用。如果在 JSP 編譯產生之后,我們重起了服務器,由于 JSP 文件編譯的結果存在,所以,可以仍然訪問 JSP 頁面,而不必重新編譯。可是如果訪問前,刪掉了 Bean 類,就會報過 ClassNotFoundException 而不是上述錯誤。關鍵在于 JSP 是否經過編譯,沒有編譯則沒有找到類報告題目中的編譯錯誤 ,編譯過則是 ClassNotFoundException 運行時實例化錯誤。
還有一個更為特殊的例子。如果 Web 應用在啟動時, WEB-INF/classes 目錄不存在,則在啟動應用后,新建 classes 目錄,動態添加新的類進去是沒有用的,會報告同樣的錯誤。原因是此時的 Tomcat 不會去檢查該目錄,也就不會找到你需要的類。對 WEB-INF/lib 目錄也是同樣。這一點可以參考下面的源代碼(org.apache.catalina.loader.WebappLoader):
盡管這個問題的復雜場景可能不一而足,不過解決它的辦法卻很簡單:停止服務器,確認你的 JSP 和 Bean 正確部署,清理掉 TOMCAT_HOME/work 中的內容,重起服務器。 此外,配置動態類加載對開發而言是個不錯的選擇。 本文基于 Tomcat 5.5.9 版本。 作者blog:http://spaces.msn.com/members/thomaszhou/
posted on 2005-12-05 16:01 bluesky 閱讀(21583) 評論(10) 編輯 收藏 所屬分類: 工作總結