Introducere în filtre

Dar asta nu este tot. Chiar nu crezi că servleturile sunt atât de simple, nu?

Pe lângă servleturile pe care le-am analizat deja, există și așa-numitele „servlet-uri utilitare” - filtre . Ele sunt foarte asemănătoare cu servlet-urile, dar sarcina lor principală este de a ajuta servleturile să proceseze cererile.

Un filtru este ca o secretară, iar un servlet este ca un director. Înainte ca documentul să ajungă la biroul directorului, acesta va trece prin mâinile secretarului. Și după ce directorul îl semnează, va merge din nou la secretară, deja ca corespondență de ieșire, de exemplu.

Un astfel de secretar poate respinge unele dintre solicitările adresate directorului (de exemplu, spam). Sau oferiți răspunsuri standard la întrebările cunoscute de el („directorul nu este la locul său”). Și așa mai departe. Mai mult, pot exista mai multe astfel de secretare: unul poate filtra spam-ul pentru toți directorii simultan, celălalt poate transfera cereri între diferiți directori și altele asemenea.

Filtrele funcționează în același mod.

servlet-uri utilitare”

Clasele Filter, FilterChain, FilterConfig

Filtrele sunt foarte asemănătoare cu servlet-urile, dar cu câteva mici diferențe. Pentru a vă scrie propriul filtru, trebuie să moșteniți din javax.servlet.Filter.

Filtrul are și metode init()și destroy(). În loc de o metodă, service()un filtru are un doFilter(). Și chiar are propria sa clasă FilterConfig. De asemenea, filtrul este adăugat la servlet în fișierul web.xml sau prin adnotarea @WebFilter.

Lista metodelor:

Metode Descriere
1 init(FilterConfig config) inițializarea filtrului
2 destroy() descărcarea filtrului
3 doFilter(ServletRequest , ServletResponse, FilterChain) procesarea cererii (filtrare)

Care este diferența dintre un servlet și un filtru?

Pot exista mai multe filtre și procesează secvenţial cererea (și răspunsul). Ele sunt combinate într-un așa-numit lanț - și există chiar și o clasă specială pentru ei FilterChain.

După procesarea cererii în metodă, doFilter()trebuie să apelați metoda doFilter()următorului filtru din lanț. Exemplu:

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() {
  }
}

De fapt, nu puteți adăuga corpul răspunsului așa . În mod oficial, filtrele și servleturile sunt independente unele de altele și pot fi modificate independent. Ele pot fi scrise de diferiți dezvoltatori în momente diferite. Funcția de filtru este doar o funcție de serviciu, de exemplu:

  • Înregistrarea tuturor solicitărilor (și răspunsurilor) primite
  • Comprimarea datelor
  • Criptarea (și decriptarea) datelor
  • Solicitați validarea datelor
  • Adăugați/eliminați anteturile dorite
  • Solicitări de redirecționare
  • Controlul accesului (verificarea dacă utilizatorul este autentificat)

Clasa RequestDispatcher

doFilter() Uneori poate fi necesar să apelați un alt servlet în timp ce un filtru rulează într-o metodă . Pentru a face acest lucru, containerul are un obiect special RequestDispatcher.

Îl poți obține în două moduri:

  • La obiectHttpServletRequest
  • La obiectServletContext

Acest obiect poate fi folosit pentru a redirecționa o solicitare existentă către un alt servlet . De exemplu, s-a dovedit că utilizatorul nu este autorizat și vrem să-i arătăm o pagină cu autorizare. Ei bine, sau a apărut o eroare pe server și vrem să afișăm o pagină de eroare utilizatorului :)

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);
    }
}

Puteți apela și RequestDispatcherde la un filtru.

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() {
  }
}

Rețineți că cererea va fi tratată în metodă forward()și nu este nevoie să apelați doFilter()după utilizare RequestDispatcher.

Comparație între redirecționare și transmitere

Și încă un punct important. Dacă doriți să redirecționați utilizatorul către un alt URI din servletul dvs., atunci puteți face acest lucru în două moduri:

  • redirect
  • forward

Le-am analizat deja, dar pentru comoditate o voi spune din nou.

Când redirecționați printr-un apel response.sendRedirect("link"), serverul trimite înapoi browserului (clientului) un răspuns 302și linkul pe care l-ați specificat. Iar browserul, după ce a analizat răspunsul serverului, descarcă linkul pe care l-ați transmis. Adică linkul din browser se schimbă cu unul nou.

Dacă redirecționați printr-un apel requestDispatcher.forward(), atunci se face o nouă solicitare în interiorul containerului, iar servletul dvs. trimite răspunsul său către browser (client) ca răspuns al servlet-ului dvs. În acest caz, browserul primește un răspuns de la noul servlet, dar linkul din browser nu se modifică.