Как добавить класс фильтра в Spring Boot?

229

Интересно, есть ли какая-нибудь аннотация для Filterкласса (для веб-приложений) в Spring Boot? Возможно @Filter?

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

Упоминалось о справочном руководстве по Spring BootFilterRegistrationBean , но я не уверен, как его использовать.

janetsmith
источник
Обратите внимание, что фильтр, добавленный с помощью @WebFilter, не работает как настоящий фильтр в спецификации сервлета. Это будет пружинный бин, вызываемый многими другими весенними бобами и не похожий на настоящие фильтры перед любым кодом сервлета.
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
Что делать, если я хочу добавить несколько фильтров? @ Опал
verystrongjoe
8
Просто добавьте дополнительный @Bean public FilterRegistrationBean AdditionalFilterRegistration ()
Хаим Раман
Как узнать, в каком порядке применяются фильтры?
BeepDog
7
FilterRegistrationBean.setOrder
Хаим Раман
Вам не нужен фильтр bean, когда вы вызываете метод someFilter()напрямую.
WST
117

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

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

}
tegatai
источник
4
Должен ли фильтр где-нибудь быть зарегистрирован?
gstackoverflow
1
Когда я попробовал этот подход, Filter был создан как bean-компонент и даже был внедрен в другой класс, но метод init () не запустился . Вероятно, init () работает только в «нормальной» регистрации, а не в контейнере Spring. Я думаю, что можно использовать PostConstruct вместо init (), но я не пробовал этого, так как отказался объявить Filter как Spring bean.
Бауржан
Как насчет упорядочения фильтров с использованием этого подхода?
Павел Власов
Как мы можем получить тело RS от ServletResponse?
user2602807
1
Важно отметить, что имя вашего компонента (в зависимости от имени вашего класса) не должно совпадать с именем bean-компонента Spring. Например, у вас может возникнуть желание создать объект MetricsFilter, но этот компонент будет затенен компонентом исполнительного элемента Spring с тем же именем. Научился этому нелегкому пути ...
Кинбико
78

Специальной аннотации для обозначения фильтра сервлетов не существует. Вы просто объявляете @Beanтип Filter(или FilterRegistrationBean). Пример (добавление настраиваемого заголовка ко всем ответам) приведен в собственной загрузочной EndpointWebMvcAutoConfiguration ;

Если вы только объявите, Filterон будет применен ко всем запросам. Если вы также добавите a, FilterRegistrationBeanвы можете дополнительно указать отдельные сервлеты и шаблоны URL для применения.

Примечание:

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

Дейв Сайер
источник
Не могли бы вы рассказать мне, как включить соответствующую запись в build.gradle? Я добавил следующее, но оно не скомпилировано: обеспечено время компиляции ('javax.servlet: servlet-api: 2.5') ('javax.servlet: jstl: 1.1.2')
janetsmith
2
Spring Boot не будет работать с Servlet 2.5, а поддержка JSP пока не очень развита. Я на самом деле не грейдер, поэтому я не знаю, что вы пытаетесь сделать. Что не так с "компиляцией"? Это работает, если вы просто зависите от "spring-boot-starter-web"? (Я не думаю, что эти вопросы связаны с первоначальным вопросом, так что, может быть, вы должны опубликовать снова с новыми вопросами?)
Дейв Сайер
Я добавил фильтр, реализовав интерфейс фильтра, однако Eclipse не может найти интерфейс. Поэтому я пытаюсь выяснить, как добавить его в classpath для компиляции.
janetsmith
1
Да, конечно, вы должны иметь Filterна своем classpath. Обычно я просто использовал бы spring-boot-starter-webдля извлечения всех соответствующих зависимостей (например, здесь ).
Дейв Сайер
Как подробно описано в других ответах, вы также можете просто аннотировать класс Filter с помощью @Component, и он будет автоматически зарегистрирован (для всех URL-адресов).
Якуб Холи
72

Есть три способа добавить свой фильтр,

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

Либо # 1 или # 2 подойдет, если вы хотите, чтобы ваш фильтр применялся ко всем запросам без настройки, используйте № 3 в противном случае. Вам не нужно указывать компонентное сканирование для # 1, чтобы работать, пока вы помещаете свой класс фильтра в тот же или вложенный пакет вашегоSpringApplication класса. Для # 3 использование вместе с # 2 необходимо только в том случае, если вы хотите, чтобы Spring управлял вашим классом фильтра, таким как наличие автоматических проводных зависимостей. Это прекрасно работает для меня, чтобы новый мой фильтр, который не нуждается в автопроводке / инжекции зависимостей.

Хотя объединение № 2 и № 3 работает нормально, я был удивлен, что в итоге два фильтра не применяются дважды. Я предполагаю, что Spring объединяет два bean-компонента как один, когда вызывает один и тот же метод для создания их обоих. Если вы хотите использовать # 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;
    }
