免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1266 | 回复: 0
打印 上一主题 下一主题

Jakarta Struts应用的七个经验 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2005-03-18 14:31 |只看该作者 |倒序浏览
编者按:本文叙述了作者在运用Struts过程中来之不易的若干经验和心得。如果你是jsp和servlet开发Web应用的Java程序员,并且也正在考虑采用基于Struts的构建方法的话,那么你会在这里发现很多颇有见地同时也很有价值的信息。
[color="#ac0000"]1. 只在必要的时候才考虑扩展Struts框架
 
 一个好的framework有很多优点,首先,它必须能够满足用户的可预见的需求。为此 Struts为Web
应用提供了一个通用的架构,这样开发人员可以把精力集中在如何解决实际业务问题上。其次,一个好的framework还必须能够在适当的地方提供扩展接
口,以便应用程序能扩展该框架来更好的适应使用者的实际需要。
  如果Struts
framework在任何场合,任何项目中都能很好的满足需求,那真是太棒了。但是实际上,没有一个框架声称能做到这一点。一定会有一些特定的应用需求是
框架的开发者们无法预见到的。因此,最好的办法就是提供足够的扩展接口,使得开发工程师能够调整struts来更好的符合他们的特殊要求。
  在Struts framework中有很多地方可供扩展和定制。几乎所有的配置类都能被替换为某个用户定制的版本,这只要简单的修改一下Struts的配置文件就可以做到。
 
 其他组件如ActionServlet和 RequestProcessor 也能用自定义的版本代替. 甚至连Struts
1.1里才有的新特性也是按照扩展的原则来设计的。例如,在异常处理机制中就允许用户定制异常处理的句柄,以便更好的对应用系统发生的错误做出响应。
 
 作为框架的这种可调整特性在它更适合你的应用的同时也在很大的程度上影响了项目开发的效果。首先,由于您的应用是基于一个现有的成熟的、稳定的
framework如Struts,测试过程中发现的错误数量将会大大减少,同时也能缩短开发时间和减少资源的投入。因为你不再需要投入开发力量用于编写
基础框架的代码了。
  然而, 实现更多的功能是要花费更大的代价的。我们必须小心避免不必要的滥用扩展性能,
Struts是由核心包加上很多工具包构成的,它们已经提供了很多已经实现的功能。因此不要盲目的扩展Struts框架,要先确定能不能采用其他方法使用
现有的功能来实现。 在决定编写扩展代码前务必要确认Struts的确没有实现你要的功能。否则重复的功能会导致混乱将来还得花费额外的精力清除它。
  [color="#ac0000"]2. 使用异常处理声明
  要定义应用程序的逻辑流程,成熟的经验是推荐在代码之外,用配置的方法来实现,而不是写死在程序代码中的。在J2EE中,这样的例子比比皆是。从实现EJB的安全性和事务性行为到描述JMS消息和目的地之间的关系,很多运行时的处理流程都是可以在程序之外定义的。
 
 Struts
创建者从一开始就采用这种方法,通过配置Struts的配置文件来定制应用系统运行时的各个方面。这一点在版本1.1的新特性上得到延续,包括新的异常处
理功能。在Struts
framework以前的版本中,开发人员不得不自己处理Struts应用中发生的错误情况。在最新的版本中,情况大大的改观了,Struts
Framework提供了内置的一个称为 ExceptionHandler 的类,
用于系统缺省处理action类运行中产生的错误。这也是在上一个技巧中我们提到的framework许多可扩展接口之一。
  
Struts缺省的
ExceptionHandler类会生成一个ActionError对象并保存在适当的范围(scope)对象中。这样就允许JSP页面使用错误类来提
醒用户出现什么问题。如果你认为这不能满足你的需求,那么可以很方便的实现你自己的ExcepionHandler类。
  具体定制异常处理的方法和机制
 
 要定制自己的异常处理机制,第一步是继承org.apache.struts.action.ExceptionHandler类。这个类有2个方法可
以覆盖,一个是excute()另外一个是storeException().
在多数情况下,只需要覆盖其中的excute()方法。下面是ExceptionHandler类的excute()方法声明:

  正如你看到的,该方法有好几个参数,其中包括原始的异常。方法返回一个ActionForward对象,用于异常处理结束后将controller类带到请求必须转发的地方去。
 
 当然您可以实现任何处理,但一般而言,我们必须检查抛出的异常,并针对该类型的异常进行特定的处理。缺省的,系统的异常处理功能是创建一个出错信息,同
时把请求转发到配置文件中指定的地方去。
定制异常处理的一个常见的例子是处理嵌套异常。假设该异常包含有嵌套异常,这些嵌套异常又包含了其他异常,因此我们必须覆盖原来的execute()方
法,对每个异常编写出错信息。
  一旦你创建了自己的ExceptionHandler 类,就应该在Struts配置文件中的部分声明这个类,以便让Struts知道改用你自定义的异常处理取代缺省的异常处理.
  可以配置你自己的ExceptionHandler 类是用于Action Mapping特定的部分还是所有的Action对象。如果是用于Action Mapping特定的部分就在元素中配置。如果想让这个类可用于所有的Action对象,可以在 元素中指定。例如,假设我们创建了异常处理类CustomizedExceptionHandler用于所有的Action类, 元素定义如下所示:

  在元素中可以对很多属性进行设置。在本文中,最重要的属性莫过于handler
属性, handler属性的值就是自定义的继承了ExceptionHandler类的子类的全名。
假如该属性没有定义,Struts会采用自己的缺省值。当然,其他的属性也很重要,但如果想覆盖缺省的异常处理的话,handler无疑是最重要的属性。
 
 最后必须指出的一点是,你可以有不同的异常处理类来处理不同的异常。在上面的例子中,CustomizedExceptionHandler用来处理任
何java.lang.Exception的子类.
其实,你也可以定义多个异常处理类,每一个专门处理不同的异常树。下面的XML片断解释了如何配置以实现这一点。

  在这里,一旦有异常抛出,struts
framework将试图在配置文件中找到ExceptionHandler,如果没有找到,那么struts将沿着该异常的父类链一层层往上找直到发现
匹配的为止。因此,我们可以定义一个层次型的异常处理关系结构,在配置文件中已经体现了这一点。
[color="#ac0000"]3. 使用应用模块(Application Modules)
 
 Struts
1.1的一个新特性是应用模块的概念。应用模块允许将单个Struts应用划分成几个模块,每个模块有自己的Struts配置文件,JSP页面,
Action等等。这个新特性是为了解决大中型的开发队伍抱怨最多的一个问题,即为了更好的支持并行开发允许多个配置文件而不是单个配置文件。
  注:在早期的beta版本中,该特性被称为子应用(sub-applications),最近的改名目的是为了更多地反映它们在逻辑上的分工。
 
 显然,当很多开发人员一起参加一个项目时,单个的Struts配置文件很容易引起资源冲突。应用模块允许Struts按照功能要求进行划分,许多情况已
经证明这样更贴近实际。例如,假设我们要开发一个典型的商店应用程序。可以将组成部分划分成模块比如catalog(商品目录),
customer(顾客), customer service(顾客服务),
order(订单)等。每个模块可以分布到不同的目录下,这样各部分的资源很容易定位,有助于开发和部署。图1 显示了该应用的目录结构。

图 1. 一个典型的商店应用程序的目录结构
  注:如果你无需将项目划分成多个模块,Struts框架支持一个缺省的应用模块。这就使得应用程序也可以在1.0版本下创建,具有可移植性,因为应用程序会自动作为缺省的应用模块。
  为了使用多应用模块功能,必须执行以下几个准备步骤:
  · 为每个应用模块创建独立的Struts配置文件。
  · 配置Web 部署描述符 Web.xml文件。
  · 使用org.apache.struts.actions.SwitchAction 来实现程序在模块之间的跳转.
  创建独立的Struts配置文件
  每个Struts应用模块必须拥有自己的配置文件。允许创建自己的独立于其他模块的Action,ActionForm,异常处理甚至更多。
 
 继续以上面的商店应用程序为例,我们可以创建以下的配置文件:一个文件名为struts-config-catalog.xml,包含catalog
