00:00
接下来我们来测试一下订单确认页要用到的这些数据能不能正确查到。首先我们要查的第一个数据是我们当前会员的所有收货地址列表,那么的请求路径是这一块,这个路径还有点不对,我们这个整个完整的请求路径,我们一定要加上它的整个基准路径名,好把这个基准路径在这也复制过来,CTRLC。这是我们要调的第一个远程接口,我们先要获取我们当前会员的所有收货地址列表,然后呢,第二个接口获取我们当前登录的用户的购物车里面的所有数据,那同样的这两个方法都是查当前会员的一些信息,这是收货地址,这是购物车,我就给他打上两个断点,我们现在呢,以debug的模式来启动我们的订单服务,我们订单服务,购物车服务以及会员服务,我们牵扯到这些远程调用,我都以debug模式来给它启动起来,好,那同样来到我们这个首页,先确保呢,我们这一块的用户是登录状态来刷新一下,好登录状态看一下我们控制台整个有没有启动成功,好,我们现在控制台订单服务已经启动了,购物车服务也都启动了,以及我们的会员服务。
01:17
好,那现在呢,我们就来点击我们的这个购物车,来点击我的购物车,那就先来到我们的购物车页面。保证我们这个购物车里边呢,没有任何断点,我们可以先来看一下我们的所有断点,我们在这儿先来禁用掉所有断点,这个断点呢,我们现在只来开放上我们的这两个,我们来看一下我们所有的断点信息,现在只有订单服务和会员服务,我们呢打了三个断点,那就没问题,把其他断点都去掉,然后我们现在来进购物车,来点我的购物车,那先来到我们购物车的这个确认页,现在是登录状态没问题,而且我们之前改了bug,只有我们选中的商品这一块呢,才会参与购物车的总价计算,好现在当我们来点击去结算,我们来点击去结算,那就跳到我们的订单服务,那么订单服务呢,接下来就要进行远程调用,先来查询我们这个会员的收货地址,那么当前的这个会员,我们先来看一下我们登录的这个用户信息,那当前登录的会员ID是六,那六号这个会员我们来到数据库里边,会员呢,有一个收货地址列表,我们这一块呢,还没有我随机的。
02:25
来插入上一个值,比如六号,然后呢,他的手机号随便来写上一个行,我们就来插入上两个值就行了,那么现在呢,第一步我们先来远程查询我们会员的收货地址,走,那先来看我们第一步的远程查询能不能成功,那第一次访问呢,由于我们这个远程服务整个池都要初始化可能比较慢,我们先来看我们第一次,第一次呢,我们查到了这个数据,106,我们这一块呢都有好没问题,然后接下来第二次,第二次我们要获取购物车里边的数据,当然购物车跟我们的这个会员地址获取不一样的是,那获取会员地址呢,我们给他传了会员ID,当然购物车呢,我们给他没传,我们让购物车自己决定,想让我们购物车来看一下,来到我们的购物车这个方法里边,如果他要自己决定,他肯定是用这个拦截器,先来看登录状态,好们来到我们的CTRL这个方法,这个方法呢,他就帮我们来查我们的这个会员信息,那给购物车这也打一个断点。
03:25
他找到我们当前登录的用户信息,来查用户的整个购物车,好,我们现在就直接放行走,那他第二个查购物车,查购物车我们先拦截器拿到uz info to来看一下。我们目前呢是登录状态没问题,但是呢,在购物车这一块,我们user info to里边,我们没有发现user ID,所以呢,购物车以为没登录,就直接给我们返回为空了,那一返回为空,我们来放行,这一块进来再次调用,这是重试,好我们来重新来放行,那说明我们这一块呢就出现了问题,就说我们购物车这一块,他为什么没有认为我们是登录状态。
04:06
来看一下我们订单这一块的代码。但是如果我们真正来访问购物车,来看一下我们的购物车,我们购物车我们真正来访问,来访问他的整个订单列表,好,我们发现呢,购物车这一块登录状态是没问题的,页面都能取到,但是我们远程调我们购物车的这个方法的时候,来到我们购物车的这一块来看一下。我们把其他的关掉,关闭右侧的来到我们购物车ctrler,我们来调service,那么这一块呢,它又发现没登录,没登录的原因肯定我们先来看拦截器,因为所有请求来之前拦截器都要拦截,拦截呢就是从session里边获取当前登录的用户走,那么就来看session里边能不能获取到当前登录的用户来重新去结算,我们把这一块呢放行。放行,一直放行到我们session这一块,那session这一块我们来走,那现在拿到这个session,我们拿登录的用户来看,我们发现这个member是空的,但实际上我们肯定是能登录的,但是我们现在拿到的member为空。
05:14
所以我们现在这一块最大的问题就是如果我们不传用户ID,购物车感知不到当前正在登录的用户,那现在的原因是什么?为什么那先把这个呢放行,我来先说一下这个是为什么,这个原因就在这,因为我们调用购物车的方法,我们是份进行远程调用,而不像购物车以前人家页面直接访问,如果人家页面访问,比如我们访问cut HTML来看会有什么不同,我来F12,那在这儿呢,就来访问购物车,如果我们访问的是购物车,我们使用页面的方式访问,我来访问cut HTML走,那么现在呢,看到我们cut htm Mr发请求的时候,我们会带上cookie cookie里边呢有我们这个相当于解session ID,好,我们把这一块呢,直接放行了走,那我们页面访问呢是正常的,正常的原因是我们访问请求的时候带了我们的这个cookie,叫鼓励session。但是接。
06:14
下来,接下来呢,就轮到了我们的这个远程调用,那远程调用如果我们来到这儿,我们来看一下源码,好,那现在来重新来发起我们的这个下单请求,那现在来重新去结算,来看远程调用跟我们页面访问有什么不同,好那远程调用呢,让他通过那远程,我们这个方法是一个远程调用,所以我们看到这个service,这个service呢,它是一个代理对象,是一个份客户端的代理对象,我们就来step into来进入远程调用,来看一下它怎么调用,那step into进来,他先判断,那么这些是不是object,一些公共的ES哈西code等这些方法,如果是方法,如果是这些方法就不需要远程调用了,否则我们就调用这些,好,我们就来进来。
07:02
进来呢,我们发现它会调用一个dispatch dispatch.get先来获取我们这个当前方法,然后在这再来引VO,我们先来step into step into,我们进来以后,我们来看我们的效果,现在我们的整个参数我们没有传什么,因为我们的远程调用这个方法呢,没有传参,而且这个的代理对象就是这个reflect份,好,他在这来invoke,我们来看他invo,他invo呢先拿到一个什么tra重试器什么的,之前呢我们还分析过这一块的源码,如果不行的话,它就来进行重重试,所以我们现在真正的执行就在这个方法里面,Is cut and deco来step into,如果我们想要执行,我发现呢,在这先准备了一个templlet,就是我们请求的这个模板,这个模板呢,指定了我们这个请求的UR地址,然后呢,他先。得到我们当前请求,请求在这,然后利用客户端来去执行,我们就来看怎么得到当前请求,Step into,我们发现呢,它是启用所有的request intercept,它呢拿所有的request拦截器拦截,拦截把我们这个整完了以后就来返回了,所以我们这个在发请求之前,它会用一些拦截器,我们在这儿来备注一下,我们备注在下边的代码份在远程调用之前,远程调用之前要构造请求,构造请求呢会调用,调用很多的拦截器,很多的拦截器,但是我们现在拦截器呢,啥都没有,这些拦截器就叫这个intercept request intercept,那现在也没有啥拦截器,相当于呢,份也没有什么。
08:47
功能要进行增强,所以呢,将原生的request template,将默认构造来的这个请求templatet给我们传递过来,但是大家注意看,那么既然它叫request tablelilet发送请求的模板,它这一块呢,有quarus,还有headers,我们发现呢,Quarus quarus的意思就是我们的查询参数零个,然后呢,Head请求头零个,那问题就出现在这儿了,它默认给我们构造的这个request和对象里边根本就没有我们的请求头,头里边的数据都是零个,但是呢,我们整个请求是这么发过来的,我们在页面掉了to try的,To try的,如果我们来发这个请求的话,我们肯定是带了我们这个cookie,这个请求投里肯定带cookie了,所以我们现在呢,我们的请求先来到这儿,我们现在来看一下,我们如果是订单这一块来进行预结算,我们来到订单这一块订。
09:48
但呢,我们请求我们点击去结算,请求呢,先会发给我们的这一块to出,To出的来调用我们这个方法,我们这个方法再来进行远程调用,也就说to try的这个请求肯定有我们head请求头cookie那一串信息,但是在我们这儿调用,我们经真正进行远程调用的时候,它给我们创建了一个新的请求模板,请求模板里边什么都没有,所以接下来这就是份的远程调用问题,我们来给大家画一个图,份远程调用会来丢失我们请求头,为什么?原因就在这儿,我们的整个流程是这样子的,我们先发了一个请求,好,这是我们发一个请求,这个请求呢,我们先是发给我们的这个叫订单服务order,好,我们先发给我们的order服务,我们这个订单服务,我们在这儿发请求的时候,由于我们当时发的这个请求叫to trade。
10:44
我们是从浏览器发出的,所以我们第一个请求是浏览器发出,浏览器发出人家自动带了所有的cookie,有了cookie相当于我们才能找到session,所以浏览器发送自动带了cookie,然后请求头自动带了cookie,请求头自动带了cookie,所以呢,我们第一次请求来到订单服务,请求头里边还有cookie,但是订单服务呢,接下来要远程调用,远程调用我们的购物车服务,诶我们现在呢是购物车服务,但是购物车服务呢,在订单服务里边,它是一个远程调用,远程调用呢,订单服务怎么调,订单服是这样子的,它先创建一个新请求,因为它是用份调,所以呢,它是创建一个request,创建一个新的请求,我们注意这是一个新的request,新的request里边什么都没有,然后根据你的方法再来解析。所以呢,粪问。
11:44
题就出现在这儿了,我们如果是利用粪,我们订单服务现在想要要远程调用好,我们使用份份来远程调用,远程调用他呢会创建一个新的这个请求,相当于他自己拿Java代码去来发一个请求,但这个请求里边什么都没有,所以呢,我们这个请求头什么都没有,这个请求什么数据都没有,没有任何任何请求头,因为它是创建的新的请求头,所以相当于我们这个请求如果远程发送,发送给购物车服务,还调人家购物车的那个ctrler,那最终就会出现这个问题,我们把这个请求发给购物车服务,想来远程调用人家功能,但是我们又没带我们这个请求头,那没带请求头,我们没带这个cookie,那就认为没有session,所以呢,我们现在的问题就出现这。
12:44
二我们由于没带请求头,哎,由于没有请求头,没有请求头,没有请求头,我们的这个购物车服务,我们就认为没登录,所以呢,购物车服务。他就认为没登录cut认为没登录,认为没登录,那没登录的原因我们就算是找到了,其实就是我们自己在这儿份远程调用的时候,我们构造了一个新请求,关键就在这儿,这个新请求没把以前老请求的信息同步过来,所以导致了我们现在的问题,我们把它放行,那怎么解决这个问题,怎么解决这个问题呢?我们先来全部放行,我们来看解决这个问题呢?其实很简单,因为我们来到之前源码的地方,我们来给它看,到这儿我们在发请求之前会有很多的拦截器,先对整个请求来做一个增强,那这个怎么增强,来给大家看一下,比如我们再来发一个。
13:47
走,我们现在来看一下我们的整个这个增强功能,来放行,好,我们来step into来到这个方法,然后呢,我们现在要在这来进行执行step into,先来执行invo这个方法,好,然后呢,我们在这execute and deco,我们要执行执行我们在构造请求的时候点进来,我们会用很多的请求拦截器,可是我们现在请求拦截器一个都没有,如果有的话,它呢会挨个调用请求拦截器的这个apply方法,把我们将要构造的这个请求模板给它丰富好,丰富好以后呢,把这个进行返回,所以我们现在能做的一件事就是如果我们有自己的这个拦截器,那就好了。所以呢,我们现在为了解决我们这个请求丢失图的问题,那么就可以来加上份的拦截器,份远程调用的请求拦截器,我们必须来加上粪远程调用远程调用的请求拦截器,请求拦截。
14:47
也就是说在我们份构造好这个请求,我们都知道拦截器是在这儿工作的,创建好请求以后,由这些拦截器一一先来进行apply进行处理,所以呢,他在这构造好以后,在这要进行处理,那处理完了以后才会把这个请求发出去,所以呢,我们现在有了拦截器,我们创建的新请求就是这么发出去的,我们先让拦截器来走一道。
15:15
好,我们现在把这一块的线来重新拦一下,现在呢,我们现在加入了拦截器提示,好我们把这一块CTRLX来写上一个,这一块加一个这个拦截器,好,我们来加入这个请求拦截器,如果我们来加上份的拦截器,它呢,创建好请求以后,我们来把它跟拦截器连起来,只要我们的这个份创建好请求,那接下来呢,它就会先调用我们的这个拦截器,你有多少拦截器挨个调用源码那一块呢,就是这么来写的,我们看到了一个数组,它在这挨个调用拦截器,调用拦截器的什么方法呢?我们来看。它在这一块是来调用我们这个拦截器的apply方法,一个for循环,把所有的拦截器都来运行,运行完了以后才把请求我们真正的去来远程执行,所们现在呢就来加上一个份的拦截器,这个拦截器呢就叫这个request intercept点进来它是一个接口,所以我们在config这里边就来写一个我们的鼓励f config鼓励的份的配置,份的配置里边我们先来说我们是一个config configuration是一个配置类,那么接下来呢,就给容器中来添上我们的这个拦截器,那么这个拦截器叫request intercept,我们直接导进来,那么就叫request intercept,这拦截器是怎么决定的,我们可以来看一下,拦截器呢,在这这就是拦截器,这个拦截器呢,在创建的时候,它是直接在构造器里边传的,所以呢,构造器里边会得到我们的这个list,我们来看谁创建了这个构造。
16:55
器点进来,那这个方法,这个method handler在创建的时候呢,创建了这个构造器,它呢也需要拦截器,这个拦截器呢,在这儿我们再来看谁来创建这个factory来点过来,它是我们这个粪在创建了这个factory,它呢会传入这个拦截器,那这个拦截器呢,在哪一块,就在这一块来看一下这一块的拦截器。
17:17
那这一块的拦截器它默认呢,是空的,相当于什么都没有,但是我们这个拦截器呢,只要我们容器中有,它自动就会从容器中拿到我们的所有拦截器,如果有拦截器,它就会给我们添进来,所以我们现在要做的事情就是给容器中放一个这个拦截器就行了,At一个B,好,我们这个拦截器的名字默认呢,就是方法名,我们填在这,然后呢,我们来放一个拦截器,我们直接用一个request intercept这我们份的这个拦截器,我们来给它返回出去。也就是说我们份在远程调用之前,都先经过每一个拦截器的这个apply方法,Apply方法呢,在这这是我们的request template,相当于我们真正要发出去的请求,那么现在呢,就在拦截器里边,我们先来确认拦截器份远程之前,远程之前先进行。
18:12
我们的request intercept的这个apply方法这一块是肯定没问题的,那在进行这个方法的时候,我们就可以让他把我们之前的请求头给我们设置到我们新的里边,之前的请求头我们能不能知道呢?其实很简单,我们可以来看一下我们整个调用逻辑是这样,我们浏览器发to出的请求来到我们的service,我们service要远程调用份份呢,要创建一个新的对象去来发请求,在创建对象的时候,它又会调拦截器,拦截器跟我们controlrler,跟我们service其实都是同一个线程的,所以呢,我们想要在拦截器里边能获取我们之前的请求,就是order这一块,我们原生来到这里边的这个请求数据能不能获取到呢?我们自己可以直接thread local给当前线程一共享,那么这个拦截器就能获取到,但是其实文家也考虑这个问题了。你经常要获。
19:13
取我们这个数据,那怎么办呢?他自己呢也抽取了一个,我们来看有一个类叫request contest holder来看一下contest hold翻译过来就是我们整个上下文环境的保持器,那这个保持器里边有一个方法叫get request attributes,还有一个叫get current request attributes,就是我们当前请求的所有属性,那么用哪个都行,我们用上边的可以拿到我们当前的整个请求属性,那么这个contextest ho点过来大家能看到,其实它就是利用thread local帮我们从请求一开始就把当前的请求数据放到thread local里边,随时想要用都能行,所以呢,这个是我们第一步可以使用这个contextest ho拿到拿到我们这个刚进来的这个请求,刚进来的这个请求数据,请求其实相当于就是拿到我们,调用我们。
20:13
这个to try的方法,当时的这个request,这个request里边是有cookie的,什么都有的,那然后接下来怎么办,我们可以来看一下,我们拿到这个以后,我们可以把它呢,转换成我们有一个叫server late server late request attributes,这是spring家给我们提供的这个,我们把它转成它,因为我们得到的是一个requesttributes,那这个requesttributes就是它那转过来,那转过来以后呢,就能获取到我们这个当前的这个请求了,点一个get request。我们发现呢,我们能获取到当前的这个请求对象,相当于我们从CONTROLTRLER1进来,我们thad local就放进去,来到我们的拦截器,我们还能获取到当前请求,那获取到当前请求有什么用?我们应该把请求里边所有的头信息都同步进来,所以呢,我们现在要做的事情就是同步我们这个请求投数据,主要我们要同步cookie,因为我们现在丢失了cookie,导致我们远程请求发出去以后,我们再给他发请求的时候,如果我们的图里边有cookie,远程服务就知道我们是登录的,我们没有那就不知道。所以呢,我们现在要做的一件事就是给我们图里边放cookie,而我们新的请求就是这个request template,老的请求是这个,所以呢这个是老请求,老请求,然后呢,我们可以来新请求,新请求呢,是这个,我们给新请求设置上它的头,我发现呢,这直接有一个叫head,我们设。
21:49
它是哪个头?因为新请求端丢失了cookie,每一次发请求如果我们都带了cookie,肯定没什么问题来看,如果我们每次发请求都带了这个cookie cookie的值人家带了什么,你也带什么,那就没什么问题。所以呢,我们现在给他添加上一个cookie cookie的值是什么?把老请求里边的cookie拿过来就行了,Request点一个get header,把老请求里边的cookie值拿来,我们放到新请求里边,好,这是我们获取这个head的,我们把这个老请求里边的headde拿来放到这。
22:24
走,那这样我就相当于给新请求里边把老请求的cookie同步了,给新请求,新请求新请求同步了咱们这个老请求的咱们这个cookie,那这样我们就最终我们远程调用的时候,我们在前边拦截器已经帮你把老请求的cookie拿来了,那你接下来给远程服务发请求,相当于你就带上了cookie,远程服务知道有cookie了,那相当于一切呢就正常了,所以我们现在呢,就加了一个拦截器逻辑能不能工作呢?来断点打在这儿,好,我们现在让我们的订单服务重新以第八个模式启动起来,那现在就来确认,我们在远程请求发送之前,一定要让我们的拦截器工作起来,工作起来,帮我们把老请求里边的cookie数据同步过来,好,我们现在来重新来测试,还是来到我们的service第一个方法,第一个方法人家给了用户ID那么的说,但没给用户ID。
23:24
我还想知道每一个微服知道当前是哪个人登录了,那就每一次请求进来都要把之前老请求的这个cookie要同步上好,我们现在来看一下我们的页面效果,来重新发送to try的请求,因为现在已经登录了,有这个cookie数据来刷新。好,我们现在发送这个凸出的请求来到这儿,我们第一个远程我们调用的时候,我们先来到了拦截器,我们发现拦截器起作用了,然后呢,我们把老请求拿来,老请求的cookie数据我们拿来,诶我们发现user k鼓励session都有,我们给新请求一放,一放以后呢,接下来我们发现这个拦截器就应用到了我们这个templatet,这个里边就有头了,以前的这个头里边什么都没有,现在有了cookie,那有了cookie你给别人去来发,你去来发远程请求,别人相当于你请求头里边就能收到cookie了,你能收到cookie一切就正常了,我来放行,那放行呢,来到我们的购物车里边,来到我们这个购物车里边,肯定就是一切正常了,那现在来全部放行,来到订单里边来全部放行。
24:32
好,现在呢,第一个是完了,接下来来第二个们第一个呢是查地址,我们没问题,接下来第二个每一个请求过来,都要把老请求的这个cookie同步上好同步上以后呢,接下来我们就走走,只要同步上了这个模板里边我们来确认一下,现在呢,这个template里边就有我们同步过来的请求头信息了,诶没问题,然后呢,接下来我们再来给它放行的时候,就来远程执行,我来放行,那执行到我们的购物车模块,购物车模块接下来他的拦截器进行工作,购物车拦截器进行工作,他获取session,由于我们已经带了cookie的那个信息了,所以他的这个session里边肯定有登录的用户,我们来看member,诶,我发现呢,现在就查到了,所以呢,这就是我们说的份远程调用丢失请求投档问题现在已放行,那最终的解决我们只需要来加上拦截器,在每一次远程请求发起之前,先把老请求的数据同步。
25:33
过来,好,这是老请求。这个老请求是浏览器发的,要啥有啥,我们该有的cookie session这些标识我们都有,而我们现在要做的就是新请求,要把老请求里边的数据要同步过来,好,我们把这一块拿过来,这是我们最关键的地方,远程调用要想要不丢失,那就在这儿好,特别我们是用session原理,我们要一些核心cookie要一直在的,所以我们想要远程调用,远程调用cookie还能有用。其他请求头也一样,所有请求头都会丢失,丢失cookie等请求头,等请求头必须必须和和咱们这个老请求,老请求同步过来。
26:22
好,这就是我们说的这一个问题,份远程丢失请求多有问题,那至此我们能走到这,那肯定一切都正常了,我们的这个远程调用这一块的方法,该远程查询的数据肯定也都有,我们再来确认一下,来到我们的订单服务,好,我们来重新发送这个请求,来确认一下我们订单服务的这些数据,那先来看一下我们的断点,来其他的断点,购物车的断点我们也都去掉,购物车的断点,拦截器的断点,会员的这些断点我们都去掉,那现在来到这个订单服务,第一个远程调用查收货地址列表没问题,然后第二个查购物车里边的数据,好,我们这个购物车这一块呢,现在还在断点状态,我现在把这个断点呢打在这一块,我们来直接放行,那购物车如果查完没问题,我们来看一下这个购物车。
27:17
购物车的断点我们都去掉了,如果查完没问题,我们肯定这一块数据都能得到,那是这样的,我们由于之前修改了代码,我们给这加了注释,代码的行数都不一样了,我们也没有重启,所以这一块断点呢没有看到什么效果,但我们现在呢解决了这个远程调用问题。
我来说两句