barryku
источник
Отличный ответ. Спасибо за детализацию всех опций, а также за то, как выполнить автоматическое подключение 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 (нет необходимости в явном встроенном в tascat 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>

ПРЕДУПРЕЖДЕНИЕ: Во-первых, если контроллер в Spring Boot возвращается в файл JSP, запрос дважды проходит фильтр.

Хотя, во-вторых, запрос пройдет фильтр только один раз.

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

Вы можете увидеть больше журнала испытаний здесь https://www.surasint.com/spring-boot-webfilter-instead-of-component/

Surasin Tancharoen
источник
Я видел, как Filterинтерфейс вызывался много раз во время запуска applicationContext. Есть ли способ выполнить его только один раз?
Pra_A
@ PAA ты имеешь ввиду из моих примеров?
Surasin Tancharoen
20

Вот пример моего пользовательского класса 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);
    }
}

И я добавил его в конфигурацию загрузки 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;
    }
}
DPancs
источник
14

Из весенних документов,

Встроенные контейнеры сервлетов - добавление сервлета, фильтра или прослушивателя в приложение

Чтобы добавить Servlet, Filter или Servlet * Listener, предоставьте для него определение @Bean .

Например:

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

Добавьте этот @Beanконфиг в ваш @Configurationкласс, и фильтр будет зарегистрирован при запуске.

Также вы можете добавлять сервлеты, фильтры и прослушиватели, используя сканирование пути к классам,

Аннотированные классы @WebServlet, @WebFilter и @WebListener можно автоматически регистрировать во встроенном контейнере сервлетов, пометив класс @Configuration с помощью @ServletComponentScan и указав пакет (ы), содержащий компоненты, которые вы хотите зарегистрировать. По умолчанию @ServletComponentScan будет сканировать из пакета аннотированного класса.

Счастливый
источник
docs.spring.io/spring-boot/docs/current/reference/html/… не работал для меня, но docs.spring.io/spring-boot/docs/1.5.8.RELEASE/reference/html/… работал для меня.
user674669
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

    }

}
KayV
источник
3
Также добавьте @ServletComponentScan
Юстас
5

У нас есть примерно четыре различных варианта регистрации фильтра с помощью Spring .

Во-первых, мы можем создать bean-компонент Spring, реализующий Filter или расширяющий 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);
    }
}

Во-вторых, мы можем создать бин Spring, расширяющий 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);
    }
}
isaolmez
источник
Какой фильтр использовать и почему?
Pra_A
3

Это скорее совет, чем ответ, но если вы используете Spring MVC в своем веб-приложении, хорошая идея - использовать Spring HandlerInterceptor вместо Filter

Он может выполнять ту же работу, но также - Может работать с 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 для регистрации

Cwrwhaf
источник
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 внутри него, вы создаете 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 и реализовать фильтр, это будет делать.

 @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. Определите весенний загрузочный фильтр и порядок вызова

Внедрите интерфейс Filter для создания нового фильтра в 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;
 }
}
Yogesh
источник
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. Создайте компонент фильтра с помощью интерфейса фильтра.

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

Во-вторых, создайте файл фильтра, расширяющий класс Filter или сторонний класс фильтра, и добавьте @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{
oaoit
источник
0

Я видел ответ от Василия Комарова. Аналогичный подход, но с использованием абстрактного класса 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.

My SpringBootApp Технические характеристики: -

Версия Spring Boot: 2.0.4.RELEASE
Версия Java: 8.0
Servlet Спецификация: Servlet 3.0 (обязательно и важно)

Я объявил свой веб-фильтр следующим образом, придерживаясь спецификаций сервлета 3.0

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

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

Чтобы полностью избежать Web.xml и добиться «Deployable» WebApp: -

Чтобы развернуть Spring Boot Application как «Традиционную WAR», класс приложения должен расширять SpringBootServletInitializer.

ПРИМЕЧАНИЕ :: SpringBootServletInitializer - это «программная реализация» файла web.xml со ссылкой на спецификации Servlet 3.0+, для которых требуется реализация WebApplicationInitializer.

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

Аннотация @ServletComponentScan

Эта аннотация позволяет сканировать базовые пакеты для веб-компонентов, аннотированных @WebFilter, @WebListener и @WebServlet.

В связи с тем, что встроенные контейнеры не поддерживают аннотации @WebServlet, @WebFilter и @WebListener, Spring Boot, в значительной степени опираясь на встроенные контейнеры, представил эту новую аннотацию @ServletComponentScan для поддержки некоторых зависимых jar-файлов, которые используют эти 3 аннотации.

Сканирование выполняется только при использовании встроенного контейнера сервлетов.

Ниже приведено определение класса приложения Spring Boot: -

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

Пользовательский инициализатор сервлета: -

Здесь: я определил пользовательский класс: «ServletInitializer», который расширяет класс: SpringBootServletInitializer.

Как объяснялось ранее, SpringBootServletInitializer отвечает за сканирование аннотаций:
- @WebFilter,
@WebListener и
- @WebServlet.

И, следовательно, класс приложения Spring Boot должен

  • Либо расширить класс: 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 Levels: ALL> TRACE> DEBUG> INFO> WARN> ERROR> FATAL> OFF

Saravanan
источник
FilterRegistrationBeanкак уже упоминалось в вопросе javax.servlet.Filter, этот ответ говорит оorg.apache.logging.log4j.core.Filter
Стив Buzonas