Java Servlet Filter viene utilizzato per intercettare la richiesta del client e fare qualche pre-elaborazione. Può anche intercettare la risposta e fare post-elaborazione prima di inviarla al client nell’applicazione web. Questo è il quarto articolo della serie Tutorial sulle Applicazioni Web, potresti voler dare un’occhiata anche agli articoli precedenti.
Filtro Servlet
In questo articolo, parleremo del Servlet Filter in Java. Esamineremo vari utilizzi del filtro servlet, come possiamo creare un filtro e imparare il suo utilizzo con una semplice applicazione web.
-
Esempio di filtro Servlet per il logging e la validazione della sessione
-
Perché abbiamo i Servlet Filter?
Nell’ultimo articolo, abbiamo appreso come gestire la sessione in un’applicazione web e se vogliamo assicurarci che una risorsa sia accessibile solo quando la sessione dell’utente è valida, possiamo farlo utilizzando gli attributi della sessione del servlet. L’approccio è semplice, ma se abbiamo molti servlet e JSP, diventerà difficile da mantenere a causa del codice ridondante. Se vogliamo cambiare il nome dell’attributo in futuro, dovremo modificarlo in tutti i luoghi in cui abbiamo l’autenticazione della sessione. Ecco perché abbiamo un servlet filter. I Servlet Filter sono componenti Java plug-and-play che possiamo utilizzare per intercettare e elaborare le richieste prima che vengano inviate ai servlet e le risposte dopo che il codice del servlet è terminato e prima che il contenitore invii la risposta al client. Alcuni compiti comuni che possiamo svolgere con i filtri del servlet sono:
- Registrazione dei parametri della richiesta nei file di log.
- Autenticazione e autorizzazione delle richieste per le risorse.
- Formattazione del corpo o dell’intestazione della richiesta prima di inviarlo al servlet.
- Compressione dei dati di risposta inviati al client.
- Modifica della risposta aggiungendo alcuni cookie, informazioni sull’intestazione, ecc.
Come ho già menzionato, i filtri del servlet sono plug-and-play e vengono configurati nel file del descrittore di distribuzione (web.xml). I servlet e i filtri sono entrambi inconsapevoli l’uno dell’altro e possiamo aggiungere o rimuovere un filtro del servlet semplicemente modificando web.xml. Possiamo avere più filtri per una singola risorsa e possiamo creare una catena di filtri per una singola risorsa in web.xml. Possiamo creare un filtro del servlet implementando l’interfaccia
javax.servlet.Filter
. -
Interfaccia del filtro Servlet
L’interfaccia del filtro Servlet è simile all’interfaccia Servlet e dobbiamo implementarla per creare il nostro filtro servlet personalizzato. L’interfaccia del filtro Servlet contiene i metodi del ciclo di vita di un filtro ed è gestita dal contenitore servlet. I metodi del ciclo di vita dell’interfaccia del filtro Servlet sono:
- void init(FilterConfig paramFilterConfig) – Quando il contenitore inizializza il filtro, questo è il metodo che viene invocato. Questo metodo viene chiamato solo una volta nel ciclo di vita del filtro e dovremmo inizializzare tutte le risorse in questo metodo. FilterConfig viene utilizzato dal contenitore per fornire parametri di inizializzazione e oggetto contesto servlet al filtro. Possiamo lanciare ServletException in questo metodo.
- doFilter(ServletRequest paramServletRequest, ServletResponse paramServletResponse, FilterChain paramFilterChain) – Questo è il metodo invocato ogni volta dal contenitore quando deve applicare un filtro a una risorsa. Il contenitore fornisce riferimenti agli oggetti richiesta e risposta al filtro come argomento. FilterChain viene utilizzato per invocare il filtro successivo nella catena. Questo è un ottimo esempio del Pattern Chain of Responsibility.
- void destroy() – Quando il contenitore scarica l’istanza del filtro, invoca il metodo destroy(). Questo è il metodo in cui possiamo chiudere tutte le risorse aperte dal filtro. Questo metodo viene chiamato solo una volta nella vita del filtro.
-
Servlet WebFilter annotation
javax.servlet.annotation.WebFilter
è stata introdotta in Servlet 3.0 e possiamo utilizzare questa annotazione per dichiarare un filtro servlet. Possiamo utilizzare questa annotazione per definire parametri di inizializzazione, nome e descrizione del filtro, servlet, modelli di URL e tipi di dispatcher su cui applicare il filtro. Se apporti modifiche frequenti alle configurazioni del filtro, è meglio utilizzare web.xml perché ciò non richiederà la ricompilazione della classe del filtro. Leggi: Guida alle annotazioni Java -
Configurazione del filtro Servlet in web.xml
Possiamo dichiarare un filtro servlet in web.xml come segue.
<filter> <filter-name>RequestLoggingFilter</filter-name> <!-- obbligatorio --> <filter-class>com.journaldev.servlet.filters.RequestLoggingFilter</filter-class> <!-- obbligatorio --> <init-param> <!-- opzionale --> <param-name>test</param-name> <param-value>testValue</param-value> </init-param> </filter>
Possiamo mappare un filtro alle classi servlet o ai modelli di URL come segue.
<filter-mapping> <filter-name>RequestLoggingFilter</filter-name> <!-- obbligatorio --> <url-pattern>/*</url-pattern> <!-- sia l'url-pattern che il nome della servlet sono obbligatori --> <servlet-name>LoginServlet</servlet-name> <dispatcher>REQUEST</dispatcher> </filter-mapping>
Nota: durante la creazione della catena dei filtri per una servlet, il container elabora prima i modelli di URL e poi i nomi delle servlet, quindi se è necessario assicurarsi che i filtri vengano eseguiti in un determinato ordine, prestare particolare attenzione durante la definizione della mappatura del filtro. I filtri servlet sono generalmente utilizzati per le richieste dei client, ma a volte vogliamo applicare filtri anche con RequestDispatcher, possiamo utilizzare l’elemento dispatcher in questo caso, i valori possibili sono REQUEST, FORWARD, INCLUDE, ERROR e ASYNC. Se non è definito alcun dispatcher, allora viene applicato solo alle richieste dei client.
-
Esempio di filtro servlet per la registrazione e la validazione della sessione
In our **servlet filter example**, we will create filters to log request cookies and parameters and validate session to all the resources except static HTMLs and LoginServlet because it will not have a session. We will create a dynamic web project **ServletFilterExample** whose project structure will look like the below image. [](https://journaldev.nyc3.cdn.digitaloceanspaces.com/2013/08/Servlet-Filter-Example-Project.png) login.html is the entry point of our application where the user will provide the login id and password for authentication. login.html code:
```
Login Page
```
LoginServlet is used to authenticate the request from the client for login.
```
package com.journaldev.servlet.session;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* Servlet implementation class LoginServlet
*/
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private final String userID = "admin";
private final String password = "password";
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// ottieni i parametri della richiesta per userID e password
String user = request.getParameter("user");
String pwd = request.getParameter("pwd");
if(userID.equals(user) && password.equals(pwd)){
HttpSession session = request.getSession();
session.setAttribute("user", "Pankaj");
// impostazione della scadenza della sessione a 30 minuti
session.setMaxInactiveInterval(30*60);
Cookie userName = new Cookie("user", user);
userName.setMaxAge(30*60);
response.addCookie(userName);
response.sendRedirect("LoginSuccess.jsp");
}else{
RequestDispatcher rd = getServletContext().getRequestDispatcher("/login.html");
PrintWriter out= response.getWriter();
out.println("Either user name or password is wrong.");
rd.include(request, response);
}
}
}
```
When the client is authenticated, it's forwarded to LoginSuccess.jsp LoginSuccess.jsp code:
```
<%@ page language="java" contentType="text/html; charset=US-ASCII"
pageEncoding="US-ASCII"%>
Login Success Page
<%
// consenti l'accesso solo se la sessione esiste
String user = (String) session.getAttribute("user");
String userName = null;
String sessionID = null;
Cookie[] cookies = request.getCookies();
if(cookies !=null){
for(Cookie cookie : cookies){
if(cookie.getName().equals("user")) userName = cookie.getValue();
if(cookie.getName().equals("JSESSIONID")) sessionID = cookie.getValue();
}
}
%>
Hi <%=userName %>, Login successful. Your Session ID=<%=sessionID %>
User=<%=user %>
Checkout Page
```
Notice that there is no session validation logic in the above JSP. It contains a link to another JSP page, CheckoutPage.jsp. CheckoutPage.jsp code:
```
<%@ page language="java" contentType="text/html; charset=US-ASCII"
pageEncoding="US-ASCII"%>
Login Success Page
<%
String userName = null;
String sessionID = null;
Cookie[] cookies = request.getCookies();
if(cookies !=null){
for(Cookie cookie : cookies){
if(cookie.getName().equals("user")) userName = cookie.getValue();
}
}
%>
Hi <%=userName %>, do the checkout.
```
LogoutServlet is invoked when a client clicks on the Logout button in any of the JSP pages.
```
package com.journaldev.servlet.session;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* Servlet implementation class LogoutServlet
*/
@WebServlet("/LogoutServlet")
public class LogoutServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
Cookie[] cookies = request.getCookies();
if(cookies != null){
for(Cookie cookie : cookies){
if(cookie.getName().equals("JSESSIONID")){
System.out.println("JSESSIONID="+cookie.getValue());
break;
}
}
}
// invalida la sessione se esiste
HttpSession session = request.getSession(false);
System.out.println("User="+session.getAttribute("user"));
if(session != null){
session.invalidate();
}
response.sendRedirect("login.html");
}
}
```
Now we will create logging and authentication servlet filter classes.
```
package com.journaldev.servlet.filters;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
/**
* Servlet Filter implementation class RequestLoggingFilter
*/
@WebFilter("/RequestLoggingFilter")
public class RequestLoggingFilter implements Filter {
private ServletContext context;
public void init(FilterConfig fConfig) throws ServletException {
this.context = fConfig.getServletContext();
this.context.log("RequestLoggingFilter initialized");
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
Enumeration params = req.getParameterNames();
while(params.hasMoreElements()){
String name = params.nextElement();
String value = request.getParameter(name);
this.context.log(req.getRemoteAddr() + "::Request Params::{"+name+"="+value+"}");
}
Cookie[] cookies = req.getCookies();
if(cookies != null){
for(Cookie cookie : cookies){
this.context.log(req.getRemoteAddr() + "::Cookie::{"+cookie.getName()+","+cookie.getValue()+"}");
}
}
// passa la richiesta lungo la catena di filtri
chain.doFilter(request, response);
}
public void destroy() {
// possiamo chiudere le risorse qui
}
}
```
```
package com.journaldev.servlet.filters;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebFilter("/AuthenticationFilter")
public class AuthenticationFilter implements Filter {
private ServletContext context;
public void init(FilterConfig fConfig) throws ServletException {
this.context = fConfig.getServletContext();
this.context.log("AuthenticationFilter initialized");
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
String uri = req.getRequestURI();
this.context.log("Requested Resource::"+uri);
HttpSession session = req.getSession(false);
if(session == null && !(uri.endsWith("html") || uri.endsWith("LoginServlet"))){
this.context.log("Unauthorized access request");
res.sendRedirect("login.html");
}else{
// passa la richiesta lungo la catena di filtri
chain.doFilter(request, response);
}
}
public void destroy() {
// chiudi eventuali risorse qui
}
}
```
Notice that we are not authenticating any HTML page or LoginServlet. Now we will configure these filters mapping in the web.xml file.
```
ServletFilterExample
login.html
RequestLoggingFilter
com.journaldev.servlet.filters.RequestLoggingFilter
AuthenticationFilter
com.journaldev.servlet.filters.AuthenticationFilter
RequestLoggingFilter
/*
REQUEST
AuthenticationFilter
/*
```
Now when we will run our application, we will get response pages like below images. [](https://journaldev.nyc3.cdn.digitaloceanspaces.com/2013/08/Servlet-Filter-Login.png) [](https://journaldev.nyc3.cdn.digitaloceanspaces.com/2013/08/Servlet-Filter-Login-Success.png) [](https://journaldev.nyc3.cdn.digitaloceanspaces.com/2013/08/Servlet-Filter-Checkout.png) If you are not logged in and try to access any JSP page, you will be forwarded to the login page. In the server log file, you can see the logs written by servlet filters as well as servlets.
```
Aug 13, 2013 1:06:07 AM org.apache.catalina.core.ApplicationContext log
INFO: 0:0:0:0:0:0:0:1%0::Cookie::{JSESSIONID,B7275762B8D23121152B1270D6EB240A}
Aug 13, 2013 1:06:07 AM org.apache.catalina.core.ApplicationContext log
INFO: Requested Resource::/ServletFilterExample/
Aug 13, 2013 1:06:07 AM org.apache.catalina.core.ApplicationContext log
INFO: Unauthorized access request
Aug 13, 2013 1:06:07 AM org.apache.catalina.core.ApplicationContext log
INFO: 0:0:0:0:0:0:0:1%0::Cookie::{JSESSIONID,B7275762B8D23121152B1270D6EB240A}
Aug 13, 2013 1:06:07 AM org.apache.catalina.core.ApplicationContext log
INFO: Requested Resource::/ServletFilterExample/login.html
Aug 13, 2013 1:06:43 AM org.apache.catalina.core.ApplicationContext log
INFO: 0:0:0:0:0:0:0:1%0::Request Params::{pwd=password}
Aug 13, 2013 1:06:43 AM org.apache.catalina.core.ApplicationContext log
INFO: 0:0:0:0:0:0:0:1%0::Request Params::{user=admin}
Aug 13, 2013 1:06:43 AM org.apache.catalina.core.ApplicationContext log
INFO: 0:0:0:0:0:0:0:1%0::Cookie::{JSESSIONID,B7275762B8D23121152B1270D6EB240A}
Aug 13, 2013 1:06:43 AM org.apache.catalina.core.ApplicationContext log
INFO: Requested Resource::/ServletFilterExample/LoginServlet
Aug 13, 2013 1:06:43 AM org.apache.catalina.core.ApplicationContext log
INFO: 0:0:0:0:0:0:0:1%0::Cookie::{JSESSIONID,8BDF777933194EDCAC1D8F1B73633C56}
Aug 13, 2013 1:06:43 AM org.apache.catalina.core.ApplicationContext log
INFO: 0:0:0:0:0:0:0:1%0::Cookie::{user,admin}
Aug 13, 2013 1:06:43 AM org.apache.catalina.core.ApplicationContext log
INFO: Requested Resource::/ServletFilterExample/LoginSuccess.jsp
Aug 13, 2013 1:06:52 AM org.apache.catalina.core.ApplicationContext log
INFO: 0:0:0:0:0:0:0:1%0::Cookie::{JSESSIONID,8BDF777933194EDCAC1D8F1B73633C56}
Aug 13, 2013 1:06:52 AM org.apache.catalina.core.ApplicationContext log
INFO: 0:0:0:0:0:0:0:1%0::Cookie::{user,admin}
Aug 13, 2013 1:06:52 AM org.apache.catalina.core.ApplicationContext log
INFO: Requested Resource::/ServletFilterExample/CheckoutPage.jsp
Aug 13, 2013 1:07:00 AM org.apache.catalina.core.ApplicationContext log
INFO: 0:0:0:0:0:0:0:1%0::Cookie::{JSESSIONID,8BDF777933194EDCAC1D8F1B73633C56}
Aug 13, 2013 1:07:00 AM org.apache.catalina.core.ApplicationContext log
INFO: 0:0:0:0:0:0:0:1%0::Cookie::{user,admin}
Aug 13, 2013 1:07:00 AM org.apache.catalina.core.ApplicationContext log
INFO: Requested Resource::/ServletFilterExample/LogoutServlet
JSESSIONID=8BDF777933194EDCAC1D8F1B73633C56
User=Pankaj
Aug 13, 2013 1:07:00 AM org.apache.catalina.core.ApplicationContext log
INFO: 0:0:0:0:0:0:0:1%0::Cookie::{JSESSIONID,8BDF777933194EDCAC1D8F1B73633C56}
Aug 13, 2013 1:07:00 AM org.apache.catalina.core.ApplicationContext log
INFO: 0:0:0:0:0:0:0:1%0::Cookie::{user,admin}
Aug 13, 2013 1:07:00 AM org.apache.catalina.core.ApplicationContext log
INFO: Requested Resource::/ServletFilterExample/login.html
Aug 13, 2013 1:07:06 AM org.apache.catalina.core.ApplicationContext log
INFO: 0:0:0:0:0:0:0:1%0::Cookie::{JSESSIONID,8BDF777933194EDCAC1D8F1B73633C56}
Aug 13, 2013 1:07:07 AM org.apache.catalina.core.ApplicationContext log
INFO: 0:0:0:0:0:0:0:1%0::Cookie::{user,admin}
Aug 13, 2013 1:07:07 AM org.apache.catalina.core.ApplicationContext log
INFO: Requested Resource::/ServletFilterExample/LoginSuccess.jsp
Aug 13, 2013 1:07:07 AM org.apache.catalina.core.ApplicationContext log
INFO: Unauthorized access request
Aug 13, 2013 1:07:07 AM org.apache.catalina.core.ApplicationContext log
INFO: 0:0:0:0:0:0:0:1%0::Cookie::{JSESSIONID,8BDF777933194EDCAC1D8F1B73633C56}
Aug 13, 2013 1:07:07 AM org.apache.catalina.core.ApplicationContext log
INFO: 0:0:0:0:0:0:0:1%0::Cookie::{user,admin}
Aug 13, 2013 1:07:07 AM org.apache.catalina.core.ApplicationContext log
INFO: Requested Resource::/ServletFilterExample/login.html
```
E questo è tutto per il filtro servlet in Java. È una delle caratteristiche importanti dell’applicazione web Java EE e dovremmo usarla per compiti comuni eseguiti da vari servlet. In post futuri, esamineremo i listener servlet e i cookie. Aggiornamento: Dopo aver ricevuto molte richieste per il progetto scaricabile, l’ho allegato al post, scaricalo dal link qui sotto.
Scarica Progetto Esempio Filtro Servlet
Guarda il prossimo articolo della serie su Servlet Listener. Aggiornamento Struts 2 utilizza un Servlet Filter per intercettare le richieste dei clienti e inoltrarle alle appropriate classi di azione, chiamate Struts 2 Interceptors. Dai un’occhiata al Tutorial per Principianti di Struts 2.
Source:
https://www.digitalocean.com/community/tutorials/java-servlet-filter-example-tutorial