Struts2包中的namespace属性如何工作?

时间:2015-11-10 06:48:27

标签: struts2 namespaces

我仍然对如何在Struts2中正确使用namespace属性感到困惑。

namespace configuration中,有人提到:

  

命名空间不是路径!

     

命名空间不像文件系统路径那样是分层的。有一个命名空间级别。例如,如果请求URL /barspace/myspace/bar.action,框架将首先查找namespace / barspace / myspace。如果/ barspace / myspace中不存在该操作,则搜索将立即回退到默认命名空间“”。框架不会将命名空间解析为一系列“文件夹”。在命名空间示例中,将选择默认命名空间中的小节操作。

我试过制作一个简单的Struts2示例:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" 
                        "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
    <constant name="struts.devMode" value="true" />

    <package name="default" extends="struts-default">
        <action name="defaultIndex">
            <result name="success">/pages/default.jsp</result>
        </action>
    </package>

    <package name="package1" namespace="/" extends="struts-default">
        <action name="index1">
            <result name="success">/pages/home1.jsp</result>
        </action>
    </package>

    <package name="package2" namespace="/namespace1" extends="struts-default">
        <action name="index2">
            <result name="success">/pages/home2.jsp</result>
        </action>   
    </package>

    <package name="package3" namespace="/namespace1/namespace2" extends="struts-default">
        <action name="index3">
            <result name="success">/pages/home3.jsp</result>
        </action>
    </package>
</struts>

SampleDynamicWebProject是上下文根。

根据文档,如果我尝试

.../SampleDynamicWebProject/randomText/defaultIndex

然后,Struts2将查找/randomText命名空间并检查defaultIndex操作。如果它不存在,那么它将查找默认命名空间,即没有命名空间属性的包。

但是,如果我尝试这个网址:

.../SampleDynamicWebProject/namespace1/randomText/index2

Struts2应该查看/namespace1/randomText动作的index2命名空间,如果它看不到,那么它应该查看默认命名空间。不过,上述网址仍然指向index2中的/namespace1操作。

当我尝试

时,同样的事情正在发生
.../SampleDynamicWebProject/randomText/index1

调用根命名空间中的index1

你能说清楚它究竟是如何运作的吗?

1 个答案:

答案 0 :(得分:1)

你肯定是对的,在文档中没有提到如果命名空间是URL的一部分,它就足以使整个过程发挥作用。

但它确实,以下是它的详细工作方式:

要解析URL并调用适当的命名空间和操作,Struts2使用ActionMapper

  

ActionMapper接口提供HTTP请求和操作调用请求之间的映射,反之亦然。

有不同的实现,但默认的是DefaultActionMapper

分析网址时,会调用parseNameAndNamespace()方法。如果它不是默认的"",也不是根"/",并且alwaysSelectFullNamespace属性设置为false(这是默认值),那么the available namespaces are scanned

魔法在this line

if (ns != null 
 && prefix.startsWith(ns) 
 && (prefix.length() ==ns.length() || prefix.charAt(ns.length()) == '/')) {
    if (ns.length() > namespace.length()) {
        namespace = ns;
    }
   ///... 
}

name = uri.substring(namespace.length() + 1);

在你的例子中:

  

/ namespace1 / randomText /索引2

prefix = /namespace1/randomText/
ns     = /namespace1

在你的情况下它不是null,URI以命名空间开头,长度相同但是URI中的/namespace1字符串之后的字符是斜线,那么动作映射器决定:

namespace = /namespace1
action    = randomText/index2

这就是命名空间的原因。但是为什么它有效,因为动作名称是index2而不是randomText/index2

第二个魔法在this other line

if (!allowSlashesInActionNames) {
    int pos = name.lastIndexOf('/');
    if (pos > -1 && pos < name.length() - 1) {
        name = name.substring(pos + 1);
    }
}

如果allowSlashesInActionNames属性设置为false(这是默认值)并且操作包含斜杠(如randomText/index2中所示),则将所有内容删除到最后一个斜杠,转换{{1} } randomText/index2

然后只要你有一个以命名空间开头并以动作结尾的URI,无论中间是什么,它都有效。

它不应该使用index2,因为没有命名空间以/randomText/namespace1/index2开头。