在HttpServletRequest中getRequestURI和getPathInfo方法有什么区别?
我正在做一个简单,非常轻量级的前端控制器。 我需要匹配请求path到不同的处理程序(动作),以便select正确的。
在我的本地机器HttpServletRequest.getPathInfo()和HttpServletRequest.getRequestURI()返回相同的结果。 但我不确定在生产环境中他们会返回什么。 
那么,这些方法和我应该select什么有什么区别呢?
  getPathInfo()在URI之后提供额外的path信息,用于访问您的Servlet,其中getRequestURI()提供完整的URI。 
我会认为它们会有所不同,因为Servlet必须首先configuration自己的URI模式; 我不认为我曾经从根(/)服务过Servlet。
例如,如果Servlet'Foo'映射到URI'/ foo'那么我会想到这个URI:
 /foo/path/to/resource 
会导致:
 RequestURI = /foo/path/to/resource 
和
 PathInfo = /path/to/resource 
我会在这里放一个小对照表(只是为了让它在某个地方):
  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 cd 
 在上面的示例中,服务器在localhost:8480上运行,并将名称30thh.loc放入OS hosts文件中。 
注释
- 
“+”仅作为查询string中的空格处理 
- 
锚“#a”没有传输到服务器。 只有浏览器可以使用它。 
- 
如果servlet映射中的 url-pattern不以*结尾(例如/test或*.jsp),则getPathInfo()返回null。
如果使用Spring MVC
- 
方法 getPathInfo()返回null。
- 
方法 getServletPath()返回上下文path和会话ID之间的部分。 在上面的例子中,值是/test?/a?+b
- 
在Spring中,请注意 @RequestMapping和@RequestParamURL编码部分。 这是buggy(当前版本3.2.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容器解码的string,指定在servletpath之后但位于请求URL中的查询string之前的额外path信息; 如果URL没有任何额外的path信息,则返回null
- 
getRequestURI()回报 
 包含从协议名称到查询string的URL部分的string
让我们分解一下客户端input到地址栏的完整URL,以便到达您的servlet:
http://www.example.com:80/awesome-application/path/to/servlet/path/info?a=1&b=2#boo
零件是:
-  scheme: http
-  主机名: www.example.com
-  港口: 80
-  上下文path: awesome-application
-   servletpath: path/to/servlet
-  path信息: path/info
-  查询: a=1&b=2
-  片段: boo
请求URI(由getRequestURI返回)对应于部分4,5和6。
(顺便说一句,即使你不要求这个,方法getRequestURL会给你1,2,3,4,5和6部分)。
现在:
- 第4部分(上下文path)用于从可能在服务器上运行的许多其他应用程序中select您的特定应用程序
- 第5部分(servletpath)用于从可能捆绑在应用程序的WAR中的许多其他servlet中select一个特定的servlet
- 第6部分(path信息)是由你的servlet的逻辑来解释的(例如它可能指向由你的servlet控制的一些资源)。
- 第7部分(查询)也可以使用getQueryString提供给您的servlet
- 第8部分(片段)甚至没有被发送到服务器,并且仅与客户端相关并且是已知的
以下内容始终有效(URL编码差异除外):
 requestURI = contextPath + servletPath + pathInfo 
以下来自Servlet 3.0规范的示例非常有用:
注意:图片如下,我没有时间在HTML中重新创build:
 