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


143

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

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

Отже, у чому різниця між цим методом і тим, що я повинен вибрати?


1
Ця відповідь також може бути корисною.
BalusC

@BalusC: дякую, я вже використовував поради з цієї відповіді.
Роман

Це пояснює різницю приємною схемою: agiletribe.wordpress.com/2016/02/23/…
AgilePro

Відповіді:


77

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

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

Наприклад, якщо Servlet 'Foo' відображено в URI '/ foo', я б подумав, що URI:

/foo/path/to/resource

Це призведе до:

RequestURI = /foo/path/to/resource

і

PathInfo = /path/to/resource

20
Варто згадати про поведінку розшифровки. getRequestURI () не декодує рядок. Де getPathInfo () декодує.
Kavindu Dodanduwa

1
У деяких випадках getRequestURI()дає мені рядок, "/foo/path/to/resource"як очікувалося, але getPathInfo()для того ж HttpServletRequestоб'єкта дає мені null. Що в світі відбувається? РЕДАКТУВАННЯ. Відповідь на нього відповідає користувач "30thh".
anddero

460

Я поміщу сюди невелику таблицю порівняння (просто щоб її десь було):

Сервлет відображається як, /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) і зазвичай не працює, як очікувалося .


20
Я друкую вашу відповідь і викладаю її як плакат у нашому офісі. Ось як це корисно!
Ібрагім Короткий

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.
Gediminas Rimsa

30

Давайте розбимо повну 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 (шлях сервлетів) використовується для вибору конкретного сервлета з багатьох інших сервлетів, які можуть бути в комплекті у ВІЙНІ вашої програми
  • частина 6 (інформація про шлях) інтерпретується логікою вашого сервлета (наприклад, це може вказувати на деякий ресурс, керований вашим сервлетом).
  • Частина 7 (запит) також доступна для вашого сервлету за допомогою getQueryString
  • частина 8 (фрагмент) навіть не надсилається на сервер і є актуальною і відомою лише клієнту

Застосовується наступне (за винятком відмінностей кодування URL):

requestURI = contextPath + servletPath + pathInfo

Наступний приклад із специфікації Servlet 3.0 є дуже корисним:


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

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


16

Розглянемо наступні конфлікти сервлетів:

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.