(商品目录)、items(商品清单)、和其它与库存相关的功能的配置信息;另一个文件名为struts- config-order.xml,
包含对order(订单)和order
tracking(订单跟踪)的设置。第三个配置文件是struts-config.xml,其中含有属于缺省的应用模块中的一般性的功能。
  配置Web部署描述符
  在Struts的早期版本中,我们在Web.xml中指定Struts配置文件的路径。好在这点没变,有助于向后兼容。但对于多个应用模块,我们需要在Web部署描述符中增加新的配置文件的设定。
  对于缺省的应用(包括Struts的早期版本),Struts framework 在Web.xml文件中查找带有config的元素,用于载入Action mapping 和其它的应用程序设定。作为例子,以下的XML片断展现一个典型的元素:

  注:如果在现有的元素中找不到"config"关键字,Struts framework将缺省地使用/WEB/struts-config.xml
  为了支持多个应用模块(Struts 1.1的新特性),必须增加附加的元素。与缺省的元素不同的是,附加的元素与每个应用模块对应,必须以config/xxx的形式命名,其中字符串xxx代表该模块唯一的名字。例如,在商店应用程序的例子中,元素可定义如下(注意粗体字部分):

  第一个 元素对应缺省的应用模块。第二和第三个元素分别代表非缺省应用模块catalog 和 order。
 
 当Struts载入应用程序时,它首先载入缺省应用模块的配置文件。然后查找带有字符串config/xxx
形式的附加的初始化参数。对每个附加的配置文件也进行解析并载入内存。这一步完成后,用户就可以很随意地用config/后面的字符串也就是名字来调用相
应的应用模块。
  多个应用模块之间调用Action类
  在为每个应用模块创建独立的配置文件之后,我
们就有可能需要调用不同的模块中Action。为此必须使用Struts框架提供的SwitchAction类。Struts
会自动将应用模块的名字添加到URL,就如Struts
自动添加应用程序的名字加到URL一样。应用模块是对框架的一个新的扩充,有助于进行并行的团队开发。如果你的团队很小那就没必要用到这个特性,不必进行
模块化。当然,就算是只有一个模块,系统还是一样的运作。
  [color="#ac0000"]4. 把JSP放到WEB-INF后以保护JSP源代码
  为了更好地保护你的JSP避免未经授权的访问和窥视, 一个好办法是将页面文件存放在Web应用的WEB-INF目录下。
 
 通常JSP开发人员会把他们的页面文件存放在Web应用相应的子目录下。一个典型的商店应用程序的目录结构如图2所示。跟catalog
(商品目录)相关的JSP被保存在catalog子目录下。跟customer相关的JSP,跟订单相关的JSP等都按照这种方法存放。

图 2.基于不同的功能 JSP 被放置在不同的目录下
  这种方法的问题是这些页面文件容易被偷看到源代码,或被直接调用。某些场合下这可能不是个大问题,可是在特定情形中却可能构成安全隐患。用户可以绕过Struts的controller直接调用JSP同样也是个问题。

了减少风险,可以把这些页面文件移到WEB-INF
目录下。基于Servlet的声明,WEB-INF不作为Web应用的公共文档树的一部分。因此,WEB-INF
目录下的资源不是为客户直接服务的。我们仍然可以使用WEB-INF目录下的JSP页面来提供视图给客户,客户却不能直接请求访问JSP。
  采用前面的例子,图3显示将JSP页面移到WEB-INF 目录下后的目录结构

图 3. JSP存放在 WEB-INF 目录下更为安全
  如果把这些JSP页面文件移到WEB-INF
目录下,在调用页面的时候就必须把"WEB-INF"添加到URL中。例如,在一个Struts配置文件中为一个logoff
action写一个Action mapping。其中JSP的路径必须以"WEB-INF"开头。如下所示:请注意粗体部分.
  这个方法在任何情况下都不失为Struts实践中的一个好方法。是唯一要注意的技巧是你必须把JSP和一个Struts action联系起来。即使该Action只是一个很基本的很简单JSP,也总是要调用一个Action,再由它调用JSP。
  最后要说明的是,并不是所有的容器都能支持这个特性。WebLogic早期的版本不能解释Servlet声明,因此无法提供支持,据报道在新版本中已经改进了。总之使用之前先检查一下你的Servlet容器。
[color="#ac0000"]5. 使用 Prebuilt Action类提升开发效率
 
 Struts framework带有好几个prebuilt
Action类,使用它们可以大大节省开发时间。其中最有用的是org.apache.struts.actions.ForwardAction 和
org.apache.struts.actions.DispatchAction.
  使用 ForwardAction
 
 在应用程序中,可能会经常出现只要将Action对象转发到某个JSP的情况。在上一点中曾提到总是由Action调用JSP是个好习惯。如果我们不必
在Action中执行任何业务逻辑,却又想遵循从Action访问页面的话,就可以使用ForwardAction,它可以使你免去创建许多空的
Action类。运用ForwardAction的好处是不必创建自己的Action类,你需要做的仅仅是在Struts配置文件中配置一个Action
mapping。
  举个例子,假定你有一个JSP文件index.jsp ,而且不能直接调用该页面,必须让程序通过一个Action类调用,那么,你可以建立以下的Action mapping来实现这一点:

  正如你看到的,当 /home 被调用时, 就会调用ForwardAction 并把请求转发到 index.jsp 页面.
再讨论一下不通过一个Action类直接转发到某个页面的情况,必须注意我们仍然使用元素中的forward属性来实现转发的目标。这时元素定义如下:

  以上两种方法都可以节省你的时间,并有助于减少一个应用所需的文件数。
  使用 DispatchAction
 
 DispatchAction是Struts包含的另一个能大量节省开发时间的Action类。与其它Action类仅提供单个execute()方法
实现单个业务不同,DispatchAction允许你在单个Action类中编写多个与业务相关的方法。这样可以减少Action类的数量,并且把相关
的业务方法集合在一起使得维护起来更容易。
  要使用DispatchAction的功能,需要自己创建一个类,通过继承抽象的
DispatchAction得到。对每个要提供的业务方法必须有特定的方法signature。例如,我们想要提供一个方法来实现对购物车添加商品清
单,创建了一个类ShoppingCartDispatchAction提供以下的方法:

  那么,这个类很可能还需要一个deleteItem()方法从客户的购物车中删除商品清单,还有clearCart()方法清除购物车等等。这时我们就可以把这些方法集合在单个Action类,不用为每个方法都提供一个Action类。
  在调用ShoppingCartDispatchAction里的某个方法时,只需在URL中提供方法名作为参数值。就是说,调用addItem()方法的 URL看起来可能类似于:
  http://myhost/storefront/action/cart?method=addItem
  其中method参数指定ShoppingCartDispatchAction中要调用的方法。参数的名称可以任意配置,这里使用的"method"只是一个例子。参数的名称可以在Struts配置文件中自行设定。
  [color="#ac0000"]6.使用动态ActionForm
 
 在Struts
framework中,ActionForm对象用来包装HTML表格数据(包括请求),并返回返回动态显示给用户的数据。它们必须是完全的
JavaBean,并继承.Struts 里面的ActionForm类,同时,用户可以有选择地覆盖两个缺省方法。
  该特性能节省很
多时间,因为它可以协助进行自动的表现层的验证。ActionForm的唯一缺点是必须为不同的HTML表格生成多个ActionForm
类以保存数据。例如,如果有一个页面含有用户的注册信息,另一个页面则含有用户的介绍人的信息,那么就需要有两个不同的ActionForm类。这在大的
应用系统中就会导致过多的ActionForm类。Struts 1.1对此做出了很好的改进,引入了动态ActionForm类概念
 
 通过Struts framework中的DynaActionForm类及其子类可以实现动态的ActionForm
,动态的ActionForm允许你通过Struts的配置文件完成ActionForm的全部配置;再也没有必要在应用程序中创建具体的
ActionForm类。具体配置方法是:在Struts的配置文件通过增加一个元素,将type属性设定成DynaActionForm或它的某个子类的全名。下面的例子创建了一个动态的ActionForm名为logonForm,它包含两个实例变量:username 和 password.

 
 动态的ActionForm可以用于Action类和JSP,使用方法跟普通的ActionForm相同,只有一个小差别。如果使用普通的
ActionForm对象则需要提供get 和 set方法取得和设置数据。以上面的例子而言,我们需要提供getUsername() 和
setUsername()方法取得和设置username变量,同样地有一对方法用于取得和设置password变量.
  这里我们使
用的是DynaActionForm,它将变量保存在一个Map类对象中,所以必须使用DynaActionForm 类中的get(name) 和
set(name)方法,其中参数name是要访问的实例变量名。例如要访问DynaActionForm中username的值,可以采用类似的代码:
  String username = (String)form.get("username");
  由于值存放在一个Map对象,所以要记得对get()方法返回的Object对象做强制性类型转换。
DynaActionForm
有好几个很有用的子类。其中最重要的是DynaValidatorForm ,这个动态的ActionForm和Validator
一起利用公共的Validator包来提供自动验证。这个特性使你得以在程序代码之外指定验证规则。将两个特性结合使用对开发人员来说将非常有吸引力。
  [color="#ac0000"]7. 使用可视化工具
 
 自从Struts 1.0
分布以来,就出现了不少可视化工具用于协助创建,修改和维护Struts的配置文件。配置文件本身是基于XML格式,在大中型的开发应用中会增大变得很笨
拙。为了更方便的管理这些文件,一旦文件大到你无法一目了然的时候,建议试着采用其中的一种GUI
工具协助开发。商业性的和开放源代码的工具都有不少,表1列出了可用的工具和其相关链接,从那里可以获取更多信息。
  表 1. Struts GUI 工具
应用程序
性质
网址
Adalon
商业软件
http://www.synthis.com/products/adalon
Easy Struts
开放源码
http://easystruts.sourceforge.net/
Struts Console
免费
http://www.jamesholmes.com/struts/console
JForms
商业软件
http://www.solanasoft.com/
Camino
商业软件
http://www.scioworks.com/scioworks_camino.html
Struts Builder
开放源码
http://sourceforge.net/projects/rivernorth/
StrutsGUI
免费
http://www.alien-factory.co.uk/struts/struts-index.html
                       
                                       
                               
21:10
|
评论 (0)
                       
               
       
               
                       
RoleMap
                       
                       

 
                       
                                       
                               
20:30
|
评论 (0)
                       
               
       
               
                       
Struts框架之构建Controller组件
                       
                       
一、概述
 
 在Struts
架构中,Controller主要是ActionServlet,但是对于业务逻辑的操作则主要由Action、ActionMapping、
ActionForward这几个组件协调完成。其中,Action扮演了真正的业务逻辑的实现者,而ActionMapping和
ActionForward则指定了不同业务逻辑或流程的运行方向。
          应用程序的 Controller
部分集中于从客户端接收请求(典型情况下是一个运行浏览器的用户),决定执行什么商业逻辑功能,然后将产生下一步用户界面的责任委派给一个适当的View
组件。在Struts中,controller的基本组件是一个ActionServlet
类的servlet。这个servlet通过定义一组映射(由Java接口 ActionMapping
描述)来配置。每个映射定义一个与所请求的URI相匹配的路径和一个 Action 类(一个实现 Action
接口的类)完整的类名,这个类负责执行预期的商业逻辑,然后将控制分派给适当的View组件来创建响应。
 
Struts也支持使用包含有运行框架所必需的标准属性之外的附加属性的 ActionMapping
类的能力。这允许我们保存特定于我们的应用程序的附加信息,同时仍可利用框架其余的特性。另外,Struts允许我们定义控制将重定向到的逻辑名,这样一
个行为方法可以请求"主菜单"页面,而不需要知道相应的JSP页面的实际名字是什么。这个功能极大地帮助我们分离控制逻辑(下一步做什么)和显示逻辑(相
应的页面的名称是什么)。
二、创建Controller组件
  Struts包括一个实现映射一个请求URI到一个行为类的主要功能的servlet。因此我们的与Controller有关的主要责任是:
 
 为每一个可能接收的逻辑请求写一个 Action 类(也就是,一个 Action
接口的实现);写一个定义类名和与每个可能的映射相关的其它信息的 ActionMapping 类(也就是,一个 ActionMapping
接口的实现);写行为映射配置文件(用XML)用来配置controller servlet。
  为应用程序更新web应用程序展开描述符文件(用XML)用来包括必需的Struts组件,我们给应用程序添加适当的Struts组件。
  1、Action 实现
  Action 接口定义一个单一的必须由一个 Action 类实现的方法,就象下面这样:
public ActionForward perform(ActionServlet servlet,
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException;
  一个 Action 类的目标是处理这个请求,然后返回一个标识JSP页面的
ActionForward 对象,控制应该重定向这个JSP页面以生成相应的响应。Struts
架构为应用系统中的每一个Action类只创建一个实例。因为所有的用户都使用这一个实例,所以你必须确定你的Action
类运行在一个多线程的环境中。
          注意,客户自己继承的Action子类,必须重写execute()方法,因为Action类在默认情况下是返回null的。
  在 Model 2 设计模式中,一个典型的 Action 类将在它的 perform() 方法中实现下面的逻辑:
 
 验证用户session的当前状态(例如,检查用户已经成功地注册)。如果 Action
类发现没有注册存在,请求应该重定向到显示用户名和口令用于注册的JSP页面。应该这样做是因为用户可能试图从"中间"(也就是,从一个书签)进入我们的
应用程序,或者因为session已经超时并且servlet容器创建了一个新的session。如果验证还没有发生(由于使用一个实现
ValidatingActionForm 接口的form bean),验证这个 form bean
的属性是必须的。如果发现一个问题,当作一个请求属性保存合适的出错信息关键字,然后将控制重定向回输入表单这样错误可以被纠正。
  执
行要求的处理来处理这个请求(例如在数据库里保存一行)。这可以用嵌入 Action
类本身的代码来完成,但是通常应该调用一个商业逻辑bean的一个合适的方法来执行。更新将用来创建下一个用户界面页面的服务器端对象(典型情况下是
request范围或session范围beans,定义我们需要在多长时间内保持这些项目可获得)。返回一个标识生成响应的JSP页面的适当的
ActionForward 对象,基于新近更新的beans。典型情况下,我们将通过接收到的 ActionMapping
对象(如果我们使用一个局部于与这个映射上的逻辑名)或者在controller servlet
本身(如果我们使用一个全局于应用程序的逻辑名)上调用 findForward() 得到一个对这样一个对象的引用。
  当为 Action 类编程时要记住的设计要点包括以下这些:
  controller servlet仅仅创建一个我们的 Action 类的实例,用于所有的请求。这样我们需要编写我们的 Action 类使其能够在一个多线程环境中正确运行,就象我们必须安全地编写一个servlet的 service() 方法一样。
  帮助线程安全编程的最重要的原则就是在我们的 Action 类中仅仅使用局部变量而不是实例变量。局部变量创建于一个分配给每个请求线程的栈中,所以没有必要担心会共享它们。
  尽管不应该,代表我们的系统中Model部分的的beans仍有可能抛出违例。我们应该在我们的 perform() 方法的逻辑中捕捉所有这样的违例,并且通过执行以下语句将它们记录在应用程序的日志文件中(包括相应的栈跟踪信息):
servlet.log("Error message text", exception);
  作为一个通用的规则,分配很少的资源并在来自同一个用户(在用户的session中)的请求间保持它们
会导致可伸缩性的问题。另外,我们将会想要防止出现非常大的 Action 类。最简单的实现途径是将我们的功能逻辑嵌入到 Action
类本身,而不是将其写在独立的商业逻辑beans中。除了使 Action
类难于理解和维护外,这种方法也使得难于重用这些商业逻辑代码,因为代码被嵌入到一个组件(Action 类)中并被捆绑运行于web应用程序环境中。
  包括在Struts中的例子程序某种程度上延伸了这个设计原则,因为商业逻辑本身是嵌入到 Action 类中的。这应该被看作是在这个样本应用程序设计中的一个bug,而不是一个Struts体系结构中的固有特性,或者是一个值得仿效的方法。
         2、ActionMapping实现
  为了成功地运行,Struts的controller servlet需要知道关于每个URI该怎样映射到一个适当的 Action 类的几件事。需要了解的知识封装在一个叫做 ActionMapping 的Java接口中,它有以下属性:
  actionClass :用于这个映射的 Action 类完整的Java类名。第一次一个特定的映射被使用,一个这个类的实例将被创建并为以后重用而保存。
  formAttribute :session范围的bean的名字,当前的这个映射的 ActionForm 被保存在这个bean之下。如果这个属性没有被定义,没有 ActionForm 被使用。
  formClass :用于这个映射的 ActionForm 类完整的Java类名。如果我们在使用对form beans的支持,这个类的一个实例将被创建并保存(在当前的用户会话中)
  path :匹配选择这个映射的请求的URI路径。看下面如何匹配的例子。
 
 Struts在一个叫做 ActionMappingBase 的类中包括了一个 ActionMapping
接口的方便的实现。如果我们不需要为我们自己的映射定义任何附加的属性,尽管把这个类作为我们的 ActionMapping
类好了,就向下面部分描述的那样配置。然而,定义一个 ActionMapping 实现(多半是扩展 ActionMappingBase
类)来包含附加的属性也是可能的。controller
servlet知道怎样自动配置这些定制属性,因为它使用Struts的Digester模块来读配置文件。
  包括在Struts的例子程序中,这个特性用来定义两个附加的属性:
 
 failure
:如果Action类检测到它接收的输入字段的一些问题,控制应该被重定向到的上下文相关的URI。典型情况下是请求发向的JSP页面名,它将引起表单被
重新显示(包含Action类设置的出错消息和大部分最近的来自ActionForm bean的输入值)。
  success :如果Action类成功执行请求的功能,控制应该被重定向到的上下文相关的URI。典型情况下是准备这个应用程序的会话流的下一个页面的JSP页面名。
 
 使用这两个额外的属性,例子程序中的 Action 类几乎完全独立于页面设计者使用的实际的JSP页面名。
这个页面可以在重新设计时被重命名,然而几乎不会影响到 Action 类本身。如果"下一个"JSP页面的名字被硬编码到 Action
类中,所有的这些类也需要被修改。
  3、ActionForward实现
  目的是控制器将Action类的处理结果转发至目的地。
 
 Action类获得ActionForward实例的句柄,然后可用三种方法返回到ActionServlet,所以我们可以这样使用
ActionForward():ActionServlet根据名称获取一个全局转发;ActionMappin实例被传送到perform()方法,
并根据名称找到一个本地转发。
  另一种是调用下面的一个构造器来创建它们自己的一个实例:
public ActionForward()
public ActionForward(String path)
public ActionForward(String path,Boolean redirect)
  4、Action映射配置文件
 
 controller servlet怎样知道我们想要得到的映射?写一个简单地初始化新的 ActionMapping
实例并且调用所有适当的set方法的小的Java类是可能的(但是很麻烦)。为了使这个处理简单些,Struts包括一个Digester模块能够处理一
个想得到的映射的基于XML的描述,同时创建适当的对象。
  开发者的责任是创建一个叫做 action.xml
的XML文件,并且把它放在我们的应用程序的WEB-INF目录中。(注意这个文件并不需要
DTD,因为实际使用的属性对于不同的用户可以是不同的)最外面的XML元素必须是<action-mappings>,在这个元素之中是嵌入的0个或更
多的 <action> 元素 -- 每一个对应于我们希望定义的一个映射。
  来自例子程序的 action.xml 文件包括"注册"功能的以下映射条目,我们用来说明这个需求:
<action-mappings>
 <forward name="logon" path="/logon.jsp"/>
 <action path="/logon" actionClass="org.apache.struts.example.LogonAction"
formAttribute="logonForm" formClass="org.apache.struts.example.LogonForm" inputForm="/logon.jsp">
  <forward name="success" path="/mainMenu.jsp"/>
 </action>
</action-mappings>
 
 就象我们所看到的,这个映射匹配路径 /logon
(实际上,因为例子程序使用扩展匹配,我们在一个JSP页面指定的请求的URI结束于/logon.do)。当接收到一个匹配这个路径的请求时,一个
LogonAction 类的实例将被创建(仅仅在第一次)并被使用。controller servlet将在关键字 logonForm
下查找一个session范围的bean,如果需要就为指定的类创建并保存一个bean。
  这个 action 元素也定义了一个逻辑名"success",它在 LogonAction 类中被用来标识当一个用户成功注册时使用的页面。象这样使用一个逻辑名允许将 action 类隔离于任何由于重新设计位置而可能发生的页面名改变。
 
 这是第二个在任何 action 之外宣告的 forward
元素,这样它就可以被所有的action全局地获得。在这个情况下,它为注册页面定义了一个逻辑名。当我们调用
mapping.findForward() 时在我们的 action
代码中,Struts首先查找这个action本地定义的逻辑名。如果没有找到,Struts会自动为我们查找全局定义的逻辑名。
5、Web应用程序展开描述符
  设置应用程序最后的步骤是配置应用程序展开描述符(保存在文件WEB-INF/web.xml中)以包括所有必需的Struts组件。作为一个指南使用例子程序的展开描述符,我们看到下面的条目需要被创建或修改。
  1)配置ActionServlet实例
  添加一个条目定义actionservlet本身,同时包括适当的初始化参数。这样一个条目看起来象是这样:
