Introduktion til filtre
Men det er ikke alt. Du tror virkelig ikke, at servlets er så simple, gør du?
Ud over de servlets, som vi allerede har analyseret, er der også såkaldte "utility servlets" - filtre . De ligner meget servlets, men deres hovedopgave er at hjælpe servlets med at behandle anmodninger.
Et filter er som en sekretær, og en servlet er som en direktør. Inden dokumentet når direktørens skrivebord, vil det gå gennem hænderne på sekretæren. Og efter at direktøren har underskrevet den, går den igen til sekretæren, allerede som udgående korrespondance f.eks.
En sådan sekretær kan afvise nogle af anmodningerne til direktøren (f.eks. spam). Eller giv standardsvar på spørgsmål, som han kender ("instruktøren er ikke på plads"). Og så videre. Desuden kan der være flere sådanne sekretærer: den ene kan filtrere spam for alle direktører på én gang, den anden kan overføre anmodninger mellem forskellige direktører og lignende.
Filtre fungerer på samme måde.
Klasser Filter, FilterChain, FilterConfig
Filtre minder meget om servlets, men med et par små forskelle. For at skrive dit eget filter skal du arve fra javax.servlet.Filter
.
Filteret har også metoder init()
og destroy()
. I stedet for en metode service()
har et filter en doFilter()
. Og har endda sin egen klasse FilterConfig. Filteret tilføjes også til servlet'en i web.xml-filen eller via @WebFilter-annotationen.
Liste over metoder:
Metoder | Beskrivelse | |
---|---|---|
1 | init(FilterConfig config) |
filterinitialisering |
2 | destroy() |
filter aflæsning |
3 | doFilter(ServletRequest , ServletResponse, FilterChain) |
anmodningsbehandling (filtrering) |
Hvad er forskellen mellem en servlet og et filter?
Der kan være flere filtre, og de behandler anmodningen (og svaret) sekventielt. De er samlet til en såkaldt kæde - og der er endda en særlig klasse for dem FilterChain
.
Efter at have behandlet anmodningen i metoden, doFilter()
skal du kalde metoden doFilter()
for det næste filter i kæden. Eksempel:
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() {
}
}
Faktisk kan du ikke tilføje svarteksten sådan . Formelt set er filtre og servlets uafhængige af hinanden og kan ændres uafhængigt. De kan skrives af forskellige udviklere på forskellige tidspunkter. Filterfunktionen er kun en servicefunktion, for eksempel:
- Logning af alle indgående anmodninger (og svar)
- Datakomprimering
- Kryptering (og dekryptering) af data
- Anmod om datavalidering
- Tilføj/fjern ønskede overskrifter
- Omdirigeringsanmodninger
- Adgangskontrol (kontrollerer om brugeren er logget ind)
RequestDispatcher klasse
doFilter()
Nogle gange kan det være nødvendigt at kalde en anden servlet, mens et filter kører i en metode . For at gøre dette har beholderen et specielt objekt RequestDispatcher
.
Du kan få det på to måder:
- Ved objektet
HttpServletRequest
- Ved objektet
ServletContext
Dette objekt kan bruges til at omdirigere en eksisterende anmodning til en anden servlet . For eksempel viste det sig, at brugeren ikke er autoriseret, og vi vil gerne vise ham en side med autorisation. Nå, eller der var en fejl på serveren, og vi vil gerne vise en fejlside til brugeren :)
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);
}
}
Du kan også ringe RequestDispatcher
fra et filter.
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() {
}
}
Bemærk, at anmodningen vil blive håndteret i metoden forward()
, og der er ingen grund til at ringe doFilter()
efter brug RequestDispatcher
.
Sammenligning af redirect og forward
Og endnu en vigtig pointe. Hvis du vil omdirigere brugeren til en anden URI i din servlet, kan du gøre dette på to måder:
redirect
forward
Vi har allerede analyseret dem, men for nemheds skyld vil jeg sige det igen.
Når du omdirigerer via et opkald response.sendRedirect("link")
, sender serveren tilbage til browseren (klienten) et svar 302
og det link, du har angivet. Og browseren, efter at have analyseret serversvaret, downloader det link, du har bestået. Det vil sige, at linket i browseren ændres til et nyt.
Hvis du viderestiller via et opkald requestDispatcher.forward()
, så laves en ny anmodning inde i containeren, og din servlet sender sit svar til browseren (klienten) som din servlets svar. I dette tilfælde modtager browseren et svar fra den nye servlet, men linket i browseren ændres ikke.
GO TO FULL VERSION