J2EE在线的银行应用程序.doc

上传人:asd****56 文档编号:70345702 上传时间:2023-01-19 格式:DOC 页数:27 大小:901KB
返回 下载 相关 举报
J2EE在线的银行应用程序.doc_第1页
第1页 / 共27页
J2EE在线的银行应用程序.doc_第2页
第2页 / 共27页
点击查看更多>>
资源描述

《J2EE在线的银行应用程序.doc》由会员分享,可在线阅读,更多相关《J2EE在线的银行应用程序.doc(27页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、J2EE在线的银行应用程序我们讨论DUKE的银行应用程序,一个在线的银行应用程序.他有两个客户端,一个让管理员管理顾客和账号的j2ee应用程序客户端,一个让顾客访问账号历史和执行的交易信息的web客户端。顾客通过实体bean访问存储在数据库中的顾客,账号,和交易信息。DUKE银行应用程序向我们展示了我们在这本书中介绍的所有的组件-EJB,j2ee应用程序客户端和web组件是如何在一起协同工作以组成一个简单但又功能丰富的应用程序的。下面的图片是一个在高层次上的组件交互图。在这一章我们将详细讨论他们的类型,包括他们是如何编译,部署,和运行的。图17-1 duke 银行应用程序EJB下图展示了客户端

2、,EJB和数据库表之间的访问路径。正如下图所示,客户端应用程序仅仅只访问会话BEAN,在EJB之间的关系中,会话BEAN是实体BEAN的客户端。在应用程序的末端,实体BEAN通过访问数据库中的表存储实体的状态。这些EJB的原代码位于j2eetutorial/bank/src/com/sun/ebank/ejb子目录。图:17-2 duke 银行应用程序中的EJB会话BEANDUKE的应用程序有三个会话BEAN,AccountControllerEJB,CustomerControllerEJB和TxControllerEJB(Tx代表一个业务交易,比如银行转账)这些会话BEAN向客户端提供了一

3、个应用程序业务逻辑的视图。它们隐藏了服务器端执行业务逻辑,访问数据库,管理关系和检查错误的细节。AccountControllerEJBAccountControllerEJB的业务方法根据执行的任务可以分为几类:生成和删除实体BEAN,管理顾客和账号之间的关系,获得账号的信息。下面的两个方法生成和删除实体BEAN。l createAccount l removeAccount AccountControllerEJB会话BEAN的这两个方法调用AccountEJB实体BEAN的create和remove方法。如果参数错误,createAccount和removeAccount方法将抛出应用程

4、序级的异常。如果参数的类型不是Checking,Savings,Credit和Money Market, createAccount方法将抛出IllegalAccountTypeException异常。createAccount方法也通过调用CustomerEJB实体BEAN的方法findByPrimaryKey来确定特定的顾客是否存在,如果顾客不存在,createAccount方法抛出CustomerNotFoundException异常。下面的方法管理账号和顾客之间的关系。addCustomerToAccountremoveCustomerFromAccountAccountEJB和Cus

5、tomerEJB实体BEAN之间有着多对多的关系。一个账号可以被多个顾客使用,一个顾客也可以有多个账号。因为实体BEAN使用BMP(Bean 管理持久性关系),所以有多种方法处理这种关系。在Duke的银行应用程序中,AccountControllerEJB会话BEAN的使用addCustomerToAccount和removeCustomerFromAccount方法管理账号和客户之间的关系。例如addCustomerToAccount方法开始先确定一个顾客是否存在。为了实现这种多对多的关系,addCustomerToAccount方法向数据库表customer_account_xref插入一

6、行,在这个交叉引用的表中,每一行都包括相关实体的customerId和accountId字段。为了删除这种关系,removeCustomerFromAccount方法从customer_account_xref表中删除一行。下面的方法得到有关账号的信息。l getAccountsOfCustomerl getDetailsAccountControllerEJB会话BEAN有两个get方法,getAccountsOfCustomer方法通过调用AccountEJB实体BEAN的findByCustomer方法返回一个给定顾客的所有账号,为了取代对AccountEJB的每一个变量(即与数据库表相

7、对应的字段)都执行get方法,AccountControllerEJB会话BEAN通过一个getDetails方法返回一个封装了AccountEJB实体BEAN状态的对象(AccountDetails对象)。CustomerControllerEJB因为AccountControllerEJB会话BEAN管理顾客和账户之间的关系,所以CustomerControllerEJB会话BEAN相对简单一些。客户端通过调用CustomerControllerEJB会话BEAN的方法createCustomer创建一个顾客,通过调用removeCustomer删除一个顾客,它不仅调用CustomerEJ

8、B实体BEAN的remove 方法,还删除customer_account_xref表中包含相应顾客的所有行。CustomerControllerEJB会话BEAN中有两个方法返回多个顾客,getCustomersOfAccount和getCustomersOfLastName,这两个方法调用CustomerEJB实体BEAN的相应的finder方法findByAccountId和findByLastName。TxControllerEJBTxControllerEJB会话BEAN处理银行交易。除了他的get方法getTxsOfAccount和getDetails,他还有几个方法用于改变一个账

9、号中的余额。l withdrawl depositl makeChargel makePaymentl transferFunds这些方法通过访问AccountEJB实体BEAN来确定账号的类型和设置账号中的余额。withdraw和deposit用于非信用卡的账号。makeCharge和makePayment用于信用卡账号。如果账号的类型不符合,这些方法抛出IllegalAccountTypeException异常。如果在取款后,账号中的余额为负数,withdraw则抛出InsufficientFundsException异常。在用信用卡支付中,如果超过了信用卡中的上限,makeCharge方

10、法抛出InsufficientCreditException异常。transferFunds方法不仅检查账号的类型还检查账号中的余额。如果需要,它抛出和withdraw,makeCharge方法相同的异常。transferFunds必须检查一个账号上的余额,并把它加到另一个账号上,这两步必须完成,因此transferFunds需要事务支持,如果其中的一步失败了,事务回滚,余额保持不变。实体BEAN在我们简单的小银行中,每一个业务实体在duke银行应用程序中都有一个对应的实体BEANl AccountEJBl CustomerEJBl TxEJB这些实体BEAN的目的是为了提供account,c

11、ustomer,tx这几个数据库表的对象视图,对数据库表中的每一行,都有一个实体BEAN的实例变量与之对应。因为这些实体BEAN使用BMP,所以他们包含访问这些数据库表的SQL语句。例如CustomerEJB实体BEAN的create方法调用SQL语句的INSERT命令。不像会话BEAN,这些实体BEAN的方法不验证参数,除了ejbCreate方法的主键参数。在设计阶段,我们决定在会话BEAN中验证参数,并抛出应用程序级的异常,例如CustomerNotInAccountException和IllegalAccountTypeException异常。因此,假如其他的应用程序使用这些实体BEAN

12、,它的会话BEAN仍然必须验证方法的参数。帮助类在EJB的jar文件中包含了几个被EJB使用的帮助类,这些帮助类的源代码位于j2eetutorial/bank/src/com/sun/ebank/util目录下。下面的表格简单的表述了这些帮助类。类名描述AccountDetails封装了AccountEJB的实例状态,被AccountEJB和AccountControllerEJB的getDetails方法返回。CodedNames定义了在调用lookup方法中使用的字符串的逻辑名称,例如java:comp/env/ejb/account,EJBGetter类引用这些字符串。CustomerD

13、etails封装了CustomerEJB的实例状态,被CustomerEJB和CustomerControllerEJB的getDetails方法返回DBHelper提供一些产生下一个主键的方法。例如getNextAccountId方法Debug提供一些简单的方法打印EJB的编译信息。如果j2ee server使用-verbose选项运行,这些信息出现在server的控制台上DomainUtil包含一些验证方法,例如getAccountTypes,checkAccountType,isCreditAccount。EJBGetter包含一些方法(通过调用lookup方法)定位并返回HOME接口。

14、例如getAccountControllerHomeTxDetails封装了TxEJB的实例状态,被TxEJB和TxControllerEJB的getDetails方法返回 表 17-1 duke 应用程序EJB的帮助类数据库表在duke的银行应用程序中,数据库的表可根据他们的目的分类,一类代表业务实体,一类管理产生下一个主键。代表业务实体的表下图展示了数据库表之间的关系。customer和account 表之间有一个多对多的关系。一个顾客可能有多个账号,一个账号也可能被多个顾客所拥有。这个多对多的关系通过交叉表customer_account_xref来实现。account和tx表有一个一对

15、多的关系。在一个账号上可以进行多次业务交易,但是一次业务交易只能引用一个账号。图: 17-3 duke 应用程序中的数据库表在图中我们使用了几个简写。PK代表主键(primary key)它的值唯一确定了数据库表中的一行。FK是外键的简写,这个字段是被引用的数据库表中的主键。Tx代表一个业务过程。例如取款和存款。管理下一个主键的表这些表有下面几个:l next_account_idl next_customer_idl next_account_idl next_tx_id这些表的每一个中都有一个单独的列叫做id,他的值被传给实体BEAN的create方法。例如,在创建一个AccountEJB

16、实体BEAN之前,AccountControllerEJB会话BEAN必须通过调用DBHelper类的getNextAccountId方法获得一个唯一的值。getNextAccountId从next_account_id表中读出id的值,并在数据库表中增加id的值,返回id。保护EJB在j2ee平台,你可以建立访问EJB方法的角色,相应的角色访问EJB相应的方法。在duke的银行应用程序中,根据他们的操作类型定义了两种角色,银行顾客和银行管理员。属于银行管理员角色的用户,可以执行管理功能:创建和删除一个账户,给一个账户增加或者删除顾客,设置信用卡的上限,设置初始账号的余额。属于银行顾客角色的用

17、户,可以存款取款,转账等功能。注意:两个角色可执行的功能上不会有重叠。通过在CustomerControllerEJb,AccountControllerEJB和TxControllerEJB会话BEAN的特定的方法上设置访问允许权,限制角色对这些方法的访问。例如,可以允许只有属于银行管理员角色的用户可以访问AccountControllerEJB的createAccount方法,可以拒绝属于银行顾客角色或其他角色的用户创建账号。为了查看是否设置了方法的允许权,在deploytool中的树状视图中找到CustomerControllerEJB,AccountControllerEJB和TxCo

18、ntrollerEJb。对其中的每一个选择安全标签(Security tab)检查方法的允许权。应用程序客户端有时候企业应用程序有一个单独的应用程序客户端来处理一些例如系统和应用程序管理的任务。例如在duke的银行应用程序中通过一个j2ee应用程序客户端来手工管理顾客和账号。这样做在站点因为某种原因不能使用或者客户喜欢通过电话来交流事情,例如,改变账号的某些信息时,是十分有用处的。一个j2ee应用程序客户端是一个通过命令行或者桌面启动的单独的应用程序。它访问运行在j2ee服务器上的EJB。J2ee客户端应用程序通过一个swing用户界面来管理顾客和账号。如下图所示:银行管理员可以通过选择菜单执

19、行下面的功能:客户管理l 查看顾客信息l 增加新顾客l 更新顾客信息l 查找顾客的id(标志) 图 : 17-4 应用程序客户端界面账号管理l 增加一个新账号。l 给一个存在的账号增加新顾客l 查看账号的信息。l 删除账号错误和一些信息出现在左边的application message watch(上图)面板的下面。数据显示在右边的面板上。类和他们之间的关系j2ee客户端应用程序被分为三个类BankAdmin,EventHandle,DataModel,这三个类之间的关系如下图(下一页)所示:BankAdmin对象建立初始化的用户界面,创建EventHandle对象,并为EventHandle

20、和DataModel对象提供调用的方法更新用户界面。EventHandle对象监听用户按下的按钮,并根据按钮作相应的处理。创建DataModel对象,并调用DataModel的方法从底层的数据库中读写数据,并在处理结束时调用BankAdmin的方法更新用户界面。DataModel对象从用户界面中检索数据,执行数据检查,并向数据库中写有效数据,或者从数据库中读数据。当数据库的读写成功时,根据对数据库的读写,调用BankAdmin类的方法更新用户界面。BankAdmin类创建用户界面的BankAdmin类,带有main方法,并提供一些受保护的方法供BankAdmin应用程序的其他类调用。图: 17

21、-5类之间关系图main 方法main方法创建BankAdmin和EventHandle类的实例,传递给main方法的参数用于确定相应的地区(即次应用程序在中国使用汉语运行,还是在英国使用英语运行),并被传递到BankAdmin的构造方法中。public static void main(String args) String language, country; if(args.length = 1) language = new String(args0); currentLocale = new Locale(language, ); else if(args.length = 2) l

22、anguage = new String(args0); country = new String(args1); currentLocale = new Locale(language, country); else currentLocale = Locale.getDefault(); frame = new BankAdmin(currentLocale); frame.setTitle(messages.getString(CustAndAccountAdmin); WindowListener l = new WindowAdapter() public void windowCl

23、osing(WindowEvent e) System.exit(0); ; frame.addWindowListener(l); frame.pack(); frame.setVisible(true); ehandle = new EventHandle(frame, messages); System.exit(0); 构造方法构造方法用于建立初始的用户界面,包含一个菜单条和两个面板。菜单条包括customer和account菜单,左边的面板包含一个消息区,右边的面板是显示或者更新数据区。类的方法BankAdmin提供了一些更新用户界面的方法。这些方法的描述如下:l clearMess

24、ages:清除出现在左边面板上的应用程序的消息。l resetPanelTwo:当用户在点击ok表示显示或者更新数据结束时调用,重新设置右边的面板。l createPanelTwoActLabels:当显示或者更新账号信息时为账号的字段创建标签。l createActFields:当显示或者更新账号信息时创建账号字段。l createPanelTwoCustLabels:当显示或者更新顾客信息时为顾客的字段创建标签。l createCustFields:当显示或者更新顾客信息时创建顾客的字段。l addCustToActFields:当在一个账号上添加顾客时创建标签和字段l makeRadio

25、Buttons:当创建一个新的账号时创建单选按钮,选择创建账号的类型l getDescription:创建单选按钮的标签用于描述账号的类型信息EventHandle类EventHandle执行ActionListener接口,这是一个用于处理行为事件的方法接口。像其他的用java 语言写的接口一样,ActionListener接口定义了一个方法集,但并没有实现它们。你必须根据应用程序的具体行为实现他们。构造方法构造方法检索ResourceBundle 和BankAdmin类的实例,并把他们赋值给自己的私有变量,这样子EventHandle就可以访问用户界面上的本地化后的文本并根据需要更新用户界

26、面。最后EventHandle的构造方法调用hookupEvents方法创建一个内在类监听和处理行为事件。public EventHandle(BankAdmin frame, ResourceBundle messages) this.frame = frame; this.messages = messages; this.dataModel = new DataModel(frame, messages); /Hook up action events hookupEvents(); actionPerformed方法ActionListener接口只有一个方法actionPerform

27、ed方法。这个方法处理当用户创建一个新账号时,用户界面产生的行为事件。确切地讲:当银行管理员选择用户账号类型的单选按钮时,它设置用户账号类型的描述,当管理员按初始余额上的返回键时,它设置新账号的初始余额。hookupEvents方法hookupEvents方法使用内在类处理菜单和按钮的按下事件。一个内在类是一个类嵌在或者定义在另一个类中。使用内在类使代码更加模块化,更加容易阅读和维护。EventHandle的内在类管理下列应用程序客户端的操作。l 查看顾客信息l 创建新顾客l 更新顾客信息l 通过顾客的lastName查询顾客的Idl 查看账号信息l 创建新账号l 给一个账号增加一个客户l 删

28、除账号l 当cancle按钮被按下时清除数据。l 当ok按钮被按下时处理数据。DataModel类DataModel类提供一些方法从数据库中读写数据,从用户界面检索数据,并在数据写入数据库之前检查数据的正确性。构造方法构造方法检索BankAdmin类的实例变量并把它赋值给自己的私有变量,所以当BankAdmin的checkActData, checkCustData,和 writeData方法检查到错误时,就可以在用户界面的面板上显示错误信息。他也收到一个ResourceBundle类的实例并把它赋值给自己的私有变量,以使它能够收到应用程序客户的本地化后的文本。因为DataModel类和数据库

29、进行交互,所以构造方法中也有一些代码用于建立和CustomerControllerEJB和AccountControllerEJB会话BEAN的远程接口的连接,并通过它们的远程接口创建它们的实例。/Constructorpublic DataModel(BankAdmin frame, ResourceBundle messages) this.frame = frame; this.messages = messages;/Look up and create CustomerController bean try CustomerControllerHome customerControl

30、lerHome = EJBGetter. getCustomerControllerHome(); customer = customerControllerHome.create(); catch (Exception NamingException) NamingException.printStackTrace(); /Look up and create AccountController bean try AccountControllerHome accountControllerHome = EJBGetter.getAccountControllerHome(); accoun

31、t = accountControllerHome.create(); catch (Exception NamingException) NamingException.printStackTrace(); 方法getData方法从用户界面的文本字段中检索数据,并使用String.trim方法除掉数据中的多余的控制字符,例如空格和回车字符。他有一个JTextFiled类型的参数,所以任何JTextField类的实例都可以被传送并处理。private String getData(JTextField component) String text, trimmed; if(component.

32、getText().length() 0) text = component.getText(); trimmed = text.trim(); return trimmed; else text = null; return text; checkCustData方法存储从getData方法中得到的顾客的数据,但是它首先检查所有要求的字段必须有数据,中间的大写不能超过一个字符,状态不能超过两个字符。当一切都检查完毕,它调用writeData 方法。如果有错误,错误信息被打印在BankAdmin对象的用户界面上。checkActData使用类似的方法检查和存储账号的数据。createCustI

33、nf和createActInf方法被EventHandle类调用,在查看,更新,创建事件中刷新面板2的显示信息。创建顾客信息l 在查看和更新事件中,createCustInf方法从数据库中读出特定顾客的信息,并把他们传递给BankAdmin类的createCustFields方法。一个布尔型的变量被用来确定createCustFields方法是创建查看事件中的只读字段还是更新事件中的可写字段。l 在创建事件中,createCustInf方法通过空数据和一个布尔型的变量调用BankAdmin类的createCustFields创建一些空的可编辑的字段,供用户输入顾客的数据。创建账号信息l 在查看

34、和更新事件中,createActInf方法从数据库中读出特定账号的信息,并把他们传递给BankAdmin类的createActFields方法。一个布尔型的变量被用来确定createActFields方法是创建查看事件中的只读字段还是更新事件中的可写字段。l 在创建事件中,createActInf方法通过空数据和一个布尔型的变量调用BankAdmin类的createActFields创建一些空的可编辑的字段,供用户输入账号的数据。l 在一个账号上增加或者删除一个顾客,不需要创建任何用户界面组件,直接在数据库上操作。Web客户端在duke的银行应用程序中,顾客通过web 客户端访问账号信息并在账

35、号上进行操作。下面的表格显示了web 客户端的功能和使用这些功能须访问的URL,以及执行这些功能的组件。功能URL的别名Jsp页面JavaBea组件主页/mainmain.jsp登陆和离开页面/logon/logonError/logofflogon.jsplogonError.jsplogoff.jsp列出账号/accountListaccountList.jsp列出账号的历史/accountHistaccountHist.jspAccountHistoryBean在账号之间转账/transferFunds/transferAcktransferFunds.jsptransferAck.js

36、pTransferBean取款存款/atm/atmAckatm.jspatmAck.jspATMBean错误处理/errorerror.jsp 表: 17-2 web客户端下面是显示账号历史的页面视图 图 17-6 账号历史设计策略在duke的银行应用程序中,Jsp页面的主要工作是显示。一种开发可维护的Jsp页面的策略是减少嵌入Jsp页面的脚本,为了达到这个目的,许多动态的处理任务都由EJB,自定义标记(tag)和JavaBean组件完成。在duke的银行应用程序中,Jsp页面使用EJB处理和数据库的交互。而且在和EJB交互的时候Jsp主要依赖JavaBean组件。在duke的书店应用程序中(

37、参看第十章和十三章),JavaBean组件BookDB扮演了通向数据库的前端或者说一个通向EJB提供的接口的通道。在duke的银行应用程序中,TransferBean扮演着同样的角色。然而其他的JavaBean组件有着丰富的功能。ATMBean调用EJB的方法并根据顾客确定的输入设置字符串。AccountHistoryBean保存着从EJB中得到的顾客想看到的数据的信息。Web客户端通过使用一个由自定义标记实现的模板机制维护着一个通用的几乎覆盖所有的Jsp页面的视图。模板机制由以下三个组件组成:l template.jsp:定义了每一个屏幕的结构。他使用insert 标记插入子组件组成一个屏幕

38、。l screenDefinitions.jsp:定义了组成被每一个屏幕使用的子组件,每一个屏幕有相同的行为,但是有不同的标题和主体部分。l dispatcher :一个servlet,用于处理请求并将请求转发给template.jsp。最后,web客户端使用了下列三种逻辑标记iterate, equal, 和 notEqual来自Struts 标记库。Web客户端的生命循环初始化web客户端的组件BeanManager类担负着管理客户端使用的EJB的责任。它创建顾客,账号和控制EJB,并提供检索EJB的方法。当初始化以后,BeanManager类从帮助类EJBGetter中检索每个EJb的h

39、ome 接口,并通过调用home 接口的create方法创建他们的实例。因为这是一个应用程序级别的功能,所以当客户端初始化时,BeanManager类自身被ContextListener类创建并作为一个Context的属性保存。public class BeanManager private CustomerController custctl; private AccountController acctctl; private TxController txctl; public BeanManager() if (custctl = null) try CustomerControlle

40、rHome home = EJBGetter.getCustomerControllerHome(); custctl = home.create(); catch (RemoteException ex) System.out.println(.); catch (CreateException ex) System.out.println(); catch (NamingException ex) System.out.println(); public CustomerController getCustomerController() return custctl; .public f

41、inal class ContextListener implements ServletContextListener private ServletContext context = null; . public void contextInitialized(ServletContextEvent event) this.context = event.getServletContext(); context.setAttribute(beanManager, new BeanManager(); context.log(contextInitialized(); . 请求处理所有请求的

42、URLs列在表18-2中,这些请求被映射到dispatcher web组件上,dispatcher web组件由dispatcher servlet 实现:public class Dispatcher extends HttpServlet public void doPost(HttpServletRequest request, HttpServletResponse response) . String selectedScreen = request.getServletPath(); request.setAttribute(selectedScreen, selectedScre

43、en); BeanManager beanManager = getServletContext().getAttribute( beanManager); . if (selectedScreen.equals(/accountHist) . else if (selectedScreen.equals(/transferAck) String fromAccountId = request.getParameter(fromAccountId); String toAccountId = request.getParameter(toAccountId); if ( (fromAccoun

44、tId = null) | (toAccountId = null) request.setAttribute(selectedScreen, /error); request.setAttribute(errorMessage, messages.getString(AccountError); else TransferBean transferBean = new TransferBean(); request.setAttribute(transferBean, transferBean); transferBean.setMessages(messages); transferBean.setFromAccountId(fromAccountId); transferBean.setToAccountId(toAccountId); transferBean.setBeanManager(beanManager); try transferBean.setTransferAmount(new BigDecimal(request.

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 技术资料 > 其他杂项

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