Tomcat与JavaWeb 6.1 JavaBean与JSP

1.    JavaBean简介

JavaBean是一种可重复使用且跨平台的软件组件。可分为两种:一种是又用户界面的JavaBean,还有一种没有用户界面,主要负责表示业务数据或者处理事务(如数据运算、操纵数据库)的JavaBean。JSP访问的通常是后一种JavaBean。

JSP与JavaBean搭配使用的好处:

  •  使得HTML与Java程序分离,这样便于维护代码。如果把所有的程序代码都写到JSP网页中,会使得代码繁杂、难以维护。
  • 可以降低对开发JSP网页的人员的java编程能力的要求。
  • JSP侧重于生成动态网页,事务处理由JavaBean来完成,这样可以充分利用JavaBean组件的可重用性特点,提高开发网站的的效率。

一个标准的JavaBean有以下特性:

  • JavaBean是一个公共的(public)类。
  • JavaBean有一个不带参数的构造方法。
  • JavaBean通过get()方法获取属性,通过set()方法设置属性。
  • 属性名和get/set方法名之间存在着固定的对应关系:如果属性名为xyz,那么get/set方法名为getXyz/setXyz,属性名中的第一个字母在方法名中大写。
  • 如果希望JavaBean能被持久化,那么可以使它实现java.io.Serializable接口。5.2章的例程ShoppingCart类就属于JavaBean,它实现了Serializable接口,因此当Servlet容器持久化一个会话时,也会对存放在其中是ShoppingCart对象进行持久化。
  • 在JavaBean中除了定义get和set方法,也可以像普通Java类一样定义其他完成特定功能的方法。

以下是一个JavaBean的例子,类名为CounterBean,在该类中定义了一个属性count,还定义了访问这个属性的get/set方法。注意,Bean要放在命名包里,不可以放在默认包里,否则无法被JSP文件引用。
CounterBean.java

package mypack;

public class CounterBean {
    private int count;

    public CounterBean(){}
    public int getCount(){
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }
}

2.    JSP访问JavaBean的语法

在JSP网页中既可以通过程序代码来访问JavaBean,也可以通过特定的JSP标签访问JavaBean。采用后一中方法可以减少JSP网页中的程序代码,使它更接近HTML页面。使用JSP标签访问JavaBean的方法如下:

    1)    导入Javabean类

如果在JSP网页中访问JavaBean,首先要通过<%@ page import=""%>指令来引入JavaBean类:

<%@ page import="CounterBean" %>
    2)     声明JavaBean对象

<jsp:useBean>标签用来声明JavaBean对象:

<jsp:useBean id="myBean" class="CounterBean" scope="session"/>
上述代码声明了一个名字为myBean的JavaBean对象。该标签具有以下属性:
  • id属性:代表JavaBean对象的ID,实际上表示引用JavaBean对象的局部变量名,以及存放在特定范围的属性名。JSP规范要求存放在所有范围内的JavaBean对象都有唯一的ID。例如不允许在会话范围内存在两个ID为“myBean”的JavaBean,也不允许在会话范围内核请求范围内分别存在ID为“myBean”的JavaBean。
  • class属性:用来指定Javabean的类名。
  • scope属性:用来指定JavaBean对象的存放范围,可选值包括page(页面范围)、request(请求范围)、session(会话范围)和application(Web应用范围)。scope属性的默认值是page,范例中的scope属性取值为session,表示会话范围.

以上示范代码中的<jsp:useBean>标签的处理流程如下:

  1. 定义一个名为myBean的局部变量。
  2. 尝试从scope指定的会话范围内读取名为myBean的属性,并且使得myBean局部变量引用具体的属性值,即CounterBean对象。
  3. 如果scope指定的会话范围内,名为“myBean”的属性不存在,那么久通过CounterBean类的默认构造方法创建一个CounterBean对象,并把它存放在会话范围内,令其属性名为"myBean",此外,myBean局部变量也引用该对象。

以上<jsp:useBean>标签和以下Java程序片段的作用是等价的:

        CounterBean myBean = null;
        //试图从会话范围内读取myBean属性
        myBean  = (CounterBean)session.getAttribute("myBean");
        if (myBean  == null){
            myBean = new CounterBean();
            session.setAttribute("myBean",myBean);
        }

可以看到,<jsp:useBean>标签在形式上比Java程序片段简洁多了。

    3)    访问JavaBean属性

JSP提供了访问JavaBean属性的标签,如果要将JavaBean的某个属性输出到网页上,可以用<jsp:getProperty>标签:

<jsp:getProperty name="myBean" property="count" />

以上标签根据name属性的值"myBean"找到又<jsp:useBean>标签声明的ID为"myBean"的CounterBean对象,然后打印它的count属性。它等价于: <%=myBean.getCount()%>程序片段。

Servlet容器在运行该标签时,会根据property指定的属性名,自动调用JavaBean的相应的get方法。属性名和get方法名之间存在固定的对应关系,在第一节javaBean特性中已经提到。范例中的CounterBean的属性名为count,那么对应的get方法就是getCount()。加入在CounterBean类中不存在getCount()方法,那么Servlet容器在运行<jsp:getProperty>标签时就会抛出异常。因此开发人员创建的JavaBean类必须严格遵守JavaBean的规范。

如果要给JavaBean的某个属性赋值,可以用<jsp:setProperty>标签,例如:

<jsp:setProperty name="myBean" property="count" value="1"/>

