HttpServletRequest, aby uzupełnić adres URL


247

Mam HttpServletRequestprzedmiot

Jak uzyskać pełny i dokładny adres URL, który spowodował, że wywołanie dotarło do mojego serwletu?

Lub przynajmniej tak dokładnie, jak to możliwe, ponieważ być może są rzeczy, które można zregenerować (być może kolejność parametrów).



dlaczego nie użyliśmy do tego funkcji util
vanduc1102

Odpowiedzi:


392

HttpServletRequestPosiada następujące metody:

  • getRequestURL() - zwraca część pełnego adresu URL przed znakiem separatora ciągu zapytania ?
  • getQueryString() - zwraca część pełnego adresu URL po znaku separatora ciągu zapytania ?

Aby uzyskać pełny adres URL, po prostu wykonaj:

public static String getFullURL(HttpServletRequest request) {
    StringBuilder requestURL = new StringBuilder(request.getRequestURL().toString());
    String queryString = request.getQueryString();

    if (queryString == null) {
        return requestURL.toString();
    } else {
        return requestURL.append('?').append(queryString).toString();
    }
}

3
Skopiowałeś opis z getRequestURI (źle), ale użyj getRequestURL w kodzie (po prawej).
Vinko Vrsalovic

21
Musisz warunkowo sprawdzić, czy ciąg zapytania jest pusty.
Adam Gent

8
Zmieniasz także StringBuffer, który tworzy kopię zapasową adresu URL żądania. Jeśli implementacja żądania nie tworzy kopii obronnej, jest to bardzo dobry sposób na wprowadzenie dziwnego zachowania i błędów w innych częściach kodu, które oczekują go w oryginalnej formie.
Ken Blair

5
Użyj StringBuilder zamiast StringBuffer
Gladwin Burboz

17
@KenBlair: StringBuffer jest zwracany celowo, abyś mógł łatwo dodać więcej skrytki. Ponieważ jest to określone w javadoc, byłoby absurdalne z implementacji oczekiwać, że zwrócony StringBuffer nie zostanie zmodyfikowany przez program wywołujący - dlatego jest to fajne.
stolsvik

145

Używam tej metody:

public static String getURL(HttpServletRequest req) {

    String scheme = req.getScheme();             // http
    String serverName = req.getServerName();     // hostname.com
    int serverPort = req.getServerPort();        // 80
    String contextPath = req.getContextPath();   // /mywebapp
    String servletPath = req.getServletPath();   // /servlet/MyServlet
    String pathInfo = req.getPathInfo();         // /a/b;c=123
    String queryString = req.getQueryString();          // d=789

    // Reconstruct original requesting URL
    StringBuilder url = new StringBuilder();
    url.append(scheme).append("://").append(serverName);

    if (serverPort != 80 && serverPort != 443) {
        url.append(":").append(serverPort);
    }

    url.append(contextPath).append(servletPath);

    if (pathInfo != null) {
        url.append(pathInfo);
    }
    if (queryString != null) {
        url.append("?").append(queryString);
    }
    return url.toString();
}

8
Jest to pomocna odpowiedź na szybkie odniesienie do wszystkich informacji dostępnych w HttpServletRequest. Myślę jednak, że chcesz sprawdzić schemat przy podejmowaniu decyzji, czy dodać element portu do wyniku. Na przykład „https” to 443.
Peter Cardona,

2
niewielką optymalizacją byłoby użycie StringBuilder zamiast StringBuffer, tylko podpowiedź
Chris

11
Tylko komentarz: bezpieczeństwo wątków nie jest problemem w tym konkretnym przykładzie, ponieważ urljest zadeklarowane, utworzone i utworzone tylko w metodzie, więc nie można uzyskać do niego dostępu z wątków innych niż ten, który wywołał metodę.
Diogo Kollross,

1
Jak wspomniano, bezpieczeństwo wątków nie stanowi tutaj problemu, ponieważ tworzysz wystąpienie StringBufferdla każdego połączenia i nie udostępniasz go innym wątkom. Należy to zmienić na StringBuilder.
Gray

1
Czy jest jakiś powód, aby nie używać getRequestURI?
Christophe Roussy

27
// http://hostname.com/mywebapp/servlet/MyServlet/a/b;c=123?d=789

public static String getUrl(HttpServletRequest req) {
    String reqUrl = req.getRequestURL().toString();
    String queryString = req.getQueryString();   // d=789
    if (queryString != null) {
        reqUrl += "?"+queryString;
    }
    return reqUrl;
}

5
Ignorujesz przewagę StringBuffer.
BalusC

Tak. Przyjmuję to, ale chyba tylko dwa dodatkowe obiekty.
Teja Kantamneni

9
Jest to jeden dodatkowy obiekt (StringBuilder) i nie mutuje zwracanego obiektu StringBuffer. Wolałbym to od „zaakceptowanej” odpowiedzi, JVM zoptymalizuje różnicę niezależnie od tego i nie wiąże się to z żadnym ryzykiem wprowadzenia błędów.
Ken Blair

(request.getRequestURL (). toString () + ((request.getQueryString ()! = null)? ("?" + request.getQueryString ()): ""))
Alex

12

W projekcie wiosennym możesz użyć

UriComponentsBuilder.fromHttpRequest(new ServletServerHttpRequest(request)).build().toUriString()

3
Dlaczego nie? new ServletServerHttpRequest(request).getURI()
Matt Sidesinger

URI to nie jest URL
Sllouyssgort

6

HttpUtil jest przestarzałe, jest to poprawna metoda

StringBuffer url = req.getRequestURL();
String queryString = req.getQueryString();
if (queryString != null) {
    url.append('?');
    url.append(queryString);
}
String requestURL = url.toString();


1

Możesz użyć filtra.

@Override
    public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException {
            HttpServletRequest test1=    (HttpServletRequest) arg0;

         test1.getRequestURL()); it gives  http://localhost:8081/applicationName/menu/index.action
         test1.getRequestURI()); it gives applicationName/menu/index.action
         String pathname = test1.getServletPath()); it gives //menu/index.action


        if(pathname.equals("//menu/index.action")){ 
            arg2.doFilter(arg0, arg1); // call to urs servlet or frameowrk managed controller method


            // in resposne 
           HttpServletResponse httpResp = (HttpServletResponse) arg1;
           RequestDispatcher rd = arg0.getRequestDispatcher("another.jsp");     
           rd.forward(arg0, arg1);





    }

nie zapomnij umieścić <dispatcher>FORWARD</dispatcher>mapowania filtrów w pliku web.xml


dla rekordu ... test1.getRequestURI ()); daje /applicationName/menu/index.action (tzn. zawiera wiodący ukośnik)
Stevko

1

Użyj następujących metod w obiekcie HttpServletRequest

java.lang.String getRequestURI () - Zwraca część adresu URL tego żądania od nazwy protokołu do ciągu zapytania w pierwszym wierszu żądania HTTP.

java.lang.StringBuffer getRequestURL () - Ponownie konstruuje adres URL, którego klient użył do wysłania żądania.

java.lang.String getQueryString () - Zwraca ciąg zapytania zawarty w adresie URL żądania po ścieżce.


0

Nieco późno na imprezę, ale włączyłem to do mojej biblioteki MarkUtils-Web w WebUtils - zatwierdzone przez Checkstyle i przetestowane przez JUnit:

import javax.servlet.http.HttpServletRequest;

public class GetRequestUrl{
    /**
     * <p>A faster replacement for {@link HttpServletRequest#getRequestURL()}
     *  (returns a {@link String} instead of a {@link StringBuffer} - and internally uses a {@link StringBuilder})
     *  that also includes the {@linkplain HttpServletRequest#getQueryString() query string}.</p>
     * <p><a href="https://gist.github.com/ziesemer/700376d8da8c60585438"
     *  >https://gist.github.com/ziesemer/700376d8da8c60585438</a></p>
     * @author Mark A. Ziesemer
     *  <a href="http://www.ziesemer.com.">&lt;www.ziesemer.com&gt;</a>
     */
    public String getRequestUrl(final HttpServletRequest req){
        final String scheme = req.getScheme();
        final int port = req.getServerPort();
        final StringBuilder url = new StringBuilder(256);
        url.append(scheme);
        url.append("://");
        url.append(req.getServerName());
        if(!(("http".equals(scheme) && (port == 0 || port == 80))
                || ("https".equals(scheme) && port == 443))){
            url.append(':');
            url.append(port);
        }
        url.append(req.getRequestURI());
        final String qs = req.getQueryString();
        if(qs != null){
            url.append('?');
            url.append(qs);
        }
        final String result = url.toString();
        return result;
    }
}

Prawdopodobnie najszybsza i najbardziej niezawodna odpowiedź do tej pory za Matem Banikiem - ale nawet on nie uwzględnia potencjalnych niestandardowych konfiguracji portów z HTTP / HTTPS.

Zobacz też:


0

Możesz napisać prosty liner z trójskładnikiem i jeśli użyjesz wzorca konstruktora StringBuffer z .getRequestURL():

private String getUrlWithQueryParms(final HttpServletRequest request) { 
    return request.getQueryString() == null ? request.getRequestURL().toString() :
        request.getRequestURL().append("?").append(request.getQueryString()).toString();
}

Ale to tylko cukier syntaktyczny.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.