什么是过滤器
过滤器Filter基于Servlet实现,过滤器的主要应用场景是对字符编码、跨域等问题进行过滤。Servlet的工作原理是拦截配置好的客户端请求,然后对Request和Response进行处理。Filter过滤器随着web应用的启动而启动,只初始化一次。
Filter的使用比较简单,继承Filter 接口,实现对应的init、doFilter以及destroy方法即可。
- init() :该方法在容器启动初始化过滤器时被调用,它在 Filter 的整个生命周期只会被调用一次。注意:这个方法必须执行成功,否则过滤器会不起作用。
- doFilter() :容器中的每一次请求都会调用该方法, FilterChain 用来调用下一个过滤器 Filter。
- destroy(): 当容器销毁 过滤器实例时调用该方法,一般在方法中销毁或关闭资源,在过滤器 Filter 的整个生命周期也只会被调用一次。
@Component
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("初始化过滤器");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//做一些处理
chain.doFilter(request,response);
}
@Override
public void destroy() {
System.out.println("销毁过滤器");
}
}
什么是拦截器
拦截器是SpringMVC中实现的一种基于Java反射(动态代理)机制的方法增强工具,拦截器的实现是继承HandlerInterceptor 接口,并实现接口的preHandle、postHandle和afterCompletion方法。
- preHandle:请求方法前置拦截,该方法会在Controller处理之前进行调用,Spring中可以有多个Interceptor,这些拦截器会按照设定的Order顺序调用,当有一个拦截器在preHandle中返回false的时候,请求就会终止。
- postHandle:preHandle返回结果为true时,在Controller方法执行之后,视图渲染之前被调用
- afterCompletion:在preHandle返回ture,并且整个请求结束之后,执行该方法。
拦截器它是链式调用,一个应用中可以同时存在多个拦截器Interceptor, 一个请求也可以触发多个拦截器 ,而每个拦截器的调用会依据它的声明顺序依次执行。
@Component
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截器前置");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("拦截器处理中");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("拦截器后置");
}
}
将自定义好的拦截器处理类进行注册,并通过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("/**");
}
}
拦截器与过滤器的区别
相同点:
1、拦截器与过滤器都是体现了AOP的思想,对方法实现增强,都可以拦截请求方法。
2、拦截器和过滤器都可以通过Order注解设定执行顺序
不同点:
1、过滤器属于Servlet级别,拦截器属于Spring级别 Filter是在javax.servlet包中定义的,要依赖于网络容器,因此只能在web项目中使用。
Interceptor是SpringMVC中实现的,归根揭底拦截器是一个Spring组件,由Spring容器进行管理。
2、过滤器和拦截器的执行顺序不同:
首先当一个请求进入Servlet之前,过滤器的doFilter方法进行过滤,
进入Servlet容器之后,执行Controller方法之前,拦截器的preHandle方法进行拦截,
执行Controller方法之后,视图渲染之前,拦截器的postHandle方法进行拦截,
请求结束之后,执行拦截器的postHandle方法。
3、过滤器基于函数回调方式实现,拦截器基于Java反射机制实现
总结
实际开发中,拦截器的应用场景会比过滤器要更多,下面是拦截器和过滤器的主要应用场景
拦截器的应用场景:权限控制,日志打印,参数校验
过滤器的应用场景:跨域问题解决,编码转换