邱吉尔曾经说过他喜欢学习新东西但他觉得没有必要让别人教他不管你是否喜欢学习新知识也不管有人教你还是你自学学习Java通常意味着仔细研究许多特殊的类学习Struts也是如此
这就是我写本系列第四部分的初衷在本文中我将详述orgapachestrutsactionActionMapping类它是从onfigActionConfig派生的ActionMapping将一个请求路径映射到一个action类它是Struts应用程序中最常用的类之一在你深入学习这个类时你会重新用到在该系列第和部分创建的两个login应用程序从而了解如何运用ActionMapping来重写应用程序
当然你可能不记得以前用过任何ActionMapping实例了这是因为控制器servlet实际上为你创建了它们你只需要配置在Struts配置文件(strutsconfigxml)中创建的每个ActionMapping实例就行了(通过给它的属性赋值)了解这些属性对正确运用ActionMapping类很重要因此我将讲述这些属性以及如何定义它们
首先让我们回想一下Struts配置文件的根元素是<strutsconfig><strutsconfig>元素可以包含一个可选的<actionmappings>元素 同样<actionmappings>元素可以包含<action>元素例如下面就是本系列第三部分的login应用程序配置文件中的<strutsconfig>元素及其子元素<strutsconfig>
<actionmappings>
<action path=/login
type=comjavaprostrutsLoginAction/>
<action path=/logout
type=comjavaprostrutsLogoutAction/>
<action path=/viewSecret
type=comjavaprostrutsViewSecretAction/>
</actionmappings>
</strutsconfig>
<actionmapping>中的每个<action>都代表控制器servlet创建的一个ActionMapping实例一个<action>元素可以包含多个特性每个特性都和ActionMapping实例中的一个属性相应
作为例子我们来看前面的Struts配置文件中的这个<action>元素<action path=/login
type=comjavaprostrutsLoginAction/>
这个<action>将路径/login映射到action类comjavaprostrutsLoginAction换句话说一个以/logindo结尾的用户请求将被传递到LoginAction类然而ActionMapping也有其它的用途你(Struts程序员)可以通过给它的属性赋值来给ActionMapping实例下达action指令(有些属性与action forms相关我将在本系列的第五部分讲述)
ActionMapping类的属性
ActionMapping有许多属性首先它从ActionConfig类继承了一些属性——如typeforwardinclude和unknown它们与action forms是无关的前三个属性是ActionMapping类最重要的属性你只能指定其中的一个所以如果一个<action>元素已经定义了一个type属性它就不能有forward属性或include属性了
type属性的值是路径所映射的Action类的完全限定的Java类的名称(你曾在前面的login应用程序中的Struts配置文件中用过这个属性)如果运用了type属性那么控制器servlet就可以调用action实现类的execute方法传递恰当的ActionMapping实例注意orgapachestrutsactionActionclass类的execute方法有如下的定义(第一个参数是一个ActionMapping实例)public ActionForward execute(ActionMapping mapping
ActionForm form HttpServletRequest request
HttpServletResponse response)
throws IOException ServletException
forward属性代表的是满足该请求的contextrelative资源(通过调用RequestDispatcherforward())而不是实例化type属性指定的Action类(更多关于如何运用这个属性的信息参见后面的修改login应用程序部分)
我们给include属性赋的值是满足该请求的contextrelative资源路径(通过调用RequestDispatcherinclude())而不是实例化type属性指定的Action类
注意<action>元素包含的forward属性与可能出现在<action>元素下的<forward>元素是不同的这就是说一个<action>元素可以有一个type属性以及一个或多个<forward>子元素如下面这个<action>元素所示(我马上会讲述<forward>元素)<action path=/login
type=comjavaprostrutsLoginAction>
<forward name=success
path=/mainMenujsp/>
<forward name=failure
path=/loginjsp/>
</action>
我们用<path>属性来指定这个ActionMapping将处理的请求路径最后用unknown属性来处理未知的路径在一个action元素中将这个属性设置为true使这个action成为该应用程序缺省的action换句话说它处理所有其它的action不能处理的请求在一个单独的应用程序中只有一个action可以被定义成是缺省的
例如下面这个<action>元素将unknown属性设置为true使该action成为缺省的<action path=/login
type=comjavaprostrutsLoginAction
unknown=true/>
<forward>元素
<forward>元素描述了一个逻辑名称与一个contextrelative URI路径识别的资源之间的映射它有以下这些属性 · className 这是你想运用的ActionForward实现类的完全限定的Java类的名称缺省情况下它的值是作为forward初始化参数给Struts控制器servlet配置的
· contextRelative 在一个模块化应用程序中如果路径属性是以一个斜线(/)开头的并且是相对于整个Web应用程序的而不是相对于该模块的我们就将这个属性设置为true缺省情况下是false
· name 这是forward的唯一标识符用来在应用程序的action类中引用它
· path 被映射资源的contextrelative路径
· redirect 设置成true运用sendRedirect()引导到该资源或者设置成false运用RequestDispatcherforward()作为替代
运用<action>下的<forward>元素意味着你不必在你的ActionForward对象中写死路径名例如我们来看前面的login应用程序中LoginAction类的execute方法中的代码public ActionForward execute(ActionMapping mapping
ActionForm form HttpServletRequest request
HttpServletResponse response)
throws IOException ServletException {
String userName =
requestgetParameter(userName);
String password =
requestgetParameter(password);
if (userName!=null && password!=null &&
userNameequals(john) &&
passwordequals()) {
HttpSession session = requestgetSession();
sessionsetAttribute(loggedIn );
return (new ActionForward(/mainMenujsp));
}
else {
return (new ActionForward(/loginjsp));
}
}
注意最后的两个return语句写死了mainMenujsp和loginjsp页面如果任意一个文件名发生改变你都必须重新编译LoginAction类但是如果你用<forward>元素你可以用一个名称映射mainMenujsp页面用另一个名称映射loginjsp页面现在如果你需要改变文件名你就可以在配置文件中进行改变而不需要重新编译了要这么做你需要在strutsconfigxml文件中声明这个<action>元素<action path=/login
type=comjavaprostrutsLoginAction>
<forward name=success path=/mainMenujsp/>
<forward name=failure path=/loginjsp/>
</action>
现在mainMenujsp就与success这个名称联系在一起了loginjsp与failure联系在一起了你可以通过调用ActionMapping类的findForward方法传入相关的名称从一个action实现类的内部得到ActionForward实例mappingfindForward(name);
例如要得到包含路径/mainMenujsp的ActionForward对象我们可以用下面的方法mappingfindForward(success);
同样要得到包含路径/loginjsp的ActionForward对象可以用writemappingfindForward(failure);
接下来我们该用<forward>方法重写login应用程序了
修改Login应用程序
注意你在第三部分创建的login应用程序发生了怎样的变化首先我们来看原应用程序中ViewSecretAction类的execute方法public ActionForward execute(ActionMapping mapping
ActionForm form HttpServletRequest request
HttpServletResponse response)
throws IOException ServletException {
return (new ActionForward(/viewSecretjsp));
}
除了返回一个路径是/viewSecretjsp的ActionForward对象外该execute方法没有做任何的处理通过运用strutsconfigxml文件中<action>元素的forward属性我们就不需要ViewSecretAction类了要实现这一点我们可以将下面的<action>代码<action path=/viewSecret
type=comjavaprostr