HttpServletRequest 中的 getRequestURI 和 getPathInfo 方法有啥区别?
Posted
技术标签:
【中文标题】HttpServletRequest 中的 getRequestURI 和 getPathInfo 方法有啥区别?【英文标题】:What's the difference between getRequestURI and getPathInfo methods in HttpServletRequest?HttpServletRequest 中的 getRequestURI 和 getPathInfo 方法有什么区别? 【发布时间】:2011-06-23 07:29:15 【问题描述】:我正在制作一个简单、非常轻巧的前置控制器。我需要将请求路径与不同的处理程序(操作)进行匹配,以便选择正确的处理程序。
在我的本地机器上 HttpServletRequest.getPathInfo()
和 HttpServletRequest.getRequestURI()
返回相同的结果。但我不确定他们会在生产环境中返回什么。
那么,这些方法有什么区别,我应该选择什么?
【问题讨论】:
您可能会发现this answer 也很有用。 @BalusC:谢谢,我已经在使用该答案中的一些技巧了。 这用一张漂亮的图表解释了差异:agiletribe.wordpress.com/2016/02/23/… 【参考方案1】:我会在这里放一个小比较表(只是为了放在某个地方):
Servlet 映射为/test%3F/*
,应用程序部署在/app
下。
http://30thh.loc:8480/app/test%3F/a%3F+b;jsessionid=S%3F+ID?p+1=c+d&p+2=e+f#a
Method URL-Decoded Result
----------------------------------------------------
getContextPath() no /app
getLocalAddr() 127.0.0.1
getLocalName() 30thh.loc
getLocalPort() 8480
getMethod() GET
getPathInfo() yes /a?+b
getProtocol() HTTP/1.1
getQueryString() no p+1=c+d&p+2=e+f
getRequestedSessionId() no S%3F+ID
getRequestURI() no /app/test%3F/a%3F+b;jsessionid=S+ID
getRequestURL() no http://30thh.loc:8480/app/test%3F/a%3F+b;jsessionid=S+ID
getScheme() http
getServerName() 30thh.loc
getServerPort() 8480
getServletPath() yes /test?
getParameterNames() yes [p 2, p 1]
getParameter("p 1") yes c d
在上面的示例中,服务器在localhost:8480
上运行,名称30thh.loc
被放入操作系统hosts
文件中。
评论
“+”仅在查询字符串中作为空格处理
锚点“#a”未传输到服务器。只有浏览器可以使用它。
如果 servlet 映射中的url-pattern
不以*
结尾(例如/test
或*.jsp
),则getPathInfo()
返回null
。
如果使用 Spring MVC
方法getPathInfo()
返回null
。
方法getServletPath()
返回上下文路径和会话ID 之间的部分。在上面的示例中,该值将是 /test?/a?+b
注意 Spring 中 @RequestMapping
和 @RequestParam
的 URL 编码部分。它有问题(当前版本 3.2.4),通常是 not working as expected。
【讨论】:
我正在打印您的答案,并将其作为海报张贴在我们的办公室。这就是它的用处!If the url-pattern in the servlet mapping does not end with * (for example /test or *.jsp), getPathInfo() returns null.
辉煌。
我相信getRequestURI()
和getRequestURL()
都应该返回未解码的jsessionid,在本例中为S%3F+ID
。至少在 Tomcat/8.5.6 上是这样。【参考方案2】:
getPathInfo()
在 URI 之后提供额外的路径信息,用于访问您的 Servlet,其中 getRequestURI()
提供完整的 URI。
我原以为它们会有所不同,因为首先必须使用自己的 URI 模式配置 Servlet;我认为我从未从根 (/) 提供过 Servlet。
例如,如果 Servlet 'Foo' 映射到 URI '/foo' 那么我会认为 URI:
/foo/path/to/resource
会导致:
RequestURI = /foo/path/to/resource
和
PathInfo = /path/to/resource
【讨论】:
值得一提的是解码行为。 getRequestURI() 不解码字符串。 getPathInfo() 在哪里解码。 在某些情况下,getRequestURI()
给了我预期的字符串"/foo/path/to/resource"
,但是对于相同的HttpServletRequest
对象的getPathInfo()
给了我null
。世界上到底发生了什么? 编辑:用户“30thh”在下面回答。【参考方案3】:
让我们分解客户在其地址栏中键入以访问您的 servlet 的完整 URL:
http://www.example.com:80/awesome-application/path/to/servlet/path/info?a=1&b=2#boo
部分是:
-
方案:
http
主机名:www.example.com
端口:80
上下文路径:awesome-application
servlet 路径:path/to/servlet
路径信息:path/info
查询:a=1&b=2
片段:boo
请求 URI(由getRequestURI 返回)对应于第 4、5 和 6 部分。
(顺便说一句,即使您不要求这样做,getRequestURL 方法也会为您提供第 1、2、3、4、5 和 6 部分)。
现在:
第 4 部分(上下文路径)用于从可能在服务器中运行的许多其他应用程序中选择您的特定应用程序 第 5 部分(servlet 路径)用于从可能捆绑在应用程序的 WAR 中的许多其他 servlet 中选择特定的 servlet 第 6 部分(路径信息)由您的 servlet 的逻辑解释(例如,它可能指向某些由您的 servlet 控制的资源)。 第 7 部分(查询)也可以使用 getQueryString 提供给您的 servlet 第 8 部分(片段)甚至不发送到服务器,并且只为客户端相关和知道以下内容始终成立(URL 编码差异除外):
requestURI = contextPath + servletPath + pathInfo
Servlet 3.0 specification 中的以下示例非常有帮助:
注意:图片如下,我没有时间用 html 重新创建:
【讨论】:
【参考方案4】:考虑以下 servlet conf:
<servlet>
<servlet-name>NewServlet</servlet-name>
<servlet-class>NewServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>NewServlet</servlet-name>
<url-pattern>/NewServlet/*</url-pattern>
</servlet-mapping>
现在,当我点击 URL http://localhost:8084/JSPTemp1/NewServlet/jhi
时,它将调用 NewServlet
,因为它与上述模式映射。
这里:
getRequestURI() = /JSPTemp1/NewServlet/jhi
getPathInfo() = /jhi
我们有那些:
getPathInfo()
退货 一个字符串,由 Web 容器解码,指定在请求 URL 中的 servlet 路径之后但在查询字符串之前的额外路径信息;如果 URL 没有任何额外的路径信息,则为 null
getRequestURI()
退货 一个字符串,包含从协议名称到查询字符串的 URL 部分
【讨论】:
以上是关于HttpServletRequest 中的 getRequestURI 和 getPathInfo 方法有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章
如何从HttpServletRequest中拿到前端以application/json形式传输的body中的json串
java中HttpServletRequest常用获取url资源名等方法总结