抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

springboot中过滤器有三种注册方式,下面我们分别来看看这三个

1.@WebFilter

通过 @WebFilter 注解来标记一个过滤器,这种方式相信大家很容易想到。这是将 Servlet 中的那一套东西直接拿到 Spring Boot 上用。
具体做法就是通过 @WebFilter 注解来标记一个 Filter,如下:

1
2
3
4
5
6
7
8
9
10
@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("-----doFilter-----");
chain.doFilter(request, response);
}
}

在 @WebFilter 注解中可以配置过滤器的拦截规则。这个注解要生效,还需要我们在项目启动类上配置 @ServletComponentScan 注解,如下:

1
2
3
4
5
6
7
8
9
10
@SpringBootApplication
@ServletComponentScan
public class FilterdemoApplication {

public static void main(String[] args) {
SpringApplication.run(FilterdemoApplication.class, args);
}

}

@ServletComponentScan 注解虽然名字带了 Servlet,但是实际上它不仅仅可以扫描项目中的 Servlet 容器,也可以扫描 Filter 和 Listener。

这是我们在 Spring Boot 中使用过滤器的第一种方式,在实际项目中,这种方式使用较少,因为这种方式有一个很大的弊端就是无法指定 Filter 的优先级,如果存在多个 Filter 时,无法通过 @Order 指定优先级。

2.@Bean

第二种方式就是将过滤器配置成 Bean,注册到 Spring 容器中去。这种方法不再需要 @ServletComponentScan 注解,只要一个 Bean 即可,如下:

1
2
3
4
5
6
7
8
9
10
@Component
public class MyFilter implements Filter {

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("-----doFilter-----");
chain.doFilter(request, response);
}
}

这种方式看起来很方便,一个注解将 Filter 纳入到 Spring 容器中即可。而且这种方式还有一个优势,就是如果存在多个 Filter,可以通过 @Order 注解指定多个 Filter 的优先级,像下面这样:

1
2
3
4
5
6
7
8
9
10
11
@Component
@Order(-1)
public class MyFilter implements Filter {

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("-----doFilter-----");
chain.doFilter(request, response);
}
}

虽然解决了优先级问题,但是发现这种方式好像没有办法设置 Filter 的拦截规则!是的,直接定义 Bean 的话,默认的拦截规则就是 /* 即拦截所有请求,开发者无法进行自定义配置。
所以第三种方式就出来了

3.FilterRegistrationBean

第三种方案还是将 Filter 封装成一个 Bean,但这个 Bean 是 FilterRegistrationBean,通过 FilterRegistrationBean 我们既可以配置 Filter 的优先级,也可以配置 Filter 的拦截规则
一般在项目中,我们都是使用 FilterRegistrationBean 来配置过滤器,看一个案例:
1.本次过滤器的案例是对登录是否为管理员身份进行校验,过滤器类AdminFilter

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
public class AdminFilter implements Filter {
@Autowired
UserService userService;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)servletRequest;
// HttpServletResponse response = (HttpServletResponse)servletResponse;
// PrintWriter out = response.getWriter();
HttpSession session = request.getSession();
User currentUser = (User) session.getAttribute(Constant.IMOOC_MALL_USER);
if (currentUser == null){
/*在Java Web开发中,咱们常常须要拦截http请求,去作一些转发或者是校验等事情。这类工做一般filter能够很轻松的搞定,但这通常都是拦截请求。而咱们有时候也会有一些需求,好比说是拦截服务器的返回(Response),但愿在数据流在服务器端处理完毕,且返回浏览器以前,在这中间作一些本身的事情。网上搜了搜,发现资源不多。因而本身实现了一版,跟你们分享一下。主要用到了HttpServletResponseWrapper获取到数据流,而后经过response.getWriter().write来回写数据。htm*/
/*
* HttpServletResponseWrapper
* Servlet规范中的filter引入了一个功能强大的拦截模式。Filter能在request到达servlet的服务方法之前拦截HttpServletRequest对象,
* 而在服务方法转移控制后又能拦截HttpServletResponse对象。
* 但是HttpServletRequest中的参数是无法改变的,
* 若是手动执行修改request中的参数,则会抛出异常。
* 且无法获取到HttpServletResponse中的输出流中的数据,
* 因为HttpServletResponse中输出流的数据会写入到默认的输出端,你手动无法获取到数据。
* 我们可以利用HttpServletRequestWrapper包装HttpServletRequest,
* 用HttpServletResponseWrapper包装HttpServletResponse,
* 在Wrapper中实现参数的修改或者是response输出流的读取,
* 然后用HttpServletRequestWrapper替换HttpServletRequest,HttpServletResponseWrapper替换HttpServletResponse。
* 这样就实现了参数的修改设置和输出流的读取。
* */
PrintWriter out = new HttpServletResponseWrapper((HttpServletResponse) servletResponse).getWriter();
out.write("{\n" +
" \"status\": 10007,\n" +
" \"msg\": \"NEED_LOGIN\",\n" +
" \"data\": null\n" +
"}");
out.flush();
out.close();
return;//方法执行到此处结束,不会进入controller
}
//校验是否是管理员
boolean adminRole = userService.checkAdminRole(currentUser);
if (adminRole){
filterChain.doFilter(servletRequest,servletResponse);
}else {
PrintWriter out = new HttpServletResponseWrapper((HttpServletResponse) servletResponse).getWriter();
out.write("{\n" +
" \"status\": 10009,\n" +
" \"msg\": \"NEED_ADMIN\",\n" +
" \"data\": null\n" +
"}");
out.flush();
out.close();
}
}

@Override
public void destroy() {
Filter.super.destroy();
}
}

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
30
31
32
package com.imooc.mall.config;

import com.imooc.mall.filter.AdminFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import javax.servlet.FilterRegistration;

/*
*描述: Admin过滤器的配置
* */
@Configuration
public class AdminFilterConfig {
@Bean
public AdminFilter adminFilter(){
return new AdminFilter();
}
@Bean(name = "adminFilterConf")
public FilterRegistrationBean adminFilterConfig(){
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(adminFilter());
filterRegistrationBean.addUrlPatterns("/admin/category/*");
filterRegistrationBean.addUrlPatterns("/admin/product/*");
filterRegistrationBean.addUrlPatterns("/admin/order/*");
filterRegistrationBean.setName("adminFilterConf");
return filterRegistrationBean;

}
}