如何在没有上下文路径的情况下获取请求 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模板中获取请求上下文