Comment ajouter une classe de filtre dans Spring Boot?


229

Je me demande s'il y a une annotation pour une Filterclasse (pour les applications Web) dans Spring Boot? Peut @Filter- être ?

Je veux ajouter un filtre personnalisé dans mon projet.

Le Guide de référence de Spring Boot en a parlé FilterRegistrationBean, mais je ne sais pas comment l'utiliser.


Notez que le filtre ajouté avec @WebFilter ne se comporte pas comme un véritable filtre dans la spécification Servlet. Ce sera un haricot de printemps appelé après beaucoup d'autres haricots de printemps et pas comme de vrais filtres avant tout code de servlet.
lrxw

pouvez-vous me dire votre exigence exacte. Si vous voulez des classes de filtre pour ComponentScan, il y a une annotation pour ce "@ ComponentScan.Filter"
Keaz

Réponses:


159

Si vous souhaitez configurer un filtre tiers, vous pouvez l'utiliser FilterRegistrationBean. Par exemple l'équivalent de 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>

Ce seront les deux beans de votre @Configurationfichier

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

Ce qui précède a été testé avec Spring-boot 1.2.3


1
que faire si je veux ajouter plusieurs filtres? @Opal
verystrongjoe

8
Ajoutez simplement un @Bean public FilterRegistrationBean supplémentaireFilterRegistration ()
Haim Raman

Comment sait-on l'ordre dans lequel les filtres sont appliqués?
BeepDog

7
FilterRegistrationBean.setOrder
Haim Raman

Vous n'avez pas besoin de filtre bean lorsque vous appelez someFilter()directement la méthode .
2017 à 7h57

117

Voici un exemple d'une méthode pour inclure un filtre personnalisé dans une application Spring Boot MVC. Assurez-vous d'inclure le package dans une analyse des composants:

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
Le filtre doit-il être enregistré quelque part?
gstackoverflow

1
Lorsque j'ai essayé cette approche, Filter a été créé en tant que bean et a même été injecté dans une autre classe, mais la méthode init () ne s'est pas exécutée . Probablement, init () ne fonctionne que dans un enregistrement «normal» et non par un conteneur à ressort. Je pense que l'on peut utiliser PostConstruct au lieu de init () mais je n'ai pas essayé car j'ai refusé de déclarer Filter comme Spring bean.
Baurzhan

Qu'en est-il de l'ordre des filtres en utilisant cette approche?
Pavel Vlasov, le

Comment obtenir le corps RS de ServletResponse?
user2602807

1
Une chose importante à noter est que le nom de votre bean (basé sur le nom de votre classe) ne doit pas être le même qu'un bean Spring. Par exemple, vous pourriez être tenté de créer un MetricsFilter, mais ce bean sera éclipsé par le bean actionneur Spring du même nom.
J'ai

78

Il n'y a pas d'annotation spéciale pour désigner un filtre de servlet. Vous déclarez simplement un @Beantype Filter(ou FilterRegistrationBean). Un exemple (en ajoutant un en-tête personnalisé à toutes les réponses) se trouve dans la propre EndpointWebMvcAutoConfiguration de Boot ;

Si vous déclarez seulement un, Filteril sera appliqué à toutes les demandes. Si vous ajoutez également un, FilterRegistrationBeanvous pouvez également spécifier des servlets individuels et des modèles d'URL à appliquer.

Remarque:

À partir de Spring Boot 1.4, FilterRegistrationBeann'est pas obsolète et déplace simplement les packages de org.springframework.boot.context.embedded.FilterRegistrationBeanversorg.springframework.boot.web.servlet.FilterRegistrationBean


Pourriez-vous me dire comment inclure l'entrée correspondante dans build.gradle? J'ai ajouté ce qui suit, mais il n'est pas compilé: providedCompile ('javax.servlet: servlet-api: 2.5') runtime ('javax.servlet: jstl: 1.1.2')
janetsmith

2
Spring Boot ne fonctionnera pas avec Servlet 2.5, et il n'y a pas encore beaucoup de support pour JSP. Je ne suis pas vraiment un gradateur, donc je ne sais pas ce que vous essayez de faire. Quel est le problème avec "compiler"? Cela fonctionne-t-il si vous dépendez simplement de "spring-boot-starter-web"? (Je ne pense pas que ces questions soient liées à la question d'origine, alors peut-être que vous devriez poster à nouveau avec les nouvelles questions?)
Dave Syer

J'ai ajouté un filtre en implémentant l'interface Filter, mais Eclipse ne parvient pas à trouver l'interface. J'essaie donc de comprendre comment l'ajouter à classpath pour la compilation.
janetsmith

