제이온

[Spring] Filtro, Interceptor e Argument Resolver?

Creato: 2024-04-27

Creato: 2024-04-27 00:41

Cos'è un filtro (Filter)?

Il filtro è una funzionalità standard J2EE che fornisce la possibilità di gestire operazioni aggiuntive su tutte le richieste che corrispondono a un determinato modello di URL, prima e dopo che queste siano state inoltrate al servlet dispatcher (Dispatcher Servlet). In altre parole, viene gestito dal web container (come Tomcat) anziché dal contenitore Spring, quindi elabora la richiesta prima che raggiunga il servlet dispatcher.


[Spring] Filtro, Interceptor e Argument Resolver?


Implementazione del filtro (Filter)

Per aggiungere un filtro, è necessario implementare l'interfaccia Filter di javax.servlet, che include i seguenti tre metodi.


  • Metodo init
    • Questo metodo viene utilizzato per inizializzare l'oggetto filtro e aggiungerlo al servizio. Il web container chiama il metodo init una sola volta per inizializzare l'oggetto filtro, e le successive richieste verranno gestite tramite il metodo doFilter().
  • Metodo doFilter
    • Questo metodo viene eseguito dal web container prima che tutte le richieste HTTP corrispondenti allo schema URL vengano inviate al servlet dispatcher, e prima che il servlet dispatcher invii la risposta HTTP al client.
      Il parametro del metodo doFilter() è FilterChain, che consente di inoltrare la richiesta alla successiva destinazione tramite il suo metodo doFilter(). Inserendo il processo di elaborazione desiderato prima e dopo chain.doFilter(), è possibile eseguire l'elaborazione desiderata.
  • Metodo destroy
    • Questo metodo viene utilizzato per rimuovere l'oggetto filtro dal servizio e restituire le risorse utilizzate. Viene chiamato dal web container una sola volta e, successivamente, l'oggetto non verrà più elaborato dal metodo doFilter().


Codice di esempio - Specifiche Servlet


Codice di esempio - @Component


  • @Component: consente di registrare il filtro come bean Spring.
  • @Order: consente di definire l'ordine dei filtri in caso di più filtri.
  • Se un filtro basato sulle specifiche Servlet viene registrato come bean Spring, è possibile utilizzare altri bean relativi alle specifiche Spring.


Codice di esempio - @Configuration

Se si desidera che il filtro funzioni solo per determinati URI, è possibile registrare il filtro come bean Spring utilizzando FilterRegistrationBean.


Scopo del filtro (Filter)

Principalmente gestisce la convalida e l'elaborazione dei parametri della richiesta stessa.


  • Operazioni comuni relative alla sicurezza
    • Poiché il filtro funziona nel web container, è possibile eseguire controlli di sicurezza (come la protezione da XSS e CSRF) e bloccare le richieste non valide. Poiché la richiesta non viene inoltrata al contenitore Spring, è possibile migliorare ulteriormente la stabilità.
  • Registrazione di tutte le richieste
  • Compressione di immagini/dati e codifica di stringhe
    • Il filtro implementa funzionalità utilizzate in modo diffuso nelle applicazioni web, come la compressione di immagini o dati e la codifica di stringhe.
  • Personalizzazione di ServletRequest
    • HttpServletRequest consente di leggere il contenuto del corpo solo una volta. Pertanto, Filter e Interceptor non possono leggere il corpo. È possibile creare un oggetto ServletRequest personalizzato per registrare il corpo.


Interceptor

Cos'è un Interceptor?

A differenza dei filtri (Filter), che sono una specifica standard J2EE, l'interceptor è una tecnologia fornita da Spring che consente di accedere e modificare le richieste e le risposte prima e dopo che il servlet dispatcher ha chiamato il controller. In altre parole, a differenza dei filtri che funzionano nel web container, l'interceptor funziona nel contesto Spring.


Il servlet dispatcher richiede al mapping del gestore di trovare il controller appropriato e restituisce una catena di esecuzione (HandlerExecutionChain) come risultato. Pertanto, se questa catena di esecuzione ha più interceptor registrati, gli interceptor vengono eseguiti in sequenza prima dell'esecuzione del controller. Se non ci sono interceptor, il controller viene eseguito direttamente.


Implementazione di Interceptor

Per aggiungere un interceptor, è necessario implementare l'interfaccia HandlerInterceptor di org.springframework.web.servlet, che include i seguenti tre metodi.


  • Metodo preHandle
    • Il metodo preHandle viene eseguito prima che il controller venga chiamato. Pertanto, può essere utilizzato per l'elaborazione preliminare, come la modifica o l'aggiunta di informazioni di richiesta prima del controller.
    • Il terzo parametro del metodo preHandle, handler, è un oggetto che astrae le informazioni del metodo annotato con @RequestMapping.
    • Il tipo di ritorno del metodo preHandle è boolean. Se il valore restituito è true, l'elaborazione continua al passaggio successivo, mentre se è false, l'elaborazione viene interrotta e le operazioni successive (il successivo interceptor o il controller) non vengono eseguite.
  • Metodo postHandle
    • Il metodo postHandle viene eseguito dopo che il controller è stato chiamato. Pertanto, può essere utilizzato per l'elaborazione post-controller.
  • Metodo afterCompletion
    • Come suggerisce il nome, il metodo afterCompletion viene eseguito dopo che tutte le operazioni sono state completate, inclusa la generazione del risultato finale da parte di tutte le viste.


Codice di esempio


  • Registra l'interceptor creato come bean.
  • Registra l'interceptor creato nel metodo addInterceptors() dell'interfaccia WebMvcConfigurer.
  • Gli interceptor vengono eseguiti nell'ordine in cui sono registrati in InterceptorRegistry.


Scopo di Interceptor

Principalmente gestisce l'elaborazione della coerenza delle informazioni della richiesta utilizzando la logica del servizio.


  • Operazioni comuni come l'autenticazione/autorizzazione
    • Ad esempio, è possibile verificare operazioni relative alla richiesta del client, come l'autenticazione o l'autorizzazione, prima che vengano inoltrate al controller.
  • Registrazione delle chiamate API
    • È possibile registrare le informazioni del client tramite gli oggetti HttpServletRequest e HttpServletResponse ricevuti.
  • Elaborazione dei dati da inoltrare al controller
    • È possibile elaborare gli oggetti HttpServletRequest e HttpServletResponse ricevuti e inoltrarli al controller.
  • Simulazione di AOP
    • È possibile ottenere informazioni aggiuntive sul metodo da eseguire, come la firma del metodo, dal terzo parametro, HandlerMethod, del metodo preHandle(), e determinare se eseguire la logica.


Filtro (Filter) vs Interceptor

  • Il filtro viene eseguito nel contesto web e l'interceptor nel contesto Spring, quindi i tempi di esecuzione sono diversi.
  • Il filtro può gestire le operazioni prima e dopo il servlet dispatcher, mentre l'interceptor può gestire le operazioni prima e dopo il controller.
  • È consigliabile utilizzare il filtro per le operazioni che devono essere gestite globalmente indipendentemente da Spring, o per la convalida dei parametri di input stessi, o quando si utilizza ServletRequest invece di HttpServletRequest.
  • È consigliabile utilizzare l'interceptor per le operazioni che devono essere gestite globalmente in base alle richieste del client all'interno di Spring, o quando è necessario mescolare la logica del servizio.
  • È possibile gestire le eccezioni utilizzando @ControllerAdvice e @ExceptionHandler con l'interceptor, ma non con il filtro.
    • Il filtro gestisce principalmente le eccezioni che si verificano in quel punto racchiudendo il metodo doFilter() in un blocco try~catch.


Argument Resolver

Cos'è Argument Resolver?

Argument Resolver consente di creare indirettamente l'oggetto desiderato dai valori contenuti nella richiesta quando una richiesta viene inviata al controller.


Scopo di Argument Resolver

Ad esempio, supponiamo che una richiesta venga inviata con un token JWT. È necessario convalidare se questo token è valido ed estrarre l'ID memorizzato nel token per creare un oggetto utente connesso.

