29.В чем разница между Filters, Listeners и Interceptors?

29.В чем разница между Filters, Listeners и Interceptors?

UNKNOWN

Filter

Это  интерфейс  из  пакета  javax.servlet,  имплементации  которого  выполняют  задачи фильтрации либо по пути запроса к ресурсу (сервлету, либо по статическому контенту), либо по пути ответа от ресурса, либо в обоих направлениях.

Фильтры  выполняют  фильтрацию  в  методе  doFilter.  Каждый  фильтр  имеет  доступ  к объекту FilterConfig, из которого он может получить параметры инициализации, и ссылку на ServletContext, который он может использовать, например, для загрузки ресурсов, необходимых для задач фильтрации. Фильтры настраиваются в дескрипторе развертывания веб-приложения.

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

Когда  вызывается  метод  doFilter(ServletRequest  request,  ServletResponse  response, FilterChain  chain)  первого  фильтра,  веб-сервер  создает  объект  FilterChain,  представляющий цепочку фильтров, и передаёт её в метод.

Interceptor

Это  интерфейс  из  пакета  org.aopalliance.intercept,  предназначенный  для  аспектно-ориентированного программирования.

В Spring, когда запрос отправляется в Controller, перед тем как он в него попадёт, он может пройти через перехватчики  Interceptor (0 или более). Это одна из реализаций АОП в Spring.  Вы  можете  использовать    Interceptor  для  выполнения  таких  задач,  как  запись  в  Log, добавление или обновление конфигурации перед тем, как запрос обработается Controller-ом.

Стек  перехватчиков:  он  предназначен  для  связывания  перехватчиков  в  цепочку  в определенном порядке. При доступе к перехваченному методу или полю перехватчик в цепочке перехватчиков вызывается в том порядке, в котором он был определен.


Мы  можем  использовать    Interceptor-ы  для  выполнения  логики  до  попадания  в контроллер,  после  обработки  в  контроллере,  а  также  после  формирования  представления.

Также  можем  запретить  выполнение  метода  контроллера.  Мы  можем  указать  любое количество перехватчиков.

Перехватчики работают с HandlerMapping и поэтому должны реализовывать интерфейс HandlerInterceptor или наследоваться от готового класса  HandlerInterceptorAdapter. В случае реализации  HandlerInterceptor  нам  нужно  переопределить  3  метода,  а  в  случае HandlerInterceptor, только необходимые нам:

  • public  boolean  preHandle(HttpServletRequest  request,  HttpServletResponse  response, Object  handler)  -  вызывается  после  того,  как  HandlerMapping  определил соответствующий  контроллер,  но  до  того,  как  HandlerAdapter  вызовет  метод контроллера. С помощью этого метода каждый перехватчик может решить, прервать цепочку  выполнения  или  направить  запрос  на  испольнение  дальше  по  цепочке перехватчиков  до  метода  контроллера.  Если  этот  метод  возвращает  true,  то  запрос отправляется следующему перехватчику или в контроллер. Если метод возвращает false,то исполнение запроса прекращается, обычно отправляя ошибку HTTP или записываясобственный ответ в response.
  • public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,  ModelAndView  modelAndView)  -  отработает  после  контроллера,  но  перед формированием представления. Мы можем использовать этот метод для добавления дополнительных  атрибутов  в  ModelAndView  или  для  определения  времени, затрачиваемого  методом-обработчиком  на  обработку  запроса  клиента.  Вы  можете добавить  больше  объектов  модели  в  представление,  но  вы  не  можете  изменить HttpServletResponse, так как он уже зафиксирован.
  • public  void  afterCompletion(HttpServletRequest  request,  HttpServletResponse  response, Object  handler,  Exception  ex)  -  отработает  после  формирования  представления.Вызывается  только  в  том  случае,  если  метод  preHandle  этого  перехватчика  успешно завершен и вернул true!

Следует знать, что HandlerInterceptor связан с бином DefaultAnnotationHandlerMapping, который отвечает за применение перехватчиков к любому классу, помеченному аннотацией @Controller.

Чтобы добавить наши перехватчики в конфигурацию Spring, нам нужно переопределить метод addInterceptors () внутри класса, который реализует WebMvcConfigurer:

@Override

public void addInterceptors(InterceptorRegistry registry) {

    // LogInterceptor applies to all URLs.

    registry.addInterceptor(new LogInterceptor());

    // This interceptor applies to URL /admin/oldLogin.

    // Using OldURLInterceptor to redirect to new URL.

    registry.addInterceptor(new OldLoginInterceptor())

        .addPathPatterns(\"/admin/oldLogin\");

    // This interceptor applies to URLs like /admin/*

    // Exclude /admin/oldLogin

    registry.addInterceptor(new AdminInterceptor())

        .addPathPatterns(\"/admin/*\")//

        .excludePathPatterns(\"/admin/oldLogin\");

}

Filter vs. Interceptor

  • Перехватчик основан на механизме Reflection, а фильтр основан на обратном вызове функции.
  • Фильтр зависит от контейнера сервлета, тогда как перехватчик не зависит от него.
  • Перехватчики  могут  работать  только  с  запросами  к  контроллерам,  в  то  время  как фильтры могут работать почти со всеми запросами (например, js, .css и т.д.).
  • Перехватчики в отличии от фильтров могут обращаться к объектам в контейнере Spring, что даёт им более изощренный функционал.

Порядок работы:

  1. Фильтры до;
  2. Перехватчики до;
  3. Метод контроллера;
  4. Перехватчики после;
  5. Фильтры после.

HandlerInterceptor в основном похож на Servlet Filter, но в отличие от последнего он просто  позволяет  настраивать  предварительную  обработку  с  возможностью  запретить выполнение самого обработчика и настраивать постобработку.

Согласно  документации  Spring,  фильтры  более  мощные,  например,  они  позволяют обмениваться объектами запроса и ответа, которые передаются по цепочке. Это означает, что фильтры  работают  больше  в  области  запроса/ответа,  в  то  время  как  HandlerInterceptors являются  бинами  и  могут  обращаться  к  другим  компонентам  в  приложении.  Обратите внимание, что фильтр настраивается в web.xml, а HandlerInterceptor в контексте приложения.

Java Listener

Listener  (Слушатель)  -  это  класс,  который  реализует  интерфейс javax.servlet.ServletContextListener.  Он  инициализируется  только  один  раз  при  запуске  веб-приложения и уничтожается при остановке веб-приложения. Слушатель сидит и ждет, когда произойдет  указанное  событие,  затем  «перехватывает»  событие  и  запускает  собственное событие. Например, мы хотим инициализировать пул соединений с базой данных до запуска веб-приложения. ServletContextListener - это то, что нам нужно, он будет запускать наш код до запуска веб-приложения.

Все  ServletContextListeners  уведомляются  об  инициализации  контекста  до инициализации любых фильтров или сервлетов в веб-приложении.

Все ServletContextListeners уведомляются об уничтожении контекста после того, как все сервлеты и фильтры уничтожены.

Чтобы  создать  свой  Listener  нам  достаточно  создать  класс,  имплементирующий интерфейс ServletContextListener и поставить над ним аннотацию @WebListener:

@WebListener

public class MyAppServletContextListener

               implements ServletContextListener{

      //Run this before web application is started

  @Override

  public void contextInitialized(ServletContextEvent arg0) {

    System.out.println(\"ServletContextListener started\");

  }

  @Override

  public void contextDestroyed(ServletContextEvent arg0) {

    System.out.println(\"ServletContextListener destroyed\");

  }

}


Предыдущий вопрос: 28. Расскажите про аннотации @Controller и @RestController. Чем они отличаются? Как вернуть ответ со своим статусом (например 213)?

Следующий вопрос: 30. Можно ли передать в GET-запросе один и тот же параметр несколько раз? Как?

Все вопросы по теме: список

Все темы: список

Вопросы/замечания/предложения/нашли ошибку: напишите мне

Report Page