HttpServletRequest для завершения URL

248

У меня есть HttpServletRequestобъект.

Как получить полный и точный URL-адрес, по которому этот вызов поступил на мой сервлет?

Или, по крайней мере, настолько точно, насколько это возможно, поскольку, возможно, существуют вещи, которые можно восстановить (возможно, порядок параметров).

ЭЛЕКТРОДИСТАНЦИОННАЯ СИСТЕМА УПРАВЛЕНИЯ
источник
Также смотрите: stackoverflow.com/questions/4931323/…
Кристоф Русси,
почему у нас нет функции util для этого
vanduc1102

Ответы:

393

HttpServletRequestИмеет следующие методы:

  • getRequestURL() - возвращает часть полного URL перед символом-разделителем строки запроса ?
  • getQueryString() - возвращает часть полного URL после символа разделителя строки запроса ?

Итак, чтобы получить полный URL, просто сделайте:

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
источник
3
Вы скопировали описание из getRequestURI (неправильно), но в коде использовали getRequestURL (справа).
Винко Врсалович
21
Вы должны условно проверить, является ли строка запроса пустой.
Адам Гент
8
Вы также изменяете StringBuffer, поддерживающий URL запроса. Если реализация запроса не делает защитную копию, это очень хороший способ представить странное поведение и ошибки в других частях кода, которые ожидают его в исходном виде.
Кен Блэр
5
Используйте StringBuilder вместо
StringBuffer
17
@KenBlair: StringBuffer возвращается специально, так что вы можете легко добавить больше тайника. Так как это указано в javadoc, было бы крайне абсурдно ожидать, что возвращаемый StringBuffer не будет изменен вызывающей стороной - следовательно, это круто.
stolsvik
145

Я использую этот метод:

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
Это полезный ответ для быстрой ссылки на все биты информации, доступные в HttpServletRequest. Тем не менее, я думаю, что вы захотите проверить схему, решая, добавлять ли часть порта к результату. Например, «https» будет 443.
Питер Кардона
2
небольшая оптимизация заключалась бы в использовании StringBuilder вместо StringBuffer, просто подсказка
Chris
11
Просто комментарий: безопасность потока не является проблемой в этом конкретном примере, потому что urlон объявлен, создан и используется только внутри метода, поэтому к нему нельзя получить доступ из потоков, отличных от того, который вызвал метод.
Диого Коллросс
1
Как уже упоминалось, безопасность потоков здесь не является проблемой, поскольку вы создаете свой экземпляр StringBufferдля каждого вызова и не делитесь им с другими потоками. Это должно быть изменено, чтобы быть StringBuilder.
Серый
1
Любая причина не использовать getRequestURI?
Кристоф Русси
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
Вы игнорируете преимущество StringBuffer.
BalusC
Да. Я принимаю это, но это только два дополнительных объекта, я думаю.
Теджа Кантамнени
9
Это один дополнительный объект (StringBuilder), который не изменяет базовый StringBuffer, который возвращается. Я на самом деле предпочел бы это, а не «принятый» ответ, JVM будет оптимизировать разницу вне зависимости, и это не имеет никакого риска появления ошибок.
Кен Блэр
(request.getRequestURL (). toString () + ((request.getQueryString ()! = null)? ("?" + request.getQueryString ()): ""))
Алекс
12

В проекте Spring вы можете использовать

UriComponentsBuilder.fromHttpRequest(new ServletServerHttpRequest(request)).build().toUriString()
Питер Санто
источник
3
Почему нет? new ServletServerHttpRequest(request).getURI()
Мэтт Сайдсингер
URI это не URL
Sllouyssgort
6

HttpUtil устарел, это правильный метод

StringBuffer url = req.getRequestURL();
String queryString = req.getQueryString();
if (queryString != null) {
    url.append('?');
    url.append(queryString);
}
String requestURL = url.toString();
Винко Врсалович
источник
5

Объединение результатов getRequestURL()и getQueryString()должно дать вам желаемый результат.

Майкл Боргвардт
источник
как обрабатывать сообщения, связанные с параметрами?
вспышка
2
@flash, строго говоря, POST-параметры не являются частью URL, они являются телом запроса.
Герт
1

Вы можете использовать фильтр.

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





    }

Не забудьте вставить <dispatcher>FORWARD</dispatcher>отображение фильтра в web.xml

абишкар бхаттараи
источник
для записи ... test1.getRequestURI ()); он дает /applicationName/menu/index.action (то есть содержит косую черту)
Stevko
1

Используйте следующие методы для объекта HttpServletRequest

java.lang.String getRequestURI () - возвращает часть URL-адреса этого запроса от имени протокола до строки запроса в первой строке HTTP-запроса.

java.lang.StringBuffer getRequestURL () - Восстанавливает URL, который клиент использовал для выполнения запроса.

java.lang.String getQueryString () - возвращает строку запроса, которая содержится в URL-адресе запроса после пути.

Кишор Пракаш
источник
0

Немного опоздал на вечеринку, но я включил это в свою библиотеку MarkUtils-Web в WebUtils - одобренную Checkstyle и проверенную 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;
    }
}

Возможно, самый быстрый и надежный ответ здесь за Мэттом Баником, но даже его ответ не учитывает возможные нестандартные конфигурации портов с HTTP / HTTPS.

Смотрите также:

ziesemer
источник
0

Вы можете написать простой однострочник с троичным, и если вы используете шаблон строителя StringBuffer из .getRequestURL():

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

Но это просто синтаксический сахар.

Йоханнес Штадлер
источник