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

jan*_*ith 208 java configuration servlet-filters spring-boot

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

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

Spring Boot Reference Guide提到了 FilterRegistrationBean,但我不知道如何使用它.

Hai*_*man 147

如果要设置第三方过滤器,可以使用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>
Run Code Online (Sandbox Code Playgroud)

这些将是您@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();
}
Run Code Online (Sandbox Code Playgroud)

以上是用spring-boot 1.2.3测试的

  • 只需添加一个额外的@Bean public FilterRegistrationBean additionalFilterRegistration() (7认同)
  • FilterRegistrationBean.setOrder (6认同)
  • 如果我想添加多个过滤器怎么办?@蛋白石 (2认同)
  • 该示例在“someFilter()”上缺少“@Bean”。 (2认同)
  • “Filter”在哪个包中?我看到超过 24 个可能的匹配项。也许包括导入语句片段。 (2认同)

小智 112

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

}
Run Code Online (Sandbox Code Playgroud)

  • 过滤器应该在某处注册吗? (3认同)
  • 需要注意的一件重要事情是您的 bean 的名称(基于您的类名)不应与 Spring bean 相同。例如,您可能想创建一个“MetricsFilter”,但是这个 bean 将被同名的 Spring 执行器 bean 所掩盖。学习了这个艰难的方式...... (3认同)

Dav*_*yer 73

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

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

注意:

从Spring Boot 1.4开始,FilterRegistrationBean不会弃用并简单地将包org.springframework.boot.context.embedded.FilterRegistrationBean移到org.springframework.boot.web.servlet.FilterRegistrationBean

  • Spring Boot不适用于Servlet 2.5,并且还没有真正支持JSP.我不是一个渐变者,所以我不知道你想做什么."编译"有什么问题?如果你只依赖"spring-boot-starter-web",它会起作用吗?(我不认为这些问题与原始问题有关,所以也许您应该再次发布新问题?) (2认同)

bar*_*yku 68

添加过滤器有三种方法,

  1. 使用其中一个Spring构造型注释您的过滤器,例如 @Component
  2. 注册一个@BeanFilter春季型@Configuration
  3. 注册一个@BeanFilterRegistrationBean春季型@Configuration

如果您希望过滤器适用于所有请求而无需自定义,则#1或#2将执行,否则使用#3.只要将过滤器类放在类的相同或子包中,就不需要为#1指定组件扫描SpringApplication.对于#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;
    }
Run Code Online (Sandbox Code Playgroud)


Sur*_*oen 29

更新时间:2017-12-16:

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

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

@Component
public class ExampleFilter implements Filter{
   ...
}
Run Code Online (Sandbox Code Playgroud)

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

@WebFilter(urlPatterns = "/api/count")
public class ExampleFilter implements Filter{
 ...
}
Run Code Online (Sandbox Code Playgroud)

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

@ServletComponentScan
@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer {
...
}
Run Code Online (Sandbox Code Playgroud)

请注意,@ 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>
Run Code Online (Sandbox Code Playgroud)

警告:第一种方法,如果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/


DPa*_*ncs 19

以下是我的自定义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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我通过将它添加到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;
    }
}
Run Code Online (Sandbox Code Playgroud)


Luc*_*cky 14

来自Spring docs,

嵌入式servlet容器 - 向应用程序添加Servlet,过滤器或监听器

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

例如:

@Bean
public Filter compressFilter() {
    CompressingFilter compressFilter = new CompressingFilter();
    return compressFilter;
}
Run Code Online (Sandbox Code Playgroud)

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

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

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


isa*_*mez 9

我们有大约四种不同的选项来使用 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

其次,我们可以创建一个扩展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);
    }
}
Run Code Online (Sandbox Code Playgroud)

或者,我们可以使用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;
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,我们可以将@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);
    }
}
Run Code Online (Sandbox Code Playgroud)


And*_*ure 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

和过滤器类

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);
    }
}
Run Code Online (Sandbox Code Playgroud)


Kay*_*ayV 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

    }

}
Run Code Online (Sandbox Code Playgroud)

  • 还要添加@ServletComponentScan (3认同)

Ghu*_*aza 5

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

@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

    }

}
Run Code Online (Sandbox Code Playgroud)


Har*_*hna 5

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

@Component
public class PerformanceFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        ...
        ...
    }

}
Run Code Online (Sandbox Code Playgroud)

步骤 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以参考此链接获取完整的申请。