HttpServletRequest zum Vervollständigen der URL

247

Ich habe ein HttpServletRequestObjekt.

Wie erhalte ich die vollständige und genaue URL, die dazu geführt hat, dass dieser Anruf bei meinem Servlet eingegangen ist?

Oder zumindest so genau wie möglich, da es vielleicht Dinge gibt, die regeneriert werden können (vielleicht die Reihenfolge der Parameter).

Flybywire
quelle
Siehe auch: stackoverflow.com/questions/4931323/…
Christophe Roussy
warum wir keine util-Funktion dafür hatten
vanduc1102

Antworten:

392

Das HttpServletRequesthat die folgenden Methoden:

  • getRequestURL() - gibt den Teil der vollständigen URL vor dem Trennzeichen für die Abfragezeichenfolge zurück ?
  • getQueryString() - Gibt den Teil der vollständigen URL nach dem Trennzeichen für die Abfragezeichenfolge zurück ?

Um die vollständige URL zu erhalten, gehen Sie einfach wie folgt vor:

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();
    }
}
Bozho
quelle
3
Sie haben die Beschreibung von getRequestURI kopiert (falsch), aber getRequestURL im Code verwendet (richtig).
Vinko Vrsalovic
21
Sie müssen bedingt prüfen, ob die Abfragezeichenfolge leer ist.
Adam Gent
8
Sie mutieren auch den StringBuffer, der die Anforderungs-URL unterstützt. Wenn die Anforderungsimplementierung keine defensive Kopie erstellt, ist dies eine sehr gute Möglichkeit, seltsames Verhalten und Fehler in andere Teile des Codes einzuführen, die dies in seiner ursprünglichen Form erwarten.
Ken Blair
5
Verwenden Sie StringBuilder anstelle von StringBuffer
Gladwin Burboz
17
@ KenBlair: Ein StringBuffer wird absichtlich zurückgegeben, damit Sie problemlos mehr Stash hinzufügen können. Da dies im Javadoc angegeben ist, wäre es für die Implementierung äußerst absurd zu erwarten, dass der zurückgegebene StringBuffer vom Aufrufer nicht geändert wird - daher ist dies cool.
Stolsvik
145

Ich benutze diese Methode:

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();
}
Mat B.
quelle
8
Dies ist eine hilfreiche Antwort für eine Kurzreferenz zu allen auf HttpServletRequest verfügbaren Informationen. Ich denke jedoch, dass Sie das Schema überprüfen möchten, um zu entscheiden, ob das Portstück zum Ergebnis hinzugefügt werden soll. "https" wäre zum Beispiel 443.
Peter Cardona
2
Eine kleine Optimierung wäre, einen StringBuilder anstelle von StringBuffer zu verwenden, nur ein Hinweis
Chris
11
Nur ein Kommentar: Die Thread-Sicherheit ist in diesem speziellen Beispiel kein Problem, da urlsie nur innerhalb der Methode deklariert, instanziiert und verwendet wird, sodass von anderen Threads als dem, auf den die Methode aufgerufen wurde, nicht zugegriffen werden kann.
Diogo Kollross
1
Wie bereits erwähnt, ist die Thread-Sicherheit hier kein Problem, da Sie StringBufferfür jeden Aufruf eine Instanz von erstellen und diese nicht für andere Threads freigeben. Dies sollte geändert werden, um a zu sein StringBuilder.
Grau
1
Gibt es einen Grund, nicht zu verwenden 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;
}
Teja Kantamneni
quelle
5
Sie ignorieren den Vorteil von StringBuffer.
BalusC
Ja. Ich akzeptiere es, aber es sind nur zwei zusätzliche Objekte, denke ich.
Teja Kantamneni
9
Es ist ein zusätzliches Objekt (ein StringBuilder) und mutiert nicht den zugrunde liegenden StringBuffer, der zurückgegeben wird. Ich würde dies der "akzeptierten" Antwort vorziehen, die JVM wird den Unterschied unabhängig davon optimieren und dies birgt nicht das Risiko, Fehler einzuführen.
Ken Blair
(request.getRequestURL (). toString () + ((request.getQueryString ()! = null)? ("?" + request.getQueryString ()): ""))
Alex
12

In einem Spring-Projekt können Sie verwenden

UriComponentsBuilder.fromHttpRequest(new ServletServerHttpRequest(request)).build().toUriString()
Peter Szanto
quelle
3
Warum nicht? new ServletServerHttpRequest(request).getURI()
Matt Sidesinger
URI ist es nicht URL
Sllouyssgort
6

Wenn HttpUtil veraltet ist, ist dies die richtige Methode

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

Kombinieren Sie die Ergebnisse von getRequestURL()und getQueryString()sollten Sie das gewünschte Ergebnis erhalten.

Michael Borgwardt
quelle
Wie gehe ich mit postbezogenen Parametern um?
Flash
2
@flash genau genommen sind POST-Parameter nicht Teil der URL, sondern der Hauptteil der Anfrage.
Geert
1

Sie können Filter verwenden.

@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);





    }

Vergessen Sie nicht, die <dispatcher>FORWARD</dispatcher>Filterzuordnung in web.xml einzufügen

Abishkar Bhattarai
quelle
für die Aufzeichnung ... test1.getRequestURI ()); es gibt /applicationName/menu/index.action (dh es enthält den führenden Schrägstrich)
Stevko
1

Verwenden Sie die folgenden Methoden für das HttpServletRequest-Objekt

java.lang.String getRequestURI () - Gibt den Teil der URL dieser Anforderung vom Protokollnamen bis zur Abfragezeichenfolge in der ersten Zeile der HTTP-Anforderung zurück.

java.lang.StringBuffer getRequestURL () - Rekonstruiert die URL, über die der Client die Anforderung gestellt hat.

java.lang.String getQueryString () - Gibt die Abfragezeichenfolge zurück, die in der Anforderungs-URL nach dem Pfad enthalten ist.

Kishor Prakash
quelle
0

Etwas spät zur Party, aber ich habe dies in meine MarkUtils- Webbibliothek in WebUtils aufgenommen - Checkstyle-genehmigt und JUnit-getestet:

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;
    }
}

Wahrscheinlich die schnellste und robusteste Antwort hier hinter Mat Baniks - aber selbst seine berücksichtigt mögliche nicht standardmäßige Portkonfigurationen mit HTTP / HTTPS nicht.

Siehe auch:

ziesemer
quelle
0

Sie können einen einfachen Einzeiler mit einem Ternär schreiben und wenn Sie das Builder-Muster des StringBuffers verwenden, aus .getRequestURL():

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

Aber das ist nur syntaktischer Zucker.

Johannes Stadler
quelle