Eu implanto um aplicativo da web em dois contêineres diferentes (Tomcat e Jetty), mas seus servlets padrão para veicular o conteúdo estático têm uma maneira diferente de lidar com a estrutura de URL que eu quero usar ( detalhes ).
Portanto, pretendo incluir um pequeno servlet no aplicativo da web para exibir seu próprio conteúdo estático (imagens, CSS, etc.). O servlet deve ter as seguintes propriedades:
- Sem dependências externas
- Simples e confiável
- Suporte para
If-Modified-Since
cabeçalho (isto é,getLastModified
método personalizado ) - (Opcional) suporte para codificação gzip, etags, ...
Esse servlet está disponível em algum lugar? O mais próximo que posso encontrar é o exemplo 4-10 do livro de servlets.
Atualização: A estrutura da URL que eu quero usar - caso você esteja se perguntando - é simplesmente:
<servlet-mapping>
<servlet-name>main</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/static/*</url-pattern>
</servlet-mapping>
Portanto, todas as solicitações devem ser passadas para o servlet principal, a menos que sejam para o static
caminho. O problema é que o servlet padrão do Tomcat não leva em conta o ServletPath (ele procura os arquivos estáticos na pasta principal), enquanto o Jetty o faz (o mesmo ocorre na static
pasta).
fonte
Respostas:
Eu vim com uma solução um pouco diferente. É um pouco hack-ish, mas aqui está o mapeamento:
Isso basicamente mapeia todos os arquivos de conteúdo por extensão para o servlet padrão e todo o resto para "myAppServlet".
Funciona no Jetty e no Tomcat.
fonte
*.sth
. Se alguém receber url,example.com/index.jsp?g=.sth
ele receberá a fonte do arquivo jsp. Ou eu estou errado? (Eu sou novo no Java EE) Eu costumo usar padrão de URL/css/*
e etc.Não há necessidade de implementação completamente customizada do servlet padrão. Nesse caso, você pode usar este servlet simples para agrupar a solicitação na implementação do contêiner:
fonte
Eu tive bons resultados com o FileServlet , pois ele suporta praticamente todo o HTTP (etags, chunking etc.).
fonte
Modelo abstrato para um servlet de recurso estático
Parcialmente baseado neste blog a partir de 2007, aqui está um modelo abstrato modernizado e altamente reutilizável para um servlet que corretamente lida com armazenamento em cache,
ETag
,If-None-Match
eIf-Modified-Since
(mas nenhum apoio Gzip e Gama, basta mantê-lo simples; Gzip poderia ser feito com um filtro ou via configuração de contêiner).Use-o junto com a interface abaixo que representa um recurso estático.
Tudo o que você precisa é apenas estender-se a partir do servlet abstrato fornecido e implementar o
getStaticResource()
método de acordo com o javadoc.Exemplo concreto que serve a partir do sistema de arquivos:
Aqui está um exemplo concreto que o serve por meio de uma URL, como
/files/foo.ext
no sistema de arquivos em disco local:Exemplo concreto que serve do banco de dados:
Aqui está um exemplo concreto que o serve por meio de uma URL, como
/files/foo.ext
no banco de dados, por meio de uma chamada de serviço EJB, que retorna sua entidade com umabyte[] content
propriedade:fonte
files/%2e%2e/mysecretfile.txt
. Essa solicitação produzfiles/../mysecretfile.txt
. Eu testei no Tomcat 7.0.55. Eles chamam de escalada de diretório: owasp.org/index.php/Path_TraversalAcabei rolando sozinho
StaticServlet
. SuportaIf-Modified-Since
codificação gzip e deve poder servir arquivos estáticos de arquivos war também. Não é um código muito difícil, mas também não é totalmente trivial.O código está disponível: StaticServlet.java . Sinta-se livre para comentar.
Atualização: Khurram pergunta sobre a
ServletUtils
classe em que é referenciadaStaticServlet
. É simplesmente uma classe com métodos auxiliares que eu usei para o meu projeto. O único método que você precisa écoalesce
(que é idêntico à função SQLCOALESCE
). Este é o código:fonte
A julgar pelas informações de exemplo acima, acho que este artigo inteiro se baseia em um comportamento com erros no Tomcat 6.0.29 e versões anteriores. Consulte https://issues.apache.org/bugzilla/show_bug.cgi?id=50026 . Atualize para o Tomcat 6.0.30 e o comportamento entre (Tomcat | Jetty) deve ser mesclado.
fonte
svn diff -c1056763 http://svn.apache.org/repos/asf/tomcat/tc6.0.x/trunk/
. Finalmente, depois de marcar este WONTFIX + 3 anos atrás!tente isso
Editar: Isso é válido apenas para as especificações do servlet 2.5 e posterior.
fonte
Eu tive o mesmo problema e o resolvi usando o código do 'servlet padrão' da base de código do Tomcat.
https://github.com/apache/tomcat/blob/master/java/org/apache/catalina/servlets/DefaultServlet.java
O DefaultServlet é o servlet que serve os recursos estáticos (jpg, html, css, gif etc.) no Tomcat.
Este servlet é muito eficiente e possui algumas das propriedades definidas acima.
Eu acho que esse código fonte é uma boa maneira de iniciar e remover as funcionalidades ou impedimentos que você não precisa.
fonte
org.apache.*
. Como você pode usá-lo com o Jetty?Encontrei um ótimo tutorial na web sobre algumas soluções alternativas. É simples e eficiente, usei-o em vários projetos com estilos de URLs REST:
http://www.kuligowski.pl/java/rest-style-urls-and-url-mapping-for-static-content-apache-tomcat,5
fonte
Eu fiz isso estendendo o tomcat DefaultServlet ( src ) e substituindo o método getRelativePath ().
... E aqui estão meus mapeamentos de servlet
fonte
Para atender a todas as solicitações de um aplicativo Spring, bem como /favicon.ico e os arquivos JSP de / WEB-INF / jsp / * que o AbstractUrlBasedView do Spring solicitará, basta remapear o servlet jsp e o servlet padrão:
Não podemos confiar no padrão de URL * .jsp no mapeamento padrão para o servlet jsp porque o padrão de caminho '/ *' é correspondido antes de qualquer mapeamento de extensão ser verificado. Mapear o servlet jsp para uma pasta mais profunda significa que ele corresponde primeiro. A correspondência '/favicon.ico' acontece exatamente antes da correspondência do padrão de caminho. As correspondências mais profundas do caminho funcionarão ou correspondências exatas, mas nenhuma correspondência de extensão poderá ultrapassar a correspondência do caminho '/ *'. Mapear '/' para o servlet padrão não parece funcionar. Você pensaria que o '/' exato venceria o padrão de caminho '/ *' no springapp.
A solução de filtro acima não funciona para solicitações JSP encaminhadas / incluídas do aplicativo. Para fazê-lo funcionar, tive que aplicar o filtro diretamente ao springapp, momento em que a correspondência de padrões de URL era inútil, pois todas as solicitações que vão para o aplicativo também vão para seus filtros. Então, adicionei a correspondência de padrões ao filtro e aprendi sobre o servlet 'jsp' e vi que ele não remove o prefixo do caminho, como o servlet padrão. Isso resolveu meu problema, que não era exatamente o mesmo, mas era bastante comum.
fonte
Verificado para o Tomcat 8.x: os recursos estáticos funcionam bem se o servlet raiz mapear para "". Para o servlet 3.x, isso pode ser feito por
@WebServlet("")
fonte
Use org.mortbay.jetty.handler.ContextHandler. Você não precisa de componentes adicionais como StaticServlet.
Na casa do cais,
contextos $ cd
$ cp javadoc.xml static.xml
$ vi static.xml
...
Defina o valor de contextPath com seu prefixo de URL e defina o valor de resourceBase como o caminho do arquivo do conteúdo estático.
Funcionou para mim.
fonte
Consulte StaticFile no JSOS: http://www.servletsuite.com/servlets/staticfile.htm
fonte