把拦截器⾥⾯获取的参数传到controller⾥⾯_过滤器和拦
截器6个区别,别再傻。。。
高效人士的七个习惯
周末有个⼩伙伴加我微信,向我请教了⼀个问题:⽼哥,「过滤器 (Filter) 和 拦截器 (Interceptor) 有啥区别啊?」 听到题⽬我的第⼀感觉就是:「简单」!
毕竟这两种⼯具开发中⽤到的频率都相当⾼,应⽤起来也是⽐较简单的,可当我准备回复他的时候,竟然不知道从哪说起,⽀⽀吾吾了半天,场⾯炒鸡尴尬有⽊有,⼯作这么久⼀个基础问题答成这样,丢了⼤⼈了。
平时觉得简单的知识点,但通常都不会太关注细节,⼀旦被别⼈问起来,反倒说不出个所以然来。
归根结底,还是对这些知识了解的不够,⼀直停留在会⽤的阶段,以⾄于现在「⼀看就会⼀说就废」!这是典型基础不扎实的表现,哎·~,其实我也就是个虚胖!
知耻⽽后勇,下边结合实践,更直观的来感受⼀下两者到底有什么不同?
准备环境
我们在项⽬中同时配置 拦截器 和 过滤器。
1、过滤器 (Filter)
过滤器的配置⽐较简单,直接实现Filter 接⼝即可,也可以通过@WebFilter注解实现对特定URL拦截,看到Filter 接⼝中定义了三个⽅法。
init() :该⽅法在容器启动初始化过滤器时被调⽤,它在 Filter 的整个⽣命周期只会被调⽤⼀次。「注意」:这个⽅法必须执⾏成功,否则过滤器会不起作⽤。
doFilter() :容器中的每⼀次请求都会调⽤该⽅法, FilterChain ⽤来调⽤下⼀个过滤器 Filter。
destroy():当容器销毁 过滤器实例时调⽤该⽅法,⼀般在⽅法中销毁或关闭资源,在过滤器 Filter 的整个⽣命周期也只会被调⽤⼀次
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Filter 前置");
}
@Override
public void doFilter(ServletRequest rvletRequest, ServletRespon rvletRespon, FilterChain filterChain) throws IOException, ServletException {
System.out.println("Filter 处理中");
filterChain.doFilter(rvletRequest, rvletRespon);
}
齐字@Override
public void destroy() {
System.out.println("Filter 后置");
}
}
2、拦截器 (Interceptor)
拦截器它是链式调⽤,⼀个应⽤中可以同时存在多个拦截器Interceptor, ⼀个请求也可以触发多个拦截器 ,⽽每个拦截器的调⽤会依据它
的声明顺序依次执⾏。
⾸先编写⼀个简单的拦截器处理类,请求的拦截是通过HandlerInterceptor 来实现,看到HandlerInterceptor 接⼝中也定义了三个⽅法。
preHandle() :这个⽅法将在请求处理之前进⾏调⽤。「注意」:如果该⽅法的返回值为fal ,将视为当前请求结束,不仅⾃⾝的拦截器会失效,还会导致其他的拦截器也不再执⾏。
postHandle():只有在 preHandle() ⽅法返回值为true 时才会执⾏。会在Controller 中的⽅法调⽤之后,DispatcherServlet 返回渲染视图之前被调⽤。「有意思的是」:postHandle() ⽅法被调⽤的顺序跟 preHandle() 是相反的,先声明的拦截器 preHandle() ⽅法先执⾏,⽽postHandle()⽅法反⽽会后执⾏。
afterCompletion():只有在 preHandle() ⽅法返回值为true 时才会执⾏。在整个请求结束之后, DispatcherServlet 渲染了对应的视图之后执⾏。
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletRespon respon, Object handler) throws Exception {
System.out.println("Interceptor 前置");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletRespon respon, Object handler, ModelAndView modelAndView) throws Exception {
红木家具保养System.out.println("Interceptor 处理中");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletRespon respon, Object handler, Exception ex) throws Exception {
System.out.println("Interceptor 后置");
}
}
将⾃定义好的拦截器处理类进⾏注册,并通过addPathPatterns、excludePathPatterns等属性设置需要拦截或需要排除的 URL。
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override宠物鸭子
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/**");
}水仙花作文
}
我们不⼀样
过滤器 和 拦截器 均体现了AOP的编程思想,都可以实现诸如⽇志记录、登录鉴权等功能,但⼆者的不同点也是⽐较多的,接下来⼀⼀说明。
1、实现原理不同
过滤器和拦截器 底层实现⽅式⼤不相同,过滤器 是基于函数回调的,拦截器 则是基于Java的反射机制(动态代理)实现的。
这⾥重点说下过滤器!
在我们⾃定义的过滤器中都会实现⼀个 doFilter()⽅法,这个⽅法有⼀个FilterChain 参数,⽽实际上它
是⼀个回调接
⼝。ApplicationFilterChain是它的实现类, 这个实现类内部也有⼀个 doFilter() ⽅法就是回调⽅法。
public interface FilterChain {
void doFilter(ServletRequest var1, ServletRespon var2) throws IOException, ServletException;
}
ApplicationFilterChain⾥⾯能拿到我们⾃定义的xxxFilter类,在其内部回调⽅法doFilter()⾥调⽤各个⾃定义xxxFilter过滤器,并执⾏doFilter() ⽅法。
public final class ApplicationFilterChain implements FilterChain {
@Override
适合做壁纸的图片public void doFilter(ServletRequest request, ServletRespon respon) {
...//省略
internalDoFilter(request,respon);
}
private void internalDoFilter(ServletRequest request, ServletRespon respon){
if (pos //获取第pos个filter
ApplicationFilterConfig filterConfig = filters[pos++];
Filter filter = Filter();
...
filter.doFilter(request, respon, this);
}
}
红红火火过新年}
⽽每个xxxFilter 会先执⾏⾃⾝的 doFilter() 过滤逻辑,最后在执⾏结束前会执⾏filterChain.doFilter(rvletRequest, rvletRespon),也就是回调ApplicationFilterChain的doFilter() ⽅法,以此循环执⾏实现函数回调。
@Override
public void doFilter(ServletRequest rvletRequest, ServletRespon rvletRespon, FilterChain filterChain) throws IOException, ServletException {
filterChain.doFilter(rvletRequest, rvletRespon);
中国大百科全书
}
2、使⽤范围不同
我们看到过滤器 实现的是 javax.rvlet.Filter 接⼝,⽽这个接⼝是在Servlet规范中定义的,也就是说过滤器Filter 的使⽤要依赖于Tomcat等容器,导致它只能在web程序中使⽤。
⽽拦截器(Interceptor) 它是⼀个Spring组件,并由Spring容器管理,并不依赖Tomcat等容器,是可以单独使⽤的。不仅能应⽤在web程序中,也可以⽤于Application、Swing等程序中。
3、触发时机不同