命名空间开头的变量(或等效的)

时间:2014-12-15 23:31:59

标签: struts2

我正在尝试创建类似http://localhost:8080/app/client/shared-namespaces-and-actions的网址:

  • /app”将是上下文根。
  • client”实际上是一个变量,取而代之的是应用程序的实际客户端版本/接口,例如 “john”(即: http://localhost:8080/app/john/namespaces-and-actions)。
  • /shared-namespaces-and-actions”将是包/操作 可在一个或多个客户端下访问(例如“/ about / contact”,或 “/产品/ 73 /编辑”)。

理想情况下,URL可以完全省略“客户端”组件,因此对于有意义的操作,可以显示某种组合视图。例如,“/app/”会显示指向客户端版本的链接,而客户端的“/app/client/”则会显示客户在其主页上所需的内容。

这个变量“客户端”组件是我有疑问的。

到目前为止,我一直在使用查询字符串参数来处理客户端选择,而不是URL路径的一部分。但是,对于像书签这样的事情,这有一些明显的问题,因为我总是要在查询字符串中传递客户端参数(不具吸引力),否则书签将失败。

有没有简单的方法来进行此更改?看起来我想要的是命名空间中的通配符,就像我对操作一样,但文档似乎并不支持这种可能性,也没有进行实验。我已经使用包来设置命名空间,拦截器堆栈以及在struts.xml文件中对相关操作进行分组,因此将所有操作更改为" /"名称空间包,其中包含客户端的附加通配符。

我看到的一个选项是扩展类DefaultActionMapper,并覆盖方法parseNameAndNamespace(String, ActionMapping, ConfigurationManager),删除URI的客户端组件(如果存在),然后将修改后的URI传递给父实现。但是,这有许多问题,例如破坏所有链接,表单目标和重定向。我希望修复链接/表单会很烦人,但并非不可能,但我不确定重定向是否也是如此。

我正在使用2.3.16.3。


struts.xml中:

<struts>
    <constant name="struts.enable.SlashesInActionNames" value="true" />
    <constant name="struts.mapper.alwaysSelectFullNamespace" value="false" />
    <constant name="struts.patternMatcher" value="namedVariable"/>

    <constant name="struts.action.extension" value="" />

    <package
        name="poc-default"
        extends="struts-default"
        strict-method-invocation="true">
        <default-interceptor-ref name="defaultStack" />
        <default-action-ref name="http404" />
        <action
            name="http404"
            class="poc.DefaultAction">
            <result name="success">/WEB-INF/http404.jsp</result>
        </action>
    </package>

<package
    name="root"
    namespace="/"
    extends="poc-default"
    strict-method-invocation="true">
    <action
        name=""
        class="poc.DefaultAction">
        <result name="success">/WEB-INF/home.jsp</result>
    </action>
    <action
        name="clients"
        class="poc.DefaultAction">
        <result name="success">/WEB-INF/client-select.jsp</result>
    </action>
</package>
</struts>

使用上面的struts.xml,&#34; http://localhost:8080/poc/&#34;转到主页,&#34; http://localhost:8080/poc/clients&#34;转到客户选择页面。

然后我更换包&#34; root&#34;使用以下内容(将命名通配符添加到命名空间):

<package
    name="root"
    namespace="/{uriClientString}/"
    extends="poc-default"
    strict-method-invocation="true">
    <action
        name=""
        class="poc.DefaultAction">
        <result name="success">/WEB-INF/home.jsp</result>
    </action>
    <action
        name="clients"
        class="poc.DefaultAction">
        <result name="success">/WEB-INF/client-select.jsp</result>
    </action>
</package>

现在,这两个操作都没有映射到网址&#34; http://localhost:8080/poc/john/&#34;和&#34; http://localhost:8080/poc/john/clients&#34;。

1 个答案:

答案 0 :(得分:0)

给Dave Newton的评论一些想法,我相信他是正确的,我正在解决我的问题(可选的客户端选择器前缀到URL)可能不是我应该怎么做。

URL重写似乎是更好(和可能)的选择,而是通过请求的属性将客户端置于上下文中。我在web.xml中的Strut 2过滤器之前创建了一个过滤器:

@Override
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
        throws ServletException, IOException {
    final HttpServletRequest httpRequest = (HttpServletRequest) request;
    final String requestServletPath = httpRequest.getServletPath();

    // Obtain set of client strings here.
    final List<String> clients = Arrays.asList("john");

    String newServletPath = null;
    for (String client : clients) {
        final String toCheck = "/" + client;
        if (requestServletPath.equals(toCheck) || requestServletPath.startsWith(toCheck + "/")) {
            /*
             * Put client into context here, {@link HttpSession#setAttribute(String, Object)} or
             * {@link ServletRequest#setAttribute(String, Object)}.
             */
            request.setAttribute("uriClientString", toCheck);
            newServletPath = requestServletPath.substring(toCheck.length());
            break;
        }
    }

    if (newServletPath != null)
        request.getRequestDispatcher(newServletPath).forward(request, response);
    else
        chain.doFilter(request, response);
}

还有必要使用Struts 2的过滤器映射来支持前进:

<filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>

不幸的是,有必要重写生成的URL以包含客户端前缀(如果正在使用它),否则Struts2将从实际命名空间开始:

<s:a namespace="%{#request.uriClientString}" action="">Home page</s:a>

最后,如果正在使用重定向,还必须重写重定向以包含客户端前缀,因为Struts2将再次从实际命名空间开始:

<action name="re">
    <result type="redirectAction">
        <param name="namespace">${#request.uriClientString}</param>
        <param name="actionName">clients</param>
    </result>
</action>

这并不像我一开始希望的那样容易实现,但是一旦所有内容都更新,它似乎会满足我的需求。

如果没有更好的建议,我会在几天内接受这个。