我仍然对如何在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
。
你能说清楚它究竟是如何运作的吗?
答案 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
开头。