Решение для перезаписи URL, необходимое для JSF - PullRequest
8 голосов
/ 28 марта 2012

Предположим, что следующий ландшафт приложения:

+-----------------+
| 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/
|                 |                                   |       |
+-----------------+                                   +-------+

Как вы можете видеть, прокси-сервер (nginx в моем случае) перенаправляет запросы на один экземпляр сервера приложений, который, в свою очередь, имеет несколько веб-модулей.с разными путями контекста.Конечно, я не хочу, чтобы мой общедоступный сервер отображал корни внутреннего контекста, а прокси хорошо справлялся со своей задачей, упаковывал и разворачивал http-запросы и т. Д. Но есть еще одна большая проблема: HTML-код, сгенерированный JSF (ссылки, ресурсы CSS, JS, формадействия) содержит контекстные пути, /ctx1 и /ctx2 в моем случае.Вот чего я хочу избежать.

В настоящее время я не нахожу никакого решения, кроме как использовать все больше и больше экземпляров (доменов) сервера приложений, в результате чего мои аппаратные ресурсы исчезают.Насколько я понимаю, мне нужно расширить свои приложения JSF с помощью некоторых оберток, потенциально зарегистрированных в faces-config.xml, которые будут удалять префикс контекста в сгенерированном html.Любые другие решения также приветствуются.

Пожалуйста, укажите мне в правильном направлении.

Ответы [ 3 ]

5 голосов
/ 29 марта 2012

Для этого вы можете использовать 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/

4 голосов
/ 29 марта 2012

Я публикую решение, которое может быть полезно для других, сталкивающихся с той же проблемой. Все, что мне нужно было сделать, это реализовать свой собственный 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;
  }
}

face-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>
1 голос
/ 23 февраля 2017

Я столкнулся с той же проблемой и попробовал ваше решение. Хотя это более или менее работало, было еще несколько глюков. И, честно говоря, это больше похоже на борьбу с симптомами, а не на излечение от болезни.

Итак, вот что наконец сработало для меня:

Вместо того, чтобы разделять развертывания по пути, я назначил каждое развертывание для своего собственного порта:

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) было достаточно определить два сервера undertow в конфигурации wildfly, каждый со своим собственным виртуальным хостом и слушателем http, например, так:

<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}"/>

Вам также понадобится jboss-web.xml в вашем проекте:

<?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>

Два сервера необходимы, потому что вы не можете добавить привязку сокета к виртуальному хосту. Таким образом, здесь есть небольшие издержки, но они незначительны по сравнению с запуском двух полных серверов приложений.

Редактировать 1:

Мне только что пришло в голову, что, вероятно, даже нет необходимости использовать разные порты, и использование одного сервера undertow для каждого деплиомента, вероятно, также является излишним.

Поскольку прокси-сервер может перенаправлять хост по запросу клиента на сервер приложений, undertow должен иметь возможность выбрать правильный виртуальный хост с помощью параметра псевдонима.

Таким образом, в основном, прокси передает любой запрос на foo.com или bar.com на localhost: 8080 и позволяет AS разбираться с вещами.

Я не проверял это , но вот как это может работать (опять же, это для Wildfly 10.0):

<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>

И jboss-web.xml потеряет тег сервера:

<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
   <virtual-host>foo-host</virtual-host>
   <context-root>/</context-root>
</jboss-web>

В случае, если это работает, не будет никаких накладных расходов.

Редактировать 2:

Только что протестировал упрощенный подход - да, он работает:)

...