Як додати клас фільтра у Spring Boot?


229

Цікаво, чи є анотація до Filterкласу (для веб-додатків) у Spring Boot? Можливо @Filter?

Я хочу додати у свій проект спеціальний фільтр.

У довідковому посібнику Spring Boot згадувалося про FilterRegistrationBean, але я не впевнений, як ним користуватися.


Зауважте, що фільтр, доданий за допомогою @WebFilter, не поводиться як справжній фільтр у специфікації Servlet. Це буде весняний боб, який називається після багатьох інших ярих бобів і не схожий на справжні фільтри перед будь-яким кодом сервлетів.
lrxw

Ви можете сказати мені точну вимогу. Якщо ви хочете класи фільтрів для ComponentScan, тоді є анотація до цього "@ ComponentScan.Filter"
Keaz

Відповіді:


159

Якщо ви хочете встановити сторонній фільтр, який ви можете використовувати FilterRegistrationBean. Наприклад, еквівалент 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>

Це будуть дві квасолі у вашому @Configurationфайлі

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

Вищезазначене було протестовано за допомогою весняного завантаження 1.2.3


1
Що робити, якщо я хочу додати кілька фільтрів? @Opal
verystrongjoe

8
Просто додайте додатковий @Bean public FilterRegistrationBean додатковийFilterRegistration ()
Хаїм Раман

Як можна знати, в якому порядку застосовуються фільтри?
BeepDog

7
FilterRegistrationBean.setOrder
Хаїм Раман

Під час someFilter()прямого виклику методу вам не потрібен фільтр .
177

117

Ось приклад одного методу включення спеціального фільтра у додаток MVC Spring Boot. Обов'язково включіть пакет у сканування компонентів:

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
Чи повинен фільтр десь бути зареєстрований?
gstackoverflow

1
Коли я спробував такий підхід, Filter був створений як bean і навіть був введений іншому класу, але метод init () не запускався . Ймовірно, init () працює лише в "нормальному" режимі реєстрації, а не на весняному контейнері. Я думаю, можна використовувати PostConstruct замість init (), але я цього не намагався, оскільки відмовився оголошувати Filter як Spring Bean.
Бауржан

Як щодо замовлення фільтрів за допомогою цього підходу?
Павло Власов

Як ми можемо отримати тіло RS від ServletResponse?
user2602807

1
Важливо відзначити, що назва вашої квасолі (на основі назви вашого класу) не повинна відповідати весняній квасолі. Наприклад, ви можете спокуситись створити MetricsFilter, але цей боб буде затьмарений однойменною пружинним приводом. Навчився цього важким шляхом ...
kinbiko

78

Немає спеціальної примітки для позначення фільтра сервлетів. Ви просто оголосите @Beanтип Filter(або FilterRegistrationBean). Приклад (додавання користувацького заголовка до всіх відповідей) - у власному Boot EndpointWebMvcAutoConfiguration ;

Якщо ви лише декларуєте це, Filterвоно буде застосовано до всіх запитів. Якщо ви також додасте a, FilterRegistrationBeanви можете додатково вказати окремі сервлети та шаблони URL для застосування.

Примітка:

Станом на Spring Boot 1.4, FilterRegistrationBeanне застаріла і просто переміщувала пакунки з org.springframework.boot.context.embedded.FilterRegistrationBeanдоorg.springframework.boot.web.servlet.FilterRegistrationBean


Ви б не хотіли сказати мені, як включити відповідний запис у build.gradle? Я додав наступне, але не компілюються: providedCompile ( 'javax.servlet: сервлет-апі: 2,5') у час виконання ( 'javax.servlet: JSTL: 1.1.2')
janetsmith

2
Spring Boot не буде працювати з Servlet 2.5, і поки що насправді не існує великої підтримки JSP. Я насправді не грейдер, тому не знаю, що ви намагаєтесь зробити. Що не так з "компілювати"? Це працює, якщо ви просто залежите від "spring-boot-starter-web"? (Я не думаю, що ці питання пов’язані з оригінальним запитанням, тож, можливо, вам варто знову написати нові запитання?)
Дейв Сіер

Я додав фільтр, реалізуючи інтерфейс Filter, проте Eclipse не в змозі знайти інтерфейс. Тому я намагаюся розібратися, як додати його до classpath для компіляції.
janetsmith

1
Так, звичайно, потрібно мати Filterна своєму класі. Зазвичай я б просто використав, spring-boot-starter-webщоб витягнути всі відповідні залежності (наприклад, тут ).
Дейв Сайер

Як і інші деталі відповідей, ви також можете просто анотувати свій клас Filter за допомогою @Component, і він буде автоматично зареєстрований (для всіх URL-адрес).
Якуб Холі

72

Існує три способи додати ваш фільтр,

  1. Анотувати ваш фільтр одним із весняних стереотипів, таких як @Component
  2. Зареєструвати @Beanз Filterтипом навесні@Configuration
  3. Зареєструвати @Beanз FilterRegistrationBeanтипом навесні@Configuration

Якщо ви хочете, щоб ваш фільтр застосовувався до всіх запитів без налаштування, використовуйте номер 1 або №2, використовуйте номер 3 інакше. Вам не потрібно вказувати сканування компонентів для роботи №1 до тих пір, поки ви кладете фільтр-клас у той самий або підпакет свого SpringApplicationкласу. Для №3 використання поряд з №2 необхідно лише тоді, коли ви хочете, щоб Spring керував своїм класом фільтрів, таким як мати автоматичну провідну залежність. Новий мій фільтр, який не потребує автоматичного підключення / вприскування залежності, працює чудово.

Хоча поєднання №2 та №3 чудово працює, я був здивований, що не закінчуються два фільтри, що застосовуються двічі. Я здогадуюсь, що Весна поєднує дві квасолі як одну, коли вона називає один і той же метод, щоб створити їх обох. Якщо ви хочете використовувати номер 3 наодинці з автовиставкою, ви можете AutowireCapableBeanFactory. Нижче наведено приклад,

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

Відмінна відповідь. Дякуємо за детальну інформацію про всі параметри, а також про те, як зробити автопровід Filterпід час використанняFilterRegistrationBean
sbk

Чудова відповідь. Це саме те, що я виграв !!
haykart

Це також описано тут: baeldung.com/spring-boot-add-filter
Якуб Холі

31

ОНОВЛЕННЯ: 2017-12-16:

Є два простих способи зробити це у Spring Boot 1.5.8.RELEASE, не потрібно XML.

Перший спосіб: Якщо у вас немає шаблону просторових URL-адрес, ви можете використовувати @Component таким чином: (Повний код та деталі можна знайти тут https://www.surasint.com/spring-boot-filter/ )

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

Другий спосіб: якщо ви хочете використовувати URL-адреси шаблонів, ви можете використовувати @WebFilter так: (Повний код та деталі тут https://www.surasint.com/spring-boot-filter-urlpattern/ )

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

Але вам також потрібно додати @ServletComponentScan анотацію у свій клас @SpringBootApplication:

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

Зауважте, що @Component - це анотація Spring, але @WebFilter - ні. @WebFilter - примітка для Servlet 3.

В обох напрямках вам просто потрібна основна залежність Spring Boot у pom.xml (не потрібно явного вбудованого яшми в tomcat)

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

Попередження: Перший спосіб, якщо контролер у Spring Boot повернеться до файлу JSP, запит пройде фільтр двічі.

Хоча, по-другому, запит пройде фільтр лише один раз.

Я вважаю за краще другий спосіб, оскільки він більше схожий на поведінку за замовчуванням у специфікації Servlet ( https://docs.oracle.com/cd/E19879-01/819-3669/6n5sg7b0b/index.html )

Більше журналу тестів ви можете побачити тут https://www.surasint.com/spring-boot-webfilter-instead-of-component/


Я Filterнеодноразово бачив інтерфейс, що дзвонив під час запуску applicationContext. Чи є спосіб виконати його лише один раз?
Pra_A

@PAA ти маєш на увазі мої приклади?
Surasin Tancharoen

20

Ось приклад мого спеціального класу фільтрів:

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

І я додав його до конфігурації завантаження Spring, додавши його до класу Configuration наступним чином:

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

З весняних документів,

Вбудовані контейнери сервлетів - додайте сервер, фільтр чи слухач до програми

Щоб додати сервлет, фільтр або сервлет * Слухач укажіть для нього визначення @Bean .

Наприклад:

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

Додайте цей @Beanконфігурацію до свого @Configurationкласу, і фільтр буде зареєстрований при запуску.

Крім того, ви можете додавати сервлетів, фільтрів і слухачів, використовуючи сканування на класовому шляху,

@WebServlet, @WebFilter та @WebListener анотовані класи можуть бути автоматично зареєстровані вбудованим контейнером сервлетів, анотувавши клас @Configuration з @ServletComponentScan та вказавши пакет (и), що містить компоненти, які потрібно зареєструвати. За замовчуванням @ServletComponentScan буде сканувати з пакета анотованого класу.



7

Якщо ви використовуєте Spring Boot + Spring Security, ви можете це зробити в налаштуваннях безпеки.

У наведеному нижче прикладі я додаю спеціальний фільтр перед UsernamePasswordAuthenticationFilter (див. Усі фільтри Spring Security за замовчуванням та їх порядок ).

@EnableWebSecurity
class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired FilterDependency filterDependency;

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

І клас фільтру

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

За допомогою анотації @WebFilter це можна зробити так:

@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
Також додайте @ServletComponentScan
Justas

5

У нас є приблизно чотири різні варіанти реєстрації фільтра за допомогою Spring .

По-перше, ми можемо створити фільтр, що реалізує весняний боб, або розширити 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);
    }
}

