如何在没有上下文路径的情况下获取请求URI?

问题描述 投票:0回答:8

方法 request.getRequestURI() 返回带有上下文路径的 URI。

例如,如果应用程序的基本 URL 是

http://localhost:8080/myapp/
(即上下文路径是 myapp),并且我为
request.getRequestURI()
调用
http://localhost:8080/myapp/secure/users
,它将返回
/myapp/secure/users

有什么办法我们可以只获取这部分

/secure/users
,即没有上下文路径的URI?

java servlets
8个回答
177
投票

如果您位于映射到前缀模式(例如

/foo/*
)的前端控制器 servlet 中,那么您可以只使用
HttpServletRequest#getPathInfo()

String pathInfo = request.getPathInfo();
// ...

假设示例中的 servlet 映射到

/secure/*
,那么这将返回
/users
,这将是典型前端控制器 servlet 中唯一感兴趣的信息。

但是,如果 servlet 映射到后缀模式,例如

*.foo
(但是您的 URL 示例并不表明情况如此),或者当您实际上位于过滤器内时(当要调用的 servlet 是尚未确定,因此
getPathInfo()
可能会返回
null
),那么最好的选择是使用通常的
String
方法,根据上下文路径的长度自行对请求 URI 进行子字符串化:

HttpServletRequest request = (HttpServletRequest) req;
String path = request.getRequestURI().substring(request.getContextPath().length());
// ...

89
投票
request.getRequestURI().substring(request.getContextPath().length())

40
投票

使用 Spring 你可以做到:

String path = new UrlPathHelper().getPathWithinApplication(request);

16
投票

getPathInfo() 有时返回 null。在文档中HttpServletRequest

如果没有额外的路径信息,该方法返回null。

我需要在 Filter 中获取没有上下文路径的文件路径,并且 getPathInfo() 返回 null。所以我使用另一种方法:httpRequest.getServletPath()

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpServletResponse httpResponse = (HttpServletResponse) response;

    String newPath = parsePathToFile(httpRequest.getServletPath());
    ...

}

9
投票

如果你在 Filter 中使用 request.getPathInfo() ,你似乎总是得到 null (至少对于 jetty 来说是这样)。

这个简洁的无效错误+响应暗示了我认为的问题:

https://issues.apache.org/bugzilla/show_bug.cgi?id=28323

我怀疑这与过滤器在 servlet 获取请求之前运行这一事实有关。这可能是一个容器错误,或者是我无法识别的预期行为。

尽管 contextPath 可用,所以 fforws 解决方案即使在过滤器中也能工作。我不喜欢手动完成,但实现已损坏或


5
投票

实现此目的的一种方法是从请求 URI 中恢复servlet上下文路径。

String p = request.getRequestURI();
String cp = getServletContext().getContextPath();

if (p.startsWith(cp)) {
  String.err.println(p.substring(cp.length());
}

请阅读此处 .


0
投票

简短回答

String requestUriWithinApp = req.getPathInfo() == null
        ? req.getServletPath()
        : req.getServletPath() + req.getPathInfo();

ServletPath
获取调用 servlet 的 URL 部分。和
PathInfo
返回与客户端发出此请求时发送的 URL 关联的任何额外路径信息。
PathInfo
可能为 null,具体取决于客户端使用的 URL。

为了获得更完整的 URI,您还可以包含查询字符串。然后你可以使用:

StringBuilder sb = new StringBuilder();
sb.append(req.getServletPath());
if (req.getPathInfo() != null) {
    sb.append(req.getPathInfo());
}
if (req.getQueryString() != null) {
    sb.append("?").append(req.getQueryString());
}

附加信息

requestURI的公式为:

requestURI = contextPath + servletPath + 路径信息

在你的问题中,你不想使用

contextPath
,所以你需要:

servletPath + 路径信息

例如,如果您有:

  • 位于
    /catalog
  • 的 Web 应用程序上下文
  • a
    GardenServlet
    表示图案
    /garden/*
  • 客户端发送的请求
    /catalog/lawn/index.html
  • 那么
    pathInfo
    就是
    /index.html

此示例在 Servlet 规范 - 3.6 请求路径元素中进行了更详细的描述。

Tuckey 的 UrlRewriteFilter 的文档包含有关如何在 ServletRequest 中组成 URL 的更完整示例。

// http://hostname.com:80/mywebapp/servlet/MyServlet/a/b;c=123?d=789 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 String url = scheme + "://" + serverName + ":" + serverPort + contextPath + servletPath; if (pathInfo != null) { url += pathInfo; } if (queryString != null) { url += "?" + queryString; } return url; }
    

-1
投票
也许你可以使用 split 方法来消除 '/myapp' 例如:

string[] uris=request.getRequestURI().split("/"); string uri="/"+uri[1]+"/"+uris[2];
    
© www.soinside.com 2019 - 2024. All rights reserved.