HttpServletRequest para completar la URL

247

Tengo un HttpServletRequestobjeto

¿Cómo obtengo la URL completa y exacta que hizo que esta llamada llegara a mi servlet?

O al menos con la mayor precisión posible, ya que tal vez hay cosas que se pueden regenerar (el orden de los parámetros, tal vez).

flybywire
fuente
Ver también: stackoverflow.com/questions/4931323/…
Christophe Roussy
¿Por qué no utilizamos una función util?
vanduc1102

Respuestas:

392

El HttpServletRequesttiene los siguientes métodos:

  • getRequestURL() - devuelve la parte de la URL completa antes del carácter separador de cadena de consulta ?
  • getQueryString() - devuelve la parte de la URL completa después del carácter separador de cadena de consulta ?

Entonces, para obtener la URL completa, solo haga:

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
fuente
3
Copiaste la descripción de getRequestURI (incorrecto) pero usas getRequestURL en el código (correcto).
Vinko Vrsalovic
21
Debe verificar condicionalmente si la cadena de consulta está vacía.
Adam Gent
8
También está mutando el StringBuffer que respalda la URL de solicitud. Si la implementación de la solicitud no está haciendo una copia defensiva, es una muy buena manera de introducir comportamientos extraños y errores en otras partes del código que lo esperan en su forma original.
Ken Blair
55
Use StringBuilder en lugar de StringBuffer
Gladwin Burboz
17
@KenBlair: se devuelve un StringBuffer a propósito, para que pueda agregar fácilmente más alijo. Dado que esto se especifica en el javadoc, sería extremadamente absurdo de la implementación esperar que el llamador no modificara el StringBuffer devuelto; por lo tanto, esto es genial.
stolsvik
145

Yo uso este método:

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.
fuente
8
Esta es una respuesta útil para una referencia rápida a todos los bits de información disponibles en HttpServletRequest. Sin embargo, creo que querría verificar el esquema al decidir si agregar la pieza de puerto al resultado. "https" sería 443, por ejemplo.
Peter Cardona
2
una pequeña optimización sería usar un StringBuilder en lugar de StringBuffer, solo una pista
Chris
11
Solo un comentario: la seguridad de subprocesos no es un problema en este ejemplo específico porque urlse declara, crea instancias y se usa solo dentro del método, por lo que no se puede acceder desde subprocesos que no sean el que llamó al método.
Diogo Kollross
1
Como se mencionó, la seguridad de subprocesos no es un problema aquí ya que está creando una instancia de su StringBufferpara cada llamada y no la comparte con ningún otro subproceso. Esto debería cambiarse para ser a StringBuilder.
Gray
1
¿Alguna razón para no usar 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
fuente
55
Estás ignorando la ventaja de StringBuffer.
BalusC
Si. Lo acepto, pero supongo que son solo dos objetos adicionales.
Teja Kantamneni
99
Es un objeto adicional (un StringBuilder) y no muta el StringBuffer subyacente que se devuelve. De hecho, preferiría esto sobre la respuesta "aceptada", la JVM optimizará la diferencia independientemente y esto no tiene el riesgo de introducir errores.
Ken Blair
(request.getRequestURL (). toString () + ((request.getQueryString ()! = null)? ("?" + request.getQueryString ()): ""))
Alex
12

En un proyecto Spring puedes usar

UriComponentsBuilder.fromHttpRequest(new ServletServerHttpRequest(request)).build().toUriString()
Peter Szanto
fuente
3
Por qué no? new ServletServerHttpRequest(request).getURI()
Matt Sidesinger
URI no es URL
Sllouyssgort
6

HttpUtil está en desuso, este es el método correcto

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

Combinando los resultados de getRequestURL()y getQueryString()debería obtener el resultado deseado.

Michael Borgwardt
fuente
¿Cómo manejar los parámetros relacionados con la publicación?
Flash
2
@flash estrictamente hablando, los parámetros POST no son parte de la URL, son el cuerpo de la solicitud.
Geert
1

Puedes usar filtro.

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





    }

no se olvide de poner <dispatcher>FORWARD</dispatcher>en el mapeo de filtro en web.xml

abishkar bhattarai
fuente
para el registro ... test1.getRequestURI ()); da /applicationName/menu/index.action (es decir, contiene la barra inclinada)
Stevko
1

Utilice los siguientes métodos en el objeto HttpServletRequest

java.lang.String getRequestURI (): devuelve la parte de la URL de esta solicitud desde el nombre del protocolo hasta la cadena de consulta en la primera línea de la solicitud HTTP.

java.lang.StringBuffer getRequestURL () -Reconstruye la URL que el cliente usó para realizar la solicitud.

java.lang.String getQueryString (): devuelve la cadena de consulta que está contenida en la URL de solicitud después de la ruta.

Kishor Prakash
fuente
0

Un poco tarde para la fiesta, pero incluí esto en mi biblioteca web MarkUtils en WebUtils : aprobado por Checkstyle y probado por 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;
    }
}

Probablemente la respuesta más rápida y robusta aquí hasta ahora detrás de la de Mat Banik, pero incluso la suya no tiene en cuenta las posibles configuraciones de puertos no estándar con HTTP / HTTPS.

Ver también:

ziesemer
fuente
0

Puede escribir un trazador de líneas simple con un ternario y si utiliza el patrón de construcción del StringBuffer desde .getRequestURL():

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

Pero eso es solo azúcar sintáctico.

Johannes Stadler
fuente