[Struts2 in action 笔记0]让人摸不着头脑的namespace域

前言-

  这几天从网上摸到一本《Struts in Action》的pdf,开心的一逼,手里的《Thinking in Java》顿时就不香了(并发那一章150页叫人绝望啊),正好回顾一下以前的知识。到现在翻了一多半了,问题也逐渐积攒了起来,正好月末挖个坑记录一下。

  TIPS:这是笔记性质的随笔,如果赶时间,请直接跳转到末尾总结

正文-

  回到正题,namespace域,配置过action的小伙伴都知道,在Struts框架里配置Action时是有“包”这个概念的,他们可以帮助你把相同作用的Action放置在一起,就和Java包的作用一样。但是Struts中的package要比在IDE里可以直观显示出来的Java 包要抽象的多。指定完Package 的name后,后面通常还跟着两个属性--namespace和extends,就像下面这样:

<package name="portfolioEX" namespace="/" extends="struts-default">
<!-- Add your Action here -->
</package>

extends="struts-default"的意思是你的这个包继承自Struts框架下的“struts-default”包,这个包声明了大量的常用Struts2组件,从完整的一套拦截器栈到常用的结果类型。通常继承此包可以解决大部分的问题。

ps:你可以很轻易的在系统中找到Struts-default.xml文件,去看看她的真实面目。


第一个踩坑点--namespace="/"namespace="  "

  
namespace="/",指的是根命名空间,而namespace=""指的是默认命名空间,默认命名空间中与动作模式匹配的的请求都会被捕获,而根命名空间则和其他显式声明的命名空间一样,是需要匹配的。
默认命名空间在所有的命名空间之下,用来处理不能与任何显式声明的命名空间匹配的请求。根命名空间虽然需要匹配,可能是我见识的太少了,我觉得匹配不上“/”的url大概·也许·差不多没有对吧?所以使用起来很容易将两者合二为一,但她们确确实实是两样东西。

  不要尝试namespace=" "的写法,

  不要尝试namespace=" "的写法,

  不要尝试namespace=" "的写法,使用默认命名空间的做法是什么也不写,或者namespace="",引号内部不要空格,昨天这个也坑了我一道,我画掉她的意义就在于此. 


第二个踩坑点--容错性,相对路径和绝对路径

我在配置文件中尝试了三种不同的namespace配置,

配置文件
<package name="portfolioEX" extends="struts-default">
<package name="portfolioEX" namespace=“/”extends="struts-default">
<package name="portfolioEX"  namespace=“ ”extends="struts-default">
    <action name="loginform">
        <result>/tryMybook/portfolioEX/Login.jsp</result>
    </action>
    <action name="registration">                
         <result>/tryMybook/portfolioEX/Registration.jsp</result>
    </action>
</package> 

jsp页面
<ul>
  <li><a href="<s:url action='loginform'/>">Login to an Existing Account</a></li>    
  <li><a href="<s:url action='registration' namespace="/test"/>">Create an Account</a></li>        
</ul> 

开启Tomcat-》打开Jsp页面-》显示源码

<ul>
  <li><a href="/NewtourStruts/tryMybook/portfolioEX/loginform.action">Login to an Existing Account</a></li>    
  <li><a href="/NewtourStruts/test/registration.action">Create an Account</a></li>        
</ul> 

这里我们能看到s标签生成了两个天差地别的url请求(如果你一直显示找不到对应的action,尝试着看一下源码中的url,这比看s标签中的属性值要直观的多,昨天一直没有查看源代码,结果导致被饶了进去。。。)

这里说一下Struts对命名空间的容错性(借用其他博主的说法)-

程序会自动在XXX/test1/test2/下查找有没有一个action 为a 的,如果有就执行;如果没有找到,就在XXX/test1/下查找有没有一个action为a的,找到就执行;按照这个规律一直找下去,但此规律不可反向,如果还没有找到,最后就会在默认命名空间下查找,若此时还没有找到,就会报错没有对应的action。

test1:不指定namespace(使用默认命名空间)-

      

  将action放到默认命名空间,这是Struts寻找action的底线,是肯定能找得到的。。。

test2:namespace="/"(使用根命名空间)-

  效果同上,图就不截了。url匹配个"/"还不是很随意,不会出现找不到action的情况。。。

  Registration.jsp由于设置了namespace的缘故,在浏览器界面显示就没有原始目录那么繁琐,同时还能给用户一些信息。

test3:namespace=" "(使用默认命名空间)-

    

   不出所料的报错,使用namespace=""的效果参考test1.。。。

test4:使用相对路径(本来想偷个懒)

<package name="portfolioEX"  extends="struts-default">
<package name="portfolioEX"  namespace=“/” extends="struts-default">
  <action name="loginform">
    <result>./Login.jsp</result>
  </action>   <action name="registration">     <result>./Registration.jsp</result>   </action> </package>

这里将loginform的结果改成了相对路径,重复test1和test2

test1. 

首先这并不是没有找到对应的action配置,即使Registration.jsp页面报了404.。。。

Login.jsp与Registration.jsp确确实实放在了同一目录下,但是由于form中设置了namespace属性而导致请求registration的url改变(如上面查看的源码一样),使用相对路径产生了404错误。。。看到错误信息中访问Registration.jsp的连接变成了/NewtourStruts/test/./Registration.jsp。<result>中的值被简单拼接到了链接后面。

test2.  

同样,两者都匹配到了对应的action,Login.jsp由于没有做多余的动作依旧稳如老狗。

而Registration.jsp又一次报了404.。。。查看错误依旧是链接问题/NewtourStruts/test/./Registration.jsp

所以当你想要在<s>标签中通过namespace属性隐藏一些奇怪的url的时候,请务必使用绝对路径!请务必使用绝对路径!请务必使用绝对路径!

当然你也可以在任何时候都使用绝对路径,这是最稳妥的选择,如果你项目不复杂的话。


 

第三个踩坑点--设置Struts2.xml中的namespace属性后寻找action的方式

上面一直将属性namespace放在了Jsp界面,介绍了默认和根命名空间,但是namespace本质还是使用在xml中,用她来防止action重名带来的混淆。

下面我们再改一下xml

<package name="portfolioEX" namespace="/tryMybook" extends="struts-default">
  <action name="loginform">
    <result>/tryMybook/portfolioEX/Login.jsp</result>
  </action>
  <action name="registration">
    <result>/tryMybook/portfolioEX/Registration.jsp</result>
  </action>
 </package>

有两个action被放在了叫/tryMybook的namespace中。

test1.Jsp页面不做更改

Jsp界面如果不变的话,

<ul>
  <li><a href="<s:url action='loginform'/>">Login to an Existing Account</a></li>          =》<a href="/NewtourStruts/tryMybook/portfolioEX/loginform.action"/>  
  <li><a href="<s:url action='registration' namespace="/test"/>">Create an Account</a></li>   =》<a href="/NewtourStruts/test/registration.action">
<ul>

 说了Struts2命名空间的容错性,回想一下,大概就知道了

这里loginform由于没有指定namespace,她寻找action的过程就会变成如下这样:

1.首先找在xml中是否有namespace设置成“/tryMybook/portfolioEX”的package,如果有,找她的所有action。如果没有找到,执行第二步。

2.找xml中是否有namespace设置成“/tryMybook”的package,如果有,找她的所有action。如果没有找到,执行第三步。

3.··········如上继续直到找到默认命名空间,如果途中找到了,执行第四步,否则,执行第五步

4.执行action的相关配置

5.产生错误信息

这里第二步就能找到,所以Login正常显示    

而registration,就不行了,她会一直找到默认命名空间,但是我们已经在xml设置了namespace,她注定找不到action最终报错。

解决方案也很简单修改Jsp表单中Registration的namespace使其由/tryMybook开头即可。

不要去尝试“/test/tryMybook” ,问为什么的话重新看上面那五步。。。你会先找"/test/tryMybook",再找"/test"最后落入默认空间。

test2.也不要去尝试xml中配置namespace="/portfolioEX"这种路径中的同名namespace

<package name="portfolioEX" namespace="/portfolioEX" extends="struts-default">
  <action name="loginform">
    <result>/tryMybook/portfolioEX/Login.jsp</result>
  </action>
  <action name="registration">
    <result>/tryMybook/portfolioEX/Registration.jsp</result>
  </action>
 </package>

此时如果还不修改Jsp文件中的loginform也会找不到action,你只要仔细重复就会发现,loginform只会寻找"/tryMybook/portfolioEX"而不是单独的”/portfolioEX“。

这样你就只能在s标签中同步设置"/portfolioEX"或"/portfolioEX/XXX"

具体为什么查看一下源码就明白了


 

总结-

1.根命名空间!=默认命名空间  真要使用默认命名空间请使用namespace=""或什么也不要写。

2.在配置action的时候请尽量使用绝对路径

 在<package>中指定了namespace,不仅为action提供了namespace,也同时规定了result返回结果的路径。 在result中可以使用绝对路径和相对路径对返回结果进行配置,绝对路径以"/"开头,代表了Web应用程序上下文的根目录,相对路径不以"/"开头。 绝对路径不受Action的namespace影响,而相对路径则以Action的namespace为根路径。

   P.S. 在result返回结果时,如果采用默认namespace,并且返回结果在根目录下,也请使用绝对路径,不要使用相对路径。否则当form中的 namspace无法匹配struts.xml中的namespace,那么会在默认namespace中找,如果找到的result返回结果采用相对路 径,那么会使用form中的namespace作为根路径继续访问

3.牢记Struts的容错性寻找action的顺序,是按路径一层一层往外,而非以一个个单独的package寻找

4.使用<s>标记时,找不到action记得打开网页源代码确认url,这可能有效

 

 
 

猜你喜欢

转载自www.cnblogs.com/YFEYI/p/12602247.html