Jak dodać klasę filtrów w Spring Boot?


229

Zastanawiam się, czy Filterw Spring Boot jest jakaś adnotacja dla klasy (dla aplikacji internetowych)? Być może @Filter?

Chcę dodać niestandardowy filtr do mojego projektu.

W Poradniku Spring Boot wspomniano o FilterRegistrationBean, ale nie jestem pewien, jak go używać.


Zauważ, że filtr dodany z @WebFilter nie zachowuje się jak prawdziwy filtr w specyfikacji serwletu. Będzie to fasolka szparagowa wywoływana po wielu innych fasolach szparagowych, a nie jak prawdziwe filtry przed jakimkolwiek kodem serwletu.
lrxw

czy możesz mi powiedzieć, że dokładnie spełniasz wymagania. Jeśli chcesz filtrować klasy dla ComponentScan, istnieje adnotacja do tego „@ ComponentScan.Filter”
Keaz

Odpowiedzi:


159

Jeśli chcesz skonfigurować filtr innej firmy, możesz użyć FilterRegistrationBean. Na przykład odpowiednik pliku 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>

To będą dwie fasole w twoim @Configurationpliku

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

Powyższe zostało przetestowane w wersji Spring-boot 1.2.3


1
co jeśli chcę dodać wiele filtrów? @Opal
verystrongjoe,

8
Wystarczy dodać dodatkowy @Bean public FilterRegistrationBean dodatkowyFilterRegistration ()
Haim Raman

Skąd wiadomo, w jakiej kolejności stosowane są filtry?
BeepDog

7
FilterRegistrationBean.setOrder
Haim Raman

Nie potrzebujesz filtru bean, gdy wywołujesz metodę someFilter()bezpośrednio.
wst

117

Oto przykład jednej metody włączenia niestandardowego filtra do aplikacji Spring Boot MVC. Pamiętaj o dołączeniu pakietu do skanu składników:

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
Czy należy gdzieś zarejestrować filtr?
gstackoverflow

1
Kiedy wypróbowałem to podejście, Filter został utworzony jako bean, a nawet został wstrzyknięty do innej klasy, ale metoda init () nie zadziałała . Prawdopodobnie init () działa tylko przy „normalnej” rejestracji, a nie przy pojemniku sprężynowym. Wydaje mi się, że zamiast init () można użyć PostConstruct, ale nie próbowałem tego, ponieważ odmówiłem zadeklarowania Filter jako Spring Bean.
Baurzhan,

Co z kolejnością filtrów przy użyciu tego podejścia?
Pavel Vlasov

Jak możemy uzyskać ciało RS z ServletResponse?
user2602807

1
Jedną ważną rzeczą do zapamiętania jest to, że nazwa twojej fasoli (w oparciu o nazwę twojej klasy) nie powinna być taka sama jak fasola wiosenna. Na przykład może pojawić się pokusa, aby utworzyć MetricsFilter, ale ta fasola zostanie przyćmiona przez komponent Spring Spring o tej samej nazwie. Nauczyłem się tego na
własnej skórze

78

Nie ma specjalnej adnotacji oznaczającej filtr serwletu. Po prostu deklarujesz @Beantyp Filter(lub FilterRegistrationBean). Przykład (dodanie niestandardowego nagłówka do wszystkich odpowiedzi) znajduje się w EndpointWebMvcAutoConfiguration Boota ;

Jeśli zadeklarujesz tylko Filter, będzie on stosowany do wszystkich wniosków. Jeśli dodasz również FilterRegistrationBean, możesz dodatkowo określić indywidualne serwlety i wzorce adresów URL do zastosowania.

Uwaga:

Począwszy od Spring Boot 1.4, FilterRegistrationBeannie jest przestarzałe i po prostu przenosi pakiety z org.springframework.boot.context.embedded.FilterRegistrationBeandoorg.springframework.boot.web.servlet.FilterRegistrationBean


