Данная статья является переводом и адаптацией отличной статьи с английского языка: https://o7planning.org/en/11689/spring-boot-interceptors-tutorial.
Interceptor и Filter являются конкретными реализациями программирования с использованием аспектов (AOP), которое представляет собой одну из концепций программирования.
Вы можете использовать Interceptor для выполнения определенных задач, таких как запись логов перед обработкой запроса контроллером, добавление или обновление конфигураций...
В Spring при отправке запроса к Controller, он должен пройти через Interceptor (0 или более) перед тем, как будет обработан контроллером.
Spring Interceptor представляет собой концепцию, очень похожую на Servlet Filter.
Что касается различий между фильтрами и интерцепторами, ответ @Kangol LI на Zhihu очень полезен.
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
}
Обратите внимание: метод **preHandle** возвращает **true** или **false**. Если возвращается **true**, это означает, что запрос продолжит свое выполнение и достигнет **Controller** для обработки.
Каждый запрос может проходить через множество интерцепторов. Ниже приведена схема, иллюстрирующая это.

**`LogInterceptor` используется для фильтрации всех запросов**
```java
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
public class LogInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
long startTime = System.currentTimeMillis();
System.out.println("\n-------- LogInterception.preHandle --- ");
System.out.println("Request URL: " + request.getRequestURL());
System.out.println("Start Time: " + System.currentTimeMillis());
request.setAttribute("startTime", startTime);
}
``````java
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, //
Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("\n-------- LogInterception.postHandle --- ");
System.out.println("Request URL: " + request.getRequestURL());
// Вы можете добавить атрибуты в modelAndView
// и использовать их на странице представления
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, //
Object handler, Exception ex) throws Exception {
System.out.println("\n-------- LogInterception.afterCompletion --- ");
long startTime = (Long) request.getAttribute("startTime");
long endTime = System.currentTimeMillis();
System.out.println("Request URL: " + request.getRequestURL());
System.out.println("End Time: " + endTime);
System.out.println("Time Taken: " + (endTime - startTime));
}
}
СтарыйЛогинИнтерцептор
— это интерцептор, который перенаправляет пользователя на новый URL /admin/login
, если он пытается использовать устаревший URL /admin/oldLogin
.```java
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
public class OldLoginInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("\n-------- OldLoginInterceptor.preHandle --- ");
System.out.println("Request URL: " + request.getRequestURL());
System.out.println("Извините! Этот URL больше не используется, перенаправление на /admin/login");
response.sendRedirect(request.getContextPath() + "/admin/login");
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, //
Object handler, ModelAndView modelAndView) throws Exception {
// Этот код никогда не будет выполнен.
System.out.println("\n-------- OldLoginInterceptor.postHandle --- ");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, //
Object handler, Exception ex) throws Exception {
// Этот код никогда не будет выполнен.
System.out.println("\n-------- QueryStringInterceptor.afterCompletion --- ");
}
}
```


**`AdminInterceptor`**```java
пакет org.o7planning.sbinterceptor.interceptor;
импортировать javax.servlet.http.HttpServletRequest;
импортировать javax.servlet.http.HttpServletResponse;
импортировать org.springframework.web.servlet.ModelAndView;
импортировать org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
общедоступный класс AdminInterceptor расширяет HandlerInterceptorAdapter {
@Переопределять
публичный boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("\n-------- AdminInterceptor.preHandle --- ");
вернуть true;
}
@Переопределять
публичный void postHandle(HttpServletRequest request, HttpServletResponse response, //
Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("\n-------- AdminInterceptor.postHandle --- ");
}
@Переопределять
публичный void afterCompletion(HttpServletRequest request, HttpServletResponse response, //
Object handler, Exception ex) throws Exception {
System.out.println("\n-------- AdminInterceptor.afterCompletion --- ");
}
}
```**Настройка перехватчиков**
``````java
import github.javaguide.springbootfilter.interceptor.AdminInterceptor;
import github.javaguide.springbootfilter.interceptor.LogInterceptor;
import github.javaguide.springbootfilter.interceptor.OldLoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// LogInterceptor применим ко всем URL.
registry.addInterceptor(new LogInterceptor());
// URL старого входа, больше не используется.
// Используется OldURLInterceptor для перенаправления на новый URL.
registry.addInterceptor(new OldLoginInterceptor())//
.addPathPatterns("/admin/oldLogin");
// Этот перехватчик применим к URL вида /admin/*
// Исключает /admin/oldLogin
registry.addInterceptor(new AdminInterceptor())//
.addPathPatterns("/admin/*")//
.excludePathPatterns("/admin/oldLogin");
}
}
```
**Пользовательский перехватчик проверки контроллера**
```java
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class InterceptorTestController {
@RequestMapping(value = { "/", "/test" })
public String test(Model model) {
System.out.println("\n-------- MainController.test --- ");
System.out.println(" ** Вы в контроллере ** ");
return "test";
}
// Этот путь больше не используется.
// Он будет перенаправлен с помощью OldLoginInterceptor
@Deprecated
@RequestMapping(value = { "/admin/oldLogin" })
public String oldLogin(Model model) {
// Код здесь никогда не выполняется.
return "oldLogin";
}
}
``````markdown
## 3. Контроллер MainController
```java
@RequestMapping(value = { "/admin/login" })
public String login(Model model) {
System.out.println("\n-------- MainController.login --- ");
System.out.println(" ** Вы в контроллере ** ");
return "login";
}
}
```
**Шаблонизатор Thymeleaf**
`test.html`
```html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title>Пример использования Spring Boot Mvc Interceptor</title>
</head>
<body>
<div style="border: 1px solid #ccc;padding: 5px;margin-bottom:10px;">
<a th:href="@{/}">Главная</a>
|
<a th:href="@{/admin/oldLogin}">/admin/oldLogin (старый URL)</a>
</div>
<h3>Spring Boot Mvc Interceptor</h3>
<span style="color:blue;">Тестирование LogInterceptor</span>
<br/><br/>
Увидеть лог в консоли..
</body>
</html>
```
`login.html`
```html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title>Пример использования Spring Boot Mvc Interceptor</title>
</head>
<body>
<div style="border: 1px solid #ccc;padding: 5px;margin-bottom:10px;">
<a th:href="@{/}">Главная</a>
|
<a th:href="@{/admin/oldLogin}">/admin/oldLogin (старый URL)</a>
</div>
<h3>Это страница входа</h3>
<span style="color:blue">Тестирование OldLoginInterceptor & AdminInterceptor</span>
<br/><br/>
Дополнительная информация в консоли.
</body>
</html>
```
### 4. Запуск программы и тестирование
При запуске программы и тестировании, когда пользователь посещает http://localhost:8080/, **LogInterceptor** фиксирует информацию (адрес страницы, время посещения) и вычисляет время обработки запроса **веб-сервером**. Кроме того, страница отображается как `test.html`.
```Когда пользователь посещает http://localhost:8080/admin/oldLogin, старую страницу входа (не используется), **OldLoginInterceptor** перенаправляет запрос на http://localhost:8080/admin/login, и страница отображается как нормальная страница входа `login.html`.
**Обратите внимание на информацию, отображаемую в консоли.**
### 5. Заключение
Вначале были рассмотрены некоторые концепции Interceptor, а затем был пройден процесс реализации пользовательского Interceptor с помощью простого примера.
Задачи:
1. Анализ порядка выполнения Filter и Interceptor;
2. Реализация слушателя в Spring Boot;
3. Сравнение и анализ Filter, Interceptor и Listener;
Код доступен по адресу: https://github.com/Snailclimb/springboot-guide/tree/master/source-code/basis/springboot-filter-interceptor
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )