小伙伴们应该听说过过滤器、拦截器、切面,印象上都能够起到截断拦截的作用,在做一些业务需求时,不知道如何选择,今天老顾就来介绍一下他们之间的区别。

过滤器可以拦截到方法的请求和响应 (ServletRequest request, ServletResponse response), 并对请求响应做出过滤操作。

过滤器依赖于 servlet 容器。在实现上,基于函数回调,它可以对几乎所有请求进行过滤,一个过滤器实例只能在容器初始化时调用一次。

使用过滤器的目的是用来做一些过滤操作,获取我们想要获取的数据,比如:在过滤器中修改字符编码;在过滤器中修改 HttpServletRequest 的一些参数,包括:过滤低俗文字、危险字符等。话不多说,先上代码。

再定义两个 Controller,一个 UserController,一个 OrderController

虽然 Filter 过滤器和 Controller 请求都已经定义了,但现在过滤器是不起作用的。需要把 Filter 配置一下,有两个方案第一个方案在 Filter 上面加上 @Component

@Component
public class TimeFilter implements Filter

第二个方案配置化注册过滤器

第二个方案的特点就是可以细化到过滤哪些规则的 URL 我们来启动应用时,过滤器被初始化了,init 函数被回调

请求 http://localhost:9000/order/1

看看控制台的日志输出

请求 http://localhost:9000/user/1

控制台日志输出

停止应用后,控制台输出

Filter 随 web 应用的启动而启动,只初始化一次,随 web 应用的停止而销毁。

  1. 启动服务器时加载过滤器的实例,并调用 init() 方法来初始化实例; 2. 每一次请求时都只调用方法 doFilter() 进行处理; 3. 停止服务器时调用 destroy() 方法,销毁实例。

正是金九银十跳槽季,为大家收集了 2019 年最新的面试资料,有文档、有攻略、有视频。有需要的同学可以在公众号【Java 知己】,发送【面试】领取最新面试资料攻略!暗号【1024】千万不要发,否则.....

我们再来看看 doFilter 方法

doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

从参数我们看到,filter 里面是能够获取到请求的参数和响应的数据;但此方法是无法知道是哪一个 Controller 类中的哪个方法被执行。还有一点需要注意的是,filter 中是没法使用注入的 bean 的,也就是无法使用 @Autowired

上面代码注入的值为 null。这是为什么呢

其实 Spring 中,web 应用启动的顺序是:listener->filter->servlet,先初始化 listener,然后再来就 filter 的初始化,再接着才到我们的 dispathServlet 的初始化,因此,当我们需要在 filter 里注入一个注解的 bean 时,就会注入失败,因为 filter 初始化时,注解的 bean 还没初始化,没法注入。 如果一定你要使用,需要做一些处理,可以私信老顾哦

依赖于 web 框架,在 SpringMVC 中就是依赖于 SpringMVC 框架。在实现上, 基于 Java 的反射机制,属于面向切面编程(AOP)的一种运用,就是在一个方法前,调用一个方法,或者在方法后,调用一个方法。

在 WebMvcConfigurationSupport 配置一下

执行结果

我们发现拦截器中可以获取到 Controller 对象

preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)

object handler 就是 controller 方法对象

HandlerMethod handlerMethod = (HandlerMethod)handler;

handlerMethod.getBean().getClass().getName(); 

handlerMethod.getMethod().getName(); 

但我们发现获取不到方法的参数值,这个是为什么呢?在 DispatcherServlet 类中,方法 doDispatch(HttpServletRequest request, HttpServletResponse response)。

applyPreHandle 这个方法执行,就是执行的拦截器的 preHandler 方法,但这个过程中,controller 方法没有从 request 中获取请求参数,组装方法参数;而是在 ha.handle 这个方法的时候,才会组装参数

虽然没法得到方法的参数,但是可以获得 IOC 的 bean 哦。

再说明一点的是 postHandler 方法

postHandler 方法的执行,当 controller 内部有异常,posthandler 方法是不会执行的。

afterCompletion 方法,不管 controller 内部是否有异常,都会执行此方法;此方法还会有个 Exception ex 这个参数;如果有异常,ex 会有异常值;没有异常 此值为 null

注意点如果 controller 内部有异常,但异常被 @ControllerAdvice 异常统一捕获的话,ex 也会为 null

AOP 操作可以对操作进行横向的拦截, 最大的优势在于他可以获取执行方法的参数, 对方法进行统一的处理。常见使用日志, 事务, 请求参数安全验证等。

上面的代码中,我们是可以获取方法的参数的

虽然切面 aop 可以拿到方法参数,但拿不到 response,request 对象。

我们这里来总结一下过滤器、拦截器、Aspect,看看区别

如果三者方式同时采用,那他们的执行顺序是什么呢?

filter -> interceptor -> ControllerAdvice -> aspect -> controller

返回值顺序,或异常返回顺序

controller -> aspect -> controllerAdvice -> Interceptor -> Filter

用一个图描述一下执行顺序

小伙伴们可以根据自身业务,和上面技术的各自特点,去选择相应的技术。今天老顾就介绍到这里,谢谢!!!


“不积跬步,无以至千里”,希望未来的你能:有梦为马 随处可栖!加油,少年!

关注公众号:「Java 知己」,每天更新Java知识哦,期待你的到来!

  • 发送「1024」,免费领取 30 本经典编程书籍。
  • 发送「Group」,与 10 万程序员一起进步。
  • 发送「面试」,领取BATJ面试资料、面试视频攻略。
  • 发送「JavaEE 实战」,领取《JavaEE 实战》系列视频教程。
  • 发送「玩转算法」,领取《玩转算法》系列视频教程。

