前言
本文记录一下在 SpringBoot 项目中是如何使用 Filter 过滤器
代码、测试
Filter 过滤器是 servlet 包下面的东西,因此我们不需要再额外引包
方法一
直接实现 Filter 接口,并使用 @Component 注解标注为组件自动注入 bean
package cn.huanzi.qch.springbootfilter.filter;import org.springframework.stereotype.Component;import javax.servlet.*;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;@Componentpublic class TestFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;System.out.println("TestFilter,"+request.getRequestURI());//执行filterChain.doFilter(servletRequest, servletResponse);}@Overridepublic void destroy() {}}
查看日志可以发现,SpringBoot 已经帮我们注入了一个 filter,拦截路径是 /*,拦截所有,如果我们需要进一步拦截具体的则需要我们自己在代码里控制

方法二
实现 Filter 接口,用 @WebFilter 注解,指定拦截路径以及一些参数,同时需要在启动类使用 @ServletComponentScan 扫描带 @WebFilter、@WebServlet、@WebListener 并将帮我们注入 bean

package cn.huanzi.qch.springbootfilter.filter;import javax.servlet.*;import javax.servlet.annotation.WebFilter;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;//配置拦截路径@WebFilter(filterName = "testFilter",urlPatterns = {"/test"})public class TestFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;System.out.println("TestFilter,"+request.getRequestURI());//执行filterChain.doFilter(servletRequest, servletResponse);}@Overridepublic void destroy() {}}
package cn.huanzi.qch.springbootfilter;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.boot.web.servlet.ServletComponentScan;//自动扫描与当前类的同包以及子包@ServletComponentScan@SpringBootApplicationpublic class SpringbootFilterApplication {public static void main(String[] args) {SpringApplication.run(SpringbootFilterApplication.class, args);}}
查看日志发现,以及帮我们注入了 testFilter,拦截路径是 / test

只指定拦截路径,不设置 filterName 一样可以注入
//配置拦截路径@WebFilter({"/test"})

方法三
当然了,我们也可以既使用 @Component 同时也使用 @WebFilter
package cn.huanzi.qch.springbootfilter.filter;import org.springframework.stereotype.Component;import javax.servlet.*;import javax.servlet.annotation.WebFilter;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;//配置拦截路径@WebFilter(filterName = "testFilter",urlPatterns = {"/test"})@Componentpublic class TestFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;System.out.println("TestFilter,"+request.getRequestURI());//执行filterChain.doFilter(servletRequest, servletResponse);}@Overridepublic void destroy() {}}
package cn.huanzi.qch.springbootfilter;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.boot.web.servlet.ServletComponentScan;//自动扫描与当前类的同包以及子包@ServletComponentScan@SpringBootApplicationpublic class SpringbootFilterApplication {public static void main(String[] args) {SpringApplication.run(SpringbootFilterApplication.class, args);}}
但是做会注入两个 bean,如果你的 @WebFilter 没有指定 filterName 或者指定的名称与类名相同,由于注入两个相同名称的 bean,程序启动报错,叫我们修改其中一个的名字,或者启用覆盖 bean

这里建议如果你硬要采用第三种方法,最好启用覆盖,因为改名将会注入两个 bean,处理逻辑一样但拦截路径不一样,这并不是我们想要的,例如:

启用覆盖
#启用覆盖同名beanspring.main.allow-bean-definition-overriding=true

PS:这里额外说一点,如果我们采用第三种方法,@ServletComponentScan 放在 TestFilter 类上 @WebFilter 也会被扫描到,不需要放在启动类,第二种方法如果也这样做就不行,估计是受到了 @Component 注解的影响
//配置拦截路径@WebFilter(filterName = "testFilter",urlPatterns = {"/test"})@ServletComponentScan@Componentpublic class TestFilter implements Filter