Se non si utilizza Argument Resolver, è necessario implementare il processo di convalida del token e di conversione in un oggetto utente connesso in ogni controller. Ciò comporterebbe codice ridondante nei controller in cui è necessaria la convalida dell'utente e un aumento delle responsabilità del controller. Argument Resolver può risolvere questo problema.


Implementazione di Argument Resolver

È possibile utilizzare Argument Resolver implementando HandlerMethodArgumentResolver. Questa interfaccia specifica l'implementazione dei due metodi seguenti.



  • Metodo supportsParameter
    • Si crea e si aggiunge una specifica annotazione prima del parametro per cui si desidera eseguire Argument Resolver. Il metodo supportsParameter() controlla se l'annotazione desiderata è presente nel parametro del metodo richiesto e restituisce true se la contiene.
  • Metodo resolveArgument
    • Se il metodo supportsParameter restituisce true, ovvero se è presente un determinato metodo con un'annotazione specifica, questo metodo esegue il binding del parametro nella forma desiderata e lo restituisce.


Se si utilizza Argument Resolver, l'implementazione del controller è la seguente.



Differenza tra Argument Resolver e Interceptor

  • Argument Resolver funziona dopo l'interceptor e restituisce l'oggetto desiderato dai valori contenuti nella richiesta quando una richiesta viene inviata al controller.
  • Al contrario, l'interceptor intercetta la richiesta prima che il controller venga effettivamente eseguito e non può restituire alcun oggetto specifico. Può restituire solo valori booleani o void.


Fonti


Domande di colloquio previste e risposte

Cos'è un filtro?

Un filtro è una funzionalità che consente di elaborare operazioni aggiuntive su tutte le richieste che corrispondono a un determinato modello di URL prima e dopo che queste sono state inoltrate al servlet dispatcher, e funziona a livello di container servlet.


Quando si usa un filtro?

I filtri possono essere utilizzati per elaborare operazioni che devono essere gestite globalmente indipendentemente da Spring. Oppure, quando si esegue la convalida incentrata sui parametri della richiesta.

In particolare, vengono utilizzati per gestire operazioni comuni relative alla sicurezza, la registrazione di tutte le richieste, la compressione di immagini/dati e la codifica di stringhe, nonché la personalizzazione di ServletRequest.


Cos'è un interceptor?

Un interceptor è una funzionalità che consente di accedere e modificare le richieste e le risposte prima e dopo che il servlet dispatcher ha chiamato il controller, e funziona a livello di container Spring.


Quando si usa un interceptor?

Gli interceptor possono essere utilizzati per elaborare operazioni che devono essere gestite globalmente in base alle richieste del client, o quando si chiama la logica del servizio durante la convalida.

In particolare, vengono utilizzati per gestire operazioni comuni come l'autenticazione/autorizzazione, la registrazione delle chiamate API e l'elaborazione dei dati da inoltrare al controller.


Qual è la differenza tra filtro e interceptor?

Il filtro viene eseguito a livello di container servlet, mentre l'interceptor a livello di container Spring.

Il filtro può gestire le operazioni prima e dopo il servlet dispatcher, mentre l'interceptor può gestire le operazioni prima e dopo il controller.

Pertanto, è consigliabile utilizzare il filtro per le operazioni che devono essere gestite globalmente indipendentemente da Spring, mentre l'interceptor per le operazioni che devono essere gestite globalmente in base alle richieste del client all'interno di Spring.


Cos'è Argument Resolver?

Argument Resolver è una funzionalità che consente di creare indirettamente l'oggetto desiderato dai valori contenuti nella richiesta quando una richiesta viene inviata al controller.


Quando si usa Argument Resolver?

Può essere utilizzato quando una richiesta viene inviata con un token JWT, per convalidare se il token è valido ed estrarre l'ID memorizzato nel token per creare un oggetto LoginMember.


Qual è la differenza tra interceptor e Argument Resolver?

Argument Resolver restituisce l'oggetto desiderato dai valori contenuti nella richiesta quando una richiesta viene inviata al controller. Al contrario, l'interceptor non può restituire alcun oggetto specifico e viene eseguito prima di Argument Resolver.

Commenti0