По-друге, ми можемо створити весняний боб, що розширює 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);
    }
}

Крім того, ми можемо використовувати клас 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;
    }
}

І , нарешті , ми можемо використовувати @WebFilter анотацію з @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);
    }
}

Який фільтр використовувати і чому?
Pra_A

3

Це скоріше порада, ніж відповідь, але якщо ви використовуєте Spring MVC у своєму веб-додатку, хороша ідея - використовувати Spring HandlerInterceptor замість фільтру

Він може виконувати ту саму роботу, але також - Може працювати з ModelAndView - Його методи можна викликати до та після обробки запиту або після завершення запиту.
- Це можна легко перевірити

1 Реалізуйте інтерфейс HandlerInterceptor і додайте до свого класу анотацію @Component

@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 Налаштуйте перехоплювач

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

}

Просто і елегантно! Спасибі
MrMins

3

Цей фільтр також допоможе вам надати доступ до перехресного походження

@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

Ви можете використовувати @WebFilter javax.servlet.annotation.WebFilter для класу, який реалізує javax.servlet.Filter

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

Потім використовуйте @ServletComponentScan для реєстрації


2

Тут я побачив багато відповідей, але жодної з них не спробував. Я тільки що створив фільтр, як у наведеному нижче коді.

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

    }
}

І залишив залишився додаток Spring Boot таким, яким він був.


2

Вам потрібні 2 основні речі: - Додайте @ServletComponentScanдо свого основного класу - ви можете додати в нього пакет з назвою фільтр, ви створите Filterклас, який має наступне:

@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

Ви також можете зробити фільтр, використовуючи @WebFilter та реалізуючи Filter, це зробить.

 @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

Фільтри як назва пропонують використовувати для фільтрації або за запитом до ресурсу, або за відповіддю з ресурсу, або обом. Spring Boot надає декілька варіантів реєстрації спеціальних фільтрів у додатку Spring Boot. Давайте розглянемо різні варіанти.

1. Визначте фільтр весняного завантаження та порядок виклику

Реалізуйте інтерфейс фільтра для створення нового фільтра у 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
 }
}

Давайте швидко розглянемо деякі важливі моменти у наведеному вище коді

  • Фільтр зареєстровано за допомогою анотації @Component .
  • Щоб запустити фільтри в потрібному порядку - нам потрібно було використовувати анотацію @Order .

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

У наведеному вище коді CustomFirstFilter запускатиметься перед CustomSecondFilter.

Чим менше число, тим вище пріоритет

2. Шаблон URL-адреси

Якщо відображення на основі конвенції не є досить гнучким, ми можемо використовувати FilterRegistrationBean для повного контролю над додатком. Тут не використовуйте анотацію @Component для класу фільтрів, а зареєструйте фільтр за допомогою 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() {

 }
}

Зареєструйте спеціальний фільтр за допомогою 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... ");
        }

    }

Вам потрібно реалізувати фільтр і його потрібно позначати за допомогою @WebFilter (urlPatterns = "/ *")

І до класу Application або Configuration вам потрібно додати @ServletComponentScan. Цим самим ваш фільтр буде зареєстрований.


