В чем разница между методами getRequestURI и getPathInfo в HttpServletRequest?

146

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

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

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

Римский
источник
1
Вы также можете найти этот ответ полезным.
BalusC
@BalusC: спасибо, я уже использовал несколько советов из этого ответа.
Роман
Это объясняет разницу с красивой диаграммой: agiletribe.wordpress.com/2016/02/23/…
AgilePro 01

Ответы:

78

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

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

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

/foo/path/to/resource

Это приведет к:

RequestURI = /foo/path/to/resource

а также

PathInfo = /path/to/resource
Trojanfoe
источник
20
стоит упомянуть о поведении декодирования. getRequestURI () не декодирует строку. Где getPathInfo () декодирует.
Kavindu Dodanduwa 06
1
В некоторых случаях getRequestURI()дает мне строку, "/foo/path/to/resource"как и ожидалось, но getPathInfo()для того же HttpServletRequestобъекта дает мне null. Что происходит в мире? РЕДАКТИРОВАТЬ: на него ниже отвечает пользователь «30thh».
anddero
471

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

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

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

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

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

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

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

30-е
источник
22
Я распечатываю ваш ответ и развешиваю его плакатом в нашем офисе. Вот как это полезно!
Ибрагим Ариф
2
If the url-pattern in the servlet mapping does not end with * (for example /test or *.jsp), getPathInfo() returns null.блестящий.
Борис Треухов
1
Я считаю, что оба getRequestURI()и getRequestURL()в этом случае должны возвращать не декодированный jsessionid S%3F+ID. По крайней мере, на Tomcat / 8.5.6.
Гедиминас Римса
34

Давайте разберем полный 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. путь сервлета: 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 (путь к сервлету) используется для выбора конкретного сервлета из множества других сервлетов, которые могут быть включены в WAR вашего приложения.
  • часть 6 (информация о пути) интерпретируется логикой вашего сервлета (например, она может указывать на некоторый ресурс, управляемый вашим сервлетом).
  • часть 7 (запрос) также доступна вашему сервлету с помощью getQueryString
  • часть 8 (фрагмент) даже не отправляется на сервер, а актуальна и известна только клиенту

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

requestURI = contextPath + servletPath + pathInfo

Следующий пример из спецификации Servlet 3.0 очень полезен:


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

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

Марк Юний Брут
источник
17

Рассмотрим следующую конфигурацию сервлета:

   <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-адреса от имени протокола до строки запроса

Джигар Джоши
источник