00:00
我们继续来做第五步,将我们以前收集到的所有SQ数据的模型我们发送给ES进行保存,保存完了呢,我们的商品上架功能就结束了,保存了的这些商品我们就可以在ES中进行检索了。当然这个保存功能呢,我们必须写在我们的鼓励mail search服务里边,它呢最终是跟ES进行交互,完成我们的保存、检索等各种功能。那么先来假设我拥有呢第一个功能来写一个ctrler。好,我们呢就放在controller包下,我们呢,将所有跟ES保存有关的,我们都放在我们这个as save我们的这个controller旗下,好。我们先来标注,我们这是一个rest controller,我们能返回接数据的。接下来我们的要求就是我们检索服务里边的所有请求都以search开头,那我们来写上request monkey,好,我们的基准路径就是我们的search,然后我们要做的第一个功能是来保存,也就是我们上架商品,那上架商品呢,我们来写一个public啊,最终呢,这个上架会有成功失败,我们就叫product status up,我们把它的状态改为这个上架的,那么想要上架的所有商品,我们是一个集合,这个集合呢是ES,我们的SQ的这个model,我们是SQES的model。
01:27
我们来写一个SQ ES models好。而且呢,我们一定要使用request和body这个注解,意思呢,请求体里边会有这么一个接省数据给我们转换成这个样子,那既然是请求体里有数据,那我们就要写一个post monkey来处理我们这个请求,那么这块的请求呢,由于我们这是save controltr都是跟我们ES里边保存有关的,首先保存我们的product,我们的商品数据,那保存完了,我们假设return一个R点一个OK,那么呢,就希望有一个服务能来处理它,我们先来写一个服务,我们service呢,先来写接口,我们这个就叫product save service,我们要把它放在我们的service包下好。
02:12
把这个呢,我们创建出来,我们最终希望这个controller里边能调用我们product save service,我们product save service把它自动注入,然后呢,它里边呢有一个方法,第一个product status up来完成商品上架功能,要上架的所有商品就是这一数据,我们来创建出这个方法。我们再来为它添上这个实现,那要实现我们先来写一个实现类,好来创建一个class,我们放在employment包下,我们就叫我们的这个product save service的实现,Product save service的employment好,我们的实现内。我们创建出来这个实现内了,来实现我们的product save service,我们把它加到容器中,At一个service,我们来添加上我们这个接口的实现方法,好,这是我们的第一个方法来上架,也就是保存我们所有的SQ数据,而这些数据呢,我们要操作ES,都要使用我们elastic的这个high level client elastic,我们的整个high level client,我们来看一下,我们当时呢,在这配置了,我们给容器中会注入一个rest,对,它是使用rest方式来进行操作的,们来到的实现类里边rest我们的high level client啊,它用来操作ES,那这一块的操作呢,那就是将数据直接保存到ES中,这数据呢,我们都组装好了,只需要将它直接存进去就行了,而保存之前我们要做的第一步,第一步我们先给ES中,ES中来建立一个索引中建立。
03:56
中来建立索引,那假设呢,有一个索引叫product,而且由于这个索引名我们经常要用,所以呢,我们也应该抽取为一个常量,那检索服务的常量呢,我们就放在它自己的里边,那constant好。
04:12
里边呢,有一个ES的常量,我们来放到这,那常量里边的第一个常量我们来写成public static final string类型的,我们商品的所有索引,我们叫product。Index,我们把这个索引呢,我们放在这,它在ES中的索引我们就叫product。这是我们。SKU数据在ES中的索引,好,我们接下来在这来尝试保存,首先我们要给ES中建立这个索引,而且呢,要建立好映射关系,建立好映射关系,映射映射关系,这个映射关系呢,我们之前给大家已经分析了,那就是这个映射关系,那么先呢,直接在ES里边操作,我点一个运行,那他呢,把这个映映射关系先建立起来,那好,这个映射关系呢,那为了方便我们CTRLC,我们直接给大家保存在当前项目的某一个里边,我们就叫product map和product。
05:14
我们的map点一个,我们来写成一个文本,好把这个呢放在这,那么第一步先来建立这个索引和映射关系,我们操作K呢已经建立好了,下来第二步给这个索引里边保存数据,给ES中我们保存这些数据,而且呢,由于我们这个保存众多,如果我们调用它的这个客户端一个一个进行保存,保存呢是我们这个index操作,那这样呢太慢了,所以呢,我们这里边有一个叫bug,这个就是我们的批量操作,我们就来使用批量操作来进行保存,批量操作里边呢,要传两个参数,我们来复制过来,来CTRLC好来复制过来,我们现在要批量保存所有的SQ数据,第一个叫b request,第二个是request option,那request option我们统一的设置都在conf里边,好,我们先来写一个b request和我们的request option,我们直接用config里边第一个common options,好,我们用它。
06:13
然后我们的b request,那既然要用,我们就先构造一个这个request来拗一个直接叫。Request,我们把它呢创建出来。那这个request创建出来以后,我们再来如何构造批量操作呢?我们可以看一下在这个b request里边,它呢有一个方法叫and and里边呢能添加一个操作,比如我们的保存就是一个index request,就是一个索引操作,所以呢,我们只需要循环去来给里边填数据,好我们在这里边来调用for each,我们直接进行一个增强for的便利,我们每一栋便利呢,都应该是一个索引操作,所以呢,我直接来new一个index request,我们现在要保存一个数据进去,好我们把这个request呢创建好,这个创建好以后,我们只需要给B里边添上点一个and,我们把这个index request给里边一放,那我们这个保存就成了。但是在构造这个index request的时候,我们可以指定一些它的基本信息数据。
07:21
首先我们来指定index,我们要给哪里边存我们的这个索引,好,那先在这儿来指定,我们在这构造器的时候就来传上索引,所以呢,都在ES count里边我们抽取的常量。我们给ES里边按照这个索引来存,然后存了以后呢,我们每一条数据都有一个唯一ID,所以呢,我可以来指定ID,这ID是什么?那就是当前商品的SQID,因为这个SID在系统里边是唯一的,我们来进行保存的啊,而且呢,这个ID它要string类型的,那我们就可以直接把它变为图string,那ID完了以后呢,那就是我们的这个真正数据是什么?数据内容我们使用source,而source里边我们最简单的方式就是传我们的杰森字符串,并且内容类型指定为杰森,所以我们先用杰森工具,杰森第二图,一个杰森string,我们将我们当前的这个要给ES中保存的对象model来转成一个杰森字符串,把这个字符串放到source里边,然后我们来指定内容类型。
08:24
我们是X content type,我们叫杰森好,这样呢,我们整个request请求就告诉构造好了,我们这是我们的构造,我们的保存请求,我们有很多保存请求,我们都放到这个bucket request里边,然后呢统一进行批量操作,那操作完了以后呢,我们接下来就要TRY看尺,由于这个网络呢,可能有异常,那么就不查看尺了,直接有异常抛异常好。把这个异常呢,我们来抛出去。我们给接口和实现类呢,我们来都填上这个异常,那至此我们这个方法只要调用了,我们就会把所有的批量操作去来执行,那执行完了以后,我们会有一个bucket的整个返回,因为批量操作的返回,我们说每一条数据都是独立统计的,所以我们在这还能统计一下到底有没有哪些商品上架失败了,如果有失败呢,我们还可以继续重新给它处理一下。
09:17
所以呢,我们在这一块也可以给他有返回结果,比如B里边有get it能拿到每一个的数据的响应结果,包括最快的判断,有一个叫是否拥有错误直接返回我们的这个触破,如我们还想感知这个错误,那我们可以就详细的在这再来做一个错误处理,来写上todo,如果批量错误,批量错误我们还在这要处理错误。当然这一块呢,我们只是拿日志,我们可以来记录一下我们在这。写一个cell forj,我们使用log来记录一下log。A。我们就写一个商品上架错误,包括是哪些商品上架出错了呢?我们也可以拿到这些所有出错的信息,比如我们在B里边点一个get itto,我们来看每一个批量,他们最终处理结果都是什么样的,我们可以来stream,先把它们来映射过来,点一个map。
10:18
我们来拿到每一个的处理结果来进行处理,在这个item里边我们可以拿到ID,这个ID相当于当前数据的ID,因为我们保存的时候,我们指定的ID,包括呢,它是哪个索引操作出错了,那都可以拿到这些信息,那比如我们就把所有的ID就收集过来,那把这些ID收集过来呢,我们来日志记录一下,比如return,那最终把他们点collect to list。把他们呢,我们在日志里边来记录一下商品上架错误,哪些商品我们直接给这来一打印,好,我们先这么来处理,我们放在这。当然这个成功和错误其实我们还是希望外界能感知到的,所以呢,我们把这个方法的签名我们来改成布尔,我们来点进它的实现,如果出现了错误,那么就直接来返回这个波尔类型的错误,我们就来return我们的波尔,而且呢,如果真正的这些商品上架出现了错误,其实呢,相当于我们PU下有些商品没有上架完成,那么除了记录错误,我们可能还得人工再来检查一下有哪些商品没有上架完成,或者呢,我们自动再来重试,多上架几次,一般我们都不会出现我们这个批量有问题的。
11:36
情况,除非我们的ES出现了问题,或者我们给ES提交的数据格式出现了和映射不符的等各种情况,好我们放在这,然后呢,我们的这个service接口我们就写完了,我们在这的实线我们也写好了,那这一块它说注入这个画一个红波浪线,大家就不要管了,因为我们给容器中已经at b已经注入了它这块波浪线太灵敏了,这个提示呢,我们不用管,我们继续来到我们的ctrler,那这个呢就会调用方法来进行上架,而这个方法呢也会抛异常,所以我们来穿看尺一下。
12:09
如果有异常,说明我们上架失败,失败了,我们返回的这个R跟成功返回的R是不一样的。那失败呢,我们就直接返回R,我们来写一个return r DR error,那这个失败的错误码以及错误消息,我们可以在。com里边,我们将所有的这些业务错误码我们都放在了common的这个错误代码里边,好,我们再来添加一个错误码,比如我们这个错误码呢,还是我们一一。我们商品功能出现了问题,那么就叫product up。Exception,比如说我们这个商品上架出现了错误,那么商品呢,是一一开头,一一再加上我们的三位标识,比如000,这是我们这个商品上架异常。
13:00
好,我们在这个ctrller呢,在这来处理我们的错误状态码,那就是使用b code枚举类点一个商品上架异常它的get code,然后呢,错误消息,那就是B子code点一个商品上架异常的错误消息单。只要我们系统发生了错误,我们都应该经常用日志来进行记录。好,我们在这来写一下cell间。我们使用log.error我们的elastic save的这个CTRL商品上架错误。那这个错误原因呢,我们可以来在这也打印一下,我们直接打印整个E对象,否则呢,返回成功,而且其实成功不成功们这主要有一个布尔的返回能出现这种错误,那可能就是ES客户端连不上了,而真正的布尔返回的false,那就说明我们某一个SQ数据真的有问题了,所以我们把这个布呢,我来提出来,它默认呢,我们来给一个叫force。
14:06
然后真正的值,那就是上架结束以后的值,我们在这儿需要做一个判断,如果是成功的,我们就返回OK,失败的我们就返回失败,如果是处,那么就来return下边的这个OK,好,我们放在这。这是我们这个return OK。那否则呢,我们就应该return的是失败。好,我们来加上。Else,我们就给他return。二。失败。那这个失败的原因跟他的这一块我们都一样。我们把这个呢复制过来。CTRLC我来放到这。走。那这就是我们商品的上架的远程接口,那这个远程接口写好了,那么商品服务需要来调用它,那调用呢,我们先把这个方法签名我来复制过来,好来到我们的商品服务,主要是我们product里边来找control e,我们来看我们以前的po info的这个service好。
15:13
我们最终把这个数据来发出去,我们在这就来写一个远程接口,我们在缝里边,我们来写一个叫。Search份service,那跟检索服务有关的所有远程接口我们都放在这来写一个an phone client,它是一个份客户端,分客户端,注意这个一定要是接口interface,我们想要调用的是远程的鼓励ma search这个服务,然后呢,我们想要调用的功能,我们把这个功能呢来复制过来,CTRLC。我们直接放到这儿走,然后呢,我们整个完整的路径,我们一定要拿过来,我们叫search save,好把它放过来,那么这个远程接口我们就声明好了,接下来来到我们的这个employment里边,我们来注入这个远程接口,我们就叫search份service,好们search份service来autowa进行自动注入,好我们把这个service呢来放到这,这个service点一个。
16:15
有一个方法叫product status up,我们把所有的这个接口数据,我们把这个要传出去的数据我们拿过来,我们就叫up products,好,我们把它复制过来,我们放到这,这是我们所有要上架的数据,整个远程调用完以后会返回R对象,那这个R对象到底成不成功,我们只需要get它的code就行了,If,如果它的这个code等等零,那说明远程调用成功了。因为我们成功的状态码是零,这是远程调用成功,那否则远程就调用失败了。那这个远程调用失败,那说明我们的上架有问题。远程调用失败,那失败呢,说明我们这次上架操作就出现问题了,但是成功一旦成功,那我们还要做一步,那to渡们的第六步,那成功了,我们一定要改掉我们当前上架的这个商品PU,那PU呢,商品有一个发布状态,状态呢要改为我们的已上架,所以我们来修改我们当前s puu的状态,我们将s pou旗下的所有SQ我们都上架了,我们就要修改它的状态。
17:29
那这个状态呢,我们就来调用我们当前this this呢,那就是我们当前的s po英f service,我们来改po英的数据,我们可以拿到它的base member,好来修改状态而已,好base member呢,来一个方法,我们比如就叫update PU status。我来给你传两个参数,第一个是s pou的ID和它的最新状态,那么先来获取到的ids po的ID是方法一传参刚进来的啊,还有它目前的状态,那在我们页面呢,我们s puu有这么三个状态,新建、上架和下架,这个状态呢,应该是作为一个枚举类存在的,所以我们最好呢,需要在。com里边来写我们的这些常量枚举类,比如商品的这个枚举类里边有基本属性,销售属性,好,我们再来写一个商品的状态,Status的枚举。
18:23
那么叫status的枚举,Status枚举的第一个叫new product new po,那就是我们的新建状态,它是零号的,那默认呢都是新建,把这一块呢,我们先来改过来,还有它的一号,那就是上架了,PU我们就叫up,我们这是一商品上架了,我们就叫商品上架,那还有我们的二号状态,是商品的下架,好,我们把它复制过来。我们的二号状态是商品下架。我们就叫po大。
19:00
那我们的这一块,那接下来就要保存的这个状态嘛,就应该是product它的这个constant里边的枚举状态,里边的商品上架的这个状态吗?点一个get code,好,那假设呢,Map有这么一个方法来给它创建出这个方法。这个方法呢,是来修改我们的状态,它有多个参数,一定要先要生成参数的签名,那先来生成per generate per,给每一个参数指定好名字,我们再来在map文件里边生成它的映射,那这个呢是一个更新操作,那我们更新的SQL语句我们就是这么来写的,我们叫update哪张表,那就这张表set,我们有一个叫publish status,我们的发布状态等于我们指定的值。但是条件呢,Well,我们的商品idd也等于我们指定的值,那除了改发布状态,其实我们还要改这个我们的商品的更新时间。
20:06
这个更新时间呢,我们就让它等于当前系统时间就行了,来用那这个函数。那这就是我们来修改我们po的发布状态,好把它复制过来,来到我们这一块,我们就要调用这个SQL语句。那这个语句里边,其中publish status,我们是要取出我们的这个status的code值,我们就来写井号大括号我们的code,那我们的ID,那就是井号大括号我们的SPID,那么更新的商品状态我们这个就写好了,我们CTRL按住我们这个调用它的service,那至此我们第六步做完以后,我们整个商品的上架我们就做完了。流程呢,稍微比较多,但即使我们写的这个商品上架,我们仍然有未来的一些问题还没有考虑到,比如我们给大家留在一个坑,我们放在这儿什么科呢?大家考虑一下,有一个叫重复调用的问题,那专业术语呢,我们就是接口密等性,我们后来会说大家先来考虑一下这个问题,为什么会有这个问题,因为我们上架服务是一个远程接口,这个远程接口调用失败了,我们会不会自动的重试再来调用一次,所以呢,我们就要牵扯到后来的一些重试机制等等,那我们把这些高级问题我们都留在后来再说,那基本功能呢,我们就写好了,下一节课呢,我们就做一个整体测试。
我来说两句