【问题标题】:How can I add a filter class in Spring Boot?如何在 Spring Boot 中添加过滤器类?
【发布时间】:2013-11-18 12:12:12
【问题描述】:

Spring Boot 中的 Filter 类(用于 Web 应用程序)是否有任何注释?也许@Filter

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

The Spring Boot Reference Guide提到过 FilterRegistrationBean,但是不知道怎么用。

【问题讨论】:

  • 请注意,使用@WebFilter 添加的过滤器的行为与 Servlet 规范中的真实过滤器不同。它将是一个在许多其他 spring bean 之后调用的 spring bean,而不像任何 servlet 代码之前的真正过滤器。
  • 你能告诉我你的确切要求吗?如果您想要 ComponentScan 的过滤器类,那么“@ComponentScan.Filter”有一个注释
  • 你应该写更多细节,我们有不同类型的过滤器,例如:请求过滤器,客户端过滤器从列表中过滤等等

标签: java configuration spring-boot servlet-filters


【解决方案1】:

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

【讨论】:

  • 如果我想添加多个过滤器怎么办? @Opal
  • 只需添加一个额外的@Bean public FilterRegistrationBean additionalFilterRegistration()
  • FilterRegistrationBean.setOrder
  • 样本错过了@BeansomeFilter()
  • Filter 在什么包中?我看到了超过 24 种可能的匹配。也许包括一个导入语句 sn-p。
【解决方案2】:

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

}

【讨论】:

  • 过滤器应该在某处注册吗?
  • 当我尝试这种方法时,Filter 被创建为 bean,甚至被注入到其他类 但 init() 方法没有运行。可能, init() 仅适用于“正常”注册而不是弹簧容器。我认为,可以使用 PostConstruct 而不是 init() 但我没有尝试过,因为我拒绝将 Filter 声明为 Spring bean。
  • 使用这种方法的过滤器排序怎么样?
  • 我们如何从 ServletResponse 中获取 RS 正文?
  • 要注意的重要一点是,您的 bean 的名称(基于您的类名)不应与 Spring bean 相同。例如,您可能想创建一个MetricsFilter,但是这个bean 将被同名的Spring 执行器bean 所掩盖。学到了很多东西...
【解决方案3】:

可以通过三种方式添加过滤器,

  1. 使用 Spring 原型之一注释您的过滤器,例如 @Component
  2. 注册@BeanFilter 输入Spring @Configuration
  3. 注册@BeanFilterRegistrationBean 输入Spring @Configuration

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

虽然将 #2 和 #3 结合起来效果很好,但我很惊讶它并没有以两个过滤器应用两次而告终。我的猜测是,当 Spring 调用相同的方法来创建这两个 bean 时,它会将这两个 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;
    }

【讨论】:

  • 优秀的答案。感谢您详细介绍所有选项,并介绍如何在使用 FilterRegistrationBean 时自动连接您的 Filter
  • 很好的答案。这正是我所习惯的!
【解决方案4】:

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

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

注意:

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

【讨论】:

  • 您介意告诉我如何在 build.gradle 中包含相应的条目吗?我添加了以下内容,但没有编译:providedCompile('javax.servlet:servlet-api:2.5') runtime('javax.servlet:jstl:1.1.2')
  • Spring Boot 不能与 Servlet 2.5 一起工作,而且对 JSP 的支持还不是很多。我不是一个真正的毕业生,所以我不知道你想做什么。 “编译”有什么问题?如果您只依赖“spring-boot-starter-web”,它是否有效? (不过,我认为这些问题与原始问题无关,所以也许您应该再次发布新问题?)
  • 我通过实现Filter接口添加了一个过滤器,但是Eclipse无法找到该接口。所以我想弄清楚如何将它添加到类路径中进行编译。
  • 是的,当然你需要在你的类路径中有Filter。通常我只会使用spring-boot-starter-web 来提取所有相关的依赖项(例如here)。
  • 作为其他响应细节,您也可以使用 @Component 注释您的 Filter 类,它将自动注册(适用于所有 URL)。
【解决方案5】:

更新: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 {
    ...
}

但是你还需要在你的@SpringBootApplication 类中添加@ServletComponentScan 注解:

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

注意@Component 是Spring 的注解,但@WebFilter 不是。 @WebFilter 是 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>

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

而第二种方式,请求只会通过一次过滤器。

我更喜欢第二种方式,因为它更类似于the Servlet specification 中的默认行为。

您可以在此处查看更多测试日志:https://www.surasint.com/spring-boot-webfilter-instead-of-component/

【讨论】:

  • 我看到Filter 接口在applicationContext 启动期间被多次调用。有没有办法只执行一次?
  • @PAA 你的意思是我的例子?
  • @Surasin :您博客上的精彩文章。问题 - 不是 \@ServletComponentScan,而是在过滤器类中提及 \@ComponentScan 以及 \@WebFilter 是否足以让 Spring App 上下文拾取它?
  • 所有 www.surasint.com 链接都已损坏(“嗯。我们找不到那个站点。我们可以'不连接到 www.surasint.com 上的服务器。").
  • @PeterMortensen 它已经消失了。 Gcloud 已经彻底摧毁了它。而且我在任何地方都没有备份 T-T
【解决方案6】:

这是我的自定义过滤器类的示例:

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 Boot 配置中,如下所示:

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

【讨论】:

    【解决方案7】:

    来自 Spring 文档,

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

    要添加 Servlet、过滤器或 Servlet *Listener,请提供 @Bean 它的定义。

    例如:

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

    将此@Bean 配置添加到您的@Configuration 类中,过滤器将在启动时注册。

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

    @WebServlet、@WebFilter 和@WebListener 注解的类可以是 通过以下方式自动注册到嵌入式 servlet 容器 使用 @ServletComponentScan 注释 @Configuration 类和 指定包含您想要的组件的包 登记。默认情况下,@ServletComponentScan 将从包中扫描 带注释的类。

    【解决方案8】:

    对于register a filter using Spring,我们大致有四种不同的选择。

    首先,我们可以创建一个 Spring bean 实现 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);
        }
    }
    

    其次,我们可以创建一个扩展GenericFilterBean的Spring bean:

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

    【讨论】:

    • 使用哪个过滤器以及为什么?
    【解决方案9】:

    如果你使用 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);
        }
    }
    

    【讨论】:

      【解决方案10】:

      使用@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
      【解决方案11】:

      此过滤器还将帮助您允许跨域访问

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

      【讨论】:

        【解决方案12】:

        与其说是答案,不如说是建议,但如果您在 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】:

        你需要两个主要的东西:

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

        【讨论】:

          【解决方案14】:

          第一步:通过实现Filter接口创建一个过滤器组件。

          @Component
          public class PerformanceFilter implements Filter {
          
              @Override
              public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                      throws IOException, ServletException {
          
                  ...
                  ...
              }
          
          }
          

          第 2 步:使用 FilterRegistrationBean 将此过滤器设置为 URI 模式。

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

          完整的申请可以参考this link

          【讨论】:

            【解决方案15】:

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

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

            然后使用@ServletComponentScan 进行注册。

            【讨论】:

              【解决方案16】:

              我在这里看到了很多答案,但我没有尝试任何一个。我刚刚按照以下代码创建了过滤器。

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

              【讨论】:

                【解决方案17】:

                用途:

                @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 仅从 Servlet 3.0 开始。所以它可能不适用于 2.5
                【解决方案18】:

                您还可以通过使用@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();
                    }
                }
                

                【讨论】:

                  【解决方案19】:

                  我看到了答案by 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 );
                      }
                  
                  }
                  

                  【讨论】:

                    【解决方案20】:

                    过滤器,顾名思义,用于过滤对资源的请求或来自资源的响应,或两者兼而有之。 Spring Boot 提供了一些选项来在 Spring Boot 应用程序中注册自定义过滤器。让我们看看不同的选项。

                    1.定义 Spring Boot 过滤器和调用顺序

                    实现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/2018
                        }
                    }
                    

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

                    • @Component注解注册的过滤器。

                    • 要以正确的顺序触发过滤器,我们需要使用 @Order 注释。

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

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

                    数字越小,优先级越高

                    2。网址格式

                    如果基于约定的映射不够灵活,我们可以使用 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 the 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;
                        }
                    }
                    

                    【讨论】:

                      【解决方案21】:

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

                      【讨论】:

                        【解决方案22】:

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

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

                        我的 SpringBootApp 规范:

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

                        我以以下方式声明我的网络过滤器,遵守 Servlet 规范 3.0

                        这是定义过滤器以替代基于 web.xml 的定义的程序化方式。

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

                        彻底避开Web.xml,实现“可部署”的WebApp:

                        要将 Spring Boot 应用程序部署为“传统 WAR”,应用程序类应扩展 SpringBootServletInitializer。

                        注意:

                        SpringBootServletInitializer 是 web.xml 的“编程实现”,参考 Servlet 3.0+ 规范,需要实现 WebApplicationInitializer。

                        因此,SpringBootApplication 不需要“web.xml”作为其应用程序类(在扩展 SpringBootServletInitializer 之后)。它扫描

                        • @WebFilter,
                        • @WebListener 和
                        • @WebServlet.

                        注解@ServletComponentScan

                        此注解可以扫描带有@WebFilter、@WebListener 和@WebServlet 注解的Web 组件的基础包。

                        由于嵌入式容器不支持@WebServlet、@WebFilter和@WebListener注解,Spring Boot在很大程度上依赖于嵌入式容器,引入了这个新的注解@ServletComponentScan来支持一些使用这三个注解的依赖JAR文件。

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

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

                        自定义 Servlet 初始化器:

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

                        如前所述,SpringBootServletInitializer 负责扫描注解:

                        • @WebFilter,
                        • @WebListener 和
                        • @WebServlet.

                        因此 Spring Boot 应用程序类应该

                        • 要么扩展类:SpringBootServletInitializer 要么
                        • 扩展扩展类的自定义类:SpringBootServletInitializer

                        【讨论】:

                          【解决方案23】:

                          对于我做过的任何配置类中的 Spring Boot:

                          @Bean
                          public OncePerRequestFilter myFilter() {
                              return new OncePerRequestFilter() {
                                  @Override
                                  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
                                      AuthUser authUser = SecurityUtil.safeGet(); // applied after secutiry filters
                                      ...
                                      filterChain.doFilter(request, response);
                                  }
                              };
                          }
                          

                          就是这样,不需要任何注册。另见What is OncePerRequestFilter?

                          【讨论】:

                            【解决方案24】:

                            过滤器主要用于记录器文件。它根据您在项目中使用的记录器而有所不同。

                            让我解释一下 log4j2:

                            <Filters>
                                <!-- It prevents an 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
                            猜你喜欢
                            • 1970-01-01
                            • 2017-02-21
                            • 1970-01-01
                            • 2018-07-14
                            • 2014-11-26
                            • 1970-01-01
                            • 2019-01-04
                            相关资源
                            最近更新 更多