Jak użyć filtra serwletu w Javie, aby zmienić przychodzący adres URL żądania serwletu?

186

Jak mogę użyć filtra serwletu do zmiany przychodzącego adresu URL żądania serwletu

http://nm-java.appspot.com/Check_License/Dir_My_App/Dir_ABC/My_Obj_123

do

http://nm-java.appspot.com/Check_License?Contact_Id=My_Obj_123

?


Aktualizacja : zgodnie z poniższymi krokami BalusC, wymyśliłem następujący kod:

public class UrlRewriteFilter implements Filter {

    @Override
    public void init(FilterConfig config) throws ServletException {
        //
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest request = (HttpServletRequest) req;
        String requestURI = request.getRequestURI();

        if (requestURI.startsWith("/Check_License/Dir_My_App/")) {
            String toReplace = requestURI.substring(requestURI.indexOf("/Dir_My_App"), requestURI.lastIndexOf("/") + 1);
            String newURI = requestURI.replace(toReplace, "?Contact_Id=");
            req.getRequestDispatcher(newURI).forward(req, res);
        } else {
            chain.doFilter(req, res);
        }
    }

    @Override
    public void destroy() {
        //
    }
}

Odpowiedni wpis web.xmlwygląda następująco:

<filter>
    <filter-name>urlRewriteFilter</filter-name>
    <filter-class>com.example.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>urlRewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Próbowałem przekierowania zarówno po stronie serwera, jak i klienta z oczekiwanymi wynikami. Udało się, dzięki BalusC!

Szczery
źródło
Powiązane pytanie: stackoverflow.com/questions/2723829/…
BalusC
Z jakiej wersji specyfikacji serwletu korzystasz? Sposób przekazywania żądań zmienia się w różnych wersjach.
Romain Hippeau
Zobacz ten post , ma również filtr, który robi to, co chcesz
Romain Hippeau
Pamiętaj, że jeśli twój oryginalny adres URL zawiera parametry, tj. Nm-java.appspot.com/Check_License/Dir_My_App/Dir_ABC/My_Obj_123 ? ** param1 = A i param2 = B **, wówczas parametry te zostaną również przesłane do następnego serwletu / jsp. Nie znalazłem sposobu na pozbycie się lub zastąpienie oryginalnych parametrów (tylko przy użyciu HttpServletRequestWrapper). Wszelkie pomysły? .. Aktualizacja: wydaje się, że http://ocpsoft.org/opensource/how-to-safely-add-modify-servlet-request-parameter-values/ rozwiązuje ten problem.
Lopotun
Dzięki szukałem przykładu przepisywania i szyfrowania adresów URL.
Aditya Yada,

Odpowiedzi:

281
  1. Wdrożyć javax.servlet.Filter.
  2. W doFilter()metodzie rzutuj przychodzące ServletRequestna HttpServletRequest.
  3. Użyj, HttpServletRequest#getRequestURI()aby złapać ścieżkę.
  4. Używaj prostych java.lang.Stringmetod, takich jak substring(), split(), concat()i tak dalej, aby wyodrębnić część odsetek i komponować nową ścieżkę.
  5. Użyj albo, ServletRequest#getRequestDispatcher()a następnie, RequestDispatcher#forward()aby przekazać żądanie / odpowiedź na nowy adres URL (przekierowanie po stronie serwera, nie odzwierciedlone w pasku adresu przeglądarki), lub przesłać przychodzące ServletResponsena, HttpServletResponsea następnie HttpServletResponse#sendRedirect()przekierować odpowiedź na nowy adres URL (przekierowanie po stronie klienta, odzwierciedlone w pasek adresu przeglądarki).
  6. Zarejestrować w filtr web.xmlna zasadzie url-patternz /*lub /Check_License/*, w zależności od ścieżki kontekstu, lub jeśli jesteś na Servlet 3.0 już, użyj @WebFilteradnotacji na tym, że zamiast.

Nie zapomnij dodać zaznaczenia w kodzie, jeśli adres URL wymaga zmiany, a jeśli nie , to po prostu zadzwoń FilterChain#doFilter(), inaczej zadzwoni sam w nieskończonej pętli.

Alternatywnie możesz również użyć istniejącego interfejsu API innej firmy, aby wykonać całą pracę za Ciebie, takiego jak UrlRewriteFilter Tuckeya, który można skonfigurować tak, jak w przypadku Apache mod_rewrite.

BalusC
źródło
1
Jakiś przykładowy kod doFilter (), który spełnia powyższe wymagania? Dzięki.
Frank
20
Na jakim dokładnie etapie utkniesz? Moja odpowiedź prawie pisze sam kod. Czy zauważyłeś również, że odniesienia do kodu w kolorze niebieskim są faktycznie linkami do Javadocs, które szczegółowo opisują zachowanie klasy / metody? W każdym razie możesz znaleźć tu i tutaj dobre samouczki JSP / Servlet, szczególnie ten o filtrach.
BalusC
1
Podejrzewam, że jest poprawny, ale jeśli filtr jest jednym z pierwszych w łańcuchu i RequestDispatcher#forward()jest wykonywany, reszta filtrów nie zostanie wykonana. Czy to nie będzie lepszy sposób niż robienie tego jako serwlet?
lucasvc
2
@datakey: po prostu zmień kolejność lub dodaj <dispatcher>FORWARD</dispatcher>do mapowania filtrów.
BalusC
1
@ JimJim2000: wystarczy zmienić kolejność lub dodać <dispatcher>FORWARD</dispatcher>do mapowania filtrów.
BalusC
21

Możesz użyć gotowego do użycia filtra przepisywania adresów URL z następującą regułą:

<rule>
  <from>^/Check_License/Dir_My_App/Dir_ABC/My_Obj_([0-9]+)$</from>
  <to>/Check_License?Contact_Id=My_Obj_$1</to>
</rule>

Sprawdź przykłady, aby uzyskać więcej ... przykładów.

Pascal Thivent
źródło
7

Prosty filtr JSF Url Prettyfier oparty na odpowiedziach BalusC . Filtr przekazuje wszystkie żądania zaczynające się od ścieżki / ui (zakładając, że masz tam zapisane wszystkie pliki xhtml) do tej samej ścieżki, ale dodając przyrostek xhtml.

public class UrlPrettyfierFilter implements Filter {

    private static final String JSF_VIEW_ROOT_PATH = "/ui";

    private static final String JSF_VIEW_SUFFIX = ".xhtml";

    @Override
    public void destroy() {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpServletRequest = ((HttpServletRequest) request);
        String requestURI = httpServletRequest.getRequestURI();
        //Only process the paths starting with /ui, so as other requests get unprocessed. 
        //You can register the filter itself for /ui/* only, too
        if (requestURI.startsWith(JSF_VIEW_ROOT_PATH) 
                && !requestURI.contains(JSF_VIEW_SUFFIX)) {
            request.getRequestDispatcher(requestURI.concat(JSF_VIEW_SUFFIX))
                .forward(request,response);
        } else {
            chain.doFilter(httpServletRequest, response);
        }
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {

    }

}
Xtreme Biker
źródło