Что такое фильтр (Filter)?
Фильтр — это функция, определенная в стандартной спецификации J2EE, которая позволяет обрабатывать дополнительные задачи для всех запросов, соответствующих шаблону URL, до/после передачи запроса в диспетчерский сервлет (Dispatcher Servlet). Другими словами, управление осуществляется не контейнером Spring, а веб-контейнером, таким как Tomcat, поэтому обработка запроса происходит до достижения диспетчерского сервлета.
Реализация фильтра (Filter)
Для добавления фильтра необходимо реализовать интерфейс Filter из javax.servlet, который имеет следующие три метода.
- Метод init
- Это метод для инициализации объекта фильтра и добавления его в сервис. Веб-контейнер вызывает метод init один раз для инициализации объекта фильтра, после чего все последующие запросы обрабатываются с помощью метода doFilter().
- Метод doFilter
- Это метод, который выполняется веб-контейнером перед передачей всех HTTP-запросов, соответствующих url-pattern, в диспетчерский сервлет, и перед отправкой HTTP-ответа клиенту диспетчерским сервлетом.
В качестве параметра doFilter() используется FilterChain, который позволяет передавать запрос следующему объекту назначения через вызов doFilter(). Вставив необходимый процесс обработки до/после chain.doFilter(), мы можем выполнить требуемую обработку.
- Это метод, который выполняется веб-контейнером перед передачей всех HTTP-запросов, соответствующих url-pattern, в диспетчерский сервлет, и перед отправкой HTTP-ответа клиенту диспетчерским сервлетом.
- Метод destroy
- Это метод для удаления объекта фильтра из сервиса и возврата используемых ресурсов. Он вызывается веб-контейнером один раз, после чего он больше не обрабатывается методом doFilter().
Пример кода - Спецификация Servlet
Пример кода - @Component
- @Component: Позволяет зарегистрировать Filter как bean Spring.
- @Order: Позволяет определить порядок, если фильтров несколько.
- Если фильтр, соответствующий спецификации Servlet, зарегистрирован таким образом как bean Spring, то можно использовать другие bean, соответствующие спецификации Spring.
Пример кода - @Configuration
Если вы хотите, чтобы фильтр работал только для определенного URI, вы можете зарегистрировать фильтр как bean Spring с помощью FilterRegistrationBean.
Назначение фильтра (Filter)
В основном отвечает за проверку и обработку самих параметров запроса.
- Общие задачи, связанные с безопасностью
- Поскольку фильтр работает в веб-контейнере, можно выполнять проверку безопасности (защита от XSS, CSRF и т. д.) и блокировать неверные запросы. Блокировка происходит до того, как запрос достигнет контейнера Spring, что повышает надежность.
- Ведение журнала для всех запросов
- Сжатие изображений/данных и кодировка строк
- Фильтр реализует функции, часто используемые в веб-приложениях, такие как сжатие изображений или данных и кодировка строк.
- Настройка ServletRequest
- HttpServletRequest позволяет читать содержимое Body только один раз. Поэтому в Filter или Interceptor нельзя читать Body. Можно создать настраиваемый ServletRequest для ведения журнала Body.
Перехватчик (Interceptor)
Что такое перехватчик (Interceptor)?
В отличие от фильтра (Filter), который является стандартной спецификацией J2EE, перехватчик (Interceptor) — это технология, предоставляемая Spring, которая позволяет ссылаться на запрос и ответ до и после вызова диспетчерским сервлетом контроллера или обрабатывать их. Иными словами, в отличие от фильтра, который работает в веб-контейнере, перехватчик работает в контексте Spring.
Диспетчерский сервлет отправляет запрос на поиск соответствующего контроллера с помощью сопоставления обработчиков, в результате чего возвращается цепочка выполнения (HandlerExecutionChain). Таким образом, если в этой цепочке выполнения зарегистрирован один или несколько перехватчиков, они выполняются последовательно перед выполнением контроллера. Если перехватчиков нет, контроллер выполняется сразу.
Реализация перехватчика (Interceptor)
Для добавления перехватчика необходимо реализовать интерфейс org.springframework.web.servlet.HandlerInterceptor, который имеет следующие три метода.
- Метод preHandle
- Метод preHandle выполняется перед вызовом контроллера. Поэтому его можно использовать для выполнения предварительной обработки, обработки информации о запросе или добавления информации перед контроллером.
- Третий параметр метода preHandle, параметр handler, представляет собой абстрактный объект, содержащий информацию о методе, к которому прикреплено @RequestMapping.
- Тип возвращаемого значения метода preHandle — boolean. Если возвращаемое значение равно true, выполнение продолжается, в противном случае выполнение прерывается, и последующие действия (следующий перехватчик или контроллер) не выполняются.
- Метод postHandle
- Метод postHandle выполняется после вызова контроллера. Поэтому его можно использовать, если необходимо выполнить последующую обработку после контроллера.
- Метод afterCompletion
- Метод afterCompletion выполняется после завершения всех операций, включая генерацию окончательного результата во всех представлениях.
Пример кода
- Созданный перехватчик регистрируется как bean.
- Созданный перехватчик регистрируется в методе addInterceptors() интерфейса WebMvcConfigurer.
- Перехватчики работают в порядке регистрации в InterceptorRegistry.
Назначение перехватчика (Interceptor)
В основном отвечает за обработку согласованности информации о запросе с использованием бизнес-логики.
- Общие задачи, связанные с аутентификацией/авторизацией
- Например, перед переходом к контроллеру можно проверить такие задачи, как аутентификация или авторизация, связанные с запросом клиента.
- Ведение журнала вызовов API
- С помощью получаемых объектов HttpServletRequest и HttpServletResponse можно записывать информацию о клиенте.
- Обработка данных, передаваемых в контроллер
- Полученные объекты HttpServletRequest и HttpServletResponse можно обработать и передать в контроллер.
- Имитация AOP
- Третий параметр метода preHandle, HandlerMethod, позволяет получить дополнительную информацию, такую как сигнатура выполняемого метода, и на основе этого определить, выполнять ли логику.
Фильтр (Filter) против перехватчика (Interceptor)
- Фильтр выполняется в веб-контексте, а перехватчик — в контексте Spring, поэтому время выполнения различается.
- Фильтр может обрабатывать действия до и после диспетчерского сервлета, а перехватчик — до и после контроллера.
- Фильтр лучше использовать для задач, которые необходимо обрабатывать глобально независимо от Spring, для проверки самих входных параметров или в случае, когда вместо HttpServletRequest используется ServletRequest.
- Перехватчик лучше использовать для глобальных задач, связанных с запросом клиента, поступающим в рамках Spring, или когда необходимо использовать бизнес-логику.
- В перехватчике можно использовать @ControllerAdvice и @ExceptionHandler для обработки исключений, а в фильтре — нет.
- Фильтр обычно обрабатывает исключения, возникающие в этот момент, путем помещения блока doFilter() в блок try~catch.
Разрешитель аргументов (Argument Resolver)
Что такое разрешитель аргументов (Argument Resolver)?
Разрешитель аргументов (Argument Resolver) может косвенно создавать нужный объект из значения, полученного при поступлении запроса в контроллер.
Назначение разрешителя аргументов (Argument Resolver)
Например, предположим, что запрос поступил вместе с токеном JWT. Нам нужно проверить, является ли этот токен действительным, а затем извлечь идентификатор, сохраненный в токене, и создать объект пользователя, который вошел в систему.
В этом случае, если не использовать Argument Resolver, необходимо реализовать процесс проверки токена и преобразования его в объект пользователя, вошедшего в систему, в каждом контроллере. Это приведет к появлению дублирующегося кода в контроллерах, в которых требуется проверка пользователя, и к увеличению ответственности контроллеров. Argument Resolver может решить эту проблему.
Реализация разрешителя аргументов (Argument Resolver)
ArgumentResolver можно использовать путем реализации HandlerMethodArgumentResolver. Этот интерфейс указывает на необходимость реализации двух следующих методов.
- Метод supportsParameter
- Создаем и прикрепляем определенную аннотацию перед параметром, для которого хотим выполнить ArgumentResolver. Метод supportsParameter() проверяет, прикреплена ли нужная аннотация к полученному методу, и если она присутствует, возвращает true.
- Метод resolveArgument
- Если в supportsParameter получено true, то есть если существует какой-либо метод с прикрепленной определенной аннотацией, этот метод связывает parameter с нужным форматом и возвращает его.
При использовании ArgumentResolver реализация контроллера будет выглядеть следующим образом.
Различия между разрешителем аргументов (Argument Resolver) и перехватчиком (Interceptor)
- ArgumentResolver работает после перехватчика и возвращает нужный объект из значения, полученного при поступлении запроса в контроллер.
- Перехватчик, наоборот, перехватывает запрос до фактического запуска контроллера и не может возвращать определенный объект. Существуют только типы возвращаемых значений boolean или void.
Источники
- https://mangkyu.tistory.com/173
- https://junhyunny.github.io/spring-boot/filter-interceptor-and-aop/
- https://supawer0728.github.io/2018/04/04/spring-filter-interceptor/
- https://tecoble.techcourse.co.kr/post/2021-05-24-spring-interceptor/
- https://baeldung-cn.com/spring-mvc-handlerinterceptor-vs-filter
- https://www.baeldung.com/spring-boot-add-filter
Ожидаемые вопросы на собеседовании и ответы
Что такое фильтр?
Фильтр — это функция, которая позволяет обрабатывать дополнительные задачи для всех запросов, соответствующих шаблону URL, до/после передачи запроса в диспетчерский сервлет, и работает на уровне контейнера сервлетов.
Когда следует использовать фильтр?
В фильтре можно обрабатывать задачи, которые необходимо выполнять глобально независимо от Spring. Или когда требуется проверка параметров запроса.
В основном он обрабатывает общие задачи, связанные с безопасностью, ведение журнала для всех запросов, сжатие изображений/данных и кодировку строк, настройку ServletRequest.
Что такое перехватчик?
Перехватчик — это функция, которая позволяет ссылаться на запрос и ответ до и после вызова диспетчерским сервлетом контроллера или обрабатывать их, и работает на уровне контейнера Spring.
Когда следует использовать перехватчик?
Перехватчик можно использовать для обработки задач, которые необходимо выполнять глобально, связанных с запросом клиента. Или когда требуется проверка, включающая вызов бизнес-логики.
В основном он обрабатывает общие задачи, связанные с аутентификацией/авторизацией, ведение журнала вызовов API, обработку данных, передаваемых в контроллер.
В чем разница между фильтром и перехватчиком?
Фильтр выполняется на уровне контейнера сервлетов, а перехватчик — на уровне контейнера Spring.
Фильтр может обрабатывать действия до и после диспетчерского сервлета, а перехватчик — до и после контроллера.
Поэтому фильтр лучше использовать для задач, которые необходимо выполнять глобально независимо от Spring, а перехватчик — для задач, связанных с запросом клиента, которые необходимо выполнять глобально.
Что такое разрешитель аргументов?
Разрешитель аргументов — это функция, которая косвенно создает нужный объект из значения, полученного при поступлении запроса в контроллер.
Когда следует использовать разрешитель аргументов?
Его можно использовать, когда запрос поступает вместе с токеном JWT, для проверки того, является ли этот токен действительным, а затем извлечения идентификатора, сохраненного в токене, и создания объекта LoginMember.
В чем разница между перехватчиком и разрешителем аргументов?
Разрешитель аргументов возвращает нужный объект из значения, полученного при поступлении запроса в контроллер. Перехватчик не может возвращать объекты, и он выполняется перед разрешителем аргументов.
Комментарии0