ActionMapping对应了配置信息,在struts配置中,一个Action标签就对应了一个ActionMapping实例,即会把Action标签中的所有的属性都放到ActionMapping里。
在Struts中,ActionServlet只是任务的分派者,它依请求分配任务给其它的对象来执行,而分配的依据是请求的URI以及struts-config.xml的<action-mappings>卷标所设定的内容。
<action-mappings>用来描述一组ActionMapping对象,当中的每一个<action>卷标都对应一个ActionMapping对象,当客户端发出请求至ActionServlet时,ActionServlet根据其URI及<action>卷标设定的path属性查看对应的ActionMapping对象,ActionMapping对象会告诉ActionServlet该使用哪一个Action对象(在<action>卷标中使用type属性设定),而ActionServlet再将工作交给该Action对象来执行。
举个例子来说,如果<action-mappings>设定如下:
代码:
|
<action-mappings>
|
则当请求的URL是http://localhost:8080/HelloStruts/Login.do,ActionServlet会使用\Login来找出path设定为Login的ActionMapping对象,该ActionMapping对象告知ActionServlet要使用onlyfun.caterpillar.LoginAction,而后ActionServlet会将呼叫LoginAction的execute()方法,并将ActionMapping对象当作参数传递给它。
ActionServlet实际上将工作交给Action对象,然而Action对象的运作必须提供一些参数来描述工作的细节,诸如使用哪一个ActionForm、forward对象的查找、错误发生时的页面对象等等,Struts将这些信息包装在ActionMapping中,并作为参数传送给Action对象,以使得Action在需要相关的信息时可以从ActionMapping中取得。
对于没有定义的ActionMapping,如果客户端请求了怎么办?Struts会丢出 404 Invalid path 的讯息,您可以撰写匿名的ActionMapping来提供自己的错误讯息:
则当请求的URL是http://localhost:8080/HelloStruts/Login.do,ActionServlet会使用\Login来找出path设定为Login的ActionMapping对象,该ActionMapping对象告知ActionServlet要使用onlyfun.caterpillar.LoginAction,而后ActionServlet会将呼叫LoginAction的execute()方法,并将ActionMapping对象当作参数传递给它。
ActionServlet实际上将工作交给Action对象,然而Action对象的运作必须提供一些参数来描述工作的细节,诸如使用哪一个ActionForm、forward对象的查找、错误发生时的页面对象等等,Struts将这些信息包装在ActionMapping中,并作为参数传送给Action对象,以使得Action在需要相关的信息时可以从ActionMapping中取得。
对于没有定义的ActionMapping,如果客户端请求了怎么办?Struts会丢出 404 Invalid path 的讯息,您可以撰写匿名的ActionMapping来提供自己的错误讯息:
代码:
|
<action>
|
如果ActionServlet收到的没有定义的Action请求,则会交由匿名的ActionMapping来处理。
在Struts中,ActionMapping继承自ActionConfig,大部份的属性定义实际上都已经在ActionConfig中完成,不过ActionMapping仍旧存在,根据线上API的说明,继承存在的事实基于它仍是现存应用程序所使用的公用类别
首先要明确ActionMapping的地位:struts应用的核心设计。它充当ActionServlet这个中央控制器的路由联络官。ActionServlet使用它的一个实例来决定接下来应该做什么。当你需要了解一个struts应用是怎样时,又或者你面对一个struts应用无从下手时,你可以从ActionMapping。
出发以下介绍下它的一些属性,这些都是在一般应用中比较常见的。
(请容许我以这样的次序进行排列,这是有目的的)
<path>:ActionMapping的一个URI,是一个虚拟引用。我本人是这样看待的,它充当着一个ActionMapping的一个实例的入口点。如果您仔细对比提交的表单的提交中的action属性你也就明白了,他们是对应的!差别只是这里的path不存在扩展名,这也是有原因的,在web.xml文件的<servlet>和<servlet-mapping>元素已经有说明了。
<type>:这个元素是一个actionmapping要实例化的action类的完全限定名。是actionservlet将要调用的action目的类。与<forwrd><include>不可同时出现。他们是互斥的。
<action path="/login"
type="com.javapro.struts.LoginAction"/>表明,来自/login的请求将被发送到LoginAction类
<forward>:不存在action类(serlet传递请求的目的类),那么通过RequestDispatcher.forward对struts和其他资源进行集成,与<type><include>互斥
<include>:不存在action类,那么通过RequestDispatcher.include方法机械的对struts和其他组件进行集成。与<type><foward>互斥。
<name>:如果存在相应的actionForm bean,这里的name就是这个formbean的逻辑名称,通过它,servlet可以找到相应的formbean来进行属性的配对。
<scope>:scope的属性值只能是request或session中的一个,它的作用是指明上面那个name属性的作用范围,缺省的状态下应该是session
<validate>:当将它设置为true的时候,servlet将会调用actionForm类的validate()方法对要保存在formean中的数据进行校验,如果返回的是一个ActionError,那么将调用input属性所指定的URI,这个默认的是true
<input>:如上面描述的那样。Input为抛出的错误提供一个转发的资源
<parameter>:最简单的理解就是servlet通过它来给action类传递额外的一些信息
<attribute>:一般情况下,sesion作用范围内可能出现多个formbean,为了区别它们,可以提供attribute属性。当然你也可以在struts配置文件中写多个formbean
另外要说明的是,actionmapping元素中可以嵌入其他的组件使得它的功能更加强大。比如嵌入<forward name=”success” path=”/success.jsp”>就可以为逻辑名称success标识一个URI。
谈到ActionMapping.相信大家用得最多的就是ActionMapping.findForward("forwardName");通过ActionMapping对象把请求转发到指定的forward对象。
没错,在大体上。ActionMapping就实现了一个路由的功能。负责把请求转发到不同的ActionForward上。
在我们经常用的配置就是:
在<action-mappings>标签中配置了N个action。实际上在struts1.1处理的时候会把这些action都装饰成一个单例的ActionMapping对象然后放到一个
ActionMappings的Map中,通过action的path属性做为key。来区别不同的ActionMapping对象。struts就通过请求不同的path就可以达到把请求转发给
不同的Action上。
------------------------------------------------------------------------------------------------------
ActionMapping工作起来就像是ActionServlet的一个路由联络官。取决于mapping 如何被填写
设置,请求可能被传递到任何地方。ActionMapping表达了Struts 应用的核心设计。如果你
想知道一个 Struts 应用是如何工作的,可以从ActionMapping开始着手。如果你想知道如何
编写一个新的Struts 应用,也请从ActionMapping开始。Mapping处于每个Struts 应用的绝对
核心。
ActionMapping的属性:
path属性
ActionMapping URI,或者path,对用户来说就象web server上的一个文件。但实际上它并不
代表一个文件。它是一个对ActionMapping的虚拟引用。
因为它暴露给其它系统, path 并不真正是个逻辑名称,就象那些我们用于ActionForward
中的一样。 path 可以包括反斜杠和扩展名--如果它引用一个文件系统——但它们都只是
一个单一名称的一部分。
ActionMapping自身是一个“平面的” 名称空间,完全没有内部层次关系。它仅仅是正好使用
了一个和层次性文件系统中一样的名称而已。
当然, 这对处理ActionMapping仍然是有帮助的,就象它们是一个层次关系或者在同一个"文
件夹"下的相关命令组的一部分。唯一的限制是名称必须匹配于在应用部署描述文件中为
ActionServlet指定的样式。这通常是/do/*或者 *.do,但是其它相似的样式也可以使用。如果
你在一个团队环境中工作,不同的团队可能有不同的 ActionMapping 名称空间使用。某些
人可能工作于/customer ActionMapping, 而另一些可能工作于/vendor ActionMapping。
这也可能和各个团队使用的Java 包的层次相关。因为 ActionMapping URI是逻辑的构造,
所以你可以用它来以各种方式组织来适合你的项目。
forward 属性
当指定了forward 属性时,servlet将不会把请求传递给Action类,而是调用
RequestDispatcher.forward。因为操作没有使用Action 类, 它也可以被用来进行
Struts 和其它资源之间的集成,或者用来构建系统原型。forward, include, 以及 type
属性是互斥的
include 属性
当指定了include 属性时, servlet将不会把请求传递给Action 类而是调用
RequedtDispatcher.include方法。因为操作没有使用Action 类, 它也可以被用来机械
进行Struts 和其它组件之间的集成。forward, include, 以及 type 属性是互斥的。
type 属性
大部分 mapping都会指定一个 Action 类类型,而不是一个forward 或者 include。Action 类
可以被多个mapping使用。 Mapping可以指定form bean,参数,forward,或者exceptions属
性。forward, include, 以及 type 属性是互斥的。
classname属性
如果被指定,classname 是应该用于此对象的ActionMapping子类的全限定Java类名称。这
就允许你使用你自己的ActionMapping 子类来引入特定的方法和属性。参见7.4节。
name属性
如果在Struts 配置文件中配置了相应的formbean段的话,这个属性指定了form bean的
逻辑名称。缺省情况下,这也是将form bean 放入请求或者会话上下文时使用的名称。使
用该类的attribute 属性来指定不同的属性(Attribute)关键字。
roles属性
这个属性是一个逗号分隔的,允许访问该ActionMapping 对象的安全角色称的列表。缺省情
况下,与基于容器的安全机制所使用的同一个系统将用于这里给定的角色列表。这意味着你
可以通过在部署描述符中指定特定的URL模板而使用基于action的安全,或者两者都使用。
安全检查由请求处理器(org.apache.struts.action.RequestProcessor)的
processRoles方法处理。通过子类化请求处理器,你也可以在基于应用的安全下使用
roles 属性。
scope属性
ActionForm bean 可以存储在当前的请求或会话范围中(这样它可以服务于另外的请求)。
虽然大部分开发人员使用请求范围来存储ActionForm, 框架的缺省设置却是会话范围
validate属性
ActionForm 生命周期内的一个重要步骤是在其数据提供给业务层之前需要进行校验。当
mapping 的validate 属性设置为true时,ActionServlet将调用ActionForm的 validate 方
法。如果 validate 返回false,请求将被转发到input 属性指定的资源。
经常,开发人员将为每个数据输入表单创建两个mapping。一个mapping 将使 validate 设
置为 false, 所以你可以创建一个空的表单。另一个则设置validate 为true,用来提交完整
的表单。
input属性
当validate被设置为true时,重要的是需要提供一个有效的输入路径。这也是当ActionForm
validate 方法返回 false时,控制应该被传递到的地方。通常这是一个表现页面。有时也
可以是另外一个用来产生页面所需要的数据对象的Action path (其 validate 必须设置为
false)。
输入转发
在Struts 1.0中,ActionMapping的 input 属性通常是一个字面的URI。在Struts 1.1中,它也
可以是一个ActionForward 的名称。ActionForward 被获取之后,其path 属性被用作input
属性。这也可以是一个全局或者局部转发。
这儿为了使用 ActionForward而不是字面的path, 可以设置这个模块的<controller> 元
素的inputForward 属性为 true:
<controller inputForward="true">
parameter属性
这个普通的paramenter属性允许Action能够在运行时被配置。许多标准的Struts Action都使用
这个属性,标准的Scaffold Action也经常使用它。Parameter属性可以包含URI, 方法名称,类
名称,或者其它一些Action在运行时可能需要的信息。这种灵活性允许一些Action履行双倍
或者三倍的职责,削减应用所需的不同的类的数量。
在一个Action 类中,parameter属性是从传递到perform的mapping中取得的:
parameter = mapping.getparameter();
attribute属性
不时地,你可能需要同时在同一个上下文中保存同一个ActionForm 的在两份拷贝。这在
ActionForm被存于会话上下文中作为工作流的一部分时,经常发生这种情况。为了避免它们
之间的名称冲突,你可以使用 attribute 属性来给一个 ActionForm bean 一个不同的名
称。另一个方法是在配置中定义另一个ActionForm bean,使用相同的类型但使用不同的名称。
divfix和suffix属性
与 attribute属性一样, divfix 和suffix 属性可用来避免应用系统中的名称冲突。如
果指定了这个属性,这就表明允许在属性名称前面加上前缀或者后缀,形成它们从请求中被
组装时的一个别名。
如果指定了前缀 this,那么在ActionForm组装时:
thisName=McClanahan
相当于
name=McClanahan
而它们都可以通过调用
getName("McClanahan");
取得。这并不影响属性如何被标签扩展输出。它只影响到自动组装机制如何从请求中感知它们
unknown ActionMapping(这个属性只能配置一个)
在Web上冲浪时,大都遇到过讨厌的404— pages not found信息。大部分web server 都提供一些特殊的特征来处理对未知页面的请求,所以 webmaster 可以将用户引导到正确的方向上。
Struts 提供了一个类似的服务来处理404错误—即unknown ActionMapping。
在Struts 配置文件中,你可以指定一个ActionMapping 来接收所有与其它ActionMapping不相
匹配的请求:
<action
name="/debug"
forward="/pages/debug.jsp"/>
如果没有设置它,没有匹配对的ActionMapping请求就会抛出:
400 Invalid path /notHere was Requested
请注意通过对ActionMapping请求, 我们的意思是URI首先必须匹配为servlet指定的前缀或者
后缀 (通常是 /do/* 或者 *.do)。对于其它样式的请求, 无论好坏,都将被容器中的其它
servlet处理:
/do/notHere (goes to the unknown ActionMapping)
/notHere.txt(goes to the Container)
比较多,不过常用的也就是path,type,scope,name,parameter如果要在form里做验证要写input,validate.
学会使用jstl保持页面数据:
当填好页面表单之后提交,数据会提交给ActionForm,当输入的数据出现错误的时候,会返回到填写表单的页面,此时想保持上次填的数据,可以使用jstl来实现:
<form action="login.do" method="post">
用户:<input type="text" name="username" value="${loginForm.username }"><br>//在ActionForm中把填的数据取出显示出来
密码:<input type="password" name="password" value="${loginForm.password }"><br>
<input type="submit" value="登录">
</form>
也可以使用struts标签来实现这个目的。