00:00
我们先简单回顾一下我们前面啊所讲的一些内容啊,不仅仅是,不仅仅是昨天的。呃,我们就从这个水果系统啊,我们从这水果系统,咱们一起来把它看一看。呃,基础知识我们就我们就不去回顾了啊,比如说SIM的这个,或者叫time它的语法呀。啊,比如说它的生命周期啊,这些基础知识咱们就不再回顾了啊,Listen这个咱们就不再回顾了,我们主要进来看一看。我们一个最初的fruit应该是1.0这个版本是吧,同学们1.0我们把它改成的是JDBC。啊,其实咱们Java SE里面我们的系统,我们也可以去也可以去实现它。啊,那么从从连接数据库开始,咱们建的目录应该是版本是1.0版本。那么我们从最初的1.0。然后呢,然后呢,我们一直到fruit应该是呃。应该是1.4这个版本。
01:02
啊,到1.4这个版本,我们开始拥有的界面是吧。因为1.4版本之前我们做的是控制台的嘛,是吧,同学们啊,显示的这个效果是在控制台的,那么从1.4这个版本开始,哎,我们在页面上做展示。那么我们就一步一步的去追加功能。1.41.51.6。那么1.6这个版本呢,我们做的是带有分页的。那么1.7呢,我们把根据关键字的查询,我们也把它加进去了。那么从1.8这个版本开始。我们开始对我们这个系统的结构开始做一些思考。1.8这个版本之前,我们主要的是把功能全部都把它写完了。然后呢,我们在1.9当中对我们的MVC这个结构做了做了一个优化。啊,我们使用的反射,因为之前我们使用的是,呃,最初我们使用的是。使用去进行改造,然后呢,我们使用的Switch case。
02:04
把我们多个,把它优化成一个是吧,同学们。在紧接着我们会发现Switch case很多。所以我们使用的反射。做了优化。那么使用反射做了优化之后,这是这是我们的fruit假设我还有其他的。啊,操作其他的实体的这个。那我又得把反射这个代码写一套,所以我干脆我就把反射这个代码呢,把它继续向上提取,我们就得到一个叫dispat。我们就得到一个核心控制器,或者叫中央控制器。然后呢,我们把之前的就变成一个一个普通的CTR了,对吧。变成普通的CTR了,那么我们去分析,我们会发现。我们的controller,它一般情况下总会分成三个部分。第一个部分参数获取参数。第二个部分业务处理。第三个部分视图资源的。
03:03
转发或者重定向。哎,它总的分成这三个部分,或者叫试图处理。那么我们会发现呢,请求参数。和试图的处理。啊,每一个CTRL里面它都有,其实动作其实都差不多,因此呢,我们又分成两步,把我们的视图处理,以及参数的请求啊处理,把它抽取到P键里面,对吧,同学们。又把它抽取进去。所以说PA它所完成的工作,它是完成一些通用的一些功能。让我们的controller,让我们的controller能够更专注于业务的处理。所以因此呢,我们的ctler就慢慢的这个ctrler,它就变成一个普通的类。他就不再和我们的API进行进行耦合了。其实这个是比较有好处的,这样我们可以做到它能够很方便的,我们对CT里面的每一个方法能够很方便的做单元测试。
04:00
啊,其实这个好处还是还是比较大的,当然了,我们这个CT并没有做到和solid API完全的耦合,因为我们发现偶尔的在一些方法里面,我们还需要去使用筛选。啊,如果说我们想要对筛选再进行解耦,其实也能做到,用我们所学的知识其实也能做到。啊,但是我们就没有必要再往下深入了啊。因为后面咱们框架里面都有,都有自带的这些特性。那么再往下呢?我们引入了service这一层。我们为什么需要service?为什么需要业务层?因为我们说过DA当中全部都是单精度的方法,对吧,同学们它全部都是单精度的方法,那么我们一个业务方法。它应该会有多个单精度方法最后组合而成吧。所以说我们需要把这个业务层把它挪进来,而不需要把业务操作的步骤全部散在我们的控制器里面,对吧?要不然你控制器里面你得去考虑第一步调用谁,第二步调用谁,第三步调用谁,If如果是什么情况,我得调用谁else我得去调用另外一个。
05:04
啊,那这样的话,Ctler它的负担是比较重的,我们CT应该是面向业务的,所以呢,我们ctler直接去调用业务组件里面的业务方法。具体这个业务有多么复杂,我们应该全部封装到service里面去。哎,是这样的。那么我们引入service之后,我们就会发现。层与层之间是存在耦合的。啊,我们需要对它进行降低耦合,甚至要解耦合,那这个时候我们就引入了RC容器。我们引入了ROC。层与层之间组建的依赖关系,我们通过RC容器帮我们去注入,我们称之为叫依赖注入。层与层之间组建,他们是依赖关系啊,依赖关系我们可以通过注入的方式给它注入进去。好,之前这些对象呢,每一层的对象是我们程序员自己去创建的,也就意味着它的生命周期是由我们自己来控制的,那现在呢,这些对象的创建以及销毁,我们全部把它纳入到ROC容器的管理,让ROC容器去帮我们去管理这些对象的生命周期,那么我们称之为叫控制反转。
06:06
这些对象的生命周期的控制权,我们从程序员的手上反转到容器,称之为叫控制反转。好了,就是这样。那么再往下,再往下,我们简单的补充了select当中的API,第一个我们讲的select当中的初始化。叫in的方法有印象吗?那么它有个参数叫config。那么我们还有一个接口叫contact,它代表的是我们上下文,我们通过这个上下文对象,我们可以去获取上下文的参数,是吧,同学们。那上下文的参数是不是可以在web.X文件当中去配置contact per是吧?通过contact去配置?好,这是这样的。这是我们所补充的啊的上下文,我们在这个当中。我们比如说in的方法,我们会得到这个con,因为这个in的方法有两个,一个是带参的,一个是无参的,我们可以去重写这个无参的,当然了,你非得要重写这个带参数的,其实也行。
07:06
啊,其实也是可以的。That。那么再紧接着我们学的是过滤器和监听器,这个基础语法咱们就不看了啊。再往下。我们讲了一个什么呢?我们讲了一个叫关于事物的管理。那么之前我们所学的基础知识,我们在JDBC当中稍微了解了一下啊,关于事务的管理,或者叫事务的操作,那么当前呢,我们事务的操作比较简单。第一,设置不自动提交。第二,我们可以提交commit。第三,我们进行入。当我们正常运行的时候,我们就commit,当一旦有异常的时候,我们就进行,哎,就是这样。但是呢,我们这个操作它是基于connection的API。那么我们,其实我们的事物,我们经过一番讨论,我们会发现我们的事物应该处于业务层,而不是DA层,因为DA里面全部都是一个一个的单进度方法,我们需要保证的是一个业务功能是吧?一个业务功能成功或失败,那这一个业务功能成功就意味着它里面所包,它里面所包含的多个do方法都成功。
08:17
这一个业务方法失败,应该是多个DA方法都失败。不能部分成功部分失败,那这样数据会出现不一致的情况。对吧,同学们,那我们讨论到这个地方,我们就会发现,我们从代码,从实现的角度,我们会发现,诶,我们当前碰到的难点应该是connection对象。因为我们以前是do方法当中每一个connection它都是自己特有的,它是不共享的。那既然我们想做事务管理多个do对象,多个do方法又能够在一个事务当中,我们需要对他们connection要使用同一个,要进行共享。我们就碰到这么一个难点,那么我们就引入了local。是吧,我们引入了瑞的。
09:01
好,然后呢,我们把事物的操作,我们抽取成一个叫transaction manager。我们抽取的那一个类。回到这儿。我们回到transaction,在这我们抽取了一个类,那这个类里面比较简单,它就给我们提供了三个方法,第一个方法叫set,叫begin transaction。第二方法叫commit,第三方法叫。那一开始我在写这个类的时候呢,我这里面代码一开始我是写的比较多的,但是我发现很多代码是重复的,那么我就把它抽取了一个叫connecting u是吧,同学们啊,这个视频里面反正都有录的这个代码修改的这个过程。所以呢,我们在U里面。我们就制定了一个叫get connection方法,一个叫close connection方法,有这么两个。Get connection就是从里面去获取。那么get如果获取不到,那么我们就要创建一个,然后把它扔进去,表示的是第一个用户啊,第一个功能要从纽带上去获取,发现没有没有怎么办?向老板要啊,创建了一个,创建用完之后再重新发纽带上去。
10:04
哎,就是这样的好了。那么close方法,Close方法我们从所有的lock上面去get,如果获取的不等于空就算了,如果不等于空啊,如果不等于空,我们就把当年这个把它close掉啊,然后再让它塞down,当然它其实还有另外一个方法。点T方法叫remove删除,你用这个方法其实也可以啊,你不用上面那个塞纳。你要remove这个方法也行。啊,就是这样的。再来。那么我们这里面呢,我们稍微讲了讲了这个,呃,Three local它的一个实现的原理,我们重点去讲了它的get和set,我们查看了一下它的这个源码。我们这个get是什么get,首先我们要获取当前线程。thad.current thread获取当前那个线程对象。然后呢,我们通过local当中有个叫有个有一个叫local map,我们点进去看一下。
11:06
我们有一个叫get map方法,是不是能获取一个叫local map呀,那么这个get map map方法是以什么为参数的?哦,它其实是以当前线程为参数的,那你想想你的线程不同,是不是获取到的这个map就不同啊?那这样就意味着我们每一个线程其实都有自己独立的一个s local map,这样就不会冲突了。只要我们在同一个线程上,那么我们就共享一个log map,只要我们不在一个线程上面,我们不是同一个线程,那么我们所使用的log map就不是同一个,这样就不就这样就不会混乱了。好。那么我们拿到这个map,我们怎么去获取呢?那就get就好了。啊,直接get我们就可以获取了,就是这样的。那么。这是我们。这是我们所说的这个s local啊,这是get的方法。
12:00
第一步,如何去确认我当前线程和另外一个线程,他们不会混淆诶,因为我们获取的是当前线程作为一个key,然后定用get map这个方法,调用我们的logo当中的get map方法。所以线程不同,获取到了three的log map,那就不同。那获取到的three local map不同,那这个容器里面所放的内容当然就不一样了,那么我们那么具体的这个容器里面我要取的是谁呢?你就把three local扔进去。当前这个刀口把它扔进去,因为我给大家举个例子。我在我这个connection里面,我的logo是不是可以创建多个。那么你具体的K1 K2 K3是不是三个K不一样,你三个K不一样,你最后你所获取的这个value值,或者叫安全。这个安全就不一样,那么安全不一样,你点Y点出来,那就当然就不一样了,是吧?哎,就是这样。好,那么我们还引入了一个机制叫OPEN3线in view filter。在这。OPEN3线,这是一个过滤器。
13:03
这个过滤器工作的时候,当请求过来的时候,哎,我们就开始开启数,就begin transaction,我们把这个开启数把它注释掉,现在已经不需要了。啊,然后呢,我们do field放行嘛。去进行业务操作,操作完只要你没有错误,那么我们是不是是不是就正常的commit呀。没错吧,一旦你有问题,是不是就被看到了?开启到之后我们就执行,如。没问题吧,就是这样的,然后呢,我们会发现我们测试正常的时候,第一步啊,大家应该还记得啊,第一步我们证明connection用的是否是同一个。只有你在多个组件里面用的是同一个,我们才能保证这是一个同一个数。哎,结果我们发现connection它的哈code确实相同,是同一个,然后紧接着我们又做了第二个实验,我们去测试,我们去证明当真的发生问题的时候,它是否真的回滚,我们发现没有。还记得吗?我们发现并没有,是什么原因,是什么原因来着。我们会发现内部一旦有问题的时候,在内部是不是已经圈开启了,内部圈开启,其实我这个开启从来都没有去抓取到,从从来就没有捕获到异常过。
14:08
是吧,同学们,那就导致了问题了,因此我们做了一些改造,我们把每一层上面的异常,我们都去重新做了一层封装,封装之后对外重新抛出运行时异常,然后在这个地方它就能捕获到了。是吧,同学们,我们是这么去处理的。OK,那么这个是我们所讲的内容,下面呢,我们来画一张图。我们的客户端在这,这是我们的客户端,我们会向服务器端会会去发一个请求。这是我们的服务阶段。啊,会向我们的服务器端发个请求,在我们服务器端我们会有,首先我们会有两个filter。我们首先会有两个filter。第一个。第一个filter。嗯,就画这吧,这是第一个。
15:02
第一个我们称之为叫character encoding filter。Character including filter,这个是用来做设置编码这件事情的这么一个过滤器。紧接着我们经过第二个过滤器,第二过滤器叫open session in view filter,是吧?同学们要经过第二个,好,我们就把它画在这。Open session in。Filter。好,就这样吧。这是第二个。好了,那么这个过滤器放行之后,我们会经过一个叫中央控制器。是吧?叫中央控制器。我们把它画在这。这是一个中央控制器组件。好,我们称之叫dispatch。Dispatch。是。
16:02
那么这个despite它会去解析我们具体的URL。解析URL。然后得到一个名字。得到一个pass。比如说这个pass的flu。会得到一个float。那么我们根据这个float,我们会去找到对应的fruit controller。所以我们在后面会有一个组件叫float controller。把它画在这。把它放在这儿。Float controller。然后呢,我们这个当中,我们还会带上一个叫opera的,还是叫什么。是叫opera的吗?Operate,比如说the index。那么这个时候呢,我们就能找到flu CT当中的index方法。就是这样,那么在这个方法内部,我们的flu controller,它其实会去调用我们的service内部的方法。
17:08
所以我们把它画在这。叫flood service。就画这吧。Service。OK,会去调用它内部的方法,那服的service又会去调用我do的方法。我们把它放到这。去定do。好,这是我们的float do。当中的方法,那么flu do其实它的父类是我们的best do。所以我们下面其实又会有best deal。我们把它们两者挨在一块。OK,就这样吧。
18:00
这叫best。那么他会帮我们去访问数据库。我们数据库在外面,在这。DB。好了。那么disch里里面,他帮我们做了三件事情。我把它写在这。第一件事情。参数处理。第二件事情啊,第二件事情就是我们的通过反射invoke方法。来调用具体的具体的这个响应方法啊,就是我们设,就是我们control内部的方法,第三个视图啊,视图处理。是吧,同学们,他经过这三个步骤。就这样吧。啊,经过了三个步骤。所以说我们的请求。他首先是我们的客户端发请求过来给我们的服务器。那么会找到我们的character。进行一个编码的设置,然后放行,放行之后,然后交给我们的open session view filter。
19:04
那么OPEN3线filter啊,再放行,放行之后就交给交给我们的叫dispa。哎,就是这样。那么despite。根据你的U。啊,解析处理得到一个float,那么这个float它怎么办呢?这个floatte其实是不是我们有一个叫RC容器啊同学们。好,我们把它画在这。这是一个RC容器。LC container。在我们RC content当中,我们会配了很多的B的组件。ID。我们又配了。ID,比如说flu service。我们还配了BID等于float。是吧?哎,没错吧,然后在我们这个fruit当中,我们是不是有个property。
20:04
Name等于flu service。是不是啊?哎,就是这样。好,这个name省略吧,啊,Property。叫service。然后呢,在我在我们这个service当中,它是不是也有一个pro。Property。好,他其实他需要的是不是DA啊,哎,就是这样。那这样就是他们的依赖关系,所以呢,我们在这个RC的这个content当中,我们有三个组件对应的啊,有三个K。第一个叫flu。第二个叫fruit service。第三个叫我们的fruit do。因此。我们这边解析URL得到fruit。Fruit之后,我们就根据这个fruit技能和这个fruit进行对应嘛。没错吧,同学们记得把它对应上。这个fruit。我们尽量找到他。
21:02
那么找到它之后,其实哎,我们就可以找到找到他了,没错吧,同学们就能找到这玩意儿,哎,就这样。因为我这里面有个class嘛,Class我配的是不是就是flu controller呀。哎,就是这样。然后我们通过反射的方式去调用其中的index方法。那么你这个index方法内部,其实我们又会去调用我们的service它的方法。那我们flu c当中,其实我们有一个flu service。好,我们把它写在这。在我们的flu当中,Private。Flute。Service。Service等于now。它其实有这么一个属性,表示我们的controlt里面是不是得需要service,它和service之间有依赖啊,那么我们一开始写的是六,后来我们把它改成等于now,等于now之后我这个属性提供了,然后我这边又有property,它是不是会把这个property里面的IEF是不是会注入给这个fruit service啊?
22:07
所以我们把这边改一下,把这边删掉一点点啊。删掉,然后我们再补一个属性。叫if。好,把它放在这儿。啊,我们称叫if。好了,那么这个ref属性。他其实就是会给他注入。啊,通过这if我能找到我我所指定的对象,然后呢,给它设置值,这其实就是叫依赖注入。就是这样的。同样的道理,我们的float service里面是不是也需要DA啊,那也一样的啊,他们之间的依赖这个输入。再来。然后呢,我们的best,其实我们的best deal里面,我们有三个方法。我们当时讲GDBC优化这个部分啊,我们抽取了三个方法。
23:03
第一个叫XQ的update,这是第一个方法。思考语句,然后参数problems。第二方法叫Q的po。好,Circle语句没错吧?那么第三个方法叫漏的方法。好,搜狗语句。好,当然我们还有一个叫XQ的。Complex。执行复杂查询的时候是吧。哎,就是这样。这是我们所抽取的方法。啊,这是我们best里面所抽取的,把它变成蓝颜色。现在大家再回过头来再看这几个方法,应该没有当初看的时候那么困难了吧?啊,还是那么困难,不会吧,应该不会是吧,现在再看应该感觉很熟悉了吧。啊,还是很困难吗?不至于啊,应该不至于好。不过没关系啊,再痛苦大家也痛苦不了几天,等我们后面再学买be的时候,那么这一套咱们就不用了。
24:04
好。这一套不用了是吧,然后又有又有新的男的东西了是吧,好。哎,这是我们best do,这是我们对于持久层我们做的优化啊,刚刚我们是对于这个层与层之间解耦,我们用了一个RC容器,然后呢。在左边,哎,我们把这个MVC。啊,MVC,我们控制控制层这边所做的优化。那么还剩最后一个就是关于这个叫叫叫事物的处理,所以呢,事物的处理我们是怎么做的呢?我们在open session in当中。我们在这边写一下。我用蓝颜色写啊,首先我们第一步。第一步。在这边我们要开启十。好,第二步我们做的是放心。是吧?第三步,我做的是提交。那么其中我们这个放行操作,我们使用的是catch。
25:01
Trial。好,二和三把它围起来。开启。一旦你出问题了,我们要进行第四步回滚。没错吧,同学们,哎,我们是这么去做的,这是我们的open session in field,我们里面所做的事情。那么这个时候呢,我们其实啊,我们service其实就存在一个service内部调用多个do,多个do之间,他们之间他们的信息是怎么去传递的。好比如说我们这个DA啊,DA组件里面有多个方法,我们就把它。呃。就把它画到这儿吧。一个方法。好,稍等一下啊,把它拷贝一下。这第一个。CTRLCCTRLV,把它放到这,这是第二个。好,这是第三个。把它往这边画一点。好,这个往这边画一点。这是第三个。就这样吧,我三个组件之间我是怎么传递的哦,因为在我们面前,我们是和线程相关的。
26:06
在我们的上面,我们有个叫瑞的local。这边一个叫local。好,我们把它写到这。的local。我们所需要,我们所需要的数据。我们需要什么数据?我们先从three logo上面去获取。啊,你需要数据,你也可以从上面去获取,你也需要数据,你也可以从上面去获取,是吧,同学们。它其实就是这么一个过程。这是我们的三个三个方法吗。我们三个do的方法吗?是吧,同学们,我们如果想共享一个connection的话,只要你和线程相关就可以啊,同一个线程我们获取到就是共享的。OK。我们把它保存下来。好,这是我们今天要讲的项目。
27:12
OK。
我来说两句