Java Version 3.5编程指南完整版_第1页
Java Version 3.5编程指南完整版_第2页
已阅读5页,还剩92页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第5章创建servletPAGE97第2章组织代码VisualAgeforJava使用项目和包来组织你的工作。包是Java用来组织类和接口的标准方式;项目则是VisualAgeforJava特有的一种高层次的组织某个项目开发成果的方式。本章中,你将要学习如何在VisualAgeforJava中使用项目和包。VisualAgeforJava使用项目和包组织代码。项目包括了某个开发者正在工作的所有对象;项目包含了包,包则包含了Java类和接口。项目还可以包括资源。资源不是Java文件,不被看作是应用程序的一部分,我们将在后面的“WorkbenchResources页”中详细讨论资源。本章中,你将学习使用VisualAgeforJava提供的管理和维护开发工作的工具。你还要学会导入外部代码和资源,导出你的工作成果。2.1VisualAgeforJava中的项目当你阅读本书时,你已经创建了一个项目来组织你所有的工作。项目提供了在最高层次上组织你的Java代码的方式。只要你创建了一个新的包,它必定是存在于于某个现存的或是新的项目中。Java语言本身并没有任何对象与项目相对应。在VisualAgeforJava3.5中,项目包含了Java包和别的资源。资源是与Java程序相关的一些文件,通常是Web应用程序的一部分,如图片、多媒体、JSPs和静态HTML文件等。第一次启动VisualAgeforJava,进入Workbench,你会看到你的工作区中已经有了几个项目,每一个又包括了几个包。表2-1列出了这些工程和他们的内容。表2-1默认的VisualAgeforJava工程和它们的内容项目内容IBMJavaImplementationcom.ibm.uvm.*package,它实现并支持VisualAgeforJava虚拟机及其环境JavaClassLibrariesjava.*和javax.*包,它们包含了JavaClassLibrariesSunClassLibrariesPMWin32Sun.*包,它是对标准java.*包的扩展表2-1中项目的代码是不能被删除或修改的,它们是VisualAgeforJava正常运行必不可少的部分。2.1.1添加的特性要开发数据库应用程序,servlets等程序,你还得添加几个特性。要添加一个特性,从File菜单中选择QuickStart或按F2键,在QuickStart对话框中选择Features和AddFeatures,然后单击OK按钮。你可以从列表中选择要添加的特性。运行本书中的范例需要添加WebSphereTestEnvironment,Servlet,IBMJSP例子和DataAccessBeans特性。2.2VisualAgeforJava中的包包是Java用来组织相关类和接口的容器。包的名字是完全合法类名的一部分。如何将不同的类用包组织起来是一个很重要的问题。你可以在使用完全合法类名和使用导入语句中选择。VisualAgeforJava在工作区的类路径中寻找外部包,类路径可以在Option对话框中加以更改。2.3Workbench要理解VisualAgeforJava如何组织项目和包,你得多了解一些关于Workbench的知识。Workbench为当前的开发环境(即工作区)提供了不同的视图。Workbench窗口的布局依赖于窗格上的标签选择。要在项目、包、资源、类、接口和AllProblem页面间转换,只需要单击相应的标签。这些页面的菜单栏也随着标签的转换而转换。在任何Workbench页面中你都可以以两种不同的方式访问选定对象(项目、包、资源、类、接口和方法)的菜单:右键单击选定对象,访问弹出式菜单使用菜单栏Source窗格的弹出式菜单和它在菜单栏上的Edit菜单功能是一样的,Browse窗格的弹出式菜单和它在菜单栏上的Selected菜单功能相同。Workbench也提供了一个工具栏以快速访问某项操作,图2-1显示了该工具栏,表2-2对工具栏中图标的功能进行了描述。图2-1Workbench工具栏createaVersion 生成一个版本ToggleEditionNameCreateField 创建字段〖field〗CreateMethod 创建方法CreateInterface 创建InterfaceCreateApplicatipon 创建应用程序CreateServlet 创建ServletCreateInterface 创建InterfaceCreateApplet 创建AppletCreateclass 创建类AddPackage 添加包AddProject 添加项目Search(hassubmenuwithrightclick) 搜索(单击右键有子菜单)OpenDebugger 启动调试器Run(hassubmenuwithrightclick) 运行(单击右键有子菜单)表3.工具栏图标的功能图标功能运行运行选定项目或包中的类或是选定的类。单击右键显示历史记录启动调试器启动调试器搜索搜索对某个字段的声明或引用添加项目向当前工作区中添加一个项目添加包向当前选定的项目中中添加一个包创建类激活CreateanewClassSmartGuide创建Applet激活CreateanewAppletSmartGuide创建Interface激活CreateanewInterfaceSmartGuide创建Servlet激活CreateanewServletSmartGuide创建应用程序激活CreateanewApplicationSmartGuide创建方法激活CreateanewMethodSmartGuide创建字段在现存类中激活CreateanewFieldSmartGuideToggleEditionName显示或隐藏程序元素的版本名版本生成一个版本2.3.1Workbench的Project页Workbench的Project页(见图2-2)包含两个窗格:浏览(Browse)窗格和源(Source)或注释(Comment)窗格。图2-2WorkbenchProject页tabselection 标签选择browsepane 浏览窗格sourcepane 源窗格statusbar 状态栏bookmarks 书签filters 过滤器默认设置下,窗格是水平放置的,如果要改变放置方向,选择Windows→FlipOrientation。如果你在浏览窗格中选中了一个包含有代码的程序元素,如类、接口或方法的话,另一个窗格会是Source窗格,其中包含了源代码。如果你选中的是包或项目的话,另一个窗格会是Comment窗格,其中包含了你添加到包或项目中的注释。当你选择Projects,Packages,Classes,Interface视图时,你的工作区中载入的项目、包、类和接口会以目录树的方式显示在Browse窗格中。第一次打开Workbench时,默认出现的是Project视图。要展开或折叠列表上的任何对象,请单击该对象左边的“+”或“-”。要在Source窗格中显示某个对象的代码,选定该对象就可以了。你可以在任何浏览窗口中选择Selected→Add→Project创建新项目。VisualAgeforJava提供的其它一些功能VisualAgeforJava提供了许多有用的功能来查看项目的不同部分。下面列出常用的四个功能:在Projects页中设置书签,只要单击Browse窗格右上方的“+”就可以了。要回到特定的代码,你可以单击设置标签时出现的数字。使用过滤器可以只显示公共变量和静态变量中的一种,或显示所有变量。复制VisualAgeforJava中任何的窗口。选择Window→Clone会打开一个环境与旧窗口相同的新窗口。当需要两个类似的窗口时,复制窗口是很有用的。但它也会带来问题,当你在两个窗口中修改同一个类的时候,在一个窗口中所做的改动有可能被另一个窗口的改动所覆盖。双击任何窗格的标题栏会使该窗格在窗口中最大化。再次双击则会将其恢复为普通的视图。你也可以通过选择Window→MaximizePane/RestorePane实现相同的功能。2.3.2Workbench的Packages视图Workbench的Packages页(见图2-3)包含了三个Browse窗格-AllPackages、Types和Methods和一个Source窗格。图2-3WorkbenchPackagepagepackageaccount;publicclassBankAccount{privatestringaccountId;privatedoublebalance;}你可以导入一个包中所有的类型或根据需要选择导入的对象。请注意,导入一个包时并不会导入它的子包,你必须将它们分别导入。你可以使用星号(java.awt.*)导入包中的所有类型,但是你必须分别导入任何子包,如java.awt.event。如果在创建类的时候已经知道它会用到的包,你应该使用Attributes对话框(要进入该对话框,你可以在CreateClass或InterfaceSmartGuide中单击Next按钮)。Attributes对话框指定要导入的包,单击AddClass和AddPackage按钮来浏览并选择要导入到你的类中的包和类(见图2-4)。图2-4CreateClassSmartGuide:Importstatement对话框2.3.3Workbench的Resources页WorkbenchResources页(见图2-5)显示了项目中所有的资源。你还可以添加或清除与你的项目相关的资源或目录结构。图中显示了几个与该项目有关的JSP和SQLJ文件。要添加或移去资源文件,单击右键在弹出的菜单中选择Add或delete。要编辑某个文件,双击该文件或使用open菜单项。VisualAgeforJava使用关联应用程序打开资源文件。资源文件通常保存在VisualAgeforJava安装目录下的project_resources子目录中,而不是拷贝到知识库中。当你对包含该资源的项目赋予版本时,资源文件就会存放在知识库文件中。图2-5WorkbenchResources页2.3.4Workbench的Class页Workbench的Class页(见图2-6)包括三个窗格:ClassHierarchy窗格、Methods窗格和Sources窗格。图2-6WorkbenchClass页通过菜单栏上的Class→Layout或ClassHierarchy窗格右上方的layout图标,你可以改变类的布局。你也可以通过Window→FlipOrientation来选择Browse窗格的定向。单击Member窗格右上角的RootMinusOne图标可以显示类的继承成员。类视图显示了类型的类继承关系,你可以快速查询类的继承树。在类视图中选择Classes→GoToClass,然后输入类名直到类的全名出现在列表中,你就能快速找到需要的类。导向辅助功能GoToClass功能只是Workbench提供的许多导航辅助功能中的一个,下面是另外常用的几个:每个窗口都有不同的GoTo选项。每个窗口都有Opento菜单项,它会在选定浏览器中打开选定的内容。每个窗口都有Clone功能,你可以对同样的信息有两种视图。通过Workspace→Search,你可以搜索不同的内容。通过Selected→ReferencesTo,你可以搜索引用到了某个选定类型的所有代码2.3.5WorkbenchInterface页除了一个显示接口,一个显示类以外,Workbench的Interface页(见图2-7)与Class页(见图2-6)很相似。Interface页包含三个窗格:Interfaces,Methods和Source。图2-7WorkbenchInterface页2.3.6Workbench的AllProblems页你可以在AllProblems页中找到工作区中所有的错误代码。如果某个方法中有错误代码的话,该方法会用红色的“X”标记出来,该方法所属的类会用灰色的“X”标记(见图2-8)。如果在类声明和接口声明中有错误代码的话,该类或声明会用红色的“X”标记出来。图2-8Workbench的AllProblems页要是你知道某个问题的存在但暂时不想管它,你可以将它们滤掉。你可以有三种方法使用过滤器:选择Showallproblems显示所有问题。选择Excludedeprecatedwarnings隐藏不想理会的警告。选择Showonlyerrors隐藏所有的警告。使用工作集(workingsets)指定项目,你可以缩小搜索范围。要使用工作集,请选择FilterProblems→WorkingSet…,在出现的workingset对话框中选定要包括的项目。你目前的VisualAgeforJava环境中应该不会有错误,你可以生成一个错误来看看它的结果:(1)选中Workbench上的Project标签。(2)展开HiThere类,选择main(string[])方法。(3)在后大括号“}”前加入一行:x=2;保存该方法(Edit→Save或^S)。图2-9显示了你试图保存生成的错误代码时出现的警告对话框。你可以选择Cancel,回到代码中修改错误,或是保存错误的代码。如果VisualAgeforJava能提出更正建议的话,它会将其显示在下方的窗格中。你可以从各项建议中选择一个,单击Correct按钮更正代码。单击警告对话框中的Save按钮。图2-9Warning对话框:未定义变量选择Workbench上的AllProblem标签(未显示),选择main方法,删除x=2;行,保存方法,错误警告应该已经消失了。大多数情况下,你输入了错误代码时会出现图2-9所示Warning对话框。但在某些情况下,当VisualAgeforJava编译器不能分析出代码的错误时,你会看到Error对话框。这时,你必须回去修改代码,否则错误代码不能被保存。如果VisualAgeforJava能提出更正建议的话,它会在下方窗格中显示出来。留下错误的代码留下错误的代码?这似乎有点奇怪。但在VisualAgeforJava中,它不会有太大风险。比如说,你在引用一个变量前没有定义它,你可以保存引用该变量的代码,以后再进入AllProblems页,在类声明中添加这个变量。在最坏的情况下,你有可能不知道如何修改错误,那么你可以回到该代码的较早版本。2.4全源代码编辑SourceView窗口提供了全源代码编辑功能。这是为那些偏好编辑类的整个源文件而不是单独的方法的开发者准备的。要在Workbench中使用SourceView,请选择OpenSourceView菜单项。你也可以在类浏览器中使用全源代码编辑,只要在类浏览器中单击Source标签就可以了。SourceView不是Workbench的一部分,而是一个独立的窗口(见图2-10)。SourceView浏览器由三个窗格组成:Elements,Source和Problems。图2-10SourceView窗口Source窗格显示所有的源代码。点击Elements窗格中相应的条目,你可以跳转到任何方法或定义语句。方法的排列秩序在第一次导入时就确定了,但也可以在SourceView窗口中更改。导出类的时候,该秩序保持不变。VisualAgeforJava不会更改诸如换行和缩进之类的文件格式。SourceView只有一个窗口。每个类都在该视图中有一个页面,通过标签,你可以同时修改多个类。你也可以在SourceView窗口和其它视图中并行编辑某个类。2.5CodeAssists在编辑代码时,VisualAgeforJavaCodeAssists可以帮助输入代码。它会分析你的输入,然后将后面可能的输入列表。要显示该列表,按^Space键(见图2-11)。图2-11CodeAssist窗口2.6在VisualAgeforJava中导入或导出你已经了解到VisualAgeforJavaProfessionalEdition将项目储存在知识库中,而不是文件系统的目录中。如果要应用你的Java项目,或是与别的开发人员共享代码,你必须导入和导出Java类。向VisualAgeforJava环境中导入,导出类和资源有以下几种方式:1.目录你可以向文件系统中导入Java资源或类。导入的源代码会被即时地编译,包继承关系也会保持下来。当你要与别的开发人员共享Java代码,但你们的使用开发环境可能不同,或他使用的不是VisualAgeforJava提供的编辑器,那么你必须导出源代码。如果指定某个路径作为包,你可以导入该包中所有的子包。该功能也可以导入该目录下的资源。要导入资源,单击Resource复选框旁边的Details按钮,选择你要导入的资源。2.JAR文件Java存档(JAR)是一个与平台无关的文件格式,它允许将一个Javaapplet和它的资源文件(如.class文件,图片和声音)包括到单个文件中。JAR文件是分发Javaapplet,Java应用程序及其相关资源文件的好办法。该文件可以放在Web服务器中供浏览器访问。你甚至可以将整个VisualAgeforJava项目都导出为一个JAR文件。3.知识库(被当作VisualAgeforJava交换文件)知识库文件可以被用来交换不同的VisualAgeforJavaProfessional环境中创建的Java类。这些文件保存了版本信息、注释和可视化开发信息。导入某个知识库文件时,它被载入到你的知识库中。你需要将它从知识库装载到工作区中。如果你想让它自动装载到工作区,请在Repositoryimport对话框中选中该选项。这种方法只能将知识库载入最近用到的项目,某些时候,你可能要手工载入。从知识库文件中导出的程序元素必须首先标记一个版本,版本和知识库将在后面的“Workspaceversusrepository”部分详细解释。2.6.1向VisualAgeforJava中导入请注意:向VisualAgeforJava环境中导入代码与在Java源代码中使用import关键字不同。向VisualAgeforJava中导入代码应采取以下步骤:(1)打开Import对话框,在下列的方法中选择一个-File→Import,从任何页的菜单栏中-Selected→Import,从Projects页的菜单栏中-Package/Types→Import,从Package页的菜单栏中-Class→Import,从Classes页的菜单栏中-Interface→Import,从Interface页的菜单栏中弹出一个SmartGuide窗口要求指定导入的源(见图2-12)图2-12向VisualAgeforJava中导入Java文件(2)选定导入的源:-Directory-.java或.class文件-Jarfiles-.jar文件-Repository-repository(知识库)文件要导入目录和Jar文件,请选择:-导入文件的存放路径-要导入的文件(源文件或字节码文件)和资源-导入类的项目-是否覆盖已存在的文件要导入知识库,请选择:-要导入的知识库文件-导入知识库的项目或包(见图2-13)图2-13从另一个知识库中导入除普通的导入/导出选项外,你还可以使用一个可以容纳一组项目的容器-解决方案。解决方案可以被用来成组地导入/导出互相关联的多个项目,比如说,你提供给某个客户的一批项目。解决方案和知识库将在后面的“导入和导出的效果”部分中讨论。本章着重于介绍导入/导出的工具,以及它们如何从/向JAR文件和目录中导入/导出。2.6.2从VisualAgeforJava中导出从VisualAgeforJava中导出代码应采取以下步骤:(1)选择一个或多个项目、包、类或接口。-选择包的时,该包中所有的类和接口都被导出。-选择项目时,该项目中所有的类和包都被导出。(2)打开Export对话框(见图2-14),你可以采用以下几种方法:-File→Export,从任何页的菜单栏中-Selected→Export,从project页的菜单栏中-Packages/Types→Export,从Package页的菜单栏中-Class→Export,从Class页的菜单栏中-Interface→Export,从Interface页的菜单栏中图2-14ExportSmartGuide页要生成或更新一个清单文件来包含类或bean的信息,请指定该清单文件的文件名。(3)选择导出路径:-Directory-.java或.class文件-JarFile-.jar文件-Repository-知识库文件如果你选择导出到Directory,请继续选择:-导出文件存放的根目录-要导出的类(源代码或字节码)和资源-你还可以设置以下选项:导出被引用的类不导出BeanInfo和PropertyEditor类是否生成运行applet所需的HTML文件是否覆盖现存文件是否在浏览器中浏览生成的HTML文件是否封闭该包(sealthepackage)每一个包都可以被封装,封装的信息将会记录在JAR文件的清单文件中。如果你选择导出到Jar文件(见图2-15),除了导出到Directory的选项外,你还要选择:图2-15导出到Jar文件-要导出的bean或类-是否压缩Jar文件如果你选择导出到知识库,请继续选择:-被导出的知识库文件-被导出的项目或类有关导出代码的提示VisualAgeforJava为导出代码提供了一些有用的新特性。选择Selectreferencedtypesandresources按钮,你可以启动DeploymentWizard。它自动包含了你的代码需要的类型,这样,你导出的Jar文件可以只包含你需要的代码。导出Jar文件时可以选择要导出的bean,这要求你的Jar文件必须有一个清单文件。清单文件使别的开发工具知道Jar文件中的bean,它还让别的VisualAgeforJava环境自动将Jar文件中的bean添加到调色板中。如果一个JAR文件会被Java应用程序或applet直接从类路径中使用,请不要对它进行压缩。你还可以导出Java资源文件和类文件中的VisualCompositionEditor信息,这需要选中options对话框中的DesignTime部分的Generatemetadatamethod复选框。VisualAgeforJava会生成一个getBuilderdata方法,它包含了该类的VisualBuilder信息。第3章移植到Java2VisualAgeforJavaVersion3.5ProfessionEdition提供了完整的Java2SDKStandardEditionV1.2.2支持。它包括:JDK1.2.2IBMDeveloperKitforJava的代码建立在SUN代码的基础上。IBM在对它的要求是:更高的性能、缩短的开发周期以及更强的可伸缩性。相比SUN提供的SDK,IBMJDK1.2.2提供了一些增强的功能,且便于维护。Swing1.1JSDK2.1+IBMExtensionJSDK2.1支持创建、测试Servlet2.1和测试JSP0.91或1.0(WebSphereApplicationServer+FIXPACK2支持JSP1.1,但VisualAgeforJava3.5+Patch2不支持)。3.1Fix/MigrateSmartGuideVisualAgeforJavaVersion3.5提供了Fix/MigrateSmartGuide,它使JDK1.1.x下的基本Java类和Swing类可以方便地向JDK1.2.2环境移植。它也可移植Swing类中的VisualComposition信息。所有的包或类名都可以被移植,如com.sun.java.swing.*==>javax.swing.*。你可以从VisualAgeforJavaVersion2或3中导入代码。Migrate工具只能移植带有版本号的代码,请不要试图移植没有设置版本的代码。选择你要移植的类。要启动Fix/MigrateSmartGuide,在Workbench窗口的菜单栏中选择Selected→Reorganize→Fix/Migrate(见图3-1)。Fix/MigrateSmartGuide窗口打开后,你可以在From/to条目中指出已改变的类或包的名字(见图3-2)。选中IncludeJDK1.2renamedpackages检验栏以移植Java应用程序中的Swing类。单击Next按钮。在接下来的窗口中指定不需要改变包名的包(见图3-3)。要指定一个包,请在包名后加上.*后缀。比如说,要调整myPackage包中所有的类,请输入myPackage.*到To字段中,为被改名的类或包键入更改后的名字,单击Add。图3-1如何启动Fix/MigrateSmartGuide图3-2Fix/MigrateSmartGuide窗口图3-3Fix/MigrateSmartGuide-Excludedpackages单击Finish按钮开始移植。你可以打开VisualCompositionEditor进行测试。3.2修理过程Fix/MigrateSmartGuide也可以修复在类向Java2SDK移植时或对用户定义的程序元素的重命名过程中损坏的类或包引用。由于这种修复不可能很精确,请在修复时遵循下列提示以获得最好的修复效果。到Workbench的AllProblems页查看损坏的引用,如果可能,最好在类这一级别上修复引用。这提供了对类修复次序的最大控制,减少了编译错误。如果你必须要在包或类级别上修复的话,VisualAge会先处理Beaninfo类,然后才是关联的bean类。优先修复引用到的类,这样可以保证当别的类要引用到它的时候,拥有更新过API的被引用的程序元素可用。如果某个类有关联的Beaninfo类,先修复Beaninfo类。在所有的类都被修复以后,要修理可视化部件中存在的错误,你可以在VisualCompositionEdition中打开该部件,从Bean菜单中重新生成代码。要把IBMDataAccessLibrariesVersion1.0中的引用移植到Version2.0中,请指定以下更改:COM.ibm.ivj.eab.data.*→com.ibm.ivj.eab.dab.*COM.ibm.ivj.javabeans.*→com.ibm.ivj.eab.dab.*要将引用移植到javax.swing.preview.JGileChooser.class,请指定以下更改:javax.swing.priview.*→javax.swing.*即使所有类引用向JavaSDK的移植都是成功的,它也不能保证所有的bean都按你的设想运行。Sun公司对某些bean的实现方法可能会有改变,请仔细的测试移植的bean。即使你是手工修复,你也必须通过该工具修复可视化组件。这是因为元数据(metadata)必须被修复,否则VisualAge可能会产生错误的代码。VisualAge可以修复对下列程序元素的引用:类、接口和包:超类标示导入标示用户自定义的字段和方法为可视化部件生成的字段和方法如果VisualAge在修理过程中遇到任何过渡性的错误,会弹出一个error窗口。你可以记下该错误,单击OK按钮继续修复。大多数情况下,这些错误是由引用被修复的顺序产生的,它们通常在所有的引用都被修复后就消失了。按照前面所示的提示来修复错误将会减少这类问题的发生。3.3移植你的Servlet和JSP如果你要将你的servlet升级到JSDK2.1(WebSphereApplicationServer3.0以后的版本对JSDK2.1提供了支持),你将需要升级下列已不被推荐使用的API。它们在不久的将来会被取消。SunAPIsHttpSessionContextHttpSession.getSessionContextHttpSession.isRequestedSessionIdFromUrlHttpServletResponse.encodeUrlHttpServletResponse.encodeRedirectUrlHttpServiceRequest.setAttributeHttpServiceResponse.callPageServletRequest.getRealPathServletContext.getServletIBMAPIscom.ibm.servlet.personalization.sam(removed)com.ibm.servlet.servlets.personalization.util(removed)com.ibm.servlet.connmgr如果你的JSP版本为JSP0.91,你应该将它升级到JSP1.0。目前还能使用0.91版,但将来则不一定。在升级前,确定你的代码没有使用不被推荐使用的API。如果你的代码使用了com.sun.server.http.HttpServerRequest或com.sun.server.http.HttpServiceResponse,请将包名改为javax.servlet。将JSP0.91移植到1.0要移植你的JSP,请更改表3-1所示标签。表3-1JSP转换映射表JSP0.91JSP1.0<SERVLET><jsp:include><BEAN><jsp:useBean><REPEAT><tsx:repeat>第4章开始ATM项目本章介绍的范例程序将要在本书以后的所有章节使用。它概括了问题域,还展示了VisualAgeforJava解决方案整个的体系结构。在问题域中还包含了面向对象的分析。对于那些读过本书的旧版《ProgrammingwithVisualAgeforJava,Version2,0120212989》或IBM红皮书《VisualAgeforJavaEnterpriseVersion2:DataAccessBeans–Servlets–CICSConnector,SG24-5256》的读者,该范例程序看起来会很熟悉。但是请注意,这些程序的目标虽然是一致的,但采取的解决方案却不同。本书着重于将它以Web应用程序的方式实现,而Web应用程序的客户端本质上是无状态的。4.1问题域本书将创建一个真正的Web应用程序,并以此来介绍VisualAgeforJava的丰富的特性,在程序创建过程中,我们将会应用到这些特性。首先,我们来介绍该程序要解决的问题。简而言之,该程序将模拟用户与ATM机(银行设在闹市区的自动取款机)的交互。对于ATM机,世界各个国家对它有不同的称呼,但其基本原理都是一样的:插入你的卡,输入一串数字,选择取款的数目,拿到钱,最后取出你的卡。不同的ATM机会在许多地方存在差别。一个差别就是这个金融业务在何时以及如何被记账:许多时候它被直接从银行帐户中扣除,另外一些时候则把它看作是一次贷款。在上面的例子中,那些卡分别被称为记帐卡或信用卡。当前,许多ATM机都可以处理两种交易,不过本书只考虑记账卡。相应的,当本书中提到卡的时候,你应该把它看作是记帐卡。现实中的ATM机还可以提供别的很多服务:显示银行帐号的余额和历史记录,汇款,向电子钱包中存钱,申请短期贷款等。本书中讨论的ATM机只能进行取款和显示银行帐号的一些情况。为了进一步地简化问题,我们认为每张卡都与一个或多个银行账户相关联。除了存取金钱以外,一张卡应该还可以查询关联帐户的余额和历史交易记录,取到的钱被直接从关联的银行帐户扣除。在许多国家,一张卡可以与多个不同的银行帐户关联:一个人的帐户通常只能使用一张卡访问,但是,不同人拥有的多个帐户也可以使用一张卡控制。另外,一个银行帐户本身可以与多张卡关联,如现实中的一个公司帐户,公司中许多人都有一张可以从该帐户中取钱的卡,整个公司共享这个帐户。该范例程序并不理会帐户的拥有者,它只是简单地允许一张卡到多个帐户,和一个帐户到多张卡的关联,以满足前述的情况。但该程序中的卡必须有一个拥有者。现在我们将解释“交易”的含义。本书认为交易发生在两个帐户之间:源帐户中减少的金额与目标帐户中增加的金额相等,且都等于交易指定的钱的数目。当交易涉及到收集现钱时,目标帐户应该是与ATM机关联的一个银行帐户。要向电子钱包中加款,必须要有一个虚拟的目的银行帐号以表示该电子钱包是交易的实际目标。本书还规定交易的数额不能为负。每次存款,取款都被看作是一次交易。下面我们要区分支票帐户(checkingaccout)和储蓄帐户(savingaccount)。一个支票帐户帐户可以允许有一定的透支限额,也就是说可以从帐户中取出超出余额的钱,使帐户中余额为负,当然,能超出的范围有限。请注意,虽然它适用于其余的许多国家,但美国的支票帐户体制不是这样的。储蓄帐户也有一个特性:他的帐户余额不能低于某个正的最小值。在本书的ATM机中,你既可以从支票帐户也可以从储蓄帐户中取款,这并不适用于大多数的欧洲国家。另一个对现实的很大简化是该程序忽略了零钱和汇率的问题:它考虑到了钱的数量,但不指定它的币种,只是简单地称之为钱。该程序在许多方面还是类似于现实中的应用的。想象以下场景:一个“cyber”ATM(Internet上的Web站点),它允许用户通过Internet用记帐卡上的钱给一个电子钱包加款。要完成这个目标,你还需要一个读卡机和一个能给你的电子钱包加款的机器,他们必须都连到一台Internet上的计算机上。当前的智能卡技术已使记帐卡和电子钱包合而为一,你就只需要一个智能卡读卡机就够了,当然,你还需要一台电脑。这已经在一些国家(如匈牙利)投入实际应用了。我们还会创建一个基于Swing的应用程序来解决同样的问题,它将被用来展示如何使用VisualAgeforJava的图形化编辑器(见第七章,“创建GUI程序”)。4.2创建ATM模型我们将为该范例程序创建一个模型:通过学习这里的图表和注释,完成本章后,你应该能很轻松地理解范例的代码。如果你理解了本章中介绍的所有内容,当然,你也能理解我们在本章末尾讨论的程序。在前面的部分,我们已经分析了要解决的问题,现在,我们要将它模型化,下面就是我们在范例程序中使用到的对象:Card(卡) 对一个或多个银行帐户有权访问Bankaccount(银行帐号) 要么是支票帐户,要么是储蓄帐户Money(钱) 用一个数字代表,单位为特定的币种Transaction(交易) 两个帐户间转帐的记录Person(用户) 与ATM机交互的人Bank(银行) 签发卡和帐户的机构ATM 使用卡取钱的机器Electronicpurse(电子钱包) 可以被当作普通钱包使用的电子装置PIN 用来保护卡的个人身份号码在进一步定义操作前,我们应该熟悉以上定义。4.2.1操作现在,我们来讨论人。这个用户拥有一张可以在ATM机上使用的卡,他或她是唯一的与ATM应用程序交互的对象。图4-1显示了人机之间的交互关系,我们有八个操作:接受卡 ATM机显示欢迎信息,用户可以将卡插入ATM机的读卡器中。验证登录 用户向ATM机输入PIN吃掉卡 如果用户多次输入错误的PIN,ATM机将卡存放在ATM机内部,同时显示一条信息。列出帐户 列出与该卡关联的所有帐户,用户可以选择要存取的帐户。显示帐户信息 ATM机显示选定的帐号,让用户选择取钱或是查看历史交易记录。取现款 ATM机询问用户取现款的数目,如果情况合适(帐户中余额足够,ATM机中有钱等),ATM机吐出现款。显示帐户记录 ATM机显示出当前帐户的历史交易记录。吐出卡 用户完成交易,读卡器吐出卡,ATM机显示信息让用户拿走卡。要获得更详细的对于图中操作的描述,请浏览用RationalRose生成的HTML版的模型。RationalRose是资源包的一部分,你可以从Redbook网站下载或在随书的CD-ROM中找到。(见附录B,“使用附加材料”)图4-1ATM操作图表person 用户insertcard 插入卡typepin 输入PINselectaccount 选择帐户returncard 返回卡chooseaction 选择操作specifyamount 指定数目ejectmoney 吐出钱acceptcard 接受卡listaccounts 列出帐户showaccountdetail 显示帐户信息dispensecase 扣除现款validatelogin 验证登录showaccounthistory 显示帐户交易历史记录consumecard 吃掉卡ejectcard 吐出卡你或许已经注意到其中有一个操作被称为“扣除现款”,而不是“给电子钱包加款”。在详细的描述了操作以后,我们发现试图区分电子钱包卡和记帐卡会使问题更加复杂,而这些复杂其实是多余的。事实上,你会发现操作“扣除现款”和“给电子钱包加款”基本上是一样的,当给电子钱包加款时,ATM机是将其当作现款扣除的。在开始部分,我们已经提出了模型中对象的初步方案。现在,我们需要对它进行调整:电子钱包应该从对象消去。到目前为止,有两个ATM机的组件已经被提及多次,我们应该将它们加入到候选的应用程序对象中去:读卡机现款扣除装置我们在为一个操作指定状态时应该考虑ATM机的状态。4.2.2ATM机状态表ATM机的状态决定了允许进行一些操作,不允许进行另外的一些操作。在Web应用程序的设计中,状态是重要的考虑因素。不同于普通的客户机/服务器程序,Web客户可能会提出进行当前系统状态不允许的操作,该情况的原因有两个。其一,传统的客户机/服务器程序中的两方通讯所采用的协议相当安全(要保证安全也很容易),于是我们相信客户机提供的身份。Web应用程序中使用HTTP协议使它易于被伪造客户端欺骗(提供了安全措施的HTTPS是个例外),伪造的客户端通常会在“错误的时刻”发出请求。其二,对于一个只能在恰当的时间请求服务的客户端,服务器不能回呼客户机以验证它是合法的。客户端本身是无状态的,HTTP协议也是单向、无状态的,所以上述问题不能由普通的Web客户端解决。UML为我们提供了状态表,这可以帮助确定类型所处的特定状态。该表可以显示一个对象所处的所有可能状态,它还能代表对象在各个状态间的过渡。状态间的过渡可以由内部或外部的操作引起。并不是所有可能的操作都被列表:如果它们对对象的状态没有影响,而且它们在所有的时候(在该对象的所有状态下)都运行,状态表一般不会将它们都列出来。在ATM系统中,我们使用了两个状态表,因为该系统有两大类状态。当ATM机被用户使用时,它所有的状态会共享一些公共的行为:别的用户不能使用它、用户在一定时间内不进行操作,ATM交易可能会过期,等等。首先,我们把上述的“使用中(InUse)”状态模型表示为一个,为了将它与其它状态相比较,我们将详细讨论ATM机在被使用时的所处的不同子状态。图4-2显示了ATM机可能处于的普通状态,图4-3则展示了组成图4-2“使用中”状态的子状态。图4-2ATM状态表outoforder 发生故障readytouse 可以使用inuse 使用中insertcard 插入卡initialize 初始化interrupt 中断see“ATMinuse”diagram 见图4-3insertcard 插入卡timeout 过期interrupt 中断“插入卡”这一动作在前面已经提到了两次,它与ATM机的“可以使用(ReadytoUse)”状态交互。当用户插入一张读卡器不能辨认的卡时,第一个“插入卡”的过渡发生了,读卡器吐出卡,ATM机还是处于“可以使用”状态。只有当卡被读卡机辨认出来后,ATM机的状态才能转换为“使用中”,这个过程由图中的第二个“插入卡”转变表示。“使用中”状态会在两种情况下结束。一个是因为长时间人机未发生交互而过期,另一个则是由于图4-3中所示的一个过渡。图4-3ATM机“使用中”状态的子状态readytouse 可以使用(见图4-2)NotloggedOn 未登录Bankaccountslisted 列出银行帐户Bankaccountschosen 选择银行帐户Askamount 要求输入数量Dispensemoney 扣除现款Transactionhistorylisted 列出交易记录EnterPIN 输入PINSTOP 交易中止Chooseaccount 选择帐户Listallaccounts 列出所有帐户Choosemoneywithdraw 选择取款金额Listhistory 列出帐户交易历史Getmoney 得到现款Collectmoney 取钱Returntoaccountdetail 回到帐户insertcard 插入卡图4-3显示了ATM及“使用中”状态的六个子状态:未登录 卡在读卡器中,但用户未输入PIN以证明自己的身份。列出银行帐户 ATM机将与该卡关联的帐户列表选择银行帐户 用户在帐户列表中选择一个帐户。如果他的卡只与一个帐户关联,则不用选择。要求输入数量 ATM机要求用户输入要取款的数额。扣除现款 ATM的现款扣除装置从ATM机内部取出要求的钱交给用户。列出交易记录 ATM机列出当前帐户的交易记录。我们建议你仔细地阅读这些图表的UML文档。虽然我们在这一部分介绍了一些内容,但或许你需要更多的材料以更好的理解这个问题。看完这些图表,你应该注意到了一点:用户可以在任何时候选择终止交易,当然,现款扣除装置取钱时例外。终止交易时,ATM机命令读卡机吐出卡,系统回到“可以使用”状态。另外一点是,用户输入PIN以后,ATM机的状态有四种可能的转换:正常情况下,PIN被验证,ATM机显示卡的关联帐户列表。PIN被验证后,卡只有一个关联帐号,ATM机直接进入该帐号。输入的PIN错误,系统提示用户重新输入PIN多次输入错误,ATM机吃掉卡。图4-3中的两个转换被用“‘”号标出来。“取钱”这个动作是由用户实现的,现实中的现款扣除装置可以察觉用户取钱的动作。我们在范例程序中将其简化为:经过一段时间以后,ATM机自动地回到“选择银行帐户”状态。时间的长短与取款的金额有关。这意味着“取钱”这一动作不会被程序表示出来,它将会被自动进行。“未登录”状态和“可以使用”状态间的转换在多次错误的输入PIN后发生。同样是为了简化,我们不考虑它。4.2.3分析类图表让我们再回头看看那些有可能成为程序中对象的候选者。经过前面的分析,我们可以抛弃其中的两个:银行在讨论中没有被提到,区分不同的银行与我们的程序没有什么关系。我们将让BankAccount对象来处理所有的银行帐户,这种处理方法使用到了三个类型,ATM,Card和Transaction,程序需要维护它们的实例,并提供必要的行为以在这些对象的列表中选择。另外一个我们提到了但是现在要抛弃的对象是用户。普通程序的客户端可以有它的属性和行为,可是在Web应用程序中,我们不可能获得Web客户端的属性,或是调用它的方法。Web客户端是无状态的,这使用户也成为多余的了(请参考前面的“ATM状态表”开头部分对这个问题的讨论)。下面是被我们淘汰后剩余的对象:Card(卡) 对一个或多个银行帐户有权访问Bankaccount(银行帐号) 要么是支票帐户,要么是储蓄帐户Money(钱) 用一个数字代表,单位为特定的币种Transaction(交易) 两个帐户间转帐的记录ATM 使用卡取钱的机器PIN 用来保护卡的个人身份号码CardReader(读卡机) ATM机上用户插卡的的设备CashDispenser(现款扣除装置) ATM机上用户取款的设备图4-4显示了这些对象之间的关系,这里还列出了一些方法和最重要的属性。图4-4类分析图表ATM ATMState 状态Card 卡Owner 拥有者CardReader 读卡机CashDispenser 现款扣除装置Pin PINBankaccount 银行帐户Transaction 交易Savingaccount 储蓄帐户Checkingaccount 支票帐户Money 钱Accept 接受Givesaccessto 允许访问Secured 受保护Dispenses 出款Associated 关联的Source/target 源/目的Balance 余额Amount 数量Ocverdraftlimit 最大透支额Minimumbalance 最低余额要对我们的Web程序的设计要求有一个彻底的了解,请仔细研究该图表和相关文档。现在简要介绍一下各对象间主要的关系。我们认为卡由一个PIN保护:只有当正确的号码被输入后,ATM机才会允许用户对卡进行进一步的操作——允许访问与卡关联的一个或多个帐户。所有的交易都有源帐户和目的帐户。不知道你是否记得,不通过一次交易,没有钱可以被储蓄或取出:在一次ATM取现款的过程中,ATM机与一个(目标)银行帐号关联,它接受用户从选择的帐户中转入的现款。每次交易都要记住牵涉到的金钱的数量。银行帐户有一个余额,除此以外,支票帐户受最大透支额保护,储蓄帐户则受最低余额限制。钱通过ATM机的现款扣除装置吐出。我们用这个模型代表了在问题域中要解决的问题。它已经可以被用来分析这个问题了。下一步我们将调整它使其真正地成为能解决该问题的设计模型。4.2.4设计类图表该部分中,我们将讨论如何将前面建立的模型实现为一个系统,该系统将业务对象实例化,可以解决实际问题:我们已经进入设计阶段了!作为本书的介绍对象,我们选中Java作为实现该系统的编程语言。本来设计阶段应该分为两个独立的部分,一个部分与编程语言无关,另一个则用Java实现前一部分,但这样的划分会使本章过长,因此我们选择了将两者混合起来讲述。我们首先看一下在分析阶段中提到的“输入PIN”(图4-4)。这个模型将PIN定为只能由卡访问。PIN所有的职责就是将输入的字符串与它本身相比较,以鉴别卡的所有者。现在我们将PIN合并到卡中:如图4-5所示,卡承担了验证PIN的任务。对象分析图中ATM机和BankAccount之间的联系决定了每次取现款的数量不能大于ATM机中实际现款的数量。取现款的目的帐户是与ATM机关联的,这表明取现款的交易有可能会由于上述限制失败。我们不得不在程序中的某个地方实现这个限制:它要么由ATM机实现,要么通过BankAccount加以限制。我们可以把检查ATM机中是否有足够的金钱这个问题与前面谈到的两个限制相比较,在取款中限制取款数额的支票帐户的最大透支额和储蓄帐户的最低余额(它们都会导致交易失败)。我们决定将上述限制的实现交给银行帐户。具体来说,我们建立了一类新帐户――ATM帐户。要使该帐户工作,我们赋予它一个新的属性,该属性表示了ATM机中在交易开始时最大的可提取的现款的数量。每次钱被提出的同时,同样数量的钱都会被从用户帐户转到ATM帐户中,每次它还会进行一些必要的检验。每次取款都会被在关联的ATM帐户中存款而补偿,从而保持ATM机的“价值”永远不变。你可以将ATM帐户与出纳员帐户相比较,该出纳员帐户被用来登记某个出纳员处理的所有金钱交易。该帐户的余额和出纳员抽屉中的现款数目之和应该在所有的时候都相等。我们并没有使用另一个对象表示现款扣除装置中实际拥有的现金数,它实际就是ATM机最大现款数额和ATM帐户余额之差。card 卡ATM ATM机CardReader 读卡机Cashdispenser 现款扣除装置BankAccount 银行帐户Id IDPin PINState 状态Currentcard 当前的卡Associated 关联currentBankAccount 当前的银行帐号图4-5设计模型中与ATM机相关的部分上面的图表显示除了ATM帐户以外,ATM机也包含读卡器和现款扣除装置。ATM机的这三个子部分被完全地与ATM机本身捆绑起来:它们同时创建,不能脱离ATM机存在,从ATM机外部不可见。ATM机通过它们实现它的行为,ATM机分析所有对ATM机的请求,以决定是否将它们发送到这三个部分中的一个。在图4-5中,我们给每张卡,银行帐户,ATM机和交易赋予了一个身份(ID),这允许我们区分这些对象的不同实例。你也可以把ID当作是区分这些对象的实例的主键。我们希望所有的这些ID都有一些公共的行为(转向/来自字符串的转换,比较大小等等),我们也希望避免将指向不同类型的对象的ID混杂起来,使用内部类并扩展一个公共的PrimaryKey类(见图4-6)可以满足上述要求。我们不但要将主键(primarykey)存放在一个数据库中,还要把它包括在Web网页中,这需要转向/来自字符串的转换和一个构造器。为了方便,我们提供了一个缺省的构造器,它自己就可以产生一个主键。图中的hashCode()方法(和equals()方法)使我们能使用HashMap类型储存并区分业务对象。图4-6与主键相关的类设计图表所有可验证业务对象的类,它们负责跟踪它们自己所有的实例,这些类都有一个Finder方法:它们接受对应类型的主键,并查看是否能找到一个与该主键对应的对象。如果它找不到对应的类,那么我们将创建一个具有适当的默认状态的新对象。这将大大的简化我们的测试代码,因为它在没有提供测试数据时也可以工作。交易也是上述BO(业务对象)中的一个,它可以由自己的专门的PrimaryKey验证。如图4-7所示,创建交易对象的唯一方法是使用交易类方法CreateTrx()。该方法保证了没有存款就不能取款。当它不能创建一个完整的交易时,它将会发出TransactionAbortedException异常并将所有已做的更改恢复到该方法起始的状态。图4-7交易BankAccount 银行帐户Transaction 交易Savingsaccount 储蓄帐户Checkingaccount 支票帐户ATMAccount ATM帐户Money 钱Id IDsrcAccount 源帐户trgtAccount 目的帐户balance 余额trxAmount 交易数量minimumBalance 最低余额overdraftAmount 最大透支额initialAmountCash 最大现款额度这里的TransactionAbortedException是图4-8所示异常(exception)的父异常:当一个ATM帐户尝试存款(以弥补取款)但会使其中的余额大于最大现款额度(initialAmountCash)时,它会发出NotEnoughCashException信号,这避免了用户要求从ATM机的取款额度超出ATM机实际存放的现款数目。另外两个异常来自于ExceedLimitException异常,它指示了用户的帐户中余额不够完成取款。OverdraftLimitExceededException显示当前的取款行为将使帐户余额大于支票帐户的最大透支额,BelowMinimumBalanceException的功能与之相似,它显示的是低于储蓄帐户的最小余额。图4-8TransactionAbortedException图表当使用JSP定制Web应用程序的出错消息时,图4-8所示结构很容易实现(第六章,“创建JSP”)。程序的内部的处理逻辑将会处理TransactionAbortedException,我们还可以将这些JSP设计得更加精细,使它们可以根据子异常的类型帮助用户找到出错的地点。请注意这些异常类型只有一个构造器。它将出错信息用一种用户可读的格式显示出来,这方便了调试和测试过程。另一个目前看起来多余的对象是钱。我们将它在模型中作为一个单独的对象,这为了便于以后在将该程序应用到现实中时添加对汇率和零钱的支持。另外一个优点是大家都熟悉的Java对类型的检验:在人为的误输入中,当接收到一个Money类型的参数时,你不太可能错误地使用某些方法,因为它们只能接受普通数值类型的赋值。即使你错误使用了,如果赋值的类型错误的话,编译器也能在运行程序前检测到该错误。仔细查看上面的图表和附录B“使用附加材料”中的整个设计,你会注意到对于那些可以验证的业务对象,并没有提供任何方法能将它们移去。这是我们的又一个简化:增加这些方法并不能为我们的讨论带来更多的内容,不理会它们却可以减少对HashMap同步存取的讨论,免除对这些对象的引用。4.2.5交互图表我们画出了图4-9所示的序列图,它展示了前面提到的业务对象如何共同工作,以完成程序的目标。我们选择了最基础的场景——取款。1.先决条件用户已经将卡插入ATM机,通过了PIN验证,选择了一个支票帐户,并要求取钱:ATM机处于ASK_AMOUNT状态,它询问取款的数量。用户想要取100,被选择的帐户中有足够的钱,ATM机中也有100的现款。2.场景用户输入100。ATM即从当前帐户中取出100,现款扣除装置吐出100。用户拿走钱,ATM返回显示当前帐户。序列图显示出用户输入100相当于给ATM机发出消息:getMoney,ATM机要求“交易”这个对象创建一个实例,该实例以选定的帐户为源帐户,该ATM的ATM帐户为目的帐户,数额为100:creatTrx。“交易”创建一个自己的新实例,在选定帐户中调用withdrow方法。该选定帐户检查它的余额,并减去取款数量。交易然后要求ATM帐户执行deposit方法,ATM帐户先要进行检验然后将取款数量增加到它的余额中。交易到这里已经成功了,它将该交易实例加入到历史记录中。ATM机将状态转换为DISPENSE_MONEY,要求现款扣除装置执行dispenseMoney方法。当现款扣除装置吐出钱以后,ATM机回到BANK_ACCOUNT_CHOOSEN状态。图4-9“取款”场景的序列图你应该已经对该程序的设计有了一个基本的了解。如果你还有不理解的地方,请参考整个模型及其文档(见附录B,“使用附加材料”)。我们现在将讨论程序的底层结构,并将它们通过不同的解决方式中加以实现。4.3整体体系结构这部分将把该范例程序应用的不同环境一一展示出来。我们在前面设计时确定的业务对象会组成它们的基础。这些对象构成了解决方案的模型,并唯一地负责执行业务逻辑。如果除了这些业务对象以外,系统中别的地方也存在业务逻辑,它们将不会对这些业务对象的逻辑过程产生任何影响。那些业务逻辑应该是被用来解决特定情况的辅助过程。举个例子,输入的PIN必须是数字,其中不能含有非法字符,对PIN输入的检查可以通过在HTML中加入JavaScript来实现。虽然该项规则检查也可以由业务对象实现,但在客户端用JavaScript完成可以减少服务器与客户端的不必要的来回通信,这种通过Internet的通信可能会增加程序的响应时间。4.3.1整体图图4-10所示业务对象处于整个图的中心地位。本书介绍的体系结构是一个基本的三层结构。顶层代表持续性储存(它储存交易的记录),中层是设计的业务对象的实现(BO层),中层以下所有的类型都代表了接口,它们特定于该应用程序用户的环境。底层(表示层)的作用基本上是翻译程序内部处理逻辑和并负责与外部环境间的输入和输出。图4-10体系结构图transaction 交易Money 钱card 卡ATM ATM机CardReader 读卡机Cashdispenser 现款扣除装置ATMAccount ATM帐户Checkingaccounts 支票帐户Savingsaccounts 储蓄帐户Insertcardservlet InsertcardservletEnterPINservlet EnterPINservletChooseaccountservlet ChooseaccountservletShowATMservlets ShowATMservletsChoosewithdrawalhistoryservlet ChoosewithdrawalhistoryservletEnteramountservlet EnteramountservletOutoforder 发生故障Readytouse 可以使用Notloggedon 未登录Bankaccountslisted 列出银行帐户Bankaccountchosen 选择银行帐户Askamount 要求输入数量Dispensemoney 扣除现款Transactionhistorylisted 列出交易记录JSPs JSPCardbean CardBeanCardBeanHome CardBeanHomeBankaccountbean BankaccountBeanJavabeans JavaBeansBrowser 浏览器GUIClient GUI客户你在图中可以见到两种主要的表示层实现方式:GUI,传统的C/S客户浏览器,Web应用程序4.3.2GUI客户该程序的GUI(GraphicalUserInterface,图形用户界面)版是一个Java应用程序。这个客户端采用了VisualAgeforJava的VCE(VisualCompositionEditor)部件,为了换换花样,它并不实现与ATM机的交互,而是提供了一些对ATM系统的管理功能。你在第七章“创建GUI程序”将看到,VCE采用JavaBean工作,图4-10中的方块区域中显示了一些包围着业务对象的JavaBean。要提示的是,原来业务对象中类一级的职责现在被交给了一个带有Home后缀的JavaBean:比如,CardBeanHome将关于卡的请求发送到相应的卡类的方法,它起了原来卡的Finder方法的作用4.3.3浏览器客户Web应用程序可以被看作是一个转换器。它将HTTP请求转换为传递给业务对象的消息,业务对象的处理结果被转换为HTML(还是使用HTTP协议)格式传回浏览器客户。上面介绍的Web应用程序包含两个程序部件:ServletJavaServerPage(JSP)第五章,“创建Servlet”解释了servlet的概念,并用其实现整个范例程序,并没有用到JSP。第六章,“创建JSP”解释了JSP,并向前面创建的只使用servlet的程序中加入了JSP技术。在本章的开头,我们指出了传统的客户机/服务器应用程序和Web应用程序(它的客户端是无状态的)的一个重要区别:简单地说,Web应用程序要在任何时候准备接受对任何方法的调用,而这些调用在当时的状态下可能是不合法的。在设计该程序的时候,我们通过确定ATM机的状态来判断并处理这些不合法的调用。ATM机的状态明白无误地表明了在交易的任一阶段可以进行的操作。由于现实中ATM机的状态只要看一眼就可以确定,我们可以将ATM机的状态与ATM机的不同显示联系起来。Servlet和JSP两种实现方式都采用了这个处理方法。该处理方法的中心部分是ShowATMServlet,它负责将ATM机当前的状态返回给客户端。该servlet是唯一响应客户浏览器的部分(它会间接地通过JSP):客户对所有别的servlet(包含JSP)的请求都被交给ShowATMServlet。这种设计确保了任何时候对程序的访问都是合法的。别的servlet使用ATM对象来提交对ATM机进行操作的请求。这些操作(来源于ATM系统的用户的操作)可以在操作图表(见图4-1)找到。每个servlet对应于用户的一项用户操作引起的操作。通过这种设计,不同的功能需求和它们的执行之间的对应就十分明显了。分析和检验完HTTP请求后,那些操作servlet调用业务对象中对应的方法,在本范例中主要是ATM。这些调用的结果可能会是ATM机状态的改变,或是出错。两种情况下ATM机都必须显示出来(即使还附带出错信息),所以这些ATMservlet总是将请求发给ShowATMServlet,以依据ATM机当前的状态产生相应。4.3.4数据库访问为了简化,图4-10中的业务对象层和图顶端的数据库之间的连接是在别的业务对象中实现的。更好的解决办法是通过中间的持续性层实现。本书只介绍VisualAgeforJavaProfessional版的特性,它不包括PersistenceBuilderFeature,而这是有效地实现持续性层的必要工具。要想找到关于如何创建持续性层的内容,请参加专门的讲座。第十章,“使用关系型数据库”讨论了基于数据库的持续性的解决方案。该方案将与我们下面即将讨论的基于内存的持续性的参考解决方案完全兼容:你只需要修改所有的客户层的import语句,让它引用下列两个相应的包:com.ibm.itso.sg245264.atm.memory 它包含了以下部分的将数据储存于内存中的范例解决方案com.ibm.itso.sg245264.atmk.database 它包含了第十章“使用关系型数据库”中介绍的数据库解决方案我们将通过JDBC2.0访问数据库,这使你可以在任何平台上使用任何的数据库引擎,只要有它的驱动。使用JDBC的另一个好处是,以上的三层可以分别存在于不同的计算机。更多的关于数据库部分的叙述,请阅读第十章“使用关系数据库”。4.4范例的实现我们将会有三个不同的客户端程序来访问业务对象,还有两种不同的解决方案。在该部分中,我们将讨论参考解决方案,它着重于实现前面讨论的设计模型的业务逻辑。开始创建程序时,最简单的的办法就是直接从设计工具生成Java类的框架代码。我们使用了一个连接工具来连接RationalRose和VisualAgeforJava。要使用这个工具,你需要下载并安装一个补丁程序和RationalRose建模工具。请参考以下网址:/support/downloadcenter/upgrades/rose.jsp所有在这里讨论到的代码和程序其余的部分都可以在附加资源中找到:见附录B,“使用附加材料”,因此,你不需要自己输入所有的代码。作为一次训练,你有可能会完成程序中的一部分,然后拷贝其余的代码以完成整个IDE。我们还提议你进行第二个训练以保证你的确掌握了本书所讲的内容:回到问题域部分,找出需要增加或改进的功能,在现有代码的基础上描述并实现它们。在我们开始介绍的同时,你也应该开始你自己的项目了,我们假设你刚刚安装了VisualAgeforJa

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论