HttpServletRequest para completar o URL

247

Eu tenho um HttpServletRequestobjeto

Como obtenho o URL exato e completo que fez com que essa chamada chegasse ao meu servlet?

Ou pelo menos com a maior precisão possível, pois talvez haja coisas que possam ser regeneradas (a ordem dos parâmetros, talvez).

flybywire
fonte
Veja também: stackoverflow.com/questions/4931323/…
Christophe Roussy
Por que não uma função util para ele
vanduc1102

Respostas:

392

O HttpServletRequestpossui os seguintes métodos:

  • getRequestURL() - retorna a parte do URL completo antes do caractere separador da cadeia de caracteres de consulta ?
  • getQueryString() - retorna a parte do URL completo após o caractere separador de cadeia de consulta ?

Portanto, para obter o URL completo, basta:

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
fonte
3
Você copiou a descrição de getRequestURI (incorreto), mas usa getRequestURL no código (direito).
Vinko Vrsalovic
21
Você precisa verificar condicionalmente se a string de consulta está vazia.
Adam Gent
8
Você também está modificando o StringBuffer que está apoiando o URL da solicitação. Se a implementação da solicitação não estiver fazendo uma cópia defensiva, é uma maneira muito boa de introduzir comportamentos estranhos e bugs em outras partes do código que esperam isso em sua forma original.
Ken Blair
5
Use StringBuilder em vez de StringBuffer
Gladwin Burboz
17
@KenBlair: Um StringBuffer é retornado de propósito, para que você possa adicionar facilmente mais stash. Como isso é especificado no javadoc, seria extremamente absurdo a implementação esperar que o StringBuffer retornado não fosse modificado pelo responsável pela chamada - portanto, isso é legal.
stolsvik
145

Eu 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.
fonte
8
Esta é uma resposta útil para uma referência rápida a todos os bits de informações disponíveis no HttpServletRequest. No entanto, acho que você deseja verificar o esquema para decidir se deseja adicionar a parte da porta ao resultado. "https" seria 443, por exemplo.
Peter Cardona
2
uma pequena otimização seria usar um StringBuilder em vez de StringBuffer, apenas uma sugestão
Chris
11
Apenas um comentário: a segurança do encadeamento não é um problema neste exemplo específico porque urlé declarada, instanciada e usada apenas dentro do método, portanto, não pode ser acessada por encadeamentos diferentes daquele que chamou o método.
Diogo Kollross
1
Como mencionado, a segurança do encadeamento não é um problema aqui, pois você cria uma instância StringBufferpara cada chamada e não a compartilha com outros encadeamentos. Isso deve ser alterado para ser a StringBuilder.
Grey
1
Alguma razão para não 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
fonte
5
Você está ignorando a vantagem de StringBuffer.
BalusC
Sim. Eu aceito, mas acho que são apenas dois objetos adicionais.
Teja Kantamneni
9
É um objeto adicional (um StringBuilder) e não altera o StringBuffer subjacente retornado. Na verdade, eu preferiria isso à resposta "aceita", a JVM otimizará a diferença independentemente e isso não tem nenhum risco de introdução de bugs.
Ken Blair
(.! request.getRequestURL () toString () + ((request.getQueryString () = null) (+ request.getQueryString ())? "?": ""))
Alex
12

Em um projeto Spring, você pode usar

UriComponentsBuilder.fromHttpRequest(new ServletServerHttpRequest(request)).build().toUriString()
Peter Szanto
fonte
3
Por que não? new ServletServerHttpRequest(request).getURI()
Matt Sidesinger
URI não é URL
Sllouyssgort 03/04
6

HttpUtil sendo preterido, este é o método correto

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

Combinando os resultados de getRequestURL()e getQueryString()você deve obter o resultado desejado.

Michael Borgwardt
fonte
como lidar com parâmetros relacionados a post?
flash
2
@flash estritamente falando, os parâmetros POST não fazem parte da URL, eles são o corpo da solicitação.
Geert
1

Você pode 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);





    }

Não se esqueça de colocar <dispatcher>FORWARD</dispatcher>no mapeamento de filtros no web.xml

abishkar bhattarai
fonte
para o registro ... test1.getRequestURI ()); fornece /applicationName/menu/index.action (isto é, contém a barra)
Stevko
1

Use os seguintes métodos no objeto HttpServletRequest

java.lang.String getRequestURI () -Retorna a parte da URL desta solicitação do nome do protocolo até a string de consulta na primeira linha da solicitação HTTP.

java.lang.StringBuffer getRequestURL () -Reconstrói a URL que o cliente usou para fazer a solicitação.

java.lang.String getQueryString () -Retorna a string de consulta que está contida na URL de solicitação após o caminho.

Kishor Prakash
fonte
0

Um pouco tarde para a festa, mas incluí isso na minha biblioteca MarkUtils-Web no WebUtils - aprovado pelo Checkstyle e testado pelo 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;
    }
}

Provavelmente a resposta mais rápida e robusta aqui até agora, atrás da de Mat Banik - mas mesmo a dele não responde por possíveis configurações de portas não padrão com HTTP / HTTPS.

Veja também:

ziesemer
fonte
0

É possível escrever um liner simples com um ternário e se você usar o padrão de construtor do StringBuffer em .getRequestURL():

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

Mas isso é apenas açúcar sintático.

Johannes Stadler
fonte