学科分类
目录
Java Web

<jsp:useBean>标签

<jsp:useBean>标签用于在某个指定的域范围(pageContext、request、session、application等)中查找一个指定名称的JavaBean对象,如果存在则直接返回该JavaBean对象的引用,如果不存在则实例化一个新的JavaBean对象并将它按指定的名称存储在指定的域范围中。<jsp:useBean>标签的语法格式如下所示:

<jsp:useBean id="beanInstanceName" [scope="{page | request | session | application}"] 
{
        class="package.class" | 
        type="package.class" | 
        class="package.class" type="package.class" | 
        beanName="{package.class | <%= expression %>}" type="package.class" 
} /> 

从上面的语法格式中可以看出,<jsp:useBean>标签中有5个属性,接下来就针对这5个属性进行讲解,具体如下:

● id:用于指定JavaBean实例对象的引用名称和其存储在域范围中的名称。

● scope:用于指定JavaBean实例对象所存储的域范围,其取值只能是page、request、session和application四个值中的一个,其默认值是page(关于域范围,请参看本教材7.4小节)

● type:用于指定JavaBean实例对象的引用变量类型,它必须是JavaBean对象的类名称、父类名称或JavaBean实现的接口名称。type属性的默认值为class属性的设置值,当JSP容器将<jsp:useBean>标签翻译成Servlet程序时,它将使用type属性值作为JavaBean对象引用变量的类型。

● class:用于指定JavaBean的完整类名(即必须带有包名),JSP容器将使用这个类名来创建JavaBean的实例对象或作为查找到的JavaBean对象的类型。

● beanName:用于指定JavaBean的名称,它的值也是a.b.c的形式,这既可以代表一个类的完整名称,也可以代表a/b/c.ser这样的资源文件。beanName属性值将被作为参数传递给java.beans.Beans类的instantiate()方法,创建出JavaBean的实例对象。需要注意的是,beanName属性值也可以为一个脚本表达式。

​ 在使用<jsp:useBean>标签时,id属性必须指定,scope属性可以不用指定,如果没有指定scope属性,则会使用它的默认值page。而对于class、type、beanName这三个属性,它们的使用方式有四种,可以参看<jsp:useBean>标签语法格式的第3行到第6行。为了更好地理解这三个属性的作用,接下来对它们的四种使用方式分别进行讲解。具体如下:

1、单独使用class属性

由于<jsp:useBean>标签会用到JavaBean组件,因此在使用标签之前,首先在cn.itcast.chapter08.javabean包下创建两个JavaBean类Employee和Manager,Manager类继承自Employee类,这两个类具体如例1和2所示。

例1 Employee.java

 1    package cn.itcast.chapter08.javabean;
 2    public class Employee {
 3        private String company;
 4        public String getCompany() {
 5            return company;
 6        }
 7        public void setCompany(String company) {
 8            this.company = company;
 9        }
 10    }

例2 Manager.java

 1    package cn.itcast.chapter08.javabean;
 2    public class Manager extends Employee {
 3        private double bonus;
 4        public double getBonus() {
 5            return bonus;
 6        }
 7        public void setBonus(double bonus) {
 8            this.bonus = bonus;
 9        }
 10    }

然后,创建一个useBean.jsp文件,在文件中使用<jsp:useBean>标签,如例3所示。

例3 useBean.jsp

 1    <%@ page language="java" pageEncoding="GBK"%>
 2    <html>
 3    <body>
 4            <jsp:useBean id="manager" scope="page"
 5                class="cn.itcast.chapter08.javabean.Manager" />
 6    </body>
 7    </html>

在例3中,使用了<jsp:useBean>标签,并设置了该标签的id、scope和class属性。为了了解这个标签中这三个属性的作用,在浏览器中访问useBean.jsp页面,然后在 <Tomcat安装目录>\work\Catalina\localhost\chapter08\org\apache\jsp目录下查看useBean.jsp文件翻译成的Servlet,可以看到<jsp:useBean>标签翻译成的Java代码如下所示:

......
cn.itcast.chapter08.javabean.Manager manager = null;
manager = (cn.itcast.chapter08.javabean.Manager) _jspx_page_context
                .getAttribute("manager",javax.servlet.jsp.PageContext.PAGE_SCOPE);
if (manager == null) {
    manager = new cn.itcast.chapter08.javabean.Manager();
    _jspx_page_context.setAttribute("manager", manager,
                    javax.servlet.jsp.PageContext.PAGE_SCOPE);
}
......

从上面的代码可以看到,JSP容器首先定义一个引用变量manager,manager为class属性指定的类型,然后在scope属性指定的域范围中查找以manager为名称的JavaBean对象,如果该域范围中不存在指定JavaBean对象,JSP容器会创建class属性指定类型的JavaBean实例对象,并用变量manager引用。

需要特别注意的是,翻译成的Servlet代码中,用于引用JavaBean实例对象的变量名和JavaBean存储在域中的名称均为id属性设置的值manager。

2、单独使用type属性

