【问题标题】:What's the difference between getRequestURI and getPathInfo methods in HttpServletRequest?HttpServletRequest 中的 getRequestURI 和 getPathInfo 方法有什么区别?
【发布时间】:2011-06-23 07:29:15
【问题描述】:

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

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

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

【问题讨论】:

标签: java servlets


【解决方案1】:

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”在下面回答。
【解决方案2】:

考虑以下 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 部分

【讨论】:

    【解决方案3】:

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

    Servlet 映射为/test%3F/*,应用程序部署在/app 下。

    http://30thh.loc:8480/app/test%3F/a%3F+b;jsessionid=S%3F+ID?p+1=c+d&amp;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 上是这样。
    【解决方案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&amp;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 specification 中的以下示例非常有帮助:


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

    【讨论】:

      猜你喜欢
      • 2021-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-26
      • 2018-05-14
      • 2010-09-14
      相关资源
      最近更新 更多