Wie füge ich eine Filterklasse in Spring Boot hinzu?


229

Ich frage mich, ob es Filterin Spring Boot Anmerkungen für eine Klasse (für Webanwendungen) gibt. Vielleicht @Filter?

Ich möchte meinem Projekt einen benutzerdefinierten Filter hinzufügen.

Das erwähnte Spring Boot-Referenzhandbuch erwähnt FilterRegistrationBean, aber ich bin nicht sicher, wie ich es verwenden soll.


Beachten Sie, dass sich der mit @WebFilter hinzugefügte Filter nicht wie ein echter Filter in der Servlet-Spezifikation verhält. Es wird eine Spring Bean sein, die nach vielen anderen Spring Beans benannt ist und vor keinem Servlet-Code echte Filter mag.
lrxw

Kannst du mir deine genaue Anforderung mitteilen? Wenn Sie Filterklassen für ComponentScan möchten, gibt es eine Anmerkung für "@ ComponentScan.Filter"
Keaz

Antworten:


159

Wenn Sie einen Filter eines Drittanbieters einrichten möchten, können Sie diesen verwenden FilterRegistrationBean. Zum Beispiel das Äquivalent von 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>

Dies sind die beiden Beans in Ihrer @ConfigurationDatei

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

Das obige wurde mit Spring-Boot 1.2.3 getestet


1
Was ist, wenn ich mehrere Filter hinzufügen möchte? @Opal
verystrongjoe

8
Fügen Sie einfach eine zusätzliche @Bean public FilterRegistrationBean zusätzlicheFilterRegistration ()
Haim Raman

Woher kennt man die Reihenfolge, in der die Filter angewendet werden?
BeepDog

7
FilterRegistrationBean.setOrder
Haim Raman

Sie benötigen keine Filter-Bean, wenn Sie die Methode someFilter()direkt aufrufen .
wst

117

Hier ist ein Beispiel für eine Methode zum Einfügen eines benutzerdefinierten Filters in eine Spring Boot MVC-Anwendung. Stellen Sie sicher, dass Sie das Paket in einen Komponentenscan aufnehmen:

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
Sollte der Filter irgendwo registriert sein?
gstackoverflow

1
Als ich diesen Ansatz ausprobierte, wurde Filter als Bean erstellt und sogar in eine andere Klasse injiziert, aber die init () -Methode wurde nicht ausgeführt . Wahrscheinlich funktioniert init () nur bei der "normalen" Registrierung, nicht beim Federcontainer. Ich denke, man kann PostConstruct anstelle von init () verwenden, aber ich habe das nicht versucht, da ich mich geweigert habe, Filter als Spring Bean zu deklarieren.
Baurzhan

Was ist mit der Filterreihenfolge mit diesem Ansatz?
Pavel Vlasov

Wie können wir RS-Body von ServletResponse erhalten?
user2602807

1
Eine wichtige Sache, die Sie beachten sollten, ist, dass der Name Ihrer Bohne (basierend auf Ihrem Klassennamen) nicht mit dem einer Springbohne identisch sein sollte. Zum Beispiel könnten Sie versucht sein, eine zu erstellen MetricsFilter, aber diese Bean wird von der gleichnamigen Spring-Aktuator-Bean überschattet.
Habe

78

Es gibt keine spezielle Anmerkung zur Bezeichnung eines Servlet-Filters. Sie deklarieren einfach einen @BeanTyp Filter(oder FilterRegistrationBean). Ein Beispiel (Hinzufügen eines benutzerdefinierten Headers zu allen Antworten) befindet sich in der EndpointWebMvcAutoConfiguration von Boot .

Wenn Sie nur a deklarieren Filter, wird es auf alle Anforderungen angewendet. Wenn Sie auch ein hinzufügen FilterRegistrationBean, können Sie zusätzlich einzelne Servlets und URL-Muster angeben, die angewendet werden sollen.

Hinweis:

Ab Spring Boot 1.4 FilterRegistrationBeanist nicht veraltet und einfach Pakete von org.springframework.boot.context.embedded.FilterRegistrationBeannach verschobenorg.springframework.boot.web.servlet.FilterRegistrationBean


Würde es Ihnen etwas ausmachen, mir zu sagen, wie ich den entsprechenden Eintrag in build.gradle aufnehmen kann? Ich habe folgendes hinzugefügt, aber es wird nicht kompiliert: BereitgestelltCompile ('javax.servlet: servlet-api: 2.5') Laufzeit ('javax.servlet: jstl: 1.1.2')
janetsmith

2
Spring Boot wird mit Servlet 2.5 nicht funktionieren, und JSP wird noch nicht wirklich unterstützt. Ich bin nicht wirklich ein Absolvent, also weiß ich nicht, was Sie versuchen zu tun. Was ist los mit "kompilieren"? Funktioniert es, wenn Sie nur auf "Spring-Boot-Starter-Web" angewiesen sind? (Ich glaube nicht, dass diese Fragen mit der ursprünglichen Frage zusammenhängen, also sollten Sie vielleicht noch einmal mit den neuen Fragen posten?)
Dave Syer

Ich habe einen Filter hinzugefügt, indem ich die Filterschnittstelle implementiert habe. Eclipse kann die Schnittstelle jedoch nicht finden. Ich versuche also herauszufinden, wie ich es zum Kompilieren zum Klassenpfad hinzufügen kann.
Janetmith

1
Ja, natürlich müssen Sie Filterauf Ihrem Klassenpfad haben. Normalerweise würde ich nur das verwenden spring-boot-starter-web, um alle relevanten Abhängigkeiten einzuziehen (z . B. hier ).
Dave Syer

Wie andere Antworten ausführlich beschreiben, können Sie Ihre Filterklasse auch einfach mit @Component kommentieren und sie wird automatisch registriert (für alle URLs).
Jakub Holý

72

Es gibt drei Möglichkeiten, Ihren Filter hinzuzufügen:

  1. Kommentieren Sie Ihren Filter mit einem der Frühlingsstereotypen wie @Component
  2. Registrieren Sie einen @Beanmit FilterTyp im Frühjahr@Configuration
  3. Registrieren Sie einen @Beanmit FilterRegistrationBeanTyp im Frühjahr@Configuration

Entweder Nr. 1 oder Nr. 2 reicht aus, wenn Sie möchten, dass Ihr Filter auf alle Anforderungen ohne Anpassung angewendet wird. Andernfalls verwenden Sie Nr. 3. Sie müssen keinen Komponentenscan angeben, damit # 1 funktioniert, solange Sie Ihre Filterklasse im selben oder Unterpaket Ihrer SpringApplicationKlasse platzieren. Für # 3 ist die Verwendung zusammen mit # 2 nur erforderlich, wenn Spring Ihre Filterklasse verwalten soll, z. B. automatisch verdrahtete Abhängigkeiten. Es funktioniert gut für mich, meinen Filter neu zu erstellen, für den keine automatische Verdrahtung / Injektion erforderlich ist.

Obwohl das Kombinieren von # 2 und # 3 gut funktioniert, war ich überrascht, dass nicht zwei Filter zweimal angewendet werden. Ich vermute, dass Spring die beiden Bohnen als eine kombiniert, wenn es dieselbe Methode aufruft, um beide zu erstellen. Wenn Sie # 3 alleine mit authowiring verwenden möchten, können Sie dies tun AutowireCapableBeanFactory. Das Folgende ist ein Beispiel:

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

Hervorragende Antwort. Vielen Dank für die Detaillierung aller Optionen und auch für die automatische Verdrahtung Filterwährend der VerwendungFilterRegistrationBean
sbk

Gute Antwort. Genau das habe ich gewohnt !!
Haykart

Dies wird auch hier beschrieben: baeldung.com/spring-boot-add-filter
Jakub Holý

31

UPDATE: 2017-12-16:

In Spring Boot 1.5.8.RELEASE gibt es zwei einfache Möglichkeiten, dies zu tun. XML ist nicht erforderlich.

