WEB开发框架解析——Java Web(三)

 

1、什么是Struts 框架

Struts名字来源于在建筑与旧式飞机中使用的支持金属架,它是由自定义标签、信息资源(message resources)、Servlet和JSP组成的一个可重用的MVC2模式的框架。以Struts1.0为例,它的结构图如图5-11所示。

从图5-11可以看出,Struts的体系结构采用了MVC设计模式,同时包含客户端(Client)请求以及业务逻辑处理(Business Logic),而MVC设计模式主要由模型(Model)、视图(View)和控制器(Controller)三部分组成

下面将分别对这些模块进行介绍。

(1)客户端(Client)

一方面可以通过浏览器发送HTTP请求,另一方面可以把接收到的HTTP响应消息在浏览器上展现出来。

(2)控制器(Controller)

控制器主要包括ActionServlet类和RequestProcesor类。其中,ActionServlet类是MVC实现的控制器部分,是整个框架的核心部分,它用来接收用户的请求,并根据用户的请求从模型模块中获取用户所需的数据,然后选择合适的视图来响应用户的请求。它采用了命令设计模式来实现这个功能:通过struts-config.xml配置文件来确定处理请求的Action类。在处理用户请求时,关于请求的处理大部分已交由RequestProcesor.process()方法来处理。RequestProcessor类的processs()方法采用了模板的设计模式(按照处理的步骤与流程顺序的调用了一系列的方法)。处理的主要流程为:

1)processPath(request,response)。

根据URI(Uniform Resource Identifier,统一资源标识符,用来唯一的标识一个资源)来得到ActionMapping元素的路径。

2)processMapping(request,response)。

根据路径信息找到ActionMapping对象。

3)processRoles(request,respose,mapping)。

Struts为Web应用提供了一种认证机制,当用户登录时,会通过processRoles方法调用requestisUserInRole()方法来检查这个用户是否有权限来执行给定的ActionMapping

4)processValidate(request,response,form,mapping)。

调用ActionFormvalidate()方法。

5)processActionCreate(request,response,mapping)。

这个方法从<action>的type属性得到Action类名,并创建返回它的实例。

6)processActionPerform(req,res,action,form,mapping)。

这个方法调用Action类的execute()方法,其中execute()方法中包含了业务逻辑的实现。需要注意的是,Action类并不是线程安全的。

(3)业务逻辑(Business Logic)

Servlet在接收到请求后会根据配置文件中的对应关系,把请求转给指定的Action类来处理,Action类采用适配器设计模式,它只是对业务逻辑进行了包装(真正的业务逻辑是由EJBsession bean 或普通的Java类来实现)。

(4)模型(Model)

在Struts体系结构中,模型分为两个部分:系统的内部状态和可以改变状态的操作(业务逻辑)。内部状态通常由一组Action form Bean表示,ActionForm封装了HTTP请求的数据的类或对象。ActionForm是一个抽象类,每一个输入表单都对应着它的一个子类。配置文件struts-config.xml中保存了HTTP请求表单与具体ActionForm类的映射关系。

(5)视图(View)

视图就是一个JSP文件,该JSP文件中没有业务逻辑的处理,也不保存系统的状态信息,它通过一些标签把数据以浏览器能识别的方式展现出来。目前,标签库主要有Bean Tags、HTMLtags、Logic Tags、Nested Tags 以及Template Tags等。
Struts框架作为一项开放源码项目,优点众多,具体而言,主要有如下几点:

1)采用了MVC设计模式

由于采用了MVC模式,因此它实现了表现与逻辑的分离,使得系统有较好的可扩展性。同时Struts的标记库(Taglib)包含了大量的tag,有助于提高系统的开发效率。

2)提供了页面导航功能,使系统的脉络更加清晰。

通过一个配置文件建立整个系统各部分之间的联系,使有系统结构变得更加清晰,从而增强了系统的可扩展性与可维护性。

3)提供了表单的验证功能,进一步增强了系统的健壮性。

4)提供了数据库连接池管理。

5)提供了Exception处理机制。

6)支持国际化。

