如何在Spring Boot中添加过滤器类?

问题描述 投票:190回答:19

我想知道,如果Spring Boot中的Filter类(用于Web应用程序)有任何注释?也许@Filter

我想在我的项目中添加自定义过滤器。

The Spring Boot Reference Guide提到了FilterRegistrationBean,但我不确定如何使用它。

java configuration spring-boot servlet-filters
19个回答
137
投票

如果要设置第三方过滤器,可以使用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

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

以上是用spring-boot 1.2.3测试的


2
投票

您可以在实现javax.servlet.Filter的类上使用@WebFilter javax.servlet.annotation.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

    }

}

然后使用@ServletComponentScan进行注册


2
投票

我在这里看到了很多答案,但我没有尝试过任何一个。我刚刚创建了过滤器,如下面的代码所示。

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

然后留下剩余的Spring Boot应用程序。


2
投票

这是一个建议而不是答案,但如果您在Web应用程序中使用Spring MVC,最好使用Spring HandlerInterceptor而不是Filter

它可以完成相同的工作,但也可以 - 使用ModelAndView - 可以在请求处理之前和之后,或在请求完成之后调用其方法。 - 它可以很容易地测试

1实现HandlerInterceptor接口并向您的类添加@Component注释

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

    }
}

2配置拦截器

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

    }
}

1
投票

您也可以使用@WebFilter制作过滤器并实现Filter,它会做。

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

}

1
投票

名称过滤器用于对资源请求或资源响应(或两者)执行过滤。 Spring Boot提供了很少的选项来在Spring Boot应用程序中注册自定义过滤器。我们来看看不同的选项。

1.定义Spring Boot Filter和Invocation Order

实现Filter接口以在Spring Boot中创建新过滤器。

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

让我们快速查看上面代码中的一些重点

  • 由@Component注释注册的过滤器。
  • 要按正确的顺序触发过滤器,我们需要使用@Order注释。 @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 } }

在上面的代码中,CustomFirstFilter将在CustomSecondFilter之前运行。

数字越低,优先级越高

2.网址格式

如果基于约定的映射不够灵活,我们可以使用FilterRegistrationBean来完全控制应用程序。在这里,不要对过滤器类使用@Component注释,而是使用FilterRegistrationBean注册过滤器。

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

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

}

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

 }
}

0
投票

首先,将@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; } } 添加到SpringBootApplication类中。

@ServletComponentScan

其次,创建一个扩展Filter或第三方过滤器类的过滤器文件,并将@ServletComponentScan public class Application { 添加到此文件中,如下所示:

@WebFilter

0
投票
@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{

您需要实现Filter并需要使用@WebFilter注释(urlPatterns =“/ *”)

在Application或Configuration类中,您需要添加@ServletComponentScan,这样您的过滤器就会被注册。


0
投票

我看到了@Vasily Komarov的回答。类似的方法,但使用抽象的HandlerInterceptorAdapter类而不是使用HandlerInterceptor。

这是一个例子......

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

}

0
投票

众所周知,Spring Boot是一种开发Web应用程序或独立应用程序的绝佳方式,只需最少的配置和自定义设置。

这就是我在Spring Boot应用程序中实现Web过滤器开发的方法

我的SpringBootApp规格: -

Spring Boot版本:2.0.4.RELEASE Java版本:8.0 Servlet规范:Servlet 3.0(强制性和重要性)

我按照以下方式声明了我的Web过滤器,遵守Servlet规范3.0

@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 ); } } 这是将Filter定义为基于web.xml的定义的替代的编程方式。

在部署期间,容器将处理“@Webfilter”注释,将根据配置创建找到它的Filter类,并将其应用于URL模式javax.servlet.Servlets和javax.servlet.DispatcherTypes。

完全避免Web.xml并实现“可部署”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注释的Web组件的基本包。

由于嵌入式容器不支持@WebServlet,@ WebFilter和@WebListener注释,Spring Boot非常依赖嵌入式容器,因此引入了这个新的注释@ServletComponentScan来支持一些使用这3个注释的依赖jar。

仅在使用嵌入式Servlet容器时执行扫描。

以下是我的Spring Boot应用程序类定义: -

enter image description here

自定义Servlet初始化程序: -

这里:我定义了一个自定义类:“ServletInitializer”,它扩展了Class:SpringBootServletInitializer。

如前所述,SpringBootServletInitializer负责扫描注释: - - @WebFilter, - @WebListener和 - @WebServlet。

因此Spring Boot应用程序类应该

  • 扩展类:SpringBootServletInitializer OR
  • 扩展类,它扩展了类:SpringBootServletInitializer

enter image description here


-5
投票

过滤器主要用于记录器文件,它根据您在项目中使用的记录器而变化Lemme explain for log4j2:

enter image description here

过滤器用于限制数据,我进一步使用阈值过滤器来限制流程中的数据级别,我提到了那里可以限制的级别。为了进一步参考,请参阅log4j2的级别顺序 - Log4J级别:ALL> TRACE> DEBUG> INFO> WARN> ERROR> FATAL> OFF


107
投票

以下是在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 {}

}

71
投票

没有特殊的注释来表示servlet过滤器。你只需要声明@Bean(或Filter)类型的FilterRegistrationBean。一个例子(为所有响应添加自定义标头)在Boot自己的EndpointWebMvcAutoConfiguration中;

如果您只声明Filter,它将应用于所有请求。如果还添加了FilterRegistrationBean,则还可以指定要应用的各个servlet和url模式。

注意:

从Spring Boot 1.4开始,FilterRegistrationBean不被弃用,只是将包从org.springframework.boot.context.embedded.FilterRegistrationBean移到org.springframework.boot.web.servlet.FilterRegistrationBean


65
投票

添加过滤器有三种方法,

  1. 使用诸如@Component之类的Spring构造型注释您的过滤器
  2. 在Spring @Bean注册Filter@Configuration类型
  3. 在Spring @Bean注册FilterRegistrationBean@Configuration类型

如果您希望过滤器适用于所有请求而无需自定义,则#1或#2将执行,否则使用#3。只要将过滤器类放在SpringApplication类的相同或子包中,就不需要为#1指定组件扫描。对于#3,只有当您希望Spring管理您的过滤器类(例如具有自动连线依赖性)时,才需要与#2一起使用。它对我来说很好,新的我的过滤器不需要任何依赖自动装配/注入。

虽然结合#2和#3工作正常,但我很惊讶它最终没有两个过滤器应用两次。我的猜测是,当它调用相同的方法来创建它们时,Spring将两个bean组合为一个。如果你想单独使用#3和authowiring,你可以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;
    }

23
投票

更新时间:2017-12-16:

在Spring Boot 1.5.8.RELEASE中有两种简单的方法可以做到这一点,不需要XML。

第一种方式:如果你没有任何特定的URL模式,你可以像这样使用@Component :(完整的代码和详细信息在这里qazxsw poi)

https://www.surasint.com/spring-boot-filter/

第二种方式:如果你想使用url模式,可以像这样使用@WebFilter :(完整代码和详细信息在这里@Component public class ExampleFilter implements Filter{ ... }

https://www.surasint.com/spring-boot-filter-urlpattern/

但是您还需要在@SpringBootApplication类中添加@ServletComponentScan注释:

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

请注意,@ Component是Spring的注释,但@WebFilter不是。 @WebFilter是Servlet 3注释。

两种方式,你只需要在pom.xml中基本的Spring Boot依赖(不需要显式的tomcat嵌入式jasper)

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

警告:第一种方法,如果Spring Boot中的Controller返回JSP文件,请求将通过过滤器两次。

而在第二种方式中,请求将仅通过过滤器一次。

我更喜欢第二种方式,因为它更类似于Servlet规范中的默认行为( <?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>

你可以在这里看到更多测试日志https://docs.oracle.com/cd/E19879-01/819-3669/6n5sg7b0b/index.html


18
投票

以下是我的自定义Filter类的示例:

https://www.surasint.com/spring-boot-webfilter-instead-of-component/

我通过将它添加到Configuration类将其添加到Spring启动配置中,如下所示:

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

14
投票

来自Spring docs,

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

添加Servlet,Filter或Servlet * Listener为它提供@Bean定义。

例如:

Embedded servlet containers - Add a Servlet, Filter or Listener to an application

将此@Bean public Filter compressFilter() { CompressingFilter compressFilter = new CompressingFilter(); return compressFilter; } 配置添加到您的@Bean类,过滤器将在启动时注册。

您还可以使用类路径扫描添加Servlet,过滤器和监听器,

通过使用@ServletComponentScan注释@Configuration类并指定包含要注册的组件的包,可以使用嵌入式servlet容器自动注册@WebServlet,@ WebFilter和@WebListener注释类。默认情况下,@ ServletComponentScan将从带注释的类的包中进行扫描。


7
投票

如果使用Spring Boot + Spring Security,则可以在安全配置中执行此操作。

在下面的示例中,我在UsernamePasswordAuthenticationFilter之前添加了一个自定义过滤器(请参阅@Configuration)。

all the default Spring Security filters and their order

和过滤器类

@EnableWebSecurity
class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired FilterDependency filterDependency;

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

5
投票

使用@WebFilter注释,可以按如下方式完成:

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);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.