天天看点

Spring Boot 自定义过滤器(Filter)

Spring Boot 自定义过滤器(Filter)

Filter 过滤器主要是用来过滤用户请求的,它允许我们对用户请求进行前置处理和后置处理,比如实现 URL 级别的权限控制、过滤非法请求等等。Filter 过滤器是面向切面编程——AOP 的具体实现(AOP切面编程只是一种编程思想而已)。

自定义 Filter 只需要实现

import javax.servlet.Filter

接口即可。Filter 接口依赖于 Servlet 容器,

Filter

接口就在 Servlet 包下,属于 Servlet 规范的一部分。

javax.servlet.Filter

public interface Filter {
  
   //初始化过滤器后执行的操作
    default void init(FilterConfig filterConfig) throws ServletException {
    }
   // 对请求进行过滤
    void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
   // 销毁过滤器后执行的操作,主要用户对某些资源的回收
    default void destroy() {
    }
}
           
Filter 是如何实现拦截的?

通过

FIlter

接口中的

doFilter

方法,实现了对用户请求的过滤,其中请求流程为

  1. 用户发送请求到 web 服务器,请求会先到过滤器;
  2. 过滤器会对请求进行一些处理比如过滤请求的参数、修改返回给客户端的 response 的内容、判断是否让用户访问该接口等等。
  3. 用户请求响应完毕。
  4. 进行一些自己想要的其他操作。
    Spring Boot 自定义过滤器(Filter)
自定义 Filter 的方法

提供两种方法

1. 通过 手动注册配置实现

MyFilter

实现了

javax.servlet.Filter

package com.zwk.spring_boot_filter_listener.util;

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.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * @description:
 * @author: zwk
 * @date: 2021/6/10
 */
@Component
public class MyFilter implements Filter {

	Logger log = LoggerFactory.getLogger(MyFilter.class);

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		Filter.super.init(filterConfig);
		System.out.println("init");
		log.info("init");
	}

	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
		servletRequest.setAttribute("filter", " doFilter");
		log.info("doFilter");
		System.out.println("请求接口为:" + ((HttpServletRequest) servletRequest).getRequestURI());
		filterChain.doFilter(servletRequest, servletResponse);
	}


	@Override
	public void destroy() {
		Filter.super.destroy();
		log.info("destroy");
	}
}

           

MyFilterConfig.java

将 Filter 注册

之所使用 @Bean + FilterRegistrationBean 的方式注册Filter 是为了更灵活的设置映射。

当然,也可以不使用 @Bean + FilterRegistrationBean 的方式注册,即使用基于约定的映射:

/*

。直接创建自定义 Filter 并且注册为 Spring 的组件即可。

@Configuration
public class MyFilterConfig {
    @Autowired
    MyFilter myFilter;
    @Bean
    public FilterRegistrationBean<MyFilter> thirdFilter() {
        FilterRegistrationBean<MyFilter> filterRegistrationBean = new FilterRegistrationBean<>();
		// 注册自定义的 Filter
        filterRegistrationBean.setFilter(myFilter);
		// 设置拦截 Url映射
        filterRegistrationBean.setUrlPatterns(new ArrayList<>(Arrays.asList("/api/*")));
        return filterRegistrationBean;
    }
}
           

2. 通过注解实现

在自己的过滤器的类上加上

@WebFilter

然后在这个注解中通过它提供好的一些参数进行配置。

@WebFilter(filterName = "MyFilterWithAnnotation", urlPatterns = "/api/*")
public class MyFilterWithAnnotation implements Filter {

   ......
}
           

注意

另外,为了能让 Spring 找到它,你需要在启动类上加上

@ServletComponentScan

注解

控制多个 Filter 的执行顺序

通过 @Order 注解,控制 顺序

通过将 @Order 注解 放置于 Filter 实现类上调整 value 的值控制执行顺序(value越小优先级越高)

@Order(1)
public class MyFilter implements Filter {

   ......
}
           

下例优先级低于上例

@Order(2)
public class MyFilter2 implements Filter {

   ......
}
           

注意

: 这种方式适用于,不使用 @Bean + FilterRegistrationBean 注册的Filter。

当需要使用 @Bean + FilterRegistrationBean 注册 Filter 时则可以使用

FilterRegistrationBean

setOrder(int value)

方法

package com.zwk.spring_boot_filter_listener.config;

import com.zwk.spring_boot_filter_listener.util.MyFilter;
import com.zwk.spring_boot_filter_listener.util.MyFilter2;
import java.util.ArrayList;
import java.util.Arrays;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @description:
 * @author: zwk
 * @date: 2021/6/10
 */
@Configuration
public class MyFilterConfig {
	final
	MyFilter myFilter;
	final
	MyFilter2 myFilter2;

	public MyFilterConfig(MyFilter myFilter, MyFilter2 myFilter2) {
		this.myFilter = myFilter;
		this.myFilter2 = myFilter2;
	}

	@Bean
	public FilterRegistrationBean<MyFilter> filterFilterRegistrationBean() {
		FilterRegistrationBean<MyFilter> filterRegistrationBean = new FilterRegistrationBean<>();
		filterRegistrationBean.setFilter(myFilter);
		filterRegistrationBean.setOrder(2);
		filterRegistrationBean.setUrlPatterns(new ArrayList<>(Arrays.asList("/testFilterController", "/testFilterController1")));
		return filterRegistrationBean;
	}

	@Bean
	public FilterRegistrationBean<MyFilter2> filterFilter2RegistrationBean() {
		FilterRegistrationBean<MyFilter2> filterRegistrationBean = new FilterRegistrationBean<>();
		filterRegistrationBean.setFilter(myFilter2);
		filterRegistrationBean.setOrder(1);
		filterRegistrationBean.setUrlPatterns(new ArrayList<>(Arrays.asList("/testFilterController", "/testFilterController1")));
		return filterRegistrationBean;
	}
}

           

引用:

本文部分知识点总结引用自:https://github.com/CodingDocs/springboot-guide/blob/master/docs/basis/springboot-filter.md

作者:Snailclimb

继续阅读