1
Oui, bien sûr, vous devez avoir Filtersur votre chemin de classe. Normalement, j'utiliserais juste le spring-boot-starter-webpour tirer toutes les dépendances pertinentes (par exemple ici ).
Dave Syer

Comme d'autres réponses le détaillent, vous pouvez également simplement annoter votre classe Filter avec @Component et elle sera automatiquement enregistrée (pour toutes les URL).
Jakub Holý

72

Il existe trois façons d'ajouter votre filtre,

  1. Annotez votre filtre avec l'un des stéréotypes de Spring tels que @Component
  2. Enregistrer un @BeanavecFiltertype Spring@Configuration
  3. Enregistrer un type @Beanavec FilterRegistrationBeanSpring@Configuration

Soit # 1 ou # 2 fera l'affaire si vous voulez que votre filtre s'applique à toutes les demandes sans personnalisation, utilisez # 3 sinon. Vous n'avez pas besoin de spécifier l'analyse des composants pour que # 1 fonctionne tant que vous placez votre classe de filtre dans le même ou sous-package de votreSpringApplication classe. Pour le n ° 3, l'utilisation avec le n ° 2 n'est nécessaire que lorsque vous souhaitez que Spring gère votre classe de filtre, comme par exemple les dépendances câblées automatiquement. Cela fonctionne très bien pour moi de nouveau mon filtre qui ne nécessite aucun câblage / injection de dépendance.

Bien que la combinaison des # 2 et # 3 fonctionne bien, j'ai été surpris que cela ne se termine pas avec deux filtres appliquant deux fois. Je suppose que Spring combine les deux beans comme un seul lorsqu'il appelle la même méthode pour créer les deux. Si vous souhaitez utiliser le # 3 seul avec le câblage automatique, vous pouvez AutowireCapableBeanFactory. Ce qui suit est un exemple,

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

Excellente réponse. Merci d'avoir détaillé toutes les options et d'avoir également expliqué comment câbler automatiquement votre ordinateur Filteren utilisantFilterRegistrationBean
sbk

Très bonne réponse. C'est exactement ce que je n'ai pas l'habitude !!
haykart

Ceci est également décrit ici: baeldung.com/spring-boot-add-filter
Jakub Holý

31

MISE À JOUR: 16/12/2017:

Il existe 2 façons simples de le faire dans Spring Boot 1.5.8.RELEASE, pas besoin de XML.

Première façon: si vous n'avez pas de modèle d'URL spatial, vous pouvez utiliser @Component comme ceci: (Le code complet et les détails sont ici https://www.surasint.com/spring-boot-filter/ )

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

Deuxième façon: si vous souhaitez utiliser des modèles d'URL, vous pouvez utiliser @WebFilter comme ceci: (Le code complet et les détails sont ici https://www.surasint.com/spring-boot-filter-urlpattern/ )

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

Mais vous devez également ajouter l'annotation @ServletComponentScan dans votre classe @SpringBootApplication:

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

Notez que @Component est l'annotation de Spring, mais pas @WebFilter. @WebFilter est une annotation Servlet 3.

Dans les deux cas, vous avez juste besoin de la dépendance de base Spring Boot dans pom.xml (pas besoin de jasper Tomcat intégré explicite)

    <?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>

AVERTISSEMENT: la première façon, si le contrôleur dans Spring Boot revient à un fichier JSP, la demande passera le filtre deux fois.

Alors que, dans le second cas, la demande ne passera le filtre qu'une seule fois.

Je préfère la deuxième façon car elle est plus similaire au comportement par défaut dans la spécification Servlet ( https://docs.oracle.com/cd/E19879-01/819-3669/6n5sg7b0b/index.html )

Vous pouvez voir plus de journal de test ici https://www.surasint.com/spring-boot-webfilter-instead-of-component/


J'ai vu l' Filterinterface être appelée plusieurs fois lors du lancement de l'applicationContext. Existe-t-il un moyen de l'exécuter une seule fois?
Pra_A

@PAA vous voulez dire de mes exemples?
Surasin Tancharoen

20

Voici un exemple de ma classe de filtre personnalisée:

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

Et je l'ai ajouté à la configuration de démarrage Spring en l'ajoutant à la classe Configuration comme suit:

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

Depuis Spring docs,

Conteneurs de servlet intégrés - Ajouter un servlet, un filtre ou un écouteur à une application

Pour ajouter un servlet, un filtre ou un écouteur de servlet *, fournissez-lui une définition @Bean .

Par exemple:

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

Ajoutez cette @Beanconfiguration à votre @Configurationclasse et le filtre sera enregistré au démarrage.

Vous pouvez également ajouter des servlets, des filtres et des écouteurs à l'aide de l'analyse des chemins de classe,

Les classes annotées @WebServlet, @WebFilter et @WebListener peuvent être automatiquement enregistrées avec un conteneur de servlet incorporé en annotant une classe @Configuration avec @ServletComponentScan et en spécifiant le ou les packages contenant les composants que vous souhaitez enregistrer. Par défaut, @ServletComponentScan analysera à partir du package de la classe annotée.



7

Si vous utilisez Spring Boot + Spring Security, vous pouvez le faire dans la configuration de sécurité.

Dans l'exemple ci-dessous, j'ajoute un filtre personnalisé avant le nom d'utilisateurPasswordAuthenticationFilter (voir tous les filtres Spring Security par défaut et leur ordre ).

@EnableWebSecurity
class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired FilterDependency filterDependency;

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

Et la classe de filtre

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

En utilisant l'annotation @WebFilter, cela peut être fait comme suit:

@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
Ajoutez également @ServletComponentScan
Justas

5

Nous avons environ quatre options différentes pour enregistrer un filtre à l'aide de Spring .

Tout d'abord, nous pouvons créer un bean Spring implémentant un filtre ou étendant 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);
    }
}

Deuxièmement, nous pouvons créer un bean Spring étendant 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);
    }
}

Alternativement, nous pouvons utiliser 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;
    }
}

Et nous pouvons enfin utiliser l' @WebFilter annotation avec @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);
    }
}

Quel filtre utiliser et pourquoi?
Pra_A

3

C'est plus un conseil qu'une réponse, mais si vous utilisez un Spring MVC dans votre application Web, la bonne idée est d'utiliser Spring HandlerInterceptor au lieu de Filter

Il peut faire le même travail, mais aussi - Peut fonctionner avec ModelAndView - Ses méthodes peuvent être appelées avant et après le traitement de la demande, ou après l'achèvement de la demande.
- Il peut être facilement testé

1 Implémentez l'interface HandlerInterceptor et ajoutez une annotation @Component à votre 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 Configurez votre intercepteur

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

}

Simple et élégant! Merci
MrMins

3

Ce filtre vous aidera également à autoriser l'accès à l'origine croisée

@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

Vous pouvez utiliser @WebFilter javax.servlet.annotation.WebFilter sur une classe qui implémente javax.servlet.Filter

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

Utilisez ensuite @ServletComponentScan pour vous inscrire


2

J'ai vu beaucoup de réponses ici mais je n'en ai essayé aucune. Je viens de créer le filtre comme dans le code suivant.

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

    }
}

Et a laissé l'application Spring Boot restante telle qu'elle était.


2

Vous avez besoin de 2 choses principales: - Ajouter @ServletComponentScanà votre classe principale - vous pouvez ajouter un package nommé filtre à l'intérieur, vous créez une Filterclasse qui a les éléments suivants:

@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

vous pouvez également créer un filtre en utilisant @WebFilter et implémente Filter, il le fera.

 @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

Filtres comme le nom le suggère, utilisés pour effectuer un filtrage sur la demande adressée à une ressource ou sur la réponse d'une ressource, ou les deux. Spring Boot fournit quelques options pour enregistrer des filtres personnalisés dans l'application Spring Boot. Examinons les différentes options.

1. Définir le filtre de démarrage de Spring et l'ordre d'invocation

Implémentez l'interface de filtre pour créer un nouveau filtre dans 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
 }
}

Examinons rapidement certains points importants du code ci-dessus

  • Le filtre enregistré par l' annotation @Component .
  • Pour déclencher des filtres dans le bon ordre, nous devions utiliser l' annotation @Order .

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

Dans le code ci-dessus, CustomFirstFilter s'exécutera avant CustomSecondFilter.

Plus le nombre est bas, plus la priorité est élevée

2. Modèle d'URL

Si le mappage basé sur les conventions n'est pas suffisamment flexible, nous pouvons utiliser FilterRegistrationBean pour le contrôle complet de l'application. Ici, n'utilisez pas d' annotation @Component pour la classe de filtre mais enregistrez le filtre à l'aide d'un 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() {

 }
}

Enregistrez le filtre personnalisé à l'aide de 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... ");
        }

    }

Vous devez implémenter Filter et devez être annoté avec @WebFilter (urlPatterns = "/ *")

Et dans la classe Application ou Configuration, vous devez ajouter @ServletComponentScan Par cela, votre filtre sera enregistré.