Czy mógłbyś mi powiedzieć, jak dołączyć odpowiedni wpis w build.gradle? Dodałem następujące, ale nie zostanie skompilowany: providedCompile ( 'javax.servlet: servlet-api: 2,5') Czas pracy ( 'javax.servlet: JSTL: 1.1.2')
janetsmith

2
Spring Boot nie będzie działał z serwletem 2.5, a tak naprawdę nie ma jeszcze wsparcia dla JSP. Tak naprawdę nie jestem równiarką, więc nie wiem, co próbujesz zrobić. Co jest złego w „kompilacji”? Czy to działa, jeśli polegasz na „wiosennym rozruchu-sieci”? (Nie sądzę jednak, aby te pytania były związane z pierwotnym pytaniem, więc może powinieneś opublikować nowe pytanie?)
Dave Syer

Dodałem filtr, implementując interfejs Filter, jednak Eclipse nie może znaleźć interfejsu. Próbuję więc wymyślić, jak dodać go do ścieżki klas do kompilacji.
janetsmith,

1
Tak, oczywiście, że musisz mieć Filterna swojej ścieżce klas. Zwykle używałbym tego, spring-boot-starter-webaby pobrać wszystkie odpowiednie zależności (np. Tutaj ).
Dave Syer,

W ramach innych odpowiedzi możesz też po prostu dodać adnotację do swojej klasy Filter za pomocą @Component, która zostanie automatycznie zarejestrowana (dla wszystkich adresów URL).
Jakub Holý

72

Istnieją trzy sposoby dodania filtra:

  1. Opisz swój filtr jednym ze stereotypów wiosennych, takich jak @Component
  2. Zarejestruj się @Beanz Filtertypem na wiosnę@Configuration
  3. Zarejestruj się @Beanz FilterRegistrationBeantypem na wiosnę@Configuration

Zrobisz # 1 lub # 2, jeśli chcesz, aby Twój filtr dotyczył wszystkich żądań bez dostosowywania, użyj # 3 w przeciwnym razie. Nie musisz określać skanowania komponentu dla nr 1, aby działał, dopóki umieścisz klasę filtra w tym samym lub paczce swojej SpringApplicationklasy. W przypadku # 3 użycie razem z # 2 jest konieczne tylko wtedy, gdy chcesz, aby Spring zarządzał klasą filtrów, na przykład automatycznie włączał zależności. Działa dobrze dla mnie, aby nowy filtr, który nie wymaga żadnej zależności / automatycznego uruchamiania / wstrzykiwania.

Chociaż połączenie nr 2 i nr 3 działa dobrze, byłem zaskoczony, że nie kończy się to na zastosowaniu dwóch filtrów dwa razy. Domyślam się, że Spring łączy dwie fasole jako jedną, gdy wywołuje tę samą metodę, aby utworzyć obie. Jeśli chcesz korzystać z samego # 3 z autouruchamianiem, możesz AutowireCapableBeanFactory. Oto przykład

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

Doskonała odpowiedź. Dziękujemy za szczegółowe opisanie wszystkich opcji, a także omówienie sposobu automatycznego uruchamiania Filterpodczas korzystaniaFilterRegistrationBean
sbk

Świetna odpowiedź. Właśnie tego nie chciałem !!
haykart

Jest to również opisane tutaj: baeldung.com/spring-boot-add-filter
Jakub Holý

31

AKTUALIZACJA: 16.12.2017:

Są dwa proste sposoby, aby to zrobić w Spring Boot 1.5.8. UWOLNIENIE, bez potrzeby XML.

