EN · DE · RU · FR · ES

#2775: PageParameterAwareMountedMapper.java

projectforge-wicket/src/main/java/de/micromata/wicket/request/mapper/PageParameterAwareMountedMapper.java Wicket Request Mapper (Маршрутизация URL) · projectforge-wicket/src/main/java/de/micromata/wicket/request/mapper/PageParameterAwareMountedMapper.java 126 строк · 47 кода · 71 комментарий · 8 пустых
Критическое исправление маршрутизации URL в Wicket, устраняющее тонкий дефект в поведении стандартного MountedMapper. Когда пользователь вручную редактирует URL Wicket — например, меняет /User/4?15 на /User/5?15 — стандартный маппер отдаёт приоритет параметру ID страницы в запросе (?15) над параметрами пути (/5), в результате чего пользователь видит кэшированную страницу для пользователя 4 вместо новой страницы для пользователя 5. Этот пользовательский маппер обнаруживает несоответствия между параметрами кэшированной страницы и параметрами текущего запроса и перенаправляет на новый экземпляр страницы с возможностью закладки, когда они различаются, гарантируя, что URL всегда отражает актуальное отображаемое содержимое.

Архитектура

Стратегия переопределения

Класс расширяет MountedMapper и переопределяет только processHybrid() — метод, который Wicket вызывает, когда у него есть как ID страницы (из кэшированной в сессии страницы), так и параметры пути (из URL). Переопределение:

  1. Вызывает родительский processHybrid() для получения обработчика по умолчанию
  2. Перехватывает PageExpiredException — если кэшированная страница устарела, возвращается к processBookmarkable(), который создаёт новую страницу
  3. Если родительский метод вернул RenderPageRequestHandler с PageProvider, содержащим экземпляр страницы, сравнивает: (a) класс страницы кэшированного экземпляра с запрошенным классом страницы и (b) параметры кэшированной страницы с параметрами текущего запроса
  4. Если любое из сравнений не удаётся, перенаправляет на processBookmarkable() — новый экземпляр страницы без состояния с правильными параметрами

Корневая проблема

Стандартный MountedMapper в Wicket реализует «гибридную» стратегию: если в URL присутствует ID страницы (либо как ?wicket:pageId=15, либо через сокращение ?15), загрузить сериализованную страницу из хранилища страниц; в противном случае создать новый экземпляр с возможностью закладки. Проблема в том, что после того, как сессия получила кэшированную страницу (например, ID страницы 15 для пользователя 4), последующие запросы с другими параметрами пути, но тем же ID страницы будут обслуживать кэшированную страницу — маппер никогда не сравнивает параметры пути с параметрами кэшированной страницы. Манипуляции с URL со стороны пользователя (или история браузера) могут привести к отображению устаревших данных.

Использование монтирования

Страницы монтируются в WicketApplication.init() с помощью mount(new PageParameterAwareMountedMapper("Home", HomePage.class)) вместо mountPage(). Это задокументировано в Javadoc самого класса с примером использования.

История Git

КоммитЧто изменилось
868d6abb7ceb63e8a1Шесть ежегодных обновлений заголовков авторских прав. Сама логика маппинга оставалась стабильной с момента создания — поведение маршрутизации URL оказалось корректным для всех смонтированных страниц при нескольких обновлениях версий Wicket.