Pergunta

Em Java, os aplicativos web são empacotados em guerras. Por padrão, muitos recipientes de servlet usará o nome de guerra, como o nome do contexto para a aplicação.

Assim myapp.war é distribuído para http://example.com/myapp .

O problema é que o webapp considera sua "raiz" para ser, assim, "root", ou simplesmente "/", enquanto HTML consideraria a raiz do seu aplicativo para ser "/ myapp".

O Servlet API e JSP têm instalações para ajudar a gerenciar isso. Por exemplo, se, em um servlet, você faz: response.sendRedirect ( "/ mypage.jsp"), o recipiente irá anteceder o contexto e criar o url: http://example.com/myapp/mypage.jsp ".

No entanto, você não pode fazer isso com, digamos, a tag IMG em HTML. Se você fizer você provavelmente irá obter um 404, porque o que você realmente queria era "/myapp/myimage.gif".

Muitos quadros têm tags JSP que são sensível ao contexto, bem como, e há diferentes maneiras de fazer URLs corretas dentro de JSP (none particularmente elegantemente).

É um problema nitty para codificadores para saltar em um fora de quando usar um "App Relativa" url, vs um URL absoluto.

Finalmente, há a questão do código Javascript que as necessidades para criar URLs na mosca, e URLs embutidas dentro CSS (para imagens de fundo e similares).

Estou curioso o que os outros técnicas usam para mitigar e solucionar esse problema. Muitos código simplesmente punt e difícil, tanto para raiz do servidor ou para qualquer contexto acontecer de estar usando. Eu já sei a resposta, isso não é o que estou procurando.

O que você faz?

Foi útil?

Solução

Você pode usar JSTL para a criação de URLs.

Por exemplo, <c:url value="/images/header.jpg" /> prefixará a raiz de contexto.

Com CSS, isso geralmente não é um problema para mim.

Eu tenho uma estrutura de raiz web como esta:

/ css
/ imagens

No arquivo CSS, então você só precisa usar URLs relativos (../images/header.jpg) e não precisa estar ciente da raiz de contexto.

Quanto JavaScript, o que funciona para mim é incluindo alguns comum JavaScript no cabeçalho da página como esta:

<script type="text/javascript">
var CONTEXT_ROOT = '<%= request.getContextPath() %>';
</script>

Em seguida, você pode usar a raiz de contexto em todos os seus scripts (ou, você pode definir uma função para caminhos de construção - pode ser um pouco mais flexível).

Obviamente, isso tudo depende de suas utilizando JSPs e JSTL, mas eu uso JSF com Facelets e as técnicas envolvidas são semelhantes -. A única diferença real é obter a raiz de contexto de uma maneira diferente

Outras dicas

Para páginas HTML, eu apenas definir a tag <base> HTML. Cada link relativo (ou seja, não começando com o esquema ou /) irá tornar-se em relação a ele. Não há nenhuma maneira limpa para agarrá-lo imediatamente por HttpServletRequest, por isso precisamos pouca ajuda de JSTL aqui.

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<c:set var="req" value="${pageContext.request}" />
<c:set var="url">${req.requestURL}</c:set>
<c:set var="uri">${req.requestURI}</c:set>

<!DOCTYPE html>
<html lang="en">
  <head>
    <base href="${fn:substring(url, 0, fn:length(url) - fn:length(uri))}${req.contextPath}/" />
    <link rel="stylesheet" href="css/default.css">
    <script src="js/default.js"></script>
  </head>
  <body>
    <img src="img/logo.png" />
    <a href="other.jsp">link</a>
  </body>
</html>

Este, por sua vez no entanto uma ressalva: âncoras (do URL #identifier) se tornarão em relação ao caminho de base também. Se você tiver qualquer um deles, você gostaria de fazê-lo em relação ao URL pedido (URI) em vez. Assim, a mudança como

<a href="#identifier">jump</a>

para

<a href="${uri}#identifier">jump</a>

Em JS, você pode simplesmente acessar o elemento <base> do DOM sempre que você gostaria de converter um URL relativo a um URL absoluto.

var base = document.getElementsByTagName("base")[0].href;

Ou se você fizer jQuery

var base = $("base").attr("href");

Em CSS, os URLs de imagem são relativos ao URL do próprio estilo. Assim, basta soltar as imagens em alguma pasta em relação ao próprio estilo. Por exemplo.

/css/style.css
/css/images/foo.png

e referência-los da seguinte forma

background-image: url('images/foo.png');

Se você um pouco como deixar cair as imagens em alguma pasta no mesmo nível que CSS pasta

/css/style.css
/images/foo.png

Em seguida, use ../ para ir ao pai comum pasta

background-image: url('../images/foo.png');

Veja também:

Eu concordo com tardate . Eu paguei a minha atenção em filtros e também ter encontrado a solução em face do projeto UrlRewriteFilter . A configuração simples, como segue abaixo:

<rule>
    <from>^.+/resources/(.*)$</from>
    <to>/resources/$1</to>
</rule>

ajuda a encaminhar todas as solicitações para * path / recursos para / recursos Pass (incluindo contexto prefixo do caminho). Então, eu posso simplesmente colocar todas as minhas images e CSS arquivos sob recursos pasta e continuar a usar URLs relativos em meus estilos de imagens de fundo e outros casos.

O Servlet API e JSP têm instalações para ajudar a gerenciar isso. Para exemplo, se, em um servlet, você faz: response.sendRedirect ( "mypage.jsp /"), o recipiente vai preceder o contexto e criar o url: http://example.com/myapp/mypage.jsp ".

Ah, talvez, talvez não - isso depende do seu recipiente e a especificação servlet!

A partir Servlet 2.3: Novas funcionalidades exposta :

E, finalmente, após um longo debate pela um grupo de peritos, servlet API 2,3 esclareceu uma vez por todas exatamente o que acontece em um res.sendRedirect ( "/ index.html") chamada para um servlet em execução dentro de um contexto não-raiz. A questão é que Servlet API 2.2 requer uma incompleta path como "index.html" para ser traduzido pelo recipiente servlet em um caminho completo, mas não diz como caminhos de contexto são tratadas. Se o servlet fazer a chamada está em um contexto no caminho "/ contextPath" deve o redirecionamento URI traduzir em relação à raiz contentor ( http: // server: port / index.html ) ou o raiz de contexto ( http: // server: port / contextPath / index.html )? Para o máximo de portabilidade, é imperativo para definir o comportamento; após um longo debate, os especialistas escolheu para traduzir em relação ao raiz recipiente. Para aqueles que querem contexto relativo, você pode preceder o saída do getContextPath () para o seu URI.

Então, não, com 2,3 seus caminhos são não traduzido automaticamente para incluir o caminho do contexto.

eu usei classes de Assistente para gerar img etiquetas etc. Esta classe auxiliar cuida de prefixo caminhos com contextPath do aplicativo. (Isso funciona, mas eu realmente não gosto dele. Se alguém tem quaisquer alternativas melhores, informe.)

Para caminhos em arquivos CSS etc. Eu uso um script de construção Ant que usa um site.production.css para Site.css no ambiente de produção e site.development.css em encironment desenvolvimento.

Como alternativa às vezes eu uso um script Ant que substitui @token @ fichas com dados apropriados para diferentes environents. Neste caso @ contextPath @ símbolo seria substituído com o caminho do contexto correto.

Uma opção é usar a estrutura "flat" aplicação e relativos URLs sempre que possível.

Por "flat" Quero dizer que não há subdiretórios sob sua raiz do aplicativo, talvez apenas alguns diretórios para conteúdo estático como "imagens /". Toda a sua JSP de, URLs de ação, servlets ir diretamente sob a raiz.

Esta não resolver completamente o seu problema, mas simplifica muito.

Vilmantas disse a palavra certa aqui:. URLs relativos

Tudo que você precisa fazer em sua IMG é usar

<img src="myimage.gif"/>

em vez de

<img src="/myimage.gif"/>

e vai ser em relação ao contexto do aplicativo (como o navegador é interpretar a URL para ir para)

Com exceção de casos especiais, eu recomendo contra o uso de URLs absolutos desta forma. Sempre. URLs absolutos são bons para quando outro webapp está apontando para algo em seu webapp. Internamente - quando um recurso é apontando para um segundo recurso no mesmo contexto -. O recurso deve saber onde ele vive, por isso deve ser capaz de expressar um caminho relativo para o segundo recurso

É claro que você vai escrever componentes modulares, que não sabem o recurso que está incluí-los. Por exemplo:

/myapp/user/email.jsp:
Email: <a href="../sendmail.jsp">${user.email}</a>

/myapp/browse/profile.jsp:
<jsp:include page="../user/email.jsp" />

/myapp/home.jsp:
<jsp:include page="../user/email.jsp" />

Então, como é email.jsp sabe o caminho relativo do sendmail.jsp? Claramente o link vai quebrar em qualquer /myapp/browse/profile.jsp ou ele vai quebrar em /myapp/home.jsp. A resposta é, manter todos os seus URLs no mesmo espaço filepath plana. Ou seja, cada URL não deve ter barras após /myapp/.

Isso é muito fácil de realizar, desde que você tem algum tipo de mapeamento entre URLs e os arquivos reais que geram o conteúdo. (Por exemplo, na Primavera, utilize DispatcherServlet para mapear URLs para arquivos JSP ou a vista.)

Há casos especiais. por exemplo. se você estiver escrevendo um aplicativo do lado do navegador em Javascript, então fica mais difícil manter um espaço filepath plana. Nesse caso, ou em outros casos especiais, ou apenas se você tem uma preferência pessoal, não é realmente um grande negócio para uso <%= request.getContextPath() %> para criar um caminho absoluto.

Você pode usar request.getContextPath () para construir URLs absolutos que não são codificados para um contexto específico. Como uma resposta mais cedo indicado, para JavaScript que você acabou de definir uma variável no topo de sua JSP (ou de preferência em um modelo) e prefixo que conforme o contexto.

Isso não funciona para substituição de imagem CSS menos que você queira gerar dinamicamente um arquivo CSS, que pode causar outros problemas. Mas desde que você sabe onde seu arquivo CSS é em relação a suas imagens, você pode sair com URLs relativos.

Por alguma razão, eu tive problemas com IE lidar com URLs relativos e tive que cair para trás a usar expressões com uma variável conjunto JavaScript para o contexto. Eu só dividir minhas substituições imagem IE fora em seu próprio arquivo e usado macros IE para puxar os corretos. Não foi um grande negócio, porque eu já tive que fazer isso para lidar com PNGs transparentes de qualquer maneira. Não é bonito, mas funciona.

Eu usei a maioria destas técnicas (salvar a arquitetura XSLT).

Eu acho que o ponto crucial (e consenso) do problema é ter um site com potencialmente vários diretórios.

Se a sua profundidade diretório (por falta de um termo melhor) é constante, então você pode contar com URLs relativos em coisas como CSS.

Mind, o layout não tem que ser completamente plano, apenas consistente.

Por exemplo, nós fizemos hierarquias como / css, / js, / comum, / admin, / usuário. Colocando páginas e recursos apropriados nos diretórios apropriados. Ter uma estrutura como esta funciona muito bem com autenticação baseada Container.

Eu também mapeou CSS * e * .js para o servlet JSP, e fez-lhes dinâmica para que eu possa construí-los em tempo real.

Eu só estava esperando que houvesse alguma coisa que eu possa ter perdido.

I não meios afirmam que o seguinte é uma questão elegante. Na verdade, em retrospectiva, eu não recomendo este problema dada a (mais provável) queda de desempenho.

JSPs do nosso aplicativo web eram estritamente XML de dados brutos. Estes dados brutos foi então enviada para um XSL (server-side), que aplicou as tags CSS certas, e cuspir o XHTML.

Nós tivemos um único template.xsl que seriam herdadas pelos múltiplos arquivos XSL que tivemos para diferentes componentes do site. Nossos caminhos foram todos definidos em um arquivo XSL chamado 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>

Uma ligação interna seria no XML da seguinte forma:

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

Isto são processadas pelo nosso 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 foi passada para cada arquivo com ${applicationScope.contextPath} A idéia por trás de nós usando XML em vez de apenas difícil de codificação-lo em um arquivo JSP / Java foi que não quer ter que recompilar.

Mais uma vez, a solução não é boa em tudo ... mas nós usá-lo uma vez!

Editar : Na verdade, a complexidade em nossa edição surgiu porque não fomos capazes de usar JSPs para toda a nossa vista. Por que não seria alguém apenas usar ${applicationScope.contextPath} para recuperar o caminho do contexto? Funcionou muito bem para nós, então.

Ao criar um site a partir do zero, lado I com @Will -. Apontar para uma estrutura de URL consistente e previsível de modo que você pode ficar com referências relativas

Mas as coisas podem ficar muito confuso se você estiver atualizando um site que foi originalmente construído para trabalhar diretamente sob a raiz do site "/" (comum bonita para sites simples JSP) ao formal Java EE embalagem (onde raiz de contexto será algum caminho sob a raiz).

Isso pode significar um monte de mudanças de código.

Se você quer evitar ou adiar as alterações de código, mas ainda garantir referenciação contexto de raiz correta, uma técnica que eu testei é usar filtros de servlet. O filtro pode ser descartado em um proejct existente sem mudar nada (exceto web.xml), e vai remapear quaisquer referências de URL do HTML de saída para o caminho correto, e também garantir redirecionamentos estão correctamente referenciado.

Um exemplo de site e de código utilizável disponível aqui: EnforceContextRootFilter-1.0-src.zip NB: as regras de mapeamento reais são implementados como regex na classe servlet e fornecer um pega-tudo muito geral - mas você pode precisar modificar para circunstâncias particulares.

btw, eu bifurcada uma pergunta ligeiramente diferente para o endereço migrar base de código existente de "/" para um contexto de caminho não raiz

I tendem a escrever uma propriedade como parte do meu núcleo biblioteca JavaScript dentro do meu. Eu não acho que ele é perfeito, mas eu acho que é o melhor que já conseguiu alcançar.

Primeiro, eu tenho um módulo que faz parte do meu núcleo aplicativo que está sempre disponível

(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 || {});

Eu, então, usar o Apache telhas com um cabeçalho comum que sempre contém o seguinte:

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

Agora que eu inicializado contexto posso usar getUrl(path) de qualquer lugar (js ou dentro de jsp / html) que irá retornar um caminho absoluto para a string de entrada dada dentro do contexto.

Observe que o seguinte são ambos equivalente intencionalmente. getUrl sempre retornará um caminho absoluto como um caminho relativo não precisa de você conhecer o contexto em primeiro lugar.

var path = APP.getUrl("/some/path");
var path2 = APP.getUrl("some/path");

Aqui é a melhor maneira: filtro de redirecionamento contexto Filtro deve ser aplicado no ponto de extensão pré-jogo e, assim, usar anotação @PreMatching.

Filtros implementar essa interface deve ser anotado com @Provider a ser descoberto pelos JAX-RS tempo de execução. Container casos pedido de filtro também pode ser descoberto e ligadas dinamicamente a determinados métodos de recursos.

explicado com código de exemplo:

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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top