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

OSCHINA-MIRROR/GiteeOS-springboot-guide

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

1. Введение в фильтры

Фильтры, вероятно, знакомы многим, особенно тем, кто начинал изучать Java-серверную часть с Servlet. Но что же можно сделать с помощью фильтров? Фильтры主要用于过滤用户请求,允许我们在请求到达目标资源之前或之后进行预处理和后处理。例如,可以实现基于 URL 的权限控制、过滤非法请求等。Фильтры являются конкретной реализацией программирования с использованием аспектов (AOP), которое представляет собой определенный подход к программированию.

Кроме того, фильтры зависят от контейнера Servlet, интерфейс Filter находится в пакете Servlet и является частью спецификации Servlet. Поэтому часто его называют "усовершенствованным Servlet".

Если вам нужно создать собственный фильтр, это очень просто: вам нужно реализовать интерфейс javax.servlet.Filter и переопределить три метода внутри него!

Filter.java

public interface Filter {
  
   // Операции, выполняемые после инициализации фильтра
    default void init(FilterConfig filterConfig) throws ServletException {
    }
   // Фильтрация запроса
    void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
   // Операции, выполняемые после завершения работы фильтра, обычно используются для освобождения ресурсов
    default void destroy() {
    }
}

2. Как фильтры реализуют перехват запросов?

В интерфейсе Filter есть метод doFilter, который реализует фильтрацию запросов. Вот основные шаги:1. Пользователь отправляет запрос на веб-сервер, запрос сначала попадает в фильтр; 2. Фильтр обрабатывает запрос, например, фильтрует параметры запроса, изменяет содержимое ответа, которое возвращается клиенту, проверяет, имеет ли пользователь доступ к определенному ресурсу и т.д. 3. Ответ на запрос пользователя завершается. 4. Выполняются дополнительные операции, которые вы хотите выполнить.

3. Как создать собственный фильтр

Вот два способа.

3.1 Ручная регистрация и конфигурация

Собственные фильтры должны реализовать интерфейс javax.servlet.Filter и переопределить три метода, определенные в интерфейсе.

MyFilter.java

/**
 * @author shuang.kou
 */
@Component
public class MyFilter implements Filter {
    private static final Logger logger = LoggerFactory.getLogger(MyFilter.class);

    @Override
    public void init(FilterConfig filterConfig) {
        logger.info("Инициализация фильтра: {}", filterConfig.getFilterName());
    }

3.1 Реализация фильтра через конфигурацию

В конфигурации регистрируем собственный фильтр.

@Configuration
public class MyFilterConfig {
    @Autowired
    MyFilter myFilter;
    @Bean
    public FilterRegistrationBean<MyFilter> thirdFilter() {
        FilterRegistrationBean<MyFilter> filterRegistrationBean = new FilterRegistrationBean<>();

        filterRegistrationBean.setFilter(myFilter);

        filterRegistrationBean.setUrlPatterns(new ArrayList<>(Arrays.asList("/api/*")));

        return filterRegistrationBean;
    }
}

3.2 Реализация фильтра через аннотацииДобавляем аннотацию @WebFilter к собственному фильтру и конфигурируем его через параметры этой аннотации.

@WebFilter(filterName = "MyFilterWithAnnotation", urlPatterns = "/api/*")
public class MyFilterWithAnnotation implements Filter {

   ......
}

Для того чтобы Spring мог найти этот фильтр, необходимо добавить аннотацию @ServletComponentScan к стартовому классу.

Метод 4: Определение нескольких фильтров и их последовательности выполнения

Что если мы добавим еще один фильтр?

MyFilter2.java

@Component
public class MyFilter2 implements Filter {
    private static final Logger logger = LoggerFactory.getLogger(MyFilter2.class);

    @Override
    public void init(FilterConfig filterConfig) {
        logger.info("Инициализация фильтра 2");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // Предварительная обработка запроса
        logger.info("Фильтр начал предварительную обработку запроса 2:");
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String requestUri = request.getRequestURI();
        System.out.println("Запрошенный интерфейс 2: " + requestUri);
        long startTime = System.currentTimeMillis();
        // Реализация функции фильтрации через метод doFilter
        filterChain.doFilter(servletRequest, servletResponse);
        // После выполнения метода doFilter запрос пользователя уже возвращен
        long endTime = System.currentTimeMillis();
        System.out.println("Запрос пользователя обработан, затраченное время 2: " + (endTime - startTime));
    }

    @Override
    public void destroy() {
        logger.info("Уничтожение фильтра 2");
    }
}

Регистрация пользовательского фильтра в конфигурации, используя метод setOrder класса FilterRegistrationBean для определения порядка выполнения фильтра.

@Configuration
public class MyFilterConfig {
    @Autowired
    MyFilter myFilter;

    @Autowired
    MyFilter2 myFilter2;

    @Bean
    public FilterRegistrationBean<MyFilter> setUpMyFilter() {
        FilterRegistrationBean<MyFilter> filterRegistrationBean = new FilterRegistrationBean<>();
        filterRegistrationBean.setOrder(2);
        filterRegistrationBean.setFilter(myFilter);
        filterRegistrationBean.setUrlPatterns(new ArrayList<>(Arrays.asList("/api/*")));

        return filterRegistrationBean;
    }

    @Bean
    public FilterRegistrationBean<MyFilter2> setUpMyFilter2() {
        FilterRegistrationBean<MyFilter2> filterRegistrationBean = new FilterRegistrationBean<>();
        filterRegistrationBean.setOrder(1);
        filterRegistrationBean.setFilter(myFilter2);
        filterRegistrationBean.setUrlPatterns(new ArrayList<>(Arrays.asList("/api/*")));
        return filterRegistrationBean;
    }
}

Создание пользовательского контроллера для проверки фильтра

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api")
public class MyController {

    @GetMapping("/hello")
    public String getHello() throws InterruptedException {
        Thread.sleep(1000);
        return "Hello";
    }
}

Результаты тестирования:

2019-10-22 22:32:15.569  INFO 1771 --- [           main] g.j.springbootfilter.filter.MyFilter2    : Инициализация фильтра 2
2019-10-22 22:32:15.569  INFO 1771 --- [           main] g.j.springbootfilter.filter.MyFilter     : Инициализация фильтра
2019-10-22 22:32:55.199  INFO 1771 --- [nio-8080-exec-1] g.j.springbootfilter.filter.MyFilter2    : Фильтр начал предварительную обработку запроса 2:
Интерфейс запроса 2: /api/hello
2019-10-22 22:32:55.199  INFO 1771 --- [nio-8080-exec-1] g.j.springbootfilter.filter.MyFilter     : Фильтр начал предварительную обработку запроса:
Интерфейс запроса: /api/hello
Запрос пользователя обработан, затраченное время: 1037 мс
Запрос пользователя обработан, затраченное время 2: 1037 мс
```Код доступен по адресу: 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