首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

第二难的责任链模式,一个demo搞定他

责任链模式为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。责任链模式是为了避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。

来一起看例子吧,假如一个请求从前端传过来,我们需要对数据进行过滤处理,防止别人进行xss攻击,或者对某些敏感词做处理。来跟着我一步一步写代码吧

首先就是最简单的一个实体类,里面有msg属性,我们要过滤这个属性的内容,简单点就是用replace来进行替换

那每次要加一个新的规则就需要加新的代码,我们设计模式能这么干吗?那当然不能,我们来写一个过滤器做这些事情。过滤标签的就只过滤标签,过滤敏感词的就只过滤敏感词。这样降低了代码的耦合度。

有些人会说那这样没个过滤器我们都要去实例化并调用他的方法,那我们就给他放到集合中去处理

到这里呢,其实我们的消息经过了这样一层层的过滤最终才存入到了数据库中

当然到这里我们的责任链还没有写完,我们还没有给他串成一个链条,现在呢是一个个的filter往里面加,这个filter我们可以给他当成一条链,再写一个类FilterChain,你看这个名字,用大腿想想就有很多filter。所以我们把上面的list拿进来,然后要有一个add的方法,再然后我们要让里面的filter运行起来,就要有dofilter的方法

这里有人会说了,你这就是把原来的代码放到了filterChain中了,有什么区别吗?别急看完下面的代码你就知道区别在哪里了

新增加了一个过滤器来将笑脸换掉,然后又写了一个链条filterChain2,那么我们想要执行就要两个链条都执行一个dofilter的方法

我们还有更好的方法,我们让FilterChain 也实现Filter接口,这样就可以让两个链条连接在一起了

大家看看能够理解这样的写法吗?可以的话我们就继续,假如说我们在处理到f2的时候就结束了,不再往下面处理了,怎么办?

我们给Filter的doFilter一个boolean类型的返回值,这样就可以在实现类中进行逻辑判断,如果返回false,就不再执行后面的过滤器了

这个我们返回false,其他的都返回true

filterChain中判断dofilter为false就直接返回false,不再执行后面的filter了。运行之后

可以看到后面的替换笑脸的过滤器并没有执行

我们下面再模拟一下servlet的Filter 是如何实现一个chain 既过滤request,又过滤response,并且顺序是request是1,2,3 而response是3,2,1。

这个大家可以去查jdk中servlet的api文档,里面的处理原理就是我下面写的这样,我只是做了简化。

这里是定义了一个request和response,嫌麻烦没有写get 和 set方法。Filter中的doFilter 加了一个链条的参数,这个其实就类似于递归

在链条中加一个index来计数,用来表示执行到哪一步了,每次执行doFilter之前都对index进行++,相当于指定下一个filter

执行该方法后大家来看结果

可以看到按照我们上面说的,reqest 按照1,2来走的,而response是按照2,1来走的。写过递归的小伙伴肯定能更快的理解这个写法。有兴趣的小伙伴可以写一下然后debug模式走一走,可能就豁然开朗了。

这里画了一个草图,给大家解释一下执行流程:

首先就是main方法中调用的是链条中的doFilter方法,

然后第一次进来index是0,list中有两个filter,

链条中第一次调htmlFilter的dofilter方法,index变成1,

然后到htmlFilter中再次调用链条的dofilter方法,

这时index变成2,这次调用SensitiveFilter的dofilter方法,

然后在SensitiveFilter中再次调用链条的dofilter方法,这时index的值和list的size一致,return false,直接返回到了SensitiveFilter中继续执行给response处理数据,

然后返回到链条中,

再返回到htmlFilter中继续执行给response处理数据,

再返回到链条中,

最后返回到main方法中

各位小伙伴们好好思考一下。毕竟这是第二难的设计模式,多写多想。理解了这个模式,Struts2 的拦截器,jsp servlet 的 Filter等都是使用的这个模式,再去读这些源码的时候就更容易理解了。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20201118A0HHTL00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券
http://www.vxiaotou.com