过滤器Filter可以在controller处理逻辑之前和之后加入一些其他逻辑,可以在controller之前进行验证和信息处理,或者在controller之后进行统计记录。过滤器可以设置过滤路径,多个过滤器也可以指定过滤顺序;
过滤器可以实现一个接口类javax.servlet.Filter:
实现接口中的三个方法:
- init:过滤器初始化操作,springboot启动的时候调用;
- doFilter:过滤处理逻辑;
- destroy:过滤器销毁操作,项目结束停止的时候调用;
注:doFilter方法里有个FilterChain参数,在过滤逻辑里需要手动调用chain.doFilter(request, response)才会往下处理其他过滤器和controller;
可以使用三种方法配置过滤器:
1.使用@Component过滤所有url地址
只需要实现Filter接口,实现接口里必要的doFilter方法(init和destroy方法是接口里的默认方法),实现类使用@Component修饰就可以了;
启动类,使用的默认配置,端口8080,本机ip是192.168.1.30:
/**
* 2023年3月10日下午3:51:13
*/
package testspringboot.test8filter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author XWF
*
*/
@SpringBootApplication
public class Test8Main {
/**
* @param args
*/
public static void main(String[] args) {
SpringApplication.run(Test8Main.class, args);
}
}
controller类:
/**
* 2023年3月10日下午4:05:24
*/
package testspringboot.test8filter;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author XWF
*
*/
@RestController
@RequestMapping("/filter")
public class MyController {
@RequestMapping("/test")
public String test1(String a) {
System.out.println("_Controller_test1:" + a);
return "test1";
}
@RequestMapping("/test/a")
public String test2(String a) {
System.out.println("_Controller_test2:" + a);
return "test2";
}
@RequestMapping("/test/b")
public String test3(String a) {
System.out.println("_Controller_test3:" + a);
return "test3";
}
}
测试的Filter类:
/**
* 2023年3月10日下午4:00:40
*/
package testspringboot.test8filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;
/**
* @author XWF
*
*/
@Component
public class MyFilter1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("MyFilter1 init:" + filterConfig.getFilterName());
}
@Override
public void destroy() {
System.out.println("MyFilter1 destroy");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("过滤所有Controller之前");
HttpServletRequest httpRequest = (HttpServletRequest) request;
System.out.println("RequestURL=" + httpRequest.getRequestURL());
chain.doFilter(request, response);
System.out.println("过滤所有Controller之后");
}
}
从启动日志就可以看到,项目启动的时候过滤器就是初始化:
http测试使用的是Apipost工具,执行几次测试:
程序输出日志:
可以看到所有的路径都会被过滤器过滤,没有controller处理的路径也会被过滤;
结束项目,过滤器就会执行销毁方法:
2.使用@Configuration配置过滤器
首先需要实现Filter接口(不使用@Component注解),然后需要一个@Configuration配置类,配置类里使用@Bean手动定义注入FilterRegistrationBean类,使用FilterRegistrationBean类设置自定义的Filter实现类和一些设置项;
两个Filter实现类:
/**
* 2023年3月13日下午4:19:00
*/
package testspringboot.test8filter;
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 org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* @author XWF
*
*/
public class MyFilter2ForConf implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("ConfFilter2 init " + filterConfig.getFilterName());
System.out.println("ConfFilter2 init flag param = " + filterConfig.getInitParameter("flag")); //获得初始化参数
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("配置的MyConfFilter2 start");
chain.doFilter(request, response);
System.out.println("配置的MyConfFilter2 end");
}
}
/**
* 2023年3月14日上午10:00:53
*/
package testspringboot.test8filter;
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;
/**
* @author XWF
*
*/
public class MyFilter3ForConf implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("ConfFilter3 init " + filterConfig.getFilterName());
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("配置的MyConfFilter_3 start");
chain.doFilter(request, response);
System.out.println("配置的MyConfFilter_3 end");
}
}
过滤器配置类:
/**
* 2023年3月14日上午9:30:13
*/
package testspringboot.test8filter;
import java.util.ArrayList;
import java.util.List;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author XWF
*
*/
@Configuration
public class FilterConf {
@Bean
public FilterRegistrationBean<MyFilter2ForConf> a() {
FilterRegistrationBean<MyFilter2ForConf> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setEnabled(true); //是否启用注入过滤器
filterRegistrationBean.setFilter(new MyFilter2ForConf()); //设置过滤器
filterRegistrationBean.setOrder(2); //设置过滤器顺序,小的在前
filterRegistrationBean.setName("My_Conf_Filter"); //设置过滤器名字
List<String> urlPatterns = new ArrayList<>();
urlPatterns.add("/filter/test/a");
filterRegistrationBean.setUrlPatterns(urlPatterns); //设置过滤路径
filterRegistrationBean.addUrlPatterns("/filter/x", "/filter/y"); //添加过滤路径
// filterRegistrationBean.setInitParameters(initParameters); //设置初始化参数
filterRegistrationBean.addInitParameter("flag", "ok"); //添加设置初始化参数
return filterRegistrationBean;
}
@Bean
public FilterRegistrationBean<MyFilter3ForConf> b() {
FilterRegistrationBean<MyFilter3ForConf> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(new MyFilter3ForConf());
filterRegistrationBean.setOrder(1);
filterRegistrationBean.addUrlPatterns("/filter/test/*");
return filterRegistrationBean;
}
}
启动项目,三个过滤器都会init:
访问controller测试:
Order为1的filter3先过滤,Order为2的filter2在后,先使用@Configuration配置的过滤器过滤,再使用@Component的过滤器,另外controller之前过滤器是顺序执行,controller之后则是倒序执行,即由外向内进入再由内向外退出过滤器;
3.使用@WebFilter和@ServletComponentScan配置过滤器
在Filter实现类上使用@WebFilter注解,在启动类上使用@ServletComponentScan注解设置扫描路径;(该方法无法设置过滤顺序,默认按类名排序)
启动类添加@ServletComponentScan注解:
/**
* 2023年3月10日下午3:51:13
*/
package testspringboot.test8filter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
/**
* @author XWF
*
*/
@SpringBootApplication
@ServletComponentScan(basePackages = {"testspringboot.test8filter"})
public class Test8Main {
/**
* @param args
*/
public static void main(String[] args) {
SpringApplication.run(Test8Main.class, args);
}
}
过滤器实现类:
/**
* 2023年3月14日上午11:09:18
*/
package testspringboot.test8filter;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.DispatcherType;
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;
import javax.servlet.annotation.WebInitParam;
/**
* @author XWF
*
*/
@WebFilter(value = "/filter/test/a", urlPatterns = {}, asyncSupported = false, description = "测试过滤器",
dispatcherTypes = {DispatcherType.REQUEST},displayName = "displayName", filterName = "注解filter4",
initParams = {@WebInitParam(name = "str", value = "HELLO")},
largeIcon = "", smallIcon = "", servletNames = "")
public class MyFilter4ForAnnotation implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Annotation Filter4 init: " + filterConfig.getFilterName());
System.out.println("Annotation Filter4 paramNames: ");
Enumeration<String> ele = filterConfig.getInitParameterNames(); //所有初始化参数名字
while(ele.hasMoreElements()) System.out.println("\t" + ele.nextElement());
System.out.println("Annotation Filter4 param str: " + filterConfig.getInitParameter("str"));
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("注解filter4 start");
chain.doFilter(request, response);
System.out.println("注解filter4 stop");
}
}
/**
* 2023年3月14日上午11:09:35
*/
package testspringboot.test8filter;
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;
/**
* @author XWF
*
*/
@WebFilter("/filter/test/*")
public class MyFilter5ForAnnotation implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Annotation Filter5 init: " + filterConfig.getFilterName()); //注解Filter默认名是类全路径
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("注解filter5 start");
chain.doFilter(request, response);
System.out.println("注解filter5 stop");
}
}
启动测试,过滤器初始化:
测试:
先执行@Configuration配置的过滤器,再执行@WebFilter注解配置的过滤器,最后执行@Component配置的过滤器(这也是默认order顺序);
@Component+@Order也能设置过滤器顺序;
在使用@WebFilter的过滤器上不要配置@Component@Configuration,否则会使@WebFilter里的过滤路径失效,将过滤所有路径;
过滤器执行顺序:
- 先执行设置order的(只有@Configuration和@Component两类) - 按照设置的order从小到大执行 - order相同的,先按照@Configuration => @Component排序,相同配置类型里按照类名排序执行;
- 后执行默认order的 - 按照@Configuration => @WebFilter => @Component三种类型顺序执行,相同配置类型里按照类名排序执行;
版权归原作者 FlyLikeButterfly 所有, 如有侵权,请联系我们删除。