设为首页 收藏本站
查看: 789|回复: 0

[经验分享] 详解 Tomcat: The value for the useBean class attribute is invalid 问题

[复制链接]

尚未签到

发表于 2017-2-8 12:01:56 | 显示全部楼层 |阅读模式
  http://www.blogjava.net/bluesky/archive/2005/12/05/22600.html
  详解 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):


DSC0000.gif DSC0001.gif if(beanName==null) DSC0002.gif {
DSC0003.gif DSC0004.gif
try{
DSC0005.gif Classbean
=ctxt.getClassLoader().loadClass(klass);
intmodifiers=bean.getModifiers();
if(!Modifier.isPublic(modifiers)||
Modifier.isInterface(modifiers)
||
Modifier.isAbstract(modifiers))
{
thrownewException("Invalidbeanclassmodifier");
DSC0006.gif }

//Checkthatthereisa0argconstructor
bean.getConstructor(newClass[]{});
generateNew
=true;
}
catch(Exceptione){
//Cannotinstantiatethespecifiedclass
if(ctxt.getOptions().getErrorOnUseBeanInvalidClassAttribute()){
err.jspError(n,
"jsp.error.invalid.bean",klass);
}

}

DSC0007.gif }

DSC0008.gif

  
可见错误可能的原因包括:
  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):



//Settinguptheclassrepository(/WEB-INF/classes),ifitexists

StringclassesPath
="/WEB-INF/classes";
DirContextclasses
=null;

try{
Objectobject
=resources.lookup(classesPath);
if(objectinstanceofDirContext){
classes
=(DirContext)object;
}

}
catch(NamingExceptione){
//Silentcatch:it'svalidthatno/WEB-INF/classescollection
//exists
}

if(classes!=null){

FileclassRepository
=null;

StringabsoluteClassesPath
=
servletContext.getRealPath(classesPath);

if(absoluteClassesPath!=null){

classRepository
=newFile(absoluteClassesPath);

}
else{

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

}


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


//Addingtherepositorytotheclassloader
classLoader.addRepository(classesPath+"/",classRepository);
loaderRepositories.add(classesPath
+"/");

}


  
尽管这个问题的复杂场景可能不一而足,不过解决它的办法却很简单:停止服务器,确认你的 JSP 和 Bean 正确部署,清理掉 TOMCAT_HOME/work 中的内容,重起服务器。 此外,配置动态类加载对开发而言是个不错的选择。

本文基于 Tomcat 5.5.9 版本。
作者blog:http://spaces.msn.com/members/thomaszhou/

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-339241-1-1.html 上篇帖子: 部署jbpm3.2.x的jbpm-console到tomcat 7上要注意的 下篇帖子: tomcat报内存溢出permgen space java.lang.OutOfMemeryEror问题解决
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表