当前位置: 首页 > news >正文

Java中的拦截器和过滤器有什么区别

本文收录于JavaStarter ,里面有我完整的Java系列文章,学习或面试都可以看看

(一)什么是过滤器

过滤器Filter基于Servlet实现,过滤器的主要应用场景是对字符编码、跨域等问题进行过滤。Servlet的工作原理是拦截配置好的客户端请求,然后对Request和Response进行处理。Filter过滤器随着web应用的启动而启动,只初始化一次。

Filter的使用比较简单,继承Filter 接口,实现对应的init、doFilter以及destroy方法即可。

1、init:在容器启动时调用初始化方法,只会初始化一次

2、doFilter:每次请求都会调用doFilter方法,通过FilterChain 调用后续的方法

3、destroy:当容器销毁时,执行destory方法,只会被调用一次。

下面是详细的代码编写方式:

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方法。

1、preHandle:请求方法前置拦截,该方法会在Controller处理之前进行调用,Spring中可以有多个Interceptor,这些拦截器会按照设定的Order顺序调用,当有一个拦截器在preHandle中返回false的时候,请求就会终止。

2、postHandle:preHandle返回结果为true时,在Controller方法执行之后,视图渲染之前被调用

3、afterCompletion:在preHandle返回ture,并且整个请求结束之后,执行该方法。

具体的代码实现如下,首先编写一个拦截器:

@Component
public class UserInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle");
        String userName=request.getParameter("userName");
        String password = request.getParameter("password");
        if (userName==null||password==null){
            response.setStatus(500);
            response.setContentType("text/html; charset=UTF-8");
            response.getWriter().print("参数缺失");
            return false;
        }
        //进行用户校验
        if (userName.equals("admin")&&password.equals("admin")){
            return true;
        }else {
            response.setStatus(500);
            response.setContentType("text/html; charset=UTF-8");
            response.getWriter().print("用户名或密码错误");
            return false;
        }
    }
    @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");
    }
}

编写完拦截器之后,通过一个配置类设置拦截器,并且可以通过addPathPatternsexcludePathPatterns执行哪些请求需要被拦截,哪些不需要被拦截。

@Configuration
public class MvcConfig implements WebMvcConfigurer {
    @Autowired
    private UserInterceptor userInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(userInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/error");
    }
}

(三)拦截器与过滤器的区别

相同点

1、拦截器与过滤器都是体现了AOP的思想,对方法实现增强,都可以拦截请求方法。

2、拦截器和过滤器都可以通过Order注解设定执行顺序

不同点

1、过滤器属于Servlet级别,拦截器属于Spring级别
Filter是在javax.servlet包中定义的,要依赖于网络容器,因此只能在web项目中使用。

Interceptor是SpringMVC中实现的,归根揭底拦截器是一个Spring组件,由Spring容器进行管理。

2、过滤器和拦截器的执行顺序不同

下面通过一张图展示Filter和Interceprtor的执行顺序


首先当一个请求进入Servlet之前,过滤器的doFilter方法进行过滤,

进入Servlet容器之后,执行Controller方法之前,拦截器的preHandle方法进行拦截,

执行Controller方法之后,视图渲染之前,拦截器的postHandle方法进行拦截,

请求结束之后,执行拦截器的postHandle方法。

3、过滤器基于函数回调方式实现,拦截器基于Java反射机制实现

(四)总结

实际开发中,拦截器的应用场景会比过滤器要更多,下面是拦截器和过滤器的主要应用场景

拦截器的应用场景:权限控制,日志打印,参数校验

过滤器的应用场景:跨域问题解决,编码转换

我翻了一下历史项目的代码,拦截器在用户权限校验场景下使用会比较多,由于一般是前后端分离项目,过滤器的使用场景就会少很多。

拦截器和过滤器算是比较常用的了,但是还是得注意两者的差距,我是鱼仔,我们下期再见!

相关文章:

  • 为什么要引入分布式任务调度系统?
  • 为什么说datax是目前最好的异构数据源数据交换工具
  • Java常用关键字:this、super、final、static、访问修饰符
  • JAVA UUID 生成唯一标识
  • 网络开发的最强大框架:Netty快速入门
  • 适配器模式详解与应用
  • 树莓派 - 使用须知
  • 粘包和半包有了解过吗?netty是如何解决这个问题的
  • 云计算与SOA之我见
  • 迭代器模式:理解与实践
  • [转]MySQL排序原理与案例分析
  • 深入浅出CMS垃圾收集器
  • php.ini中的session配置说明
  • 如何上传自己的jar包到maven中央仓库(2021最新版)
  • ElasticSearch聚合查询Restful语法和JavaApi详解(基于ES7.6)
  • [分享]iOS开发-关于在xcode中引用文件夹右边出现问号的解决办法
  • [译]CSS 居中(Center)方法大合集
  • Android 架构优化~MVP 架构改造
  • Apache Pulsar 2.1 重磅发布
  • CSS魔法堂:Absolute Positioning就这个样
  • IndexedDB
  • JDK9: 集成 Jshell 和 Maven 项目.
  • oschina
  • Spring Boot MyBatis配置多种数据库
  • 从PHP迁移至Golang - 基础篇
  • 关于使用markdown的方法(引自CSDN教程)
  • 聊聊sentinel的DegradeSlot
  • 使用 Node.js 的 nodemailer 模块发送邮件(支持 QQ、163 等、支持附件)
  • ​Spring Boot 分片上传文件
  • #HarmonyOS:软件安装window和mac预览Hello World
  • (a /b)*c的值
  • (C++)八皇后问题
  • (done) ROC曲线 和 AUC值 分别是什么?
  • (分布式缓存)Redis哨兵
  • (附源码)spring boot北京冬奥会志愿者报名系统 毕业设计 150947
  • (十三)Flask之特殊装饰器详解
  • .jks文件(JAVA KeyStore)
  • .Net6使用WebSocket与前端进行通信
  • .net开源工作流引擎ccflow表单数据返回值Pop分组模式和表格模式对比
  • /etc/skel 目录作用
  • ?.的用法
  • @Bean注解详解
  • @WebServiceClient注解,wsdlLocation 可配置
  • [51nod1610]路径计数
  • [CERC2017]Cumulative Code
  • [CF407E]k-d-sequence
  • [cocos creator]EditBox,editing-return事件,清空输入框
  • [Gym-102091E] How Many Groups
  • [HackMyVM]靶场 Quick3
  • [hihocoder1395] 最大权闭合子图
  • [HTML]Web前端开发技术7(HTML5、CSS3、JavaScript )CSS的定位机制——喵喵画网页
  • [Java算法分析与设计]--线性结构与顺序表(List)的实现应用
  • [LeetCode] Sort List
  • [MQ]常用的mq产品图形管理web界面或客户端
  • [MySQL FAQ]系列 -- 账号密码包含反斜线时怎么办