我正在尝试创建类似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;。
答案 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>
这并不像我一开始希望的那样容易实现,但是一旦所有内容都更新,它似乎会满足我的需求。
如果没有更好的建议,我会在几天内接受这个。