本文由 简悦 SimpRead 转码, 原文地址 https://segmentfault.com/a/1190000012072060

前言

springmvc 中有两种很普遍的 AOP 实现:
1. 过滤器(Filter)
2. 拦截器(Interceptor)

本篇面对的是一些刚接触 springboot 的人群
所以主要讲解 filter 和 interceptor 的简单实现和它们之间到底有什么区别
(一些复杂的功能我会之后发出文章,请记得关注)

Filter 的简单实现

字面意思:过滤器就是过滤的作用,在 web 开发中过滤一些我们指定的 url
那么它能帮我们过滤什么呢?
那功能可就多了:
比如过拦截掉我们不需要的接口请求
修改请求(request)和响应(response)内容
完成 CORS 跨域请求等等

现在我们来实现一个简单的过滤器:
可以新建一个 filter 包,随着项目的扩大过滤器会越来越多
在这里我新建了一个TestFilter类,实现 Filter 接口

1
2
3
4
@Component
@WebFilter(urlPatterns = "/Blogs",filterName = "blosTest")
public class TestFilter implements Filter{}

我们一步步来
1.@Component 就是把这个类注入到 IOC 容器中
2.@WebFilter(urlPatterns = “/Blogs”,filterName = “blosTest”) 说明这是一个 web 过滤器,它拦截的 url 为/Blogs,过滤器名字为blogsTest

下面贴出实现接口之后的三个重构方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Override
public void init(FilterConfig filterConfig) throws ServletException {

}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request= (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
System.out.printf("过滤器实现");
filterChain.doFilter(request,response);
}

@Override
public void destroy() {

}

初始化(init)和摧毁(destroy)方法一般不会用到,具体使用看下源码便知
doFilter()是过滤器的核心
注意:在实现接口方法之后,我们要转换 request 和 response 类型至 HttpServlet,否则接下去的操作可能会报错。
如果过滤通过,执行filterChain.doFilter(request,response);
说明这个 url 已经经过了我们的 Filter
其他不要设置,我们执行看下结果:

可以看到,只需要一个类我们就实现了一个简单的过滤器

当然可以不用注解的方式,配置启动类

1
2
3
4
5
6
7
8
9
10
11
12
13
//过滤器
@Bean
public FilterRegistrationBean filterRegistrationBean(){
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
List<String> urlPatterns = new ArrayList<String>();

TestFilter testFilter = new TestFilter(); //new过滤器
urlPatterns.add("/Blogs"); //指定需要过滤的url
filterRegistrationBean.setFilter(testFilter); //set
filterRegistrationBean.setUrlPatterns(urlPatterns); //set

return filterRegistrationBean;
}

这也是可以的,本人其实还是比较推荐这种方式添加过滤器

Interceptor 的简单实现

拦截器的实现比过滤器稍微复杂一点
我们同样可以新建一个 interceptor 包
在里面新建一个名为MyInterceptor的类

1
2
public class MyInterceptor implements HandlerInterceptor {}

这个类实现了HandleInterceptor接口
直接贴类代码,我会在代码中注释功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class MyInterceptor implements HandlerInterceptor {
//在请求处理之前进行调用(Controller方法调用之前
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.printf("preHandle被调用");
return true; //如果false,停止流程,api被拦截
}

//请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle被调用");
}

//在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("afterCompletion被调用");
}
}

它依次实现了三个方法
相比过滤器,拦截器还需要在 springmvc 中注入
所以我们打开启动类,写入以下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class WarApplication {

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

//mvc控制器
//@Configuration
static class WebMvcConfigurer extends WebMvcConfigurerAdapter{
//增加拦截器
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(new MyInterceptor()) //指定拦截器类
.addPathPatterns("/Handles"); //指定该类拦截的url
}
}
}

这里我在/Handles这个 url 中进行拦截
代码写完了,来看下结果

当进入指定 url 时,我们执行到了拦截器
接下来就可以根据需求去使用拦截器了

区别

过滤器和拦截器非常相似,但是它们有很大的区别
最简单明了的区别就是过滤器可以修改 request,而拦截器不能
过滤器需要在 servlet 容器中实现,拦截器可以适用于 javaEE,javaSE 等各种环境
拦截器可以调用 IOC 容器中的各种依赖,而过滤器不能
过滤器只能在请求的前后使用,而拦截器可以详细到每个方法
区别很多,大家可以去查下

总的来说
过滤器就是筛选出你要的东西,比如 requeset 中你要的那部分
拦截器在做安全方面用的比较多,比如终止一些流程
网上有一张图片很不错,这里拷过来给大家看一下

以上便是 springboot 中过滤器和拦截器的实现和区别;
觉得还可以的请点个赞,赞不了也可以收藏下;
总之,谢谢阅读~

本文地址 https://blog.coder4j.cn/posts/17d41b3e/