HttpServletRequest完成URL

fly*_*ire 230 java servlets http

我有一个HttpServletRequest对象.

如何获得导致此调用的完整且准确的URL到达我的servlet?

或者至少尽可能准确,因为可能存在可以重新生成的东西(可能是参数的顺序).

Boz*_*zho 360

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 您需要有条件地检查查询字符串是否为空. (21认同)
  • @KenBlair:有意返回一个StringBuffer,以便您可以轻松添加更多存储.由于这是在javadoc上指定的,因此期望返回的StringBuffer不会被调用者修改将是非常荒谬的 - 因此,这很酷. (16认同)
  • 您还在改变支持请求URL的StringBuffer.如果请求实现没有制作防御性副本,那么这是一种非常好的方法,可以在代码的其他部分引入奇怪的行为和错误,这些代码期望它的原始形式. (8认同)
  • 使用StringBuilder而不是StringBuffer (5认同)
  • 您从getRequestURI复制了描述(错误),但在代码中使用了getRequestURL(右). (3认同)
  • 如果您和用户之间有代理,则可能还需要处理`X-Forwarded-For`和`X-Forwarded-Proto`标题. (2认同)

Mat*_* B. 132

我用这个方法:

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();
}
Run Code Online (Sandbox Code Playgroud)

  • 只是注释:线程安全在这个特定示例中不是问题,因为`url`被声明,实例化,并且仅在方法内使用,因此不能从调用该方法的线程以外的线程访问它. (11认同)
  • 对于快速参考HttpServletRequest上可用的所有信息,这是一个有用的答案.但是,我认为你想在决定是否将端口片添加到结果时检查方案.例如,"https"将是443. (8认同)
  • 一个小的优化是使用StringBuilder而不是StringBuffer,只是一个提示 (2认同)
  • 有什么理由不使用 `getRequestURI` 吗? (2认同)

Tej*_*eni 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;
}
Run Code Online (Sandbox Code Playgroud)

  • 它是*一个*附加对象(StringBuilder),并且不会改变返回的底层StringBuffer.我实际上更喜欢这个而不是"接受"的答案,JVM将优化差异,而且没有任何引入错误的风险. (9认同)
  • 你忽略了`StringBuffer`的优势. (5认同)

Vin*_*vic 6

不推荐使用HttpUtil,这是正确的方法

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


Pet*_*nto 6

在Spring项目中,您可以使用

UriComponentsBuilder.fromHttpRequest(new ServletServerHttpRequest(request)).build().toUriString()
Run Code Online (Sandbox Code Playgroud)

  • 为什么不?`new ServletServerHttpRequest(request).getURI()` (3认同)

Mic*_*rdt 5

结合的结果getRequestURL()getQueryString()应该得到你想要的结果.

  • @flash严格来说,POST参数不是URL的一部分,它们是请求的_body_. (2认同)