0%

SpringBoot项目实战之Filter实现自定义过滤器

Servlet包中提供了Filter接口供我们实现自定义过滤器。

自定义拦截器可以参考我之前的文章

与之不同的是,拦截器是Spring框架提供的功能,而Filter过滤器是Servlet提供的。下面是拦截器与过滤器的一些主要区别:

  • Filter由Servlet包提供,只能用于Web应用,不能使用Spring容器资源;拦截器由Spring提供,既能用于Web应用,也能用于Application和Swing应用,能使用Spring容器资源。
  • Filter只能在Servlet的前后起作用;而拦截器能深入到方法前后、异常抛出前后。
  • Filter基于函数回调;拦截器基于java的反射机制。
  • ……

实现自定义过滤器

  • 1、实现Filter接口,自定义过滤器
  • 2、注册过滤器

我们可以定义多个过滤器,形成一个过滤链,执行的顺序可以在注册的时候设置优先级,优先级的数字越小优先级越大

自定义过滤器

定义过滤器1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/**
* @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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/**
* @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类来注册过滤器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
* @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;
}
}

测试

编写测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@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中添加的测试值成功的返回到了前台,测试成功