Erster Weg: Wenn Sie kein räumliches URL-Muster haben, können Sie @Component wie folgt verwenden: (Vollständiger Code und Details finden Sie hier https://www.surasint.com/spring-boot-filter/ )

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

Zweiter Weg: Wenn Sie URL-Muster verwenden möchten, können Sie @WebFilter folgendermaßen verwenden: (Vollständiger Code und Details finden Sie hier https://www.surasint.com/spring-boot-filter-urlpattern/ )

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

Sie müssen Ihrer @ SpringBootApplication-Klasse jedoch auch die Annotation @ServletComponentScan hinzufügen:

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

Beachten Sie, dass @Component die Annotation von Spring ist, @WebFilter jedoch nicht. @WebFilter ist eine Servlet 3-Annotation.

In beiden Fällen benötigen Sie lediglich die grundlegende Spring Boot-Abhängigkeit in pom.xml (kein expliziter eingebetteter Tomcat-Jaspis erforderlich).

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

WARNUNG: Der erste Weg, wenn der Controller in Spring Boot zu einer JSP-Datei zurückkehrt, besteht die Anforderung den Filter zweimal.

Während die Anforderung auf die zweite Weise den Filter nur einmal durchläuft.

Ich bevorzuge den zweiten Weg, da er dem Standardverhalten in der Servlet-Spezifikation ähnlicher ist ( https://docs.oracle.com/cd/E19879-01/819-3669/6n5sg7b0b/index.html ).

Weitere Testprotokolle finden Sie hier https://www.surasint.com/spring-boot-webfilter-instead-of-component/


Ich habe gesehen, dass die FilterSchnittstelle beim Start des applicationContext mehrmals aufgerufen wurde. Gibt es eine Möglichkeit, es nur einmal auszuführen?
Pra_A

@PAA meinst du aus meinen Beispielen?
Surasin Tancharoen

20

Hier ist ein Beispiel für meine benutzerdefinierte Filterklasse:

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

Und ich habe es der Spring-Boot-Konfiguration hinzugefügt, indem ich es wie folgt zur Konfigurationsklasse hinzugefügt habe:

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

Aus Spring Docs,

Eingebettete Servlet-Container - Fügen Sie einer Anwendung ein Servlet, einen Filter oder einen Listener hinzu

So fügen Sie ein Servlet, einen Filter oder ein Servlet hinzu * Listener geben Sie eine @ Bean- Definition dafür an.

Z.B:

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

Fügen Sie diese @BeanKonfiguration Ihrer @ConfigurationKlasse hinzu, und der Filter wird beim Start registriert.

Sie können Servlets, Filter und Listener auch mithilfe des Klassenpfad-Scannens hinzufügen.

Mit @WebServlet, @WebFilter und @WebListener kommentierte Klassen können automatisch in einem eingebetteten Servlet-Container registriert werden, indem eine @ Configuration-Klasse mit @ServletComponentScan kommentiert und die Pakete angegeben werden, die die zu registrierenden Komponenten enthalten. Standardmäßig scannt @ServletComponentScan aus dem Paket der mit Anmerkungen versehenen Klasse.



7

Wenn Sie Spring Boot + Spring Security verwenden, können Sie dies in der Sicherheitskonfiguration tun.

Im folgenden Beispiel füge ich vor dem BenutzernamenPasswordAuthenticationFilter einen benutzerdefinierten Filter hinzu (siehe alle Standardfilter von Spring Security und deren Reihenfolge ).

@EnableWebSecurity
class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired FilterDependency filterDependency;

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

Und die Filterklasse

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

Mit der Annotation @WebFilter können Sie wie folgt vorgehen:

@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
Fügen Sie auch @ServletComponentScan
Justas

5

Wir haben ungefähr vier verschiedene Möglichkeiten, einen Filter mit Spring zu registrieren .

Erstens können wir eine Spring Bean erstellen, die Filter implementiert oder HttpFilter erweitert :

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

Zweitens können wir eine Spring Bean erstellen, die GenericFilterBean erweitert :

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

Alternativ können wir die FilterRegistrationBean- Klasse verwenden:

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

Und schließlich können wir die Verwendung @WebFilter Annotation mit @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);
    }
}

Welcher Filter soll verwendet werden und warum?
Pra_A

3

Es ist eher ein Rat als eine Antwort, aber wenn Sie eine Spring MVC in Ihrer Webanwendung verwenden, ist es eine gute Idee, Spring HandlerInterceptor anstelle von Filter zu verwenden

