过滤器Filter
定义
对Servlet容器调用Servlet的过程进行拦截,基于函数回调实现
常见使用场景
- 统一设置编码
- 过滤敏感字符
- 登录校验
- URL级别的访问权限控制
- 数据压缩
使用方式
这了展示的是SpringBoot整合过滤器的方式,
使用配置类的方式(bean注入)
- 编写filter类并实现Filter接口,
- 实现Filter接口中的init,doFilter方法,与destory方法
- doFilter方法中使用(request, response);来放行servlet
- 编写Filter配置类,注解加上@ConFiguration注解
- 编写方法,返回值类型为FilterRegistrationBean ,
- 方法内创建FilterRegistrationBean对象,构造器内传入过滤器类的对象,直接new一个就可以,或者让Spring容器自动注入后再使用
- 调用FilterRegistrationBean 对象的addUrlPatterns方法类设定过滤的请求路径,
过滤器类
@Slf4j//方便使用下面的()方法输出日志
public class LoginCheckFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
log.info("过滤器{}正在生效",LoginCheckFilter.class.getName());
log.info("过滤器{}拦截到了请求{}",LoginCheckFilter.class.getName(),request.getRequestURI());
filterChain.doFilter(request,response);
log.info("请求{}已经被放行",request.getRequestURI());
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("过滤器{}被初始化",LoginCheckFilter.class.getName());
Filter.super.init(filterConfig);
}
@Override
public void destroy() {
log.info("过滤器{}被销毁",LoginCheckFilter.class.getName());
Filter.super.destroy();
}
}
配置类
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<LoginCheckFilter> filterRegistrationBean() {
FilterRegistrationBean<LoginCheckFilter> loginCheckFilter = new FilterRegistrationBean<>();
loginCheckFilter.setFilter(new LoginCheckFilter());//注册自定义过滤器
loginCheckFilter.setName("LoginCheckFilter");//过滤器名称
loginCheckFilter.addUrlPatterns("/*");//过滤所有路径
loginCheckFilter.setOrder(1);//优先级,最*按照数据从小到大来执行过滤器
return loginCheckFilter;
}
}
使用注解@
- 创建过滤器类,方法与上面创建过滤器类的步骤一样
- 过滤器类上面添加注解 @WebFilter(urlPatterns = {“拦截路径”}, filterName = “过滤器名称”)
- 在启动类上添加@ServeltComponentScan注解来扫描servlet组件(包括:@WebFilter和@WebListener)
注意,使用注解方式无法控制多个过滤器的顺序,()默认执行顺序是按照类名字母的排序,
使用@Order注解控制Bean的执行顺序时,必须配合注解一起使用,才会起作用
但是@Component与@WebFilter注解都会把过滤器类加载一遍,并且@component会把@WebFilter加载的Bean覆盖掉,从而使得@WebFilter配置的拦截路径与过滤器名称失效,
所以如果指定了优先级则配置的拦截路径失效,默认为任意路径,如果不使用@Order注解则无法控制多个过滤器的执行顺序,
综上笔者这里推荐使用Bean注入的方式来使用过滤器
总结
- Filter是依赖于Servlet的,需要导入Servlet的依赖
- 过滤器会在容器启动时被初始化,并且只会初始化一次
- doFilter()方法在目标请求被拦截前执行,放行调用(servletRequest,servletResponse);具体变量名根据方法体而变
- destroy()方法在容器销毁时执行,只执行一次
- Filter可以拦截所有请求,包括静态资源,
- 过滤器基于函数回调实现,
扩展
- 过滤器,监听器和Servlet是JavaWeb三大组件之一,它们的在SpringBoot中的使用方式都差不多区别如下
- 使用注解方式使用时都需要在启动类加上@ServletComponentScan注解
- 三个注解为@WebSrvlet,@WebFilter和@Weblistener
- Servlet类继承的是HttpServlet,Filter实现的是Filter类,Listener实现ServletContextListener类
- 使用Bean注入方式使用时,Filter组件方法返回类型是FilterRegistrationBean,Listener组件方法返回类型为ServletListenerRefistrationBean,Servlet组件返回类型为ServletRefistrationBean
拦截器Interceptor
定义
类似于Servlet中的过滤器,主要用于拦截用户请求并做相应的处理,基于java反射机制(动态代理)实现
常见使用场景
- 日志记录
- 权限校验
- 登录校验
- 性能检测[检测方法的执行时间]
其实拦截器和过滤器很像,有些使用场景。无论选用谁都能实现。需要注意的使他们彼此的使用范围,触发机制。
使用方式
- 编写拦截器类并实现HandlerInterceptor 接口
- 实现HandlerInterceptor 接口的preHandle,postHandle和afterHandle方法
- 编写配置类,注意加上@configuration注解,并继承WebMvcConfigurer接口
总结
- 拦截器依赖于SpringMvc的,需要导入Mvc的依赖
- preHandle() 在目标请求完成之前执行。有返回值Boolean类型,true:表示放行
- postHandle() 在目标请求之完成后执行。
- afterCompletion() 在整个请求完成之后【modelAndView已被渲染执行】。
- 拦截器只能拦截action请求,不包括静态资源(有待验证)
- 基于java反射机制实现
版权声明:本文为****博主「Hekliu」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:/liu59412/article/details/122208904
拦截器不生效原因分析
- 配置类没有加@configuration注解
- 拦截路径出错,/*拦截当前目录,/**拦截所有目录
- WebMvcConfigurationSupport,WebMvcConfigurer,WebMvcConfigurerAdapter项目中不能有两个以上的类继承或实现自这三个类 因为这三个类都是WebMVC的配置类,如果同时出现只会有一个类生效,一般实现WebMvcConfilgurer就可以了
过滤器与拦截器的区别
- 触发顺序不一样,
- 过滤器的触发顺序在拦截器前,也就是先执行过滤器,在执行拦截器, 过滤前 - 拦截前 - Action处理 - 拦截后 - 过滤后。
- 过滤器之间的执行顺序嵌套的,
- 但是拦截器执行顺序也是嵌套执行的但是,因为有三个方法,会先执行pre方法,再一起执行post方法,最后一起执行after方法
- 实现方式不同,过滤器基于函数回调实现,拦截器基于动态代理(反射)实现
- 拦截器是基于java的反射机制的,而过滤器是基于函数回调。
- 拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
- 拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
- 拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
- 在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次
- 拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。
aop与过滤器,拦截器的区别
- 过滤器,拦截器拦截的是URL。AOP拦截的是类的元数据(包、类、方法名、参数等)。
- 过滤器并没有定义业务用于执行逻辑前、后等,仅仅是请求到达就执行。
- 拦截器有三个方法,相对于过滤器更加细致,有被拦截逻辑执行前、后等。
- AOP针对具体的代码,能够实现更加复杂的业务逻辑。
- 三者功能类似,但各有优势,从过滤器 -> 拦截器 -> 切面,拦截规则越来越细致。
- 执行顺序依次是过滤器、拦截器、切面。
推荐阅读
过滤器,拦截器,aop区别与使用场景_Hekliu的博客-****博客_过滤器和拦截器的区别和使用场景
SpringBoot中使用过滤器_Lyzxii的博客-****博客_springboot 过滤器
过滤器与拦截器的区别_纸上得来终觉浅~的博客-****博客_过滤器和拦截器的区别和使用场景