主题:Struts 2 自学之路: 3.2 名称空间(namespace)详解

来源:互联网 发布:进销存软件excel表格 编辑:程序博客网 时间:2024/05/18 01:12
内容简介: 
这篇文章将会通过实例详细介绍 struts.xml 文件中 package 元素下 namespace 属性的作用 
          
说在前面的话: 
namespace的作用是控制相应package下的action的url地址,url地址在web编程中是基础中的基础 
我们的程序不同的功能实际上就是对相应url地址的访问来触发的,这个要牢牢掌握,有点象java的classpath 

需要注意的事项: 
我修改了tomcat端口,所以你们看到的http://127.0.0.1:8888/里的8888,要以你自己的tomcat端口为准 
修改了xml文件一定要重新启动tomcat或者重新热部署 

第一部分 
首先我还是废话一下这个基础,这些你都很清楚可以跳过前面这部分 
先来看一下一些相对路径的不同写法在tomcat里的运行情况,这里我们使用表单的action来介绍 

打开我们上次的工程,在WebRoot文件夹下新建一个目录namespace,然后在里面新建一个Jsp文件testurl.jsp,这里下载 
其代码如下 

Java代码  收藏代码
  1. <%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>  
  2. <%@taglib prefix="s" uri="/struts-tags"%>  
  3. <!-- 使用struts标签必需在这里倒入 -->  
  4. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
  5. <html>  
  6.     <head>  
  7.         <title>testurl</title>  
  8.     </head>  
  9.     <body>  
  10.         由于struts标签的action和html表单的action在处理上有某些不同<br>  
  11.         struts标签的action把以"/"开头的路径优化过,提交下面的表单<br>        
  12.         由于没有test.jsp,肯定全部是404错误,没关系,我们只需要查看其url地址,这足够让我们理解其具体行为了  
  13.         <br>  
  14.         <br>  
  15.         <table border="1">  
  16.             <tr>  
  17.                 <th>  
  18.                     使用html表单访问test.jsp  
  19.                 </th>  
  20.                 <th>  
  21.                     使用struts表单标签访问test.jsp  
  22.                 </th>  
  23.             </tr>  
  24.             <tr>  
  25.                 <td>  
  26.                     action="test.jsp"  
  27.                     <form action="test.jsp" method="post">  
  28.                         <input type="submit" value="html表单访问test.jsp" />  
  29.                     </form>  
  30.                 </td>  
  31.                 <td>  
  32.                     action="test.jsp"  
  33.                     <s:form action="test.jsp">  
  34.                         <s:submit value="struts表单标签访问test.jsp" />  
  35.                     </s:form>  
  36.                 </td>  
  37.             <tr>  
  38.             <tr>  
  39.                 <td>  
  40.                     action="/test.jsp"  
  41.                     <form action="/test.jsp" method="post">  
  42.                         <input type="submit" value="html表单访问test.jsp" />  
  43.                     </form>  
  44.                 </td>  
  45.                 <td>  
  46.                     action="/test.jsp"  
  47.                     <s:form action="/test.jsp">  
  48.                         <s:submit value="struts表单标签访问test.jsp" />  
  49.                     </s:form>  
  50.                 </td>  
  51.             <tr>  
  52.             <tr>  
  53.                 <td>  
  54.                     action="./test.jsp"  
  55.                     <form action="./test.jsp" method="post">  
  56.                         <input type="submit" value="html表单访问test.jsp" />  
  57.                     </form>  
  58.                 </td>  
  59.                 <td>  
  60.                     action="./test.jsp"  
  61.                     <s:form action="./test.jsp">  
  62.                         <s:submit value="struts表单标签访问test.jsp" />  
  63.                     </s:form>  
  64.                 </td>  
  65.             <tr>  
  66.             <tr>  
  67.                 <td>  
  68.                     action="../test.jsp"  
  69.                     <form action="../test.jsp" method="post">  
  70.                         <input type="submit" value="html表单访问test.jsp" />  
  71.                     </form>  
  72.                 </td>  
  73.                 <td>  
  74.                     action="../test.jsp"  
  75.                     <s:form action="../test.jsp">  
  76.                         <s:submit value="struts表单标签访问test.jsp" />  
  77.                     </s:form>  
  78.                 </td>  
  79.             <tr>  
  80.             <tr>  
  81.                 <td>  
  82.                     action="/Struts2Study/namespace/test.jsp"  
  83.                     <form action="/Struts2Study/namespace/test.jsp" method="post">  
  84.                         <input type="submit" value="html表单访问test.jsp" />  
  85.                     </form>  
  86.                 </td>  
  87.                 <td>  
  88.                     action="/namespace/test.jsp"  
  89.                     <s:form action="/namespace/test.jsp">  
  90.                         <s:submit value="struts表单标签访问test.jsp" />  
  91.                     </s:form>  
  92.                 </td>  
  93.             <tr>  
  94.         </table>  
  95.     </body>  
  96. </html>  


运行上面的例子可以看到结果,从运行结果可以看出,struts的form标签的action是经过优化的 
当html的form表单的action="/url"(以/开头的url地址)时,其会从http://127.0.0.1:8080这个根开始附加,我们要访问具体信息必需要加上 
项目的上下文(context),就是tomcat安装目录下wepapps/context(具体是你工程名字)这个文件夹名字,象这样 
<form action="/Struts2Study/namespace/test.jsp" method="post"> 
而struts的form标签的action="/url"(以/开头的url地址)时,struts2帮我们作了优化,他会自动为我们在htpp://127.0.0.1:8080/后面加上 
项目的上下文,再附加action后的url,而这也是我们开发时想要的本意,象这样<s:form action="/namespace/test.jsp"> 
其余的都是一样的 
action="url" 和 action="./url" 都表示当前路径 
action="../" 表示上级路径 

上面的表单实际上是被当作超链接来使用的(没有表单参数,只是跳转),超链接的实际访问效果和表单是一样的 action="test.jsp" 和 
<a href="test.jsp"> 都是访问test.jsp,只是表单允许用户输入数据,而超链接办不到 



第二部分 
接下来就该进入正题了,先把工程以前在根目录的index.jsp,error.jsp和welcome.jsp复制到namespace文件夹里,然后修改其代码 
再新建两个jsp文件,分别为 error1.jsp,welcome1.jsp,这两个同error.jsp和welcome.jsp一样,只要确认文本就ok 
index.jsp
Java代码  收藏代码
  1. <%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>  
  2. <%@taglib prefix="s" uri="/struts-tags"%>  
  3. <!-- 要使用struts的标签就要先倒入 -->  
  4. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
  5. <html>  
  6.   <head>      
  7.     <title>第一个Struts程序</title>  
  8.   </head>    
  9.   <body>  
  10.     <center>  
  11.     action="NameSpace.action"  
  12.     <form action="NameSpace.action" method="post">  
  13.         <table align="center">  
  14.         <caption><h3>用户登录</h3></caption>  
  15.             <tr>  
  16.                 <td>用户名:<input type="text" name="username"/></td>  
  17.             </tr>  
  18.             <tr>  
  19.                 <td>密  码:<input type="text" name="password"/></td>  
  20.             </tr>  
  21.             <tr align="center">  
  22.                 <td colspan="2"><input type="submit" value="登录"/>  
  23.                 <input type="reset" value="重填"/></td>  
  24.             </tr>  
  25.         </table>  
  26.     </form>  
  27.     action="/Struts2Study/namespace/NameSpace.action"  
  28.     <form action="/Struts2Study/namespace/NameSpace.action" method="post">  
  29.         <table align="center">  
  30.         <caption><h3>用户登录</h3></caption>  
  31.             <tr>  
  32.                 <td>用户名:<input type="text" name="username"/></td>  
  33.             </tr>  
  34.             <tr>  
  35.                 <td>密  码:<input type="text" name="password"/></td>  
  36.             </tr>  
  37.             <tr align="center">  
  38.                 <td colspan="2"><input type="submit" value="登录"/>  
  39.                 <input type="reset" value="重填"/></td>  
  40.             </tr>  
  41.         </table>  
  42.     </form>  
  43.     action="/Struts2Study/NameSpace.action"  
  44.     <form action="/Struts2Study/NameSpace.action" method="post">  
  45.         <table align="center">  
  46.         <caption><h3>用户登录</h3></caption>  
  47.             <tr>  
  48.                 <td>用户名:<input type="text" name="username"/></td>  
  49.             </tr>  
  50.             <tr>  
  51.                 <td>密  码:<input type="text" name="password"/></td>  
  52.             </tr>  
  53.             <tr align="center">  
  54.                 <td colspan="2"><input type="submit" value="登录"/>  
  55.                 <input type="reset" value="重填"/></td>  
  56.             </tr>  
  57.         </table>  
  58.     </form>  
  59.     <br>  
  60.     <h5>以下是使用struts的form标签</h5>  
  61.     <br>  
  62.     action="NameSpace"  
  63.     <s:form action="NameSpace">  
  64.         <s:textfield name="username" label="用户名"/>  
  65.         <s:textfield name="password" label="密  码"/>  
  66.         <s:submit value="登录"/>  
  67.     </s:form>  
  68.     action="/namespace/NameSpace.action"  
  69.     <s:form action="/namespace/NameSpace.action">  
  70.         <s:textfield name="username" label="用户名"/>  
  71.         <s:textfield name="password" label="密  码"/>  
  72.         <s:submit value="登录"/>  
  73.     </s:form>  
  74.     action="/NameSpace.action"  
  75.     <s:form action="/NameSpace.action">  
  76.         <s:textfield name="username" label="用户名"/>  
  77.         <s:textfield name="password" label="密  码"/>  
  78.         <s:submit value="登录"/>  
  79.     </s:form>  
  80.     </center>  
  81.   </body>  
  82. </html>  


下面来确认error.jsp,welcome.jsp,error1.jsp及welcome1.jsp的body部分 
Java代码  收藏代码
  1. <!-- error.jsp -->  
  2. <body>  
  3.     你是谁啊,我根本不认识你,再不离开我放狗了  
  4.     namespace/error.jsp  
  5. </body>  
  6.   
  7. <!-- error1.jsp -->  
  8. <body>  
  9.     who are you? i don't know you,i'll call my dog if you won't go<br>  
  10.     namespace/error1.jsp      
  11. </body>  
  12.   
  13. <!-- welcome.jsp -->  
  14. <body>  
  15.     你好啊亲爱滴,我等你很久了<br>  
  16.     namespace/welcome.jsp  
  17. </body>  
  18.   
  19. <!-- welcome1.jsp -->  
  20. <body>  
  21.     hi,darlin,i wait for you for a long time<br>  
  22.     namespace/welcome1.jsp      
  23. </body>  



接下来在新建包yufei.namespace,然后从hello把HelloAction.java复制过去,不用修改代码 
HelloAction.java
Java代码  收藏代码
  1. package yufei.namespace;  
  2.   
  3. public class HelloAction  
  4.     {  
  5.     private String username;  
  6.     private String password;  
  7.     public String getPassword()  
  8.         {  
  9.         return password;  
  10.         }  
  11.     public void setPassword(String password)  
  12.         {  
  13.         this.password = password;  
  14.         }  
  15.     public String getUsername()  
  16.         {  
  17.         return username;  
  18.         }  
  19.     public void setUsername(String username)  
  20.         {  
  21.         this.username = username;  
  22.         }  
  23.     public String execute()  
  24.         {  
  25.         String strReturn = "error";  
  26.         if (username.equals("yufei"))  
  27.             strReturn = "success";  
  28.         return strReturn;  
  29.         }  
  30.     }  


接着我们在yufei.namespace包中新建一个xml文件namespace.xml,并且在struts.xml文件中加入以下内容 
Java代码  收藏代码
  1. <!-- 倒入其它配置文件 -->  
  2. <include file="yufei/namespace/namespace.xml"/>  


