1. Введение
В этом уроке мы сосредоточимся на Spring MVC HandlerInterceptor.
В частности, мы изменим параметры модели Spring MVC до и после обработки запроса.
Если вы хотите прочитать об основах HandlerInterceptor
, ознакомьтесь с этой статьей .
2. Зависимости Maven
Чтобы использовать Interceptors
, вам необходимо включить следующий раздел в раздел зависимостей
вашего файла pom.xml
:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.13</version>
</dependency>
Последнюю версию можно найти здесь .
Эта зависимость распространяется только на Spring Web, поэтому не забудьте добавить s pring-core
и spring-context
для полноценного веб-приложения, а также библиотеку журналов по вашему выбору.
3. Пользовательская реализация
Одним из вариантов использования HandlerInterceptor
является добавление в модель общих/специфических для пользователя параметров, которые будут доступны в каждом сгенерированном представлении.
В нашем примере мы будем использовать пользовательскую реализацию перехватчика, чтобы добавить имя зарегистрированного пользователя в параметры модели. В более сложных системах мы можем добавить более конкретную информацию, такую как: путь к аватару пользователя, местоположение пользователя и т. д.
Давайте начнем с определения нашего нового класса Interceptor :
public class UserInterceptor extends HandlerInterceptorAdapter {
private static Logger log = LoggerFactory.getLogger(UserInterceptor.class);
...
}
Мы расширяем HandlerInterceptorAdapter
, так как хотим реализовать только методы preHandle()
и postHandle()
.
Как мы упоминали ранее, мы хотим добавить в модель имя зарегистрированного пользователя. Прежде всего, нам нужно проверить, вошел ли пользователь в систему. Мы можем получить эту информацию, проверив SecurityContextHolder
:
public static boolean isUserLogged() {
try {
return !SecurityContextHolder.getContext().getAuthentication()
.getName().equals("anonymousUser");
} catch (Exception e) {
return false;
}
}
Когда HttpSession
установлен, но никто не вошел в систему, имя пользователя в контексте Spring Security равно анонимному
пользователю . Далее приступаем к реализации preHandle():
3.1. Метод прехендл()
Перед обработкой запроса мы не можем получить доступ к параметрам модели. Чтобы добавить имя пользователя, нам нужно использовать HttpSession
для установки параметров:
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object object) throws Exception {
if (isUserLogged()) {
addToModelUserDetails(request.getSession());
}
return true;
}
Это очень важно, если мы используем часть этой информации перед обработкой запроса. Как видим, мы проверяем, залогинен ли пользователь, а затем добавляем параметры в наш запрос, получая его сессию:
private void addToModelUserDetails(HttpSession session) {
log.info("=============== addToModelUserDetails =========================");
String loggedUsername
= SecurityContextHolder.getContext().getAuthentication().getName();
session.setAttribute("username", loggedUsername);
log.info("user(" + loggedUsername + ") session : " + session);
log.info("=============== addToModelUserDetails =========================");
}
Мы использовали SecurityContextHolder
для получения loggedUsername
. Вы можете переопределить реализацию Spring Security UserDetails
для получения электронной почты вместо стандартного имени пользователя.
3.2. Метод p ostHandle()
После обработки запроса параметры нашей модели становятся доступными, поэтому мы можем получить к ним доступ для изменения значений или добавления новых. Для этого мы используем переопределенный метод postHandle()
:
@Override
public void postHandle(
HttpServletRequest req,
HttpServletResponse res,
Object o,
ModelAndView model) throws Exception {
if (model != null && !isRedirectView(model)) {
if (isUserLogged()) {
addToModelUserDetails(model);
}
}
}
Рассмотрим детали реализации.
Прежде всего, лучше проверить, не является ли модель нулевой.
Это не позволит нам столкнуться с NullPointerException
.
Кроме того, мы можем проверить, не является ли View
экземпляром Redirect View.
Нет необходимости добавлять/изменять параметры после обработки запроса и последующего перенаправления, так как сразу же новый контроллер снова выполнит обработку. Чтобы проверить, перенаправлено ли представление, мы вводим следующий метод:
public static boolean isRedirectView(ModelAndView mv) {
String viewName = mv.getViewName();
if (viewName.startsWith("redirect:/")) {
return true;
}
View view = mv.getView();
return (view != null && view instanceof SmartView
&& ((SmartView) view).isRedirectView());
}
Наконец, мы снова проверяем, зарегистрирован ли пользователь, и если да, мы добавляем параметры в модель Spring:
private void addToModelUserDetails(ModelAndView model) {
log.info("=============== addToModelUserDetails =========================");
String loggedUsername = SecurityContextHolder.getContext()
.getAuthentication().getName();
model.addObject("loggedUsername", loggedUsername);
log.trace("session : " + model.getModel());
log.info("=============== addToModelUserDetails =========================");
}
Обратите внимание, что логирование очень важно, так как эта логика работает «за кулисами» нашего приложения. Легко забыть, что мы изменяем некоторые параметры модели в каждом представлении
, не регистрируя это должным образом.
4. Конфигурация
Чтобы добавить наш недавно созданный Interceptor
в конфигурацию Spring, нам нужно переопределить метод addInterceptors()
внутри класса WebConfig , который реализует
WebMvcConfigurer:
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new UserInterceptor());
}
Мы можем добиться той же конфигурации, отредактировав наш файл конфигурации XML Spring:
<mvc:interceptors>
<bean id="userInterceptor" class="com.foreach.web.interceptor.UserInterceptor"/>
</mvc:interceptors>
С этого момента мы можем получить доступ ко всем параметрам, связанным с пользователем, во всех сгенерированных представлениях.
Обратите внимание: если настроено несколько перехватчиков Spring, метод
preHandle()
выполняется в порядке конфигурации, тогда как методы postHandle()
и afterCompletion()
вызываются в обратном порядке.
5. Вывод
В этом руководстве представлен перехват веб-запросов с использованием Spring MVC HandlerInterceptor для предоставления информации о пользователе.
В этом конкретном примере мы сосредоточились на добавлении сведений о зарегистрированном пользователе в наше веб-приложение к параметрам модели. Вы можете расширить эту реализацию HandlerInterceptor
, добавив более подробную информацию.
Все примеры и конфигурации доступны здесь, на GitHub .
5.1. Статьи в серии
Все статьи цикла:
- Введение в перехватчики Spring MVC Handler
- Изменение параметров модели Spring с помощью Handler Interceptor (этот)