<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-72  評論-20  文章-0  trackbacks-1

    使用Tomcat 常見 "The value for the useBean class attribute is invalid" 錯誤。該錯誤是指 JSP 中給定的 useBean 標(biāo)簽的 class 屬性的值無效(不是 Bean 的屬性值)。
     
    在說明這個問題前,先看看有關(guān)的 Tomcat 源代碼(org.apache.jasper.compiler.Generator):

      if (beanName == null) {
          try {
              Class bean = ctxt.getClassLoader().loadClass(klass);
              int modifiers = bean.getModifiers();
              if (!Modifier.isPublic(modifiers) ||
                   Modifier.isInterface(modifiers) ||
                  Modifier.isAbstract (modifiers)) {
                  throw new Exception("Invalid bean class modifier");
              }
              // Check that there is a 0 arg constructor
              bean.getConstructor(new Class[] {});
              generateNew = true;
          } catch (Exception e) {
              // Cannot instantiate the specified class
              if (ctxt.getOptions().getErrorOnUseBeanInvalidClassAttribute()) {
                  err.jspError(n, "jsp.error.invalid.bean ", klass);
              }
          }
      }


    可見錯誤可能的原因包括:

    1. 在編譯 JSP 時(不是運行時),指定的 Bean 類沒找到
    2. Bean 雖然找到了,但是它不是 public 的,或者找到的 class 文件是 interface 或抽象類
    3. Bean 類中沒有 public 的默認構(gòu)建函數(shù)

    第二點很明顯,不用多解釋,最經(jīng)常發(fā)生的情況是 Bean 類忘了聲明為 public 。

    第三點中需要注意的是,如果你的 Bean 類沒有提供任何構(gòu)造函數(shù),將自動生成一個默認構(gòu)建函數(shù),這沒有問題。但是,如果你有構(gòu)造函數(shù),則不會自動生成該默認構(gòu)造函數(shù)。經(jīng)常被忽略的問題是寫了默認構(gòu)造函數(shù)卻不是 public 的。

    第一點看起來簡單,不過卻最令人頭痛,尤其是在開發(fā)環(huán)境里。這里需要注意的是,"在編譯 JSP 時",意味著引用 Bean 的 JSP 是新的,或者剛剛更新過,或者 TOMCAT_HOME/work 中的編譯結(jié)果被清除了。此時,Tomcat 將自動(重新)編譯該 JSP,此時如果發(fā)現(xiàn) Bean 沒找到,就會報這個錯。情況因為 JSP 或者 Bean 類正在開發(fā)而變得復(fù)雜,一一列舉所有情況沒有意義,這里我舉一些典型例子,借此應(yīng)該可以舉一反三:
     
    如果 JSP 編譯結(jié)果存在,且 JSP 沒有更新,Tomcat 不會重新編譯 JSP,同時默認情況也不會自動重新加載更新過的 Bean 類(參考 http://jakarta.apache.org/tomcat/tomcat-5.5-doc/config/context.html 中的 reloadable)。所以,你會發(fā)現(xiàn)此時即使刪除了 Bean 類都沒有問題,當(dāng)然,更新 Bean 類也不會有什么用。如果在 JSP 編譯產(chǎn)生之后,我們重起了服務(wù)器,由于 JSP 文件編譯的結(jié)果存在,所以,可以仍然訪問 JSP 頁面,而不必重新編譯。可是如果訪問前,刪掉了 Bean 類,就會報過 ClassNotFoundException 而不是上述錯誤。關(guān)鍵在于 JSP 是否經(jīng)過編譯,沒有編譯則沒有找到類報告題目中的編譯錯誤 ,編譯過則是 ClassNotFoundException 運行時實例化錯誤。


    還有一個更為特殊的例子。如果 Web 應(yīng)用在啟動時, WEB-INF/classes 目錄不存在,則在啟動應(yīng)用后,新建 classes 目錄,動態(tài)添加新的類進去是沒有用的,會報告同樣的錯誤。原因是此時的 Tomcat 不會去檢查該目錄,也就不會找到你需要的類。對 WEB-INF/lib 目錄也是同樣。這一點可以參考下面的源代碼(org.apache.catalina.loader.WebappLoader):
     
      // Setting up the class repository (/WEB-INF/classes), if it exists

      String classesPath = "/WEB-INF/classes";
      DirContext classes = null;

      try {
          Object object = resources.lookup(classesPath);
          if (object instanceof DirContext) {
              classes = (DirContext) object;
          }
      } catch(NamingException e) {
          // Silent catch: it's valid that no /WEB-INF/classes collection
          // exists
      }

      if (classes != null) {

          File classRepository = null;

          String absoluteClassesPath =
              servletContext.getRealPath(classesPath);

          if (absoluteClassesPath != null) {

              classRepository = new File(absoluteClassesPath);

          } else {

              classRepository = new File(workDir, classesPath);
              classRepository.mkdirs();
              copyDir(classes, classRepository);

          }

          if(log.isDebugEnabled())
              log.debug(sm.getString("webappLoader.classDeploy", classesPath,
                           classRepository.getAbsolutePath()));


          // Adding the repository to the class loader
          classLoader.addRepository(classesPath + "/", classRepository);
          loaderRepositories.add(classesPath + "/" );

      }

     

    上面最后兩個語句將 "/WEB-INF/classes" 注冊到類裝載器中。如果目錄不存在,則該目錄不會被注冊,即使在運行過程中創(chuàng)建該目錄,Tomcat 目前也沒有機制動態(tài)的注冊該目錄(應(yīng)該是出于效率考慮)。


    盡管這個問題的復(fù)雜場景可能不一而足,不過解決它的辦法卻很簡單:停止服務(wù)器,確認你的 JSP 和 Bean 正確部署,清理掉 TOMCAT_HOME/work 中的內(nèi)容,重起服務(wù)器。 此外,配置動態(tài)類加載對開發(fā)而言是個不錯的選擇。
     
    本文基于 Tomcat 5.5.9 版本。

    --
    Stephen Suen(SUNRUJUN)

     

    posted on 2006-06-14 14:25 前方的路 閱讀(803) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 亚洲五月午夜免费在线视频| 在线a人片天堂免费观看高清 | 国产免费的野战视频| 国产精品亚洲成在人线| 窝窝影视午夜看片免费| 日本不卡免费新一二三区| 黄床大片30分钟免费看| 亚洲国产成人久久精品99| 精品97国产免费人成视频| 久久91亚洲人成电影网站| 99精品视频在线观看免费播放 | 亚洲欧洲中文日产| 美女网站免费福利视频| 亚洲日韩国产欧美一区二区三区 | 欧美日韩亚洲精品| 亚洲?V无码乱码国产精品| 国产日韩在线视频免费播放| 亚洲AV无码一区二区三区系列| 8888四色奇米在线观看免费看| 久久精品亚洲AV久久久无码 | 国产免费一区二区三区不卡| 亚洲第一成年男人的天堂| 四虎永久在线精品免费观看视频 | 亚洲av日韩综合一区在线观看| 69av免费观看| 国产成人人综合亚洲欧美丁香花| 亚洲国产婷婷综合在线精品| a级男女仿爱免费视频| 亚洲午夜精品一区二区公牛电影院 | 四虎免费大片aⅴ入口| a毛片成人免费全部播放| 少妇中文字幕乱码亚洲影视| 成人一a毛片免费视频| 国产精品免费一区二区三区| 亚洲短视频在线观看| 一级大黄美女免费播放| 亚洲精品免费在线观看| 成人a免费α片在线视频网站| 国产在线国偷精品免费看 | 男人j进女人p免费视频| 亚洲欧洲第一a在线观看|