Es kann den gleichen Job ausführen, aber auch - Kann mit ModelAndView arbeiten - Seine Methoden können vor und nach der Anforderungsverarbeitung oder nach Abschluss der Anforderung aufgerufen werden.
- Es kann leicht getestet werden

1 Implementieren Sie die HandlerInterceptor-Schnittstelle und fügen Sie Ihrer Klasse eine @ Component-Annotation hinzu

@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 Konfigurieren Sie Ihren Interceptor

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

}

Einfach und elegant! Vielen Dank
MrMins

3

Dieser Filter hilft Ihnen auch dabei, den Cross-Origin-Zugriff zuzulassen

@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

Sie können @WebFilter javax.servlet.annotation.WebFilter für eine Klasse verwenden, die javax.servlet.Filter implementiert

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

Verwenden Sie dann @ServletComponentScan, um sich zu registrieren


2

Ich habe hier viele Antworten gesehen, aber keine ausprobiert. Ich habe gerade den Filter wie im folgenden Code erstellt.

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

    }
}

Und ließ die verbleibende Spring Boot-Anwendung so wie sie war.


2

Sie benötigen zwei wichtige Dinge: - @ServletComponentScanZu Ihrer Hauptklasse hinzufügen - Sie können ein Paket mit dem Namen filter hinzufügen, in dem Sie eine FilterKlasse erstellen , die Folgendes enthält:

@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

Sie können einen Filter auch mithilfe von @WebFilter erstellen und Filter implementieren.

 @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

Filter, wie der Name schon sagt, werden verwendet, um entweder die Anforderung an eine Ressource oder die Antwort einer Ressource oder beides zu filtern. Spring Boot bietet nur wenige Optionen zum Registrieren benutzerdefinierter Filter in der Spring Boot-Anwendung. Schauen wir uns die verschiedenen Optionen an.

1. Definieren Sie den Spring Boot Filter und die Aufrufreihenfolge

Implementieren Sie die Filterschnittstelle, um einen neuen Filter in Spring Boot zu erstellen.

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

Schauen wir uns kurz einige wichtige Punkte im obigen Code an

  • Der durch @Component- Annotation registrierte Filter .
  • Um Filter in der richtigen Reihenfolge auszulösen, mussten wir die Annotation @Order verwenden .

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

Im obigen Code wird CustomFirstFilter vor dem CustomSecondFilter ausgeführt.

Je niedriger die Zahl, desto höher die Priorität

2. URL-Muster

Wenn die konventionelle Zuordnung nicht flexibel genug ist, können wir FilterRegistrationBean für die vollständige Steuerung der Anwendung verwenden. Verwenden Sie hier keine @ Component- Annotation für die Filterklasse, sondern registrieren Sie den Filter mit einer 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() {

 }
}

Registrieren Sie den benutzerdefinierten Filter mit 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... ");
        }

    }

Sie müssen Filter implementieren und mit @WebFilter (urlPatterns = "/ *") kommentiert werden.

Und in der Anwendungs- oder Konfigurationsklasse müssen Sie @ServletComponentScan hinzufügen. Dadurch wird Ihr Filter registriert.


Dies @WebFilterist erst seit Servlet 3.0. Daher funktioniert es möglicherweise nicht richtig für 2.5
ha9u63ar

1

Schritt 1: Erstellen Sie eine Filterkomponente, indem Sie die Filterschnittstelle implementieren.

@Component
public class PerformanceFilter implements Filter {

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

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

}

Schritt 2: Setzen Sie diesen Filter mit FilterRegistrationBean auf die Uri-Muster.

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

Sie können diesen Link für die vollständige Anwendung verweisen .


0

@ServletComponentScanFügen Sie zunächst Ihrer SpringBootApplication-Klasse hinzu.