Pierwszy sposób: jeśli nie masz żadnego spacjalnego wzorca adresu URL, możesz użyć @Component w ten sposób: (Pełny kod i szczegóły są tutaj https://www.surasint.com/spring-boot-filter/ )

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

Drugi sposób: jeśli chcesz używać wzorców adresów URL, możesz użyć @WebFilter w następujący sposób: (Pełny kod i szczegóły są tutaj https://www.surasint.com/spring-boot-filter-urlpattern/ )

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

Ale musisz również dodać adnotację @ServletComponentScan w swojej klasie @SpringBootApplication:

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

Zauważ, że @Component jest adnotacją Springa, ale @WebFilter nie jest. @WebFilter jest adnotacją Servlet 3.

Oba sposoby, potrzebujesz tylko podstawowej zależności Spring Boot w pom.xml (nie potrzebujesz jawnego osadzonego tomcat jasper)

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

OSTRZEŻENIE: Pierwszy sposób, jeśli kontroler w Spring Boot powróci do pliku JSP, żądanie przejdzie filtr dwukrotnie.

Podczas gdy w drugi sposób żądanie przejdzie filtr tylko raz.

Wolę drugi sposób, ponieważ jest bardziej podobny do domyślnego zachowania w specyfikacji serwletu ( https://docs.oracle.com/cd/E19879-01/819-3669/6n5sg7b0b/index.html )

Więcej dzienników testów można zobaczyć tutaj https://www.surasint.com/spring-boot-webfilter-instead-of-component/


Widziałem Filterinterfejs wywoływany wiele razy podczas uruchamiania aplikacjiContext. Czy jest jakiś sposób, aby wykonać to tylko raz?
Pra_A

@ PAA masz na myśli z moich przykładów?
Surasin Tancharoen,

20

Oto przykład mojej niestandardowej klasy Filter:

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

Dodałem go do konfiguracji rozruchu Spring, dodając go do klasy Configuration w następujący sposób:

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

Z dokumentów wiosny,

Wbudowane kontenery serwletów - Dodaj serwlet, filtr lub detektor do aplikacji

Aby dodać detektor serwletu, filtru lub serwletu *, podaj dla niego definicję @Bean .

Na przykład:

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

Dodaj tę @Beankonfigurację do swojej @Configurationklasy, a filtr zostanie zarejestrowany podczas uruchamiania.

Możesz także dodawać serwlety, filtry i detektory za pomocą skanowania ścieżki klas,

Klasy z adnotacjami @WebServlet, @WebFilter i @WebListener mogą być automatycznie rejestrowane w osadzonym kontenerze serwletu poprzez oznaczenie klasy @Configuration za pomocą @ServletComponentScan i określenie pakietów zawierających komponenty, które chcesz zarejestrować. Domyślnie @ServletComponentScan będzie skanować z pakietu klasy z adnotacjami.



7

Jeśli używasz Spring Boot + Spring Security, możesz to zrobić w konfiguracji zabezpieczeń.

W poniższym przykładzie dodałem niestandardowy filtr przed nazwą użytkownika HasłoHuthenticationFilter (zobacz wszystkie domyślne filtry Spring Security i ich kolejność ).

@EnableWebSecurity
class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired FilterDependency filterDependency;

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

I klasa filtrów

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

Za pomocą adnotacji @WebFilter można to zrobić w następujący sposób:

@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
Dodaj również @ServletComponentScan
Justas

5

Mamy mniej więcej cztery różne opcje rejestracji filtra za pomocą Springa .

Po pierwsze możemy stworzyć Spring Bean implementujący Filtr lub rozszerzający 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);
    }
}

Po drugie, możemy utworzyć Spring Bean rozszerzający 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);
    }
}

Alternatywnie możemy użyć klasy 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;
    }
}

I wreszcie możemy użyć @WebFilter adnotacji z @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);
    }
}

Którego filtra użyć i dlaczego?
Pra_A

3

To raczej rada niż odpowiedź, ale jeśli używasz Spring MVC w swojej aplikacji internetowej, dobrym pomysłem jest użycie Spring HandlerInterceptor zamiast Filter

Może wykonywać to samo zadanie, ale także - Może współpracować z ModelAndView - Jego metody można wywoływać przed przetwarzaniem żądania i po nim lub po zakończeniu żądania.
- Można to łatwo przetestować

1 Zaimplementuj interfejs HandlerInterceptor i dodaj adnotację @Component do swojej klasy

@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 Skonfiguruj przechwytywacz

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

}

Prosty i elegancki! Dzięki
MrMins,

3

Ten filtr pomoże również w uzyskaniu dostępu do różnych źródeł

@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

Możesz użyć @WebFilter javax.servlet.annotation.WebFilter na klasie, która implementuje javax.servlet.Filter

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

Następnie użyj @ServletComponentScan, aby się zarejestrować


2

Widziałem tutaj wiele odpowiedzi, ale nie próbowałem żadnej z nich. Właśnie utworzyłem filtr jak w poniższym kodzie.

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

    }
}

I pozostawił pozostałą aplikację Spring Boot taką, jaka była.


2

Potrzebujesz 2 głównych rzeczy: - Dodaj @ServletComponentScando swojej klasy głównej - możesz dodać do niej pakiet o nazwie filtr, tworząc Filterklasę, która ma następujące elementy:

@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

możesz również zrobić filtr za pomocą @WebFilter i implementuje Filtr, to zrobi.

 @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

Filtry, jak sugeruje nazwa, używane do przeprowadzania filtrowania na żądanie do zasobu lub na odpowiedź z zasobu, lub oba. Spring Boot oferuje kilka opcji rejestracji niestandardowych filtrów w aplikacji Spring Boot. Spójrzmy na różne opcje.

1. Zdefiniuj filtr Spring Boot i kolejność wywoływania

Zaimplementuj interfejs Filtr, aby utworzyć nowy filtr w 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
 }
}

Rzućmy okiem na kilka ważnych punktów w powyższym kodzie

  • Filtr zarejestrowany przez adnotację @Component .
  • Aby uruchomić filtry w odpowiedniej kolejności - musieliśmy użyć adnotacji @Order .

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

W powyższym kodzie CustomFirstFilter będzie działał przed CustomSecondFilter.

Im niższa liczba, tym wyższy priorytet

2. Wzorzec adresu URL

Jeśli mapowanie oparte na konwencjach nie jest wystarczająco elastyczne, możemy użyć FilterRegistrationBean do pełnej kontroli aplikacji. W tym przypadku nie używaj adnotacji @Component dla klasy filtra, ale zarejestruj filtr za pomocą 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() {

 }
}

Zarejestruj niestandardowy filtr za pomocą 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... ");
        }

    }

Musisz zaimplementować Filtr i mieć adnotację @WebFilter (urlPatterns = "/ *")

W klasie Application lub Configuration należy dodać @ServletComponentScan. W ten sposób Twój filtr zostanie zarejestrowany.


Dzieje się @WebFiltertak dopiero od Servlet 3.0. Więc może nie działać poprawnie dla 2.5
ha9u63ar

1

Krok 1: Utwórz składnik filtru, wdrażając interfejs filtra.

@Component
public class PerformanceFilter implements Filter {

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

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

}

Krok 2: Ustaw ten filtr na wzorce URI za pomocą FilterRegistrationBean.

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

Możesz skorzystać z tego linku, aby uzyskać kompletną aplikację.


0

Najpierw dodaj @ServletComponentScando swojej klasy SpringBootApplication.

@ServletComponentScan
public class Application {

Po drugie, utwórz plik filtru rozszerzający klasę Filter lub klasę filtrów innej firmy i dodaj @WebFilterdo tego pliku w następujący sposób:

@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

Odpowiedź zobaczyłem @Vasily Komarov. Podobne podejście, ale przy użyciu abstrakcyjnej klasy HandlerInterceptorAdapter zamiast HandlerInterceptor .

Oto przykład...

@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

Jak wszyscy wiecie, Spring Boot to wspaniały sposób na opracowanie aplikacji internetowej lub StandaloneApp przy minimalnej konfiguracji i szczegółowej instalacji.

W ten sposób osiągnąłem Rozwój filtra internetowego w aplikacji Spring Boot

Moja specyfikacja SpringBootApp: -

Wersja Spring Boot: 2.0.4. ZWOLNIENIE
Wersja Java: 8.0
Specyfikacja serwletu: Servlet 3.0 (obowiązkowy i ważny)

Zadeklarowałem mój filtr sieciowy w następujący sposób, zgodnie ze specyfikacją serwletu 3.0

wprowadź opis zdjęcia tutaj Jest to programowy sposób definiowania filtra jako zamiennika definicji opartych na pliku web.xml.

Adnotacja „@Webfilter” zostanie przetworzona przez kontener podczas wdrażania, klasa Filter, w której zostanie znaleziona, zostanie utworzona zgodnie z konfiguracją i zastosowana do wzorców adresów URL javax.servlet.Servlets i javax.servlet.DispatcherTypes.

Aby całkowicie uniknąć Web.xml i osiągnąć WebApp „do wdrożenia”: -

Aby wdrożyć aplikację Spring Boot jako „tradycyjną WAR”, klasa aplikacji powinna rozszerzyć SpringBootServletInitializer.

UWAGA :: SpringBootServletInitializer to „programowa implementacja” pliku web.xml w odniesieniu do specyfikacji Servlet 3.0+, która wymaga implementacji WebApplicationInitializer.

Zatem SpringBootApplication nie wymaga pliku „web.xml”, ponieważ jego klasa aplikacji (po rozszerzeniu SpringBootServletInitializer) skanuje w poszukiwaniu
- @WebFilter,
- @WebListener i
- @WebServlet.

Adnotacja @ServletComponentScan

Ta adnotacja umożliwia skanowanie pakietów podstawowych w poszukiwaniu składników WWW opatrzonych adnotacjami @WebFilter, @WebListener i @WebServlet.

Ze względu na fakt, że osadzone kontenery nie obsługują adnotacji @WebServlet, @WebFilter i @WebListener, Spring Boot, polegając w dużej mierze na osadzonych kontenerach, wprowadził nową adnotację @ServletComponentScan do obsługi niektórych zależnych słoików, które używają tych 3 adnotacji.

Skanowanie jest wykonywane tylko przy użyciu osadzonego kontenera serwletu.

Oto moja definicja klasy aplikacji Spring Boot: -

wprowadź opis zdjęcia tutaj

Niestandardowy inicjator serwletu: -

Tutaj: zdefiniowałem niestandardową klasę: „ServletInitializer”, która rozszerza klasę: SpringBootServletInitializer.

Jak wyjaśniono wcześniej, SpringBootServletInitializer odpowiada za skanowanie adnotacji: -
- @WebFilter,
- @WebListener i
- @WebServlet.

I dlatego klasa aplikacji Spring Boot powinna

  • Albo rozszerz klasę: SpringBootServletInitializer OR
  • expand Klasa niestandardowa, która rozszerza klasę: SpringBootServletInitializer

wprowadź opis zdjęcia tutaj


-6

Filtry są najczęściej używane w plikach rejestratora, różni się w zależności od rejestratora używanego w projekcie Lemme wyjaśnić dla 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>

Filtry służą do ograniczania danych, a ja dodatkowo stosuję filtr progowy w celu ograniczenia poziomów danych w przepływie. Wspomniałem o poziomach, które można tam ograniczyć. Dla dalszego odniesienia patrz kolejność poziomów log4j2 - Poziomy Log4J: WSZYSTKIE> ŚLEDZENIE> DEBUGOWANIE> INFORMACJE> OSTRZEŻENIE> BŁĄD> FATAL> WYŁ.


FilterRegistrationBeanjak wspomniano w pytaniu jest javax.servlet.Filterodpowiedź ta opowiada oorg.apache.logging.log4j.core.Filter
Steve Buzonas
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.