JSF。 需要URL重写解决方案

假设以下应用程序格局:

+-----------------+ | App server | +-----------------+ | | +-------+ | ear1 | | | | +-web1 (/ctx1) +--<-- http://localhost/ctx1/xxx/ --+ +--<-- http://www.domain.com/xxx/ | | | | | | | proxy | | ear2 | | | | +-web2 (/ctx2) +--<-- http://localhost/ctx2/yyy/ --+ +--<-- http://abc.domain.com/yyy/ | | | | +-----------------+ +-------+ 

正如您所看到的,代理(在我的情况下是nginx )是将请求转发到单个应用程序服务器实例,而后者又有多个具有不同上下文路径的Web模块。 当然我不希望我的公共服务器暴露内部上下文根和代理它的工作做得好,包装和解包http请求等等。但仍然有一个大问题:JSF生成的HTML代码(链接,css,js资源,表单actions)包含上下文路径,在我的例子中是/ctx1/ctx2 。 这就是我想要避免的。

除了使用越来越多不同的应用服务器实例(域)之外,我现在没有解决方案,导致我的硬件资源逐渐消失。 据我了解,我需要使用一些包装器来扩展我的JSF应用程序,这些包装器可能在faces-config.xml注册,这将删除生成的html中的上下文前缀。 还欢迎任何其他解决方案。

请指出我正确的方向。

你可以使用OCPsoft Rewrite URLRewriteFilter (目前不是PrettyFaces,但你可以同时使用它们,直到它们在PrettyFaces 4发布后正式连接在一起 – Rewrite是PrettyFaces 4的核心项目)

使用单个配置规则,执行此类操作应该相当简单。 如果这条规则过于严格或过于笼统,你显然可以摆弄。

 .defineRule() .when(URL.matches("{prefix}" + context.getContextPath() + "{suffix}") .perform(Substitute.with("{prefix}{suffix}")) 

看看重写网站。 这很容易设置。 http://ocpsoft.org/rewrite/

我发布的解决方案可能对面临同样问题的其他人有所帮助。 我需要做的就是实现我自己的javax.faces.application.ViewHandler并在faces-config.xml注册它:

 public class CustomViewHandler extends ViewHandlerWrapper { private ViewHandler wrappped; public CustomViewHandler(ViewHandler wrappped) { super(); this.wrappped = wrappped; } @Override public ViewHandler getWrapped() { return wrappped; } @Override public String getActionURL(FacesContext context, String viewId) { String url = super.getActionURL(context, viewId); return removeContextPath(context, url); } @Override public String getRedirectURL(FacesContext context, String viewId, Map> parameters, boolean includeViewParams) { String url = super.getRedirectURL(context, viewId, parameters, includeViewParams); return removeContextPath(context, url); } @Override public String getResourceURL(FacesContext context, String path) { String url = super.getResourceURL(context, path); return removeContextPath(context, url); } private String removeContextPath(FacesContext context, String url) { ServletContext servletContext = (ServletContext) context.getExternalContext().getContext(); String contextPath = servletContext.getContextPath(); if("".equals(contextPath)) return url; // root context path, nothing to remove return url.startsWith(contextPath) ? url.substring(contextPath.length()) : url; } } 

faces-config.xml:

   test.CustomViewHandler   

我遇到了同样的问题并尝试了你的解决方案。 虽然它或多或少有效,但仍然存在一些问题。 说实话,感觉更像是对抗症状而不是治愈疾病。

所以这就是最终对我有用的东西:

我没有通过路径分配部署,而是将每个部署分配到自己的端口:

 foo.war <-- http://localhost:8080/ -- | Proxy | <-- http://www.foo.com -- | Client | bar.war <-- http://localhost:8181/ -- | Proxy | <-- http://www.bar.com -- | Client | 

这样,两个部署都可以使用/作为其上下文路径,因此无需编辑上下文路径。

要实现此目的,您不必运行两个应用程序服务器。 在我的情况下(Wildfly 10.0),在wildfly配置中定义两个underow服务器就足够了,每个服务器都有自己的虚拟主机和http监听器,如下所示:

           

您还需要在项目中使用jboss-web.xml:

   foo-server foo-host /  

需要两台服务器,因为您无法将套接字绑定添加到虚拟主机。 因此这里有一点点开销,但与运行两个完整的应用服务器相比可忽略不计。

编辑1:

它只是发生在我身上,甚至可能不需要使用不同的端口,并且每个deplyoment使用一个底部服务器也可能是多余的。

由于代理能够根据客户端的请求将主机转发到应用程序服务器,因此应该能够通过别名参数选择适当的虚拟主机。

所以基本上,代理会将任何请求转发到foo.com或bar.com到localhost:8080并让AS解决问题。

我没有对此进行过测试 ,但是这里的工作原理(再次,这是针对Wildfly 10.0):

      

并且jboss-web.xml会丢失服务器标记:

   foo-host /  

如果这样可行,则根本不涉及任何开销。

编辑2:

刚刚测试了简化的方法 - 是的,它的工作原理:)