Java JSF需要的URL重写解决方案

Java JSF需要的URL重写解决方案,java,jsf,web-applications,jsf-2,prettyfaces,Java,Jsf,Web Applications,Jsf 2,Prettyfaces,假设以下应用程序环境: +-----------------+ | App server | +-----------------+ | | +-------+ | ear1 | | | | +-web1 (/ctx1) +--<-- http://localhost/ctx1/

假设以下应用程序环境:

+-----------------+
| 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/
|                 |                                   |       |
+-----------------+                                   +-------+
+-----------------+
|应用服务器|
+-----------------+
|                 |                                   +-------+
|ear1 | ||

|+-web1(/ctx1)+--我发布的解决方案可能对其他面临相同问题的人有所帮助。我所需要做的就是实现我自己的
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;
  }
}
公共类CustomViewHandler扩展了ViewHandlerWrapper{
私有视图处理程序包装;
公共CustomViewHandler(ViewHandler包装){
超级();
this.wrapped=wrapped;
}
@凌驾
公共ViewHandler getWrapped(){
返回包装;
}
@凌驾
公共字符串getActionURL(FacesContext上下文,字符串viewId){
字符串url=super.getActionURL(上下文,视图ID);
返回removeContextPath(上下文、url);
}
@凌驾
公共字符串getRedirectURL(FacesContext上下文、字符串viewId、映射参数、布尔IncludeDeviceWParams){
字符串url=super.getRedirectURL(上下文、视图ID、参数、includeViewParams);
返回removeContextPath(上下文、url);
}
@凌驾
公共字符串getResourceURL(FacesContext上下文,字符串路径){
字符串url=super.getResourceURL(上下文,路径);
返回removeContextPath(上下文、url);
}
私有字符串removeContextPath(FacesContext上下文,字符串url){
ServletContext ServletContext=(ServletContext)context.getExternalContext().getContext();
字符串contextPath=servletContext.getContextPath();
如果(“.equals(contextPath))返回url;//根上下文路径,则没有要删除的内容
返回url.startsWith(contextPath)?url.substring(contextPath.length()):url;
}
}
faces-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>

test.CustomViewHandler
您可以使用它(目前不是PrettyFaces,但您可以同时使用它们,直到它们在PrettyFaces 4发布后正式结合在一起-重写是PrettyFaces 4的核心项目)

使用单个配置规则执行类似操作应该相当简单。如果这条规则太严格或太笼统,你显然可以胡闹

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

查看重写站点。设置起来很容易

我也面临同样的问题,并尝试了你的解决方案。虽然它或多或少在工作,但仍有一些小故障。老实说,这感觉更像是对抗症状而不是治愈疾病

以下是最终对我有效的方法:

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

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

foo.war嗨,林肯!它是否也适用于css、js和我页面上的其他资源?只要这些链接是通过JSF呈现的,而不是在HTML中硬编码,那么是的,绝对可以。否则,您可以设置其他规则来处理该场景。注意:这也可以通过
过滤器和少于一半的代码来完成。@BalusC,今天我正要实现您的过滤器解决方案,但是被你的帖子被删除的事实吓跑了。)我删除它只是因为它根本不值得付出努力。使用预先构建的URL重写过滤器!有很多选择@BalusC,您好,仅供参考:正如您所建议的,刚刚测试了
Fliter
,除了部分请求之外,所有都可以正常工作,似乎ajax不支持请求的上下文路径。
<server name="foo-server">
   <http-listener name="foo-listener" proxy-address-forwarding="true" socket-binding="foo-http"/>
   <host name="foo-host" default-web-module="foo.war" alias="localhost, foo.com, wwww.foo.com"/>
</server>
<server name="bar-server">
   <http-listener name="bar-listener" proxy-address-forwarding="true" socket-binding="bar-http"/>
   <host name="bar-host" default-web-module="bar.war" alias="localhost, bar.com, wwww.bar.com"/>
</server>

<socket-binding name="foo-http" port="${jboss.http.port:8080}"/>
<socket-binding name="bar-http" port="${jboss.http.port:8181}"/>
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
   <server-instance>foo-server</server-instance>
   <virtual-host>foo-host</virtual-host>
   <context-root>/</context-root>
</jboss-web>
<server name="default-server">
   <http-listener name="http" proxy-address-forwarding="true" socket-binding="http"/>
   <host name="foo-host" default-web-module="foo.war" alias="foo.com, wwww.foo.com"/>
   <host name="bar-host" default-web-module="bar.war" alias="bar.com, wwww.bar.com"/>
</server>
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
   <virtual-host>foo-host</virtual-host>
   <context-root>/</context-root>
</jboss-web>