商城分析(如何编写“编辑”功能,让这个“编辑”功能一点进去有商品的回显,包括显示商品的SPU和商品的SKU)
我们点击编辑请求
可以看到浏览器返回一个什么值给我们了。我们先看看前端是怎么写的,打开网址看看前端页面
可以看到edit是一个编辑按钮,有个点击商品的点击事件,点击后是执行editGoods方法,这里说明一下就是editGoods就是一个编辑商品的方法,之前我们已经是写过这个方法了,然后props.item这个是一个自定义组件,因为props就是一个自定义组件的标识,也就是说你如果使用了props的话,就代表这个就是一个自定义组件,再加上一个类似于items一样的组件名,就是调用一个自定义组件。
可以看看整体的方法如上所示,props.item的方法都在上面写着呢,全部都是props.item方法,这些都是自定义组件,都是让后端进行接收的组件。我们如何知道它是由后端进行接收的呢?可以看到有个text-xs-center,这个就是标题的意思,有了这个标识,你就知道这些数值是标题的,就可以让后端进行接收。然而这些都是什么呢?这些都是一个个spu对象,我们怎么知道它是SPU对象呢?如下图所示,这些都是表示商品的基本参数,也就是说商品的分类,品牌,标题等等基本的信息,你也可以理解为一种商品无论什么颜色什么型号它都具备的这些信息就是spu,然而颜色不同,型号不同组成一个新的商品那就是sku。这也是spu和sku的理解方法。
我们跟着这个editGoods去找到它对应的方法,可以看到它的方法在这里,并且传入了一个oldGoods,因为它要传入旧的商品数据,然后进行修改里面操作的内容,可以看到它前面有个await,这个代表什么意思呢?
我们点击一下编辑这个按钮,没有任何反应,也没有弹东西出来。
当我们把await全部去掉,再去刷新浏览器并且点击编辑按钮
弹出了编辑窗口。我们前端页面工作的原理就是,如果你上一个程序出错误了,他还是会给你运行下一个程序的,保证窗口可以显示,但是如果你加上了await的话,那就是在前端页面中,你运行的程序出错了,那下面的方法就不会继续执行了,然而这个作用仅限于在同一个方法内进行作用的。而且控制弹窗弹出来的是show方法,上面两个方法出错,去掉await后下面的方法也是正常运行。
我们可以看到我们还没编写好后端页面,这个方法已经是出错了的,但是它还是会继续运行,因为我们去掉了await。
我们先去找找这个loadData,为什么要去找这个呢?因为这两个方法出错了,我们要编写对应的后端业务逻辑,并且加上await(对弹窗内容进行保障),才能执行下一步。也就是说只有这两个方法不出错,我们才可以进行下一步。
找到loadData,可以通过async看到这是一个同步的方法,也就是get到url后把数据进行同步。
可以看到,它这里有个加载地址,因为loadData方法里面就是get到这个url,而且它需要的是oldGoods的id也就是spu的id,为什么说是spu的id呢?因为这个是旧商品的id,在oldGoods列表当中的方法已经把这个id设定为spu的id了,然后最终它返回给spuDetail这个参数。
接下来我们就要去编写后端的方法,首先可以看到我们的注解GetMapping,这个地址该怎么获得呢?之前说过两种方法,一种是浏览器上获得,一种是前端页面获得。最后注意要有个占位符,为什么要加这个占位符呢?你可以去浏览器看看它的符号是/55,55是个比喻,真正的意思就是这个斜号,有这个斜号的话就代表要使用占位符。下面的方法当中我们一定要注意使用,ResponseEntity,返回值为什么是SpuDetail?
下面这个表是SpuDetail表,因为你一开始的商品信息是spu,这个商品的品牌跟分类是没有办法改了,但是商品的描述,商品规格参数这些是属于SpuDetail,也就是浏览器那个表单里面的第二步,第三步,而且你要看看前端那里编写的返回数据是spuDetail,你可以在上面的图片找找,所以这里我们要返回的是spuDetail。下次我们要做出判断,要返回什么类型的值的时候,要根据前端的情况来考虑。在上面这一张图片中,我们注意这个SpuDetail不是List列表,返回值只有一个SpuDetail,然后调用Service方法,自己编写一个Service执行业务逻辑,我们注意要截取占位符的方法PathVariable。在下面当中我们要做日常操作,也就是判断这个查询结果是否为空,为空的话要返回一个404错误。这里提一下为什么这些逻辑要在Goods类写呢?因为Goods类就是负责这个浏览器当前页面的信息方法页。
在这里我们需要用到mapper里面的哪个方法呢?为什么要用第一个呢?第一个是什么意思?第一个就是根据主键去查询他的结果,也就是你输入一个数据库里面的主键,他就会根据你当前数据表里面的主键去寻找结果,刚好我们这里spu的id就是一个主键,可以看看下面的数据库图片,
然后我们这个方法就搞定了。
我们再去写第二个方法,我们可以先去前端找找对应的方法参数是什么,可以看到下面这张图,他的地址还有他返回的参数是skus,为什么我们这里就要写skus的list呢?我们是如何知道他是一个list呢?你可以看看他的请求路径,已经有个list,虽然这个list只是个地址,但是也是已经提示了你,他这个返回的参数是一个list,我们上次编写sku,他是通过各种属性之间的两两组合,组合成一个新的商品,很多这样新的商品又组合成一个列表,为什么我们刚刚的spuDetail却不是list,因为他只是一条信息呀,只是我们根据主键去查询数据库里面的那条对应的信息。
然而这里,我们还能不能使用通过主键去查找数据信息呢?你可以看看下面数据库的信息,他的主键并不是spuId,而是id
虽然他的主键并不是spuId,但是他的数据库里面有spuId,而且你可以看看上图中如果是182的话将会返回多个信息,这就组成了一个List,所以我们可以通过查找spuId并且返回多个信息组成List。
这里的查询方法我们只用普通的select就可以了,然后去new一个Sku,然后把spuId传进去获得一个列表,这里不要搞混淆一个点,我们这里传进来的spuId只有一个,所以我们只可以传一个spuId进去,但是我们使用查询方法输入spuId到数据库返回对应的数据却是一个列表。
这里总结一下普通查询方法的思路,也就是你先new一个你要查询对象数据表对应的pojo,命名为record,然后传进id,最终使用Mapper里面的普通select方法返回一个列表。
我们如果直接return会有什么结果,我们来看看。
你可以看到这里少了库存。
因为我们SKU列表也是有个stock字段,你可以看到他每个商品对应的库存都是空的,他不会直接返回,每个商品的库存多少给你,这里需要我们一个个去给他配对库存。这是为什么呢?因为在SKU这张表里面,根本就没有库存信息,库存信息在另外一场数据表里面,所以我们要一个个用库存的mapper方法来匹配给每个sku的每条数据。
这里为什么要用到用主键来查询呢?
这是sku表对应的skuId
可以看到我们的库存表对应的主键就是sku_id,所以我们只要传入sku的id,就可以找到对应的库存信息。
所以这里就是我们把SKU的id传进去,然后最终用sku的stock这个方法把stock的库存信息传进去。最终返回skus出去就可以了。
最终结果。
这里总结一下。该怎么去完成这个商品编辑功能呢?首先我们要看前端写的什么东西,哪一个是请求路径,哪一个是返回值?我们根据这个返回值做出判断,返回值返回的是哪种数据,我们就要编写哪种数据的业务逻辑。比如返回SpuDetail,我们就要去编写SpuDetail的业务逻辑,首先我们要找到它的pojo类,要看看是否返回一个列表,如果不是列表,我们直接写返回这个pojo类就可以了,你要注意看清楚地址后面是斜号还是问号,不同的符号有不同的截取方法,Controller比较容易写,调用service方法,并且做出判断是否为空,如果为空的话,返回404错误。Service就是调用Mapper的方法,我们看看他传过来的参数是不是一个主键,如果是一个主键的话,我们可以直接通过主键查询数据库信息的Mapper方法,来返回一个信息。
如果是涉及到列表的,那就要看传进来的参数是不是主键,如果是主键的话,只能查询到一条信息,如果不是主键的话,我们要先new一个pojo对象,然后把id传进来,如果id有很多个,就用List接收id,我们这里的情况是只有一个id,我们先去数据库看一看这个id查询到的东西是不是我们想要的,如果查询到的东西是我们想要的,那我们可以用普通的select方法去查询结果,结果是一个List就用List接收,如果在另一个表里面,我们需要用到这个List来查询对应的List信息,并且一个个去匹配,我们就需要用到遍历方法,也就是一个个去匹配并且返回结果就行。