Come aggiungere una classe di filtri in Spring Boot?


229

Mi chiedo, se ci sono annotazioni per una Filterclasse (per applicazioni Web) in Spring Boot? Forse @Filter?

Voglio aggiungere un filtro personalizzato nel mio progetto.

La Guida di riferimento di Spring Boot menzionata FilterRegistrationBean, ma non sono sicuro di come usarla.


Si noti che il filtro aggiunto con @WebFilter non si comporta come un filtro reale nelle specifiche Servlet. Sarà un bean di primavera chiamato dopo molti altri bean di primavera e non come veri filtri prima di qualsiasi codice servlet.
lrxw,

puoi dirmi che esatto requisito. Se vuoi classi di filtri per ComponentScan, allora c'è un'annotazione per quel "@ ComponentScan.Filter"
Keaz,

Risposte:


159

Se si desidera impostare un filtro di terze parti, è possibile utilizzare FilterRegistrationBean. Ad esempio l'equivalente di web.xml

<filter>
     <filter-name>SomeFilter</filter-name>
        <filter-class>com.somecompany.SomeFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>SomeFilter</filter-name>
    <url-pattern>/url/*</url-pattern>
    <init-param>
       <param-name>paramName</param-name>
       <param-value>paramValue</param-value>
    </init-param>
</filter-mapping>

Questi saranno i due bean nel tuo @Configurationfile

@Bean
public FilterRegistrationBean someFilterRegistration() {

    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(someFilter());
    registration.addUrlPatterns("/url/*");
    registration.addInitParameter("paramName", "paramValue");
    registration.setName("someFilter");
    registration.setOrder(1);
    return registration;
} 

public Filter someFilter() {
    return new SomeFilter();
}

Quanto sopra è stato testato con Spring-Boot 1.2.3


1
cosa succede se voglio aggiungere più filtri? @Opal
verystrongjoe,

8
Basta aggiungere un filtro pubblico aggiuntivo @Bean FilterRegistrationBean additionalFilterRegistration ()
Haim Raman

Come si fa a sapere l'ordine in cui vengono applicati i filtri?
BeepDog,

7
FilterRegistrationBean.setOrder
Haim Raman,

Non è necessario il bean di filtro quando si chiama someFilter()direttamente il metodo .
wst

117

Ecco un esempio di un metodo per includere un filtro personalizzato in un'applicazione MVC di Spring Boot. Assicurati di includere il pacchetto in una scansione dei componenti:

package com.dearheart.gtsc.filters;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;

@Component
public class XClacksOverhead implements Filter {

  public static final String X_CLACKS_OVERHEAD = "X-Clacks-Overhead";

  @Override
  public void doFilter(ServletRequest req, ServletResponse res,
      FilterChain chain) throws IOException, ServletException {

    HttpServletResponse response = (HttpServletResponse) res;
    response.setHeader(X_CLACKS_OVERHEAD, "GNU Terry Pratchett");
    chain.doFilter(req, res);
  }

  @Override
  public void destroy() {}

  @Override
  public void init(FilterConfig arg0) throws ServletException {}

}

4
Il filtro deve essere registrato da qualche parte?
gstackoverflow,

1
Quando ho provato questo approccio, Filter è stato creato come bean e persino iniettato in un'altra classe ma il metodo init () non è stato eseguito . Probabilmente, init () funziona solo nella registrazione 'normale' e non nel contenitore a molla. Penso che si possa usare PostConstruct invece di init () ma non l'ho provato perché ho rifiutato di dichiarare Filter come Spring bean.
Baurzhan,

Che dire dell'ordinamento dei filtri con questo approccio?
Pavel Vlasov,

Come possiamo ottenere RS body da ServletResponse?
user2602807,

1
Una cosa importante da notare è che il nome del tuo bean (basato sul nome della tua classe) non dovrebbe essere lo stesso di un bean Spring. Ad esempio, potresti essere tentato di creare un MetricsFilter, ma questo bean verrà oscurato dal bean di attuatore Spring con lo stesso nome. L'
ho

78

Non esiste un'annotazione speciale per indicare un filtro servlet. Devi solo dichiarare un @Beantipo Filter(o FilterRegistrationBean). Un esempio (l'aggiunta di un'intestazione personalizzata per tutte le risposte) è in proprio di Boot EndpointWebMvcAutoConfiguration ;

Se si dichiara solo un Filterverrà applicato a tutte le richieste. Se aggiungi anche un FilterRegistrationBeanpuoi anche specificare singoli servlet e pattern url da applicare.

Nota:

A partire da Spring Boot 1.4, FilterRegistrationBeannon è deprecato e semplicemente spostato i pacchetti da org.springframework.boot.context.embedded.FilterRegistrationBeanaorg.springframework.boot.web.servlet.FilterRegistrationBean


Ti dispiacerebbe dirmi come includere la voce corrispondente in build.gradle? Ho aggiunto quanto segue, ma non viene compilato: fornitoCompile ('javax.servlet: servlet-api: 2.5') runtime ('javax.servlet: jstl: 1.1.2')
janetsmith

2
Spring Boot non funzionerà con Servlet 2.5 e non c'è ancora molto supporto per JSP. Non sono davvero un selezionatore, quindi non so cosa stai cercando di fare. Cosa c'è che non va nella "compilazione"? Funziona se dipendi semplicemente da "spring-boot-starter-web"? (Non penso che queste domande siano correlate alla domanda originale, quindi forse dovresti postare di nuovo con le nuove domande?)
Dave Syer

Ho aggiunto un filtro implementando l'interfaccia Filtro, tuttavia Eclipse non è in grado di trovare l'interfaccia. Quindi sto cercando di capire come aggiungerlo al classpath per la compilazione.
Janetsmith,

1
Sì, certo che devi avere Filtersul tuo percorso di classe. Normalmente userò semplicemente il spring-boot-starter-webper attirare tutte le dipendenze rilevanti (ad esempio qui ).
Dave Syer,

Come altri dettagli delle risposte, puoi anche annotare la tua classe Filter con @Component e verrà automaticamente registrata (per tutti gli URL).
Jakub Holý,

72

Esistono tre modi per aggiungere il filtro,

  1. Annota il tuo filtro con uno degli stereotipi Spring come @Component
  2. Registrare un @Beancon il Filtertipo in primavera@Configuration
  3. Registrare un @Beancon il FilterRegistrationBeantipo in primavera@Configuration

# 1 o # 2 lo faranno se desideri che il filtro si applichi a tutte le richieste senza personalizzazione, altrimenti usa # 3. Non è necessario specificare la scansione del componente per far funzionare # 1 finché si colloca la classe di filtro nello stesso o sotto-pacchetto delSpringApplication classe. Per il n. 3, l'uso insieme al n. 2 è necessario solo quando si desidera che Spring gestisca la propria classe di filtri, ad esempio se dispone di dipendenze cablate automaticamente. Per me funziona perfettamente con il nuovo filtro che non necessita di autowiring / iniezione di dipendenza.

Sebbene la combinazione di n. 2 e n. 3 funzioni correttamente, sono rimasto sorpreso dal fatto che non si ottengano due filtri applicati due volte. La mia ipotesi è che Spring combini i due bean come uno quando chiama lo stesso metodo per crearli entrambi. Nel caso in cui si desideri utilizzare il n. 3 da solo con l'autorizzazione, è possibile AutowireCapableBeanFactory. Quanto segue è un esempio,

private @Autowired AutowireCapableBeanFactory beanFactory;

    @Bean
    public FilterRegistrationBean myFilter() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        Filter myFilter = new MyFilter();
        beanFactory.autowireBean(myFilter);
        registration.setFilter(myFilter);
        registration.addUrlPatterns("/myfilterpath/*");
        return registration;
    }

Risposta eccellente. Grazie per il dettaglio di tutte le opzioni e per la spiegazione su come autorizzare il tuo Filterdurante l'utilizzoFilterRegistrationBean
sbk

Bella risposta. Questo è esattamente quello che ho indossato !!
Haykart,

Questo è anche descritto qui: baeldung.com/spring-boot-add-filter
Jakub Holý

31

AGGIORNAMENTO: 16-12-2017:

Ci sono 2 semplici modi per farlo in Spring Boot 1.5.8.RELEASE, non è necessario XML.

Primo modo: se non si dispone di alcun pattern URL spazioso, è possibile utilizzare @Component in questo modo: (Codice completo e dettagli sono disponibili qui https://www.surasint.com/spring-boot-filter/ )

@Component
public class ExampleFilter implements Filter{
   ...
}

Secondo modo: se vuoi usare i pattern url, puoi usare @WebFilter in questo modo: (Il codice completo e i dettagli sono qui https://www.surasint.com/spring-boot-filter-urlpattern/ )

@WebFilter(urlPatterns = "/api/count")
public class ExampleFilter implements Filter{
 ...
}

Ma devi anche aggiungere l'annotazione @ServletComponentScan nella classe @SpringBootApplication:

@ServletComponentScan
@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer {
...
}

Nota che @Component è l'annotazione di Spring, ma @WebFilter no. @WebFilter è l'annotazione Servlet 3.

In entrambi i casi, è sufficiente la dipendenza Spring Boot di base in pom.xml (non è necessario un jasper integrato tomcat esplicito)

    <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.8.RELEASE</version>
    </parent>

    <groupId>com.surasint.example</groupId>
    <artifactId>spring-boot-04</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <properties>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.source>1.8</maven.compiler.source>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

AVVERTIMENTO: il primo modo, se il Controller in Spring Boot ritorna in un file JSP, la richiesta passerà il filtro due volte.

Mentre, nel secondo modo, la richiesta passerà il filtro una sola volta.

Preferisco il secondo modo perché è più simile al comportamento predefinito nelle specifiche Servlet ( https://docs.oracle.com/cd/E19879-01/819-3669/6n5sg7b0b/index.html )

Puoi vedere altri log di test qui https://www.surasint.com/spring-boot-webfilter-instead-of-component/


Ho visto l' Filterinterfaccia essere chiamata numerose volte durante il lancio di applicationContext. C'è un modo per eseguirlo solo una volta?
Pra_A

@PAA intendi dai miei esempi?
Surasin Tancharoen,

20

Ecco un esempio della mia classe di filtri personalizzata:

package com.dawson.controller.filter;

import org.springframework.stereotype.Component;
import org.springframework.web.filter.GenericFilterBean;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


@Component
public class DawsonApiFilter extends GenericFilterBean {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        if (req.getHeader("x-dawson-nonce") == null || req.getHeader("x-dawson-signature") == null) {
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            httpResponse.setContentType("application/json");
            httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, "Required headers not specified in the request");
            return;
        }
        chain.doFilter(request, response);
    }
}

E l'ho aggiunto alla configurazione di avvio Spring aggiungendolo alla classe Configuration come segue:

package com.dawson.configuration;

import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module;
import com.dawson.controller.filter.DawsonApiFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

@SpringBootApplication
public class ApplicationConfiguration {
    @Bean
    public FilterRegistrationBean dawsonApiFilter() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new DawsonApiFilter());
// In case you want the filter to apply to specific URL patterns only
        registration.addUrlPatterns("/dawson/*");
        return registration;
    }
}

14

Dai documenti di primavera,

Contenitori servlet incorporati: aggiungere un servlet, un filtro o un listener a un'applicazione

Per aggiungere un servlet, un filtro o un listener di servlet *, fornire un @Bean definizione .

Per esempio:

@Bean
public Filter compressFilter() {
    CompressingFilter compressFilter = new CompressingFilter();
    return compressFilter;
}

Aggiungi questa @Beanconfigurazione al tuo@Configuration classe e il filtro verrà registrato all'avvio.

Inoltre puoi aggiungere servlet, filtri e listener utilizzando la scansione del percorso di classe,

Le classi annotate @WebServlet, @WebFilter e @WebListener possono essere registrate automaticamente con un contenitore servlet incorporato annotando una classe @Configuration con @ServletComponentScan e specificando i pacchetti che contengono i componenti che si desidera registrare. Per impostazione predefinita, @ServletComponentScan eseguirà la scansione dal pacchetto della classe annotata.



7

Se usi Spring Boot + Spring Security, puoi farlo nella configurazione di sicurezza.

Nell'esempio seguente, sto aggiungendo un filtro personalizzato prima di UsernamePasswordAuthenticationFilter (vedi tutti i filtri predefiniti di Spring Security e il loro ordine ).

@EnableWebSecurity
class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired FilterDependency filterDependency;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .addFilterBefore(
                new MyFilter(filterDependency),
                UsernamePasswordAuthenticationFilter.class);
    }
}

E la classe del filtro

class MyFilter extends OncePerRequestFilter  {
    private final FilterDependency filterDependency;

    public MyFilter(FilterDependency filterDependency) {
        this.filterDependency = filterDependency;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request,
        HttpServletResponse response,
        FilterChain filterChain)
        throws ServletException, IOException {
       // filter
       filterChain.doFilter(request, response);
    }
}

5

Utilizzando l'annotazione @WebFilter, si può fare come segue:

@WebFilter(urlPatterns = {"/*" })
public class AuthenticationFilter implements Filter{

    private static Logger logger = Logger.getLogger(AuthenticationFilter.class);

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

    @Override
    public void doFilter(ServletRequest arg0, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

         logger.info("checking client id in filter");
        HttpServletRequest request = (HttpServletRequest) arg0;
        String clientId = request.getHeader("clientId");
        if (StringUtils.isNotEmpty(clientId)) {
            chain.doFilter(request, response);
        } else {
            logger.error("client id missing.");
        }
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        // TODO Auto-generated method stub

    }

}

3
Aggiungi anche @ServletComponentScan
Justas il

5

Abbiamo circa quattro diverse opzioni per registrare un filtro usando Spring .

Innanzitutto, possiamo creare un bean Spring implementando Filter o estendendo HttpFilter :

@Component
public class MyFilter extends HttpFilter {

    @Override
    protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) 
        throws IOException, ServletException {
        // Implementation details...

        chain.doFilter(request, response);
    }
}

In secondo luogo, possiamo creare un bean Spring che estende GenericFilterBean :

@Component
public class MyFilter extends GenericFilterBean {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
  throws IOException, ServletException {
    //Implementation details...

        chain.doFilter(currentRequest, servletResponse);
    }
}

In alternativa possiamo usare la classe FilterRegistrationBean :

@Configuration
public class FilterConfiguration {

    private final MyFilter myFilter;

    @Autowired
    public FilterConfiguration(MyFilter myFilter) {
        this.myFilter = myFilter;
    }

    @Bean
    public FilterRegistrationBean<MyFilter> myFilterRegistration() {
        FilterRegistrationBean<DateLoggingFilter> filterRegistrationBean = new FilterRegistrationBean<>();
        filterRegistrationBean.setFilter(myFilter);
        filterRegistrationBean.setUrlPatterns(Collections.singletonList("/*"));
        filterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST);
        filterRegistrationBean.setOrder(Ordered.LOWEST_PRECEDENCE - 1);
        return filterRegistrationBean;
    }
}

E infine possiamo usare l' annotazione @WebFilter con @ServletComponentScan :

@WebFilter(urlPatterns = "/*", dispatcherTypes = {DispatcherType.REQUEST})
public class MyFilter extends HttpFilter {

    @Override
    protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
  throws IOException, ServletException {
        // Implementation details...

        chain.doFilter(request, response);
    }
}

Quale filtro usare e perché?
Pra_A

3

È più un consiglio che una risposta, ma se si utilizza Spring MVC nella propria applicazione Web, è consigliabile utilizzare Spring HandlerInterceptor anziché Filter

Può fare lo stesso lavoro, ma anche - Può funzionare con ModelAndView - I suoi metodi possono essere chiamati prima e dopo l'elaborazione della richiesta o dopo il completamento della richiesta.
- Può essere facilmente testato

1 Implementa l'interfaccia HandlerInterceptor e aggiungi un'annotazione @Component alla tua classe

@Component
public class SecurityInterceptor implements HandlerInterceptor {

    private static Logger log = LoggerFactory.getLogger(SecurityInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        request.getSession(true);
        if(isLoggedIn(request))
            return true;

        response.getWriter().write("{\"loggedIn\":false}");
        return false;
    }

    private boolean isLoggedIn(HttpServletRequest request) {
        try {
            UserSession userSession = (UserSession) request.getSession(true).getAttribute("userSession");
            return userSession != null && userSession.isLoggedIn();
        } catch(IllegalStateException ex) {
            return false;
        }
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {

    }
}

2 Configura il tuo intercettore

@Configuration
public class WebConfig implements WebMvcConfigurer {

    private HandlerInterceptor securityInterceptor;

    @Autowired
    public void setSecurityInterceptor(HandlerInterceptor securityInterceptor) {
        this.securityInterceptor = securityInterceptor;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(securityInterceptor).addPathPatterns("/**").excludePathPatterns("/login", "/logout");
    }

}

Semplice ed elegante! Grazie
MrMins il

3

Questo filtro ti aiuterà anche a consentire l'accesso incrociato all'origine

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class SimpleCORSFilter implements Filter {

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

            HttpServletResponse response = (HttpServletResponse) res;
            HttpServletRequest request = (HttpServletRequest) req;
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
            response.setHeader("Access-Control-Max-Age", "20000");
            response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN");

            if("OPTIONS".equalsIgnoreCase(request.getMethod())) {
                response.setStatus(HttpServletResponse.SC_OK);
            } else {
                chain.doFilter(req, res);
            }
    }


    public void destroy() {}

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        // TODO Auto-generated method stub

    }

}

2

È possibile utilizzare @WebFilter javax.servlet.annotation.WebFilter su una classe che implementa javax.servlet.Filter

@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {}

Quindi utilizzare @ServletComponentScan per registrarsi


2

Ho visto molte risposte qui, ma non ho provato nessuna di esse. Ho appena creato il filtro come nel seguente codice.

import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(urlPatterns = "/Admin")
@Configuration
public class AdminFilter implements Filter{
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse  servletResponse, FilterChain filterChain) throws IOException, ServletException      {
    System.out.println("happened");

    }

    @Override
    public void destroy() {

    }
}

E ha lasciato l'applicazione Spring Boot rimanente com'era.


2

Hai bisogno di 2 cose principali: - Aggiungi @ServletComponentScanalla tua Classe principale - puoi aggiungere un pacchetto chiamato filtro al suo interno e creare una FilterClasse che abbia i seguenti:

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class RequestFilter implements Filter {

 // whatever field you have

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
    HttpServletResponse response = (HttpServletResponse) res;
    HttpServletRequest request = (HttpServletRequest) req;

 // whatever implementation you want

        try {
            chain.doFilter(req, res);
        } catch(Exception e) {
            e.printStackTrace();
        }

}

public void init(FilterConfig filterConfig) {}

public void destroy() {}
}

1

puoi anche creare un filtro usando @WebFilter e implementa Filter, lo farà.

 @Configuration
        public class AppInConfig 
        {
        @Bean
      @Order(1)
      public FilterRegistrationBean aiFilterRegistration() {
            FilterRegistrationBean registration = new FilterRegistrationBean();
            registration.setFilter(new TrackingFilter());
            registration.addUrlPatterns("/**");
            registration.setOrder(1);
            return registration;
        } 
    @Bean(name = "TrackingFilter")
        public Filter TrackingFilter() {
            return new TrackingFilter();
        }   
    }

1

I filtri come suggerito dal nome vengono utilizzati per eseguire il filtro sulla richiesta a una risorsa o sulla risposta da una risorsa o su entrambi. Spring Boot offre alcune opzioni per registrare filtri personalizzati nell'applicazione Spring Boot. Diamo un'occhiata alle diverse opzioni.

1. Definire il filtro di avvio a molla e l'ordine di invito

Implementare l'interfaccia Filter per creare un nuovo filtro in Spring Boot.

@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CustomFilter implements Filter {

 private static final Logger LOGGER = LoggerFactory.getLogger(CustomFilter.class);

 @Override
 public void init(FilterConfig filterConfig) throws ServletException {
  LOGGER.info("########## Initiating Custom filter ##########");
 }

 @Override
 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

  HttpServletRequest request = (HttpServletRequest) servletRequest;
  HttpServletResponse response = (HttpServletResponse) servletResponse;

  LOGGER.info("Logging Request  {} : {}", request.getMethod(), request.getRequestURI());

  //call next filter in the filter chain
  filterChain.doFilter(request, response);

  LOGGER.info("Logging Response :{}", response.getContentType());
 }

 @Override
 public void destroy() {
  // TODO: 7/4/18
 }
}

Vediamo rapidamente alcuni punti importanti nel codice sopra

  • Il filtro registrato dall'annotazione @Component .
  • Per attivare i filtri nell'ordine giusto, dovevamo utilizzare l' annotazione @Order .

    @Component
    @Order(1)
    public class CustomFirstFilter implements Filter {
    
    }
    @Component
    @Order(2)
    public class CustomSecondFilter implements Filter {
    
    }

Nel codice sopra, CustomFirstFilter verrà eseguito prima di CustomSecondFilter.

Più basso è il numero, maggiore è la precedenza

2. Pattern URL

Se la mappatura basata su convenzione non è abbastanza flessibile, possiamo usare FilterRegistrationBean per il controllo completo dell'applicazione. Qui, non usare l' annotazione @Component per la classe filter ma registra il filtro usando FilterRegistrationBean .

 public class CustomURLFilter implements Filter {

 private static final Logger LOGGER = LoggerFactory.getLogger(CustomURLFilter.class);

 @Override
 public void init(FilterConfig filterConfig) throws ServletException {
  LOGGER.info("########## Initiating CustomURLFilter filter ##########");
 }

 @Override
 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

  HttpServletRequest request = (HttpServletRequest) servletRequest;
  HttpServletResponse response = (HttpServletResponse) servletResponse;

  LOGGER.info("This Filter is only called when request is mapped for /customer resource");

  //call next filter in the filter chain
  filterChain.doFilter(request, response);
 }

 @Override
 public void destroy() {

 }
}

Registra il filtro personalizzato utilizzando FilterRegistrationBean .

@Configuration
public class AppConfig {

 @Bean
 public FilterRegistrationBean < CustomURLFilter > filterRegistrationBean() {
  FilterRegistrationBean < CustomURLFilter > registrationBean = new FilterRegistrationBean();
  CustomURLFilter customURLFilter = new CustomURLFilter();

  registrationBean.setFilter(customURLFilter);
  registrationBean.addUrlPatterns("/greeting/*");
  registrationBean.setOrder(2); //set precedence
  return registrationBean;
 }
}

1

    @WebFilter(urlPatterns="/*")
    public class XSSFilter implements Filter {

        private static final org.apache.log4j.Logger LOGGER = LogManager.getLogger(XSSFilter.class);

        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            LOGGER.info("Initiating XSSFilter... ");

        }

        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            HttpServletRequest req = (HttpServletRequest) request;
            HttpRequestWrapper requestWrapper = new HttpRequestWrapper(req);
            chain.doFilter(requestWrapper, response);
        }

        @Override
        public void destroy() {
            LOGGER.info("Destroying XSSFilter... ");
        }

    }

Devi implementare Filter e devi essere annotato con @WebFilter (urlPatterns = "/ *")

E nella classe Applicazione o Configurazione è necessario aggiungere @ServletComponentScan In questo modo il filtro verrà registrato.


Questo @WebFilterè solo dal Servlet 3.0. Quindi potrebbe non funzionare correttamente per 2.5
ha9u63ar

1

Passaggio 1: creare un componente filtro implementando l'interfaccia Filtro.

@Component
public class PerformanceFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

            ......
            ......
    }

}

Passaggio 2: impostare questo filtro sui pattern uri utilizzando FilterRegistrationBean.

@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean<PerformanceFilter> perfFilter() {
        FilterRegistrationBean<PerformanceFilter> registration = new FilterRegistrationBean<>();
        registration.setFilter(new PerformanceFilter());
        registration.addUrlPatterns("/*");
        return registration;
    }
}

È possibile fare riferimento a questo collegamento per l'applicazione completa.


0

Innanzitutto, aggiungi @ServletComponentScanalla classe SpringBootApplication.

@ServletComponentScan
public class Application {

In secondo luogo, creare un file filtro che estende Filter o classe filtro di terze parti e aggiungere @WebFiltera questo file in questo modo:

@Order(1) //optional
@WebFilter(filterName = "XXXFilter", urlPatterns = "/*",
    dispatcherTypes = {DispatcherType.REQUEST, DispatcherType.FORWARD},
    initParams = {@WebInitParam(name = "confPath", value = "classpath:/xxx.xml")})
public class XXXFilter extends Filter{

0

Ho visto la risposta di @Vasily Komarov. Approccio simile, ma usando la classe astratta HandlerInterceptorAdapter invece di usare HandlerInterceptor .

Ecco un esempio ...

@Component
public class CustomInterceptor extends HandlerInterceptorAdapter {
   @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
    }
}

@Configuration
public class InterceptorConfig extends WebMvcConfigurerAdapter {

    @Autowired
    private CustomInterceptor customInterceptor ;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(customInterceptor );
    }

}

0

Come tutti sapete, Spring Boot è un modo meraviglioso di sviluppare una WebApp o una StandaloneApp con una configurazione minima e un'installazione mirata.

È così che ho realizzato uno sviluppo di filtri Web nell'applicazione Spring Boot

Le mie specifiche SpringBootApp: -

Versione Spring Boot: 2.0.4.RELEASE
Versione Java: 8.0
Specifica servlet : Servlet 3.0 (obbligatoria e importante)

Ho dichiarato il mio filtro Web nel modo seguente, aderendo alle specifiche servlet 3.0

inserisci qui la descrizione dell'immagine Questo è il modo programmatico di definire un filtro in sostituzione di definizioni basate su web.xml.

L'annotazione "@Webfilter" verrà elaborata dal contenitore durante la distribuzione, la classe Filter in cui viene trovata verrà creata secondo la configurazione e applicata ai pattern URL, javax.servlet.Servlets e javax.servlet.DispatcherTypes.

Per evitare completamente Web.xml e ottenere WebApp "Distribuibile": -

Per distribuire l'applicazione Spring Boot come "WAR tradizionale", la classe dell'applicazione dovrebbe estendere SpringBootServletInitializer.

NOTA:: SpringBootServletInitializer è una "Implementazione programmatica" di web.xml con riferimento alle specifiche Servlet 3.0+, che richiede un'implementazione di WebApplicationInitializer.

Pertanto, SpringBootApplication non richiede "web.xml" mentre la sua classe Application (dopo l'estensione di SpringBootServletInitializer) esegue la scansione di
- @WebFilter,
- @WebListener e
- @WebServlet.

Annotation @ServletComponentScan

Questa annotazione abilita la scansione dei pacchetti di base per i componenti Web annotati con @WebFilter, @WebListener e @WebServlet.

A causa del fatto che i contenitori incorporati non supportano le annotazioni @WebServlet, @WebFilter e @WebListener, Spring Boot, facendo molto affidamento sui contenitori incorporati, ha introdotto questa nuova annotazione @ServletComponentScan per supportare alcuni vasi dipendenti che utilizzano queste 3 annotazioni.

La scansione viene eseguita solo quando si utilizza un contenitore servlet incorporato.

Di seguito è la mia definizione di classe di applicazione Spring Boot: -

inserisci qui la descrizione dell'immagine

Inizializzatore servlet personalizzato: -

Qui: ho definito una classe personalizzata: "ServletInitializer" che estende la classe: SpringBootServletInitializer.

Come spiegato in precedenza, SpringBootServletInitializer è responsabile della scansione delle annotazioni: -
- @WebFilter,
- @WebListener e
- @WebServlet.

E quindi la classe di applicazione Spring Boot dovrebbe

  • Estendere la classe: SpringBootServletInitializer OR
  • estende la classe personalizzata che estende la classe: SpringBootServletInitializer

inserisci qui la descrizione dell'immagine


-6

I filtri vengono utilizzati principalmente nei file di logger e variano in base al logger utilizzato nel progetto Lemme spiegato per log4j2:

<Filters>
                <!-- It prevents error -->
                <ThresholdFilter level="error" onMatch="DENY" onMismatch="NEUTRAL"/>
                <!-- It prevents debug -->
                <ThresholdFilter level="debug" onMatch="DENY" onMismatch="NEUTRAL" />
                <!-- It allows all levels except debug/trace -->
                <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY" /> 
            </Filters>

I filtri sono usati per limitare i dati e ho usato ulteriormente il filtro di soglia per limitare i livelli di dati nel flusso. Ho citato i livelli che possono essere limitati lì. Per ulteriore riferimento, vedere l'ordine dei livelli di log4j2 - Livelli Log4J: TUTTI> TRACCIA> DEBUG> INFO> AVVISO> ERRORE> FATALE> OFF


FilterRegistrationBeancome menzionato nell'interrogazione javax.servlet.Filter, questa risposta parla diorg.apache.logging.log4j.core.Filter
Steve Buzonas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.