目录
一、熟悉
三兄弟的区别
过滤器和拦截器的区别
使用场景
二、使用
filter
Interceptor
aop
一、熟悉
三个词都很熟悉,在某些课程或者博客中总被提到,但平时基本不怎么写;
三者在家族中的关系可以看下下边这张图,可以很直观的看到,如果一个请求过来的时候
1、先会经过filter链,之后才会到达servlet中;
2、然后才会到达interceptor拦截器;
3、通过拦截器后,会被指定的aop拦截到;
4、最后才会到达服务层;
三兄弟的区别
1、过滤器,拦截器拦截的是URL。AOP拦截的是类的元数据(包、类、方法名、参数等)。
2、过滤器并没有定义业务用于执行逻辑前、后等,仅仅是请求到达就执行。
3、拦截器有三个方法,相对于过滤器更加细致,有被拦截逻辑执行前、后等。
4、AOP针对具体的代码,能够实现更加复杂的业务逻辑。
三者功能类似,但各有优势,从过滤器–》拦截器–》切面,拦截规则越来越细致。 执行顺序依次是过滤器、拦截器、切面。
过滤器和拦截器的区别
1、最简单明了的区别就是过滤器可以修改request,而拦截器不能
2、过滤器需要在servlet容器中实现,拦截器可以适用于javaEE,javaSE等各种环境
3、拦截器可以调用IOC容器中的各种依赖,而过滤器不能(不绝对)
4、过滤器只能在请求的前后使用,而拦截器可以详细到每个方法
5、过滤器和拦截器触发时机不一样,过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。
6、拦截器可以获取IOC容器中的各个bean,而过滤器就不行,因为拦截器是spring提供并管理的,spring的功能可以被拦截器使用,在拦截器里注入一个service,可以调用业务逻辑。而过滤器是JavaEE标准,只需依赖servlet api ,不需要依赖spring。
7、过滤器的实现基于回调函数。而拦截器(代理模式)的实现基于反射
8、Filter是依赖于Servlet容器,属于Servlet规范的一部分,而拦截器则是独立存在的,可以在任何情况下使用。
9、Filter的执行由Servlet容器回调完成,而拦截器通常通过动态代理(反射)的方式来执行。
10、Filter的生命周期由Servlet容器管理,而拦截器则可以通过IoC容器来管理,因此可以通过注入等方式来获取其他Bean的实例,因此使用会更方便。
使用场景
三者的功能大致相同,但根据自身特点,在使用的时候可以根据场景选择更适合的;
过滤器:
1、过滤敏感词汇(防止sql注入等)
2、设置字符编码
3、URL级别的权限访问控制
4、压缩响应信息
拦截器:
1、登录验证,可以根据request中的获取用户信息等来验证是否登录;
2、权限控制,访问目标资源之前,进行权限检查,检查用户有无权限;
3、处理cookie、本地化、国际化、主题等
4、性能监控,监控请求处理时长等。
aop:
1、日志记录,记录请求操作日志,以便统计请求访问量.(粒度更细,比拦截器更合适)
二、使用
filter
方式1:bean方式(无法注入IOC中的bean)
/**
* Filter是依赖于Servlet的,需要有Servlet的依赖。
* init() 在容器初始化时执行,只执行一次。
* doFilter() 目标请求之前拦截执行,拦截之后需要放行才开始执行目标方法。filterChain.doFilter(servletRequest,servletResponse);
* destroy() 在容器销毁时执行,只执行一次。
* Filter可以拦截所有请求。包括静态资源[css,js…等]。
* 基于函数回调实现。
* 过滤器只能在容器初始化时被调用一次。
*/
public class TestFilter2 implements Filter {
// @Autowired
// AsyncService asyncService;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@SneakyThrows
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// asyncService.task(2);
System.out.println("进入注解方式filter bean 方式");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
@Configuration
public class filterConfig {
@Bean
public FilterRegistrationBean heFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean(new TestFilter2());
// 匹配规则
registration.addUrlPatterns("/*");
// 过个过滤器的执行顺序,数字越小优先级越高
registration.setOrder(1);
return registration;
}
}
方式二:注解(可以注入IOC中的bean)
@Component
// filterName就是当前类名称,还有一个urlPattens的参数,这个参数表示要过滤的URL上的后缀名,是多参数,可以用数组表示。
@WebFilter(value = "/*") // (filterName = "f1", urlPatterns = {"*.html","*.jsp","/hello"})
public class TestFilter implements Filter {
@Autowired
AsyncService asyncService;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@SneakyThrows
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
asyncService.task(1);
System.out.println("进入注解方式filter");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
Interceptor
@Component
public class InterceptorTest implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截器preHandle在控制器方法执行前执行");
//true:表示放行
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("拦截器postHandle在控制器方法执行后执行");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("拦截器afterCompletion在请求完成后执行");
}
}
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Resource
private InterceptorTest interceptorTest;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// ** 表示所有拦截路径
registry.addInterceptor(interceptorTest).addPathPatterns("/**");
// // 或下面这种写法 【若编写自定义拦截器类没有加@Component注解】
// registry.addInterceptor(new interceptorTest()).addPathPatterns("/**");
}
}
aop
springboot中的aop配置(hello world)及统一异常处理_springboot aop异常处理_子书少卿的博客-CSDN博客
todo:
过滤器修改请求参数
过滤器中注入bean的方式(有出入)
多过滤器时(两种方式混合),默认顺序和顺序控制
参考资料:拦截器、过滤器、AOP的区别和联系_过滤器和aop_可爱发的博客-CSDN博客