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
при условии, что префикс остается простым и не содержит символов, которые необходимо кодировать.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