| …… private PropertyChangeSupport changes=new PropertyChangeSupport(this); public void addPropertyChangeListener(PropertyChangeListener l) { changes.addPropertyChangeListener(l); public void removePropertyChangeListener(PropertyChangeListener l){ changes.removePropertyChangeListener(l); } …… } |
| public class MoleculeNameEditor extends Java.beans.PropertyEditorSupport{ public String[] getTags(){ String resule[]={"HyaluronicAcid","Benzene","buckmisterfullerine" "cyclohexane","ethane","water"}; return resule; } } |
| public class MoleculeBeanInfo extends SimpleBeanInfo { public PropertyDescriptor[] getPropertyDescriptors(){ try { PropertyDescriptor pd=new PropertyDescriptor("moleculeame", Molecule.class); /*通过pd引用了上一节的MoleculeNameEditor类,取得并返回mleculeName属性*/ pd.setPropertyEditorClass(MoleculeNameEditor.class); PropertyDescriptor result[]={pd}; return result; } catch(Exception ex){ System.err.println("MoleculeBeanInfo: unexpected exeption: "+ex); return null; } } } |
当一个JavaBean在构造工具内被用户化,并与其它Bean建立连接之后,它的所有状态都应当可被保存,下一次被load进构造工具内或在运行时,就应当是上一次修改完的信息。为了能做到这一点,要把Bean的某些字段的信息保存下来,在定义Bean时要使它实现Java.io.Serializable接口。例如:
public class Button implements Java.io.Serializable {……}
实现了序列化接口的Bean中字段的信息将被自动保存。若不想保存某些字段的信息则可在这些字段前冠以transient或static关键字,transient和static变量的信息是不可被保存的。通常,一个Bean所有公开出来的属性都应当是被保存的,也可有选择地保存内部状态。Bean开发者在修改软件时,可以添加字段,移走对其它类的引用,改变一个字段的private、protected或public状态,这些都不影响类的存储结构关系。然而,当从类中删除一个字段,改变一个变量在类体系中的位置,把某个字段改成transient/static,或原来是transient/static,现改为别的特性时,都将引起存储关系的变化。
JavaBean组件被设计出来后,一般是以扩展名为jar的Zip格式文件存储,在jar中包含与JavaBean有关的信息,并以MANIFEST文件指定其中的哪些类是JavaBean。以jar文件存储的JavaBean在网络中传送时极大地减少了数据的传输数量,并把JavaBean运行时所需要的一些资源捆绑在一起。
本小节主要论述了JavaBeans的一些内部特性及其常规设计方法,参考的是JavaBeans规范1.0A版本。随着世界各大ISV对JavaBeans越来越多的支持,规范在一些细节上还在不断演化,但基本框架不会再有大的变动。
用JSP和JavaBean如何实现"简单购物车"应用?
1. 简单购物车的实现方案
下面,本节将通过一个简单的购物车程序来说明一下JSP和JavaBean在网络体系结构中是怎样相互作用的,并且借这个例子解释编写一个实际可用的电子商务应用程序应该注意的一些问题。在电子商务应用中JSP和JavaBean的结合方式如下图所示:

JSP和JavaBean在电子商务应用中的结合方式
如果从Model/View/Controller(MVC)模式来理解电子商务应用体系结构,可以把应用程序划分成独立的数据管理(Model),表现形式(View)和控制组件(Controller),成为最先进的图形用户接口的基础,这些划分模块支持独立开发并且可以重复使用组件。其中JSP最适合充当实现网络应用程序的对外表现的部分;而JavaBeans封装了提供给Web网站的服务信息内容并且简化了数据在体系结构组件之间的传输;Servlet则正好充当控制者和协调用户请求和应用程序信息、更新程序数据等功能,其逻辑关系图如下所示:

MCV模式下的电子商务应用体系结构图
2.简单购物车的实现细节
⑴ Controller部分
本部分的实现代码和解释如下:
CustomerServlet.Java
package shoppingcart;
import Javax.servlet.*;
import Javax.servlet.http.*;
import Java.io.IOException;
public class CustomerServlet extends HttpServlet {
……
上面的程序段显示了CustomerServlet类中的doGet()和doPost()方法。 CustomerServlet类做了两件事情来控制应用程序的工作流程:
·通过 BasketBean类实现,保持购物车组件的状态,;
·它通过一系列的JSP页面向顾客发送请求。
一旦购物车与某一个特定的顾客session相联系,顾客的BasketBean对象的实例就会存储在 HttpSession对象中。一个以普通ID进入CustomerServlet工作流程的客户,他会产生很多动作,servlet引擎提供了HttpSession对象来组织并存储这一系列的相互作用(Session对象为存储和取回任何使用唯一的键/值对的Java对象提供了方便的方法)。在CustomerServlet类中 ,首先通过HttpSession session = request.getSession(true)从 servlet 引擎中取得Session对象,读者可以看到,程序传递了true值,意思是告诉Servlet引擎,如果一个session对象已经不存在了,就新建一个;然后查看Session中是否有购物车,如果找不到购物车,就知道这个购物Session刚刚开始,必须新建一辆购物车,并且把它保存在Session对象中,如果能够在Session中找到购物车,那就知道顾客正处在一个购物期间,那时就必须存储购物车当前的状态。在查看了购物车的状态之后,把顾客的请求发送到相应的JSP页中去,请求本身包含一个状态参数(BasketBean.PAGE)告诉CustomerServlet把请求发送到哪里,控制器取回这个参数,然后使用一个RequestDispatcher对象把请求提交给下一个JSP页。
⑵ Model部分
本部分的实现代码和解释如下(BasketBean类):
package shoppingcart;
import Javax.servlet.http.HttpServletRequest;
import Java.util.Hashtable;
import Java.util.Enumeration;
public class BasketBean {
……
BasketBean类实现购物车应用程序中一个简单的数据管理模型,它提供了一个方法,用于取得一个顾客正在购买的货物的信息,还提供了一个方法用来更新购物车的内容,程序使用一张哈希表来维护顾客请求的商品列表。InventoryBean对象管理商品的目录,我们是使用一个数组来实现商品的目录的。每个Product类的实例存储四个属性:商品名字,商品标识号,单价和购买的数量,只要顾客购买了东西,Product类的实例就会改变。
⑶ View部分
购物车方案中设定了3个JSP页面:Inventory.jsp,Purchase.jsp和Receipt.jsp(代码见下)。应用程序发送Inventory.jsp页面给新来的顾客,顾客通过不断的更新Inventory.jsp,来挑选商品;顾客选择好想要购买的商品以后,应用程序就会把顾客的购买请求发送到Purchase.jsp页,进行处理;最后,顾客证实确实购买这些商品,应用程序把顾客请求发送到Receipt.jsp。

JSP页面交互流程图