当然,Struts也有它的不足之处,主要有以下几点:

1)Taglib中包含了大量的tag,对于初学者而言,开发难度比较大。

2)Struts开发中包含了许多XML格式的配置文件。

一方面,这些配置文件不易调试;另一方面,大量的XML文件也不便于管理。

3)Struts只能支持Web应用程序的开发。

4)Struts的Action不是线程安全的,因此Action类用到的所有资源都必须进行同步。

5)单元测试不方便。

由于Action与Web层的紧耦合,导致其非常依赖于Web容器,给单元测试带来了不便。

6)部署烦琐。

当转到表示层时,需要配置forward,例如,如果有10个表示层的JSP文件,则需要配置10个Struts。此外,当目录、文件变更后,需要重新修改forward,而且每次修改配置之后,还需要重新部署整个项目,对于Tomcate等服务器,还必须重启服务器。

7)对Servlet的依赖性过强。

Struts处理Action时必需要依赖ServletRequest和ServletResponse,摆脱不了对Servlet容器的依赖。
 

2、Struts 框架响应客户请求的工作流程是什么

在Struts框架中,控制器主要是ActionServlet,但是对业务逻辑的操作则主要由Action、ActionMapping,ActionForward等组件协调完成。其中,Action扮演了真正的控制逻辑实现者的角色,而ActionMappingActionForward则指定了不同业务逻辑或流程的运行方向。

对于采用Struts框架的Web应用而言,在Web应用启动时,会加载并初始化ActionServlet,ActionServletstruts-config.xml文件中读取配置信息,并把它们存放到ActionMappings对象中。具体而言,当ActionServlet接收到一个客户请求时,执行如下流程:

1)检索和用户请求匹配的ActionMapping实例,如果不存在,就返回用户请求路径无效的信息。

2)如果ActionForm实例不存在,就创建一个ActionForm对象,把客户提交的表单数据保存到ActionForm对象中。

3)根据配置信息决定是否需要表单验证。如果需要验证,就调用ActionForm的validate()方法。

4)如果ActionForm的validate()方法返回null 或返回一个不包含ActionMessgeActionErrors对象,就表示表单验证成功。

5)ActionServlet 根据ActionMapping实例包含的映射信息决定将请求转发给哪个Action。如果对应的Action实例不存在,就先创建一个实例,然后调用Action的execute()方法。

6)Action的execute()方法返回一个ActionForward对象,ActionServlet再把客户请求转发给ActionForward对象指向的JSP组件。

7)ActionForward对象指向的JSP组件生成动态页面,返回给客户。

对于以上流程中的步骤4),如果ActionForm的validate()方法返回一个(包含一个)或多个ActionMessage的ActionErrors对象,就表示表单验证失败,此时,ActionServlet将直接把请求转发给包含客户提交表单的JSP组件。在这种情况下,不会再创建Action对象并调用Action的execute方法了。


3、Struts框架的数据验证可分为几种类型

数据验证也称为输入校验,用于指导对用户的输入进行基本的过滤,包括必填的字段(字段必须为数字)以及两次输入的密码必须一致等。Struts框架提供了现成的、易于使用的数据验证功能。

具体而言,数据验证可以分为两种类型表单验证与业务逻辑验证。其中,表单验证由ActionForm Bean处理,例如,如果用户没有在表单中输入姓名就提交表单,将生成表单验证错误。该方式重写ActionForm的validate()方法,在该方法内对所有字段进行基本的校验。若出现不符合要求的输出,则将错误提示封装在ActionError对象里,最后将多个ActionError组合成ActionErrors对象,因此ActionErrors对象中封装了所有出错信息。

业务逻辑验证由Action处理,如果用户在表单中输入的姓名为“Hehao”,那么按照本应用的业务规则,不允许输入“Hehao”,因此将生成业务逻辑错误。需要注意的是,在Action里面完成数据验证,实际上就是在execute()方法前面增加数据验证的部分代码。


4、Form Bean的表单验证流程是什么

Form Bean的表单验证主要有以下4个步骤:

