内容摘要: 1.1 什么是应用框架:框架(framework)是可以被重用的一种半成品的应用程序,我们可以用它来制作专门的定制程序。这就如同人类一样,软件应用的相同点要远远大于不同点。它们在相同的机器上运行,把信息输入相同的设备,用相同的显示设备显示,并将数据村存储到相同的硬件设备中...
1.1 什么是应用框架:
框架(framework)是可以被重用的一种半成品的应用程序,我们可以用它来制作专门的定制程序。这就如同人类一样,软件应用的相同点要远远大于不同点。它们在相同的机器上运行,把信息输入相同的设备,用相同的显示设备显示,并将数据村存储到相同的硬件设备中。传统的桌面开发应用的开发人员更习惯于使用可以涵盖应用开发同一性的工具包和开发环境。框架提供给开发人员这些公共基础上的应用框架从而为他们的产品提供可重用服务的基本架构。
框架是经典的构建-购买-命题。如果你独立构建它——那当你可以独立完成的时候你就会理解它,但是你又花费了多长时间来用之自如呢?如果你购买了它,你必须得克服学习曲线——并且学习它将话费你大约多长时间?这里没有明确的答案,因此许多专家会认为,例如Struts这样的框架能提供比全新的开发更显著的投资回报,特别是对大型项目来说尤为显著。
1.2 其它类型的框架:
框架的思想不仅仅用于应用程序也可以应用于组件。通过这些,我们以前也提到过一些可以与在Struts一起使用的框架。其中包括Lucene搜索引擎,Scaffold工具包,Struts验证器,以及Tiles标签库等等。就像应用框架一样,这些工具也提供了一些可以用在用户的定制组件之中的半成品。
某些框架已经被限定于专门的开发环境之中。而Struts以及本文中涉及的其他框架却不是这样的。你可以在各种各样的开发环境中来使用Struts:例如Visual Age for Java, JBuilder, Eclipse, Emacs, 甚至在Textpad中都可以使用Struts。只要是可以用来开发Java的工具都可以用来开发Struts。
1.3 使用的技术:
使用Struts的应用开发基于大量的其它技术。这些技术并不专属于Struts而是针对所有Java web 应用的。开发人员之所以使用Struts之类的框架的一个原因是为了隐藏在HTTP,CGI,以及JSP之类技术后面的繁琐细节。作为一个Struts开发人员,你并不需要完全了解Struts的所有相关知识,但是它们有助于解决比较麻烦的问题。
1.4 超文本传输协议 (HTTP) :
当两个国家之间进行交涉时,外交官们总是遵循一定的正式协议。
设计外交协议的主要目的是避免误会从而防止谈判破裂。同样,当两台计算机需要进行会话时,它们也要遵循一个正式协议。这个协议定义数据如何传输以及到达后如何进行解码。Web应用程序使用HTTP协议从而在运行浏览器的计算机和运行的服务器的程序之间传输数据。
很多服务器应用程序使用HTTP之外的其他协议。这些协议中的大多数是计算机之间的持久性连接。应用服务器可以清楚的知道是谁什么时候连接的并截止到何时中断的连接。因为它们知道每一个连接的状态甚至每一个使用它的人,这就是所谓的状态协议。
与此相反,HTTP被认为是一个无状态协议。HTTP Server 可以接受来自于各种客户的各种请求并且可以提供一些响应,即使这个响应仅仅是一个No。没有大量的协议和连接持久性,无状态协议可以处理大量的请求。这就是Internet可以被数量如此巨大的计算机使用的原因之一。
HTTP 成为通用标准的原因之一是简单性。一个HTTP请求看起来就像一个平常的文本文档。这使应用程序创建HTTP请求变得相当容易。你甚至可以通过标准的程序比如说Telnet来手动发送HTTP请求。当HTTP响应返回时,开发人员也可以直接在文本文档中读到其中的内容。
HTTP请求的首行包含方法,其后是请求的来源地址和HTTP版本。可以没有也可以有多个。HTTP头向服务器提供额外的信息。可以包括浏览器的类型和版本,可接受的文档类型,浏览器的cookies,仅仅为了一个名等等。在这7 种请求方法中, GET和 POST是最流行的。
当服务器接收到请求,服务器会马上产生一个HTTP响应。响应的首行称为状态行包含了HTTP协议的版本,字符型状态,以及该状态的简短描述。紧随状态行其后,服务器将返回一组类似于HTTP请求头的HTTP响应头。
按我们所描述的,HTTP并不会在请求之间保留状态信息。服务器接受请求,发出响应,并且顺利的处理文本请求。尽管HTTP是简单与快捷的,但是无状态的HTTP协议并不适合于需要跟踪用户状态的动态应用。
Cookies和 URL 重写是两种应用于请求之间跟踪用户状态的方式。cookie是一种用户电脑上的特殊信息包。URL重写是在页面地址中存储一个特殊的标记从而让Java服务器可以用它来跟踪用户。这两种方法都不是完美的,而且使用哪一个都意味着开发web工程时需要进行额外的工作。对其本身来说,标准的HTTP web服务器并不需要发送动态内容。它主要是使用请求来定位并在相应中返回文件资源。通常这里的文件使用超文本语言 (HTML) [W3C,HTML] 格式化以及显示它们。HTML页面通常包含一些到其他页面的超连接,或者说一些其他内容比如图片视频等等。用户点击链接产生一个新的请求,同时开始了一个新的处理过程。
标准web服务器对于静态内容和图片的处理相当好,但处理动态内容时需要外力的帮助。
定义:web中的静态内容直接来自于文本或数据文件,例如HTML或JPEG文件。这些文件可以随时改变,但通过浏览器请求时却不能自动改变。相反,从另一方面来说,动态内容是临时产生的,它是针对浏览器的一个典型的个别请求的响应。
1.5 公共网关接口(CGI) :
首个广泛使用动态内容的标准是通用网关接口Common Gateway Interface (CGI)。CGI使用环境变量,标准的输入输出等标准的操作系统特征,在Web服务器之间,以及和主机系统之间创建桥接和网关。其他应用可以看到web server传递过来的请求并创建一个定制的响应。
当一个web服务器收到一个对CGI程序的请求时,服务器运行CGI程序并向CGI提供它请求里面所包含的信息。CGI程序开始运行后将输出返回给web 服务器。web服务器把相应发送给浏览器。
CGI定义了一套关于什么信息将作为环境变量传递以及它希望如何使用标准的输入输出。就像HTTP一样,CGI是灵活和易于实现的,并且已经有大量成型的CGI程序。
CGI程序的主要缺点是每个请求对应一个新副本。这是一个相对昂贵的处理方法对大容量站点来说每分钟的数千个请求可能会使站点瘫痪。另一个缺点是依赖于平台。为一个操作系统写的CGI不能在其他操作系统上使用。
1.6 Java servlet:
Sun公司的Java Servlet平台直接解决了CGI程序的两个主要缺点。首先servlet 比CGI 程序提供更好的性能和资源利用。其次,JAVA的一次编写,随处运行的特性意味着servlet可以在存在虚拟机(JVM)的操作系统间随意移动。
Servlet类似于一个微型web服务器。它接受请求并产生响应。但是,与常规web服务器不同的是,servlet API 是专门用来帮助Java 开发人员创建动态应用的。
Servlet 自身是如同其他任何一个Java类,需要编译成字节码文件的Java类。Servlet访问HTTP 特定服务的API,但它仍然是一个运行于程序之中的Java 对象并可以利用所有的Java 资产。
为了使常规web服务器能访问servlet,servlet被安放在一个容器中。servlet容器连接web服务器。每个servlet 都可以声明它想处理哪种URL。当符合条件的请求到达web服务器的时候,web服务器将请求传递给servlet容器,servlet容器则调用servlet。
但是与CGI 程序不同,并不是每个请求都会创建新的servlet。一旦容器实例化了一个servlet,它就仅为每个新的请求创建一个新的线程。Java线程比CGI程序的服务器话费要少很多。一旦servlet被创建,使用它处理额外的请求仅带来很小的额外开支。Servlet开发人员可以使用init() 方法保持对昂贵资源的引用,比如连接数据库或者EJB Home接口等等,以便它们可以在不同的请求之间进行共享资源。获得这些资源需要好肥几秒钟的时间——这比大多数网上冲浪的人的最长等待时间要长一些。
Servlet的另一个好处是,它可以多线程运行,servlet开发人员必须特别注意确保servlet是线程安全的。
1.7 JavaServer Pages:
对于CGI程序servlets虽然前进了一大步,但它也不是无敌的。为了产生响应,开发人员仍然使用大量的println语句来生成HTML。代码如下:
out.println("<P>One line of HTML.</P>");
out.println("<P>Another line of HTML.</P>");
在servlet中产生HTTP响应是很正常的。也有一些库来帮助你产生HTML,但是随着应用的日益复杂化,Java开发人员脱离了HTML设计师的身份。与此同时,给出这种选择,大多数项目经理更喜欢选择将团队分成几个小组来工作。 他们喜欢HTML设计人员处理表示层的工作,与此同时Java工程师则侧重于业务逻辑。单独使用servlet的场合下鼓励混合标记和业务逻辑,这让分组工作变得困难。
为了解决这个问题,Sun公司提出了一个将脚本和模板技术结合到一个组件中的服务器页面技术(JavaServer Pages)。为构建JSP页面, 开发人员开始用以前创建HTML页面的方式来创建页面,使用HTML 语法。为了在页面中引用动态内容,开发人员还将脚本元素置入页面之中。脚本元素是一些标记语言压缩了可以被JSP识别的逻辑。你可以在JSP页面中简单的识别出被压缩在一对<% 和 %>标记中的脚本元素。
为了让大家容易识别JSP页面,JSP文件的扩展名须为.jsp。
当一个客户请求JSP页面时,容器将页面翻译成Java servlet 源代码文件并将它编译成Java 类文件——就像你从零开始写一个servlet文件一样。运行的时候,容器也可以检测出JSP文件对应的类文件的最后更新时间。如果JSP文件在上次编译之后被修改过,容器将再一次翻译和编译JSP文件。
项目经理现在可以将表示层工作分配给HTML 开发人员,而 JAVA开发人员将会被分配一些业务逻辑工作。一定要记住最重要的是JSP页面其实就是一个servlet。用servlet可以处理的事,用JSP也可以处理。
1.8 JavaBean:
JavaBean是一种符合一定的设计模式的 Java类这样的设计模式使它们易于和其他开发工具和组件一起使用。
定义:JavaBean 是一种用JAVA 语言写成的可重用组件。要编写一个JavaBean,类必须是具体的公共类(public),并且有无参构造函数(NON-ARGS CONSTRUCTOR)。JavaBean把通过提供符合一致性的设计模式的public访问方法暴露的内部字段称为属性。众所周知属性名也符合这种模式,其他JAVA 类也可以通过自省来发现和操作JavaBean 属性。
JavaBean设计模式提供的访问bean的内部状态的方法有两种:访问器(accessor)是用来读一个JavaBean状态的;修改器(mutator)是用来修改JavaBean状态的。
修改器方法一般以小写的set 后跟属性名来命名的。属姓名的首字母必须大写。其返回值类型一般为void——因为修改器只能改变属性值,所以无返回值类型。属性简单的修改器在其方法体中可能只有一个参数,该参数可以是任何类型。修改器有时候也可根据其前缀称为设置器(setters)。
相似的设计模式也应用于访问器方法的创建。访问器方法一般以小写的get 为前缀,后跟属性名来命名的。属性名的首字母必须大写。返回值类型必须与对应的修改器方法的参数类型匹配。属性简单的访问器在其方法体中不能接受任何参数。毋庸置疑访问其经常被称为获取器(getters)。
例如对Double类型的属性weight 的访问器方法体可能为:
public Double getWeight();
如果访问器返回一个逻辑值,会有一个变体模式。代替使用小写的 get,逻辑属性的访问器可以使用is ,前缀后跟属性名。属性名的首字母必须大写。返回值必须是一个逻辑值——不管是 boolean型 还是Boolean型。逻辑访问器在其方法体中不能接受任何参数。
例如,对On属性的布尔型访问器的方法体可能为:
public boolean isOn();
在使用JavaBean 时,规范的方法体标识扮演了极为重要的角色。其他组件可以使用Java 的反射API并且通过查找前缀为set,is,get的方法来发现JavaBean的属性。如果组件发现一个这样的JavaBean标识,那它就知道这个方法可以用来访问或者改变bean的属性。
Sun公司引入JavaBean是为GUI组件服务的,但是它们已经用在了Java开发的各个方面,甚至包括web应用。当Sun公司的工程师开发出JSP标签的扩展类时,也开始设计它们以和JavaBean一起运行。一个页面的动态数据可以使用JavaBean来进行传递,并且JSP标签可以用bean的属性来定制页面的输出。