GetRequestURI имеет значение null с Netty и Spring Boot 3

В 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' : ''}"
3
0
698
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

В 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. Я полностью пропустил раздел 1.6 в документации о том, что нового в 3.1. Большое спасибо за ваше время и усилия.

Ajay Kumar 28.11.2022 04:31

Добавляя к ответу @andrewJames,

Если вы используете request.getServletPath() на многих страницах, то в таком случае удобнее использовать аннотацию Spring @ModelAttribute в классе @ControllerAdvice. Он зарегистрирует этот метод @ModelAttribute для всех контроллеров в вашем приложении. Пример:

@ControllerAdvice
public class GlobalController {

  @ModelAttribute("servletPath")
  String getRequestServletPath(HttpServletRequest request) {
    return request.getServletPath();
  }
}

Наконец, на любой странице вы можете получить доступ, используя:

${servletPath}

Да, я знаю об этом и использую его для публикации имени приложения и имени пользователя, вошедшего в систему, на всех страницах.

Ajay Kumar 03.01.2023 23:51

Другие вопросы по теме