Это сообщение переведено AI.
Выбрать язык
Текст, резюмированный ИИ durumis
- Filter — это стандартный спецификационный функционал J2EE, который обеспечивает возможность обработки дополнительных задач для всех запросов, соответствующих шаблону URL, до и после передачи запроса диспетчеру сервлетов. Он работает в веб-контейнере, в то время как Interceptor — это технология, предоставляемая Spring, которая предоставляет возможность ссылаться на запросы и ответы или обрабатывать их до и после того, как диспетчер сервлетов вызовет контроллер. Он работает в контексте Spring.
- Argument Resolver может косвенно помочь создать нужный объект из полученных значений, когда в контроллер поступает запрос.
- Filter и Interceptor отличаются тем, работают ли они в контейнере Spring или веб-контейнере, обрабатывают ли они запрос на основе диспетчера сервлетов или на основе контроллера. Argument Resolver работает после Interceptor и возвращает определенный объект.
Что такое фильтр (Filter)?
Фильтр — это функция стандартной спецификации J2EE, которая позволяет обрабатывать дополнительные задачи для всех запросов, соответствующих шаблону URL, до и после передачи запроса в диспетчерский сервлет (Dispatcher Servlet). То есть, он управляется веб-контейнером, таким как Tomcat, а не контейнером Spring, поэтому он обрабатывает запросы перед их поступлением в диспетчерский сервлет.
Реализация фильтра (Filter)
Чтобы добавить фильтр, необходимо реализовать интерфейс Filter из javax.servlet, который имеет следующие три метода.
- Метод init
- Этот метод инициализирует объект фильтра и добавляет его в сервис. Веб-контейнер вызывается один раз для инициализации объекта фильтра, после чего все последующие запросы обрабатываются с помощью метода doFilter().
- Метод doFilter
- Этот метод выполняется веб-контейнером перед передачей всех HTTP-запросов, соответствующих шаблону URL, в диспетчерский сервлет, и после того, как диспетчерский сервлет отправляет HTTP-ответ клиенту.
В качестве параметра doFilter() используется FilterChain, который позволяет передавать запрос следующему объекту. Вставляя необходимый код обработки до и после chain.doFilter(), можно выполнять нужные операции.
- Этот метод выполняется веб-контейнером перед передачей всех HTTP-запросов, соответствующих шаблону URL, в диспетчерский сервлет, и после того, как диспетчерский сервлет отправляет HTTP-ответ клиенту.
- Метод destroy
- Этот метод удаляет объект фильтра из сервиса и возвращает используемые ресурсы. Он вызывается веб-контейнером один раз, после чего объект больше не обрабатывается методом doFilter().
Пример кода — спецификация Servlet
@WebFilter("/*")
public class dolphagoFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
//Обработка перед фильтром
request.setCharacterEncoding("UTF-8");
System.out.println("До doFilter()....");
filterChain.doFilter(request, response);
//Обработка после фильтра
System.out.println("После doFilter()....");
}
@Override
public void destroy() { }
Пример кода — @Component
@Order(1)
@Component
public class CustomFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException { }
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
chain.doFilter(request, response);
}
@Override
public void destroy() { }
- @Component: позволяет зарегистрировать фильтр как бийн Spring.
- @Order: позволяет задать порядок фильтров, если их несколько.
- При регистрации фильтра, соответствующего спецификации сервлетов, как бийн Spring, можно использовать другие бины, соответствующие спецификации Spring.
Пример кода — @Configuration
@Configuration
public class CustomRegistrationBean {
@Bean
public FilterRegistrationBean customFilterBean() {
FilterRegistrationBean registration = new FilterRegistrationBean<>();
registration.setFilter(new CustomFilter());
registration.setOrder(1);
registration.addUrlPatterns("/api/*");
return registration;
}
Если необходимо, чтобы фильтр работал только для определенных URI, можно зарегистрировать его как бийн Spring, используя FilterRegistrationBean.
Цели фильтра (Filter)
Он в основном отвечает за проверку и обработку самих параметров запроса.
- Общие задачи, связанные с безопасностью
- Поскольку фильтр работает в веб-контейнере, он может выполнять проверку безопасности (например, защиту от XSS, CSRF), блокируя запросы, которые не являются допустимыми. Это может повысить надежность, так как запрос не будет передан в контейнер Spring.
- Ведение журнала для всех запросов
- Сжатие изображений/данных и кодировка строк
- Фильтр реализует функции, которые широко используются в веб-приложениях, например, сжатие изображений или данных, а также кодировка строк.
- Настройка ServletRequest
- HttpServletRequest может читать содержимое Body только один раз. Поэтому Filter или Interceptor не могут читать Body. Можно создать собственный ServletRequest для записи содержимого Body в журнал.
Перехватчик (Interceptor)
Что такое перехватчик (Interceptor)?
Перехватчик (Interceptor) — это технология, предоставляемая Spring, в отличие от фильтра (Filter), который является стандартной спецификацией J2EE. Она позволяет получить доступ к запросу и ответу перед вызовом контроллера диспетчерским сервлетом, а также обрабатывать их. То есть, в отличие от фильтра, который работает в веб-контейнере, перехватчик работает в контексте Spring.
Диспетчерский сервлет отправляет запрос обработчику сопоставлений для поиска подходящего контроллера, в результате чего возвращается цепочка выполнения (HandlerExecutionChain). Таким образом, если в этой цепочке выполнения зарегистрировано один или несколько перехватчиков, то выполнение будет происходить последовательно через перехватчики, а затем через контроллер. Если перехватчики отсутствуют, контроллер выполняется сразу.
Реализация перехватчика (Interceptor)
Чтобы добавить перехватчик, необходимо реализовать интерфейс org.springframework.web.servlet.HandlerInterceptor, который имеет следующие три метода.
- Метод preHandle
- Метод preHandle выполняется перед вызовом контроллера. Поэтому его можно использовать для выполнения предварительной обработки перед контроллером, например, для обработки информации о запросе или ее дополнения.
- Третий параметр метода preHandle, handler, представляет собой объект, абстрагирующий информацию о методе, к которому привязано @RequestMapping.
- Тип возвращаемого значения метода preHandle — boolean. Если возвращаемое значение равно true, то выполнение переходит к следующему этапу, а если false, то выполнение останавливается, и последующие операции (следующий перехватчик или контроллер) не выполняются.
- Метод postHandle
- Метод postHandle выполняется после вызова контроллера. Его можно использовать для выполнения последующей обработки после контроллера.
- Метод afterCompletion
- Как следует из названия, метод afterCompletion выполняется после завершения всех операций, включая создание конечного результата во всех представлениях.
Пример кода
@Component
public class CustomInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
}
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new CustomInterceptor());
registry.addInterceptor(new LoggingInterceptor());
}
- Созданный перехватчик регистрируется как бийн.
- Созданный перехватчик регистрируется в методе addInterceptors() интерфейса WebMvcConfigurer.
- Перехватчики работают в том порядке, в котором они были зарегистрированы в InterceptorRegistry.
Цели перехватчика (Interceptor)
Он в основном отвечает за обработку согласованности информации о запросе, используя логику сервиса.
- Общие задачи, связанные с аутентификацией/авторизацией
- В качестве типичного примера можно привести проверку, связанную с аутентификацией или авторизацией клиента, перед передачей в контроллер.
- Ведение журнала для вызовов API
- Можно записывать информацию о клиенте, используя объекты HttpServletRequest и HttpServletResponse, которые передаются.
- Обработка данных, передаваемых в контроллер
- Можно обработать объекты HttpServletRequest и HttpServletResponse, которые передаются, и передать их в контроллер.
- Имитация AOP
- Можно получить доступ к информации о сигнатуре выполняемого метода, например, HandlerMethod, передаваемого в качестве третьего параметра метода preHandle(), чтобы определить, следует ли выполнять логику.
Фильтр (Filter) против перехватчика (Interceptor)
- Фильтр выполняется в контексте веб-контекста, а перехватчик — в контексте Spring, поэтому у них разное время выполнения.
- Фильтр может обрабатывать как до, так и после диспетчерского сервлета, а перехватчик — до и после контроллера.
- Фильтр лучше использовать для выполнения задач, которые не зависят от Spring, например, для глобальной обработки, проверки самих параметров, поступающих на вход, или использования ServletRequest вместо HttpServletRequest.
- Перехватчик лучше использовать для выполнения задач, связанных с запросами клиента, которые должны обрабатываться глобально в контексте Spring, или при необходимости использовать логику сервиса.
- Перехватчик позволяет использовать @ControllerAdvice и @ExceptionHandler для обработки исключений, в то время как фильтр не может использовать их для обработки исключений.
- Фильтр обычно обрабатывает исключения, возникшие в этот момент, заключая метод doFilter() в блок try~catch.
Разрешение аргументов
Что такое разрешение аргументов (Argument Resolver)?
Разрешение аргументов (Argument Resolver) — это непрямой способ создания нужного объекта из значения, полученного из запроса при поступлении запроса в контроллер.
Цели разрешения аргументов (Argument Resolver)
Предположим, что вместе с запросом был передан JWT-токен. Нам необходимо проверить, является ли этот токен действительным, а затем извлечь идентификатор, сохраненный в токене, и создать объект зарегистрированного пользователя.
В этом случае, если не использовать разрешение аргументов, то необходимо реализовать процесс проверки токена и преобразования его в объект зарегистрированного пользователя в каждом контроллере. Это приведет к появлению дублирующегося кода в контроллерах, где требуется проверка пользователя, и увеличит ответственность контроллеров. Решение этой проблемы предлагает разрешение аргументов.
Реализация разрешения аргументов (Argument Resolver)
Разрешение аргументов (Argument Resolver) можно использовать, реализовав HandlerMethodArgumentResolver. Этот интерфейс требует реализации двух методов:
boolean supportsParameter(MethodParameter parameter);
@Nullable
- Метод supportsParameter
- Создайте собственную аннотацию и прикрепите ее к параметру, который вы хотите обработать с помощью Argument Resolver. Метод supportsParameter() проверяет, присутствует ли в параметре запрашиваемого метода нужная аннотация, и возвращает true, если она присутствует.
- Метод resolveArgument
- Если в методе supportsParameter возвращается true, то есть, если в каком-либо методе есть аннотация, этот метод преобразует parameter в нужный формат и возвращает информацию.
При использовании Argument Resolver контроллер реализуется следующим образом:
@GetMapping("/me")
public ResponseEntity findMemberOfMine(@AuthenticationPrincipal LoginMember loginMember) {
MemberResponse memberResponse = memberService.findMember(loginMember.getId());
return ResponseEntity.ok().body(memberResponse);
Различия между разрешением аргументов (Argument Resolver) и перехватчиком (Interceptor)
- Разрешение аргументов (Argument Resolver) выполняется после перехватчика, преобразуя полученное из запроса значение в нужный объект.
- Перехватчик, в свою очередь, перехватывает запрос до фактического выполнения контроллера, и не может возвращать определенный объект. Он может возвращать только 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 вместо HttpServletRequest.
В качестве типичных примеров можно привести общие задачи, связанные с безопасностью, ведение журнала для всех запросов, сжатие изображений/данных и кодировку строк, а также настройку ServletRequest.
Что такое перехватчик?
Перехватчик — это функция, которая позволяет получить доступ к запросу и ответу до и после вызова контроллера диспетчерским сервлетом, а также обрабатывать их, работает на уровне контекста Spring.
Когда используются перехватчики?
Перехватчики можно использовать для выполнения задач, связанных с запросами клиента, которые должны обрабатываться глобально в контексте Spring, или при необходимости использовать логику сервиса.
В качестве типичных примеров можно привести общие задачи, связанные с аутентификацией/авторизацией, ведение журнала для вызовов API, обработку данных, передаваемых в контроллер.
В чем разница между фильтром и перехватчиком?
Фильтр работает на уровне сервлетов-контейнера, а перехватчик — на уровне контекста Spring.
Фильтр может обрабатывать как до, так и после диспетчерского сервлета, а перехватчик — до и после контроллера.
Таким образом, фильтр лучше использовать для выполнения задач, которые не зависят от Spring, а перехватчик — для задач, связанных с запросами клиента, которые должны обрабатываться глобально в контексте Spring.
Что такое разрешение аргументов?
Разрешение аргументов — это непрямой способ создания нужного объекта из значения, полученного из запроса при поступлении запроса в контроллер.
Когда используется разрешение аргументов?
Разрешение аргументов можно использовать, например, когда вместе с запросом был передан JWT-токен, и необходимо проверить, является ли этот токен действительным, а затем извлечь идентификатор, сохраненный в токене, и создать объект зарегистрированного пользователя.
В чем разница между перехватчиком и разрешением аргументов?
Разрешение аргументов (Argument Resolver) выполняется после перехватчика, преобразуя полученное из запроса значение в нужный объект. В свою очередь, перехватчик не может возвращать определенный объект, он может возвращать только boolean или void, и выполняется до разрешения аргументов.