Struts2 包中的命名空间属性是如何工作的? [英] How does the namespace attribute in a Struts2 package work?

查看:42
本文介绍了Struts2 包中的命名空间属性是如何工作的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对如何在 Struts2 中正确使用命名空间属性仍然感到困惑.

I am still confused how to properly use the namespace attribute in Struts2.

命名空间配置中提到:

命名空间不是路径!

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

Namespace are not hierarchical like a file system path. There is one namespace level. For example if the URL /barspace/myspace/bar.action is requested, the framework will first look for namespace /barspace/myspace. If the action does not exist at /barspace/myspace, the search will immediately fall back to the default namespace "". The framework will not parse the namespace into a series of "folders". In the Namespace Example, the bar action in the default namespace would be selected.

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

I have tried making a simple Struts2 sample:

<?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 操作.如果它不存在,那么它将寻找默认命名空间,即没有命名空间属性的包.

Then, Struts2 will look for the /randomText namespace and check for the defaultIndex action. If it doesn't exist, then it will look for the default namespace which is the package with no namespace attribute.

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

But if I try this URL:

.../SampleDynamicWebProject/namespace1/randomText/index2

Struts2 应该查看 /namespace1/randomText 名称空间的 index2 操作,如果它看不到,那么它应该查看默认名称空间.但是,上面的 URL 仍然指向 /namespace1 中的 index2 操作.

Struts2 should look at the /namespace1/randomText namespace for the index2 action and if it cannot see one, then it should look at the default namespace. However, the URL above is still directed at the index2 action in the /namespace1.

当我尝试时发生了同样的事情

The same thing is happening when I try

.../SampleDynamicWebProject/randomText/index1

调用根命名空间中的index1.

你能解释一下它是如何工作的吗?

Can you please clarify how exactly it works?

推荐答案

您绝对是对的,文档中没有任何地方提到如果名称空间是 URL 的一部分,就足以使整个事情正常工作.

You're definitely right, nowhere in the documentation is mentioned that if a namespace is part of the URL, it is enough to make the whole thing work.

但确实如此,以下是它的详细工作原理:

But it does, and here is how it works in detail:

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

To parse an URL and call the appropriate namespace and action, Struts2 uses an ActionMapper:

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

The ActionMapper interface provides a mapping between HTTP requests and action invocation requests and vice-versa.

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

There are different implementations, but the default one is the DefaultActionMapper.

当分析一个 URL 时,parseNameAndNamespace() 方法被调用.如果它不是默认的 "" 也不是根 "/" 之一,并且 alwaysSelectFullNamespace 属性设置为 false>(这是默认值),然后 扫描可用的命名空间:

When an URL is analyzed, the parseNameAndNamespace() method is invoked. If it's not the default "" nor the root "/" one, and the alwaysSelectFullNamespace attribute is set to false (that is the default), then the available namespaces are scanned:

神奇之处在于 这一行:

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/index2

/namespace1/randomText/index2

prefix = /namespace1/randomText/
ns     = /namespace1

在您的情况下,它不为空,URI 以命名空间开头,长度相同,但 URI 中 /namespace1 字符串后面的字符是一个斜杠,然后动作映射器决定:

In your case it is not null, the URI starts with the namespace, the length is not the same BUT the character after the /namespace1 String in the URI is a slash, then the action mapper decides that:

namespace = /namespace1
action    = randomText/index2

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

This is why the namespace is taken. But then why it works, since the action name is index2 and not randomText/index2 ?

第二个魔法在 另一行:

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

如果 allowSlashesInActionNames 属性设置为 false(这是默认值)并且操作包含斜杠(如在 randomText/index2 中),则将所有内容剥离到最后一个斜线,在 index2 中转换 randomText/index2.

If the allowSlashesInActionNames attribute is set to false (that is the default) and the action contains slashes (like in randomText/index2), then strips everything up to the last slash, transforming randomText/index2 in index2.

然后只要您有一个以命名空间开头并以操作结尾的 URI,无论中间是什么,它都可以工作.

Then as long as you have an URI that is starting with a namespace and ending with an action, no matter what's in the middle, it works.

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

It should not work instead using /randomText/namespace1/index2, because no namespace is starting with /randomText.

这篇关于Struts2 包中的命名空间属性是如何工作的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