В Thymeleaf <3.1 я использовал приведенное ниже выражение, чтобы получить URI запроса.
th:classappend = "${#arrays.contains(urls, #httpServletRequest.getRequestURI()) ? 'active' : ''}"
Это работало все время, пока недавно я не обновился до Spring Boot 3.0, который тянет Thymeleaf 3.1. Я получаю эти исключения:
[THYMELEAF][parallel-2] Exception processing template "index": Exception evaluating SpringEL expression: "#arrays.contains(urls, #servletServerHttpRequest.getRequestURI()) ? 'active' : ''" (template: "fragments/header" - line 185, col 6)
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1011E: Method call: Attempted to call method getRequestURI() on null context object
Какова альтернатива сейчас, поскольку я использую Netty вместо Tomcat в Spring Boot 3.0? Я не мог понять это из здесь.
В качестве обходного пути, на данный момент, чтобы решить эту проблему, я использую:
@GetMapping ("/")
String homePage(Model model) {
model.addAttribute("pagename", "home");
return "index";
}
И
th:classappend = "${pagename == 'home' ? 'active' : ''}"
В Thymeleaf 3.0 доступ предоставляется к HttpServletRequest
:
#request : прямой доступ к объекту javax.servlet.http.HttpServletRequest, связанному с текущим запросом. ссылка
Это было удалено из Thymeleaf в 3.1.0. Вот эквивалентный раздел из документации: Пространства имен веб-контекста для атрибутов запроса/сеанса и т. д..
В документации «что нового в версии 3.1» конкретно не упоминается HttpServletRequest
, но упоминается удаление всех «служебных объектов выражений на основе веб-API».
#request, #response, #session и #servletContext больше не доступны для выражений в Thymeleaf 3.1.
Spring Boot 3.0.0 использует Thymeleaf 3.1.0 (как вы заметили).
Что делать вместо этого?
См. соответствующую проблему GitHub: Рекомендуемый способ перехода после обновления до SpringBoot3 — атрибуты
Конкретно:
Эти объекты недоступны напрямую в шаблонах в Thymeleaf 3.1 по соображениям безопасности. Рекомендуемый способ сделать эту информацию доступной для шаблонов — добавить определенные фрагменты информации, которые действительно необходимы шаблону, в качестве переменных контекста (атрибуты модели в Spring).
Пример:
model.addAttribute("servletPath", request.getServletPath();
Это тот же базовый подход, который вы уже применяете в своей работе.
См. также: Удаление служебных объектов выражений на основе веб-API
Добавляя к ответу @andrewJames,
Если вы используете request.getServletPath()
на многих страницах, то в таком случае удобнее использовать аннотацию Spring @ModelAttribute
в классе @ControllerAdvice
. Он зарегистрирует этот метод @ModelAttribute
для всех контроллеров в вашем приложении. Пример:
@ControllerAdvice
public class GlobalController {
@ModelAttribute("servletPath")
String getRequestServletPath(HttpServletRequest request) {
return request.getServletPath();
}
}
Наконец, на любой странице вы можете получить доступ, используя:
${servletPath}
Да, я знаю об этом и использую его для публикации имени приложения и имени пользователя, вошедшего в систему, на всех страницах.
Ты потрясающий @andrewJames. Я полностью пропустил раздел 1.6 в документации о том, что нового в 3.1. Большое спасибо за ваше время и усилия.