Любые умные способы обработки контекста в веб-приложении? - PullRequest
39 голосов
/ 24 сентября 2008

В Java веб-приложения включены в WAR-файлы. По умолчанию многие контейнеры сервлетов используют имя WAR в качестве имени контекста для приложения.

Таким образом myapp.war развернут на http://example.com/myapp.

Проблема в том, что веб-приложение считает, что его «корень», ну, «root» или просто «/», тогда как HTML будет считать корень вашего приложения «/myapp".

».

Servlet API и JSP имеют средства, помогающие справиться с этим. Например, если в сервлете вы делаете: response.sendRedirect ("/ mypage.jsp"), контейнер будет предшествовать контексту и создаст URL: http://example.com/myapp/mypage.jsp".

Однако вы не можете сделать это, скажем, с помощью тега IMG в HTML. Если вы сделаете image, скорее всего, вы получите 404, потому что вы действительно хотели "/myapp/myimage.gif".

Многие фреймворки имеют теги JSP, которые также учитывают контекст, и существуют разные способы создания правильных URL-адресов в JSP (ни один из них не особенно элегантен).

Для программистов это непростая проблема: когда нужно использовать URL-адрес App Relative против абсолютного URL-адреса.

Наконец, существует проблема с кодом Javascript, который должен создавать URL-адреса на лету, и встроенные URL-адреса в CSS (для фоновых изображений и т. П.).

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

Что ты делаешь?

Ответы [ 14 ]

0 голосов
/ 12 декабря 2017

Вот лучший способ: Фильтр перенаправления контекста Фильтр должен быть применен в точке расширения перед совпадением и, следовательно, использовать аннотацию @ PreMatching.

Фильтры, реализующие этот интерфейс, должны быть аннотированы @Provider для обнаружения средой выполнения JAX-RS. Экземпляры фильтра запросов контейнера также могут быть обнаружены и динамически привязаны к конкретным методам ресурсов.

Поясняется с примером кода:

http://writeulearn.com/java-filters/

0 голосов
/ 08 сентября 2016

Я склонен писать свойство как часть моей основной библиотеки JavaScript внутри моей. Я не думаю, что это идеально, но я думаю, что это лучшее, чего мне удалось достичь.

Во-первых, у меня есть модуль, который является частью моего ядра приложения, который всегда доступен

(function (APP) {
  var ctx;
  APP.setContext = function (val) {
    // protect rogue JS from setting the context.
    if (ctx) {
      return;
    }
    val = val || val.trim();
    // Don't allow a double slash for a context.
    if (val.charAt(0) === '/' && val.charAt(1) === '/') {
      return;
    }
    // Context must both start and end in /.
    if (val.length === 0 || val === '/') {
      val = '/';
    } else {
      if (val.charAt(0) !== '/') {
        val = '/' + val;
      }
      if (val.slice(-1) !== '/') {
        val += '/';
      }
    }
    ctx = val;
  };
  APP.getContext = function () {
    return ctx || '/';
  };
  APP.getUrl = function (val) {
    if (val && val.length > 0) {
      return APP.getContext() + (val.charAt(0) === '/' ? val.substring(1) : val);
    }
    return APP.getContext();
  };
})(window.APP = window.APP || {});

Затем я использую плитки Apache с общим заголовком, который всегда содержит следующее:

<script type="text/javascript">
  APP.setContext('${pageContext.request['contextPath']}');
  // If preferred use JSTL cor, but it must be available and declared.
  //APP.setContext('<c:url value='/'/>');
</script>

Теперь, когда я инициализировал контекст, я могу использовать getUrl(path) из любого места (файлы js или внутри jsp / html), которые будут возвращать абсолютный путь для данной входной строки в контексте.

Обратите внимание, что следующие оба намеренно эквивалентны. getUrl всегда будет возвращать абсолютный путь, поскольку относительный путь не требует, чтобы вы знали контекст в первую очередь.

var path = APP.getUrl("/some/path");
var path2 = APP.getUrl("some/path");
0 голосов
/ 27 сентября 2008

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

Но все может стать очень запутанным, если вы обновляете сайт, изначально созданный для работы непосредственно под корнем сайта "/" (довольно часто для простых сайтов JSP), до формальной Java EE упаковки (где корень контекста будет некоторым путем под корнем).

Это может означать много изменений кода.

Если вы хотите избежать или отложить изменения кода, но при этом обеспечить правильные ссылки на корень контекста, я протестировал методику использования фильтров сервлетов. Фильтр может быть удален в существующий проект без каких-либо изменений (за исключением web.xml), и он переназначит любые URL-ссылки в исходящем HTML на правильный путь, а также обеспечит правильную ссылку на перенаправления.

Пример сайта и используемый код доступны здесь: EnforceContextRootFilter-1.0-src.zip Примечание: действительные правила отображения реализованы в виде регулярного выражения в классе сервлетов и обеспечивают довольно общий охват - но вам может потребоваться изменить их для определенных обстоятельств.

Кстати, я ответил на несколько иной вопрос по адресу Перенос существующей базы кода из "/" в некорневой контекстный путь

0 голосов
/ 24 сентября 2008

I под no означает утверждение, что следующее является элегантной проблемой. На самом деле, оглядываясь назад, я бы не рекомендовал эту проблему, учитывая (скорее всего) снижение производительности.

JSP нашего веб-приложения были строго необработанными данными XML. Эти необработанные данные были затем отправлены в XSL (на стороне сервера), который применил правильные теги CSS и выплюнул XHTML.

У нас был один файл template.xsl, который был бы унаследован несколькими XSL-файлами, которые были у нас для разных компонентов веб-сайта. Наши пути были определены в файле XSL с именем paths.xml:

<?xml version="1.0" encoding="UTF-8"?>
<paths>
    <path name="account" parent="home">Account/</path>
    <path name="css">css/</path>
    <path name="home">servlet/</path>
    <path name="icons" parent="images">icons/</path>
    <path name="images">images/</path>
    <path name="js">js/</path>
</paths>

Внутренняя ссылка в XML будет выглядеть следующим образом:

<ilink name="link to icons" type="icons">link to icons</ilink>

Это будет обработано нашим XSL:

<xsl:template match="ilink">
    <xsl:variable name="temp">
        <xsl:value-of select="$rootpath" />
        <xsl:call-template name="paths">
            <xsl:with-param name="path-name"><xsl:value-of select="@type" /></xsl:with-param>
        </xsl:call-template>
        <xsl:value-of select="@file" />
    </xsl:variable>
        <a href="{$temp}" title="{@name}" ><xsl:value-of select="." /></a>
</xsl:template>

$rootPath был передан в каждый файл с ${applicationScope.contextPath} Идея, лежащая в основе использования XML вместо простого его кодирования в файле JSP / Java, заключалась в том, что мы не хотели перекомпилировать.

Опять же, решение не совсем хорошее ... но мы его уже использовали!

Редактировать : На самом деле сложность нашей проблемы возникла из-за того, что мы не смогли использовать JSP для всего нашего представления. Почему кто-то просто не использует ${applicationScope.contextPath} для получения пути к контексту? Тогда у нас все работало нормально.

...