Bean的中文含义是“豆子”,顾名思义Java Bean是一段Java小程序。Java Bean实际上是指一种特殊的Java类,它通常用来实现一些比较常用的简单功能,并可以很容易的被重用或者是插入其他应用程序中去。所有遵循一定编程原则的Java类都可以被称作Java Bean。本章将由浅入深介绍Java Bean的设计原理及应用方式,并重点介绍Java Bean在JSP中的应用。
17.1 Java Bean技术概述
Java Bean是基于Java的组件模型,由属性、方法和事件3部分组成。在该模型中,Java Bean可以被修改或与其他组件结合以生成新组件或完整的程序。它是一种Java类,通过封装成为具有某种功能或者处理某个业务的对象。因此,也可以通过嵌在JSP页面内的Java代码访问Bean及其属性。
Bean的含义是可重复使用的Java组件。所谓组件就是一个由可以自行进行内部管理的一个或几个类所组成、外界不了解其内部信息和运行方式的群体。使用它的对象只能通过接口来操作。
17.2 Java Bean编写规范
Java Bean实际上是根据Java Bean技术标准所指定Bean的命名和设计规范编写的Java类。这些类遵循一个接口格式,以便于使函数命名、底层行为以及继承或实现的行为,其最大的优点在于可以实现代码的可重用性。Bean并不需要继承特别的基类(Base Class)或实现特定的接口(Interface)。Bean的编写规范使Bean的容器(Container)能够分析一个Java类文件,并将其方法(Methods)翻译成属性(Properties),即把Java类作为一个Bean类使用。Bean的编写规范包括Bean类的构造方法、定义属性和访问方法编写规则。
17.2.1 Bean组件的工作机制
在JavaBeans Version1.01 A规范中定义了该组件的5种重要机制:
内省(Introspection):组建可以发表其支持的操作和属性,同时也支持在其他组件中发现重复利用的对象库,如用户权限控制和电子邮件自动回复等。
通信(Communication):生成和收集组件的消息事件。
持续(Persistence):存放组件的状态。
属性 (Properties):支持组件布局的控制,包括组件占用的空间和组件的相对位置。
定制(Customization):开发者可控制组件所需的改变机制。
17.2.2 Java Bean的编写要求
编写Java Bean必须满足以下几点要求:
所有的Java Bean必须放在一个包(Package)中。
Java Bean必须生成public class类,文件名称应该与类名称一致。
所有属性必须封装,一个Java Bean类不应有公共实例变量,类变量都为private。
属性值应该通过一组存取方法(getXxx 和 setXxx)来访问:对于每个属性,应该有一个带匹配公用 getter 和 setter 方法的专用实例变量。
Java Bean 类必须有一个空的构造函数:类中必须有一个不带参数的公用构造器,此构造器也应该通过调用各个属性的设置方法来设置属性的默认值。
17.2.3 Java Bean的命名规范
Java Bean的命名规范如下:
包命名:全部字母小写。
类命名:每个单词首字母大写。
属性名:第一个单词全部小写,之后每个单词首字母大写。
方法名:与属性命名方法相同。
常量名:全部字母大写。
17.2.4 Java Bean的包
包即package在本书前面的章节中已经有过介绍,Java Bean的包和前面章节中介绍的包含义基本上是一样的,但是也有区别,前面介绍的包都是Java本身定义的,而Java Bean的包是用户自己定义的。
每一个Java Bean源文件被编译成.class文件后,都必须存放在相应的文件夹下,存放这个.class文件的文件夹就是一个包。Java Bean的包必须存放在特定的目录下,在每个JSP引擎中都规定了存放Java Bean包的位置,不同的JSP引擎对Java Bean存放的位置有不同的规定,如在本书第16章介绍的Tomcat软件中,Java Bean的所有包都存放在WEB-INF/classes文件夹中。如果存在多级目录,则需要将.class文件所在目录的所有上级目录包含到包名称中,每一级目录之间用英文标点“.”隔开。例如下面代码:
package jsp.example.mybean;
17.2.5 Java Bean的结构
代码是一个典型的Java Bean实例,我们用它来说明Java Bean的结构。
属性:即Java Bean类的成员变量,用于描述Java Bean对象的状态,对象属性值的改变触发事件,属性本身就是事件源。
方法:在 Java Bean中,函数和过程统称为方法,通过方法来改变和获取属性的值。方法可以分为构造方法、访问方法和普通方法等。
事件:事件实际上是一种特殊的Java Bean,属性值的改变触发事件,事件激发相关对象作出反应,通过Java Bean注册对象事件监听者机制来接收、处理事件,它实现了Java Bean之间的通信。
17.3 Java Bean属性
在上一节中我们简单提到了Java Bean的属性,Java Bean的属性与一般Java程序中所指的属性,或者说与所有面向对象的程序设计语言中对象的属性是一个概念,在程序中的具体体现就是类中的变量。属性分为四类,即单值(Simple)、索引(Index)、关联(Bound)和约束(Constrained)属性。本节将对这些属性进行详细说明。
17.3.1 单值(Simple)属性
单值(Simple)属性是最普通的属性类型,该类属性只有一个单一的数据值,该数据值的数据类型可以是Java中的任意数据类型,包括类和接口等类型。
定义了属性,还需定义对应的访问方法,一般每个单值属性都伴随有一对get/set 方法。属性名与和该属性相关的get/set方法名对应。例如如果有一个名为“xxx”的属性,则会有setXxx和getXxx方法。
另外,布尔(Boolean)属性是一种特殊的单值属性,它只有两个允许值:true和false,如果有一个名为“xxx”的布尔属性,则可以通过isX方法访问。
在上一节的代码实例中所有的属性都是简单属性,get、set和is等方法就是对这些简单属性的访问方法,关于访问方法,将在17.4.2小节中介绍。
17.3.2 索引(Indexed)属性
如果需要定义一批同类型的属性,使用单值属性就会显得非常烦琐,为解决此问题,Java Bean中提供了索引(Indexed) 属性,索引属性是指Java Bean中数组类型的成员变量。使用与该属性对应的set/get方法可取得数组的值。索引属性通过对应的访问方法设置或取得该属性中某个元素的值,也可以一次设置或取得整个属性的值。
17.3.3 关联(Bound)属性
关联(Bound)属性是指当该种属性的值发生变化时,要通知其他的对象。每次属性值改变时,这种属性就触发一个PropertyChange事件(在Java程序中,事件也是一个对象,事件将在17.5节详细介绍)。事件中封装了属性名、属性的原值、属性变化后的新值。这种事件传递到其他的Beans,至于接收事件的Beans应做什么动作,由其自己定义。
属性的改变称为Java Bean事件。外部与Java Bean这些事件相关的类对象称为监听者(Listener)。监听者可能只对Java Bean某一属性相关的事件有兴趣,也可能对所有属性相关的事件有兴趣,因此Java Bean提供两类事件监听者注册和注销的方法,即全局事件监听者注册、注销的方法和一般事件监听者注册、注销的方法。
17.3.4 约束(Constrained)属性
Java Bean的属性如果改变时,相关的外部类对象首先要检查这个属性改变的合理性再决定是否接受这种改变,这样的Java Bean属性叫约束(Constrained)属性。当约束属性的改变被拒绝时,改变约束属性的方法产生一个约束属性改变异常 (PropertyVetoException),通过这个异常处理,Java Bean约束属性还原回原来的值,并为这个还原操作发送一个新的属性修改通知。
约束属性的改变可能会被拒绝,因此它的setXxx与一般其他 Java Bean属性的setXxx也有所不同。约束属性的写方法如下:
public void setXxx(xxxType newXxx) throws PropertyVetoException
17.4 Java Bean方法
在前面17.2.5小节介绍Java Bean结构时,简单地介绍了Java Bean方法,我们知道在Java Bean中的函数和过程统称为方法,通过方法来改变和获取17.3节中介绍的各种属性值。方法可以分为构造方法、访问方法和普通方法等。本节将学习创建和使用这些方法。
17.4.1 构造方法
Java Bean的构造方法与本书第8章介绍的累的构造方法意思是一样的,就是对Java Bean的属性及其方法进行初始化,即对所定义的属性及方法设一个初始值,构造方法名要和Java Bean的类名相同。下面的代码定义的就是一个Java Bean及其构造方法。
17.4.2 访问方法
在定义了Bean的属性,并通过构造方法将其初始化后,要让其他程序访问Bean的这些属性,就必须为其创建访问方法。访问方法就是对组件中定义的属性的访问,包括读和写两种访问方式。读就是一种用于取出Bean属性的值的取值函数,即getter;而写则是一种用于设置Bean属性的赋值函数,即setter。以下列出的就是Bean属性访问方法的具体语法格式:
public void setPropertyName(PropertyType value);//给属性赋值,即写方法
public PropertyType getPropertyName();//读取属性值,即读方法
17.4.3 一般方法
除了对属性的访问方法外,还可以在Bean创建一般方法来实现对函数的调用,只要将Bean中的一般方法定义成公有的方法,就可以供其他程序调用。代码是一个实现求阶乘函数的一般方法。
代码 Multiple.java
1 package jsp.examples.mybean;
2 public class Multiple{
3 public int Multi(int j){
4 int x = 1;
5 for (int i = 1; i <= j; ++i)
6 { x = x * i; }
7 return x;}
8 }
17.5 Java Bean事件
事件处理是JavaBeans体系结构的核心之一。通过事件处理机制,可让一些组件作为事件源,发出可被描述环境或其他组件接收的事件。这样,不同的组件就可在构造工具内组合在一起,组件之间通过事件的传递进行通信,构成一个应用。从概念上讲,事件是一种在“源对象”和“监听者对象”之间某种状态发生变化的传递机制。事件有许多不同的用途,例如在Windows系统中常要处理的鼠标事件、窗口边界改变事件、键盘事件等。
17.5.1 事件模型
Java Bean事件模型如图所示,事件源是一个JavaBean类对象,它把属性改变的时间对象传递给事件监听者,事件监听者负责事件的处理。事件监听者必须在事件源注册。
17.5.2 事件状态对象
与事件发生有关的状态信息一般都封装在事件状态对象 (Event State Object) 中,这种对象是java.util.EventObject的子类。按设计习惯,这种事件状态对象类的名应以Event结尾。例如代码是一个鼠标移动事件实例。
17.5.3 事件监听者接口与事件监听者
由于Java事件模型是基于方法调用的,因此需要一个定义并组织事件操纵方法的方式。 JavaBeans中,事件操纵方法都被定义在继承了java.util.EventListener类的事件监听者(EventListener)接口中,按规定,EventListener接口的命名要以Listener结尾。任何一个类如果想操纵在EventListener接口中,定义的方法都必须以实现这个接口方式进行。这个类就是事件监听者。例如如下代码。
//先定义了一个鼠标移动事件对象
public class MouseMovedExampleEvent extends java.util.EventObject {
// 在此类中包含了与鼠标移动事件有关的状态信息
...
}
//定义了鼠标移动事件的监听者接口
interface MouseMovedExampleListener extends java.util.EventListener {
//在这个接口中定义了鼠标移动事件监听者所应支持的方法
void mouseMoved(MouseMovedExampleEvent mme);
}
17.5.4 事件监听者注册与注销
为了让各种可能的事件监听者把自己注册入合适的事件源中,就建立源与事件监听者间的事件流,事件源必须为事件监听者提供注册和注销的方法。在前面第17.3节关联属性和约束属性的介绍中,已看到了这种使用过程,在实际中,事件监听者的注册和注销要使用以下标准的设计格式:
public void add< ListenerType>(< ListenerType> listener);
public void remove< ListenerType>(< ListenerType> listener);
下面是一个具体的实例,首先定义了一个事件监听者接口:
import java.util.*;
public interface ModelChangedListener extends EventListener
{ void modelChanged(EventObject e);}
17.5.5 适配类
适配类是Java事件模型中极其重要的一部分。在一些应用场合,事件从源到监听者之间的传递要通过适配类来“转发”。例如:当事件源发出一个事件,而有几个事件监听者对象都可接收该事件,但只有指定对象做出反应时,就要在事件源与事件监听者之间插入一个事件适配器类,由适配器类来指定事件应该是由哪些监听者来响应。适配类成为了事件监听者,事件源实际是把适配类作为监听者注册入监听者队列中,而真正的事件响应者并未在监听者队列中,事件响应者应做的动作由适配类决定。目前绝大多数的开发工具在生成代码时,事件处理都是通过适配类来进行的。
17.6 Java Bean在JSP中的应用
在前面几节我们学习了Java Bean的编写,由于Java Bean是为了重复使用的程序段落,具有“Write once, run anywhere, reuse everywhere”,即“一次性编写,任何地方执行,所有地方可重用”的特点,所以可以为JSP平台提供一个简单的、紧凑的和优秀的问题解决方案,能大幅度提高系统的功能上限、加快执行速度,而且不需要牺牲系统的性能。同时,采用JavaBean技术可以使系统更易于维护,因此极大地提高了JSP的应用范围。本节将详细学习如何在JSP中应用Bean组件。
17.6.1 调用Java Bean
在上一章16.6.2节中介绍了通过JSP标记中的<jsp:useBean>动作来调用Java Bean,下面我们在学习完Java Bean的编写之后,再来复习一下这个标记:
<jsp:useBean id="beanId" scope="page|request|session|application" class="package.class" />
首先,我们通过标记中的id属性标记Bean,以使JSP页面的其余部分可以正确的识别该Bean。
其次,使用scope属性来确定该Bean的使用范围。scope属性所决定的使用范围,可以参考我们在上一章第16.7.10小节中所作的介绍。
最后,class属性通知JSP页面从何处查找Bean,即找到Bean的.class文件。在此我们必须同时指定 JavaBean的包(package)名和类(class)名,即class="package.class",否则JSP引擎将无法找到相应的 Bean。
17.6.2 链接数据库Bean
在第10章中我们学习了通过JDBC链接数据库以及在数据库中进行数据的查询、修改、插入和删除等操作。在JSP的应用中,数据库的运用有着十分重要的地位,可以说数据库的运用是JSP应用的关键之一。在数据库的运用中我们可以发现,在数据库相关程序中,这些操作都有很多相似之处,许多语句都是通用的。在学习了Java Bean之后,我们很自然的就想到是否可以将这些语句编写到一个Java Bean中,这样可以为以后编写的数据库程序提供极大的方便。
17.6.3 通过Java Bean查询数据库
在前面的小节中,我们编写了一个典型的链接数据库Bean,在这一小节中,我们通过一个实例来学习JSP中如何通过这个Java Bean来访问数据库。
在此,我们先用Access数据库软件创建一个名为 AddressBook.mdb的数据库,这个数据库中有一个名为“user”的表。将这个数据库设置成名为“JavaBeanTestDB”的系统数据源,具体的设置方法参考本书的第11章11.3.2小节中的详细介绍。
本实例的目的是对数据库中的user表进行查询、修改、插入和删除操作。代码17-11实现的是将user表中的用户ID、用户名以及用户密码显示出来,并通过“添加”、“修改”和“删除”按钮分别链接到添加、修改和删除记录页面。
17.6.4 向数据库添加记录
在单击图中的“添加”按钮后,将跳转到添加记录页面,添加记录页面的源文件如代码所示:
17.6.5 修改数据库记录
在单击17.6.3小节图中的“修改”按钮后,将跳转到修改记录页面,该页面实现对用户密码的修改,修改记录页面的源文件如代码所示。
17.6.6 删除数据库记录
删除数据库记录首先是建立数据库链接,然后通过删除选定的数据库记录字句执行记录,如果该记录不存在则返回,如果存在则删除该记录。删除数据库记录页面的源文件如代码所示。
17.7 本章习题
(1)选择题
说明:本章的选择题中有单选题也有多选题,用于读者检查自己对本章中关键概念的掌握程度。
1.如果要编写一个Bean,并将该Bean存放在WEB-INF/classes/jsp/example/mybean目录下,则包(package)名称是?
A.package mybean; B.package classes.jsp.example.mybean;
C.package jsp.example; D.package jsp.example.mybean;
2.编写一个Bean必须满足哪几点要求?
A.必须放在一个包(Package)中 B.必须生成public class类
C.必须有一个空的构造函数 D.所有属性必须封装
E.应该通过一组存取方法来访问
3.Java Bean中的属性命名的规范是?
A.全部字母小写 B.每个单词首字母大写
C.第一个单词全部小写,之后每个单词首字母大写 D.全部字母大写
4.在JSP中引用Bean应该如何操作?
A.page指令 B.include指令 C.include动作 D.useBean动作
5.private int[] myInt;语句定义的是?
A.单值属性 B.索引属性 C.关联属性 D.约束属性
6.在代码17-10所生成的Bean中,close()方法执行了哪些操作?
A.关闭数据集 B.关闭Statement对象
C.关闭数据链接 D.关闭数据库驱动
7.在useBean动作中,应该设置下面那些参数?
A.Id B.Scope C.Class D.name
8.Java Bean有几种属性?
A.4种 B.3种 C.2种 D.1种
9.Java Bean的方法可以分为几种?
A.4种 B.3 种 C.2种 D.1种
10.在17.6.2小节的Bean实例中,如果数据源改变,需要设置哪几种属性的值?
A.rs属性 B.url属性
C.user属性 D.password属性
(2)程序阅读题
指出下面Java Bean代码中的错误(共6处错误):
package jsp.examples.mybean;
import java.beans.*;
public class Hello { //类名,应该与文件名相同
//定义属性
String myStr;
public Boolean myBool;
public hello() {
myStr = "Hello Java Bean!";
myBool = true;
}
//get方法
private String getMyStr()
{ return this.myStr;}
//set方法
public void setMyStr(String str)
{this.myStr = str;}
public Boolean setMyBool(Boolean bool)
{ this.myBool = bool; }
//is方法
public void isMyBool()
{ return this.myBool; }
}
(3)实际操作题
编写一个用户登注册页面,通过调用数据库链接Bean将用户输入的注册信息写入数据库,用户注册后转到欢迎页面,并显示用户信息。
17.1 Java Bean技术概述
Java Bean是基于Java的组件模型,由属性、方法和事件3部分组成。在该模型中,Java Bean可以被修改或与其他组件结合以生成新组件或完整的程序。它是一种Java类,通过封装成为具有某种功能或者处理某个业务的对象。因此,也可以通过嵌在JSP页面内的Java代码访问Bean及其属性。
Bean的含义是可重复使用的Java组件。所谓组件就是一个由可以自行进行内部管理的一个或几个类所组成、外界不了解其内部信息和运行方式的群体。使用它的对象只能通过接口来操作。
17.2 Java Bean编写规范
Java Bean实际上是根据Java Bean技术标准所指定Bean的命名和设计规范编写的Java类。这些类遵循一个接口格式,以便于使函数命名、底层行为以及继承或实现的行为,其最大的优点在于可以实现代码的可重用性。Bean并不需要继承特别的基类(Base Class)或实现特定的接口(Interface)。Bean的编写规范使Bean的容器(Container)能够分析一个Java类文件,并将其方法(Methods)翻译成属性(Properties),即把Java类作为一个Bean类使用。Bean的编写规范包括Bean类的构造方法、定义属性和访问方法编写规则。
17.2.1 Bean组件的工作机制
在JavaBeans Version1.01 A规范中定义了该组件的5种重要机制:
内省(Introspection):组建可以发表其支持的操作和属性,同时也支持在其他组件中发现重复利用的对象库,如用户权限控制和电子邮件自动回复等。
通信(Communication):生成和收集组件的消息事件。
持续(Persistence):存放组件的状态。
属性 (Properties):支持组件布局的控制,包括组件占用的空间和组件的相对位置。
定制(Customization):开发者可控制组件所需的改变机制。
17.2.2 Java Bean的编写要求
编写Java Bean必须满足以下几点要求:
所有的Java Bean必须放在一个包(Package)中。
Java Bean必须生成public class类,文件名称应该与类名称一致。
所有属性必须封装,一个Java Bean类不应有公共实例变量,类变量都为private。
属性值应该通过一组存取方法(getXxx 和 setXxx)来访问:对于每个属性,应该有一个带匹配公用 getter 和 setter 方法的专用实例变量。
Java Bean 类必须有一个空的构造函数:类中必须有一个不带参数的公用构造器,此构造器也应该通过调用各个属性的设置方法来设置属性的默认值。
17.2.3 Java Bean的命名规范
Java Bean的命名规范如下:
包命名:全部字母小写。
类命名:每个单词首字母大写。
属性名:第一个单词全部小写,之后每个单词首字母大写。
方法名:与属性命名方法相同。
常量名:全部字母大写。
17.2.4 Java Bean的包
包即package在本书前面的章节中已经有过介绍,Java Bean的包和前面章节中介绍的包含义基本上是一样的,但是也有区别,前面介绍的包都是Java本身定义的,而Java Bean的包是用户自己定义的。
每一个Java Bean源文件被编译成.class文件后,都必须存放在相应的文件夹下,存放这个.class文件的文件夹就是一个包。Java Bean的包必须存放在特定的目录下,在每个JSP引擎中都规定了存放Java Bean包的位置,不同的JSP引擎对Java Bean存放的位置有不同的规定,如在本书第16章介绍的Tomcat软件中,Java Bean的所有包都存放在WEB-INF/classes文件夹中。如果存在多级目录,则需要将.class文件所在目录的所有上级目录包含到包名称中,每一级目录之间用英文标点“.”隔开。例如下面代码:
package jsp.example.mybean;
17.2.5 Java Bean的结构
代码是一个典型的Java Bean实例,我们用它来说明Java Bean的结构。
属性:即Java Bean类的成员变量,用于描述Java Bean对象的状态,对象属性值的改变触发事件,属性本身就是事件源。
方法:在 Java Bean中,函数和过程统称为方法,通过方法来改变和获取属性的值。方法可以分为构造方法、访问方法和普通方法等。
事件:事件实际上是一种特殊的Java Bean,属性值的改变触发事件,事件激发相关对象作出反应,通过Java Bean注册对象事件监听者机制来接收、处理事件,它实现了Java Bean之间的通信。
17.3 Java Bean属性
在上一节中我们简单提到了Java Bean的属性,Java Bean的属性与一般Java程序中所指的属性,或者说与所有面向对象的程序设计语言中对象的属性是一个概念,在程序中的具体体现就是类中的变量。属性分为四类,即单值(Simple)、索引(Index)、关联(Bound)和约束(Constrained)属性。本节将对这些属性进行详细说明。
17.3.1 单值(Simple)属性
单值(Simple)属性是最普通的属性类型,该类属性只有一个单一的数据值,该数据值的数据类型可以是Java中的任意数据类型,包括类和接口等类型。
定义了属性,还需定义对应的访问方法,一般每个单值属性都伴随有一对get/set 方法。属性名与和该属性相关的get/set方法名对应。例如如果有一个名为“xxx”的属性,则会有setXxx和getXxx方法。
另外,布尔(Boolean)属性是一种特殊的单值属性,它只有两个允许值:true和false,如果有一个名为“xxx”的布尔属性,则可以通过isX方法访问。
在上一节的代码实例中所有的属性都是简单属性,get、set和is等方法就是对这些简单属性的访问方法,关于访问方法,将在17.4.2小节中介绍。
17.3.2 索引(Indexed)属性
如果需要定义一批同类型的属性,使用单值属性就会显得非常烦琐,为解决此问题,Java Bean中提供了索引(Indexed) 属性,索引属性是指Java Bean中数组类型的成员变量。使用与该属性对应的set/get方法可取得数组的值。索引属性通过对应的访问方法设置或取得该属性中某个元素的值,也可以一次设置或取得整个属性的值。
17.3.3 关联(Bound)属性
关联(Bound)属性是指当该种属性的值发生变化时,要通知其他的对象。每次属性值改变时,这种属性就触发一个PropertyChange事件(在Java程序中,事件也是一个对象,事件将在17.5节详细介绍)。事件中封装了属性名、属性的原值、属性变化后的新值。这种事件传递到其他的Beans,至于接收事件的Beans应做什么动作,由其自己定义。
属性的改变称为Java Bean事件。外部与Java Bean这些事件相关的类对象称为监听者(Listener)。监听者可能只对Java Bean某一属性相关的事件有兴趣,也可能对所有属性相关的事件有兴趣,因此Java Bean提供两类事件监听者注册和注销的方法,即全局事件监听者注册、注销的方法和一般事件监听者注册、注销的方法。
17.3.4 约束(Constrained)属性
Java Bean的属性如果改变时,相关的外部类对象首先要检查这个属性改变的合理性再决定是否接受这种改变,这样的Java Bean属性叫约束(Constrained)属性。当约束属性的改变被拒绝时,改变约束属性的方法产生一个约束属性改变异常 (PropertyVetoException),通过这个异常处理,Java Bean约束属性还原回原来的值,并为这个还原操作发送一个新的属性修改通知。
约束属性的改变可能会被拒绝,因此它的setXxx与一般其他 Java Bean属性的setXxx也有所不同。约束属性的写方法如下:
public void setXxx(xxxType newXxx) throws PropertyVetoException
17.4 Java Bean方法
在前面17.2.5小节介绍Java Bean结构时,简单地介绍了Java Bean方法,我们知道在Java Bean中的函数和过程统称为方法,通过方法来改变和获取17.3节中介绍的各种属性值。方法可以分为构造方法、访问方法和普通方法等。本节将学习创建和使用这些方法。
17.4.1 构造方法
Java Bean的构造方法与本书第8章介绍的累的构造方法意思是一样的,就是对Java Bean的属性及其方法进行初始化,即对所定义的属性及方法设一个初始值,构造方法名要和Java Bean的类名相同。下面的代码定义的就是一个Java Bean及其构造方法。
17.4.2 访问方法
在定义了Bean的属性,并通过构造方法将其初始化后,要让其他程序访问Bean的这些属性,就必须为其创建访问方法。访问方法就是对组件中定义的属性的访问,包括读和写两种访问方式。读就是一种用于取出Bean属性的值的取值函数,即getter;而写则是一种用于设置Bean属性的赋值函数,即setter。以下列出的就是Bean属性访问方法的具体语法格式:
public void setPropertyName(PropertyType value);//给属性赋值,即写方法
public PropertyType getPropertyName();//读取属性值,即读方法
17.4.3 一般方法
除了对属性的访问方法外,还可以在Bean创建一般方法来实现对函数的调用,只要将Bean中的一般方法定义成公有的方法,就可以供其他程序调用。代码是一个实现求阶乘函数的一般方法。
代码 Multiple.java
1 package jsp.examples.mybean;
2 public class Multiple{
3 public int Multi(int j){
4 int x = 1;
5 for (int i = 1; i <= j; ++i)
6 { x = x * i; }
7 return x;}
8 }
17.5 Java Bean事件
事件处理是JavaBeans体系结构的核心之一。通过事件处理机制,可让一些组件作为事件源,发出可被描述环境或其他组件接收的事件。这样,不同的组件就可在构造工具内组合在一起,组件之间通过事件的传递进行通信,构成一个应用。从概念上讲,事件是一种在“源对象”和“监听者对象”之间某种状态发生变化的传递机制。事件有许多不同的用途,例如在Windows系统中常要处理的鼠标事件、窗口边界改变事件、键盘事件等。
17.5.1 事件模型
Java Bean事件模型如图所示,事件源是一个JavaBean类对象,它把属性改变的时间对象传递给事件监听者,事件监听者负责事件的处理。事件监听者必须在事件源注册。
17.5.2 事件状态对象
与事件发生有关的状态信息一般都封装在事件状态对象 (Event State Object) 中,这种对象是java.util.EventObject的子类。按设计习惯,这种事件状态对象类的名应以Event结尾。例如代码是一个鼠标移动事件实例。
17.5.3 事件监听者接口与事件监听者
由于Java事件模型是基于方法调用的,因此需要一个定义并组织事件操纵方法的方式。 JavaBeans中,事件操纵方法都被定义在继承了java.util.EventListener类的事件监听者(EventListener)接口中,按规定,EventListener接口的命名要以Listener结尾。任何一个类如果想操纵在EventListener接口中,定义的方法都必须以实现这个接口方式进行。这个类就是事件监听者。例如如下代码。
//先定义了一个鼠标移动事件对象
public class MouseMovedExampleEvent extends java.util.EventObject {
// 在此类中包含了与鼠标移动事件有关的状态信息
...
}
//定义了鼠标移动事件的监听者接口
interface MouseMovedExampleListener extends java.util.EventListener {
//在这个接口中定义了鼠标移动事件监听者所应支持的方法
void mouseMoved(MouseMovedExampleEvent mme);
}
17.5.4 事件监听者注册与注销
为了让各种可能的事件监听者把自己注册入合适的事件源中,就建立源与事件监听者间的事件流,事件源必须为事件监听者提供注册和注销的方法。在前面第17.3节关联属性和约束属性的介绍中,已看到了这种使用过程,在实际中,事件监听者的注册和注销要使用以下标准的设计格式:
public void add< ListenerType>(< ListenerType> listener);
public void remove< ListenerType>(< ListenerType> listener);
下面是一个具体的实例,首先定义了一个事件监听者接口:
import java.util.*;
public interface ModelChangedListener extends EventListener
{ void modelChanged(EventObject e);}
17.5.5 适配类
适配类是Java事件模型中极其重要的一部分。在一些应用场合,事件从源到监听者之间的传递要通过适配类来“转发”。例如:当事件源发出一个事件,而有几个事件监听者对象都可接收该事件,但只有指定对象做出反应时,就要在事件源与事件监听者之间插入一个事件适配器类,由适配器类来指定事件应该是由哪些监听者来响应。适配类成为了事件监听者,事件源实际是把适配类作为监听者注册入监听者队列中,而真正的事件响应者并未在监听者队列中,事件响应者应做的动作由适配类决定。目前绝大多数的开发工具在生成代码时,事件处理都是通过适配类来进行的。
17.6 Java Bean在JSP中的应用
在前面几节我们学习了Java Bean的编写,由于Java Bean是为了重复使用的程序段落,具有“Write once, run anywhere, reuse everywhere”,即“一次性编写,任何地方执行,所有地方可重用”的特点,所以可以为JSP平台提供一个简单的、紧凑的和优秀的问题解决方案,能大幅度提高系统的功能上限、加快执行速度,而且不需要牺牲系统的性能。同时,采用JavaBean技术可以使系统更易于维护,因此极大地提高了JSP的应用范围。本节将详细学习如何在JSP中应用Bean组件。
17.6.1 调用Java Bean
在上一章16.6.2节中介绍了通过JSP标记中的<jsp:useBean>动作来调用Java Bean,下面我们在学习完Java Bean的编写之后,再来复习一下这个标记:
<jsp:useBean id="beanId" scope="page|request|session|application" class="package.class" />
首先,我们通过标记中的id属性标记Bean,以使JSP页面的其余部分可以正确的识别该Bean。
其次,使用scope属性来确定该Bean的使用范围。scope属性所决定的使用范围,可以参考我们在上一章第16.7.10小节中所作的介绍。
最后,class属性通知JSP页面从何处查找Bean,即找到Bean的.class文件。在此我们必须同时指定 JavaBean的包(package)名和类(class)名,即class="package.class",否则JSP引擎将无法找到相应的 Bean。
17.6.2 链接数据库Bean
在第10章中我们学习了通过JDBC链接数据库以及在数据库中进行数据的查询、修改、插入和删除等操作。在JSP的应用中,数据库的运用有着十分重要的地位,可以说数据库的运用是JSP应用的关键之一。在数据库的运用中我们可以发现,在数据库相关程序中,这些操作都有很多相似之处,许多语句都是通用的。在学习了Java Bean之后,我们很自然的就想到是否可以将这些语句编写到一个Java Bean中,这样可以为以后编写的数据库程序提供极大的方便。
17.6.3 通过Java Bean查询数据库
在前面的小节中,我们编写了一个典型的链接数据库Bean,在这一小节中,我们通过一个实例来学习JSP中如何通过这个Java Bean来访问数据库。
在此,我们先用Access数据库软件创建一个名为 AddressBook.mdb的数据库,这个数据库中有一个名为“user”的表。将这个数据库设置成名为“JavaBeanTestDB”的系统数据源,具体的设置方法参考本书的第11章11.3.2小节中的详细介绍。
本实例的目的是对数据库中的user表进行查询、修改、插入和删除操作。代码17-11实现的是将user表中的用户ID、用户名以及用户密码显示出来,并通过“添加”、“修改”和“删除”按钮分别链接到添加、修改和删除记录页面。
17.6.4 向数据库添加记录
在单击图中的“添加”按钮后,将跳转到添加记录页面,添加记录页面的源文件如代码所示:
17.6.5 修改数据库记录
在单击17.6.3小节图中的“修改”按钮后,将跳转到修改记录页面,该页面实现对用户密码的修改,修改记录页面的源文件如代码所示。
17.6.6 删除数据库记录
删除数据库记录首先是建立数据库链接,然后通过删除选定的数据库记录字句执行记录,如果该记录不存在则返回,如果存在则删除该记录。删除数据库记录页面的源文件如代码所示。
17.7 本章习题
(1)选择题
说明:本章的选择题中有单选题也有多选题,用于读者检查自己对本章中关键概念的掌握程度。
1.如果要编写一个Bean,并将该Bean存放在WEB-INF/classes/jsp/example/mybean目录下,则包(package)名称是?
A.package mybean; B.package classes.jsp.example.mybean;
C.package jsp.example; D.package jsp.example.mybean;
2.编写一个Bean必须满足哪几点要求?
A.必须放在一个包(Package)中 B.必须生成public class类
C.必须有一个空的构造函数 D.所有属性必须封装
E.应该通过一组存取方法来访问
3.Java Bean中的属性命名的规范是?
A.全部字母小写 B.每个单词首字母大写
C.第一个单词全部小写,之后每个单词首字母大写 D.全部字母大写
4.在JSP中引用Bean应该如何操作?
A.page指令 B.include指令 C.include动作 D.useBean动作
5.private int[] myInt;语句定义的是?
A.单值属性 B.索引属性 C.关联属性 D.约束属性
6.在代码17-10所生成的Bean中,close()方法执行了哪些操作?
A.关闭数据集 B.关闭Statement对象
C.关闭数据链接 D.关闭数据库驱动
7.在useBean动作中,应该设置下面那些参数?
A.Id B.Scope C.Class D.name
8.Java Bean有几种属性?
A.4种 B.3种 C.2种 D.1种
9.Java Bean的方法可以分为几种?
A.4种 B.3 种 C.2种 D.1种
10.在17.6.2小节的Bean实例中,如果数据源改变,需要设置哪几种属性的值?
A.rs属性 B.url属性
C.user属性 D.password属性
(2)程序阅读题
指出下面Java Bean代码中的错误(共6处错误):
package jsp.examples.mybean;
import java.beans.*;
public class Hello { //类名,应该与文件名相同
//定义属性
String myStr;
public Boolean myBool;
public hello() {
myStr = "Hello Java Bean!";
myBool = true;
}
//get方法
private String getMyStr()
{ return this.myStr;}
//set方法
public void setMyStr(String str)
{this.myStr = str;}
public Boolean setMyBool(Boolean bool)
{ this.myBool = bool; }
//is方法
public void isMyBool()
{ return this.myBool; }
}
(3)实际操作题
编写一个用户登注册页面,通过调用数据库链接Bean将用户输入的注册信息写入数据库,用户注册后转到欢迎页面,并显示用户信息。