1)用户提交HTML表单后,Struts框架会自动把表单数据组装到ActionForm Bean中。

2)Struts框架调用ActionForm Bean的validate()方法进行表单验证。

3)如果validate()方法返回的ActionErrors 对象为null,或者不包含任何ActionMessage对象,就表示没有错误,数据验证通过。

4)如果ActionErrors中包含ActionMessage对象,就表示发生了验证错误,Struts框架会把ActionErrors 对象保存到request范围内,然后把请求转发到恰当的视图组件中,视图组件通过<html:errors>标签把request 范围内的ActionErrors对象中包含的错误消息显示出来,提示用户修改错误。


5、在Struts配置文件中,<action>元素包含哪些属性和子元素

 

6、ActionForm Bean的作用有哪些

Action一般用于控制业务逻辑的处理,例如增加、删除、修改、查询等,ActionForm Bean用于封装用户请求的参数。当接收到页面输入的数据后,会首先保存在ActionForm Bean中,然后在Action里面调用逻辑层的代码来处理这些数据。
ActionForm Bean的作用有如下3点:

1)ActionForm Bean 本质上也是一种JavaBean,是专门用来传递表单数据的数据传递对象(DATA Transfer Object,DTO)。除了具有一些JavaBean的常规方法外,ActionForm Bean还包含一些特殊的方法,例如用于验证HTML表单的数据以及将其属性重新设置为默认值。

2)Struts框架利用ActionForm Bean来进行View组件和Controller组件之间表单数据的传递。

3)Struts框架把View组件接收到的用户输入的表单数据保存在ActionForm Bean中,然后把它传递给Controller组件,Controller组件可以对ActionForm Bean中的数据进行修改,JSP文件使用Struts标签读取修改后的ActionForm Bean的信息,重新设置HTML表单。


7、ActionForm的执行步骤有哪些

ActionForm的执行步骤有以下几点:

1)检查Action的映射,确定Action中是否已经配置了对ActionForm的映射。

2)根据name属性查找Form Bean的配置信息。

3)检查Action的Form Bean的使用范围,确定在此范围下是否已经有此Form Bean的实例。假如当前范围下已经存在此FormBean的实例,而且对当前请求来说,是同一种类型的话,那么就重用。否则,就重新构建一个Form Bean的实例。

4)Form Bean的reset()方法被调用。

5)调用对应的setter()方法,对状态属性赋值。

6)根据validate的属性选择调用方法。如果validate的属性被设置为true,那么就调用Form Bean的validate()方法。如果validate()方法没有返回任何错误,控制器将ActionForm作为参数传递给Action实例的execute()方法并执行。
 

8、forward 与global-forward 有什么区别

forward的主要作用是根据Action返回的值找到对应的JSP页面global-forward是全局的forward,当多个Action 返回同一个值时,例如在分页时或者得到数据列表时可将这个forward元素写在global-forward中,这样就不用每次都在Action 里面配置forward了。

以下示例给出了二者的使用区别:

9、Struts如何实现国际化

国际化(internationalization,简称il8n,其意为internationalization的首末字符i和n之间有18个字符)与本地化(localization,简称110n,其意为localization的首末字符1和n之间有10个字符)是指让产品(例如出版物、软件、硬件等)能够适应非本地环境,特别是其他语言与文化。具体而言,就是要求程序在不修改内部代码的情况下,能根据不同语言以及地区显示相应的界面。国际化资源文件是指用不同国家的语言描述相同的信息,并放在各自对应的
.properties属性文件中,程序根据运行时的环境决定到底加载哪个文件。

Struts提供了对国际化的支持。使用国际化功能也非常简单,主要是先准备各语言的资源文件,在资源文件中定义键和对应的字符串,然后在显示的地方指定键就可以了,例如,在实现国际化时需要在JSP文件中加入Struts的bean标记库<%@taglib uri="/WEB-INF/struts-bean.tld"prefix="bean"%>,如下例所示。

接下来需要创建一个资源文件ApplicationResource.properties,文件中的内容如下:

