一 ,springboot使用filter有两种方式一种是通过FilterRegistrationBean代码注册,一种是通过注解@WebFilter
1,注解@WebFilter
需要在主程序Applicaiton上开启@ServletComponentScan
新建一个 Filter类,MyFilter继承Filter,类上加上@WebFilter注解
package com.kerry.filter;
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.annotation.WebFilter;
@WebFilter(filterName="myFilter",urlPatterns="/filter/*")
public class MyFilter implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("@WebFilter myFilter init ");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("@WebFilter myFilter doFilter");
chain.doFilter(request, response);
}
@Override
public void destroy() {
System.out.println("@WebFilter myFilter destroy ");
}
}
然后启动springboot项目的时候,容器会初始化init方法
2 通过 注册FilterRegistrationBean
新建一个MyFilter1类继承Filter
package com.kerry.filter;
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;
public class MyFilter1 implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println(" myFilter1 init ");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("myFilter1 doFilter");
chain.doFilter(request, response);
}
@Override
public void destroy() {
System.out.println("myFilter1 destroy ");
}
}
再注册myfilter1
package com.kerry.configure;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
//import com.kerry.filter.MyFilter;
import com.kerry.filter.MyFilter1;
@Configuration
public class FilterConfigure {
@Bean
public FilterRegistrationBean filterRegistrationBean(){
FilterRegistrationBean frb = new FilterRegistrationBean();
frb.setFilter(new MyFilter1());
frb.addUrlPatterns("/filter1/*");
return frb;
}
// @Bean
// public FilterRegistrationBean filter1RegistrationBean(){
// FilterRegistrationBean frb = new FilterRegistrationBean();
// frb.setFilter(new MyFilter());
// frb.addUrlPatterns("/filter/hello/*");
// return frb;
// }
// @Bean
// ......
}
然后启动项目,会看控制台打印init信息
补充点,当都使用FilterRegistrationBean注册Filter的时候,如果UrlPatterns一个是 /filter1/* 一个 /filter/hello/*
到底是怎么顺序呢?
package com.kerry.configure;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.kerry.filter.MyFilter;
import com.kerry.filter.MyFilter1;
@Configuration
public class FilterConfigure {
@Bean
public FilterRegistrationBean filterRegistrationBean(){
FilterRegistrationBean frb = new FilterRegistrationBean();
frb.setFilter(new MyFilter1());
frb.addUrlPatterns("/filter/*");
return frb;
}
@Bean
public FilterRegistrationBean filter1RegistrationBean(){
FilterRegistrationBean frb = new FilterRegistrationBean();
frb.setFilter(new MyFilter());
frb.addUrlPatterns("/filter/hello/*");
return frb;
}
// @Bean
// ......
}
init顺序 myFilter1 init ,myFilter init
测试结果发现 当访问 /filter/hello/123 的时候, 会先执行 myFilter1 doFilter(/filter/*) 再执行myFilter doFilter(/filter/hello/*)
因为两个filter都匹配了url所以 都会执行。
接着替换两个方法的顺序,调换下 再看
init顺序没有变化, myFilter1 init ,myFilter init
测试结果发现 当访问 /filter/hello/123 的时候, 会先执行myFilter doFilter(/filter/hello/*)再执行 myFilter1 doFilter(/filter/*)
执行顺序和上面完全相反
接着测试 把Myfilter的urlPatterns改为/filter/hello 会发现
@Bean
public FilterRegistrationBean filterRegistrationBean(){
FilterRegistrationBean frb = new FilterRegistrationBean();
frb.setFilter(new MyFilter1());
frb.addUrlPatterns("/filter/*");
return frb;
}
@Bean
public FilterRegistrationBean filter1RegistrationBean(){
FilterRegistrationBean frb = new FilterRegistrationBean();
frb.setFilter(new MyFilter());
frb.addUrlPatterns("/filter/hello");
return frb;
}
输入url /filter/hello/123 结果 myFilter1 doFilter(/filter/*) 只执行了一个filter 因为url只符合第一个myfilter1
输入url /filter/hello 结果 先执行 myFilter1 doFilter(/filter/*),后执行 myFilter doFilter(/filter/hello) 两个filter都会执行
接着把两个bean注册的方法顺序改变下,
@Bean
public FilterRegistrationBean filter1RegistrationBean(){
FilterRegistrationBean frb = new FilterRegistrationBean();
frb.setFilter(new MyFilter());
frb.addUrlPatterns("/filter/hello");
return frb;
}
@Bean
public FilterRegistrationBean filterRegistrationBean(){
FilterRegistrationBean frb = new FilterRegistrationBean();
frb.setFilter(new MyFilter1());
frb.addUrlPatterns("/filter/*");
return frb;
}
init 顺序 myFilter1 init ,myFilter init 顺序没有变过
输入url /filter/hello/123 结果 myFilter1 doFilter(/filter/*) 只执行了一个filter 因为只符合myfilter1的情况
输入url /filter/hello 结果 先执行myFilter doFilter(/filter/hello) ,后执行myFilter1 doFilter(/filter/*)两个filter都会执行 但是顺序也改变了
综上测试结论: 多个filter且 url具有重复过滤的时候,注册filterbean的init顺序 是通过filterNmae进行字符串字典排序注册的,fileter默认名字是类名第一个字母小写
执行顺序都符合url filter的情况下是先注册先执行
附上项目代码结构: