一文读懂拦截器与过滤器

2022-06-23 15:34:20 浏览数 (1)

1. 什么是过滤器

过滤器,顾名思义就是起到过滤筛选作用的一种事物,只不过相较于现实生活中的过滤器,这里的过滤器过滤的对象是客户端访问的web资源,也可以理解为一种预处理手段,对资源进行拦截后,将其中我们认为的杂质(用户自己定义的)过滤,符合条件的放行,不符合的则拦截下来。

1.1 过滤器常见使用场景

  • 统一设置编码
  • 过滤敏感字符
  • 登录校验
  • URL级别的访问权限控制
  • 数据压缩

1.2 springboot整合过滤器

bean注入方式 a) 编写Filter

代码语言:javascript复制
public class HeFilter implements Filter {
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}
	
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {
		System.out.println("您已进入filter过滤器,您的请求正常,请继续遵规则...");
		chain.doFilter(request, response);
	}
	
	@Override
	public void destroy() {
	}
}

b) 编写Filter配置类

代码语言:javascript复制
@Configuration
public class ServletConfig {
    
    @Bean
    public FilterRegistrationBean heFilterRegistration() {
        FilterRegistrationBean registration = new FilterRegistrationBean(new HeFilter());
        registration.addUrlPatterns("/*");
        return registration;
    }
}

注解方式

代码语言:javascript复制
@Slf4j
@Component
// filterName就是当前类名称,还有一个urlPattens的参数,这个参数表示要过滤的URL上的后缀名,是多参数,可以用数组表示。
@WebFilter(value = "/hello")或(filterName = "f1", urlPatterns = {"*.html","*.jsp","/hello"})
public class HelloFilter2 implements Filter {
 
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
 
    }
 
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
            FilterChain filterChain) throws IOException, ServletException {
        log.info("进入到过滤器2啦");
        filterChain.doFilter(servletRequest,servletResponse);
    }
 
    @Override
    public void destroy() {
 
    }
}
代码语言:javascript复制
在主启动类上加@ServletComponentScan("com.pandy.blog.filters")   指明filter所在位置的包。
若有多个filter,默认根据filter类名的字母倒叙排列,且@WebFilter注解方式的过滤器优先级高于Bean注入方式配置的过滤器

1.3 Filter过滤器详解

a) Filter是依赖于Servlet的,需要有Servlet的依赖。 b) init() 在容器初始化时执行,只执行一次。 c) doFilter() 目标方法之前拦截执行,拦截之后需要放行才开始执行目标方法。filterChain.doFilter(servletRequest,servletResponse); d) destroy() 在容器销毁时执行,只执行一次。 e) Filter可以拦截所有请求。包括静态资源[css,js...]。 f) 基于函数回调实现。 g) 过滤器只能在容器初始化时被调用一次。

2. 什么是拦截器

拦截器是springmvc提供的,类似于过滤器。主要用于拦截用户请求并作相应的处理。

2.1 拦截器常见使用场景

a) 日志记录 b) 权限校验 c) 登录校验 d) 性能检测[检测方法的执行时间] 其实拦截器和过滤器很像,很多使用场景。无论选用谁都能实现。需要注意的使他们彼此的使用范围,触发机制。

2.2 springboot整合拦截器

a) 编写自定义拦截器类实现HandlerInterceptor接口或集成其子类

代码语言:javascript复制
@Component
public class InterceptorDemo 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在请求完成后执行");
    }
}

b) 基于springmvc编写配置类

代码语言:javascript复制
@Configuration
// 老版本呢是继承WebMvcConfigurerAdapter不过新版本已经放弃了,推荐用下面的方式。
public class InterceptorConfig implements WebMvcConfigurer { 

    @Autowired
    private InterceptorDemo interceptorDemo;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // ** 表示所有拦截路径
        registry.addInterceptor(interceptorDemo).addPathPatterns("/**");
        // 或下面这种写法  【若编写自定义拦截器类没有加@Component注解】
        registry.addInterceptor(new InterceptorDemo()).addPathPatterns("/**");
    }
}

2.3 拦截器详解

a) 拦截器是依赖于SpringMVC的,需要有mvc的依赖。 b) preHandle() 在目标方法之前执行。有返回值Boolean类型,true:表示放行 c) postHandle() 在目标方法之后执行。 d) afterCompletion() 在整个请求完成之后执行。 e) 拦截器只能拦截action请求。不包括静态资源[css,js...]。 f) 基于java反射机制实现。 g) 在拦截器的生命周期中,可以多次被调用。

3. 拦截器与过滤器区别

1、过滤器和拦截器触发时机不一样,过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。 2、拦截器可以获取IOC容器中的各个bean,而过滤器就不行,因为拦截器是spring提供并管理的,spring的功能可以被拦截器使用,在拦截器里注入一个service,可以调用业务逻辑。而过滤器是JavaEE标准,只需依赖servlet api ,不需要依赖spring。 3、过滤器的实现基于回调函数。而拦截器(代理模式)的实现基于反射 4、Filter是依赖于Servlet容器,属于Servlet规范的一部分,而拦截器则是独立存在的,可以在任何情况下使用。 5、Filter的执行由Servlet容器回调完成,而拦截器通常通过动态代理(反射)的方式来执行。 6、Filter的生命周期由Servlet容器管理,而拦截器则可以通过IoC容器来管理,因此可以通过注入等方式来获取其他Bean的实例,因此使用会更方便。

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

①拦截器是基于java的反射机制的,而过滤器是基于函数回调。

②拦截器不依赖与servlet容器,过滤器依赖与servlet容器。

③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。

④拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。

⑤在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。

⑥拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。

拦截器可以获取ioc中的service bean实现业务逻辑,拦截器可以获取ioc中的service bean实现业务逻辑,拦截器可以获取ioc中的service bean实现业务逻辑,

触发时机

1.过滤器和拦截器触发时机不一样:

  过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。

1.过滤器和拦截器触发时间和地点不一样:

  过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。

1.过滤器和拦截器触发时间和地点不一样:

  过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。

总结:过滤器包裹住servlet,servlet包裹住拦截器。

如下图所示:

0 人点赞