如果想把英文显示转换为中文,那么需要先创建一个临时的中文资源文件ApplicationRe-source_temp.properites,例如,page.wel=欢迎,接着对临时中文资源文件进行编码转换。可以使用myeclipse的插件,也可以在命令行模式下执行如下命令:

最后,把资源文件ApplicationResource_zh_CN.properties 添加到相应的struts-config.xml配置文件中即可。


10、Struts 1与Struts 2有哪些区别

Strut 1框架由ActionForm和JavaBean组成,其中ActionForm用于封装用户的请求参数,封装成ActionForm对象,该对象被ActionServlet 转发给Action,Action 根据ActionFrom里面的请求参数处理用户的请求。Struts2框架的基础是核心控制器FilterDispatcher,它包含了框架内部的控制流程和处理机制。业务控制器Action和业务逻辑组件是需要用户自己来实现的。开发人员在开发Action和业务逻辑组件的同时,还需要编写相关的配置文件,以供核心控制器FilterDispatcher来使用。

Struts 1与Struts2都是MVC的Web框架,尽管二者都叫Struts,但也存在着很多不一致的地方。具体而言,主要表现在以下方面:

1)风险控制方面。

Struts1是老牌框架,应用广泛,有很好的群众基础,开发风险很小,成本更低。Struts2虽然基于Struct1,但是相对不成熟,而且未知的风险和变化很多,受众并不多。所以,使用Struts2开发项目的风险更大,成本更高。

2)Action 实现类方面。

Struts1要求Action类继承一个抽象基类,而Struts2中Action类既可以实现一个Action接口,也可以实现其他接口,使可选和定制的服务成为可能。同时,Struts 2提供了一个ActionSupport基类去实现常用的接口。

3)线程模式方面。

Struts 1Action是单例模式并且必须是线程安全的,因为仅有Action的一个实例来处理所有请求。而Struts 2Action对象为每一个请求产生一个实例,因此不存在线程安全的问题。

4)Servlet 依赖方面。

Struts 1Action依赖于Servlet API,因为Struts 1Action的execute()方法中有HttpServletRequest和HttpServletResponse方法。Struts 2Action不再依赖于Servlet API,因为Struts2的Action是由POJ0(Plain Old Java Objects,简单的Java对象)组成,在Struts2中,Servlet上下文以简单Map的形式表现出来,这使得Action可以进行独立的测试,当然,如果Action需要直接访问HttpServletRequest和HttpServletResponse参数,Struts 2Action仍然可以访问它们。但是,大部分时候,Action都无需直接访问HttpServetRequest和HtpServletResponse,从而给了开发人员更多选择。

5)可测性方面。

测试Struts1Action的一个主要问题是execute()方法依赖于Servlet API,这使得Action的测试要依赖于Web容器。为了脱离Web容器测试Struts1的Action,必须借助于第三方扩展:Struts TestCase,该扩展包包含了系列的Mock对象(模拟了HttpServetRequest和HttpServletResponse对象),从而可以脱离Web容器测试Struts1的Action类。Struts 2 Action可以通过初始化、设置属性、调用方法来测试。

6)封装请求参数。

Struts 1使用ActionForm对象封装用户的请求参数,所有ActionForm必须继承一个基类——ActionForm。普通的JavaBean不能用作ActionForm,因此,开发人员必须创建大量的ActionForm类封装用户请求参数。虽然Struts1提供了动态ActionForm来简化ActionForm的开发,但依然需要在配置文件中定义ActionForm。而 Struts2直接使用Action属性来封装用户请求属性,避免了开发人员需要大量开发ActionForm类的烦琐。实际上,这些属性还可以是包含子属性的Rich对象类型。如果开发人员依然“怀念”Struts 1ActionForm的模式,Struts2提供了ModelDriven模式,可以让开发人员使用单独的Model对象来封装用户请求参数。但该Model对象无需继承任何Struts2基类,是一个POJ0,从而降低了代码污染。

7)表达式语言方面。

Struts1整合了JSP标准标签库(JSPStandard Tag Library,JSTL),因此可以使用JSTL表达式语言。Struts2可以使用JSTL,但它整合了一种更强大和灵活的表达式语言——对象图的符号语言(Object Graph Notation Language,OGNL),因此,Struts2下的表达式语言功能更加强大。

