Перейти к основному содержимому

Изменение параметров модели Spring с помощью Handler Interceptor

· 5 мин. чтения

Задача: Сумма двух чисел

Напишите функцию twoSum. Которая получает массив целых чисел nums и целую сумму target, а возвращает индексы двух чисел, сумма которых равна target. Любой набор входных данных имеет ровно одно решение, и вы не можете использовать один и тот же элемент дважды. Ответ можно возвращать в любом порядке...

ANDROMEDA

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. Статьи в серии

Все статьи цикла: