Въведение във филтрите

Но това не е всичко. Наистина не мислите, че сервлетите са толкова прости, нали?

В допълнение към сървлетите, които вече анализирахме, има и така наречените „полезни сървлети“ - филтри . Те са много подобни на сървлетите, но основната им задача е да помагат на сървлетите да обработват заявки.

Филтърът е като секретар, а сервлетът е като директор. Преди documentът да стигне до бюрото на директора, той ще премине през ръцете на секретаря. И след като директорът го подпише, той пак ще отиде при секретарката, вече като изходяща кореспонденция, например.

Такъв секретар може да отхвърли някои от заявките към директора (например спам). Или дайте стандартни отговори на познати му въпроси („директорът не е на мястото си“). И така нататък. Освен това може да има няколко такива секретари: единият може да филтрира спам за всички директори наведнъж, другият може да прехвърля заявки между различни директори и други подобни.

Филтрите работят по същия начин.

помощни сървлети”

Класове Filter, FilterChain, FilterConfig

Филтрите са много подобни на сървлетите, но с няколко малки разлики. За да напишете свой собствен филтър, трябва да наследите от javax.servlet.Filter.

Филтърът също има методи init()и destroy(). Вместо метод, service()филтърът има doFilter(). И дори има свой собствен клас FilterConfig. Филтърът също се добавя към сървлета във file web.xml or чрез анотацията @WebFilter.

Списък с методи:

Методи Описание
1 init(FilterConfig config) инициализация на филтъра
2 destroy() разтоварване на филтъра
3 doFilter(ServletRequest , ServletResponse, FilterChain) обработка на заявка (филтриране)

Каква е разликата между сървлет и филтър?

Може да има няколко филтъра и те последователно обработват заявката (и отговора). Те са обединени в така наречената верига - и дори има специален клас за тях FilterChain.

След като обработите заявката в метода, doFilter()трябва да извикате метода doFilter()на следващия филтър във веригата. Пример:

public class MyFilter implements Filter {

  public void init(FilterConfig arg0) throws ServletException {
  }

  public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws Exception {

      PrintWriter out = resp.getWriter();
      out.print("Adding something before the body of the response");

      chain.doFilter(req, resp); // call the next filter in the chain

      out.print("Adding something after the body of the response");
    }

  public void destroy() {
  }
}

Всъщност не можете да добавите тялото на отговора по този начин . Формално филтрите и сървлетите са независими един от друг и могат да се променят независимо. Те могат да бъдат написани от различни разработчици по различно време. Филтърната функция е просто сервизна функция, например:

  • Регистриране на всички входящи заявки (и отговори)
  • Компресиране на данни
  • Криптиране (и декриптиране) на данни
  • Заявка за валидиране на данни
  • Добавяне/премахване на желани заглавки
  • Заявки за пренасочване
  • Контрол на достъпа (проверка дали потребителят е влязъл)

Клас RequestDispatcher

doFilter() Понякога може да е необходимо да се извика друг сървлет, докато филтърът работи в рамките на метод . За да направите това, контейнерът има специален обект RequestDispatcher.

Можете да го получите по два начина:

  • На обектаHttpServletRequest
  • На обектаServletContext

Този обект може да се използва за пренасочване на съществуваща заявка към друг сървлет . Например, оказа се, че потребителят не е оторизиран и искаме да му покажем page с оторизация. Е, or имаше грешка на сървъра и искаме да покажем page за грешка на потребителя :)

public class HelloServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response)  throws Exception {
           String path = "/error.html";
           ServletContext servletContext = this.getServletContext();
           RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher(path);
           requestDispatcher.forward(request, response);
    }
}

Можете също да се обадите RequestDispatcherот филтър.

public class MyFilter implements Filter {

  public void init(FilterConfig arg0) throws ServletException {
  }

  public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws Exception {
           String path = "/error.html";
           ServletContext servletContext = req.getServletContext();
           RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher(path);
           requestDispatcher.forward(req, resp);
    }

  public void destroy() {
  }
}

Имайте предвид, че заявката ще бъде обработена в метода forward()и няма нужда да се обаждате doFilter()след употреба RequestDispatcher.

Сравнение на пренасочване и препращане

И още един важен момент. Ако искате да пренасочите потребителя към друг URI във вашия сървлет, тогава можете да направите това по два начина:

  • redirect
  • forward

Вече ги анализирахме, но за удобство ще го повторя.

Когато пренасочвате чрез повикване response.sendRedirect("link"), сървърът изпраща обратно на браузъра (клиента) отговор 302и връзката, която сте посочor. И браузърът, след като анализира отговора на сървъра, изтегля връзката, която сте подали. Тоест връзката в браузъра се променя на нова.

Ако пренасочите чрез повикване requestDispatcher.forward(), тогава се прави нова заявка вътре в контейнера и вашият сървлет изпраща своя отговор до браузъра (клиента) като отговор на вашия сервлет. В този случай браузърът получава отговор от новия сървлет, но връзката в браузъра не се променя.