Ce @WebFiltern'est que depuis Servlet 3.0. Donc, cela pourrait ne pas fonctionner correctement pour le 2.5
ha9u63ar

1

Étape 1: créez un composant de filtre en implémentant l'interface de filtre.

@Component
public class PerformanceFilter implements Filter {

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

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

}

Étape 2: définissez ce filtre sur les modèles d'URI à l'aide de FilterRegistrationBean.

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

Vous pouvez renvoyer ce lien pour une demande complète.


0

Tout d'abord, ajoutez @ServletComponentScanà votre classe SpringBootApplication.

@ServletComponentScan
public class Application {

Deuxièmement, créez un fichier de filtre étendant Filter ou une classe de filtre tierce et ajoutez @WebFilterà ce fichier comme ceci:

@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

J'ai vu la réponse de @Vasily Komarov. Approche similaire, mais en utilisant la classe abstraite HandlerInterceptorAdapter au lieu d'utiliser HandlerInterceptor .

Voici un exemple...

@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

Comme vous le savez tous, Spring Boot est une merveilleuse façon de développer une WebApp ou StandaloneApp avec une configuration minimale et une configuration réfléchie.

Voici comment j'ai réalisé un développement de filtre Web dans une application Spring Boot

Mes spécifications SpringBootApp: -

Version Spring Boot: 2.0.4.RELEASE
Version Java: 8.0
Spécification du servlet : Servlet 3.0 (obligatoire et important)

J'ai déclaré mon filtre Web de la manière suivante, en respectant les spécifications de la servlet 3.0

entrez la description de l'image ici Il s'agit de la manière programmatique de définir un filtre en remplacement des définitions basées sur web.xml.

L'annotation "@Webfilter" sera traitée par le conteneur pendant le déploiement, la classe Filter dans laquelle elle se trouve sera créée selon la configuration et appliquée aux modèles d'URL, javax.servlet.Servlets et javax.servlet.DispatcherTypes.

Pour éviter complètement Web.xml et obtenir une WebApp "déployable": -

Pour déployer Spring Boot Application en tant que «WAR traditionnel», la classe d'application doit étendre SpringBootServletInitializer.

REMARQUE :: SpringBootServletInitializer est une "implémentation programmatique" de web.xml en référence aux spécifications Servlet 3.0+, qui nécessitent une implémentation de WebApplicationInitializer.

Ainsi, SpringBootApplication ne nécessite pas "web.xml" car sa classe Application (après extension de SpringBootServletInitializer) recherche
- @WebFilter,
- @WebListener et
- @WebServlet.

Annotation @ServletComponentScan

Cette annotation permet d'analyser les packages de base pour les composants Web annotés avec @WebFilter, @WebListener et @WebServlet.

Étant donné que les conteneurs incorporés ne prennent pas en charge les annotations @WebServlet, @WebFilter et @WebListener, Spring Boot, s'appuyant fortement sur les conteneurs incorporés, a introduit cette nouvelle annotation @ServletComponentScan pour prendre en charge certains pots dépendants qui utilisent ces 3 annotations.

L'analyse n'est effectuée que lors de l'utilisation d'un conteneur de servlet intégré.

Voici ma définition de classe d'application Spring Boot: -

entrez la description de l'image ici

Initialiseur de servlet personnalisé: -

Ici: J'ai défini une classe personnalisée: "ServletInitializer" qui étend la classe: SpringBootServletInitializer.

Comme expliqué précédemment, SpringBootServletInitializer est responsable de l'analyse des annotations: -
- @WebFilter,
- @WebListener et
- @WebServlet.

Et donc la classe d'application Spring Boot devrait

  • Soit étendre la classe: SpringBootServletInitializer OU
  • étendre la classe personnalisée qui étend la classe: SpringBootServletInitializer

entrez la description de l'image ici


-6

Les filtres sont principalement utilisés dans les fichiers logger, cela varie en fonction du logger que vous utilisez dans le projet Lemme expliquer pour 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>

Les filtres sont utilisés pour restreindre les données et j'ai utilisé un filtre de seuil pour restreindre davantage les niveaux de données dans le flux J'ai mentionné les niveaux qui peuvent être restreints là-bas. Pour votre réfrence supplémentaire, voir l'ordre des niveaux de log4j2 - Log4J Levels: ALL> TRACE> DEBUG> INFO> WARN> ERROR> FATAL> OFF


FilterRegistrationBeancomme mentionné dans la question est pour javax.servlet.Filter, cette réponse parle deorg.apache.logging.log4j.core.Filter
Steve Buzonas
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.