【发布时间】:2011-01-14 09:37:02
【问题描述】:
我有一个HttpServletRequest 对象。
如何获取导致此调用到达我的 servlet 的完整且准确的 URL?
或者至少尽可能准确,因为也许有些东西可以重新生成(也许是参数的顺序)。
【问题讨论】:
-
为什么我们没有 util 函数
我有一个HttpServletRequest 对象。
如何获取导致此调用到达我的 servlet 的完整且准确的 URL?
或者至少尽可能准确,因为也许有些东西可以重新生成(也许是参数的顺序)。
【问题讨论】:
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();
}
}
【讨论】:
结合getRequestURL() 和getQueryString() 的结果应该可以得到你想要的结果。
【讨论】:
HttpUtil 被弃用,这是正确的方法
StringBuffer url = req.getRequestURL();
String queryString = req.getQueryString();
if (queryString != null) {
url.append('?');
url.append(queryString);
}
String requestURL = url.toString();
【讨论】:
// 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;
}
【讨论】:
StringBuffer的优势。
我用这个方法:
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();
}
【讨论】:
url 仅在方法内部声明、实例化和使用,因此不能从除调用该方法的那个。
StringBuffer 的实例,而不是与任何其他线程共享它。这应该改为StringBuilder。
getRequestURI ?
您可以使用过滤器。
@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 中的过滤器映射中
【讨论】:
对 HttpServletRequest 对象使用以下方法
java.lang.String getRequestURI() - 返回此请求的 URL 中从协议名称到 HTTP 请求第一行中的查询字符串的部分。
java.lang.StringBuffer getRequestURL() - 重构客户端用于发出请求的 URL。
java.lang.String getQueryString() - 返回路径后面的请求 URL 中包含的查询字符串。
【讨论】:
在 Spring 项目中你可以使用
UriComponentsBuilder.fromHttpRequest(new ServletServerHttpRequest(request)).build().toUriString()
【讨论】:
new ServletServerHttpRequest(request).getURI()
聚会有点晚了,但我在WebUtils 中的MarkUtils-Web library 中包含了这个 - Checkstyle-approved 和 JUnit-tested:
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."><www.ziesemer.com></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;
}
}
可能是迄今为止最快和最可靠的答案,仅次于 Mat Banik 的答案 - 但即使是他的答案也没有考虑到 HTTP/HTTPS 的潜在非标准端口配置。
另见:
【讨论】:
如果您使用来自.getRequestURL() 的StringBuffer 的构建器模式,您可以编写一个简单的带有三元的单行器:
private String getUrlWithQueryParms(final HttpServletRequest request) {
return request.getQueryString() == null ? request.getRequestURL().toString() :
request.getRequestURL().append("?").append(request.getQueryString()).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();
}
这缺少查询部分,但可以按照其他答案中的假设附加。我来这里是因为我特别需要那些转发的东西,希望能帮助别人。
【讨论】: