Servlet API відкриває повний шлях запиту як requestURI
і далі поділяє його на contextPath
, servletPath
та pathInfo
, значення яких залежить від того, яким чином відображено сервлет. Виходячи з цих вступних даних Spring MVC повинен визначити шлях пошуку, який буде використовуватися для відображення обробника, що є шляхом у відображенні самого DispatcherServlet
, виключаючи contextPath
і будь-який префікс servletMapping
, якщо він присутній.
ServletPath
та pathInfo
декодуються, що унеможливлює їх пряме порівняння з повним requestURI
для отримання lookupPath, тому виникає потреба в декодуванні requestURI
. Однак це породжує свої проблеми, оскільки шлях може містити закодовані зарезервовані символи, такі як "/"
або ";"
, які можуть змінити структуру шляху після їх декодування, що також може призвести до проблем безпеки. Крім того, контейнери сервлетів можуть різною мірою нормалізувати servletPath
, що робить ще більш неможливим виконання порівняння startsWith
з requestURI
.
servletPath
, який супроводжує тип відображення servletPath
на основі префікса. Якщо DispatcherServlet
відображено як стандартний сервлет зі знаком "/"
або інакше без префікса зі знаком "/*"
, а контейнер сервлетів має версію 4.0+, то Spring MVC зможе визначити тип відображення сервлета і повністю уникнути використання servletPath
та pathInfo
. У контейнері сервлетів 3.1, за умови використання тих самих типів відображення сервлетів, аналогічного результату можна досягти шляхом надання UrlPathHelper
з alwaysUseFullPath=true
через Path Matching у конфігурації MVC.
На щастя, стандартне відображення сервлетів "/"
є продуманим вибором. Однак все ще існує проблема, пов'язана з тим, що requestURI
потрібно декодувати, щоб можна було порівнювати з відображенням контролерів. Це знову ж таки небажано через ймовірність декодування зарезервованих символів, які змінять структуру шляху. Якщо наявність таких символів не очікується, можна заблокувати їх (як у HTTP-брандмауері Spring Security), або ж можна налаштувати UrlPathHelper
з urlDecode=false
, але відображення контролера повинні будуть відповідати закодованому шляху, що не завжди працює прийнятно. До того ж, іноді DispatcherServlet
доводиться ділити простір URL з іншим сервлетом, і це може вимагати відображення префіксу.
Наведені вище проблеми можна вирішити більш ґрунтовно, якщо перейти від PathMatcher
до парсованого PathPattern
, доступного у версії 5.3 і вище. На відміну від AntPathMatcher
, якому потрібен або декодований шлях пошуку, або закодоване відображення контролера, парсований PathPattern
зіставляється з парсованим поданням шляху, що називається RequestPath
, по одному сегменту шляху за раз. Це дозволяє декодувати та очистити значення сегментів шляху окремо без ризику змінити структуру шляху. Парсований PathPattern
також підтримує використання відображення префікса servletPath
за умови, що префікс залишається простим і не містить символів, які необхідно кодувати.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