namespace.xml的代码如下,这些前篇文章都讲过了,这里不再说了 
Java代码  收藏代码
  1. <?xml version="1.0" encoding="GBK"?>  
  2. <!DOCTYPE struts PUBLIC   
  3.     "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"  
  4.     "http://struts.apache.org/dtds/struts-2.0.dtd">  
  5. <struts>  
  6.     <package name="yufei.namespace" extends="struts-default">  
  7.         <action name="NameSpace" class="yufei.namespace.HelloAction">  
  8.             <result name="success">/namespace/welcome.jsp</result>  
  9.             <result name="error">/namespace/error.jsp</result>  
  10.         </action>  
  11.     </package>  
  12. </struts>  


接下来我们启动tomcat来测试程序,jsp里的表单action多的就不说了,在第一部分已经废话了很多,这里有个小知识 
就是使用struts的form标签时,如果是当前路径,可以不带.action,即不是以/或./或../这类开头的,可以看index.jsp代码 
不过我建议还是每个地方都写上,这样看上去更统一,这点知道就行了,在地址拦输入http://127.0.0.1:8888/Struts2Study/namespace/index.jsp 
每个表单分别提交一次,我们观察url地址,会发现有两种地址,分别是 
http://127.0.0.1:8888/Struts2Study/namespace/NameSpace.action 
http://127.0.0.1:8888/Struts2Study/NameSpace.action 
而且都能正常到执行,这里先不忙解释,我们对namespace.xml做一些小手脚来继续观察,给package元素加上namespace属性 
设置其值为namespace="namespace"(这个值代表的其实是路径) 
Java代码  收藏代码
  1. <?xml version="1.0" encoding="GBK"?>  
  2. <!DOCTYPE struts PUBLIC   
  3.     "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"  
  4.     "http://struts.apache.org/dtds/struts-2.0.dtd">  
  5. <struts>  
  6.     <!-- 新加上namespace -->  
  7.     <package name="yufei.namespace" extends="struts-default" namespace="/namespace">  
  8.         <action name="NameSpace" class="yufei.namespace.HelloAction">  
  9.             <result name="success">/namespace/welcome.jsp</result>  
  10.             <result name="error">/namespace/error.jsp</result>  
  11.         </action>  
  12.     </package>  
  13. </struts>  


重新启动tomcat(或重热部署),然后在打开namespace下的index.jsp,现在我们再来提交表单试试 
现在出现了异常情况...当我们提交表单到http://127.0.0.1:8888/Struts2Study/NameSpace.action时发生了异常 
而我们提交到http://127.0.0.1:8888/Struts2Study/namespace/NameSpace.action却能正常执行 
原因就在于这个namespace属性的设置 
我们来回顾一下struts2的基本流程,当客户发生请求以后,触发struts2的FilterDispatcher过滤器(默认配置是所有请求都会触发) 
如果请求是以.action结尾,FilterDispatcher会去struts.xml里面查找action元素的name属性配置,找到匹配的然后运行其class 
属性指定的类 
在struts2基本流程里是这样说明的,现在补充一点,匹配的不光是name属性,还有package的namespace属性,现在我这里就来讲一下 
struts2是如何去查找匹配action的,这是我自己的理解,没有任何资料参考,如有什么不妥之处请邮件告知(yufei@wapke.cn)
 
以今天这个index.jsp里 action=NameSpace.action 来举例说明,当我们提交此表单时,会请求以下这个url资源 
http://127.0.0.1:8888/Struts2Study/namespace/NameSpace.action 
这时filterdispatcher触发,然后其发现请求url是以.action结尾,然后其就去配置文件里面查找,匹配的方式应该是 
将http://127.0.0.1:8888/Struts2Study请求资源的根路径去掉,然后再将最后的.action去掉留下中间那部分(这里就是 
/namespace/NameSpace),然后将剩下这部分再分为两个部分,即最后一个/以前的部分,和最后一个/以后部分,分解以后就是这样, 
/namesapce(最后一个/以前,不包括最后一个/)和NameSpace(最后一个/以后,不包括最后一个/)然后拿分解出来的第一部分去 
和package元素里的namespace比对,找到相同的就在这个package元素里找其子action元素的name属性和分解出来的第二部分对比 
,相同就执行其class属性对应的类,如果找不到,就会到默认namespace里去找,默认namespace是"",namesapce="" 和 namespace="/" 和 namespace空缺不写 是一样的效果,都代表在项目根路径上去匹配action的name,以上面的url举例就是 
http://127.0.0.1:8888/Struts2Study/到这里去找NameSpace.action, 
如果剩下这部分/以前没有内容,就代表到默认名称空间去找 
注意:namespace属性的值等于"/"代表根空间,""代表默认空间,只是默认情况下二者大致相当,指执行结果 

