HttpServletRequest pour compléter l'URL

247

J'ai un HttpServletRequestobjet.

Comment puis-je obtenir l'URL complète et exacte à l'origine de cet appel sur ma servlet?

Ou au moins aussi précisément que possible, car il y a peut-être des choses qui peuvent être régénérées (l'ordre des paramètres, peut-être).

fil volant
la source
Voir aussi: stackoverflow.com/questions/4931323/…
Christophe Roussy
pourquoi nous n'avons pas utilisé de fonction util pour cela
vanduc1102

Réponses:

392

A HttpServletRequestles méthodes suivantes:

  • getRequestURL() - renvoie la partie de l'URL complète avant le caractère séparateur de chaîne de requête ?
  • getQueryString() - renvoie la partie de l'URL complète après le caractère séparateur de chaîne de requête ?

Donc, pour obtenir l'URL complète, faites simplement:

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
la source
3
Vous avez copié la description de getRequestURI (incorrect) mais utilisez getRequestURL dans le code (à droite).
Vinko Vrsalovic
21
Vous devez vérifier conditionnellement si la chaîne de requête est vide.
Adam Gent du
8
Vous mutez également le StringBuffer soutenant l'URL de demande. Si l'implémentation de la demande ne fait pas de copie défensive, c'est un très bon moyen d'introduire un comportement étrange et des bogues dans d'autres parties du code qui l'attendent sous sa forme originale.
Ken Blair
5
Utilisez StringBuilder au lieu de StringBuffer
Gladwin Burboz
17
@KenBlair: Un StringBuffer est retourné exprès, de sorte que vous pouvez facilement ajouter plus de cachette. Comme cela est spécifié sur le javadoc, il serait extrêmement absurde de l'implémentation de s'attendre à ce que le StringBuffer retourné ne soit pas modifié par l'appelant - par conséquent, c'est cool.
stolsvik
145

J'utilise cette méthode:

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.
la source
8
Ceci est une réponse utile pour une référence rapide à tous les bits d'informations disponibles sur HttpServletRequest. Cependant, je pense que vous voudriez vérifier le schéma pour décider d'ajouter ou non la pièce de port au résultat. "https" serait par exemple 443.
Peter Cardona
2
une petite optimisation serait d'utiliser un StringBuilder au lieu de StringBuffer, juste un indice
Chris
11
Juste un commentaire: la sécurité des threads n'est pas un problème dans cet exemple spécifique car elle urlest déclarée, instanciée et utilisée uniquement à l'intérieur de la méthode, donc elle n'est pas accessible à partir de threads autres que celui qui a appelé la méthode.
Diogo Kollross
1
Comme mentionné, la sécurité des threads n'est pas un problème ici car vous créez une instance de votre StringBufferpour chaque appel et ne la partagez pas avec d'autres threads. Cela devrait être changé pour être un StringBuilder.
Gray
1
Une raison de ne pas l'utiliser 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
la source
5
Vous ignorez l'avantage de StringBuffer.
BalusC
Oui. Je l'accepte, mais ce ne sont que deux objets supplémentaires, je suppose.
Teja Kantamneni
9
C'est un objet supplémentaire (un StringBuilder) et ne mute pas le StringBuffer sous-jacent qui est retourné. Je préférerais en fait cela à la réponse "acceptée", la JVM optimisera la différence indépendamment et cela n'a aucun risque d'introduire des bogues.
Ken Blair
(request.getRequestURL (). toString () + ((request.getQueryString ()! = null)? ("?" + request.getQueryString ()): ""))
Alex
12

Dans un projet Spring, vous pouvez utiliser

UriComponentsBuilder.fromHttpRequest(new ServletServerHttpRequest(request)).build().toUriString()
Peter Szanto
la source
3
Pourquoi pas? new ServletServerHttpRequest(request).getURI()
Matt Sidesinger
URI ce n'est pas une URL
Sllouyssgort
6

HttpUtil étant obsolète, c'est la bonne méthode

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

La combinaison des résultats getRequestURL()et getQueryString()devrait vous obtenir le résultat souhaité.

Michael Borgwardt
la source
comment gérer les paramètres liés aux messages?
flash
2
@flash à proprement parler, les paramètres POST ne font pas partie de l'URL, ils sont le corps de la requête.
Geert
1

Vous pouvez utiliser un filtre.

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





    }

n'oubliez pas de mettre le <dispatcher>FORWARD</dispatcher>mappage de filtre dans web.xml

abishkar bhattarai
la source
pour l'enregistrement ... test1.getRequestURI ()); il donne /applicationName/menu/index.action (c'est-à-dire qu'il contient la barre oblique principale)
Stevko
1

Utilisez les méthodes suivantes sur l'objet HttpServletRequest

java.lang.String getRequestURI () -Retourne la partie de l'URL de cette demande du nom du protocole jusqu'à la chaîne de requête dans la première ligne de la demande HTTP.

java.lang.StringBuffer getRequestURL () -Reconstruit l'URL utilisée par le client pour effectuer la demande.

java.lang.String getQueryString () -Retourne la chaîne de requête contenue dans l'URL de demande après le chemin.

Kishor Prakash
la source
0

Un peu tard pour la fête, mais je l'ai inclus dans ma bibliothèque MarkUtils-Web dans WebUtils - approuvé par Checkstyle et testé par 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;
    }
}

Probablement la réponse la plus rapide et la plus robuste jusqu'ici derrière Mat Banik - mais même la sienne ne tient pas compte des configurations de port non standard potentielles avec HTTP / HTTPS.

Voir également:

ziesemer
la source
0

Vous pouvez écrire un simple liner avec un ternaire et si vous utilisez le modèle de générateur du StringBuffer à partir de .getRequestURL():

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

Mais ce n'est que du sucre syntaxique.

Johannes Stadler
la source