我有一个HttpServletRequest对象。

我如何获得导致这个调用到达我的servlet的完整而准确的URL ?

或者至少尽可能准确,因为有些东西是可以重新生成的(也许是参数的顺序)。


当前回答

在HttpServletRequest对象上使用以下方法

以getRequestURI () 返回该请求的URL部分,从协议名到HTTP请求第一行的查询字符串。

java.lang.StringBuffer getRequestURL () -重建客户端用来发出请求的URL。

以getQueryString () -返回包含在请求URL中路径后面的查询字符串。

其他回答

// 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;
}

在Spring项目中您可以使用

UriComponentsBuilder.fromHttpRequest(new ServletServerHttpRequest(request)).build().toUriString()

HttpUtil已弃用,这是正确的方法

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

当请求被转发时,例如从反向代理,HttpServletRequest.getRequestURL()方法将不会返回被转发的url,而是返回本地url。 当设置了x-forwarded-* Headers时,这可以很容易地处理:

public static String getCurrentUrl(HttpServletRequest request) {
    String forwardedHost = request.getHeader("x-forwarded-host");

    if(forwardedHost == null) {
        return request.getRequestURL().toString();
    }

    String scheme = request.getHeader("x-forwarded-proto");
    String prefix = request.getHeader("x-forwarded-prefix");

    return scheme + "://" + forwardedHost + prefix + request.getRequestURI();
}

这缺少查询部分,但可以在其他答案中添加。我来这里,是因为我特别需要转发的东西,希望能帮助别人解决这个问题。

如果你使用了.getRequestURL()中的StringBuffer的构建器模式,你可以用三元写一个简单的一行代码:

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

但这只是语法糖。