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

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

Spring Boot参考指南中提到过 FilterRegistrationBean,但我不确定如何使用它。


当前回答

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

其他回答

添加过滤器有三种方法,

用一个Spring原型(如@Component)注释你的过滤器 在Spring @Configuration中注册一个Filter类型的@Bean 在Spring @Configuration中用FilterRegistrationBean类型注册一个@Bean

Either #1 or #2 will do if you want your filter applies to all requests without customization, use #3 otherwise. You don't need to specify component scan for #1 to work as long as you place your filter class in the same or sub-package of your SpringApplication class. For #3, use along with #2 is only necessary when you want Spring to manage your filter class such as have it auto wired dependencies. It works just fine for me to new my filter which doesn't need any dependency autowiring/injection.

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

你主要需要两样东西:

Add @ServletComponentScan to your Main Class You may add a package named filter inside it. You create a Filter class that has the following: @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() { } }

更新:2022-05-29:

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

第一个方法:

如果你没有任何特定的URL模式,你可以像这样使用@Component(完整的代码和细节在这里https://github.com/surasint/surasint-examples/tree/master/spring-boot-jdbi/3_spring-boot-filter,看看README.txt开始):

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

第二种方式:

如果你想使用URL模式,你可以像这样使用@WebFilter(完整的代码和细节在这里https://github.com/surasint/surasint-examples/tree/master/spring-boot-jdbi/4_spring-boot-filter-urlpattern,看看README.txt开始):

@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文件,请求将通过过滤器两次。

而在第二种方式中,请求将只通过筛选器一次。

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

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

这就是全部,不需要任何注册。参见什么是OncePerRequestFilter?

Use:

@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。通过此操作,您的筛选器将被注册。