hi, 欢迎回来,那么上节呢,我们大致了解了 refresh token 它的工作原理,以及它是如何为我们实现退出登录这个目的的。 但是呢,上一节我们只是在我们的登录还有注册中实现了 refresh token 相关的逻辑,我们还没有实现对应的刷新,对应的退出登录,那今天呢,我们就来完成相应的内容,先把这些方法呢给它收起来。那我们今天要做的,首先呢,第一个是这里的 refresh refresh, 那 么 refresh 呢,很明显,它要接受我们的 refresh token 作为我们的这样一个自助串。 ok, 然后呢,第一步先叫验我们的这样一个 refresh token, 那 这里呢,我们使用 jwt service verify a sin 传入我们的 refresh token。 那 么在校验的过程中啊,我们这里是可以指定它的 secret 的, 那么很明显,这里的 secret 我 们要多次的用到,因此呢,干脆啊,我们这里的配置内容呢,我们我们给它单独的拿出来,把这里 复制粘贴到上面去,我用全大写吧, access secret, refresh secret 给下面简单地替代一下, 这里也是一样给它收起来。那么在这里我们的 secret 呢,这里很明显就应该是 refresh secret, 然后呢,判断的结果,它是一个 promise, 对 吧?那么如果 判断它不对的话,它应该是默认会抛出相应的异常的,这里我们不用管。那么这里判断完成之后,一旦它通过了,接下来我们要做的就是在数据库中去进行查询,然后判断。因此接下来我们调用 users service, 我 们使用 find one, 那 么这里的 find one 呢,我们要基于我们的用户 id 来进行查询,所以呢,我们要基于我们的 refresh token 来获取我们的用户 id。 因为大家很明显能够看到我们在生成的时候呢,我们是把我们的 user id 作为一个 sub 给它传进到 我们的 payload 的 中间的,所以呢,我们是可以从这个 token 中间反向的结构得出我们的这样一个 id 的。 那么这个地方呢,我们想要从中获取到我们的用户 id, 其实这里的 verify i think 它返回的就是我们的 payload, 只不过呢,这里如果我们直接这样写的话呢,它是没有这样一个类型校验的,你会发现它返回的类型呢,竟然是一个 any, 那 当然这个是很正常的,因为我们没有在解析的过程中呢给它指定任何的类型,那它返回的这个 delete 自然就是一个 any 类型, 所以呢,这里啊,我们暂时这样写,我们后面呢肯定会对它进行一定的改正。那我们这里调用 find one 返回得到我们的 user, 那接下来呢,就是进行比对了,我们使用 be 匕,使用 compare, 因为我们的这个 refresh token 在 数据库中是通过我们的 be 匕进行加密的,所以呢,我们要比对一下 传进来的这个 token 和数据库中查询出来的这个 token, 当然这个是加密后的内容,它是否是一致的,然后这里呢,它提示我这里可能有问题。很显然,我们要判断一下我们的 user refresh token 它是不是存在的,只有当存在的情况下才应该进行判断,如果不存在呢,直接抛出我们的 unauthorized exception, 然后里面的错误信息还是一样统一的 invalid credentials, 也就是 如果我们的用户中间的这个 refresh token 它本身都不存在,就说明我们这个用户它是有问题的。那么比对的结果同样呢,我们要写一下,然后呢根据这个结果判断一下,如果为 false, 同样返回 authorized exception, 那 全部都通过之后呢?这里呢,我们再次调用之前我们写好的 this issue token, 传入我们的 user, 它的结构不太对啊,这里我想想我们能不能把它稍微简化一下呢? 我们其实只需要用到 user 对 应的两个东西啊,一个是 id, 一个是 email, 我 们其实只需要用到这两个东西就行了,我们不需要一个完整的 user 对 象,我们改一下,我们这里改为 id, 还有这里的 email, 这里两个就来自我们的 user id, 还有 user 到 email 拿到我们的 issue tokens, 我 给它改一下 id, 还有 email, 这上面同样的给它改过来, 然后呢,这里缺失类型提示啊,我们给它加上这两个基础的给它改好,改好之后来到上面,我们在 sign in 和 sign up 这个地方呢给它改过来, 那这里我们的 refresh 这样一个 service 应该就是完成的了,我们来简单的加上一些注士,我就让我的 ai 插件帮我写,好吧,因为这些东西呢,是很简单的,我们就不费神了。那最后我们来实现这里的这个退出登录 sign out, 那 么退出登录呢,就和刚才的 refresh 不 太一样, refresh 肯定是需要我们的 refresh token 来实现,那退出登录的话呢,我们 需要使用当前有效的这样一个 access token 来实现,这个相信大家应该是很好理解的,我们只有当前的用户 他的访问令牌有效的情况下,他才能够退出他的状态,不可能随便一个黑客拿着无效的一个令牌就能够让当前的用户被踢下线,这很显然是不正常的。 所以呢,这里我们接受的参数就是 access token, 那 么这里就非常的简单了,我们去校验一下就可以了,那么这里校验我们的 access token 没问题。那么接下来呢,我们就在这里调用我们的 this user service update 传入的用户 id, 那 这里的用户 id 依然要来自我们的 payload, 然后呢要更新的内容应该就是这里的 refresh token, 那 么这里的报错呢,其实很简单,它同样是提示我类型不兼容,对吧?它这里呢是和我们的 create user dto 呢,不对,这里为什么呢?明明我们已经打了问号的,为什么这里不能设置为 null? 那 么在 type script 或者说在 javascript 中,如果一个类它的属性后面跟上一个问号,那么表示这个类呢,它可以设置成一个 define, 也可以设置成它本来的类型,但是它和 null 是 没有任何的关系的, 而我们的数据库更新,它是需要设置成 non 值的,所以呢,这里为了给它改过来,我们只能在这里写上我们的这个 union type 组合类型, 这样写好之后呢,它就可以设置成 non。 这个是 javascript 还有 type script 的 中间一个非常经典的问题啊,那么成功更新之后,相信就没有任何问题了,我们返回一个相应的内容啊,这个返回的内容我们就留到 control 了中间去写, ok, 那 么此时呢,我们的 reference sign out 应该就 没什么问题了。我们接下来的话呢,去完成我们 controller 的 部分复制一下,这里应该是 refresh, 我 把它的名字改成 refresh token, 那 么它接收到的参数是什么呢?很明显就是这里的 refresh token。 然后呢,我们这里调用的方法就应该是 refresh 给大家传进来。那需要注意啊,这个东西本身啊,它是会被映射成一个对象的,而不是一个单纯的属性。所以呢,我们这里应该是叫做 body, 稍微好一点,它的类型呢,我们在这里手动地写上是这个 refresh, 然后呢,我们传入 body 点 refresh, 这样就可以了。 ok, 然后呢,是我们的 sign out, 应该是 log out, 我 想想, 这里所有的 controller 它都是叫以 sign 开头,那这里呢,都是 sign in register。 好, 我这样写法应该是没问题的,那它接收的内容,这里的 log in register refresh logout。 那 接下来我们就来测试一下相应的配置呢,我们先检查一下,检查我们的数据库连接, 需要注意啊,我们之前的内容中呢,我们是更改了 user 表中的这个 refresh token, 它的一个类型定义,而具体这个地方应该是要改过来的,它是可以为 non 值的,这个原因呢,就和刚才的 dto 其实是一样的,这里它是应该允许为 non 值的。那么接下来我们还应该把这个 anti user 表的这样一个迁移计划呢,给它创建出来 migration create, 我 们来看一下这个迁移计划是否是我们想要的。这里应该是三月十八号,今天我们创建的迁移计划,那这里呢,是新增了这样一个 column, 新增了这样一个列。好的,那我们来直接 migration fresh。 说实话,同时呢,同步我们的 migration 迁移计划。 此时来到我们的 nio 数据库,我们去检查一下,打开我们的 user 表,我们来看一下这里的这个列。 这里的 refresh token 可以 看到全部都是为 non 值的,因为我们在插入的时候就没有插入这个 refresh token。 那 我们接这里呢,我们只测试这么四个端点,因为我们还没有将我们的 j w t 这样一套健全系统应用在我们的 g r 的 中。并且呢,我们这套系统目前其实还有很多地方呢,我们没有解决, 尤其是刚才我们在获取这里的 payload 的 时候,比如刚才的 refresh 这个地方,我们在获取 payload 的 时候呢,这里是没有类型提示的,这样做很明显是有风险的。所以呢,我们这里加上 to do, 我 们后面再看具体的解决方法, 包括还有这里的 signout, 它去解析的时候,我们也是需要去给它加上类型提示的。 ok, 我 们来运行这个项目,打开我们的 bruno, 我 们选择去注册这里报五百啊,说明我们这里的服务器是有问题的,我们看一下 这它的异常错误是什么呢? j w t secret is not defined。 我 们看一下第一个它提出问题的地方。 generate token by user, 我 们跳转过去, 好,是这个地方,那说明我们的环境变量它没有正常的加载进来,并且这里的呃,变量名有点问题啊,那这里是因为啥呢?好,我先把这里删掉 啊,这里其实很简单啊,我们在加载的过程中呢,因为我们的 nest 是 基于我们的类进行注入的,那么注入的过程呢,它是类优先的,所以呢,我们整个这个 secret 相应的内容,最好是把它放在我们的类中间去使用, 所以这个地方我们直接剪切给它放到单独的这个类它的属性上,然后我给它改一下名字,啊,稍微这里应该是 secret, 这里也是一样 secret, 不 然我们这种不伦不类的编写 这种拼写有点有点奇怪啊。这里就是 refresh secret 前面加上了一个 this, 然后是这里 access refresh, 那 这里它应该会自动重启啊,但是呢,刚才我们注册的时候,它是会把这样一个数据先写进数据库,然后呢再生成这样一个 token 的, 所以呢,虽然我们这里生成 token 的 过程呢,它失败了, 他报五百错误了,但是呢,我们这样一个用户,他其实是被写进去了的。其实呢,这里我们的逻辑是有问题的,我们应该先生成,然后再去写,可以看到这里的用户他是写进去的,我把这个给它删掉,我们再来测试一下。回车啊,这样呢就是没问题的了,我们有这个 access token, 有 这个 refresh token, 我 们复制这里的内容, 我们再来登录,登录的话应该会拿到一个截然不同的 access token, 还有 refresh token。 因此我们把这里注册的部分呢,我们先截个图,和我们待会儿登录的这个部分呢进行对比 登录,登录没问题,然后我们对比一下深层的 token, 那 很明显,这里的 access token 还有 refresh token 全部都变成新的了。那相应的,如果我们拿着刚才注册的这个 refresh token, 我 们尝试去 refresh 的 话,那很明显应该是会报错的哦,这里呢, 很明显发生了错误啊,我们拿着刚刚已经失效的这样一个 refresh token, 我 们尝试去刷新,既然还能够刷新出来,那说明呢,我们的代码逻辑呢,肯定是有问题的,我们来检查一下。 好的,那么现在呢,这样一个诡异的情况就这么发生了,明明我们在注册在登录之后呢,注册时返回的 refresh token 应该会被登录时返回的 refresh token 给它挤掉才对。 我们能看到它返回的这两个 refresh token, 它的字母串本身就不是相同的,但为什么我们依然能够使用这样一个 refresh token 一 直不断地来刷新呢?这显然是一个 非常非常不正常的现象,就是因为我们的 jwt 在 签名的时候呢,它的内容本身就是有一定的重复性的,能看到我们在进行这里的 jwt 签名的时候呢,它只接收了我们的 id 还有 e mail, 它其实并不能从 id 和 e mail 上 来决定每一个签名的唯一性,我们还应该加入一个新的东西,来保证每一个签名都是独一无二的。 这里呢,其实很简单,我们可以加上一个简单的字段,比如啊,就比如这里的 j t i, 那 j t i 是 什么意思呢?那 j t i 就是 jason web token id 它的缩写, 那么对应这里,我们要通过随机生成的方式来实现,那这里我们的 id 呢,可以用上我们的 random u u id, 这里呢是 node js 内置的一个工具啊,我们直接这样返回就行了, 它是能够直接生成一个随机的 u u id 的, 那所谓 u u id 是 什么呢?这里我们先不做解释啊,大家就把它理解成一个 会随机生成的这样一个字幕串就可以了,它是来自我们 node js 核心库的,不用我们去安装什么额外的东西。那么这样实现之后呢,我们来把刚才注册的这样一些新的用户给它删掉, 删除,我们来重新运行一下,来到 bruno, 我 们重新的来注册一个新的用户 啊,可以看到我们加上了 jti, 也就是 jasonweb token id 之后呢,我们的 token 它的长度变得更长了,因为我们的 payload 的 它变得更多了,然后呢,我们来到这里的 log in, 我 们去登录一下,好的,那此时呢,我们拿着刚才注册时返回的这样一个 refresh token, 我 们去尝试刷新。 那么当前这个诡异的问题呢?其实啊,说实话比较棘手啊,这并不是我们的 jwt 签发的时候有问题, 米姐,就算我们等了很多秒之后呢,我们加上了刚才的 g t i 啊,依然没办法解决这个问题,这说明呢,我们在比对我们的签名的时候呢,存在问题,那么具体比对的地方呢?其实就是这里啊, 这个地方,这个地方比对的时候呢,它其实发生了问题,就是因为呢,我们的 b、 c, 它在比对的时候呢,它不会比对非常长的这样一长段的字母串, 而我们的 j、 w, d token 呢,它就是这么一长段的字母串,它只会截取前面的一些,而可以看到我们的这两个 token 呢,不管是 access token 还是 refresh token, 它们在用相同的算法 进行签名生成的时候呢,它前面的一小段其实都是一样的,所以呢,在对比的时候呢,很明显就是会出错的。 也就是说呢,在对比的时候呢,我们的这里的 beeper 它就不太可靠了,要么我们把它的这个 refresh token 给它做一次处理,要么我们换用其他的比对方式。那么这里呢,我们在深层的逻辑上呢,我们就要改一下,我们把这里 issue token 这里进行加密的部分呢,我们 改成其他的,因为本质上呢,这里我们并不是对密码做加密,所以呢完全没必要用 beeper, 我 们自己来构造一个加密的这样一个小函数, private hash refresh token 啊,接收的是 refresh token, 因为我们要对 refresh token 做一些处理,我们想让它变得更短一点,那这里呢,我们可以用什么呢啊?我们可以用 create hash, 这也是刚才我们这个 node js 内置的库,我们使用这个上二五六, 然后呢调用 update digest 传入 hexadecimal, 这样呢就能够保证它返回的这个内容呢,它的长度是固定的,我看看这里没有导入吗?导入一下,然后呢用它来替换我们这里的 becraft hash 这个操作, this hash refresh token, 然后呢,比对的时候,也就是在 refresh 这个地方,这个比对的时候呢,我们就不用 becraft compare 了,我们就直接使用刚才的 this hash refresh token, 我 们把传进来的 refresh token 再做一次简单的这个处理,然后呢和我们的这个 user 点 refresh 做一次比对就可以了,这样的话,我们就不用到 becraft 对 我们的 gwt token 做任何的处理。那这样修改之后呢,我们再次重置我们的数据库,重新来测试一下,看看刚才那个 token 不 过期的问题是不是依然存在。启动我们的项目,来到我们的 brono, 同样的先注册, 然后返回的 token 长度和刚才是差不多的,但是我们先来到这里的数据库,那此时呢,你会发现我们的 refresh token 它的长度呢,其实就没有刚才那么夸张了。此时呢,我们再来到 bruno, 我 们再登录, 登录之后呢,我们这里的这个 refresh token 它应该会被改掉。好,我们再拿刚才注册的时候返回的 refresh token, 我 们尝试去刷新 回车,那这个时候呢,我们的 token 它就真正的失效了,因为我们刚才在比对的时候呢,错误地使用了 beecraft, beecraft 在 比对的时候呢,就有我刚才所说的这么一个长度截断的问题。好的,最后是 logout, logout 的 地方呢?我看一下,我检查一下啊,应该是在 controller 这个地方,应该是 logout 保险啊,应该是 signout, signout ok, 它会接受我们的 access token, 那 么 access token 呢?应该是刚才登录时候返回的这个东西啊,这里如果我们复制刚才得到的 refresh token 的 话,那很明显它是会报错的,这里可以看到是我们的服务器内部报出。我们看一下 这里的错误,它提示的是什么呢? invalid signature 报错是正常的,只不过呢,我们的 nest 的 js 它默认不会处理这个错误。所以呢,之后我们需要写一些简单的 filter, 对 我们的这个 j w t 内部的错误呢做一些处理才行。这个错误呢叫做 j d json token arrow。 那 接下来我们传入正确的这样一个 access token 粘贴回车,那此时呢就正确地进行注销了。当然我们没有写这个响应体啊,所以呢,它什么也没有。我们刷新一下好这里的 refresh token, 它就成功地取消掉了。然后到此呢,我们就算是成功地完成了 refresh token 以及相应的退出登录的逻辑。我们的整个健全和 j w t 的 部分呢,算是做好了,当然目前我们还没有用它来保护我们的接口,对吧?那这个部分呢,我们就留到下一节的,再把它结合进去。那么相信本节呢,是比较的麻烦的,因为我们 涉及到了一些 refetch token 相应的逻辑,并且呢解决了一些其他的问题啊,我们发现了 becraft 在 j w t 这个场景下的一些简单的缺点,我们需要自己 对我们的 token 做一些处理,但是呢,其他的逻辑相信各位是能够理解的。我们上一节已经讲过了,我们要做的呢,就是去解决一些细枝末节的问题,那么以上就是本期视频的所有内容,希望你能关注或订阅我的频道,感谢你的观看,我们下期视频再见!
粉丝1504获赞7193

这就是我坚持的动力,我看今天群里反馈了一些问题,你改了没?没,还没来得及改那些。那都是些小的,一晃没有大的一些罢了。我今天改啥?就是现在就是, 呃,性能有点,媒体稍微人多一点啊,这个 cpo 以及内存就会飙升,所以我在排查代码,看他们男女有没有内存泄漏。今天我利用用这个 阿里这个诺基亚的新闻平台在这飞行看内存就占了百分之九十八点三,我在排查。排查在吗?嗯,那完了我把群里那些问题整理一下,你有时间一起改吧。 哎,行行,我,我先把又先把这个搞完吧,大家能够流畅的用。嗯,没看啊,今今天到现在又一千零二 二十三个,我觉得现在每一天稳稳当当的在一切以上。可以可以可以可以,加油,这就是我坚持的动力,哈哈哈。

今天是使用 next 加 ts 开发服务端的第三天,呃,我也是从零学习这两个技术啊,然后去做服务端的开发。 哎,我觉得这个东西啊,真的是太简单了,那个耐克斯特呢,几行代码就可以去写一个接口,真的是风光的特别到位。我觉得只要搞明白他的 sos 以及抗初老还有猫斗啊,哎,我觉得这个问题就基本上你就可以写借口了,很容易 啊。还有他的数据库的操作啊,你可以用一些第三方库,你基本上你连色库都不用写,我原本还开始写什么 ci, x, trump 啊,英赛的英兔等等啊这样的色库语句,后来发现,哎,有一个第三方库,你可以直接套到数据库啊,你直接比如说 你要查所有的数据翻的,哦,特别容易啊,哎,还有好多比如说像一些入餐的教宴啊,你可以定一个地区,然后它里边可以去做用第三方包,也可以去做入餐的格式的教宴。哎,再说一下, ts 之前也没有用啊,那么为了这个项目,我觉得也没有必要去单独的去学 ts, 在这里边唯独用到 ts 就是他的类啊,以及他的什么,他的这个呃,变量的类型对吧,其他的其实都没啥区别啊。 呃,总之啊,这个进展还是很顺利的哦,还有一个事情,就说我们前端在写代码的时候啊,都是服务端给我们提供过来的一个接口文档,大部分 都用的是这个死歪哥,对吧?哎呀,当时啊,我们就想这个死歪哥,就问他他们是怎么搞的,对吧,也知道是用代码声称的,但也没想到他这玩意用代码声称这么简单, 也是有一个第三方包对吧?啊,你只需要在相关的位置去做一个引用定义,哎呀,很快就可以生成一个很完善的非常详细的一个索爱格文档啊,我觉得我身上的索爱格文档啊是特别特别详细的,比好多服务的给的索爱格文档还不详细,哈哈。 啊,我觉得,呃,现在觉得越写越有意思,所以我也强烈建议啊,我们做潜在的小伙伴一定得尝试,即使你不会弄的 gs, 我觉得这个与你会什么录的 gs 没啥关系,听见没,你直接上手可以用它去搞一个哪怕很简单的几个接口啊, 走一遍这样的所有的流程,包括从他的漏油入餐、返回值,查询数据以及到文档的声称。 你会对你整个的开发有一个非常大的一个提升和认知,让你以后跟服务单的交互啊,会更得心应手啊。哎,好了,继续工作了。

微信小程序已经不支持使用 get user 接口获取到头像和昵称了,获取到的昵称会是默认的微信用户头像是默认的灰色头像。那么当下最普遍的一个登录流程,我们来看一下。点击进入到我们的个人中心页面,那我需要点击注册登录, 此时前端会使用微信小程序提供的 login 接口获取到扣的,然后调用服务端给出的接口把扣的传过去。那服务端接收到扣的之后,同时还需要 a p p id secret, 用这三个向微信接口服务去换取到 open id 和 section key, 并且在数据库中保存一条数据。那么此时我希望我们显示在个人中心的是我们真正的一个微信的昵称和微信 头像,那微信小程序给我们提供了一个微信昵称和头像获取的方式,我们需要挨个的手动去获取。进入到修改页,那我们要获取头像,我们可以点击这里, 点击之后会弹出一个弹出框,在这我们可以选择使用微信头像或者在相册当中去选择,你也可以使用拍照的功能去拍出一张头像,那这个方式它使用的是微信小程序提供的一个 button 组件,把 open type 的值设置为了 choose a wetter, 然后我们点击使用微信头像,他就会获取到我们这个头像的一个地址,然后我们要把这个地址更新到数据库当中去,然后我们回到我们个人中心页面,这里就显示了微信的一个真正的头像,那同理我们要获取到微信真正的一个昵称,我们也是进入 到修改页,然后点击这里,那点击这里呢?他也会弹出一个框,用户昵称的获取。微信小程序给我们提供的是一个 input 组件,把 type 设置成了 nickname, 那我们选择微信用户昵称,这就选择过来了。那同理我们要把这个昵称也更新到数据库当中,然后我们再回到个人中心页面,此时这里就显示了一个真正的用户昵称。

我前一阵讲那个 later, 我已经讲了一阵了啊,然后也写了一个系统管理平台,支持多站点多模块了。前端的话呢,就用我写的前端脚手架,在那脚手架基础之上完成的,前端使用的是新版的 vivo 技术,包括 ts 等等等一大堆。 然后后面的话,我过段时间呢,就要讲这个 nice 的 gs, 这个雷荣的项目,我应该还有个两三堂课吧,然后有人老问我,这个雷我跟 nice 的哪个好学,哪个简单? 嗯,因为他俩是不同的语言啊,一个是 psp, 一个呢是 gs 是吧?假设说你的这个对的,这两个语言熟悉程度跟我差不多,就是呢,都还凑合,是吧?那这种情况下他俩其实真差不多,有很多相 统的概念是吧?我们就外部应用,比如说中间转,比如说中间建,比如说首位,比如说 polis, 比如说依赖猪肉服务容器,有很多概念呢,其实是相似的, 路由啊,控制器啊,模型啊,模块啊等等等。所以呢,其实学习成本啊,如果你语言都差不多的话,我觉得就是,嗯,五五开吧, 这两个框架其实都特别的适合于中小企业,我们知道绝大多数企业都是中小企业,所以这两个框架其实都特别好,开发速度特别的快。 那我过几天啊,这个 later 那个项目还有两三堂课,我给他讲完之后,我过几天我呢就要讲 nice gs, 到时候呢,你可以来我直播间看一下。那如果你说我就想 通过一套 gs 语言是吧?我把前后端都做他,我呢以后呢,要也要写一些手机应用,后端的话呢,我就用我一个变成语言全部搞定,因为现在 gs 也挺厉害,是吧?那这个的话呢,可能对你来讲还是有好处。 我到时候啊,这个系统平台我已经写了,我回头的话拿这个 nice 的 gs 也会写一个系统平台,到时候我就会网上写很多模块,那个平台之上的网上无限的增加模块。 嗯,我第一个增加的话呢,应该是后盾人,那个咱那个在线网站啊,到时候会晚上增加那个视频播放网站, 之后的话,像这个倒计时软件,我也可以写个桌面端程序。呃,然后呢,这个后台的话呢,就可以使用这个系统平台,包括我可以写一个桌面端的什么壁纸啊? 换电脑壁纸的,类似的这样的软件都可以,所以大家可以关注一下,然后咱们一起学习,一起进步。


今天介绍中央空调控制器, nice 的温控器,金属外观具有极强的装饰性,人走到跟前会显示时间或者温度,他可以自动控制空调地暖新风 按压进入界面 波动切换功能, 操作简单,满屏写着高级 内置传感器,可以检测室内温度,根据室内温度和人物移动来自动开启或关闭空调等。设备 有奥特斯,该种功能根据主人的作息自动学习编程,比如你在某一特定时间设定了某个温度,他会进行记录,之后会自动设置,所以更加节能环保,做到真正的极致智能,也可以手机远程控制。关注我,了解更多智能家居!

我最近每天晚上八点都在讲 nice gs, 然后帮助大家呢,从零开始学会一个 gs 的后端框架,让前段工程师呢也可以做前后端的一套应用。不过我在讲的时候啊,很多人会问我,他说 nice 的 gs 跟这个 spr 之间到底有什么区别? nice gs 呢,它是在 eceprise 基础之上进行的开发。呃,做出来的一个框架,或者简单来讲的话呢,就类似于你使用的各种安卓操作系统,它都是在原声操作系统之上进行的美化修饰,添加一些小软件,是吧,做一些好的体验。 那么 isprise 的话呢,就类似于原声的安卓应用。这个 nice 的 gs 呢,就类似于拿到你的你买的安卓手机用到的那个那个系统。对, nice 的 gs 啊,他就是站在 isprise 这个巨人肩膀之上,遥望远方。

如果说你连 nice 的 g s 都看得很吃力,我真的建议你暂时别选 note, note 它是一套非常复杂的体系,跟前端一样,你现在选 nice 的 g s, 就好比 你去学前端,连三大件都不学,直接去搞 rex, 那你觉得这个方法正确吗?那肯定错误,对不对?好,我们来看一下啊,后台的体系到底有多么的复杂,今天就把大家通通都劝退啊。首先我们来看 最早期啊,服务端啊,他最流行的模式是单体架构,那什么是单体架构呢?其实非常简单啊,说白了,后台 他只有一套代码,一套代码里面分一些这个模块,那个模块中间加一个负载均衡器,项目部署就上线了。那这样的话,其实他有非常明显的问题。第一个,业务偶合性太强,功能不容易扩大啊。第二个,服务性能很难扩展,这个怎么讲啊?其实非常简单,我举个例子, 他说我模块 a 他非常是内存,我模块 b 他非常是 cpu, 那假如说这个时候模块 a 他的用户量起来了,他一下子是不是就会把你系统的内存直接打满,但是你的 cpu 占用非常非常低,那这样对于服务器来讲,是不是一种性能损失?为什么呀?因为只用了内存,但是没用 cpu, 那就浪费钱啊。我们再来看 s o a 架构,它是解决前面的问题。那 s o a 架构实际上呢,就跟我们前端啊,一个项目啊,分了几个代码仓库一样,我们把这个业务拆开,但是呢, s o a 它还是会存在问题啊,因为拆开的力度比较大, 那这样力度是不够的。第二个呢,像 s o a 这种模式呢,它需要一个集中的调度总线,那这个调度总线呢?它调度各个模块啊,调度我们的用户的访问,那这样的话其实很容易在调度总线这里呢出现 性能瓶颈,所以呢,后面就衍生出了非常流行的微服务价格体系。好,我们来看一下微服务价格,他又分两块,那首先你搞微服务,那你一定得知道我这些服务到底该怎么划分,那这个时候你可能先要参加一个考试,对吧? 这个就是在微服务体系里面非常流行的叫做 ddd 领域驱动设计,这个就是一个指南,告诉你你一个项目来了之后,到底怎么去划分模块啊?就好比你现在找工作,你必须有个本科学历一样,这个是敲门砖啊,所以搞微服务,你必须先把这个搞懂。好,接下来我们再来看啊,微服务他简易的一个 架构图。好,我们再来看一下啊,首先我们的客户端,比如说分为 pc 手机 api 给了位, api 给了位,这个是什么 api 网关,下面就是一些划分力度更加细的 一个一个的微服务。你看比如说产品服务、订单服务,他有自己的数据库,服务与服务之间呢,就可以相互去进行调度。好,我们来看一下啊,实际上整个微服务架构体系里面呢,比较重要的就有这六大模块。首先是 api 网关啊,它的作用主要是用于复杂均衡返乡代理,然后提供 http 服务,包括健全。 一个请求来了,我不可能随随便便你谁都能访问我们的底层服务吧?对不对?得有一层防火墙。好,我们再来看第二个服务监调用,那服务监调用又得考虑非常多的问题,那我到底服务与服务之间是用什么协议呢?用 tcp 还是用 iptp 啊?还是用现在比较流行的 gmc? 那还有第三个问题也要考虑,那比如说啊,我现在一个系统一个服务啊,我见过一些大型的系统,有上千个服务,那比如说我这个时候有一个新的服务来了啊,系统怎么知道是不是?这个时候?其实就需要有个服务发现,也叫 注册中心得知道啊,我的新的服务来了,可以提供服务,那第四个,那这么多的服务,其中有一个挂了怎么办?我该怎么处理?那第五个,那 我有上千个服务,那服务与服务之间他肯定是有依赖关系的,我 a 调 b, b 调 c, 那模块错综复杂,相互依赖,那到底先部署谁?是不是?那假如我先部署 a, 那 a 又依赖别人,那别人没有部署,那怎么办?那第六个, 那他的数据调用的链路也会非常的长,那同理,我 a 掉 b 掉 c 啊,链路十几条,一个服务掉了十几个服务,那其中一个出错了,我到底怎么去排查?到底错误在哪里?你是不是搞死? 你看一个前端项目,你就一个地方错了,你都找 bug 找半个小时,那你说这有十几个服务,对吧?那其中一个挂了,你怎么知道是哪里?那不得整死你啊?所以整个体系还是非常非常复杂的,我们总结一下啊,看起来 微服务架构非常美好,实际上呢,非常非常复杂,你如果说没有深刻的理解啊,就非常容易玩崩盘,那到这里你不要认为微服务就结束了,实际上啊,现在又有一个非常流行的架构,叫做 servermax, 那 servermax 其实它是对微服务的一种改进。比如说我举例子啊, 那每个微服务我们可以简单的视为包含两个部分啊,业务逻辑、网络功能,对不对?这是两个非常 非常核心的,那其中网络这一块啊,是非常非常复杂的,需要解决很多问题。比如说啊,你使用什么网络传输协议?是 h g p 一点零还是二点零,还是 g r p c? 那你考虑网络的时候,你是不是得考虑哦,服务发现的机制,熔断机制,那超时了怎么办?怎么从事服务调用的时候啊? 怎么复杂均衡?那每个微服务对吧?我一个系统上千个微服务,那都需要处理这些网络问题,那如果说所有的微服务都用加码还好,但 是你一个大公司,对吧?组成一套微服务的网络,那有的用 go, 有的用加吧,那怎么办?怎么去统一?那其实非常非常的复杂,所以这个时候就引入了 sarmanc 的架构,那 sarmanc 它的主要作用是什么呢?其实在每一个微服里面呢,就注入一个通用的模块啊,叫做 say the car, 他专门负责网络处理,而且和语言无关啊,大家看张图就能非常行现啊,在我们那边呢,这种东西叫做什么?叫做边斗啊?所以塞得卡,就好像哎,给你加了一个座椅啊,他就给你保驾护航。但是呢, sarmax 他也有他的不足之处,首先呢,就是增加了我们整个系统的一个复杂度,比如说 增加一些模块,而且服务之间的通信不像以前那么直接了,而且要经过代理,对吧?那你不要认为到这里就结束了,我们再来看还有哪些东西你没学啊?你比如说啊,数据库就有什么关系型、非关系型类 唇形数据库,还有列数据库,包括你还得去考虑分布式数据,一次性主,从主背主主到底是什么意思,包括性能优化、分布式说等等等等啊,各种乱七八糟的。所以如果你没有对服务端非常浓厚的兴趣,我不建议你们轻易的去 尝试啊,一旦开始知识体系非常的庞大,如果你真的对这些内容感兴趣,可以来我们关门地址九九九深造一下,这些内容都是我之前在腾讯的实践,人家讲不了的,我们可以我就问你还有谁主页橱窗直接冲。

各位同学大家好,这里是由 it 赢点 com 为大家提供的 nest gs 系列教程,我是朱杰老师。大地,那这样的话,我们主要给大家讲解一下这个 nest gs 中的中介介。 首先我们看一下什么是这个中介介啊,通俗的讲,中介介就是匹配路由之前,或者匹配路由完成以后做的一系列的操作啊。那这个 nest g s 中的中介介啊,实际上和这个 express 里边中介介是一样的啊,那它的功能的话和这个 express 也是一样的,这里边我们就不读了啊。 net g s 中的中介件可以是一个函数,也可以是一个被 injectable 装饰器装饰的类啊,那接下来的话,我们看一下在 net g s 中如何创建和使用中介件啊,打开这个官方文档给大家看一下。那在。 net g s 中的这个中介件的话 啊,可以是一个类,也可以是一个方法。如果是一个类的话,那这时候我们可以通过 next g s 里边给我们提供的这个脚手架工具来创业,也就是 next g made well 啊,然后这里边写你中介件的名称,然后这个命令执行完成以后,他就会给我们生成这样一个中介件的类啊, 那在这里边的话啊,我们就可以啊去处理我们这个请求啊,以及处理响应,以及啊决定他是否向下匹配啊,这就是中间键。 那这个中介介创建好以后,然后接下来的话,我们还需要配置,配置的话,我们需要找到更模块啊,一定要注意,在更模块里边首先引入这个中介介啊,你看他这里边是不是创建的这个名称啊, 然后接下来的话在这里边引入了这个路基键。引入以后啊,然后接下来的话,他这里边还需要实现一个 nes 它的这个接口啊,也就是 next module 的一个接口。实现以后,然后这里边的话啊,实现它里边这个 configure 方法,然后在这里边的话啊接收一个啊参数 啊,叫 made well consumer 的一个参数啊,然后接下来的话,在这个方法里边可以通过 consumer 点 apply, 然后来配置这中介件啊,也就是啊使用我们这个中介件,然后这里边的话啊啊决定在哪些路由里边使用,也就是 forus 里边可以配置到底哪些路由使用当前这个中介件啊,这就是我们如何创建以及使用中介件啊。那接下来的话我们给大家演示一下, 打开我们这个项目啊,然后再客气的话,我们新建了这样一个项目。新建好以后,然后接下来的话我们又新建了几个控制器啊,通过 next g ctrl, 然后创建了这么几个控制器啊,我们 我把它放在了这个 ctrl 文件夹里边,然后接下来的话我们运行一下啊,运行以后我们首先看一下能不能访问这几个页面啊 啊? local house 的三千,然后这时候的话它加载的是我们这个根控制器里边的这个方法啊,然后接下来的话我们在这里边输入一个 user, 我们看一下能不能加载这个控制器。可以啊,然后这里边还有什么呢?还有这个尿字 啊, news n e w s 还有这个 product 啊啊 product, 这就是我们课前新建的这几个控制器啊, 然后接下来我们就在这个项目里边给大家演示这个中计件的使用啊,那首先的话我们创建一个中计件啊,创建中计件的话可以通过 next g 来创建啊, n n e s t 啊, next g, 然后这里边盖盖还要跑啊, 我们看一下这里边的话啊,他就有这个命令行工具啊,来生成我们这个终极键,看一下是不是有个 made well, 然后接下来的话,我们通过 nettg, 然后这里边来个啊 made well, 双击,然后按一下右键啊,按一下右键,然后这里边再按一下右键,他这边就可以粘贴, 然后这里边的话创建一个 in it 的中间键啊,当然我们想的是这个中间键回头放在一个文件夹里边啊,和我们这个控制器一样啊,那这时候的话我们就可以这样写了啊,我们在 inter 前边啊写一个文件夹的, 呃,名称就是这个是相当于文件夹啊,然后后边这个应用它相当于中介件的名称,那这时候我们回车一下,它就会在 s r c 目录里边生成一个中介件的文件夹,然后在里边啊给我们生成一个应应,他的中介件啊,这就是中介件啊,他其实就是被 这个 injectable 这个装饰器装饰的一个类啊,然后这里边的话实现了这个呃, next midwear 啊,这个接口啊,然后在这里边的话我们就可以配置我们这个中机键啊啊,比如说匹配路由之前我们想的是打印一下当前这个日期啊,那这时候我们就可以这样写 啊,当然你也可以在这里边做一些全线的判断以及处理一些过户的功能啊,那这样的话我们这个中间键就新建好了,新建好以后,然后接下来的话,我们还需要 配置这个中介介啊,配置中介介的话,我们需要找到我们的根模块啊,找到根模块,那这时候的话找到我们的 a p p 点儿 model 点 t s, 然后在这里边儿的话需要引入我们当前的这个中介介啊,那这个中介介的话,你注意它的一个路径,它在啊 mate vera 啊, mate vera 这个文件夹里边叫 int mate vere, 把它引入啊,然后这里 的话名称就叫英特 matebel 啊,犹如以后,然后接下来的话,哎,我们要去配置他下边这个 app model 这个类啊,以前的话这个更模块里边这个类是是一个空的啊,然后接下来的话我们需要啊实现一个接口,那这时候的话我们就直接把这个代码拿过来了啊,啊?拿过来给大家看一下 啊,实现这个 nest module 这个呃接口啊,当然 nest module 的话你也需要引入啊,他在我们这个呃 nest common 这个模块下边啊,然后接下来的话啊,这里边啊 里边去处理他这个接口里边这个孔飞鸽这个方法啊,在孔飞鸽里边的话,我们需要接收一个参数叫 consumer 啊,然后 consumer 的话,他这个呃类型就是这个 maidevir 啊, consumer, 然后这个 madvare consumer, 我们也需要引入一下啊,然后接下来的话这里边啊,也就这个 consumer 这个方法里边 我们就可以配置这个中机键啊,通过 consumer 啊,也就是通过这个参数点 apply apply 这里边就是我们这个中机键,那这里边的话,我们需要应用这个 intermadever 中机键啊, 然后这里边有一个 foreus 啊,有个 foreus, 然后这里边的话就可以配置我们这个路由,比如说这里边写个心的话,表示匹配所有的路由啊,匹配啊,所有的路由, 那这时候的话啊,当我们再访问我们的这个呃页面的时候啊,啊,我们重新运行一下,再访问我们这个页面的时候,他就会啊,首先经过谁呢?首先经过我们这里边这个中基建啊,首先经过中基建 打印一下日期,然后再继续向下匹配啊,那这时候你看一下啊,走一下。当我们啊访问这个 product 的时候,是不是打印出了当前日期啊?当我们访问六子的时候,他同样的打印出当前日期, 当我们访问这个 user 的时候,同样的,对吧?包括我们访问首页的时候,他也执行了我们这个中介介里边的方法啊,比如说这里边我们再打一句话啊,叫中介介,对吧?叫中介介 啊,叫 int 终结界啊。啊,那这样的话,无论你访问哪个页面啊,它首先都会经过这里边这个终结界啊。 ok, 那接下来的话啊,我们想的是有些路由配置这个中间键,有些不配置啊,那这时候的话,我们看一下如何去配置他,那这时候再找到这个 app, 点 model, 点 ts 啊, 那这时候的话,我们就可以在这个 forerew 词里边做文章了,比如说我们想的是啊,只有这个新闻啊,新闻这个路由,然后啊匹配这个中介介,其他的路由不匹配这个中介介啊,那这时候的话,我们就可以 在 forus 里边啊,直接写当前这个路由,叫 news, 那这时候我们再运行一下给大家看一下啊,那之后走一下,你发现访问缪子这个路由的时候,打印出了终结界,但是我们访问其他路由的时候,你仔细看啊,访问这个啊, u 字 啊,柚子没有打印吧啊?访问这个破烂给他是不没有打印啊,就这个意思啊,这就表示啊,匹配指定路由啊啊,这表示匹配所有路由,我们把这个都给大家注射到这啊,匹配所有路由啊,这个代码注射掉,然后接下来的话,我们这里边啊再写一个, 再写一个,比如说叫点,然后这里一边来一个 user 啊,表示匹配指定路由啊,匹配指定路由,那这时候的话只有谁呢?是不是只有 user 会匹配当前这个中机键啊?你看一下访问 u 的是不是匹配了,然后其他的路由他就不会执行这个终结界啊啊,这就是这个终结界的使用啊,当然这里边配置方法非常多啊,我们在这个 forus 里边,这里边可以直接传入一个控制器啊,也就是你引入的控制器可以直接传入你,比如说这个文档上,他就给我们写了啊 啊,文档上就有给我们写啊,直接传入一个控制器啊,看一下他直接传入一个控制器啊,这个表示只有这个控制器会匹配当前路由啊,但是这种方法的话,我们不建议大家写啊啊,我们不建议大家写这种方法,我们建议大家就是啊用路由的方式去匹配这个中间键啊, 当然我们这里边还有其他的写法啊,啊,也就是匹配终极界的时候,我们也可以这样写,你看一下,这里边我们可以写一个 pass, 对吧?啊,指定当前的一个啊,路由啊,以及啊 指定当前路由里边的哪些请求匹配这个中间接啊,我们也可以这样写啊,那这时候我们就直接把它复制过来,或者我们也可以自己敲一下,对吧?自己敲一下, 那这时候同样的,比如说我们想要 user 匹配终极键,那这时候我们就在这里边写个 pass user 啊,然后这里边写个 mass 啊, mast 啊,然后这里边啊引入这个 request mast 啊,在这里边引入 request mast, 然后在这里边的话啊,匹配当前终结界的时候,我们可以啊指定到底哪些请求匹配终结界啊?比如说刚才写的的话,那就是所有的请求都匹配,如果我们只写一个 request master 点 get, 表示只有 get 请求匹配终结界啊, 如果我们写一个 out 啊,表示所有的这个啊, user 里边的请求都会匹配这个中机键啊,就这个意思。当然如果这样配置的话啊,我们也可以配置多 哥哥啊,你看一下这时候的话啊,就是如果你只是这样配置的话,是不是只有 user 会匹配这个中机机啊?那这时候我们运行一下啊,仔细看啊,我们访问首页没有打印啊,访问这个 user 啊,访问稍等,访问柚子 六子,你发现也没有打印啊,但是我们访问 user 的时候,是不是这里边打印出了终极键,表示匹配到了这个终极界啊?那接下来的话,我们想的是 user 和谁呢? user 和 news 去匹配当前这个终极键啊,其他的不匹配,也就是我们访问 news 的时候他也能打印, 那这时候的话,我们可以在这个 forus 里边继续去配置啊,继续去配置,那这里边再来一个 news, 那这样的话表示什么呢?表示这个 user 和这个 news 都去匹配当前中机键啊,那这时候你再看一下我们访问 news 的时候打印了吧,我们在访问这个 user 的时候是不是又打印了?当我们 访问这个 product 的时候啊,你发现 product 的时候,你发现没有反应啊,当我们访问这个收页的时候,你发现也没有反应啊,这就是啊,另一种配置中介介的方法啊,另一种配置中介介的方法,那这种的话啊,其实还是用的比较多的啊,就是这里边写的这种啊, 啊,这表示匹配啊,多个路由,多个路由啊。行啊,那这个我们就介绍到这啊,然后接下来的话我们再继续啊,接下来的话,比如说我们有多个终结界啊,我们想的是有些路由匹配这个终结界,有些路由匹配另一个终结界啊, 比如说接下来我们再创建一个中机键,叫 user 的一个中机键啊,那这时候我们把它给结束,结束以后再重新新建个中机键,比如说啊, user 的中机键啊,通过 next g, 然后 made well 啊,然后 创建在梅德威尔的下边啊,那这里边的话又多了一个 user 的中基建啊。 user, 然后这里边的话我们就打出一句话啊,叫啊,我是 user 的中基建,稍等一下,就这个中基建,他只是给这个呃,用户用的啊,这叫我是 user 的中基建啊,中基建, ok, 当然这里边这个 nest 一定要写上啊,如果不写的话,他这里边匹配到这就不会继续向下匹配了啊,你这个页面就有个卡死的状态啊。然后刚才那个中介介的话写一个,我是公共中介介啊,我是公共 啊,中介介,中介介。 ok 啊,那这时候的话,我们再给大家运行一下啊,运行一下,运行后我们再配置一下什么呢?配置一下这个 user 的中介件啊,那这时候的话,同样在 a p, pp 点 model 点 ts 里边进行配置啊,那这时候的话我们就可以啊,一次配置多个终极界啊,你看一下啊,我们下的是你所有路由都匹配谁呢?所有路由都匹配这个阴影的这个终极界。那这时候的话,我们就这样写啊,你看一下啊,我们把上面的些全部注视掉啊, 啊,或者到这却不写注视掉,注视掉以后我们再重新给大家写啊,就在下边来啊,我们想的是 所有路由啊,所有路由都匹配这个 in it 的终极节啊,那这时候我们就写看,呃,这个 consumer 点 apply, 然后这里边 in it module 啊 啊 intermediber, 然后再来一个点儿,再来一个点儿什么呢? for, 那 for 入词,然后在这里边儿的话写一个芯,表示所有路由是不都匹配你这个 inter 终极键。然后接下来的话,我们想的是指定路由,也就是 user 匹配 user 的终极键啊,那这时候的话,我们需要引入这个 user 的中机键啊,引入 user 中机键,把它给首先引入啊,叫 user 啊, user 中机键 user made well okay 啊,我们想的是只有 user 匹配 user 中间,那这时候的话,我们继续点啊,他这里边可以连缀操作 oplay 什么呢? apply 啊? user user made well 啊。然后这里边的话啊,点 for roots, 让谁去匹配呢?让,让这个 user 拿着这个 user 去匹配 user 的终极键啊,就这个意思啊,表示什么意思啊?表示所有路由都可以匹配音的终极键啊。但是这个 user 的话啊, user 的话,它不仅能匹配因它,它也可以匹配它自己的这个终极键。那这时候我们给大家运行一下啊,你看一下 啊,预习一下,看一下这控制台啊,我们刷新一下,你发现这里边是不是匹配了啊?我是公共中介介啊。 然后这里边如果你访问六子的话,他是不是也只匹配我是公共主机键?但是这时候你看啊,如果我们访问 user 的话,走一下, 你看他匹配了我是公共中机械,并且匹配了我是 user 中机械,对吧?这就是这个意思啊, user 再走一下,我是公共中机械,我是 user 中机械啊啊,这就是给大家讲的呃,配置多个中机键啊 啊,以及多个终极界的一个匹配方式啊。当然我们这个终极界还可以有另一种写法。那接下来我们再给大家写一下啊,再给大家写一下啊,同样的,我们再新建一个终极界啊,比如说还有一个叫六子的终极界。再新建一个 啊,先记好以后,然后接下来的话,我们修改一下 news 的这个中介介啊,然后在这里边打印出一句话啊, come soda log 啊,我是 news 的中介介啊, 柚子的中基建。然后接下来的话,同样的,我们在这个更模块里边把当前这个中基建引入啊,啊,引入这个纽子的中基建,给大家演示一下这个中基建的使用啊,你只有会使用中基建啊,回头我们啊,我们的一些右逻辑你才会处理啊, 这个中介介非常非常重要啊,然后接下来的话,我们再把这个给大家注视掉啊,注视掉,注视掉以后,我们再给大家写另一种方法啊。 啊,那这首的话我们想的是什么呢?想的是你这个 user 啊, user 和 news 啊, user 和 news 都去匹配 user news 的中间键啊,其他的不匹配,那这首怎么写? 那这时候的话我们就可以这样配置啊,在我们这个 apply 里边一次可以配置多个终极键啊,然后这个 foru 词里边的话,我们也可以一次配置多个路由,对吧?啊,那这时候的话,我们就这样写了,然后这里边来 pass, 我们直接把上边这个复制过来啊,复制过来啊,把它给复制过来 k, 然后再复制一个,再复制一个。什么呢?我们刚才是不是说的 user 和 news 啊, user 和 news 匹配啊,都匹配,这两个中间接,对吧?啊?其他的都不匹配,就这个意思 啊,这就表示我们可以在 apply 里边一次配置多个中机键,也可以在 forus 里边一次配置多个路由啊,那这时候我们再给大家运行一下 啊,然后接下来我们访问一下啊,比如说访问 user 看一下啊,公共中机械, user 中机械,那这里边不对啊,这里边写错了,这里边应该,呃去配置这个 news 的中机械啊,我们配置成英英特了,然后再来一下, 然后再重新访问啊,仔细看,访问一下,我是 user 中基建,我是 news 中基建啊,然后接下来我们再来一个,比如说叫 news 啊,稍等一下, 访问这个 news 的时候,你看一下他是不是也匹配了这两个中机器啊,也就是这个 user 和 news 都会匹配这两个中机机啊。但是其他的路由啊,我们再保存一下,你看一下其他路由他到底会不会匹配啊?这个 user 肯定会,对吧?然后接下来,比如说我们跟你发现没有匹配,然后这里边这个坡大给他 啊,你发现没有匹配啊,这就是我们一次配置多个中间键啊,以及一次配置多个匹配的路由。当然匹配路由的时候啊,你也可以用通配符啊,这个和我们路由里边讲的是一样的啊啊,比如说由啊 啊 u u c 啊 u c r 表示什么呢?表示以以 u 开头,以 r 结尾的所有的路由都匹配当前中机键啊,那这时候你输入 u 字的时候,他照样可以匹配这个 u 字的中机键,就这个意思啊 啊,那这样的话,我们这个终极界基本就给大家讲完了啊。呃,这里边多个终极界,刚才已经讲了,这里边还有函数式终极界啊,函数式终极界的话,你就给他返回一个方法啊,这个和 express 里边非常相似啊,这个我们就不给大家演示了 啊,在我们 next gs 里面用的比较多的就是这种方式啊,当然这种方式的终极键也可以啊,比如说我们用的这个第三方的这个。呃, express 的终极键,有些可能就是这样的终极键啊啊,那这时候的话,你直接啊,直接配置啊,和我们刚才是一样的,也就是比如说啊,这里边,你看啊,我们写一下啊,这叫函数式终极键啊, 函数是终极界。呃,函数是终极界,比如说在哪写呢?那就在最上边这啊,最上边这啊,写一个,写个这样的终极界,对吧?写个这样的终极界,然后接下来的话,我们在这里边同样的可以应用 这个终极键啊,这就叫函数式终极键啊。然后接下来运行一下,走一下,看一下 request 是不是打印了啊?这叫函数式终极键啊,就是这个这叫函数式终极键。 你也可以把它单独撤离出去啊,中结界啊,单独撤离出去也可以啊,这叫啊函数是终结界。 ok, 然后接下来的话,我们再看一下这个全局中介介啊,就是这个的用法和我们这个类类型的中介介用法都是一样的啊,然后接下来再看一个叫 全局终结界啊。全局终结界在哪用的?全局终结界就是在我们的这个呃,根啊根里边用,也就入口里边用,你看一下这里边 apb 点柚子,这就叫全局终结界啊,全局终结界。那接下来的话,我们给大家演示一下这个全局 据中介介的用法啊,首先把所有的都关闭,关闭以后啊,然后接下来的话,我们把刚才的那个方法中介介给他抽离出去啊,也就是这个中介介给他抽离出去啊。我们在这个 made well 里边新建一个文件,然后这里边的话叫,呃,啷个点 made well 啊?点一个 ts 啊,然后接下来的话,把这里边这个代码给他拿过来啊,拿过来啊,拿过来,放在这里边啊,放在这里边, 然后接下来的话在这里边引入啊,当然这里边的话需要暴露啊,暴露的话通过这个 e x p o r t 啊 x 炮的进行暴露,把这个方法暴露一下啊,这里边格式化一下这个文档啊,格式化后没效果啊。 ok, 稍等一下,我们把它整理一下啊,这就是一个函数式终极键,然后接下来的话,我们在这里一边引入这个函数式终极键啊。呃,那 这里边的话应该叫 made well, 下边的 longer 啊, longer 点 made well, 然后这里边的话引入他啊,引入他, ok, 引入以后,那这样的话啊,你在下边使用是不也是一样用啊?这个没问题啊,然后接下来的话,你运行一下,看一下到底对不对啊?走一下 函数是终结界,没问题啊,没问题以后,然后接下来我们给大家看一下这个全局终结界啊,那全局终结界的话啊,就是直接在我们这个魅点 ts 里边来配置的,首先的话我们需要引入这个终结界 啊,引入的时候要注意啊,这个全局中介介的话啊啊,他没法引入我们这个类类型中介介,就是现在的话,如果你引入这样的中介介,他会报错的。比如说这里边我们使用一下这个, 呃,叫什么呢?使用一下这个 in int 啊, int 这个终极键,那我们给大家看一下到底对不对啊?比如说这里边我们引入它,引入它以后,然后接下来的话在下边啊, 通过 app 点儿柚子来配置这个中机械啊。 app 点儿柚子配置当前这个中机械 啊,那配置以后,然后接下来运行一下啊,我们看一下这里边他会不会报错啊?走一下,报错了,对吧?报错了,你看一下这边报错了。当然如果你这边加括号,那同样的他这里边啊,他这边也会报错,或者有些同学说,哎,这里边加个六,那这时候我们看一下会不会报错。走一下 啊,走一下,你发现这里边是不是照样的报错啊?所以啊,就是我们这个全举终极界的话啊,这里边没法引入这个类类性的终极界。那这时候的话我们可以引入什么呢?引入这个方法终极界啊,比如说我们把刚才的这个,呃,这个 longer 啊, longer 给它引入啊,再全局给它引入。引入以后,然后接下来的话,我们在这里一边配置一下 啊,那就是叫 app, 叫柚子, app, 叫柚子啊,柚子。然后接下来把我们这个中间接给他放进去,那这时候的话,我们看一下他这里边会不会报错啊?会不会报错 啊?保存以后,然后重新运行一下啊,看一下啊,我们刷新一下,你发现函数是终极界,对吧?然后这里边又打印出函数是终极界 啊,这就是这就是我们给大家讲的这个全局终结界啊,也就是全局终结界的话,这里边啊只能引入函数函数式终结界啊, 结局中介介,只能引入啊,函数式啊,函数式中介介啊,这里边要注意一下,然后在这里边的话啊,在我们这个呃根模块里边,你既可以配置函数式中介介,也可以配置啊,类类型中介介啊,都 是可以的。行,那这一家的话,我们就给大家呃,讲到这啊,这一家就主要给大家讲了 nest g s 中的中介件啊,那这里边常见的用法我们都给大家讲了啊, 啊,有这个中介界的一个创建啊,然后中介界的一个配置啊,中介界的这个配置的话啊,大家这个代码可以不用去记他啊,但是你得会去配置他啊,得会去配置他啊, 啊,得知道这里边这个是什么意思,以及多个中机键如何配置,然后不同路由的这个中机键如何去配置啊,这个得会灵活的使用啊, 然后又给大家讲了一个叫啊方法终极界啊,啊,也叫函数式终极界,函数式终极界的话啊,和我们这个 express 里边的终极界非常相似啊,然后最后又给大家讲了这个叫什么呢?讲了一个全局终极界,全局终极界的话要 注意这里边只能引入函数式终结界啊,然后这里边的用法的话和这个 express 里边是一样的啊,那这一讲的话我们就给大家讲到这啊啊,我们这个 next g s 中的终结界啊,基本就给大家讲完了啊,那这一讲的话我们就讲到这啊。


各位同学大家好,这里是由 it 影点 com 为大家提供的 nest g s 系列教程,我是独角老师大地。那这样的话,我们首先给大家介绍一下这个 nest g s, 然后给大家讲解一下这个 nest g s 的环境搭建以及创建运行这个 nest g s 的项目。 那首先的话,我们看一下这个 next g s 的一个简单介绍。 next g s 是一个接近式的 note g s 框架,可以在 type script 和 javascript 之上构建高效可伸缩的企业及服务端应用程序。 next g s 是基于这个 type script 编写的,并且结合了这个 o p f p 啊 f r p 等相关设计理念啊,在设计上很多灵感来自于这个 angler 啊,那谷歌的 angler 很多模式又来自于这个 java 中的 speed 框架啊,比如 比如说依赖注入面线切灭编程等。所以我们可以认为 nest 是 note g s 版本的这个 spring 框架啊。 nest 框架底层 http 平台默认是基于这个 express 实现的,所以啊,我们无需担心第三方库的缺失, nest 只在成为一个与平台无关的框架啊,也就是从技术上讲啊, nest 可以结合任意的 note g s h t t p 框架 啊。那在 net g s 里边默认支持了这个 express 以及 firstly 啊。当然,你也可以选择适合你的这个 not g s h d t p 框架来结合我们这个 net g s 来开发应用程序啊。 那这个 nest g s 的核心思想就是提供了一个层与层之间的偶合度极小,抽象化极高的一个框架体系啊。目前的话,这个 nest gs 在行业内啊,受到了很高的关注度啊,所以我们有必要学习一下,那下边的话啊,这里边我们给大家列举了他的官网啊,以及啊中文的一个翻译网站,以及 github 上边这个地址啊 啊,这就是这个 nest g s 的一个简单介绍啊,那这里边我们要知道的就是这个 nest g s 它是基于这个 types trip 编写的啊啊,它是一种面向对向的一种编程方式, 然后它很多灵感来自于这个 angler 啊,所以这个 nest 里边的语法很多和 angler 里边非常相似啊。 然后再一个要知道就是 nest 它是一个与平台无关的框架啊,但是他默认啊,支持了这个 express 以及 firstly 啊,所以我们无需担心他第三方库的缺失啊,也就是啊,很多功能的话,我们直接可以用 express 里边的模 模块来实现啊,这就是 nest g s 的简单介绍。那接下来的话,我们看一下这个 nest g s 和 egg g s 的一些区别啊,那这个 nest g s 和 egg g s 都是比较优秀的。这个 note g s 框架啊,都是为企业级应用而生 啊,这个 x g s 啊,它是基于这个 coa next g s 默认是基于这个 express 啊,当然 next 也可以基于其他框架。 那这个 x 的文档的话啊,相比这个 nest g s 要优秀一些,因为 x 的话是我们国内啊开发的。这个 nest g s 的话,它是老外开发的啊,所以这个文档以及资源的话啊,这个 x 更优秀一些。 那关于这个约定方面的话啊,这个 x g s 其实比这个 next g s 也标准一些啊,我们知道这个 express 科瓦是 纳子 gs 社区啊,用的比较广泛的框架啊,简单并且容易扩展,非常适合个人项目啊,但是框架本身缺少这个约定标准的 mvc 啊,会有千奇百怪的写法 啊,所以的话啊啊,我们要学一下这个 egg g s 或者 nest g g s 啊,它都是按照约定进行开发的,但是啊,这个 e g g s 的话,相比这个 nest g s 这个约定更标准一些啊,更规范一些。 然后啊,这个面向对象方面的话啊,这个 next g s 要优于这个 egg g s 啊,因为我们知道 next g s 它是基于这个 text script 啊,并且啊,它啊很多东西是参考这个 angler 开发的啊, 如果你会这个 anger 或者 java 的话,学习这个 net g s 是非常容易的啊,下面的话,我们也列举了官方文档上给我们提供的 egg g s 特性以及 nest g s 的特性,那这个的话,我们就不读了啊,这就是这个啊, egg g s 以及 nest g s 的一些啊区别啊,这里边我们做了一些简单的对比啊。 ok, 那接下来的话,我们再给大家看一下 学习这个 nest g s 必备的基础啊,我们知道这个 nest g s 它是基于这个 type strip 以及 express 的啊,所以我们首先必须要有这个 not g s type strip express 基础啊,你才能学习我们这个 nest g s 啊,如果大家没有这个基础的话,你首先学习一下我们前边录制的这个 type script 啊,这个入门实战,然后这个免费教程以及这个 not g s express 啊,基础的免费教程啊,你要会这些东西,你才能学会我们这个 next g s。 ok, 那这个介绍 以及啊,学习 next gs 必备基础了解以后,那接下来的话,我们给大家看一下这个 next gs 的环境搭建以及创建运行这个 next gs 的项目。 那 nest gs 的话,它是 note gs 框架啊,所以我们在搭建 nest gs 环境之前,必须在电脑上安装 notegs 环境啊,推荐安装 notegs 最新稳定版本啊,也就是回头你安装一下这个版本啊,这个就是最新稳定版本。 ok, note gs 环境搭建成功以后,然后接下来的话啊,我们就可以用命令行工具来安装 nest c l l, 也就是 nest 的一个开发环境。 怎么安装呢啊?通过 n p m i g g 然后 at next g s 斜杠 c l i 就可以安装这个 next g s 环境啊,当然也可以通 通过 cnpm, 也可以通过样来安装我们这个 nest gs 的这个环境啊。那接下来的话,我们给大家演示一下啊,首先的话,打开我们这个命令行工具啊,在我们这个 windows 里边和麦克电脑里边都是一样的啊, 然后接下来的话啊,输入这个命令来安装我们这个啊。 net gs 的这个 c l i 啊,也叫脚手架工具啊啊,这里边的话,我们就用这个 c n p m 来安装,当然你也可以通过样来安装啊,那如果用 n p m 的话,可能会失败啊,所以我们推荐大家使用后边这两种方式 啊, ok, 我们安装一下,那这个 next gs c l i 就是我们这个 next g s 的这个环境啊,也就是它的一个脚手架工具。 ok, 看一下啊,安装完成了,那这个 c l i 安装完成以后,接下来我们就可以通过 next 命令 来创建我们这个项目啊,接下来的话,比如说我们想在地盘的这个 nest 目录里边来创建一个 nest demo 零幺的项目,那这时候的话,我们首先得进入这个地盘的 nest 目录啊,那这时候的话,我们就在这敲入这个 d 冒号啊,然后接下来 cd 到这个 nest 啊, cd 到 nest cd 进去以后,然后接下来的话,我们就可以在这里边来创建项目啊,那创建项目的话啊,通过 nest new 啊,来创建我们这个项目,那这里边的话我们输入 nest demo 零幺,然后回车 啊,回车以后啊,他这里边让我们选择安装依赖的这个,呃,叫工具啊,那这里边的话啊,可以是 npm 也可以是样啊,因为我们这个电脑上已经安装过这个样了啊,所以这里边的话我们就选择样 npm 的话啊,可能会失败,所以这里边 话我们推荐大家使用这个样啊,如果大家电脑上没有安装这个样的话啊,你可以通过 n p m 然后这里边来个 igar j, 然后这里边来个样啊,就可以安装这个样啊,也可以通过 c n p m 来安装这个样啊。 ok 啊,那这样的话我们这个项目就创建成功了啊,并且这里边这个依赖也安装成功了, 安装成功以后,然后接下来的话,我们 cd 到这个项目里边啊,你看一下它下边都有提示啊, cd 到这个 nest demo 零幺里边,然后运行这个叫呃样啊, raw start 或者 n p m raw 一个 start 就可以运行我们这个项目啊, s t a r t 啊,那接下来我们运行一下啊, y a r n 一二 raw s t a r t 啊 啊,刚才这个命令敲错了, ok, 那这样的话啊,他就会啊,把我们这个呃 nest 的项目启动啊,然后接下来的话,我们 在浏览器里边输入 local house 的冒号三千,就可以打开我们这个项目啊, local house 的冒号三千,看一下这里边输出一个啊, hollow word 对吧? 啊,这就是我们这个呃 nest 的一个项目就创建好了。创建好以后,然后接下来的话,我们导入到这个 vs code 里边啊,给大家分析一下这个 nest 的一个目录结构啊。啊,找到我们刚才创建的这个 nest demo 零幺, 然后把它打开啊,打开以后我们给大家看一下这里边的这个目录啊, note modules 的话,就是放我们这个模块的地方啊,然后接下来的话,下边有一个叫 package 点 jason 啊,这里边的话主要是 配置我们这个项目的版本号,项目名称啊,以及项目的一些元素剂啊,以及我们这个项目所需要的一些依赖啊,这个文件必须得知道。然后再接下来啊,这里边 还有一些,呃,还有一些 get 忽略的文件儿,还有我们这个 next c l i 的配置文件儿,以及一些其他的配置文件儿啊,这些你可以不用管,也就是这里边儿这个配置文件儿啊,我们要关注的就是这里边儿这个叫 package 这点儿 dancer 啊,其他的配置文件儿都可以不用管。 然后这里边还有两个文件夹啊,一个叫 src, 一个叫 test, test 的话你也可以不用管,它是我们测试相关的目录啊,这个 src 的话就是我们开发项目的目录啊, 这边的话默认有这么多文件啊,魅点 g s 的话就是我们这个 nes 的一个入口文件啊,然后再接下来的话,在呃魅点 g s 里边加载了这个 a p p model 啊, a p p model 的话是我们一个更模块,然后在这个更模块里边的话引入了这个控制器以及这个服务啊,更模块的话告诉这个 nest gs 如何组装这个应用啊,然后接下来我们再留 浏览器里边输入 local house 的三千,那其实访问的是谁呢?访问的是这个控制器里边的这个方法,然后在这个方法里边他又调用了服务里边的这个方法啊,所以这里边返回了一个 hello word 啊,然后这里边我们也可以改一下,改成一个叫你好 啊,你好啊, nest g s ok, 然后接下来运行一下啊,当然这样改完以后啊,他这个 nest 的程序并不会立马生效啊, 如果我们想要他改完立马生效的话,那这时候我们需要运行这个命令啊,看一下,叫 n p m 而撞 start, 冒号 d v, 那这样的话你 你改完代码以后他就会立马生效啊,那这时候我们再重新运行一下,叫 yard run 什么呢? yard run start, 然后这里边来个 d v 或者 n p m round start 啊,冒号 d v 都是可以的啊。 啊,那这样的话我们这个项目照样运行起来了啊,你好,奈斯特 gs, 然后这时候的话啊,你改一下这里边这个代码啊,改一下代码保存以后,那这时候他就会热加载啊,热加载看一下, 那这样的话,我们改完这个代码以后啊,就不需要重新运行我们这个项目了啊,你直接在这保存,然后接下来的话我们就可以看效果了啊,这就是我们刚才给大家讲的两个命令, 那这些命令的话,其实都是在我们这个 package 点 jason 里边配置的,你看一下啊, npm run star, 它就是执行的这个命令啊, n p m run 啊,这个 start 第一位执行的就是这个命令啊,当然 yeah roll start 和亚 roll start 第一位都是一个意思啊,就是我们刚才在这里边儿啊,是不是执行了一个叫 yeah run 啊, start 第一位啊,你也可以执行这个叫 n p m 啊, star 是第一位啊,这个都是一个意思啊啊,同样的可以运行啊,看一下是不是也可以运行我们这个项目啊, 这就是给大家讲的如何搭建 nest g s 环境以及创建 nest g s 的项目啊,那这个 nest g s 环境的话,我们只需要搭建一次,也就是你这个命令或者这个命令执行以后,后期的话,我们直接可以通过 nest 六来创建我们这个项目了啊。 next 能有创建项目的时候,然后接下来的话,我们选择一下安装这个模块的这个工具啊,选择完成以后他就会下载依赖,下载完成以后,那这时候的话我们就可以运行这个项目了啊,运行的话,我们 cd 到这个目录里边运行这个 eroster 冒号 dv 或者叫 n p m roll start dv 啊,都可以运行我们这个项目啊,也就是刚才给大家讲的这几个命令啊, n p m 或者啊鸭 roll, 但是第一位都是可以的啊。 ok, 然后我们又简单的给大家介绍了一下我们这个目录结构啊,我们要啊关注的目录就是这个 src 目录, src 目录就是我们这个开发目录啊,这里边的话啊,刚创建好的话,有这么几个文件 啊,有这个 mate gs, mate gs 的话是我们这个入口啊,在这个 mate gs 里边我们可以配置这个全局的中介件啊,啊,以及可以做一些啊配置平台的操作啊,比如说这里边我们可以加载这个 express 平台, 然后再接下来的话啊,在这个 a p p 里边加载了这个更模块啊,看一下在 a p b 里边加载了更模块,然后在更模块里边的话,定义了我们这个 a p p ctrl 以及 a p b swats 啊,如果你学过这个 angler 的话,这个代码啊和 angler 里边非常非常相似啊。然后接下来的话啊,如果 我们访问什么呢?如果我们访问一个叫 local host 三千啊,访问这个地址的话,它其实实际默认加载的是谁呢?实际默认加载的是不就是这个 app controller 里边对应的这个方法啊?你看一下我们刚才运行的时候,实际它加载的是这个 啊,那这里边的话啊,虽然他没有配置路由,但是他这里边会给我们自动适配路由啊,比如说你看一下我在这写个 get news 啊, get news, 然后在这里边的话就写一个叫 get news 啊,这个表示路由啊,你上边写个 news, 然后下边这个方法的话,你可以随意写啊,随意写,比如说就叫 news, 然后接下来的话,这里边我返回一个支付串啊,啊,支付串叫这是啊,这是 nest 里面自定义的方法啊,也叫页面啊, 也叫路由, ok, 也叫路由,那这时候我们给大家运行一下,看一下啊,啊,保存,保存以后,然后接下来的话,我们要啊调用这个方法的话,我们直接在这里边输入啊,对应的这个路由,也就是 news 啊, news, 那这里边的话,我们刚才结束了啊,我们再重新预习一下啊,预习起来以后你看一下啊,输入 locals 三七下边 news, 那这样的话是不是就加载了这个控制器里边对应的这个方法? ok, 那同理啊,同理应该能猜到,对吧?你可以继续配置我们这个路由啊,比如说这里边再来个,呃,叫 product, p r o d o c t 啊 product, 然后这里边叫 get product, 注意啊,上面这个的话是装饰器啊,如果大家不懂这个装饰器什么意思,回头看一下我们前边讲的这个 type script 这个代码啊,啊,讲一下啊, 看一下 typescrip 的这个教程啊,那这时候我们再预警一下这里边啊,输 product, 对吧? product, 它是不是就可以加载这 product? ok, 然后在这个 ctrl 里边的话,它又注入了这个服务啊, 也就是你看我们默认访问的时候,他其实调用的是什么呢?是不调用的是这个 swipes 里边这个,呃, get hello, 这个这个方法,那这里边我们也可以配置其他的方法啊,比如说叫 get product 啊, p r o d u c t 啊,然后这里边啊,他返回的类型是这个 stream 啊,这就是 type strip 的语法。然后这里边的话,我们必须得返回一个 stream 啊,返回 stream 啊,然后这里边写一个叫啊,商品啊,商品啊,服务,商品服务。 ok, 然后接下来的话,同样的我们在这里边可以调用我们刚才定义的这个方法啊,叫 res 点一个 a p p swift 啊, a p p swift 是不是在我们这里边引入了,在控制器里边引入并且注入了,然后调用里边的这个叫 get product。 ok, 那这时候我们在访问这个 product 路由的时候,他应该加载什么,是吧?加载商品服务啊。 ok, 啊,这就是啊,我们默认创建好项目的一个架构啊,他就是这样一个架构,以及他如何运行的啊?我们访问访问这个路由的时候啊,访问这个,呃,这个路由的时候啊,他首先加载的是控制器啊,以及访问这个页面,首先加载控制器,然后控制器里边又去调用了我们对应的这个服务啊。 ok, 这就是一个基本结构。当然啊,呃,正常的这个 next 项目的话啊,它是由模块组成的,也就是我们啊访问这个页面的时候啊,访问这个啊, local house 的冒号三七的时候,它首先啊 进入这个魅点 gs, 然后魅点 gs 的话这里边加载这个歌模块,然后歌模块里边的话他又去调用其他的模块啊,然后在其他的模块里边他又有什么呢?又有对应的这个啊,控制器以及对应的这个服务啊,也就是在其他的模块里边啊,他又有, 呃,又有我们刚才写的这些东西啊,复制一下,稍等一下,复制一下,看能不能复制过来啊?又有这些东西,就这个意思啊,就这个意思 啊,后边这个啊才是一个,呃,比较完整的啊。 next gs 一个架构,前边的话就是我们刚创建好的这个架构啊,大家首先了解一下, 然后后边的话我们再一点点给大家讲这个控制器,讲服务以及讲对应的这个模块啊。那这一点的话我们就给大家先讲到这里啊,这一点的话,首先给大家介绍了一下这个 nice gs 啊, 然后给大家讲了这个环境搭建以及创建运行 nest gs 项目啊,最后又给大家介绍了一下我们这个 nest gs 里边的这些文件啊,以及他的一个执行流程啊,执行流程啊,以及 nest 项目的一个基本结构啊,那这讲的话我们就讲到这啊。