Wdrażam aplikację internetową w dwóch różnych kontenerach (Tomcat i Jetty), ale ich domyślne serwlety do obsługi treści statycznej mają inny sposób obsługi struktury adresu URL, którego chcę używać ( szczegóły ).
Dlatego chcę dołączyć mały serwlet do aplikacji internetowej, który będzie obsługiwał własną statyczną zawartość (obrazy, CSS itp.). Serwlet powinien posiadać następujące właściwości:
- Brak zależności zewnętrznych
- Prosty i niezawodny
- Obsługa
If-Modified-Since
nagłówka (tj.getLastModified
Metoda niestandardowa ) - (Opcjonalnie) obsługa kodowania gzip, etags, ...
Czy taki serwlet jest gdzieś dostępny? Najbliższy, jaki mogę znaleźć, to przykład 4-10 z książki serwletów.
Aktualizacja: struktura adresu URL, której chcę użyć - na wypadek, gdybyś się zastanawiał - to po prostu:
<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>
Dlatego wszystkie żądania powinny być przekazywane do głównego serwletu, chyba że dotyczą static
ścieżki. Problem polega na tym, że domyślny serwlet Tomcata nie bierze pod uwagę ścieżki ServletPath (więc szuka plików statycznych w folderze głównym), podczas gdy Jetty robi to (więc szuka w static
folderze).
źródło
Odpowiedzi:
Wymyśliłem nieco inne rozwiązanie. To trochę hakerskie, ale oto mapowanie:
To po prostu odwzorowuje wszystkie pliki treści według rozszerzenia na domyślny serwlet, a wszystko inne na „myAppServlet”.
Działa zarówno w Jetty, jak i Tomcat.
źródło
*.sth
. Jeśli ktoś otrzyma adres URLexample.com/index.jsp?g=.sth
, otrzyma źródło pliku jsp. Albo nie mam racji? (Jestem nowy w Java EE) Zwykle używam wzorca/css/*
W tym przypadku nie ma potrzeby całkowicie niestandardowej implementacji domyślnego serwletu, można użyć tego prostego serwletu, aby opakować żądanie w implementację kontenera:
źródło
Osiągnąłem dobre wyniki z serwletem FileServlet , ponieważ obsługuje on prawie cały protokół HTTP (etagi, fragmenty itp.).
źródło
Abstrakcyjny szablon dla statycznego serwletu zasobów
Częściowo oparty na tym blogu z 2007 roku, oto zmodernizowany i wielokrotnego użytku szablon abstrakcyjny dla serwletu, który prawidłowo radzi sobie z buforowaniem
ETag
,If-None-Match
iIf-Modified-Since
(ale bez obsługi Gzip i Range; tylko dla uproszczenia; Gzip można zrobić z filtrem lub przez konfiguracja kontenera).Używaj go razem z poniższym interfejsem reprezentującym statyczny zasób.
Wszystko, czego potrzebujesz, to po prostu rozszerzenie z podanego abstrakcyjnego serwletu i zaimplementowanie
getStaticResource()
metody zgodnie z javadoc.Konkretny przykład serwujący z systemu plików:
Oto konkretny przykład, który podaje go za pośrednictwem adresu URL, takiego jak
/files/foo.ext
z lokalnego systemu plików dysku:Konkretny przykład z bazy danych:
Oto konkretny przykład, który wyświetla go za pośrednictwem adresu URL, takiego jak
/files/foo.ext
z bazy danych, za pośrednictwem wywołania usługi EJB, które zwraca jednostkę posiadającąbyte[] content
właściwość:źródło
files/%2e%2e/mysecretfile.txt
. To żądanie produkujefiles/../mysecretfile.txt
. Przetestowałem to na Tomcat 7.0.55. Nazywają to wspinaczką katalogową: owasp.org/index.php/Path_TraversalSkończyło się na tym, że skręciłem własne
StaticServlet
. ObsługujeIf-Modified-Since
kodowanie gzip i powinien być w stanie obsługiwać również pliki statyczne z plików wojennych. Nie jest to bardzo trudny kod, ale nie jest też całkowicie trywialny.Kod jest dostępny: StaticServlet.java . Zapraszam do komentowania.
Aktualizacja: Khurram pyta o
ServletUtils
klasę, do której się odwołujeStaticServlet
. To po prostu klasa z metodami pomocniczymi, których użyłem w swoim projekcie. Jedyną potrzebną metodą jestcoalesce
(która jest identyczna z funkcją SQLCOALESCE
). To jest kod:źródło
Sądząc po przykładowych informacjach powyżej, myślę, że cały ten artykuł jest oparty na błędnym zachowaniu w Tomcat 6.0.29 i wcześniejszych. Zobacz https://issues.apache.org/bugzilla/show_bug.cgi?id=50026 . Zaktualizuj do Tomcat 6.0.30, a zachowanie między (Tomcat | Jetty) powinno się scalić.
źródło
svn diff -c1056763 http://svn.apache.org/repos/asf/tomcat/tc6.0.x/trunk/
. Nareszcie, po zaznaczeniu tego WONTFIX +3 lata temu!Spróbuj tego
Edycja: dotyczy to tylko specyfikacji serwletu 2.5 i nowszych.
źródło
Miałem ten sam problem i rozwiązałem go używając kodu „domyślnego serwletu” z bazy kodu Tomcat.
https://github.com/apache/tomcat/blob/master/java/org/apache/catalina/servlets/DefaultServlet.java
DefaultServlet jest aplet, który służy zasoby statyczne (jpg, html, css, gif itp) w Tomcat.
Ten serwlet jest bardzo wydajny i ma pewne właściwości zdefiniowane powyżej.
Myślę, że ten kod źródłowy jest dobrym sposobem na rozpoczęcie i usunięcie funkcjonalności lub zależności, których nie potrzebujesz.
źródło
org.apache.*
. Jak możesz go używać z Jetty?Znalazłem w sieci świetny samouczek na temat obejścia tego problemu. Jest prosty i wydajny, użyłem go w kilku projektach z podejściem do stylów adresów URL REST:
http://www.kuligowski.pl/java/rest-style-urls-and-url-mapping-for-static-content-apache-tomcat,5
źródło
Zrobiłem to, rozszerzając tomcat DefaultServlet ( src ) i nadpisując metodę getRelativePath ().
... A oto moje mapowania serwletów
źródło
Aby obsłużyć wszystkie żądania z aplikacji Spring, a także /favicon.ico i pliki JSP z / WEB-INF / jsp / *, których zażąda Spring's AbstractUrlBasedView, możesz po prostu przemapować serwlet jsp i domyślny serwlet:
Nie możemy polegać na wzorcu adresu URL * .jsp w standardowym mapowaniu serwletu jsp, ponieważ wzorzec ścieżki „/ *” jest dopasowywany przed sprawdzeniem mapowania rozszerzenia. Mapowanie serwletu jsp do głębszego folderu oznacza, że jest on dopasowywany jako pierwszy. Dopasowanie „/favicon.ico” ma miejsce dokładnie przed dopasowaniem wzorca ścieżki. Głębsze dopasowania ścieżek będą działać lub dokładne dopasowania, ale żadne dopasowania rozszerzeń nie mogą wyjść poza dopasowanie ścieżki „/ *”. Mapowanie „/” do domyślnego serwletu nie działa. Można by pomyśleć, że dokładne „/” pokonałoby wzorzec ścieżki „/ *” na springapp.
Powyższe rozwiązanie filtrujące nie działa w przypadku przekazanych / dołączonych żądań JSP z aplikacji. Aby to zadziałało, musiałem zastosować filtr bezpośrednio do springapp, w którym to momencie dopasowanie wzorca adresu URL było bezużyteczne, ponieważ wszystkie żądania, które trafiają do aplikacji, również trafiają do jej filtrów. Dodałem więc dopasowywanie wzorców do filtru, a potem dowiedziałem się o aplecie „jsp” i zobaczyłem, że nie usuwa on przedrostka ścieżki, tak jak robi to domyślny aplet. To rozwiązało mój problem, który nie był dokładnie taki sam, ale dość powszechny.
źródło
Zaznaczone dla Tomcat 8.x: zasoby statyczne działają poprawnie, jeśli serwlet główny jest odwzorowany na „”. W przypadku serwletu 3.x można to zrobić przez
@WebServlet("")
źródło
Użyj org.mortbay.jetty.handler.ContextHandler. Nie potrzebujesz dodatkowych komponentów, takich jak StaticServlet.
W domu na molo
$ cd konteksty
$ cp javadoc.xml static.xml
$ vi static.xml
...
Ustaw wartość contextPath z prefiksem adresu URL i ustaw wartość resourceBase jako ścieżkę do pliku zawartości statycznej.
U mnie to zadziałało.
źródło
Zobacz StaticFile w JSOS: http://www.servletsuite.com/servlets/staticfile.htm
źródło