Какая разница между методами getRequestURI и getPathInfo в HttpServletRequest?

Я делаю простой, очень легкий передний контроллер. Мне нужно сопоставить пути запросов к различным обработчикам (действиям), чтобы выбрать правильный.

На моей локальной машине HttpServletRequest.getPathInfo() и HttpServletRequest.getRequestURI() вернуть те же результаты. Но я не уверен, что они вернут в производственной среде.

Итак, какая разница между этими методами и что выбрать?

Ответ 1

getPathInfo() предоставляет дополнительную информацию о пути после URI, используемую для доступа к вашему сервлета, где getRequestURI() предоставляет полный URI.

Я бы подумал, что они будут разными, поскольку Servlet должен быть настроен с собственным шаблоном URI в первую очередь; Я не думаю, что когда-либо служил сервлетом из root (/).

Например, если Servlet 'Foo' сопоставляется с URI '/foo', тогда я бы подумал, что URI:

 
/foo/path/to/resource

Результат:

RequestURI = /foo/path/to/resource

и

PathInfo = /path/to/resource

Ответ 2

Я помещу здесь небольшую таблицу сравнения (просто чтобы ее где-то найти):

Сервлет отображается как /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" не передается на сервер. Только браузер может работать с ним.

  • Если url-pattern в отображении сервлета не заканчивается на * (например, /test или *.jsp), getPathInfo() возвращает null.

Если используется Spring MVC

  • Метод getPathInfo() возвращает null.

  • Метод getServletPath() возвращает часть между контуром и идентификатором сеанса. В приведенном выше примере значение будет /test?/a?+b

  • Будьте осторожны с URL-закодированными частями @RequestMapping и @RequestParam в Spring. Это ошибка (текущая версия 3.2.4) и обычно не работает должным образом.

Ответ 3

Рассмотрим следующий сервлет 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()

    возвращает
    строка, декодированная веб-контейнером, указывающая дополнительную информацию о пути, которая поступает после пути сервлета, но до строки запроса в URL-адресе запроса; или null, если URL-адрес не содержит дополнительной информации о пути

  • getRequestURI()

    возвращает
    Строка, содержащая часть URL-адреса от имени протокола до строки запроса

Ответ 4

Позвольте сложить полный 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
  • путь сервлета: path/to/servlet
  • информация о пути: path/info
  • query: a=1&b=2
  • фрагмент: boo

URI запроса (возвращаемый getRequestURI) соответствует частям 4, 5 и 6.

(кстати, хотя вы не просите об этом, метод getRequestURL даст вам части 1, 2, 3, 4, 5 и 6).

Сейчас:

  • часть 4 (путь контекста) используется для выбора вашего конкретного приложения из многих других приложений, которые могут выполняться на сервере.
  • часть 5 (путь сервлета) используется для выбора определенного сервлета из многих других сервлетов, которые могут быть добавлены в ваше приложение WAR
  • часть 6 (информация о пути) интерпретируется вашей логикой сервлета (например, она может указывать на некоторый ресурс, управляемый вашим сервлетом).
  • часть 7 (запрос) также доступна для вашего сервлета, используя getQueryString
  • часть 8 (фрагмент) даже не отправляется на сервер и имеет значение и известна только клиенту

Следующее всегда выполняется (кроме различий в кодировке URL):

requestURI = contextPath + servletPath + pathInfo

Ниже приведен пример из спецификации Servlet 3.0:


Примечание: изображение следует, у меня нет времени для воссоздания в HTML:

введите описание изображения здесь