需要注意的是,如果一个JSP文件通过<jsp:setProperty>或<jsp:getProperty>标签访问一个JavaBean的属性,要求该JSP文件先通过<jsp:useBean>标签声明这个JavaBean,否则<jsp:setProperty>和<jsp:getProperty>运行时就会抛出异常。

3.    JavaBean的范围

<jsp:useBean>标签中可以设置JavaBean的scope属性,它决定了JavaBean对象存在的范围。下面用访问CounterBean的4个JSP例子来演示4种范围的特性和区别。

    1)    页面(page)范围内的JavaBean

页面范围对应的时间段为:从客户请求访问一个JSP文件开始,到这个JSP文件执行结束。在pageCounter1.jsp中声明了一个存放在页面范围内的CounterBean,每次当客户请求访问pageCounter1.jsp时,<jsp:useBean>比起哦爱你都会创建一个CounterBean对象,并把它存放在页面范围内,该CounterBean对象在两种情况下会结束生命周期:

  • 客户请求访问当前pageCounter1.jsp页面执行完毕,接着通过<jsp:forward>标记将请求转发到另一个Web组件。
  • 客户请求访问的当前pageCounter1.jsp页面执行完毕并向客户端发送响应。

由此可见,页面范围内的JavaBean对象只在当前爱你JSP页面中有效。加入pageCounter1.jsp把请求转发给pageCounter2.jsp,那么pageCounter2.jsp是无法访问到pageCounter1.jsp页面范围内的JavaBean对象的。

pageCounter1.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<jsp:useBean id="myPageBean" class="mypack.CounterBean" scope="page"/>
<html><head><title>pageCounter</title></head>
<body>
<jsp:setProperty name="myPageBean" property="count" value="<%=myPageBean.getCount()+1 %>"/>
Current count value is :<jsp:getProperty name="myPageBean" property="count"/>
<%
    String scopeNames[] = {"No Scope","page","request","session","application"};
    int scope = pageContext.getAttributesScope("myPageBean");
%>
<p>scope = <%=scopeNames[scope]%></p>
</body>
</html>

运行Web应用,通过浏览器多次访问pageCounter1.jsp,会看到CounterBean对象的count属性的值始终为1.客户端每次访问pageCounter1.jsp,服务器端都会创建新的CounterBean对象,并把它存放在当前页面范围内。count属性的初始值为0,接下来<jsp:setProperty>标签把count属性的值增加1.等到pageCounter1.jsp完成了对本次客户端请求的响应,这个CounterBean对象就结束生命周期。

现在,修改pageCounter1.jsp文件,在文件末尾把请求转发给pageCounter2.jsp:

<jsp:forward page="pageCounter2.jsp"/>
pageCounter2.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>pageCounter</title>
</head>
<body>
<jsp:useBean id="myPageBean" scope="page" class="mypack.CounterBean"/>
Current count value is :<jsp:getProperty name="myPageBean" property="count"/>
</body>
</html>

该JSP页面也在页面范围内声明了一个名为myPageBean的CounterBean对象,然后打印它的count属性。

下一步,运行应用,通过浏览器访问地址:localhost:8080/pageCounter1.jsp,pageCounter1.jsp把请求转发给pageCounter2.jsp,浏览器端最后得到pageCounter2.jsp的打印结果:


pageCounter2.jsp页面范围和pageCounter1.jsp的页面范围各自独立。当客户请求被转发给2的时候,1的页面范围内的CounterBean对象就结束生命周期,接下来pageCounter2.jsp创建一个CounterBean对象,并把它存放在自己的当前页面范围内。CounterBean对象的count属性的初始值为0 。

    2)    请求(request)范围内的JavaBean

请求范围对应的时间段为:从客户请求访问一个JSP文件开始,到这个JSP文件返回响应结果结束,如果这个JSP文件把请求转发给其他Web组件,那么直到其他Web组件返回响应结果结束。

对于请求范围内的javaBean对象,它存在于响应一个客户请求的整个过程中。当所有共享同一个客户请求的JSP文件执行完毕并向客户端返回响应时,本次请求范围内的JavaBean对象结束生命周期。在JSP文件中声明的request范围内的javaBean对象,它可以被一下Web组件共享:

  • 该JSP文件本身。
  • 和该JSP文件共享同一个客户请求(即HttpServletRequest对象)的Web组件,包括该JSP文件通过<%@ include>指令或<jsp:include>标记包含的其他Web组件,以及通过<jsp:forward>标记转发的其他目标Web组件。

请求范围内的javaBean对象实际上是作为属性保存在HttpServletRequest对象中的,其属性名和JavaBean对象的ID相同,属性值为JavaBean对象,因此也可以通过HttpServletRequest.getAttribute()方法来读取请求范围内的JavaBean对象:

CounterBean obj = (CounterBean)request.getAttribute("nyRequestBean");
    3)    会话(session)范围内的JavaBean
会话范围对应整个会话的生存周期,处于同一个会话中的Web组件共享这个会话范围内的JavaBean对象。

会话范围内的JavaBean对象实际上是作为属性保存在HttpSession对象(在JSP固定饮用为session)中的,和request类似。

    4)    Web应用(application)范围内的JavaBean
Web应用范围对应整个Web应用的生存周期,处于同一个Web应用中的所有Web组件共享这个Web应用范围内的JavaBean对象。

Web应用范围内的JavaBean对象实际上是作为属性保存在ServletContext对象(在JSP固定饮用为application)中的,和request类似。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值