为了明白什么是先查找指定名称空间,再查找默认名称空间,我们把namespace.xml的配置文件改动一下 
把package元素里的namespace属性去掉(你也可以分别试着让namespace=""或namesapce="/"来看效果) 

Java代码  收藏代码
  1. <!-- 去掉namespace属性 -->  
  2. <package name="yufei.namespace" extends="struts-default">  


这样又回到一开始的配置了,然后我们来执行,会有两种url地址,但是两种地址都能正常运行 
http://127.0.0.1:8888/Struts2Study/namespace/NameSpace.action 
http://127.0.0.1:8888/Struts2Study/NameSpace.action 
第二种情况还比较好理解,这个就是上面说的/以前没有内容,就代表到默认名称空间查找 
第一种情况要复杂点,被FilterDispatcher拦截下来后,它先到namespace="/namespace"里面去找 
,没有找到,然后又到namespace=""去查找,找到了,所以也执行了 

接下来我们再来把配置文件的 namespace改回 namesapce="namespace" 
修改配置文件以后http://127.0.0.1:8888/Struts2Study/NameSpace.action会报异常 
原因是/以前没有内容,就代表到默认名称空间查找,而配置文件里根本没有配置有默认空间的package,所以肯定找不到 
给index.jsp再添加一个表单,提交给一个更容易看明白的地址 

Java代码  收藏代码
  1. action="/namespace1/NameSpace.action"  
  2.     <s:form action="/namespace1/NameSpace.action">  
  3.     <s:textfield name="username" label="用户名"/>  
  4.     <s:textfield name="password" label="密  码"/>  
  5.     <s:submit value="登录"/>  
  6. </s:form>  
  7. <!-- 加入到最后 -->      


这个表单提交到以下地址,报了异常 
http://127.0.0.1:8888/Struts2Study/namespace1/NameSpace.action 
这个被FilterDispatcher拦截下来后,先到namespace="/namespace1"里面去找,没有找到,然后又到namespace=""去查找 
还是没有找到,所以还是报异常 



最后我们来做一个同名action的试验来结束名称空间的讲解,看不同名称空间,同名action是某可以使用 
修改namespace.xml如下 
Java代码  收藏代码
  1. <?xml version="1.0" encoding="GBK"?>  
  2. <!DOCTYPE struts PUBLIC   
  3.     "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"  
  4.     "http://struts.apache.org/dtds/struts-2.0.dtd">  
  5. <struts>  
  6.     <!-- 新加上namespace -->  
  7.     <package name="yufei.namespace" extends="struts-default" namespace="/namespace">  
  8.         <action name="NameSpace" class="yufei.namespace.HelloAction">  
  9.             <result name="success">/namespace/welcome.jsp</result>  
  10.             <result name="error">/namespace/error.jsp</result>  
  11.         </action>  
  12.     </package>  
  13.     <!-- package name不能出现重复的 -->  
  14.     <package name="yufei.namespace1" extends="struts-default" namespace="/namespace1">  
  15.         <action name="NameSpace" class="yufei.namespace.HelloAction">  
  16.             <!-- 执行的类都是一样的,所以要让其跳转到不同的地方来看效果 -->  
  17.             <result name="success">/namespace/welcome1.jsp</result>  
  18.             <result name="error">/namespace/error1.jsp</result>  
  19.         </action>  
  20.     </package>  
  21. </struts>  


现在我们进入index.jsp,然后来提交我们刚才加入在最后的表单,现在我们是不是看到一堆烦人的鸟文了啊^_^