Standardowe Servlet API nie obsługuje tej funkcji. Możesz też użyć filtru przepisywania URL do tego jak jeden Tuckey za (co jest znacznie podobny Apache HTTPD użytkownika mod_rewrite
), lub dodać czek w doFilter()
sposobie słuchania filtrować /*
.
String path = ((HttpServletRequest) request).getRequestURI();
if (path.startsWith("/specialpath/")) {
chain.doFilter(request, response);
} else {
}
W razie potrzeby możesz określić ścieżki, które mają być zignorowane, jako element init-param
filtru, aby web.xml
mimo wszystko można było nim sterować . Możesz go pobrać w filtrze w następujący sposób:
private String pathToBeIgnored;
public void init(FilterConfig config) {
pathToBeIgnored = config.getInitParameter("pathToBeIgnored");
}
Jeśli filtr jest częścią interfejsu API innej firmy i dlatego nie możesz go zmodyfikować, zmapuj go na bardziej szczegółowe url-pattern
, np. /otherfilterpath/*
I utwórz nowy filtr, w /*
którym przekierowuje do ścieżki pasującej do filtra strony trzeciej.
String path = ((HttpServletRequest) request).getRequestURI();
if (path.startsWith("/specialpath/")) {
chain.doFilter(request, response);
} else {
request.getRequestDispatcher("/otherfilterpath" + path).forward(request, response);
}
Aby uniknąć tego, że ten filtr będzie wywoływał siebie w nieskończonej pętli, musisz pozwolić mu tylko nasłuchiwać (wysyłać) REQUEST
i włączać FORWARD
tylko filtr strony trzeciej .
Zobacz też:
Zastosowałem podejście opisane przez Erica Daugherty'ego : stworzyłem specjalny serwlet, który zawsze odpowiada kodem 403 i stawiam jego mapowanie przed ogólnym.
Fragment mapowania:
<servlet> <servlet-name>generalServlet</servlet-name> <servlet-class>project.servlet.GeneralServlet</servlet-class> </servlet> <servlet> <servlet-name>specialServlet</servlet-name> <servlet-class>project.servlet.SpecialServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>specialServlet</servlet-name> <url-pattern>/resources/restricted/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>generalServlet</servlet-name> <url-pattern>/resources/*</url-pattern> </servlet-mapping>
I klasa serwletów:
public class SpecialServlet extends HttpServlet { public SpecialServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.sendError(HttpServletResponse.SC_FORBIDDEN); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.sendError(HttpServletResponse.SC_FORBIDDEN); } }
źródło
To podejście działa, gdy chcesz zapobiec określonemu filtrowi i wszystkim kolejnym. Powinien dobrze działać, jeśli np. chcesz udostępniać część treści jako statyczne zasoby w swoim kontenerze serwletów, zamiast pozwalać logice aplikacji (przez filtr taki jak GuiceFilter):
Zamapuj folder ze statycznymi plikami zasobów na domyślny serwlet. Utwórz filtr serwletów i umieść go przed GuiceFilter w swoim web.xml. W utworzonym filtrze możesz oddzielić przekazywanie niektórych żądań do GuiceFilter, a innych bezpośrednio do dyspozytora. Oto przykład ...
web.xml
<servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/static/*</url-pattern> </servlet-mapping> <filter> <filter-name>StaticResourceFilter</filter-name> <filter-class>com.project.filter.StaticResourceFilter</filter-class> </filter> <filter-mapping> <filter-name>StaticResourceFilter</filter-name> <url-pattern>/static/*</url-pattern> </filter-mapping> <filter> <filter-name>guiceFilter</filter-name> <filter-class>com.google.inject.servlet.GuiceFilter</filter-class> </filter> <filter-mapping> <filter-name>guiceFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
StaticResourceFilter.class
public class StaticResourceFilter implements Filter { private final static Logger LOGGER = LoggerFactory.getLogger(StaticResourceFilter.class); private static final String RESOURCE_PATH = "/static/"; @Override public void init(final FilterConfig filterConfig) throws ServletException { LOGGER.info("StaticResourceFilter initialized"); } @Override public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException { String path = ((HttpServletRequest) request).getServletPath(); if (path.toLowerCase().startsWith(RESOURCE_PATH)) { request.getRequestDispatcher(path).forward(request, response); } else { chain.doFilter(request, response); } } @Override public void destroy() { LOGGER.info("StaticResourceFilter destroyed"); } }
Niestety, jeśli chcesz po prostu pominąć jeden krok w łańcuchu filtrów, zachowując następujące po nim, to nie zadziała.
źródło
.getRequestURI()
zakończy się niepowodzeniem (najprawdopodobniej powodując błąd 404), ponieważ zostanie.getRequestDispatcher
rozwiązany względem ścieżki kontekstu . Jeśli twoja ścieżka kontekstu to/a
, to w twoim przykładzie identyfikator URI żądania będzie taki/a/static
, a użyciegetRequestDispatcher("/a/static")
spowoduje/a/a/static
zamiast tego rozwiązanie . Poprawka: użyj.getServletPath()
zamiast.getRequestURI()
. Prześlę zmianę, aby to naprawić, ale chciałem tylko zostawić komentarz Do Twojej wiadomościMyślę, że nie możesz, jedyną inną alternatywą konfiguracji jest wyliczenie ścieżek, które chcesz filtrować, więc zamiast tego
/*
możesz dodać kilka dla/this/*
i/that/*
itp., Ale to nie doprowadzi do wystarczającego rozwiązania, gdy masz dużo tych ścieżek.To, co możesz zrobić, to dodać parametr do filtru, dostarczając wyrażenie (takie jak wyrażenie regularne), które jest używane do pomijania funkcji filtru dla dopasowanych ścieżek. Kontener serwletów nadal będzie wywoływał filtr dla tych adresów URL, ale będziesz mieć lepszą kontrolę nad konfiguracją.
Edytować
Teraz, gdy wspomniałeś, że nie masz kontroli nad filtrem, możesz albo dziedziczyć z tego filtru wywołujące
super
metody w jego metodach, z wyjątkiem sytuacji, gdy istnieje ścieżka adresu URL, który chcesz pominąć, i postępować zgodnie z łańcuchem filtrów, takim jak proponowany @BalusC, lub zbudować filtr, który tworzy instancję filtru i delegatów w tych samych okolicznościach. W obu przypadkach parametry filtru obejmowałyby zarówno dodawany parametr wyrażenia, jak i filtr, z którego dziedziczono lub do którego delegowano.Zaletą tworzenia filtru delegującego (opakowania) jest to, że można dodać klasę filtru opakowanego filtru jako parametr i użyć go ponownie w innych sytuacjach, takich jak ta.
źródło
Musiałem też filtrować na podstawie wzorca adresu URL (/ {nazwa usługi} / api / stats /) w kodzie java.
if (path.startsWith("/{servicename}/api/statistics/")) { validatingAuthToken(((HttpServletRequest) request).getHeader("auth_token")); filterChain.doFilter(request, response); }
Ale to dziwne, że serwlet nie obsługuje wzorca adresu URL innego niż (/ *). Powinien to być bardzo częsty przypadek dla API serwletów!
źródło
Napotkałem ten sam problem, ale poniżej znajduje się odpowiedź.
web.xml
<!-- set this param value for the filter--> <init-param> <param-name>freePages</param-name> <param-value> MainFrame.jsp; </param-value> </init-param>
filter.java
strFreePages = config.getInitParameter("freePages"); //get the exclue pattern from config file isFreePage(strRequestPage) //decide the exclude path
w ten sposób nie musisz nękać konkretnej klasy Filter.
źródło
Jeśli z jakiegoś powodu nie możesz zmienić oryginalnego mapowania filtru („/ *” w moim przypadku) i wysyłasz do niezmiennego filtra innej firmy, przydatne mogą być następujące elementy:
Następujące prace w Weblogic 12.1.3:
źródło
Byłem w stanie poradzić sobie z tym wiosną 2 w następujący sposób
private boolean isInPath(ServletRequest request) { String PATH_TO_VALIDATE = "/path/"; String path = ((HttpServletRequest) request).getRequestURI(); return path != null && path.toLowerCase().contains(PATH_TO_VALIDATE); }
źródło