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


248

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

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

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



почему у нас нет функции 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();
    }
}

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 ()): ""))
Алекс


6

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

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


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.

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


0

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

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.