JavaBean 是一种JAVA语言写成的可重用组件。为写成JavaBean,类必须是具体的和公共的,并且具有无参数的构造器。
JavaBean 通过提供符合一致性设计模式的公共方法将内部域暴露成员属性,set和get方法获取。众所周知,属性名称符合这种模式,其他Java 类可以通过自省机制(反射机制)发现和操作这些JavaBean 的属性。
介绍
按着Sun公司的定义,JavaBean是一个可重复使用的软件组件。
实际上JavaBean是一种Java类,通过封装属性和方法成为具有某种功能或者处理某个业务的对象,简称bean。由于javabean是基于java语言的,因此javabean不依赖平台,具有以下特点:
1. 可以实现代码的重复利用
2. 易编写、易维护、易使用
3. 可以在任何安装了Java运行环境的平台上的使用,而不需要重新编译。
编写javabean就是编写一个java的类,所以你只要会写类就能编写一个bean,这个类创建的一个对象称做一个bean。为了能让使用这个bean的应用程序构建工具(比如JSP引擎)知道这个bean的属性和方法,只需在类的方法命名上遵守以下规则:
1. 如果类的成员变量的名字是xxx,那么为了更改或获取成员变量的值,即更改或获取属性,在类中可以使用两个方法:
getXxx()
,用来获取属性xxx。
setXxx()
,用来修改属性xxx.。
2. 对于boolean类型的成员变量,即布尔逻辑类型的属性,允许使用"is"代替上面的"get"。
3. 类中访问属性的方法都必须是public的,一般属性是private的。
4. 类中如果有构造方法,那么这个构造方法也是public的并且是无参数的。
功能特点
用户可以使用JavaBean将功能、处理、值、数据库访问和其他任何可以用java代码创造的对象进行打包,并且其他的开发者可以通过内部的JSP页面、Servlet、其他JavaBean、applet程序或者应用来使用这些对象。
用户可以认为JavaBean提供了一种随时随地的复制和粘贴的功能,而不用关心任何改变。
分类
- 有用户界面(UI,User Interface)的JavaBean
-可视化的bean必须继承的类是java.awt.Component,这样它们才能添加到可视化容器中去 - 没有用户界面,主要负责处理事务(如数据运算,操纵数据库)的JavaBean
-bean没有必须继承的特定的基类或接口
组成
属性
JavaBean提供了高层次的属性概念,属性在JavaBean中不只是传统的面向对象的概念里的属性,它同时还得到了属性读取和属性写入的API的支持。属性值可以通过调用适当的bean方法进行。比如,可能bean有一个名字属性,这个属性的值可能需要调用String getName()方法读取,而写入属性值可能要需要调用void setName(String str)的方法。
每个JavaBean属性通常都应该遵循简单的方法命名规则,这样应用程序构造器工具和最终用户才能找到JavaBean提供的属性,然后查询或修改属性值,对bean进行操作。
JavaBean还可以对属性值的改变作出及时的反应。比如一个显示当前时间的JavaBean,如果改变时钟的时区属性,则时钟会立即重画,显示当前指定时区的时间。
方法
JavaBean中的方法就是通常的Java方法,它可以从其他组件或在脚本环境中调用。默认情况下,所有bean的公有方法都可以被外部调用,但bean一般只会引出其公有方法的一个子集。
由于JavaBean本身是Java对象,调用这个对象的方法是与其交互作用的唯一途径。JavaBean严格遵守面向对象的类设计逻辑,不让外部世界访问其任何字段(没有public字段)。这样,方法调用是接触Bean的唯一途径。
但是和普通类不同的是,对有些Bean来说,采用调用实例方法的低级机制并不是操作和使用Bean的主要途径。公开Bean方法在Bean操作中降为辅助地位,因为两个高级Bean特性–属性和事件是与Bean交互作用的更好方式。
因此Bean可以提供要让客户使用的public方法,Bean设计人员希望看到绝大部分Bean的功能反映在属性和事件中,而不是在人工调用和各个方法中。
事件(event)
Bean与其他软件组件交流信息的主要方式是发送和接受事件。
我们可以将bean的事件支持功能看作是集成电路中的输入输出引脚:工程师将引脚连接在一起组成系统,让组件进行通讯。有些引脚用于输入,有些引脚用于输出,相当于事件模型中的发送事件和接收事件。
事件为JavaBean组件提供了一种发送通知给其他组件的方法。在AWT事件模型中,一个事件源可以注册事件监听器对象。当事件源检测到发生了某种事件时,它将调用事件监听器对象中的一个适当的事件处理方法来处理这个事件。
范围(scope)
JavaBean 的范围 Scope 是一个具有生命时间的变量。
JavaBean的范围在<jsp:useBean scope=”….>
标志中右边进行表示。将产生一个JavaBean的快捷参考。
说明:jsp服务器引擎将剥离<jsp。。。。
标记。并且在最终用户的浏览器上无法显示实际代码。
在Bean中限制HTML的产生:
理论上,JavaBean 将不会产生任何HTML,因为这是jsp层负责的工作;然而,为动态消息提供一些预先准备的格式是非常有用的。产生的HTML将被标注的 JavaBean方法返回。
注意:
- 不要试图在JavaBean返回的HTML中放置任何字体尺寸。
并不是所有的浏览器都相同。很多浏览器无法处理完整的字体尺寸。
- 不要试图在JavaBean返回的HTML中放置任何脚本或者DHTML。
向页面直接输出脚本或者DHTML相当于自我毁灭,因为某些浏览器版本在处理不正确的脚本时会崩溃(非常少但是有)。如果用户的JavaBean在运行时是动态的推出复杂的HTML语言,用户将陷入调试的噩梦。另外,复杂的HTML将限制JavaBean的寿命和灵活性。
- 不要提供任何的选择。
如果用户使用不同的系统浏览页面,可以提供一种可以替换的方法。
页面page
页面和请求范围的JavaBean有时类似表单的bean , 这是因为 他们大都用于处理表单。表单需要很长的时间来处理用户的输入
通常情况下用于页面接受HTTP/POST或者GET请求。另外页面和请求范围的bean可以用于减少大型站点服务器上的负载,如果使用对话bean,耽搁的处理就可能会消耗掉很多资源。
请求request
页面和请求范围的JavaBean有时类似表单的bean , 这是因为 他们大都用于处理表单。表单需要很长的时间来处理用户的输入
通常情况下用于页面接受HTTP/POST或者GET请求。另外页面和请求范围的bean可以用于减少大型站点服务器上的负载,如果使用对话bean,耽搁的处理就可能会消耗掉很多资源。
对话session
对话范围的JavaBean 主要应用于跨多个页面和时间段: 例如填充用户信息。 添加信息并且接受回馈,保存用户最近执行页面的轨迹。
对话范围JavaBean保留一些和用户对话 ID 相关的信息。这些信息来自临时的对话cookie,并在当用户关闭浏览器时,这个cookie将从客户端和服务器删除。
应用application
应用范围通常应用于服务器的部件,例如 JDBC连接池、应用监视、用户计数和其他参与用户行为的类。
任务
JavaBean的任务就是: “Write once, run anywhere, reuse everywhere”,即“一次性编写,任何地方执行,任何地方重用”。这个任何实际上就是要解决困扰软件工业的日益增加的复杂性,提供一个简单的、紧凑的和优秀的问题解决方案。
-
**一个开发良好的软件组件应该是一次性地编写,而不需要再重新编写代码以增强或完善功能。**因此,JavaBean应该提供一个实际的方法来增强现有代码的利用率,而不再需要在原有代码上重新进行编程。除了在节约开发资源方面的意义外,一次性地编写JavaBean组件也可以在版本控制方面起到非常好的作用。开发者可以不断地对组件进行改进,而不必从头开始编写代码。这样就可以在原有基础上不断提高组件功能,而不会犯相同的错误。
-
JavaBean组件在任意地方运行是指组件可以在任何环境和平台上使用,这可以满足各种交互式平台的需求。由于JavaBean是基于Java的,所以它可以很容易地得到交互式平台的支持。JavaBean组件在任意地方执行不仅是指组件可以在不同的操作平台上运行,还包括在分布式网络环境中运行。
-
**JavaBean组件在任意地方的重用说的是它能够在包括应用程序、其他组件、文档、Web站点和应用程序构造器工具的多种方案中再利用。**这也许是JavaBean组件的最为重要的任务了,因为它正是JavaBean组件区别于Java程序的特点之一。Java程序的任务就是JavaBean组件所具有的前两个任务,而这第3个任务却是JavaBean组件独有的。
设计目标
1.紧凑而方便的创建和使用
JavaBean紧凑性的需求是基于JavaBean组件常常用于分布式计算环境中,这使得JavaBean组件常常需要在有限的带宽连接环境下进行传输。显然,为了适应传送的效率和速度,JavaBean组件必须是越紧凑越好。另外,为了更好地创建和使用组件,就应该使其越简单越好。通常为了提高组件的简易性和紧凑性,设计过程需要投入相对较大的功夫。
现已有的组件软件技术通常是使用复杂的API,这常常搞得开发者在创建组件时晕头转向。因此,JavaBean组件必须不仅容易使用,而且必须便于开发。这对于组件开发者而言是至关重要的,因为这可以使得开发者不必花大量功夫在使用API进行程序设计上,从而更好地对组件进行润饰,提高组件的可观赏性。
JavaBean组件大部分是基于已有的传统Java编程的类结构上的,这对于那些已经可以熟练地使用Java语言的开发者非常有利。而且这可以使得JavaBean组件更加紧凑,因为Java语言在编程上吸收了以前的编程语言中的大量优点,已经使开发出来的程序变得相当有效率。
2.完全的可移植性
JavaBean API与操作基础的独立于平台的Java系统相结合,提供了独立于平台的组件解决方案。因此,组件开发者就可以不必再为带有Java applet平台特有的类库而担心了。最终的结果都将是计算机界共享可重复使用的组件,并在任何支持Java的系统中无需修改地执行。
3.继承Java的强大功能
现有的Java结构已经提供了多种易于应用于组件的功能。其中一个比较重要的是Java本身的内置类发现功能,它可以使得对象在运行时彼此动态地交互作用,这样对象就可以从开发系统或其开发历史中独立出来。
对于JavaBean而言,由于它是基于Java语言的,所以它就自然地继承了这个对于组件技术而言非常重要的功能,而不再需要任何额外开销来支持它。
JavaBean继承在现有Java功能中还有一个重要的方面,就是持久性,它保存对象并获得对象的内部状态。通过Java提供的序列化(serialization)机制,持久性可以由JavaBean自动进行处理。当然,在需要的时候,开发者也可以自己建立定制的持久性方案。
4.应用程序构造器支持
JavaBean的另一个设计目标是设计环境的问题和开发者如何使用JavaBean创建应用程序。JavaBean体系结构支持指定设计环境属性和编辑机制以便于JavaBean组件的可视化编辑。这样开发者可以使用可视化应用程序构造器无缝地组装和修改JavaBean组件。就像Windows平台上的可视化开发工具VBX或OCX控件处理组件一样。通过这种方法,组件开发者可以指定在开发环境中使用和操作组件的方法。
5.分布式计算支持
支持分布式计算虽然不是JavaBean体系结构中的核心元素,但也是JavaBean中的一个主要问题。
JavaBean使得开发者可以在任何时候使用分布式计算机制,但不使用分布式计算的核心支持来给自己增加额外负担。这正是出于JavaBean组件的紧凑性考虑的,无疑分布式计算需要大量的额外开销。
需求
JavaBean是java类,属于某些特定的译码指导方针,并且扩展了适应性和范围,允许用户访问内部的属性和方法。
通过这些,JavaBean类可以用于下列方法:
1. 在IDE中,JavaBean的功能允许应用开发者浏览其中的方法,即JavaBean是被编译的,并且无法利用原始的源文件。
2. 在 Remote Method Invocation(RMI) 的分布式风格中,这项功能听起来并不让人兴奋,但是在未来的包含企业版的JavaBean后,将改变这种情况。
3. 为了JavaBean的属性值和状态可以保存到磁盘上。
开发环境
普通JavaBean组件是要分布在各自环境中,所以它们应该能够适应各种环境。
虽然无法事先预知JavaBean要运行的确切环境,但以下两点是可以确定的:
-
bean必须能够在一个应用程序构造器工具中运行。
-
bean必须可以在产生的应用程序的运行环境中使用。
设计环境
bean必须可以在设计环境(design environment)中运行。在设计环境中,bean应该提供设计信息给应用程序构造器工具并允许终端用户制定bean的外观和行为。
在传统的软件构造活动中,必须通过编译、链接之后才能看到应用程序的最终运行结果;而利用JavaBean设计的软件中,则没有这种明确的界限。使用JavaBean,就可以非常直观地设计应用程序软件,在设计过程中赋予软件主机。而且,这个过程更加容易重复开发,设计思想更加容易变成原型。
运行环境
bean必须可以在运行环境(run-time environment)中使用。在这个环境中,对设计信息和定制的需求并不重要。一个组件的设计环境信息和设计环境中编写的代码通常可能是非常巨大的。
因此,我们可能需要在bean的设计环境方面和运行环境方面作一个明确的区分,这样,就可能需要在运行环境中不使用bean的任何设计环境代码来配置这个bean。所以,JavaBean就必须分别支持运行环境接口的类库和设计环境接口的类库。
编程
通用
首先,必须拥有不带参数的公用构造器
该参数应该通过调用各个特性的设置方法来设置特性的默认值
public Fireworks()
{
setAutoStart(true);
setBackground(Color.black);
setSpeed(10);
setRadius(40);
}
如果bean 是一个从 java.awt.Component 类继承而来的可视 bean,应该为 bean 定义一个默认的首选大小
public Dimension getPreferredSize()
{
return (new Dimension(radius*3, radius*3));
}
public Dimension getMinimumSize()
{
return getPreferredSize();
}
特性
对于需要的每个特性,应该有一个带有匹配公用 getter 和 setter 方法的专用实例变量
private int speed;
public int getSpeed()
{
return speed;
}
public void setSpeed(int s)
{
speed = s;
}
注:如果特性的更改影响到 bean 的大小和位置,需要确认获得验证的事物。建议编写自己的 validateAll 方法,如下所示:
private void validateAll()
{
if (isValid())
{
Component self = this;
self.invalidate();
Component myParent = self.getParent();
if (myParent != null)
{
myParent.invalidate();
self = myParent;
}
self.validate();
}
}
操作
对于要使用到的操作,需要设置公有方法
public void start()
{
if(thread==null)
{
thread=new Thread(this);
thread.start();
}
}
注:为操作写的方法应该在无须期待用户创建连接或设置很多特性的情况下独立操作
事件
对于需要的事件或事件设置,应该定义事件和监听器类
事件源:查看FireworksEvent.java 源文件以及 Fireworks.java 文件
import java.awt.*;
import java.util.*;
public classFireworksEvent extends EventObject
{
public static final int EXPLODED = 1;
int id = 0;
public FireworksEvent(Component source, int id)
{
super(source);
id = id;
}
public int getID()
{
return id;
}
}
注:为此事件设置中的每个事件定义一个公用静态结束事件标识符,例如在此例子中的 EXPLODED
监听器类:
import java.util.*;
public interface FireworksListener extends EventListener
{
public abstract void exploded(FireworksEvent e);
}
注:
为此事件设置中的每个事件定义一个公用抽象方法,例如在此例子中的 exploded
侦听器类必须扩展 EventListener ,以使 JAR 向导能够找到它
示例
Javabean就是Java类。从表示层的处理来考虑,Javabean就是一个个的service类。
现在就用一个实际的例子来说明javabean是怎样工作的,建立一个用户注册登陆小模块
1建立一个javabean封装用户的信息(姓名和密码)UserInfo.java
/*setter方法来设置用户的信息,getter方法来获取用户的信息*/
package user;//存放UserInfo.java的包,该包中放在web-inf目录下
public class UserInfo
{
private String password;
private String name;
//获取信息
public String getPassword()
{
return this.password;
}
public String getName()
{
return this.name;
}
//设置信息
public void setPassword(String p)
{
this.password=p;
}
public void setName(String n)
{
this.name=name;
}
}
2,建立一个javabean处理数据库操作以及一些简单的逻辑操作UserRegist.java
package user;//同理也放在这个包中
import java.sql.*;
public class UserRegist
{
private UserInfo userInfo;//在此javabean中把UserInfo.java这个javabean引进来
private Connection conn=null;
//连接数据库
public UserRegist()
{
try
{
Class.forName("com.mysql.jdbc.Driver");
conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/joke?user=root");
}
catch(Exception e)
{
e.printStackTrace();
}
}
public void setUserInfo(UserInfo userInfo)
{
this.userInfo=userInfo;
}
//进行注册
public void regist()throws Exception
{
String reg="insert into user_Info values(?,?)";
try
{
PreparedStatement pstmt=conn.prepareStatement(reg);
//create a preparestatement sentence ,then to set their name
pstmt.setString(1,userInfo.getPassword());
pstmt.setString(2,userInfo.getName());
//excute update
pstmt.executeUpdate();
}
catch(Exception e)
{
e.printStackTrace();
throw e;
}
}
}
3,做一个简单的表单html页面了,login.html,接受用户输入的信息
<form action="regist.jsp" name="form1">
<table>
<tr>
<td> username:</td>
<td><input name="name"></input></td>
</tr>
<tr>
<td>userpassword:</td>
<td><input type="password" name="password"></input></td>
</tr>
<tr>
<td><input type="submit" value="go"></td>
<td><input type="reset" value="reset"></td>
<table>
</form>
4,最后我们做的事就是用一个简单的jsp页面让两个javabean工作起来,regist.jsp
<%@page contentType="text/html;charset=GB2312"%>
//利用此标签来调用UserInfo.java
<jsp:useBean id="userInfo" class="user.UserInfo" scope="page">
//利用此标签来用UserInfo.java接受并保存表单中的信息
<jsp:setProperty name="userInfo" property="*"/>
</jsp:useBean>
//来调用UserRegist.java
<jsp:useBean id="regist" class="user.UserRegist" scope="page"/>
<%
regist.setUserInfo(userInfo);//调用UserRegist.java中的setUserInfo()方法获取保存在serInfo.java中的信息
regist.regist( );//调用UserRegist.java中的regist( )方法进行注册
out.println("registed ok!");
%>
<br><hr><br>
<a href="login.jsp">back</a>