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

Posted

技术标签:

【中文标题】如何在没有上下文路径的情况下获取请求 URI?【英文标题】:How to get request URI without context path? 【发布时间】:2011-05-15 18:03:51 【问题描述】:

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

例如,如果一个应用程序的基本 URL 是 http://localhost:8080/myapp/(即上下文路径是 myapp),并且我为 http://localhost:8080/myapp/secure/users 调用 request.getRequestURI(),它将返回 /myapp/secure/users .

有什么方法可以只得到这部分/secure/users,即没有上下文路径的URI?

【问题讨论】:

What's the difference between getRequestURI and getPathInfo methods in HttpServletRequest?的可能重复 【参考方案1】:

如果您在前控制器 servlet 中,该 servlet 映射到前缀模式(例如 /foo/*),那么您可以只使用 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());
// ...

【讨论】:

有理由用这个来代替getServletPath()吗?我正在编写一个过滤器,我注意到getPathInfo() 返回null,但getServletPath() 返回的路径减去上下文(适合传递给请求调度程序)。 @JasonC:如回答,如果前端控制器 servlet 未映射到前缀模式,getPathInfo() 将返回 null。 是的。我的意思是:您是否有理由更喜欢 getPathInfo 而不是 getServletPath?这里的许多其他高分答案也没有使用 getServletPath,这就是让我怀疑它的原因,也是我想知道的原因。我有一个正在处理的 servlet 项目,我正在努力提高自己的技能。 @JasonC:当您安装了基于 servlet 的 MVC 框架(如 JSF 或 Spring MVC)时,servlet 路径可能会发生变化。然后它将代表 MVC 框架的内部路径(例如 /foo.xhtml 而不是 /foo.jsf)而不是实际的请求 URI(最终用户将在浏览器的地址栏中看到的那个)。在这种情况下,原始的 servlet 路径可以解析为带有键 RequestDispatcher.FORWARD_SERVLET_PATH 的请求属性。无论如何,问题明确要求提供请求 URI(如在浏览器的地址栏中),因此答案基于此。【参考方案2】:
request.getRequestURI().substring(request.getContextPath().length())

【讨论】:

太棒了!这正是我想要的。 +1 我认为这是比 getPathInfo 更好的答案,因为 getPathInfo 可以为 null 和其他奇怪的东西。各种 Spring 代码确实 getContextPath 并将其从 URI 中删除,就像您所做的那样,而不是 getPathInfo。【参考方案3】:

使用 Spring,您可以:

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

【讨论】:

当然保留一个 UrlPathHelper 的实例是有意义的,例如作为类成员变量... 我们怎样才能得到实际的请求映射url?请在此处指导:***.com/questions/60446807/…【参考方案4】:

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

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

我需要在过滤器中获取没有上下文路径的文件路径,并且 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());
    ...


【讨论】:

【参考方案5】:

如果你在过滤器中使用 request.getPathInfo() ,你似乎总是得到空值(至少在码头上)。

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

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

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

虽然 contextPath 是可用的,所以 fforws 解决方案甚至可以在过滤器中使用。我不喜欢手工做,但实现被破坏或

【讨论】:

【参考方案6】:

实现此目的的一种方法是从请求 URI 中保留 serverlet 上下文路径。

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

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

阅读here。

【讨论】:

【参考方案7】:

也许你可以只使用 split 方法来消除 '/myapp' 例如:

string[] uris=request.getRequestURI().split("/");
string uri="/"+uri[1]+"/"+uris[2];

【讨论】:

如果我以 root 身份部署我的应用程序并且其基本 URL 变为 localhost:8080,这将导致问题。在这种情况下 request.getRequestURI() 将返回 "/secure/user" 并且您的拆分方法将在这里引起问题。代码不应依赖于部署。

以上是关于如何在没有上下文路径的情况下获取请求 URI?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不包含上下文根名称的情况下使用相对路径?

spring 如何在freemarker模板中获取请求上下文

在没有上下文的情况下获取 AssetManager

android选择图片,通过uri获取路径

如何在spring中的freemarker模板中获取请求上下文

如何在 Tomcat 中设置上下文路径,以便在不附加部署文件夹名称的情况下进入站点?