在 HttpServletRequest 中 getRequestURI 和 getPathInfo 方法之间有什么区别?

我在做一个简单,非常轻便的前置控制器。我需要将请求路径匹配到不同的处理程序(操作) ,以便选择正确的路径。

在我的本地机器 HttpServletRequest.getPathInfo()HttpServletRequest.getRequestURI()返回相同的结果。但我不确定它们在生产环境中会返回什么。

那么,这些方法和我应该选择的方法有什么区别呢?

187520 次浏览

getPathInfo()在 URI 之后提供额外的路径信息,用于访问 Servlet,而 getRequestURI()提供完整的 URI。

我认为它们会有所不同,因为 Servlet 首先必须配置为自己的 URI 模式; 我认为我从未从 root (/)服务过 Servlet。

例如,如果 Servlet‘ Foo’映射到 URI’/Foo’,那么我会认为 URI:

/foo/path/to/resource

会导致:

RequestURI = /foo/path/to/resource

还有

PathInfo = /path/to/resource

考虑以下 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,指定在请求 URL 中的 servlet 路径之后但在查询字符串之前的额外路径信息; 或者,如果 URL 没有任何额外路径信息,则为 null

  • getRequestURI()

    报税表
    包含从协议名到查询字符串的 URL 部分的 String

我将在这里放一个小的比较表(只是为了把它放在某个地方) :

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被放入到 OS hosts文件中。

评论

  • “ +”仅在查询字符串中作为空格处理

  • 锚“ # a”不会传输到服务器。只有浏览器可以使用它。

  • 如果 servlet 映射中的 url-pattern没有以 *结束(例如 /test*.jsp) ,则 getPathInfo()返回 null

如果使用 Spring MVC

  • 方法 getPathInfo()返回 null

  • 方法 getServletPath()返回上下文路径和会话 ID 之间的部分。在上面的例子中,值应该是 /test?/a?+b

  • 在 Spring 中要小心使用 @RequestMapping@RequestParam的 URL 编码部分。它有 bug (当前版本3.2.4) ,通常是 不像预期的那样工作

让我们分解一下客户端为了到达 servlet 而在地址栏中输入的完整 URL:

Http://www.example.com:80/awesome-application/path/to/servlet/path/info?a=1&b=2#boo

这些部分是:

  1. 计划: http
  2. 主机名: www.example.com
  3. 端口: 80
  4. 上下文路径: awesome-application
  5. Servlet 路径: path/to/servlet
  6. 路径信息: path/info
  7. 查询: a=1&b=2
  8. 片段: 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规范的例子非常有帮助:


注意: 图片如下,我没有时间在 HTML 中重新创建:

enter image description here