将上面<jsp:useBean>标签中的class属性改成type属性,示例代码具体如下:

<jsp:useBean id="manager" scope="page"
     type="cn.itcast.chapter08.javabean.Manager" />

刷新浏览器再次访问useBean.jsp页面,可以发现浏览器出现了500异常,如图1所示。

图1 运行结果

从图1中可以看出,发生异常的原因是manager这个JavaBean对象没有找到。为了找出发生异常的根源,我们仍然去<Tomcat安装目录>\work\Catalina\localhost\chapter08\org\apache\jsp目录下查看useBean.jsp文件翻译成的Servlet,可以看到<jsp:useBean>标签翻译成的Java代码如下所示:

…… ……
cn.itcast.chapter08.javabean.Manager manager = null;
manager = (cn.itcast.chapter08.javabean.Manager) _jspx_page_context
        .getAttribute("manager",javax.servlet.jsp.PageContext.PAGE_SCOPE);
if (manager == null) {
    throw new java.lang.InstantiationException("bean manager not found within scope");
}
…… ……

从上面的代码中可以看出,当只设置了type属性值时,JSP容器会在指定的域范围中查找以id属性值为名称的JavaBean对象,如果对象不存在,JSP容器不会创建新的JavaBean对象,而会抛出InstantiationException异常。了解了源代码,就不难理解在访问useBean.jsp页面时为什么会出现异常了。

为了解决这个问题,在<jsp:useBean>标签上面写一段JSP脚本片段,为pageContext域增加一个属性,属性的名称为“manager”,值为Manger对象。JSP脚本片段如下所示:

<%
    pageContext.setAttribute("manager",new cn.itcast.chapter08.javabean.Manager());
%>

刷新浏览器再次访问useBean.jsp页面,发现页面浏览器页面中的异常消失了。

需要注意的是,<jsp:useBean>标签的type属性值还可以指定为JavaBean的父类或者由JavaBean实现的接口。下面对type属性的值进行修改,将其设置为“cn.itcast.chapter08.javabean.Employee”,访问useBean.jsp页面后,再次查看翻译的Servlet文件,可以看到<jsp:useBean>标签翻译成的Java代码如下所示:

…… ……
cn.itcast.chapter08.javabean.Employee manager = null;
manager = (cn.itcast.chapter08.javabean.Employee) _jspx_page_context
        .getAttribute("manager",javax.servlet.jsp.PageContext.PAGE_SCOPE);
if (manager == null) {
    throw new java.lang.InstantiationException("bean manager not found within scope");
}
…… ……

从上面的代码中可以看到,JSP容器将 Javabean引用变量的类型指定为type属性的值“cn.itcast.chapter08.javabean.Employee”,同时将从域范围中查找到的JavaBean也转换成了Employee类型。

3、class属性和type属性结合使用

由于type属性的默认值为class属性的设置值,也就是说在<jsp:useBean>标签中只要设置了class属性,

相当于设置了type属性的默认值,因此这种情况和第一种情况相同,这里就不再赘述了。

4、beanName属性和type属性的结合使用

将useBean.jsp页面中的JSP脚本片段去掉,并对<jsp:useBean>标签进行修改,使用id、beanName和

type属性,示例代码具体如下:

<jsp:useBean id="manager" beanName="cn.itcast.chapter08.javabean.Manager"
            type="cn.itcast.chapter08.javabean.Manager" />

在浏览器中访问useBean.jsp页面,然后查看翻译的Servlet文件,可以看到<jsp:useBean>标签翻译成的Java代码如下所示:

…… ……
cn.itcast.chapter08.javabean.Employee manager = null;
manager = (cn.itcast.chapter08.javabean.Employee) _jspx_page_context
        .getAttribute("manager",javax.servlet.jsp.PageContext.PAGE_SCOPE);
if (manager == null) {
    try {
        manager = (cn.itcast.chapter08.javabean.Employee) java.beans.Beans
                .instantiate(this.getClass().getClassLoader(),
                        "cn.itcast.chapter08.javabean.Employee");
        } catch (java.lang.ClassNotFoundException exc) {
            throw new InstantiationException(exc.getMessage());
        } catch (java.lang.Exception exc) {
            throw new javax.servlet.ServletException(
                "Cannot create bean of class "
                    + "cn.itcast.chapter08.javabean.Employee",exc);
        }
_jspx_page_context.setAttribute("manager", manager,
        javax.servlet.jsp.PageContext.PAGE_SCOPE);
}
…… ……

从上面的代码中可以看到,JSP容器会在scope属性指定的域范围中查找以id属性值为名称的JavaBean对象,如果该域范围中不存在指定JavaBean对象,JSP容器会将加载当前类的对象和beanName属性值作为参数传递给java.beans.Beans类的instantiate()方法,去创建新的JavaBean实例对象,如果创建成功,JSP容器会将该对象以id属性值为名称存储到scope属性指定的域范围中。至于instantiate()方法如何创建JavaBean对象这里就不再讲解了,大家如果有兴趣可以自己去查看源代码。

点击此处
隐藏目录