[转贴]详解 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 版本。
作者blog:http://spaces.msn.com/members/thomaszhou/
分享到:
相关推荐
12)对于`user.jsp`,要显示`loginName:`和`password:`,首先需要实例化并初始化User对象,然后使用`jsp:getProperty`标签来获取对象的属性值。因此,JSP代码片段应该如下所示: ```jsp <jsp:useBean id="user" ...
在JSP中,可以使用<useBean>标签来创建和访问Java Bean。例如,<jsp:useBean id="dao" scope="page" class="com.wy.dao.OperationData"/>创建了一个名为dao的Java Bean实例,并指定了它的作用范围为页面(page)。 ...
- `<jsp:useBean id="userBean" scope="page" class="user.user"/>`创建了一个名为`userBean`的bean对象。 - `<jsp:setProperty name="userBean" property="*"/>`设置了bean的所有属性值。 - `<% %> `中的Java...
在这里,`<jsp:useBean>`标签用于实例化自定义标签的处理类,然后在`<my:customTag>`标签中使用它。 在`mytags.tld`中,我们将定义自定义标签及其属性: ```xml <tlib-version>1.0 <jsp-version>2.0</jsp-...
- JSP页面可以通过`<jsp:useBean>`指令创建JavaBeans实例,并通过`<jsp:setProperty>`设置其属性值,最后通过`<jsp:getProperty>`获取属性值。 ### 示例:使用JavaBeans的简易应用 1. **实现流程:** - 创建一个...
给定的`User.java`类定义了getter和setter方法,`user.jsp`中需要使用`<jsp:useBean>`创建bean并设置属性值。因此,下划线处应填入a) `<jsp:useBean id="user" class="user.User" scope="page"/>`来实例化bean,并用...
1. **加载JavaBean**:当JSP页面被请求时,`<jsp:useBean>`标签会创建一个`goodsbean`实例并存储在`application`作用域中。 2. **设置属性**:接下来,使用`setProduct`和`setPrice`方法设置商品的信息。 3. **输出...
6)在给定的`user.jsp`中,要使浏览器显示`loginName:sa`和`password:sa`,需要先在JSP中创建一个`User` Bean,并设置属性值。正确的选项是: ```jsp <jsp:useBean id="user" class="user.User" scope="page"/> ...
- `jsp:useBean`标签用于创建JavaBean实例,`class`属性指定JavaBean的完整类名,包括包名。 - `jsp:setProperty`标签用于设置JavaBean的属性值,`*`表示设置所有可写属性。 - `jsp:getProperty`标签用于获取...
在JSP页面中,我们使用`<jsp:useBean>`标签创建了一个名为`brush`的`PaintBrush`对象,并指定了它的类路径(`class="PaintBrush.PaintBrush"`)。然后,我们通过`<jsp:getProperty>`标签获取了`brush`对象的颜色属性...
10. `<jsp:useBean>` 标签用于创建或查找Java Bean,并将其绑定到一个页面作用域的变量。例子中创建了一个`com.abc.bean.MyBean`的实例,名为`testBean`,并设置了它的`name`属性为"小强"。 二、综合题解析: 1. `...
根据给定的文件信息,以下是对JSP面试题(下)相关知识点的详细解析: ### 1. JSP中的作用域是什么? - **Page**: 指的是一个JSP页面的作用域,通常用于存储该页面内可以访问的对象。 - **Request**: 作用域仅在一...
<jsp:useBean id="beanName" class="fully.qualified.ClassName" scope="page|request|session|application"/> ``` 3. **`jsp:setProperty`**:用于设置JavaBean对象的属性值。通常配合 `jsp:useBean` 使用,以...
以上知识点和案例,结合给定文件中的【标题】、【描述】和【标签】,能够为初学者提供一个较为全面的JSP开发入门和理解。通过实践这些案例,初学者可以逐渐掌握JSP的基本使用方法,并能够在实际开发中应用所学知识。
在JSP页面中使用JavaBean时,通常会通过`<jsp:useBean>`标签来实现。该标签提供了多个属性用于指定JavaBean的信息。 - **正确选项:** - A. `id` - D. `class` **解析:** - **A. `id`**:用于标识当前JavaBean的...
3. **命名不一致**:检查JavaBean的类名和包名是否与`<jsp:useBean>`标签中的`class`属性匹配。在这里,`class`属性值为`test.MyBean`,这意味着类应该名为`MyBean`且位于`test`包内。 4. **编译错误**:如果`...
为JavaBean对象设置属性值,可以使用`<jsp:setProperty>`标签进行设置。 ### 21. 获取JavaBean属性 ```html <jsp:getProperty name="user" property="username"/> ``` 从JavaBean对象中获取属性值,并将其展示在...
4. 在J2EE中,test.jsp文件中有如下一行代码:<jsp:useBean id=”user” scope=”_____” type=”com.UserBean”/>要使user对象中一直存在于对话中,直至其终止或被删除为止,下划线中应填入()。 知识点:JSP的...
正确的语法格式是`<jsp:useBean id="beanName" class="fullyQualifiedName" scope="page|request|session|application"/>`,其中`id`属性定义了一个变量名,可以在后续的JSP代码中引用该对象;`class`属性指定了要...