Detailed explanation of SpringBoot custom filter Filter usage

The JavaWeb component Servlet provides a filter filtering function, which is to intercept the request and response of the target resource, and perform special functional processing on the intercepted request and response. For example, some sensitive information in our request is filtered by using a filter

1. The principle of Filter

The Java Servlet API provides a Filter interface, and you can write a Filter implementation class to implement a custom filter. Filter's request process is:

  1. The client initiates a request
  2. The service container judges whether the current request resource has a filter, and if so, executes the filter
  3. After filtering through the filter, the request is sent to the Servlet server
  4. The return result is returned to the requester through the filter

Filter interface source code:

package javax.servlet;

import java.io.IOException;

public interface Filter {
    
    
    default void init(FilterConfig filterConfig) throws ServletException {
    
    
    }

    void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;

    default void destroy() {
    
    
    }
}
  • init(): This method is executed only once when the filter is created, and is used to initialize the properties of the filter
  • doFilter(): This method will intercept the request. The user needs to customize the filtering of the request content and response content in this method. Call the doFilter method of the FilterChain object of this method to execute the following logic for the request to be released. If If the doFilter method is not called, the request ends and returns a failed response to the client
  • destroy(): This method is used to destroy the filter. After the filter is created, as long as the project keeps running, the filter will always exist. When the project stops, this method will be called to destroy the filter

2. Implementation of Filter in SpringBoot

There are two ways to implement custom Filter in SpringBoot, one is to use @WebFilter and @ServletComponentScan to combine annotations, and the other is to inject FilterRegistrationBean object through configuration class

2.1 @WebFilter annotation method

@WebFilter source code is as follows:

@Target({
    
    ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebFilter {
    
    
    String description() default "";

    String displayName() default "";

    WebInitParam[] initParams() default {
    
    };

    String filterName() default "";

    String smallIcon() default "";

    String largeIcon() default "";

    String[] servletNames() default {
    
    };

    String[] value() default {
    
    };

    String[] urlPatterns() default {
    
    };

    DispatcherType[] dispatcherTypes() default {
    
    DispatcherType.REQUEST};

    boolean asyncSupported() default false;
}

Detailed explanation of several important parameters:

  1. urlPatterns : Customize the URLs that need to be intercepted. Regular matching can be used. If this parameter value is not specified, all requests will be intercepted by default.
  2. filterName : the name of the custom filter
  3. initParams : An array of custom filter initialization parameters, which can be obtained through the getInitParameter() method of the FilterConfig object of the custom filter init(); If we need to exclude some URLs that do not need to be intercepted in the custom intercepted URL, we can put the URL that needs to be excluded into the initParams parameter and then exclude it in the doFilter method)

Customize a filter named testFilter that intercepts all URLs except those with "/test" as follows:

@WebFilter(filterName = "testFilter", urlPatterns = "/*", 
        initParams = @WebInitParam(name = "noFilterUrl", value = "/test"))
public class TestFilter implements Filter {
    
    
    private List<String> noFilterUrls; 
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    
    
        // 从过滤器配置中获取initParams参数
        String noFilterUrl = filterConfig.getInitParameter("noFilterUrl");
        // 将排除的URL放入成员变量noFilterUrls中
        if (StringUtils.isNotBlank(noFilterUrl)) {
    
    
            noFilterUrls = new ArrayList<>(Arrays.asList(noFilterUrl.split(",")));
        }
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
    
    
        // 若请求中包含noFilterUrls中的片段则直接跳过过滤器进入下一步请求中
        String url = ((HttpServletRequest)servletRequest).getRequestURI();
        Boolean flag = false;
        if (!CollectionUtils.isEmpty(noFilterUrls)) {
    
    
            for (String noFilterUrl : noFilterUrls) {
    
    
                if (url.contains(noFilterUrl)) {
    
    
                    flag = true;
                    break;
                }
            }
        }
        if (!flag) {
    
    
            ......	//过滤请求响应逻辑
        } 
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {
    
    

    }
}

The @ServletComponentScan annotation needs to be added to the startup class to make the filter take effect

@SpringBootApplication
@ServletComponentScan
public class EurekaApplication {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(EurekaApplication.class);
    }
}

What needs to be noted here is that if multiple filters with FIlter functions are implemented. The method of using the @WebFilter annotation can only be executed according to the order of the class name of the filter name. Adding the @Order annotation is invalid, because @WebFilter does not use the order defined by the @Order annotation when the container is loaded, but directly uses the class by default. Sort by name. Therefore, if you implement multiple filters in this way, and there are order requirements, you need to pay attention to the definition of the class name.

2.2 Configure Filter by injecting FilterRegistrationBean object through custom configuration class

This method is similar to the one above. In fact, it is to change the configuration of the above method to create a configuration object, and also support the order in which the configuration filter is executed.
For example, the configuration of the filter in the above example is as follows:

@Configuration
public class FilterConfig {
    
    

    @Autowired
    private TestFilter testFilter;

    @Bean
    public FilterRegistrationBean requestFilterRegistration() {
    
    
        FilterRegistrationBean registration = new FilterRegistrationBean();
        // 将过滤器配置到FilterRegistrationBean对象中
        registration.setFilter(testFilter);
        // 给过滤器取名
        registration.setName("requestFilter");
        // 设置过滤器优先级,该值越小越优先被执行
        registration.setOrder(1);
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("noFilterUrl", "/test");
        // 设置initParams参数
        registration.setInitParameters(paramMap);
        List<String> urlPatterns = new ArrayList<>();
        urlPatterns.add("/*");
        // 设置urlPatterns参数
        registration.setUrlPatterns(urlPatterns);
        return registration;
    }
}

When implementing multiple filters and following a custom order, just register the Order property in the FilterRegistrationBean object in the configuration file to change the order. To register multiple filters, you only need to create multiple beans in the configuration class.

Guess you like

Origin blog.csdn.net/weixin_44947701/article/details/122021825
Recommended