首页 文章

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

提问于
浏览
171

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

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

The Spring Boot Reference Guide提及 FilterRegistrationBean ,但我不确定如何使用它 .

17 回答

  • 101

    UPDATE: 2017-12-16:

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

    First way: 如果您没有任何空间网址模式,可以像这样使用@Component :(完整代码和详细信息在这里https://www.surasint.com/spring-boot-filter/

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

    Second way: 如果你想使用url模式,可以像这样使用@WebFilter :(完整代码和详细信息在这里https://www.surasint.com/spring-boot-filter-urlpattern/

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

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

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

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

    两种方式,你只需要在pom.xml中基本的spring boot依赖(不需要显式的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>
    

    WARNING: 第一种方法,如果Spring引导中的Controller返回到jsp文件,请求将通过过滤器两次 .

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

    我更喜欢第二种方式,因为它更类似于Servlet规范中的默认行为(https://docs.oracle.com/cd/E19879-01/819-3669/6n5sg7b0b/index.html

    你可以在这里看到更多测试日志https://www.surasint.com/spring-boot-webfilter-instead-of-component/

  • 66

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

  • 1

    没有特殊的注释来表示servlet过滤器 . 您只需声明 Filter 类型 Filter (或 FilterRegistrationBean ) . 一个示例(向所有响应添加自定义标头)在Boot自己的_369485中;

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

    Note:

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

  • 124

    首先,将 @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{
    
  • 13

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

    在下面的示例中,我在UsernamePasswordAuthenticationFilter之前添加了一个自定义过滤器(请参阅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);
        }
    }
    

    和过滤器类

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

    使用@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
    
        }
    
    }
    
  • 0

    以下是我的自定义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);
        }
    }
    

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

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

    您可以在实现javax.servlet.Filter的类上使用@WebFilter javax.servlet.annotation.WebFilter

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

    然后使用@ServletComponentScan进行注册

  • 57

    它更多的是建议而非答案,但如果您在Web应用程序中使用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");
        }
    
    }
    
  • 13

    您也可以使用@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();
            }   
        }
    
  • 8

    添加过滤器有三种方法,

    • 使用其中一个Spring构造型注释您的过滤器,例如 @Component

    • 在Spring @Configuration 中使用 Filter 类型注册 @Bean

    • 在Spring中注册 @BeanFilterRegistrationBean 类型 @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;
        }
    
  • 0

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

    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应用程序 .

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

    过滤器主要用于 Logger 文件,它根据您在项目中使用的 Logger 而变化Lemme explain for 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

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

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

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

  • 17

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

    来自Spring docs,

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

    添加Servlet,Filter或Servlet * Listener为其提供@Bean定义 .

    例如:

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

    将此 @Bean 配置添加到 @Configuration 类,并在启动时注册过滤器 .

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

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

相关问题