此文章已同步更新至我的个人博客https://simonting.gitee.io
Servlet包中提供了Filter接口供我们实现自定义过滤器。
自定义拦截器可以参考我之前的文章
与之不同的是,拦截器是Spring框架提供的功能,而Filter过滤器是Servlet提供的。下面是拦截器与过滤器的一些主要区别:
- Filter由Servlet包提供,只能用于Web应用,不能使用Spring容器资源;拦截器由Spring提供,既能用于Web应用,也能用于Application和Swing应用,能使用Spring容器资源。
- Filter只能在Servlet的前后起作用;而拦截器能深入到方法前后、异常抛出前后。
- Filter基于函数回调;拦截器基于java的反射机制。
- …
实现自定义过滤器
- 1、实现Filter接口,自定义过滤器
- 2、注册过滤器
我们可以定义多个过滤器,形成一个过滤链,执行的顺序可以在注册的时候设置优先级,优先级的数字越小优先级越大
自定义过滤器
定义过滤器1
/**
* @Author zhangting
* @Desc 自定义过滤器1
* @Date 2020/08/04
**/
@Slf4j
public class MyFilter1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// web应用程序启动时,web服务器将创建Filter的实例对象,并调用init方法,完成对象的初始化功能,此方法只执行一次。
log.info("----- init filter1 -----");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 实际的过滤操作
log.info("----- doFilter1 -----");
HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
// 模拟测试
httpRequest.setAttribute("name", "zhangting");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
// Filter对象床创建后会驻留在内存,当web应用移除或服务器停止时才会销毁,此方法只执行一次。
log.info("----- destroy filter1 -----");
}
}
定义过滤器2
/**
* @Author zhangting
* @Desc 自定义过滤器2
* @Date 2020/08/04
**/
@Slf4j
public class MyFilter2 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// web应用程序启动时,web服务器将创建Filter的实例对象,并调用init方法,完成对象的初始化功能,此方法只执行一次。
log.info("----- init filter2 -----");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 实际的过滤操作
log.info("----- doFilter2 -----");
HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
// 模拟测试
httpRequest.setAttribute("city", "nanjing");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
// Filter对象床创建后会驻留在内存,当web应用移除或服务器停止时才会销毁,此方法只执行一次。
log.info("----- destroy filter2 -----");
}
}
注册过滤器
编写一个javaconfig类来注册过滤器
/**
* @Author zhangting
* @Desc 注册过滤器
* @Date 2020/08/04
**/
@Slf4j
@Configuration
public class FilterConfig {
@Bean
@Primary
public FilterRegistrationBean<MyFilter1> registerMyFilter1() {
log.info("register MyFilter1...");
FilterRegistrationBean<MyFilter1> filterRegistrationBean = new FilterRegistrationBean<MyFilter1>();
// 注册
filterRegistrationBean.setFilter(new MyFilter1());
// 设置需要过滤的URL,不设置则默认为全部
filterRegistrationBean.addUrlPatterns("/v1/filter");
filterRegistrationBean.setName("myFilter1");
// 设置优先级,数字越小优先级越大
filterRegistrationBean.setOrder(1);
return filterRegistrationBean;
}
@Bean
public FilterRegistrationBean<MyFilter2> registerMyFilter2() {
log.info("register MyFilter2...");
FilterRegistrationBean<MyFilter2> filterRegistrationBean = new FilterRegistrationBean<MyFilter2>();
// 注册
filterRegistrationBean.setFilter(new MyFilter2());
// 设置需要过滤的URL,不设置则默认为全部
filterRegistrationBean.addUrlPatterns("/v1/filter");
filterRegistrationBean.setName("myFilter2");
// 设置优先级,数字越小优先级越大
filterRegistrationBean.setOrder(2);
return filterRegistrationBean;
}
}
测试
编写测试类
@Slf4j
@RestController
@RequestMapping("/v1")
public class TestController {
@GetMapping("/filter")
public ResponseEntity<?> filter(HttpServletRequest request) {
Map<String, String> map = new HashMap<>();
// 在过滤器1中往request中塞了一个name,在过滤器2中往request中塞了一个city
map.put("name", request.getAttribute("name").toString());
map.put("city", request.getAttribute("city").toString());
return new ResponseEntity<>(map, HttpStatus.OK);
}
}
启动服务,两个过滤器会在启动的时候进行注册及调用init方法对过滤器进行初始化。
使用postman对/v1/filter接口发起请求
查看日志可以得知,过滤器按照我们设置的执行顺序执行,先执行过滤器1,再执行过滤器2。
我们在过滤器1、2中添加的测试值成功的返回到了前台,测试成功