SpringBoot 中Filter的作用以及使用
1、Filter的作用
Filter使用户可以改变一个 request和修改一个response.
Filter 不是一个servlet,它不能产生一个response,它能够在一个request到达servlet之前预处理request,也可以在离开 servlet时处理response.
换种说法,filter其实是一个”servlet chaining”(servlet 链).
通俗点说法filter相当于加油站,request是条路,response是条路,
目的地是servlet,这个加油站设在什么地方对什么数据操作可以由你来控制。
1
2
3
4
5
Filter过滤器实现的是javax.servlet.Filter接口的类,而在javax.servlet.Filter中定义了以下三个方法:
init(FilterConfig fConfig)
init()方法用来初始化过滤器,可以在init()方法中获取Filter中的初始化参数。
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//用来获取Filter中初始化的参数
}
1
2
3
4
doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
doFilter()方法完成过滤操作。当请求发过来的时候,过滤器将执行doFilter方法。
在HttpServletRequest 执行doFilter()之前,根据需要检查 HttpServletRequest ,同时也可以修改HttpServletRequest 请求头和数据。
在HttpServletResponse 执行doFilter()之后,根据需要检查 HttpServletResponse ,同时也可以修改HttpServletResponse响应头和数据。
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println(“进行过滤以及逻辑判断操作”);
filterChain.doFilter(servletRequest,servletResponse);
}
1
2
3
4
5
6
destroy()
Filter对象创建后会驻留在内存,当web应用移除或服务器停止时调用destroy()方法进行销毁。在Web容器卸载 Filter 对象之前被调用。destroy()方法在Filter的生命周期中仅执行一次。通过destroy()方法,可以释放过滤器占用的资源。
@Override
public void destroy() {
//销毁Filter对象,Filter生命周期结束
}
1
2
3
4
上来我们先创建一个小demo 然后我们再讲解其中的原理
我们在IDEA中创建一个SpringBoot的基础项目(这里不介绍这么创建了)
一、这里采用的@WebFilter注解过滤
目录结构
@Order(x)x越小优先级 越高
@WebFilter 用于将一个类声明为过滤器,该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为过滤器。**该注解具有下表给出的一些常用属性 ( 以下所有属性均为可选属性,但是 value、urlPatterns、servletNames 三者必需至少包含一个,且 value 和 urlPatterns 不能共存,如果同时指定,通常忽略 value 的取值 )
package cn.tll.config;
import org.springframework.core.annotation.Order;
import javax.servlet.*;
import javax.servlet.FilterConfig;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
-
@author tll
-
@create 2020/8/1 12:41
-
@Order(x) 里面的数越小 越优先执行
-
@WebFilter() 代表着这是个Filter类 并把它注入到容器中
*/
@Order(1)
@WebFilter(initParams = {@WebInitParam(name = “nofilter”,value = “/one,/two”)})
public class FirstFilter implements Filter {/**
- 不过滤的资源
*/
private String[] nofilter;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//将不过滤的资源存入数组中
String nofilterString = filterConfig.getInitParameter(“nofilter”);
if (nofilterString!=null&&nofilterString.length()>0){
nofilter = nofilterString.split(",");
}}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
boolean flag = isNofilter(request);
if (flag){
filterChain.doFilter(servletRequest,servletResponse);
}else {
request.getRequestDispatcher("/forword").forward(servletRequest,servletResponse);
}}
@Override
public void destroy() {}
/**
*isNofilter 判断路径是否不需要过滤
*/
public boolean isNofilter(HttpServletRequest request){
String requestURI = request.getRequestURI();
System.out.println(requestURI);
for (String s : nofilter) {
if (requestURI.contains(s)){
return true;
}
}
return false;
}
} - 不过滤的资源
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
63
64
65
66
67
Controller中的代码
这里的@RestController注解作用就不用多说了
package cn.tll.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
-
@author tll
-
@create 2020/8/1 12:48
*/
@RestController
public class IndexController {@RequestMapping({"/","/index"})
public String index(){
return “访问成功”;
}@RequestMapping("/forword")
public String forword(){
return “请先登录”;
}@RequestMapping("/one")
public String one(){
return “one”;
}@RequestMapping("/two")
public String two(){
return “two”;
}
}
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
最后千万不要忘了在启动类上加上@ServletComponentScan
注:@ServletComponentScan注解的含义在SpringBootApplication(启动类)上使用@ServletComponentScan注解后,Servlet、Filter(过滤器)、Listener(监听器)可以直接通过@WebServlet、@WebFilter、@WebListener注解自动注册,无需其他代码!
package cn.tll;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
/**
- 因为使用的是注解Filter 所以需要在程序入口加入@ServletComponentScan
*/
@SpringBootApplication
@ServletComponentScan
public class SpringbootFilterApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootFilterApplication.class, args);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
二,@Bean注解方式
我们还是先创建一个干净的SpringBoot项目吧
首先把Controller写好 先测试一下有无问题
package cn.tll.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
-
@author tll
-
@create 2020/8/2 8:51
*/
@RestController
public class IndexController {@RequestMapping({"/","/index"})
public String index(){
return “欢迎进入首页”;
}@RequestMapping(“noRoot”)
public String noRoot(){
return “对不起,请先登录”;
}@RequestMapping("/one")
public String one(){
return “one”;
}@RequestMapping("/two")
public String two(){
return “two”;
}
}
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
好的没问题
再创建一个WebConfig
package cn.tll.config;
import cn.tll.filter.FirstFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
-
@author tll
-
@create 2020/8/2 8:57
*/
@Configuration
public class WebConfig {@Bean
public FilterRegistrationBean filterRegistrationBean(){
FilterRegistrationBean registrationBean = new FilterRegistrationBean(new FirstFilter());
//过滤所有路径
registrationBean.addUrlPatterns("/*");
//添加不过滤路径
registrationBean.addInitParameter(“noFilter”,"/one,/two");
registrationBean.setName(“firstFilter”);
registrationBean.setOrder(1);
return registrationBean;
}@Bean
public FilterRegistrationBean twoFilterRegistrationBean(){
FilterRegistrationBean registrationBean = new FilterRegistrationBean(new TwoFilter());
registrationBean.setOrder(2);
registrationBean.addUrlPatterns("/*");
registrationBean.setName(“TwoFilter”);
return registrationBean;
}
}
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
接着就是创建Filter了
这里创建两个Filter主要是用于查看setOrder优先级是否有用
Order(x) 里面的x数值越小优先级越高
package cn.tll.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
-
@author tll
-
@create 2020/8/2 9:00
*/
public class FirstFilter implements Filter {private String[] noFilters;
/**
- 过滤器初始化
- @param filterConfig
- @throws ServletException
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String noFilter = filterConfig.getInitParameter(“noFilter”);
if (noFilter!=null&&noFilter.length()>0){
noFilters = noFilter.split(",");
}
}
/**
- 过滤器方法
- @param servletRequest
- @param servletResponse
- @param filterChain
- @throws IOException
- @throws ServletException
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println(“这里是FirstFilter”);
HttpServletRequest request = (HttpServletRequest) servletRequest;
boolean flag = isFilter(request);
if (flag){
System.out.println(“可以访问”);
filterChain.doFilter(servletRequest,servletResponse);
}else {
System.out.println(“不可以访问”);
//没有权限不可以访问,需要转发到友好界面
request.getRequestDispatcher("/noRoot").forward(servletRequest,servletResponse);
}
}
/**
- 过滤器销毁
*/
@Override
public void destroy() {
}
/**
-
判断URL是否包含不过滤的路径
-
@param request
-
@return
*/
public boolean isFilter(HttpServletRequest request){
String requestURI = request.getRequestURI();
for (String noFilter : noFilters) {
System.out.println(noFilter);
if (requestURI.contains(noFilter)){
return true;}
}
return false;
}
}
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package cn.tll.filter;
import javax.servlet.*;
import java.io.IOException;
/**
-
@author tll
-
@create 2020/8/2 9:23
*/
public class TwoFilter implements Filter {@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println(“这里是TwoFiter”);
filterChain.doFilter(servletRequest,servletResponse);
}@Override
public void destroy() {}
}
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
大功告成,你觉得那种方法简单呢?
源码地址
@WebFilter注解开发
@Bean注解开发源码
————————————————
版权声明:本文为优快云博主「天亮再出发」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/qq_43483502/article/details/107733067