<servlet>
 <servlet-name>action</servlet-name>
 <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
 <init-param>
  <param-name>application</param-name>
  <param-value>org.apache.struts.example.ApplicationResources</param-value>
 </init-param>
 <init-param>
  <param-name>config</param-name>
  <param-value>/WEB-INF/action.xml</param-value>
 </init-param>
 <init-param>
  <param-name>debug</param-name>
  <param-value>2</param-value>
 </init-param>
 <init-param>
  <param-name>mapping</param-name>
  <param-value>org.apache.struts.example.ApplicationMapping</param-value>
 </init-param>
 <load-on-startup>2</load-on-startup>
</servlet>
  controller servlet支持的初始化参数在下面描述,拷贝自 ActionServlet 类的 Javadocs 。方括号描述如果我们没有为那个初始化参数提供一个值时假设的缺省值。
  application :应用程序资源包基类的Java类名。[NONE]
  config :包含配置信息的XML资源的上下文相关的路径。[/WEB-INF/action.xml]
  debug :这个servlet的调试级别,它控制记录多少信息到日志中。[0]
  digester : 我们在 initMapping() 中利用的Digester的调试级别,它记录到System.out而不是
servlet的日志中。[0]
  forward :使用的ActionForward实现的Java类名。[org.apache.struts.action.ActionForward]
  mapping :使用的ActionMapping实现的Java类名。[org.apache.struts.action.ActionMappingBase]
  nocache : 如果设置为 true,增加HTTP头信息到所有响应中使浏览器对于生成或重定向到的任何响应不做缓冲。[false]
  null :如果设置为 true,设置应用程序资源使得如果未知的消息关键字被使用则返回 null。否则,一个包括不欢迎的消息关键字的出错消息将被返回。[true]
  2)配置ActionServlet映射
  有两种通常的方法来定义将被controller servlet处理的URL:前缀匹配和扩展匹配。每种方法的一个适当的映射条目将在下面被描述。
  前缀匹配意思是我们想让所有以一个特殊值开头(在上下文路径部分之后)的URL传递给这个servlet。这样一个条目看起来可以象是这样:
