JSF所需的URL重写解决方案

Osw*_*Osw 8 java jsf web-applications jsf-2 prettyfaces

假设以下应用程序格局:

+-----------------+
| App server      |
+-----------------+
|                 |                                   +-------+
| ear1            |                                   |       |
|  +-web1 (/ctx1) +--<-- http://localhost/ctx1/xxx/ --+       +--<-- http://www.example.com/xxx/
|                 |                                   |       |
|                 |                                   | proxy |
| ear2            |                                   |       |
|  +-web2 (/ctx2) +--<-- http://localhost/ctx2/yyy/ --+       +--<-- http://abc.example.com/yyy/
|                 |                                   |       |
+-----------------+                                   +-------+
Run Code Online (Sandbox Code Playgroud)

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

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

请指出我正确的方向.

Osw*_*Osw 7

我正在发布可能对面临同样问题的其他人有帮助的解决方案。我需要做的就是实现我自己的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<String, List<String>> 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;
  }
}
Run Code Online (Sandbox Code Playgroud)

面孔-config.xml :

<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
              version="2.0">
  <application>
    <view-handler>test.CustomViewHandler</view-handler>
  </application>
</faces-config>
Run Code Online (Sandbox Code Playgroud)

  • 注意:这也可以使用“过滤器”和少于一半的代码来完成。 (3认同)

Lin*_*oln 5

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

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

.defineRule()
.when(URL.matches("{prefix}" + context.getContextPath() + "{suffix}")
.perform(Substitute.with("{prefix}{suffix}"))
Run Code Online (Sandbox Code Playgroud)

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