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

内容简介:
这篇文章将会通过实例详细介绍 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. <%@pagelanguage="java"import="java.util.*"pageEncoding="GB18030"%>
  2. <%@taglibprefix="s"uri="/struts-tags"%>
  3. <!--使用struts标签必需在这里倒入-->
  4. <!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.01Transitional//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. <tableborder="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. <formaction="test.jsp"method="post">
  28. <inputtype="submit"value="html表单访问test.jsp"/>
  29. </form>
  30. </td>
  31. <td>
  32. action="test.jsp"
  33. <s:formaction="test.jsp">
  34. <s:submitvalue="struts表单标签访问test.jsp"/>
  35. </s:form>
  36. </td>
  37. <tr>
  38. <tr>
  39. <td>
  40. action="/test.jsp"
  41. <formaction="/test.jsp"method="post">
  42. <inputtype="submit"value="html表单访问test.jsp"/>
  43. </form>
  44. </td>
  45. <td>
  46. action="/test.jsp"
  47. <s:formaction="/test.jsp">
  48. <s:submitvalue="struts表单标签访问test.jsp"/>
  49. </s:form>
  50. </td>
  51. <tr>
  52. <tr>
  53. <td>
  54. action="./test.jsp"
  55. <formaction="./test.jsp"method="post">
  56. <inputtype="submit"value="html表单访问test.jsp"/>
  57. </form>
  58. </td>
  59. <td>
  60. action="./test.jsp"
  61. <s:formaction="./test.jsp">
  62. <s:submitvalue="struts表单标签访问test.jsp"/>
  63. </s:form>
  64. </td>
  65. <tr>
  66. <tr>
  67. <td>
  68. action="../test.jsp"
  69. <formaction="../test.jsp"method="post">
  70. <inputtype="submit"value="html表单访问test.jsp"/>
  71. </form>
  72. </td>
  73. <td>
  74. action="../test.jsp"
  75. <s:formaction="../test.jsp">
  76. <s:submitvalue="struts表单标签访问test.jsp"/>
  77. </s:form>
  78. </td>
  79. <tr>
  80. <tr>
  81. <td>
  82. action="/Struts2Study/namespace/test.jsp"
  83. <formaction="/Struts2Study/namespace/test.jsp"method="post">
  84. <inputtype="submit"value="html表单访问test.jsp"/>
  85. </form>
  86. </td>
  87. <td>
  88. action="/namespace/test.jsp"
  89. <s:formaction="/namespace/test.jsp">
  90. <s:submitvalue="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. <%@pagelanguage="java"import="java.util.*"pageEncoding="GB18030"%>
  2. <%@taglibprefix="s"uri="/struts-tags"%>
  3. <!--要使用struts的标签就要先倒入-->
  4. <!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.01Transitional//EN">
  5. <html>
  6. <head>
  7. <title>第一个Struts程序</title>
  8. </head>
  9. <body>
  10. <center>
  11. action="NameSpace.action"
  12. <formaction="NameSpace.action"method="post">
  13. <tablealign="center">
  14. <caption><h3>用户登录</h3></caption>
  15. <tr>
  16. <td>用户名:<inputtype="text"name="username"/></td>
  17. </tr>
  18. <tr>
  19. <td>密码:<inputtype="text"name="password"/></td>
  20. </tr>
  21. <tralign="center">
  22. <tdcolspan="2"><inputtype="submit"value="登录"/>
  23. <inputtype="reset"value="重填"/></td>
  24. </tr>
  25. </table>
  26. </form>
  27. action="/Struts2Study/namespace/NameSpace.action"
  28. <formaction="/Struts2Study/namespace/NameSpace.action"method="post">
  29. <tablealign="center">
  30. <caption><h3>用户登录</h3></caption>
  31. <tr>
  32. <td>用户名:<inputtype="text"name="username"/></td>
  33. </tr>
  34. <tr>
  35. <td>密码:<inputtype="text"name="password"/></td>
  36. </tr>
  37. <tralign="center">
  38. <tdcolspan="2"><inputtype="submit"value="登录"/>
  39. <inputtype="reset"value="重填"/></td>
  40. </tr>
  41. </table>
  42. </form>
  43. action="/Struts2Study/NameSpace.action"
  44. <formaction="/Struts2Study/NameSpace.action"method="post">
  45. <tablealign="center">
  46. <caption><h3>用户登录</h3></caption>
  47. <tr>
  48. <td>用户名:<inputtype="text"name="username"/></td>
  49. </tr>
  50. <tr>
  51. <td>密码:<inputtype="text"name="password"/></td>
  52. </tr>
  53. <tralign="center">
  54. <tdcolspan="2"><inputtype="submit"value="登录"/>
  55. <inputtype="reset"value="重填"/></td>
  56. </tr>
  57. </table>
  58. </form>
  59. <br>
  60. <h5>以下是使用struts的form标签</h5>
  61. <br>
  62. action="NameSpace"
  63. <s:formaction="NameSpace">
  64. <s:textfieldname="username"label="用户名"/>
  65. <s:textfieldname="password"label="密码"/>
  66. <s:submitvalue="登录"/>
  67. </s:form>
  68. action="/namespace/NameSpace.action"
  69. <s:formaction="/namespace/NameSpace.action">
  70. <s:textfieldname="username"label="用户名"/>
  71. <s:textfieldname="password"label="密码"/>
  72. <s:submitvalue="登录"/>
  73. </s:form>
  74. action="/NameSpace.action"
  75. <s:formaction="/NameSpace.action">
  76. <s:textfieldname="username"label="用户名"/>
  77. <s:textfieldname="password"label="密码"/>
  78. <s:submitvalue="登录"/>
  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. <!--error1.jsp-->
  7. <body>
  8. whoareyou?idon'tknowyou,i'llcallmydogifyouwon'tgo<br>
  9. namespace/error1.jsp
  10. </body>
  11. <!--welcome.jsp-->
  12. <body>
  13. 你好啊亲爱滴,我等你很久了<br>
  14. namespace/welcome.jsp
  15. </body>
  16. <!--welcome1.jsp-->
  17. <body>
  18. hi,darlin,iwaitforyouforalongtime<br>
  19. namespace/welcome1.jsp
  20. </body>




接下来在新建包yufei.namespace,然后从hello把HelloAction.java复制过去,不用修改代码
HelloAction.java

Java代码 复制代码
  1. packageyufei.namespace;
  2. publicclassHelloAction
  3. {
  4. privateStringusername;
  5. privateStringpassword;
  6. publicStringgetPassword()
  7. {
  8. returnpassword;
  9. }
  10. publicvoidsetPassword(Stringpassword)
  11. {
  12. this.password=password;
  13. }
  14. publicStringgetUsername()
  15. {
  16. returnusername;
  17. }
  18. publicvoidsetUsername(Stringusername)
  19. {
  20. this.username=username;
  21. }
  22. publicStringexecute()
  23. {
  24. StringstrReturn="error";
  25. if(username.equals("yufei"))
  26. strReturn="success";
  27. returnstrReturn;
  28. }
  29. }



接着我们在yufei.namespace包中新建一个xml文件namespace.xml,并且在struts.xml文件中加入以下内容

Java代码 复制代码
  1. <!--倒入其它配置文件-->
  2. <includefile="yufei/namespace/namespace.xml"/>



namespace.xml的代码如下,这些前篇文章都讲过了,这里不再说了

Java代码 复制代码
  1. <?xmlversion="1.0"encoding="GBK"?>
  2. <!DOCTYPEstrutsPUBLIC
  3. "-//ApacheSoftwareFoundation//DTDStrutsConfiguration2.0//EN"
  4. "http://struts.apache.org/dtds/struts-2.0.dtd">
  5. <struts>
  6. <packagename="yufei.namespace"extends="struts-default">
  7. <actionname="NameSpace"class="yufei.namespace.HelloAction">
  8. <resultname="success">/namespace/welcome.jsp</result>
  9. <resultname="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. <?xmlversion="1.0"encoding="GBK"?>
  2. <!DOCTYPEstrutsPUBLIC
  3. "-//ApacheSoftwareFoundation//DTDStrutsConfiguration2.0//EN"
  4. "http://struts.apache.org/dtds/struts-2.0.dtd">
  5. <struts>
  6. <!--新加上namespace-->
  7. <packagename="yufei.namespace"extends="struts-default"namespace="/namespace">
  8. <actionname="NameSpace"class="yufei.namespace.HelloAction">
  9. <resultname="success">/namespace/welcome.jsp</result>
  10. <resultname="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的,这是我自己的理解,没有任何资料参考,如有什么不妥之处请邮件告知([email protected])

以今天这个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. <packagename="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:formaction="/namespace1/NameSpace.action">
  3. <s:textfieldname="username"label="用户名"/>
  4. <s:textfieldname="password"label="密码"/>
  5. <s:submitvalue="登录"/>
  6. </s:form>
  7. <!--加入到最后-->



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



最后我们来做一个同名action的试验来结束名称空间的讲解,看不同名称空间,同名action是某可以使用
修改namespace.xml如下

Java代码 复制代码
  1. <?xmlversion="1.0"encoding="GBK"?>
  2. <!DOCTYPEstrutsPUBLIC
  3. "-//ApacheSoftwareFoundation//DTDStrutsConfiguration2.0//EN"
  4. "http://struts.apache.org/dtds/struts-2.0.dtd">
  5. <struts>
  6. <!--新加上namespace-->
  7. <packagename="yufei.namespace"extends="struts-default"namespace="/namespace">
  8. <actionname="NameSpace"class="yufei.namespace.HelloAction">
  9. <resultname="success">/namespace/welcome.jsp</result>
  10. <resultname="error">/namespace/error.jsp</result>
  11. </action>
  12. </package>
  13. <!--packagename不能出现重复的-->
  14. <packagename="yufei.namespace1"extends="struts-default"namespace="/namespace1">
  15. <actionname="NameSpace"class="yufei.namespace.HelloAction">
  16. <!--执行的类都是一样的,所以要让其跳转到不同的地方来看效果-->
  17. <resultname="success">/namespace/welcome1.jsp</result>
  18. <resultname="error">/namespace/error1.jsp</result>
  19. </action>
  20. </package>
  21. </struts>



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

你可能感兴趣的:(namespace)