<servlet-mapping>
 <servlet-name>action</servlet-name>
 <url-pattern>/execute/*</url-pattern>
</servlet-mapping>
  它意味着一个匹配前面描述的 /logon 路径的请求的URL看起来象是这样:
http://www.mystudy.com/myapplication/execute/logon
  这里 /myapplication是我们的应用程序展开所在的上下文路径。
 
 另一方面,扩展映射基于URL以一个跟着定义的一组字符的句点结束的事实而将URL匹配到action servlet
。例如,JSP处理servlet映射到 *.jsp 模式这样它在每个JSP页面请求时被调用。为了使用 *.do
扩展(它意味着"做某件事")映射条目看起来应该象是这样:
<servlet-mapping>
 <servlet-name>action</servlet-name>
 <url-pattern>*.do</url-pattern>
</servlet-mapping>
  并且一个匹配以前描述的 /logon 路径的请求的URI可以看起来象是这样:
http://www.mystudy.com/myapplication/logon.do
  3)配置Struts标记库
  下一步,我们必须添加一个定义Struts标记库的条目。这个条目看起来应该象是这样:
<taglib>
 <taglib-uri>/WEB-INF/struts.tld</taglib-uri>
 <taglib-location>/WEB-INF/struts.tld</taglib-location>
</taglib>
  它告诉JSP系统到哪里去找这个库的标记库描述符(在我们的应用程序的WEB-INF目录)。
  4)添加Struts组件到我们的应用程序中
  为了在我们的应用程序运行时使用Struts,我们必须将 struts.tld 文件拷贝到我们的 WEB-INF 目录,将struts.jar 文件拷贝到我们的 WEB-INF/lib 。


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/5142/showart_16348.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP