00:00
适配器这个设计模式呢,在哪里用到了,在spring mvc这个框架里面呢,咱们用到了适配器这种设计模式,我们来分析一下。在spring mvc呢,有个叫handler adapter,大家应该有些印象。就说学过spring mvc的同学呢,应该有些印象,对吧,他在这里呢,用到了适配器。这个模式,那首先呢,我们简单的回顾一下spring mvc它的一个请求,一个request请求的一个流程,我们打开这个图看一下,这个图呢,我已经打开了,我们来看。他大体的流程是这样子的,我们以一个用户登录来说,比如说我这里输入用户名跟密码,然后我把这个请求呢,发给了这个dispatch。这个dispatch里面呢,它有一个方法叫do do dispatch是吧,进行一个请求,进行一个处理。那么他在这里处理的时候呢,他首先通过这个handler m去找到。
01:06
用户希望请求的这个handler。其实这个harder呢,是个control,就是一个控制器。只是呢,以不同的请求方式,我们拿到的这个handle,那呃,Handle从大的这个范畴来说也是一个control嘛,对吧?呃,就是说找到他的一个处理器,找到这个处理器以后,同学们他就执行这个方法。那在执行方法的时候,这里面就有关键了,它怎么来执行这个目标方法呢?这边会用到我们适配器,待会呢看源码可以看到它执行完了过呢,会返回一个model and view这个结果,拿到这个结果以后。这个PI呢,会去调调用这个internal resource view。呃,View,呃,Resolve来返回来,对这个返回的model and view进行解析,找到这个资源,找到这个资源以后,这个老呃,这个JSP呢,就会去执行他的代码,执行完了过后把这个结果封装成一个字符串返给我们的这个汤姆凯特,然后汤姆凯特把这个字符串以HTP这种协议的方式返回给我们浏览器,浏览器拿到结果过后解析。
02:19
大致的流程就这样子的。同学们要注意的是,在这里。在这里呢,我们会去根据不同的请求追听,是根据不同的请求拿到一个handler,然后在执行这个目标方法的时候呢。他要根据什么呀,他要去根据你的这个handler不同来来处理,来去执行,可是我怎么知道执行哪个方法呢?这里会就就会用到不同的我们这个适配器来处理,那么我们看一下源码,大家一下就明白了,来追追源码。打开这个spring代码,在这个test里面呢,我写一个代码,这个代码现在我们研究是adapter adapter没问题。
03:01
把这个写上,我们从哪里开始追呢?同学们看一下,我们从这个地方开始追。我们在这里用到了这一个。啊,这个最核心的这个类。这个类是在这好,我们看一下在哪里呢,在这。叫dispatch。那我们来追一追,把这个源码打开。把这个源码打开过后呢,我们往下面看,就是当一个请求来的时候,Pach会用dopa来处理,在哪里找到这个方法?度这个方法。找一下这。对,就do do dispatch,那同学们可以看到这个do dispatch呢,会接收到这个request。那么同学们可以看在这里有一个核心的方法,方法在哪里,我们一步步找哈,找最管用的,找这大家看这。在这儿,诶我找一下。
04:02
在哪里啊,在这,同学们看到。呃,同学们有没有去研究这个源代码啊,没有研究,你听我说哈,他根据你这个process request。这个process request就就是一个request,就就就是你这个请求,你这个请求,根据你这个请求呢,我得到一个handler,同学们,这个handler其实就是我们的control,就是我们的控制器明白。好,拿到这个控制器以后,下一步。他拿到这个控制器以后,看关键的代码在这。把这个handler通过这个返回的MYMY的handler得到它的控制器,然后返回一个什么呀?Handler adapter就是适配器,那为什么要返回一个适配器呢?就是因为我不同的handler,我要用不同的适配去去调用相应的方法进行处理。那么我们来看一下这个源码是怎么跑的,大家可以看到get handler呢,其实它这个返回的是handler adapter handler adapter其实是个接口,我们往里面追一下。
05:08
同学们可以看到它使用这个接口,那么这个是一个adapter的接口,那么实现具体实现我们这个adapter,它具体的适配器实现的内容哪些呢?我们来看一下,注意一下它的源码。同学们可以看到在。同学们看在这个handler adapter。这个适配器接口下面呢,有各种各样的适配器。大家看哪些是你们熟悉的,是不是这个很熟悉啊,Http request handler,有些同学可能用过这个。有些同学可能还用过这个是吧,Simple control handler adapter,还有这个simple service handler adapter,也就是说我们这个适配器呢,其实这个接口下面有有好几个具体的实现这个适配器接口的适配器类。
06:01
OK,那么同学们通过这个源码大体应该知道,就是大体我们可以看到它是怎么来得到的啊,我们再追一下源代码。首先看流程,他先拿到request。拿到这个request过后呢,把它交给了一个HTTP,这个service request,通过这个request,他拿到我们的一个。在这拿到一个handler。通过这个handlener。就是通过这个controller,这个handleer,从大的领域来说就是个control,通过这个呢,我们得到对应这个controller,对应的这个adapter。那怎么拿到看源码来看,其实啊,他是在这里做了一个for循环。大家有发现没有,就是他在这个地方便利我们所有的这个handler adapter,那如果说他发现支持就是这个,这个是为帧,它就返回这个适配器。那同学们要知道,在我们这一个,在我们这个handler adapter这个接口里面,其实就有一个方法就是support,我们看一下是不是这样子的,注意一下。
07:08
这边看。这里边儿是不是就是有几个核心的方法,一个是support,一个是handle。Handle就是处理嘛,处理什么什么什么对不对,好回到我们这个源码。当他根据这个get handle handler adapter返回我们这个请求对应的适配器过后,它又怎么办呢?往下走。同学们往下走,走到这儿来了,我要他在这儿啊,同学们看这里。拿到这个,拿到这个适配器以后,适配器会去调用一个方法,就这核心的方法,Hand hand。这是实际调用的handle。也就是说通过这个适配器,注意听通过这个适配得到的这个适配器去调用我们这个controller的handle的方法。就是你这个handleer,其实就是control,再说一遍,就是通过这个来调用handle,而这个handle这个方法呢,就是我们那个适配器里面。
08:07
要去做的一个方法,大体就是这样一个流程,好,我们再根据这个思路再来走一遍,大家看是这样子的啊,首先呢,我们会去通过这个handle的mapping获取一个control,这个control就是反映到我们spring MV mvc呢它也叫handleler,拿到这个handler过后,通过这个handlener去得到一个适配器。这个适配器是。哪一种是要跟他匹配的?然后我们再通过这个适配去去调用controller的方法,并返回一个model and view。OK,好,大体流程这样子的,那么它在这个方法里面就是get handle方法,它怎么拿的,它在这里面有一个for循环,如果这个support为真,它就返回了。OK,那他在这个handle方法,它是怎么处理的呢?这个那不同的不同的这个呃,实现就处理机制就不一样。
09:05
好,呃,大体的这个流程大家应该可以看出来,我们这再总结一下,就handle map的实现,指类呢,有多种,使得每一种controller有一种对应的适配器实现。种类,每每一种controller有不同实验方式。也就是说实际上是通过适配器去调用我们controller的这个方法来进行。请求的处理。来进行请求的处理,所以说大体这个,如果我们画一个类图的话,大概是这样子的,同学们注意听哈,说这边有control。也就是我们所说的handler。那么下面呢,有具体的各种control。视线内,我们这边呢,还有一个adapter。Adapter。Adapter好啊,Adapter下面呢,也有具体的adapter。
10:02
OK,然后在这个do get,呃,Do do这个这个PA这个方法里面呢,它依赖这个,再依赖这个。他先干什么呢?呃,他先是去根据你这个请求拿到一个control,然后再根据这个这个controller或者handle呢,返回一个adapter,然后让这个adapter去调用这个方法去,Adapter是这个adapter是调用这个controller方法来实现这个处理,它是这样一种流程。就是说通过相相应通知通过这个adapter这个适配器呢。呃,关联起来对controller的一个调用。啊,大家可能这样听着是不是有点晕了啊,我相信听的有点晕,但怎么办呢?让大家听得更明白一点呢?我想了一个办法。想了一个什么样的办法呢?就说我们这个是spring mvc,它框架里面的源码,我想了这样一个办法,大家看看能不能呃更容易让大家理解我们呢,手,我们动手写一个MVC,通过适配器设计模式获取到对应CTRL的源码,我们自己写一遍。
11:11
就是我们把它核心的代码拎出来给他看一下,这样子呢,大家就能体会到这种适配器模式的一种使用,好吧,那这样子啊,因为这个源码我这已经有了,我我也我我倒先先把这个画下画下画一个这个图来看一下。好,现在呢,我们我们还回到这个位置,因为刚才讲的是adapter,说说我在这写一段代码,大家看看能否理解哈。啊,我我看我怎么去写一段代码呢。嗯,在这吧,在这个spring里面,我们写段代码来模拟它,比如说现在我们写一个叫做spring。注意听讲MVC这个框架。好的,那这里面有些核心的代码我已经有了,因此呢,我就不想写了,为什么?因为并不难,我核心就是这么三个类。
12:02
Control dispatch类的和handle adapter是不是这是不是它最核心的呀,我把它拿过来。放到这边来。哦,OK,这样这样子还不行,我得把这个这样打开哈。哦,就重新再打开一次。把它打开。打开,然后我先复制过来。复制到这边。附到我的桌面,然后呢,再从这个桌面把它剪过来就没问题了。好,剪过来了,剪过来,我们先来看一下这个流程哈,先先把这个改一下,包改一下。这边这个包呢,我们也改一下。因为这这面包跟我不一样。把handle my adapter也改一下。好,同学们看一下,那为了让大家看清楚这个呢,我们先把这个流程走一走,首先。Control,这个control里面有个接口叫control,下面呢有http control,就是我,我会根据你不同的请求,我会呃返回不同的controller,呃,这个这个对象有simple,有all notation,这个controller,也就是说这个之间的关系,如果我们画一个类图的话,它是这样子一个关系,注意听讲。
13:19
好来走一个哈,不着急,相当于说我这有个接口。这个接口呢,叫control。把这个核心讲出来啊,Control。康。Control。Control,诶,这个单词别写错了啊,看看这个单词怎么写比较好,对的啊,Come。Control好这样写的,这接口那下面呢,我们有各种类。哦,我们刚才看是不是有个http control。对吧,好,还有什么类呀。还有一个simple simple control。
14:01
是不是还有什么没有啊?啊,应该说还好像还有一个类,我们看一下。还有一个这个。这个control OK,放这来。那么这三个controller呢?他们实现了这个接口。是这样子的吧,同学们实现了这个接口。好的。这是control。那么我们还有适配器。适配器这边呢,我们取的名字叫做handler。Adapter是个适配器,适配器呢,它是个接口,最先进是个接口,我写上这叫handler。Handler doctor。Adapter吧。好,这个适配器里面呢,下面有哪些适配器呢?那刚才大家看源码里面是不是有好些种啊,有好些种,那我这里面就模拟了一下,我写了这么几种。一个是simple handler啊,这个adapter。好,这是一个,我还写了一个,还写了一个什么呢?Htdhttp handler adapter,注意听讲哈,这个就说你理解了以后就会很轻松。还有一个是不是,我记得好像还写了一个是呃,Notation。
15:15
这个handler adapter,好,也把它写过了。那大家可以看到现在其实他们是一一对应的关系,我我先这样画一下。同样他这几个adapter呢,也是去实现了我们这个接口没问题吧。大家看我们这个simple handler simple,呃,Simple control simple handler adapter,这有个htp control,这个h http handler adapteration control有个all notation handleer,那么他们之间。会存在什么关系吗?是诶,这个画错了,大家看。这个这个图啊,大家看在我们这个方法里面,在handle adapter里面,我们是怎么做处理呢?进去看一下。
16:03
看这里。这一个接口里面就有POS和hand这个方法,大家还记不记得我们在刚才追源码的时候,追源代码的时候,这个handler adapter是不是也有这两个方法呀?是不是和这个handle还还有印象吗?同学们可可能有点忘了,呃,我们再看一下。就是。呃。就是我们这儿不是。不是这拿到一拿到了这个handle adapter吗?对吧,我们追到这里面去看一下。是不是这个接口里面就有suppose,还有一个handle对吧,这是我们这两个最核心的方法,我在这呢也把它画出来了。好的,那现在还差一个什么呢?OK,把这个这边太小了,往那边挪一下,还差一个调用者就是第4PACH。我把这个呢也拿过来。这个类。
17:01
好,同学们可以看到。在这里我有一个类。那这个类里边它有一个核心的方法,它一个核心的方法,同学们可以看到这个核心方法就是什么呢?就是这个do dispatch。是不是啊,度。就这个。我这儿写到这儿来。叫do dispatch,那么在这个dispatch里面呢,它里面有所有的handle,这个这个它有个集合,把所有的handle都放进去了,也就是说他把什么组合进去了呢?在这里。他把这个组合进去了。组合的时候是多个。大家可以看到,在dispatch这里面呢,我做了一个list,里面有handler adapter,在初始化的时候,我把这三个adapter全部放进去了,放到这个历史的集合了。放到历史集合了,那在这里面,呃,我们这个。Dispatch会怎么样,会使用到?
18:01
他会依赖这个control。这样的一个关系,好,同学们有发现啊,Handleer这个adapter,它会去调用CR里面方法,它是怎么调用的呢?我们来看一个方法,也就是说。也就是说这个里面啊,比如说他会用到他。OK。HT。他。而我们这个a notation handler map会用到它,这是它是怎么用的呢?来看一下源码对不看。我们以这个simple handler来为例,它首先呢会实现我们这两个方法,在这里handle的时候,他如果发现。他把这个接收到的这个handle拿过来,他强转。强转,也就是说他当然他首先要判断你,你确实是这个类型,他才会去去会去强转的啊,所以这个s po呢,呃,这个的方法是用来判断是不是看到没有,它先调说你传进来的这个handler。
19:05
也就是我们说这个control啊,因为handler在从大的领域来说就是一个控制器,它先判断你传进的这个。这个handler是不是一个simple control,如果是我再去调用handler,然后在在用的时候呢,我我这个地方先把它转成simple controller,然后去调用这个controller里面的do simple handler,那这个方法在哪里写的呢?这个方法写的是在simple controller里面写的,大家看一下是不是这样子的。是不是OK,所以说所以说这个这个流程就这样子的了,就是在dope里面,我们先根据他的请求拿到control,再根据这个control去获取我们的。对应的这个adapter,然后通过这个adapter去调用。控制器里面的方法,这样呢,相当于说我们就通过适配器的一种方式建立了这两者之间的联系,因为我们希望的是通过这个control来找到对应的。
20:10
这个设备去进行进行这个调用和处理好,这个流程就是这样子来的啊,大家看能不能理解。啊,能不能理解好这个这个线条这样画一下。好把这个隔一下啊。这上面拉下。大题能应该能理解哈,应该能理解好,我们来把这个代码呢给大家跑一下,大家就明白了,来走一下。好,呃,看一下这个是读,首先呢,假如说我们这拿到的是这一个control,然后呢,我get handler的时候,把这个controller放进去,就拿到了我们适配器,再用这个适配器调handleler,这个适配器调用的就是controller对应方法,谁的哪一个controller的呢,它的。OK,那如果说他你得到的是这个这个control,那调用就是这个controller的这个这个handle方法,以此类推。
21:02
啊,Get handle什么get呢?我跟那个源码写的一样,先变历。便利。便利就说我先在这边已经拿到一个control了,然后呢,我通过这个呃,便利的方式,我发现你这个control跟我这个适配器匹配,我就返回这个适配器,也就便利是根据。根据得到的得到的这个control。或者说你们可能有些同学叫handler。诶,Handleer,我看这有handleer啊,来干什么呢?返回或者要得到对应的适配器。四倍器是不是这样子的,你看如果支持我就返回,得到以后呢,呃,在返回去过后,再用这个adapter去调用handle。这个handle肯定就是根据你把这个control的这这个拿到了是吧,Control里面是该怎么做就怎么做就完了,好这里面我做了一个简单适应,就是六了一个dispatch,然dopa,那如果不出什么意外,这边他应该调用的是all notation这个control里面的方法及哪个方法呢?
22:15
即我们这个controller的allocation这个方法,即他会说出这句话。也就是说,如果我这边没有做变化,他应该输出是all,这句话我们运行一下。啊有点绕是不是,你看是这样子的吧,是这样子的,那如果说我把这一个,我把这我们现在。嗯,不小心,我们得到的不是这种controller,而是上面的control。你不用做任何变化,你发现没有。它会自动的去。适配也就适配器的价值就在你,适配器的价值就是在于,只要你这个控制器变化了,我这边适配器有变化,我调用的你的方法也会变化,呃,就是这个意思,他中间做这种适配缓冲。好,那如果是这样子的话呢,他最终调的是这个http control里面方法及哪个方法呢。
23:06
记这个方法。那这个时候返回的就应该是HTTP。这这句话能理解我的意思吧?对不对,我在运行着。我在运行,你看这个返回的是这个了。好,同学们,我相信通过这个这个方式的去讲解呢,可能比刚才理解的多少要深入一点了,对不对,尽管有可能还是不是特别的明白,但肯定要比刚才要理解的更深入一点。就是这这这个图还是话还是很清晰的把他们关系描述出来了,那这样子以后我们要去做这个处理的话呢,就非常简单,呃,怎么样简单呢,大家看。适配器扩展controller的时候,只需要增加一个适配器内就完成了spring mvc的扩展,这个就是我们设计模式的一种力量。是不是,呃,你因为你变变化并不大嘛,变化并不大。
24:02
好呃,以后你要变的就是这块,如果我们这加一个。我就说这这里面的代码不需要变。就你使用方是不需要变化的。他完全满足我们OCP的原则,比如说我又加了一个,假如说啊,我我又加了一个。Other。Other control。R control,然后呢,我去。我去实现这个。哎,这个件是实线,哎,这写错了,画的应该是这根线哈。应该是一个线虚的。实现了,那把这个写完了过后呢,同样我们在这边再写一个类。再写一个什么呢?叫做other。R,什么呀?就是我们handler。Handler adapter。是不是这样的道理?然后呢,这个这个适配器,我们仍然去让它。
25:01
去实现这个方法。好,同学们,当我们把这两个一分架构这个代码就是同学们发现调用方。就是我们去使用,使用去处理这个请求的这个地方需要变化吗?同学们不需要变化,是不是不需要变化,因为你请求的这个类型是什么,我就会去适配到。对应的这个适配器,并调用它的方法,而且这两个还是隔适配器和这个控制器的是分离的,所以他们之间还有解耦的这个效果,所以这个方式呢,还是very OK的还是very OK的好,同学们关于源码呢,老师就只能讲到这个份上了,希望同学们能够呃认真的去体会这种设计模式的力量。就是因为有些东西需要我们去理解,就是很难,可能老师讲完了过后,你还是有点模模糊糊的,但是不要紧,就是你多去理解一下。啊,多去看一下源码,就能够逐渐的理解适配器它这种模式的一种价值。
26:04
好,关于这一这个源码分析,我们就聊到这里。
我来说两句