1 什么是应用框架:
框架(framework)是可重用的,半成品的应用程序,可以用来产生专门的定制程序。象人一样,软件应用的相似性比不同点要多。它们运行在相似的机器上,期望从相同的设备输入信息,输出到相同的显示设备,并且将数据存储到相同的硬盘设备。开发传统桌面应用的开发人员更习惯于那些可以涵盖应用开发同一性的工具包和开发环境。构架在这些公共基础上的应用框架可以为开发人员提供可以为他们的产品提供可重用服务的基础架构。
框架向开发人员提供一系列具有以下特征的骨架组件:
1.已经知道它们在其它程序上工作得很好;
2.它们随时可以在下一个项目中使用;
3.它们可以被组织的其它团队使用;
对于框架是典型的构建还是购买命题。如果你自己构建它,在你完成时你就会理解它,但是在你被融入之前又将花费多长时间呢?如果要购买,你必须得克服学习曲线,同样,在你可以用它进行工作之前又得花多长时间?这里没有所谓正确答案,但许多观察者都会同意,象Struts这样的框架能提供比从头开始开发更显著的投资回报,特别是对于大型项目来说。
2 其它类型的框架:
框架的概念不仅用于应用程序也可用于组件。在其它的资料里面,我们也介绍了一些可以和Struts一起使用的框架。这些包括Lucene搜索引擎,Scaffold工具包,Struts验证器,以及Tiles标签库。与应用框架一样,这些工具也提供了一些半完成的版本,可以用在用户的定制组件之中。某些框架被限制于专门的开发环境中。Struts以及本文中涉及的组件却不是这样。你可以在很多环境中来开发Struts: Visual Age for Java, JBuilder, Eclipse, Emacs, 甚至使用Textpad。对于你的工具,如果你可以用来开发Java, 你就可以用它来开发Struts。
3 使用的技术:
使用Struts的应用开发使用了大量的其他基础技术。这些技术并不是专门针对Struts,而是所有Java web 应用都可以使用的。开发者使用Struts之类的框架是为了隐藏在诸如HTTP,CGI,以及JSP之类技术后面的繁琐的细节。作为一个Struts开发者,你并不需要知晓所有的相关知识,但是这些基本技术的工作原理可能有助于你针对棘手问题设计出创造性的方案。
3.1 超文本传输协议 (HTTP):
当两个国家之间进行调解时,外交官们总是遵循一定的正式协议。外交协议主要设计来避免误解,以及防止谈判破裂。同样,当计算机间需要对话,它们也遵循一个正式的协议。这个协议定义数据是如何传输,以及它们到达后如何进行解码。Web应用程序就是使用HTTP协议在运行浏览器的计算机和运行的服务器的程序间传输数据。
很多服务器应用程序使用HTTP之外的其他协议。他们在计算机之间维护一个持久性的连接。应用服务器可以清楚的知道是谁连接上来,而且何时中断连接。因为它们知道每一个连接的状态,以及每一个使用它的人。这称之为状态协议。
相反, HTTP是一个无状态协议。HTTP Server 可以接受来自于各种客户的各种请求,并提供各种响应,即使是这个响应仅仅是说No。没有大量的协商和连接持久性,无状态协议可以处理大量的请求。这也是Internet 可以扩展到很多计算机的原因。
HTTP 成为通用标准的原因是其简单性。HTTP请求看起来就像一个平常的文本文档。这使应用程序很容易创建HTTP请求。你甚至可以通过标准的程序如Telnet来手动传递一个HTTP请求。当HTTP响应返回时,它也是一个开发者可以直接阅读的平面文本。HTTP请求的第一行包含方法,其后是请求的来源地址和HTTP版本。HTTP请求头跟在首行后面,可以没有也可以有多个。HTTP头向服务器提供额外的信息。可以包括浏览器的种类和版本,可接受的文档类型,浏览器的cookies等等。7 种请求方法中, GET和 POST是用得最多的。
一旦服务器接收到请求,它就要产生一个HTTP响应。响应的第一行称为状态行,包含了HTTP协议的版本,数字型状态,以及状态的简短描述。状态行后,服务器将返回一个HTTP响应头,类似于HTTP请求头。如上所述,HTTP并不在请求间保持状态信息。服务器接受请求,发出响应,并且继续愉快地处理文本请求。
因为简单和效率,无状态协议不适合于需要跟踪用户状态的动态应用。Cookies和 URL 重写是两个在请求间跟踪用户状态的方式。cookie是一种特殊的信息包,存储于用户的计算机中。URL重写是在页面地址中存储一个特殊的标记,Java服务器可以用它来跟踪用户。这两种方法都不是无缝的,是用哪一个都意味着在开发时都要进行额外的工作。对其本身来说,标准的HTTP web服务器并不传输动态内容。它主要是使用请求来定位文件资源,并在响应中返回此资源。通常这里的文件使用Hypertext Markup Language (HTML) [W3C,HTML] 格式化,以使浏览器可以显示它们。HTML页面通常包含一些到其他页面的超文本连接,也可以显示其他一些内容比如图像和视频等等。用户点击连接将产生另一个请求,就开始一个新的处理过程。标准web服务器处理静态内容处理得很好,但处理动态内容时则需要额外的帮助手段了。
定义 静态内容直接来自于文本或数据文件,比如HTML或者 JPEG文件。这些文件可以随时改变,但通过浏览器请求时,却不能自动改变。相反,动态内容是临时产生的,典型地,它是针对浏览器的个别请求的响应。
3.2 公共网关接口(CGI):
第一个普遍用来产生动态内容的标准是通用网关接口(Common Gateway Interface (CGI))。CGI使用标准的操作系统特征,比如环境变量和标准输入输出,在Web服务器间以及和主机系统间创建桥接和网关。其他程序可以看到web server传递过来的请求,并创建一个定制的响应。当web服务器接收到一个对CGI程序的请求时,它便运行这个程序并向其提供它请求里面所包含的信息。CGI程序运行,并将输出返回给Web server,web server 则将输出响应给浏览器。CGI定义了一套关于什么信息将作为环境变量传递,以及它希望怎样使用标准输入和输出的惯例。与HTTP一样,CGI是灵活和易于实现的,并且已经有大量现成的CGI程序。
CGI的主要缺点是它必须为每个请求运行一个程序。这是一个相对昂贵的处理方法,对大容量站点来说,每分钟有数千个请求,有可能使站点瘫痪。CGI程序的另一个缺点是平台依赖性,一个平台上开发的程序不一定在另一个平台上能运行。
3.3 Java servlet:
Sun公司的Java Servlet平台直接解决了CGI程序的两个主要缺点:
首先,servlet 比常规CGI 程序提供更好的性能和资源利用。其次,一次编写,随处运行的JAVA特性意味着servlet在有JVM 的操作系统间是轻便的可移动的。Servlet看起来好像是一个微小的web server。它接受请求并产生响应。但,和常规web server不同,servlet API 是专门设计来帮助Java 开发人员创建动态应用的。
Servlet 本身是要编译成字节码的Java类,就像其他Java对象一样。Servlet访问HTTP 特定服务的API,但它仍然是一个运行于程序之中的Java 对象,并可以利用所有的Java 资产。为了使常规web servers能访问servlet,servlet被安插在一个容器之中。Servlet容器连接到Web服务器。每servlet 都可以声明它可以处理何种样式的URL。当符合所注册样式的请求到达,web server将请求传递给容器,容器则调用响应的servlet。但和CGI 程序不同,并不是针对每个请求都要创建一个新的servlet。一旦容器实例化了一个servlet,它就仅为每个新的请求创建一个新的线程。Java线程可比使用CGI程序的服务器处理开销小多了。
一旦servlet被创建,使用它处理额外的请求仅带来很小的额外开销。Servlet开发人员可以使用init() 方法保持对昂贵资源的引用,比如到数据库或者EJB Home接口的连接,以便它们可以在不同的请求之间进行共享。获得这些资源要耗费数秒时间,这比大多数冲浪者愿意等的时间要长些。
Servlet的另一个好处是,它是多线程的,servlet开发人员必须特别注意确保它们的servlet是线程安全的。学习servlet 编程,我们推荐Java Servlets by Example, 作者Alan R. Williamson[Williamson]。
3.4 JavaServer Pages:
虽然servlets对CGI程序来说前进了一大步,但它也不是万能灵药。为了产生响应,开发人员不得不使用大量的println语句来生成HTML。比如这样的代码:
out.println("<P>One line of HTML.</P>");
out.println("<P>Another line of HTML.</P>");
在产生HTTP响应的Servlet 中是很普遍的。也有一些库有助于你产生HTML。随着应用越来越复杂,Java开发人员将不再扮演HTML页面设计的角色。同时,大多数项目经理更喜欢将团队分成不同的小组。 它们喜欢HTML设计人员处理表现层的工作,而Java工程师则专注于业务逻辑。单独使用servlet的做法鼓励混合标记和业务逻辑,很难区分团队人员的专业工作。
为解决这个问题,Sun提出了一个将脚本和模板技术结合到一个组件中的服务器页面技术(JavaServer Pages)。为创建JSP页面, 开发者按创建HTML页面类似的方式创建页面,使用相同的HTML 语法。为将动态内容引入页面,开发人员可以将脚本元素置入页面之中。脚本元素是一些标记,封装了可以被JSP识别的逻辑。你可以在JSP页面中很容易的识别出脚本元素,他们被封装在一对<% 和 %>标记中。
为了识别JSP页面,文件需要保存为扩展名.jsp。当一个客户请求JSP页面时,容器将页面翻译成Java servlet 源代码文件,并将它编译成Java 类文件——就象你写的servlet文件一样。在运行时,容器也能检测JSP文件和相应的类的最后更新时间。如果,JSP 文件自上次编译以来被修改了,容器将重新翻译和编译JSP文件。项目经理现在可以将表现层分派给HTML 开发人员,将业务逻辑工作分派给JAVA开发人员。重要的是记住,JSP页面事实上是一个servlet。你可以在servlet做的,也可以在JSP中做。
3.5 JavaBean:
JavaBean是一种 Java类,它遵从一定的设计模式,使它们易于和其他开发工具和组件一起使用。
定义 JavaBean 是一种JAVA 语言写成的可重用组件。要编写JavaBean,类必须是具体类和公共类,并且具有无参数的构造器(NON-ARGS CONSTRUCTOR)。JavaBean通过提供符合一致性设计模式的公共访问方法将内部字段暴露称为属性。众所周知,属性名称也符合这种模式,其他JAVA 类可以通过自省机制发现和操作这些JavaBean 属性。
我们必须做的如下:
1.编写一个类,通过实现doStart()或者doEnd()方法来实现javax.servlet.jsp.tagext.TagSupport 或者javax.servlet.jsp.tagext.BodyTagSupport接口。这些方法获得一个JspWriter对象,你可以用它来输出你需要的HTML内容。
2.创建一个标签库描述文件(TLD)来将你的新建的类,映射到一个标签名称。
3.在你的Web 应用描述符(web.xml)中定义你的<taglib> 元素。通过在JSP 页面的顶部放置下面的语句:<%@tagliburi="/tags/app.tld prefix="app" %>来告诉JSP 页面你将使用你自己的标签库。
4.这个语句导入将在本页中使用的标签库,并分配给它一个前缀。关于更多细节,请参考JSP标签库技术页面。
JavaBean 设计模式提供两种类型的方式来访问bean 的内部状态:访问器(accessor) 用来读JavaBean的状态,修改器(mutator )用来改变 JavaBean 的状态。
Mutator 通常以小写的set 前缀开始,后跟属性名。属性名的第一个字母必须大写。返回值通常是void,因为mutator 仅仅改变属性的值,而不返回它们。简单属性的mutator在其方法体中可能只有一个参数,该参数可以是各种类型。Mutator也可根据其前缀称为设置器setters 。例如,对Double 类型的属性weight 的mutator方法体可能是:
public void setWeight(Double weight)
相似的设计模式也用于访问器方法的创建。Accessor 通常以小写的get 为前缀,后跟属性名。属性名的第一个字母必须大写。返回值必须匹配相应的修改器方法的参数。简单属性的Accessor在其方法体中不能接受参数。同样,访问器accessor 也经常称为获取器getter。
属性weight 的访问器方法体可能是:public Double getWeight()
如果访问器返回一个逻辑值,这种情况下有个变体模式。不使用小写的 get,逻辑属性的访问器可以使用小写的is 前缀,后跟属性名。属性名的首字母必须大写。返回值肯定是逻辑值,不管是 boolean 还是Boolean。逻辑访问器在其方法体中不能接受参数。On属性的逻辑访问器的方法体可能是:public boolean isOn()
在使用JavaBean 时,规范的方法体签名扮演了极为重要的角色。其他组件可以使用Java 的反射API 通过查找前缀为set、is或者get的方法来发现JavaBean的属性。如果一个组件在一个JavaBean 中发现一个这样的方法,它就知道这个方法可以用来访问或者改变JavaBean 的属性。Sun引入JavaBean是为了用于GUI组件,但它们已经用在Java开发的各个方面,包括Web应用。Sun的工程师在开发JSP标签的扩展类时,也被设计来可以和JavaBean一起工作。一个页面的动态数据可以使用一个JavaBean来传递,并且JSP标记可以随后使用bean的属性来定制页面的输出。
Model 2:
Servlet/JSP规范的0.92 版描述了在一个应用中使用servlet和JSP的架构。在其后的规范中,Model 2 这个叫法消失了,但它已经在Java web开发人员中非常通用了。根据Model 2,servlet处理数据存取和导航流,JSP处理表现。Model 2使Java工程师和HTML设计者分别工作于它们所擅长和负责的部分。Model 2应用的一部分发生改变并不强求其他部分也跟着发生改变。HTML开发人员可以改变程序的外观和感觉,并不需要改变后端servlet的工作方式。Struts框架是基于Model 2的架构。它提供一个控制器servlet来处理导航流和一些特殊类来帮助数据访问。随框架也提供一个丰富的标签库,以使Struts易于和JSP一起使用。
4 小结:
在本文中,我们介绍了Struts应用框架。并介绍了一些基本知识,关于HTTP, CGI, Java servlet, JSP,以及JavaBean。我们也说明了Model 2应用架构,以及它如何用来将servlets和JSP 在结合在同一个应用之中。现在你已经有关于Strtus Web应用程序模样的初步印象,以后我们将更深入的讨论Strtuts框架的理论和具体实践。