1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/GiteeOS-springboot-guide

Клонировать/Скачать
springboot-interceptor.md 15 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 04.06.2025 10:20 f496caa

Данная статья является переводом и адаптацией отличной статьи с английского языка: https://o7planning.org/en/11689/spring-boot-interceptors-tutorial.

1. Введение в Interceptor

Interceptor и Filter являются конкретными реализациями программирования с использованием аспектов (AOP), которое представляет собой одну из концепций программирования.

Вы можете использовать Interceptor для выполнения определенных задач, таких как запись логов перед обработкой запроса контроллером, добавление или обновление конфигураций...

В Spring при отправке запроса к Controller, он должен пройти через Interceptor (0 или более) перед тем, как будет обработан контроллером.

Spring Interceptor представляет собой концепцию, очень похожую на Servlet Filter.

2. Различия между фильтрами и интерцепторами

Что касается различий между фильтрами и интерцепторами, ответ @Kangol LI на Zhihu очень полезен.

  • Фильтр (Filter): Когда у вас есть множество элементов, вы хотите выбрать только те, которые соответствуют вашим требованиям. Инструмент, который определяет эти требования, называется фильтром.
  • Интерцептор (Interceptor): Когда процесс уже идет, вы хотите вмешаться в его ход, даже остановить его, это то, что делает интерцептор.

3. Создание пользовательского InterceptorЕсли вам нужно создать пользовательский Interceptor, вам необходимо реализовать интерфейс org.springframework.web.servlet.HandlerInterceptor или наследовать класс org.springframework.web.servlet.handler.HandlerInterceptorAdapter и переопределить следующие три метода:```java

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** для обработки.

![Схема работы Interceptor](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/interceptor-spring.png)Каждый запрос может проходить через множество интерцепторов. Ниже приведена схема, иллюстрирующая это.

![Каждый запрос может проходить через множество интерцепторов](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/interceptor-spring.png)

**`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 --- ");
    }

}
```

![](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2bk/2019-7/OldLoginInterceptor.png)

![](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2bk/2019-7/OldLoginInterceptor2.png)

**`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>
         &nbsp;&nbsp; | &nbsp;&nbsp;
         <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>
         &nbsp;&nbsp; | &nbsp;&nbsp;
         <a th:href="@{/admin/oldLogin}">/admin/oldLogin (старый URL)</a>  
      </div>
       
      <h3>Это страница входа</h3>
       
      <span style="color:blue">Тестирование OldLoginInterceptor &amp; 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 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/GiteeOS-springboot-guide.git
git@api.gitlife.ru:oschina-mirror/GiteeOS-springboot-guide.git
oschina-mirror
GiteeOS-springboot-guide
GiteeOS-springboot-guide
master