8)绑定值到视图。

Struts1使用标准JSP机制把对象绑定到视图页面,而Struts2使用“ValueStack”技术,使标签库能够访问值,而不需要把对象和视图页面绑定在一起。

9)类型转换。

Struts 1ActionForm 属性通常都是String类型。Struts1使用Commons-Bea-nutils进行类型转换,每个类一个转换器,转换器是不可配置的;Struts2使用OGNL进行类型转换,支持基本数据类型和常用对象之间的转换。

10)数据校验。

Struts1与Stut2都支持通过validate()方法的手动验证,不同的是,Struts1支持在ActionForm重写validate()方法中手动校验,或者通过整合Commons alidator 框架来完成数据校验,而Struts2支持通过重写validate()方法进行校验,也支持整合XWork校验框架进行校验。

11)Action执行控制。

Struts1支持每一个模块对应一个请求处理(即生命周期的概念),但是模块中的所有Action必须共享相同的生命周期。Struts2支持通过拦截器堆栈(Interceptor Stacks)为每一个Action创建不同的生命周期。开发人员可以根据需要创建相应堆栈,以便和不同的Action一起使用。

12)捕获输入。

Struts1使用ActionForm对象捕获输入,所有ActionForm必须继承自一个框架依赖的基类。因为其他JavaBean不能用作ActionForm,开发人员经常创建多余的类捕获输入。而Struts2直接使用Action属性作为输入属性,消除了对第二个输人对象的需求。


11、什么是loC

控制反转(Inverse of Control,1oC)有时也被称为依赖注入,是一种降低对象之间耦合关系的设计思想。一般而言,在分层体系结构中,都是上层调用下层的接口,上层依赖于下层的执行,即调用者依赖于被调用者。而通过loC方式,使得上层不再依赖于下层的接口,即通过采用一定的机制来选择不同的下层实现,完成控制反转,使得由调用者来决定被调用者。IoC通过注入一个实例化的对象来达到解耦和的目的。使用这种方法后,对象不会被显式地调用,而是根据需求通过IoC容器(例如Spring)来提供。

采用IoC机制能够提高系统的可扩展性,如果对象之间通过显式调用进行交互会导致调用者与被调用者存在着非常紧密的联系,其中一方的改动将会导致程序出现很大的改动,例如,要为一家卖茶的商店提供一套管理系统,在这家商店刚开业时只卖绿茶(GreenTea),随着规模的扩大或者根据具体销售量,未来可能会随时改变茶的类型,例如红茶(BlackTea)等,传统的实现方法会针对茶抽象化一个基类,绿茶类只需要继承自该基类即可,如图5-12所示。
 

采用该实现方法后,在需要使用GreenTea时只需要执行以下代码即可:AbstractTeat=new GreenTea(),当然,这种方法是可以满足当前设计要求的。但是该方法的可扩展性不好,存在着不恰当的地方,例如,商家发现绿茶的销售并不好,决定开始销售红茶(Black Tea)时,那么只需要实现一个BlackTea类,并且让这个类继承自AbstractTea即可。但是,系统中所有用到AbstractTea t=new GreenTea()的地方都需要被改为AbstractTeat=new BlackTea(),而这种创建对象实例的方法往往会导致程序的改动量非常大。

那么怎样才能增强系统的可扩展性呢?——设计模式,此时可以使用设计模式中的工厂模式来把创建对象的行为包装起来,实现方法如图5-13所示。

通过以上方法,可以把创建对象的过程委托给TeaFatory来完成,在需要使用Tea对象时只需要调用Factory类的getTea方法即可,具体创建对象的逻辑在TeaFactory中来实现,那么当商家需要把绿茶替换为红茶时,系统中只需要改动TeaFactory中创建对象的逻辑即可,采用了工厂模式后,只需要在一个地方做改动就可以满足要求,这样就增强了系统的可扩展性。