@ServletComponentScan
public class Application {

Zweitens erstellen Sie eine Filterdatei, die Filter oder die Filterklasse eines Drittanbieters erweitert, und fügen Sie @WebFilterdiese Datei wie folgt hinzu:

@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

Ich habe eine Antwort von @Vasily Komarov gesehen. Ähnlicher Ansatz, jedoch Verwendung der abstrakten HandlerInterceptorAdapter- Klasse anstelle von HandlerInterceptor .

Hier ist ein Beispiel...

@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

Wie Sie alle wissen, ist Spring Boot eine wunderbare Möglichkeit, eine WebApp oder StandaloneApp mit minimaler Konfiguration und eigenwilligem Setup zu entwickeln.

Auf diese Weise habe ich eine Webfilterentwicklung in Spring Boot-Anwendung erreicht

Meine SpringBootApp-Spezifikationen: -

Spring Boot-Version: 2.0.4.RELEASE
Java-Version: 8.0
Servlet-Spezifikation: Servlet 3.0 (obligatorisch und wichtig)

Ich habe meinen Webfilter wie folgt deklariert und dabei die Servlet-Spezifikationen 3.0 eingehalten

Geben Sie hier die Bildbeschreibung ein Dies ist die programmatische Methode zum Definieren eines Filters als Ersatz für web.xml-basierte Definitionen.

Die Annotation "@Webfilter" wird vom Container während der Bereitstellung verarbeitet. Die Filterklasse, in der sie gefunden wird, wird gemäß der Konfiguration erstellt und auf die URL-Muster javax.servlet.Servlets und javax.servlet.DispatcherTypes angewendet.

Um Web.xml vollständig zu vermeiden und "Deployable" WebApp zu erreichen: -

Um die Spring Boot-Anwendung als "traditionelles WAR" bereitzustellen, sollte die Anwendungsklasse SpringBootServletInitializer erweitern.

HINWEIS :: SpringBootServletInitializer ist eine "programmatische Implementierung" von web.xml unter Bezugnahme auf Servlet 3.0+ -Spezifikationen, für die eine Implementierung von WebApplicationInitializer erforderlich ist.

Daher benötigt SpringBootApplication nicht "web.xml", da die Anwendungsklasse (nach Erweiterung von SpringBootServletInitializer) nach
- @WebFilter,
- @WebListener und
- @WebServlet sucht.

Anmerkung @ServletComponentScan

Diese Annotation ermöglicht das Scannen von Basispaketen für die mit @WebFilter, @WebListener und @WebServlet annotierten Webkomponenten.

Aufgrund der Tatsache, dass eingebettete Container die Annotationen @WebServlet, @WebFilter und @WebListener nicht unterstützen, hat Spring Boot, das sich stark auf eingebettete Container stützt, diese neue Annotation @ServletComponentScan eingeführt, um einige abhängige Jars zu unterstützen, die diese 3 Annotationen verwenden.

Das Scannen wird nur durchgeführt, wenn ein eingebetteter Servlet-Container verwendet wird.

Es folgt meine Definition der Spring Boot-Anwendungsklasse: -

Geben Sie hier die Bildbeschreibung ein

Benutzerdefinierter Servlet-Initialisierer: -

Hier: Ich habe eine benutzerdefinierte Klasse definiert: "ServletInitializer", die die Klasse: SpringBootServletInitializer erweitert.

Wie bereits erläutert, ist SpringBootServletInitializer für das Scannen von Anmerkungen verantwortlich: -
- @WebFilter,
- @WebListener und
- @WebServlet.

Und daher sollte die Spring Boot-Anwendungsklasse

  • Erweitern Sie entweder die Klasse: SpringBootServletInitializer ODER
  • Erweitern Benutzerdefinierte Klasse, die die Klasse erweitert: SpringBootServletInitializer

Geben Sie hier die Bildbeschreibung ein


-6

Filter werden hauptsächlich in Logger-Dateien verwendet. Sie variieren je nach dem Logger, den Sie im Projekt Lemme EXPLAIN für log4j2 verwenden:

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

Filter werden verwendet, um die Daten einzuschränken, und ich habe den Schwellenwertfilter weiter verwendet, um die Datenebenen im Fluss einzuschränken. Ich habe die Ebenen erwähnt, die dort eingeschränkt werden können. Weitere Informationen finden Sie in der Levelreihenfolge von log4j2 - Log4J Levels: ALL> TRACE> DEBUG> INFO> WARN> ERROR> FATAL> OFF


FilterRegistrationBeanWie in der Frage erwähnt javax.servlet.Filter, spricht diese Antwort fürorg.apache.logging.log4j.core.Filter
Steve Buzonas
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.