详解 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

相关文章

MySQL 表空却 ibd 文件过大的问题及解决方法

《MySQL表空却ibd文件过大的问题及解决方法》本文给大家介绍MySQL表空却ibd文件过大的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考... 目录一、问题背景:表空却 “吃满” 磁盘的怪事二、问题复现:一步步编程还原异常场景1. 准备测试源表与数据

Spring创建Bean的八种主要方式详解

《Spring创建Bean的八种主要方式详解》Spring(尤其是SpringBoot)提供了多种方式来让容器创建和管理Bean,@Component、@Configuration+@Bean、@En... 目录引言一、Spring 创建 Bean 的 8 种主要方式1. @Component 及其衍生注解

Python异步编程之await与asyncio基本用法详解

《Python异步编程之await与asyncio基本用法详解》在Python中,await和asyncio是异步编程的核心工具,用于高效处理I/O密集型任务(如网络请求、文件读写、数据库操作等),接... 目录一、核心概念二、使用场景三、基本用法1. 定义协程2. 运行协程3. 并发执行多个任务四、关键

从基础到进阶详解Python条件判断的实用指南

《从基础到进阶详解Python条件判断的实用指南》本文将通过15个实战案例,带你大家掌握条件判断的核心技巧,并从基础语法到高级应用一网打尽,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录​引言:条件判断为何如此重要一、基础语法:三行代码构建决策系统二、多条件分支:elif的魔法三、

Java利用@SneakyThrows注解提升异常处理效率详解

《Java利用@SneakyThrows注解提升异常处理效率详解》这篇文章将深度剖析@SneakyThrows的原理,用法,适用场景以及隐藏的陷阱,看看它如何让Java异常处理效率飙升50%,感兴趣的... 目录前言一、检查型异常的“诅咒”:为什么Java开发者讨厌它1.1 检查型异常的痛点1.2 为什么说

解决Nginx启动报错Job for nginx.service failed because the control process exited with error code问题

《解决Nginx启动报错Jobfornginx.servicefailedbecausethecontrolprocessexitedwitherrorcode问题》Nginx启... 目录一、报错如下二、解决原因三、解决方式总结一、报错如下Job for nginx.service failed bec

SysMain服务可以关吗? 解决SysMain服务导致的高CPU使用率问题

《SysMain服务可以关吗?解决SysMain服务导致的高CPU使用率问题》SysMain服务是超级预读取,该服务会记录您打开应用程序的模式,并预先将它们加载到内存中以节省时间,但它可能占用大量... 在使用电脑的过程中,CPU使用率居高不下是许多用户都遇到过的问题,其中名为SysMain的服务往往是罪魁

MySQL的配置文件详解及实例代码

《MySQL的配置文件详解及实例代码》MySQL的配置文件是服务器运行的重要组成部分,用于设置服务器操作的各种参数,下面:本文主要介绍MySQL配置文件的相关资料,文中通过代码介绍的非常详细,需要... 目录前言一、配置文件结构1.[mysqld]2.[client]3.[mysql]4.[mysqldum

springboot2.1.3 hystrix集成及hystrix-dashboard监控详解

《springboot2.1.3hystrix集成及hystrix-dashboard监控详解》Hystrix是Netflix开源的微服务容错工具,通过线程池隔离和熔断机制防止服务崩溃,支持降级、监... 目录Hystrix是Netflix开源技术www.chinasem.cn栈中的又一员猛将Hystrix熔

Java调用Python脚本实现HelloWorld的示例详解

《Java调用Python脚本实现HelloWorld的示例详解》作为程序员,我们经常会遇到需要在Java项目中调用Python脚本的场景,下面我们来看看如何从基础到进阶,一步步实现Java与Pyth... 目录一、环境准备二、基础调用:使用 Runtime.exec()2.1 实现步骤2.2 代码解析三、