虽然说采用工厂设计模式后增强了系统的可扩展性,但是从本质上来讲,工厂模式只不过是把程序中会变动的逻辑移动到工厂类里面了,当系统中的类较多时,在系统扩展时需要经常改动工厂类中的代码。而采用IoC设计思想后,程序将会有更好的可扩展性,下面主要介绍Spring框架在采用IoC后的实现方法,如图5-14所示。

Spring容器将会根据配置文件来创建调用者对象(Sale),同时把被调用的对象(AbstractTea的子类)的实例化对象通过构造函数或set()方法的形式注入到调用者对象中。

首先,创建名为SpringConfig.xml的文件。

当Spring容器创建Sale对象时,根据配置文件SpringConfig.xml就会创建一个BlueTea的件,而不需要修改代码。

在需要Sale时,可以通过如下方式来创建Sale对象:

上例中,Spring采用loC的方式来实现把实例化的对象注入到开发人员自定义的对象中,具有较强的可扩展性。
具体而言,IoC主要有以下两个方面的优点:

1)通过IoC容器,开发人员不需要关注对象如何被创建的,同时增加新类也非常方便,只需要修改配置文件即可实现对象的“热插拔”。

2)loC容器可以通过配置文件来确定需要注入的实例化对象,因此非常便于进行单元测试。

尽管如此,IoC也有自身的缺点,具体表现为以下两点:

1)对象是通过反射机制实例化出来的,因此会对系统的性能有一定的影响。

2)创建对象的流程变得比较复杂。


12、什么是AOP

面向切面编程(Aspect-Oriented Programming,AOP)是对面向对象开发的一种补充,它允许开发人员在不改变原来模型的基础上动态地修改模型以满足新的需求,例如,开发人员可以在不改变原来业务逻辑模型的基础上可以动态地增加日志、安全或异常处理的功能。

下面介绍一个在Spring中使用AOP编程的简单例子。

13、什么是Spring框架

Spring是一个J2EE的框架,这个框架提供了对轻量级IoC的良好支持,同时也提供了对AOP技术非常好的封装。相比其他框架,Spring框架的设计更加模块化,框架内的每个模块都能完成特定的工作,而且各个模块可以独立地运行,不会相互牵制。因此,在使用Spring框架时,开发人员可以使用整个框架,也可以只使用框架内的一部分模块,例如可以只使用Spring AOP模块来实现日志管理功能,而不需要使用其他模块。

Spring框架主要由7个模块组成,它们分别是Spring AOP、Spring ORM、Spring DA0、Spring Web、Spring Context、Spring Web MVC、Spring Core等。Spring框架图如图5-16所示。

表5-7详细介绍了各个模块的作用。

Spring在J2EE中到底扮演着怎样的角色?在哪些地方可以使用Spring?

Spring的工作原理如图5-17所示,可以看出,Spring有着非常广泛的用途,不仅可以在Web容器中用来管理Web服务器端的模块,例如Servlet,还可以用来管理用于访问数据库的Hibernate。由于Spring在管理Business Object(业务对象)和DAO时使用了IoC和AOP的思想,因此这些被Spring管理的对象都可以脱离EJB容器单独运行和测试。在需要被Spring容器管理时,只需要增加配置文件,Spring框架就会根据配置文件与相应的机制实现对这些对象的管理。

除此之外,使用Spring还有如下好处:

1)在使用J2EE开发多层应用程序时,Spring有效地管理了中间层的代码,由于Spring采用了控制反转和面向切面编程的思想,因此这些代码非常容易进行单独测试。

2)使用Spring有助于开发人员培养一个良好的编程习惯:面向接口编程而不是面向类编程。面向接口编程使得程序有更好的可扩展性。

3)Spring对数据的存取提供了一个一致的框架(不论是使用JDBC还是0/R映射的框架,例如Hibernate或JDO)。

4)Spring通过支持不同的事务处理API(如JTA、JDBC、Hibernate等)的方法对事务的管理提供了一致的抽象方法。

5)使用Spring框架编写的大部分业务对象不需要依赖Spring。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  详细 X
  没有英汉互译结果
   请尝试网页搜索
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值