Це @WebFilterлише з Servlet 3.0. Таким чином, це може не працювати належним чином для 2,5
ha9u63ar

1

Крок 1: Створіть компонент фільтра, застосувавши інтерфейс Filter.

@Component
public class PerformanceFilter implements Filter {

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

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

}

Крок 2: Установіть цей фільтр на шаблони uri, використовуючи FilterRegistrationBean.

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

Ви можете посилатися на це посилання для повного застосування.


0

Спочатку додайте @ServletComponentScanдо свого класу SpringBootApplication.

@ServletComponentScan
public class Application {

По-друге, створіть фільтр-файл, що розширює фільтр або сторонній клас фільтру, і додайте @WebFilterдо цього файлу так:

@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

Я побачив відповідь від @Vasily Komarov. Аналогічний підхід, але використовуючи абстрактний клас HandlerInterceptorAdapter замість HandlerInterceptor .

Ось приклад ...

@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

Як ви всі знаєте, Spring Boot - це чудовий спосіб розробки WebApp або StandaloneApp з мінімальною конфігурацією та висловлюваною настройкою.

Ось так я домігся розробки веб-фільтра у додатку Spring Boot

Мої характеристики SpringBootApp: -

Версія весняного завантаження: 2.0.4.РЕЛІЗА
Версія Java: 8.0
Специфікація сервлета: Сервлет 3.0 (обов'язковий та важливий)

Я оголосив свій веб-фільтр наступним чином, дотримуючись сервісних специфікацій 3.0

введіть тут опис зображення Це програмний спосіб визначення фільтра як заміни визначень на основі web.xml.

Анотація "@Webfilter" буде оброблена контейнером під час розгортання, клас фільтру, в якому він знайдеться, буде створений відповідно до конфігурації та застосований до шаблонів URL-адрес, javax.servlet.Servlets та javax.servlet.DispatcherTypes.

Щоб повністю уникнути Web.xml та досягти "розгортаного" WebApp: -

Щоб розгорнути програму Spring Boot як "традиційну війну", клас додатків повинен поширити SpringBootServletInitializer.

ПРИМІТКА: SpringBootServletInitializer - це "Програмна реалізація" web.xml з посиланням на специфікації Servlet 3.0+, що вимагає реалізації WebApplicationInitializer.

Таким чином, SpringBootApplication не вимагає "web.xml", оскільки його клас додатків (після розширення SpringBootServletInitializer) сканує
- @WebFilter,
- @WebListener та
- @WebServlet.

Анотація @ServletComponentScan

Ця анотація дозволяє сканувати базові пакети для веб-компонентів, помічених за допомогою @WebFilter, @WebListener та @WebServlet.

Через те, що вбудовані контейнери не підтримують анотації @WebServlet, @WebFilter та @WebListener, Spring Boot, значною мірою покладаючись на вбудовані контейнери, представив цю нову анотацію @ServletComponentScan для підтримки деяких залежних баночок, які використовують ці 3 анотації.

Сканування виконується лише при використанні вбудованого контейнера сервлетів.

Далі йде визначення мого додатка Spring Boot:

введіть тут опис зображення

Спеціальний ініціалізатор сервлетів: -

Тут я визначив спеціальний клас: "ServletInitializer", який розширює клас: SpringBootServletInitializer.

Як було пояснено раніше, SpringBootServletInitializer відповідає за сканування приміток: -
- @WebFilter,
- @WebListener та
- @WebServlet.

А значить, Клас застосування Весняного завантаження повинен

  • Або розширіть клас: SpringBootServletInitializer АБО
  • розширити Спеціальний клас, який розширює клас: SpringBootServletInitializer

введіть тут опис зображення


-6

Фільтри в основному використовуються у файлах реєстратора, він змінюється залежно від реєстратора, який ви використовуєте в проекті Lemme Пояснення для 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>

Фільтри використовуються для обмеження даних, і я використовував пороговий фільтр додатково для обмеження рівнів даних у потоці. Я згадав про рівні, які там можуть бути обмежені. Для подальшої уваги дивіться порядок рівнів log4j2 - Log4J Рівні: ALL> TRACE> DEBUG> INFO> WARN> ERROR> FATAL> OFF


FilterRegistrationBeanяк згадується в запитанні javax.servlet.Filter, ця відповідь говорить проorg.apache.logging.log4j.core.Filter
Стів Бузонас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.