详解 Tomcat: The value for the useBean class attribute is invalid 问题

2024-05-02 02:32

本文主要是介绍详解 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):
 

   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 的默认构建函数

第二点很明显,不用多解释,最经常发生的情况是 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):

 

   //  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 
+ "/" ); 

  }


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

这篇关于详解 Tomcat: The value for the useBean class attribute is invalid 问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/953214

相关文章

MybatisPlus 多数据源切换@DS注解失效问题解决

《MybatisPlus多数据源切换@DS注解失效问题解决》在业务开发中使用到了多数据源,遇到了@DS注解失效问题,有两个场景使用到同一个@DS的查询方法,下面就来介绍一下该问题的解决,感兴趣的可以... 在业务开发中使用到了多数据源,遇到了@DS注解失效问题,有两个场景使用到同一个@DS的查询方法,一个正

Centos7 firewall和docker冲突问题及解决过程

《Centos7firewall和docker冲突问题及解决过程》本文描述了一个在CentOS7上使用firewalld和Docker容器的问题,当firewalld启动或重启时,会从iptable... 目录系统环境问题描述问题排查解决办法总结本文只是我对问题的记录,只能用作参考,不能China编程说明问题,请

基于C++的UDP网络通信系统设计与实现详解

《基于C++的UDP网络通信系统设计与实现详解》在网络编程领域,UDP作为一种无连接的传输层协议,以其高效、低延迟的特性在实时性要求高的应用场景中占据重要地位,下面我们就来看看如何从零开始构建一个完整... 目录前言一、UDP服务器UdpServer.hpp1.1 基本框架设计1.2 初始化函数Init详解

springboot+redis实现订单过期(超时取消)功能的方法详解

《springboot+redis实现订单过期(超时取消)功能的方法详解》在SpringBoot中使用Redis实现订单过期(超时取消)功能,有多种成熟方案,本文为大家整理了几个详细方法,文中的示例代... 目录一、Redis键过期回调方案(推荐)1. 配置Redis监听器2. 监听键过期事件3. Redi

Springboot配置文件相关语法及读取方式详解

《Springboot配置文件相关语法及读取方式详解》本文主要介绍了SpringBoot中的两种配置文件形式,即.properties文件和.yml/.yaml文件,详细讲解了这两种文件的语法和读取方... 目录配置文件的形式语法1、key-value形式2、数组形式读取方式1、通过@value注解2、通过

JAVA Calendar设置上个月时,日期不存在或错误提示问题及解决

《JAVACalendar设置上个月时,日期不存在或错误提示问题及解决》在使用Java的Calendar类设置上个月的日期时,如果遇到不存在的日期(如4月31日),默认会自动调整到下个月的相应日期(... 目录Java Calendar设置上个月时,日期不存在或错误提示java进行日期计算时如果出现不存在的

Mybatis对MySQL if 函数的不支持问题解读

《Mybatis对MySQLif函数的不支持问题解读》接手项目后,为了实现多租户功能,引入了Mybatis-plus,发现之前运行正常的SQL语句报错,原因是Mybatis不支持MySQL的if函... 目录MyBATis对mysql if 函数的不支持问题描述经过查询网上搜索资料找到原因解决方案总结Myb

自定义注解SpringBoot防重复提交AOP方法详解

《自定义注解SpringBoot防重复提交AOP方法详解》该文章描述了一个防止重复提交的流程,通过HttpServletRequest对象获取请求信息,生成唯一标识,使用Redis分布式锁判断请求是否... 目录防重复提交流程引入依赖properties配置自定义注解切面Redis工具类controller

Nginx错误拦截转发 error_page的问题解决

《Nginx错误拦截转发error_page的问题解决》Nginx通过配置错误页面和请求处理机制,可以在请求失败时展示自定义错误页面,提升用户体验,下面就来介绍一下Nginx错误拦截转发error_... 目录1. 准备自定义错误页面2. 配置 Nginx 错误页面基础配置示例:3. 关键配置说明4. 生效

Python容器转换与共有函数举例详解

《Python容器转换与共有函数举例详解》Python容器是Python编程语言中非常基础且重要的概念,它们提供了数据的存储和组织方式,下面:本文主要介绍Python容器转换与共有函数的相关资料,... 目录python容器转换与共有函数详解一、容器类型概览二、容器类型转换1. 基本容器转换2. 高级转换示