程序员,你还不会合理选择Filter、Interceptor、Aspect?的更多相关文章

  1. 【译】x86程序员手册07 - 2.5操作数选择

    2.5 Operand Selection 操作数选择 An instruction can act on zero or more operands, which are the data mani ...

  2. 黑马程序员——C语言基础 流程控制 选择结构和循环结构

    ---恢复内容开始--- Java培训.Android培训.iOS培训..Net培训.期待与您交流! (以下内容是对黑马苹果入学视频的个人知识点总结) (一)流程控制 1> 顺序结构:默认的流程 ...

  3. 一个.Net程序员:既然选择了编程,只管风雨兼程(转)

    一个.Net程序员:既然选择了编程,只管风雨兼程 一次会议记录是不会有人感兴趣的,做标题党也是不道德的.所以,走了个折衷的路线,标题不叫会议记录, 内容不纯总结,技术加吐槽,经验加总结. 对于一个程序 ...

  4. 2018年,Java程序员转型大数据开发,是不是一个好选择?

    近日网上有一篇关于Java程序员职场生存现状的文章“2017年 Java 程序员,风光背后的危机”,在Java程序员圈子里引起了广泛关注和热议. 2017年,Java 程序员面临更加激烈的竞争. 不得 ...

  5. 你好,我是梁桐铭,.NET程序员,啰嗦下过去几年来的感悟吧

    序 所有的文章都会有序言,我的当然也不例外. 因为职业和工作的关系,很少有时间陪伴家人,感谢妻子10年以来的容忍和支持,感谢女儿给我生活带来的乐趣. 希望孩子长大了之后能热爱编程(可以不用以它谋生). ...

  6. 聊聊阿里社招面试,谈谈“野生”Java程序员学习的道路

    引言 很尴尬的是,这个类型的文章其实之前笔者就写过,原文章里,笔者自称LZ(也就是楼主,有人说是老子的简写,笔者只想说,这位同学你站出来,保证不打死你,-_-),原文章名称叫做<回答阿里社招面试 ...

  7. 十年京东Java程序员的工作总结,写给迷茫中的你!

    很多年前,刚刚从大学毕业的时候,很多公司来校招.其中最烂俗的一个面试问题是:“你希望你之后三到五年的发展是什么?”.我当时的标准回答是(原话):“成为在某一方面能够独当一面的技术专家“.后来经历了几家 ...

  8. BAT的关于程序员的那些事

    前言 你是否早有进入BAT公司的想法,但却因为对其不了解而在门外彷徨? 你是否想把技术团队打造成像BAT这些超级互联网公司,但却无从下手? 你是否已经进入了BAT,但是不知道如何晋升而苦恼? 那这篇文 ...

  9. IBM 总架构师:话说程序员的职业生涯

    作者:IBM 软件集团大中华区总架构师 寇卫东 有一些年轻的程序员向我咨询,将来的路应该怎么走?俗话说,条条大路通罗马.不同的路都能走向成功.到底选哪条路,取决于自己的兴趣.可能有程序员会问:如果还没 ...

随机推荐

  1. git上传本地项目到github或者gitlib(两个是一样的)。

    第一步:在github上面创建一个repository   点击create就好了.然后会出现下面的页面. 第三步:打开你所在文件夹,或者是新建的文件夹(用来做仓库的)右键会出现下面  选用git B ...

  2. SpringBoot 日志系统

    日志框架 开发一个大型系统的简易步骤: system.out.println("..") 将关键的数据在控制台输出 框架记录系统的一些运行时的信息,---日志框架. 牛逼的功能-- ...

  3. October 06th, 2019. Week 41st, Sunday

    Life is very capricious. 生命无常. Is life capricious? Maybe. But we can still make life a little more c ...

  4. JS数组去除空值

    /** * 扩展Array方法, 去除数组中空白数据 */ Array.prototype.notempty = function() { var arr = []; this.map(functio ...

  5. 开发一个这样的 APP 要多长时间?

    作者:蒋国刚 www.cnblogs.com/guogangj/p/4676836.html 这是一个“如有雷同,纯属巧合”的故事,外加一些废话,大家请勿对号入座.开始了…… 我有些尴尬地拿着水杯,正 ...

  6. Python函数(函数定义、函数调用)用法详解

    Python 中,函数的应用非常广泛,前面章节中我们已经接触过多个函数,比如 input() .print().range().len() 函数等等,这些都是 Python 的内置函数,可以直接使用. ...

  7. Cisco学习记录(二):路由及网络设备配置

    本篇我们利用cisco packet tracer搭建一个简单的网络.我们在左下方的设备中尝试选择创建两个4321路由器和一个3560-24PS Multilayer交换机,然后在左下方的电缆线中选择 ...

  8. 资深架构师教你String 常量池、 String.itern()

    什么是常量 用final修饰的成员变量表示常量,值一旦给定就无法改变! final修饰的变量有三种:静态变量.实例变量和局部变量,分别表示三种类型的常量. Class文件中的常量池 在Class文件结 ...

  9. C++ 深入浅出工厂模式(进阶篇)

    介绍 前文初始篇C++ 深入浅出工厂模式(初始篇),主要阐述了简单工厂模式.工厂方法模式和抽象工厂模式的结构.特点和缺陷等.以上三种方式,在新增产品时,要么修改工厂类,要么需新增具体的工厂类,说明工厂 ...

  10. cmdb项目-2

    1.命令插件异常处理 + 日志采集 1)为了更清楚发送客户端收集信息的状态 ,优化返回api的数据 ,变为字典存储 {状态 错误信息 数据} ,因为每个插件的每种系统下都要这个返回值我们将他单独做成类 ...