繁体   English   中英

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

[英]How can I add a filter class in Spring Boot?

在 Spring Boot 中是否有针对Filter class(针对 web 应用程序)的注释? 也许@Filter

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

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

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

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

}

没有特殊的注释来表示 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

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

  1. 使用 Spring @Component型之一对过滤器进行注释,例如@Component
  2. 在 Spring @Configuration注册一个带有Filter类型的@Bean
  3. 在 Spring @Configuration注册一个带有FilterRegistrationBean类型的@Bean

如果您希望过滤器应用于所有请求而无需自定义,则 #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;
    }

更新: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>

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

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

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

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

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

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

从 Spring 文档中,

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

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

例如:

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

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

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

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

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

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

和过滤器类

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

使用@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

    }

}

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

@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

    }

}

这与其说是答案,不如说是建议,但如果您在 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");
    }

}

你需要两个主要的东西:

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

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

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

然后使用@ServletComponentScan 进行注册。

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

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

用:

@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接口来创建一个过滤器组件。

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

您可以参考此链接以获取完整的应用程序。

您还可以通过使用@WebFilter并实现Filter来制作过滤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();
    }
}

过滤器,顾名思义,用于对资源的请求或来自资源的响应或两者执行过滤。 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;
    }
}

首先,将@ServletComponentScan添加到您的 SpringBootApplication 类。

@ServletComponentScan
public class Application {

其次,创建一个扩展过滤器或第三方过滤器类的过滤器文件,并将@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{

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

}

众所周知,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”,它扩展了类:SpringBootServletInitializer。

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

  • @WebFilter,
  • @WebListener 和
  • @WebServlet。

因此 Spring Boot 应用程序类应该

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

在此处输入图片说明

对于 Spring 以任何配置启动 class 我已经完成:

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

使用 Spring 构造型之一(例如 @Component)注释您的过滤器。 在 Spring @Configuration 中注册一个带有过滤器类型的@Bean。 在 Spring @Configuration 中注册一个带有 FilterRegistrationBean 类型的 @Bean。

对于基于任何条件和 spring 引导中的任何列表的过滤,查询语言更加灵活,允许我们精确过滤到我们需要的资源。 例如,如果我们有像 User 这样的简单实体并像这样定义它。

@Entity
public class User {
@Id
@GeneratedValue(strategy = 
GenerationType.AUTO)
private Long id;

private String firstName;
private String lastName;
private String email;

private int age;

//Setter and getter as usual

然后我们创建一个实现 Specification 接口的 UserSpecification,我们将传入我们自己的约束来构造实际的查询。 在这部分中,与定义的标准构建器相关的方法非常有用和灵活。

public class UserSpecification implements Specification<User> {

private SearchCriteria criteria;

@Override
public Predicate toPredicate
  (Root<User> root, CriteriaQuery<?> query, CriteriaBuilder builder) {

    if (criteria.getOperation().equalsIgnoreCase(">")) {
        return builder.greaterThanOrEqualTo(
          root.<String> get(criteria.getKey()), criteria.getValue().toString());
    } 
    else if (criteria.getOperation().equalsIgnoreCase("<")) {
        return builder.lessThanOrEqualTo(
          root.<String> get(criteria.getKey()), criteria.getValue().toString());
    } 
    else if (criteria.getOperation().equalsIgnoreCase(":")) {
        if (root.get(criteria.getKey()).getJavaType() == String.class) {
            return builder.like(
              root.<String>get(criteria.getKey()), "%" + criteria.getValue() + "%");
        } else {
            return builder.equal(root.get(criteria.getKey()), criteria.getValue());
        }
    }
    return null;
}
}

除了我们根据以下 SearchCriteria class 中表示的一些简单约束创建规范外,任何条件都可以这样创建:

public class SearchCriteria {
private String key;
private String operation;
private Object value;
 }

最后定义 UserRepository 并扩展 JpaSpecificationExecutor,

public interface UserRepository 
extends JpaRepository<User, Long>, 
JpaSpecificationExecutor<User> {}

过滤器主要用于记录器文件。 它因您在项目中使用的记录器而异。

让我解释一下 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 Levels 的级别顺序:ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFF

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM