2). 页面发送ajax请求,获取第一个分类下的菜品或者套餐
A. 根据分类ID查询套餐列表:
异步请求,查询分类对应的菜品列表,功能我们已经实现了,但是我们之前查询的只是菜品的基本信息,不包含菜品的口味信息。所以在前端界面中,我们看不到选择菜品分类的信息。
经过上述的分析,我们可以看到,服务端我们主要提供两个方法, 分别用来:
A. 根据分类ID查询菜品列表(包含菜品口味列表), 具体请求信息如下:
请求 | 说明 |
请求方式 | GET |
请求路径 | /dish/list |
请求参数 | ?categoryId=1397844263642378242&status=1 |
该功能在服务端已经实现,我们需要修改此方法,在原有方法的基础上增加查询菜品的口味信息。
B. 根据分类ID查询套餐列表, 具体请求信息如下:
请求 | 说明 |
请求方式 | GET |
请求路径 | /setmeal/list |
请求参数 | ?categoryId=1397844263642378242&status=1 |
该功能在服务端并未实现。
2.3 代码开发
2.3.1 查询菜品方法修改
由于之前我们实现的根据分类查询菜品列表,仅仅查询了菜品的基本信息,未查询菜品口味信息,而移动端用户在点餐时,是需要选择口味信息的,所以我们需要对之前的代码实现进行完善,那么如何完善呢?
我们需要修改DishController的list方法,原来此方法的返回值类型为:R>。为了满足移动端对数据的要求(菜品基本信息和菜品对应的口味信息),现在需要将方法的返回值类型改为:R> ,因为在DishDto中封装了菜品对应的口味信息:
代码逻辑:
A. 根据分类ID查询,查询目前正在启售的菜品列表 (已实现)
B. 遍历菜品列表,并查询菜品的分类信息及菜品的口味列表
C. 组装数据DishDto,并返回
代码实现:
<spanstyle="background-color:#f8f8f8"><spanstyle="color:#333333"><spanstyle="color:#555555"></span>(<spanstyle="color:#aa1111">"/list"</span>) <spanstyle="color:#770088">public</span><spanstyle="color:#000000">R</span><spanstyle="color:#981a1a"><</span><spanstyle="color:#000000">List</span><spanstyle="color:#981a1a"><</span><spanstyle="color:#000000">DishDto</span><spanstyle="color:#981a1a">>></span><spanstyle="color:#0000ff">list</span>(<spanstyle="color:#000000">Dish</span><spanstyle="color:#000000">dish</span>){ <spanstyle="color:#aa5500">//构造查询条件</span><spanstyle="color:#000000">LambdaQueryWrapper</span><spanstyle="color:#981a1a"><</span><spanstyle="color:#000000">Dish</span><spanstyle="color:#981a1a">></span><spanstyle="color:#000000">queryWrapper</span><spanstyle="color:#981a1a">=</span><spanstyle="color:#770088">new</span><spanstyle="color:#000000">LambdaQueryWrapper</span><spanstyle="color:#981a1a"><></span>(); <spanstyle="color:#000000">queryWrapper</span>.<spanstyle="color:#000000">eq</span>(<spanstyle="color:#000000">dish</span>.<spanstyle="color:#000000">getCategoryId</span>() <spanstyle="color:#981a1a">!=</span><spanstyle="color:#221199">null</span> ,<spanstyle="color:#000000">Dish</span>::<spanstyle="color:#000000">getCategoryId</span>,<spanstyle="color:#000000">dish</span>.<spanstyle="color:#000000">getCategoryId</span>()); <spanstyle="color:#aa5500">//添加条件,查询状态为1(起售状态)的菜品</span><spanstyle="color:#000000">queryWrapper</span>.<spanstyle="color:#000000">eq</span>(<spanstyle="color:#000000">Dish</span>::<spanstyle="color:#000000">getStatus</span>,<spanstyle="color:#116644">1</span>); <spanstyle="color:#aa5500">//添加排序条件</span><spanstyle="color:#000000">queryWrapper</span>.<spanstyle="color:#000000">orderByAsc</span>(<spanstyle="color:#000000">Dish</span>::<spanstyle="color:#000000">getSort</span>).<spanstyle="color:#000000">orderByDesc</span>(<spanstyle="color:#000000">Dish</span>::<spanstyle="color:#000000">getUpdateTime</span>); <spanstyle="color:#000000">List</span><spanstyle="color:#981a1a"><</span><spanstyle="color:#000000">Dish</span><spanstyle="color:#981a1a">></span><spanstyle="color:#000000">list</span><spanstyle="color:#981a1a">=</span><spanstyle="color:#000000">dishService</span>.<spanstyle="color:#000000">list</span>(<spanstyle="color:#000000">queryWrapper</span>); <spanstyle="color:#000000">List</span><spanstyle="color:#981a1a"><</span><spanstyle="color:#000000">DishDto</span><spanstyle="color:#981a1a">></span><spanstyle="color:#000000">dishDtoList</span><spanstyle="color:#981a1a">=</span><spanstyle="color:#000000">list</span>.<spanstyle="color:#000000">stream</span>().<spanstyle="color:#000000">map</span>((<spanstyle="color:#000000">item</span>) <spanstyle="color:#981a1a">-></span> { <spanstyle="color:#000000">DishDto</span><spanstyle="color:#000000">dishDto</span><spanstyle="color:#981a1a">=</span><spanstyle="color:#770088">new</span><spanstyle="color:#000000">DishDto</span>(); <spanstyle="color:#000000">BeanUtils</span>.<spanstyle="color:#000000">copyProperties</span>(<spanstyle="color:#000000">item</span>,<spanstyle="color:#000000">dishDto</span>); <spanstyle="color:#008855">Long</span><spanstyle="color:#000000">categoryId</span><spanstyle="color:#981a1a">=</span><spanstyle="color:#000000">item</span>.<spanstyle="color:#000000">getCategoryId</span>();<spanstyle="color:#aa5500">//分类id</span><spanstyle="color:#aa5500">//根据id查询分类对象</span><spanstyle="color:#000000">Category</span><spanstyle="color:#000000">category</span><spanstyle="color:#981a1a">=</span><spanstyle="color:#000000">categoryService</span>.<spanstyle="color:#000000">getById</span>(<spanstyle="color:#000000">categoryId</span>); <spanstyle="color:#770088">if</span>(<spanstyle="color:#000000">category</span><spanstyle="color:#981a1a">!=</span><spanstyle="color:#221199">null</span>){ <spanstyle="color:#008855">String</span><spanstyle="color:#000000">categoryName</span><spanstyle="color:#981a1a">=</span><spanstyle="color:#000000">category</span>.<spanstyle="color:#000000">getName</span>(); <spanstyle="color:#000000">dishDto</span>.<spanstyle="color:#000000">setCategoryName</span>(<spanstyle="color:#000000">categoryName</span>); } <spanstyle="color:#aa5500">//当前菜品的id</span><spanstyle="color:#008855">Long</span><spanstyle="color:#000000">dishId</span><spanstyle="color:#981a1a">=</span><spanstyle="color:#000000">item</span>.<spanstyle="color:#000000">getId</span>(); <spanstyle="color:#000000">LambdaQueryWrapper</span><spanstyle="color:#981a1a"><</span><spanstyle="color:#000000">DishFlavor</span><spanstyle="color:#981a1a">></span><spanstyle="color:#000000">lambdaQueryWrapper</span><spanstyle="color:#981a1a">=</span><spanstyle="color:#770088">new</span><spanstyle="color:#000000">LambdaQueryWrapper</span><spanstyle="color:#981a1a"><></span>(); <spanstyle="color:#000000">lambdaQueryWrapper</span>.<spanstyle="color:#000000">eq</span>(<spanstyle="color:#000000">DishFlavor</span>::<spanstyle="color:#000000">getDishId</span>,<spanstyle="color:#000000">dishId</span>); <spanstyle="color:#aa5500">//SQL:select * from dish_flavor where dish_id = ?</span><spanstyle="color:#000000">List</span><spanstyle="color:#981a1a"><</span><spanstyle="color:#000000">DishFlavor</span><spanstyle="color:#981a1a">></span><spanstyle="color:#000000">dishFlavorList</span><spanstyle="color:#981a1a">=</span><spanstyle="color:#000000">dishFlavorService</span>.<spanstyle="color:#000000">list</span>(<spanstyle="color:#000000">lambdaQueryWrapper</span>); <spanstyle="color:#000000">dishDto</span>.<spanstyle="color:#000000">setFlavors</span>(<spanstyle="color:#000000">dishFlavorList</span>); <spanstyle="color:#770088">return</span><spanstyle="color:#000000">dishDto</span>; }).<spanstyle="color:#000000">collect</span>(<spanstyle="color:#000000">Collectors</span>.<spanstyle="color:#000000">toList</span>()); <spanstyle="color:#770088">return</span><spanstyle="color:#000000">R</span>.<spanstyle="color:#000000">success</span>(<spanstyle="color:#000000">dishDtoList</span>); }</span></span>
2.3.2 根据分类ID查询套餐
在SetmealController中创建list方法,根据条件查询套餐数据。
<spanstyle="background-color:#f8f8f8"><spanstyle="color:#333333"><spanstyle="color:#aa5500">/**</span><span style="color:#aa5500">* 根据条件查询套餐数据</span><span style="color:#aa5500">* @param setmeal</span><span style="color:#aa5500">* @return</span><span style="color:#aa5500">*/</span><spanstyle="color:#555555"></span>(<spanstyle="color:#aa1111">"/list"</span>) <spanstyle="color:#770088">public</span><spanstyle="color:#000000">R</span><spanstyle="color:#981a1a"><</span><spanstyle="color:#000000">List</span><spanstyle="color:#981a1a"><</span><spanstyle="color:#000000">Setmeal</span><spanstyle="color:#981a1a">>></span><spanstyle="color:#0000ff">list</span>(<spanstyle="color:#000000">Setmeal</span><spanstyle="color:#000000">setmeal</span>){ <spanstyle="color:#000000">LambdaQueryWrapper</span><spanstyle="color:#981a1a"><</span><spanstyle="color:#000000">Setmeal</span><spanstyle="color:#981a1a">></span><spanstyle="color:#000000">queryWrapper</span><spanstyle="color:#981a1a">=</span><spanstyle="color:#770088">new</span><spanstyle="color:#000000">LambdaQueryWrapper</span><spanstyle="color:#981a1a"><></span>(); <spanstyle="color:#000000">queryWrapper</span>.<spanstyle="color:#000000">eq</span>(<spanstyle="color:#000000">setmeal</span>.<spanstyle="color:#000000">getCategoryId</span>() <spanstyle="color:#981a1a">!=</span><spanstyle="color:#221199">null</span>,<spanstyle="color:#000000">Setmeal</span>::<spanstyle="color:#000000">getCategoryId</span>,<spanstyle="color:#000000">setmeal</span>.<spanstyle="color:#000000">getCategoryId</span>()); <spanstyle="color:#000000">queryWrapper</span>.<spanstyle="color:#000000">eq</span>(<spanstyle="color:#000000">setmeal</span>.<spanstyle="color:#000000">getStatus</span>() <spanstyle="color:#981a1a">!=</span><spanstyle="color:#221199">null</span>,<spanstyle="color:#000000">Setmeal</span>::<spanstyle="color:#000000">getStatus</span>,<spanstyle="color:#000000">setmeal</span>.<spanstyle="color:#000000">getStatus</span>()); <spanstyle="color:#000000">queryWrapper</span>.<spanstyle="color:#000000">orderByDesc</span>(<spanstyle="color:#000000">Setmeal</span>::<spanstyle="color:#000000">getUpdateTime</span>); <spanstyle="color:#000000">List</span><spanstyle="color:#981a1a"><</span><spanstyle="color:#000000">Setmeal</span><spanstyle="color:#981a1a">></span><spanstyle="color:#000000">list</span><spanstyle="color:#981a1a">=</span><spanstyle="color:#000000">setmealService</span>.<spanstyle="color:#000000">list</span>(<spanstyle="color:#000000">queryWrapper</span>); <spanstyle="color:#770088">return</span><spanstyle="color:#000000">R</span>.<spanstyle="color:#000000">success</span>(<spanstyle="color:#000000">list</span>); }</span></span>
2.4 功能测试
把菜品展示的功能代码完善完成之后,我们重新启动服务,来测试一个菜品展示的功能。测试过程中可以使用浏览器的监控工具查看页面和服务端的数据交互细节。
点击分类,根据分类查询菜品列表/套餐列表:
3. 购物车
3.1 需求分析
移动端用户可以将菜品或者套餐添加到购物车。对于菜品来说,如果设置了口味信息,则需要选择规格后才能加入购物车;对于套餐来说,可以直接点击
将当前套餐加入购物车。在购物车中可以修改菜品和套餐的数量,也可以清空购物车。
这里面我们需要实现的功能包括:
1). 添加购物车
2). 查询购物车
3). 清空购物车
3.2 数据模型
用户的购物车数据,也是需要保存在数据库中的,购物车对应的数据表为shopping_cart表,具体表结构如下:
说明:
购物车数据是关联用户的,在表结构中,我们需要记录,每一个用户的购物车数据是哪些
菜品列表展示出来的既有套餐,又有菜品,如果APP端选择的是套餐,就保存套餐ID(setmeal_id),如果APP端选择的是菜品,就保存菜品ID(dish_id)
对同一个菜品/套餐,如果选择多份不需要添加多条记录,增加数量number即可
最终shopping_cart表中存储的数据示例:
3.3 前端页面分析
在开发代码之前,需要梳理一下购物车操作时前端页面和服务端的交互过程:
1). 点击 "加入购物车" 或者 "+" 按钮,页面发送ajax请求,请求服务端,将菜品或者套餐添加到购物车
2). 点击购物车图标,页面发送ajax请求,请求服务端查询购物车中的菜品和套餐
此时,我们就需要将查询购物车的代码放开,不用再加载静态的json数据了。
3). 点击清空购物车按钮,页面发送ajax请求,请求服务端来执行清空购物车操作
经过上述的分析,我们可以看到,对于购物车的功能,我们主要需要开发以下几个功能,具体的请求信息如下:
1). 加入购物车
请求 | 说明 |
请求方式 | POST |
请求路径 | /shoppingCart/add |
请求参数 | json格式 |
<spanstyle="background-color:#f8f8f8"><spanstyle="color:#333333"><spanstyle="color:#000000">菜品数据</span>: {<spanstyle="color:#000000">"amount"</span>:<spanstyle="color:#116644">118</span>,<spanstyle="color:#000000">"dishFlavor"</span>:<spanstyle="color:#aa1111">"不要蒜,微辣"</span>,<spanstyle="color:#000000">"dishId"</span>:<spanstyle="color:#aa1111">"1397851099502260226"</span>,<spanstyle="color:#000000">"name"</span>:<spanstyle="color:#aa1111">"全家福"</span>,<spanstyle="color:#000000">"image"</span>:<spanstyle="color:#aa1111">"a53a4e6a-3b83-4044-87f9-9d49b30a8fdc.jpg"</span>} <spanstyle="color:#000000">套餐数据</span>: {<spanstyle="color:#000000">"amount"</span>:<spanstyle="color:#116644">38</span>,<spanstyle="color:#000000">"setmealId"</span>:<spanstyle="color:#aa1111">"1423329486060957698"</span>,<spanstyle="color:#000000">"name"</span>:<spanstyle="color:#aa1111">"营养超值工作餐"</span>,<spanstyle="color:#000000">"image"</span>:<spanstyle="color:#aa1111">"9cd7a80a-da54-4f46-bf33-af3576514cec.jpg"</span>}</span></span>
2). 查询购物车列表
请求 | 说明 |
请求方式 | GET |
请求路径 | /shoppingCart/list |
3). 清空购物车功能
请求 | 说明 |
请求方式 | DELETE |
请求路径 | /shoppingCart/clean |
3.4 准备工作
分析完毕购物车的业务需求和实现思路之后,在开发业务功能前,先将需要用到的类和接口基本结构创建好:
1). 实体类 ShoppingCart(直接从课程资料中导入即可)
所属包: com.itheima.reggie.entity
<spanstyle="background-color:#f8f8f8"><spanstyle="color:#333333"><spanstyle="color:#770088">import</span><spanstyle="color:#000000">lombok</span>.<spanstyle="color:#000000">Data</span>; <spanstyle="color:#770088">import</span><spanstyle="color:#000000">java</span>.<spanstyle="color:#000000">io</span>.<spanstyle="color:#000000">Serializable</span>; <spanstyle="color:#770088">import</span><spanstyle="color:#000000">java</span>.<spanstyle="color:#000000">math</span>.<spanstyle="color:#000000">BigDecimal</span>; <spanstyle="color:#770088">import</span><spanstyle="color:#000000">java</span>.<spanstyle="color:#000000">time</span>.<spanstyle="color:#000000">LocalDateTime</span>; <spanstyle="color:#aa5500">/**</span><span style="color:#aa5500">* 购物车</span><span style="color:#aa5500">*/</span><spanstyle="color:#555555"></span><spanstyle="color:#770088">public</span><spanstyle="color:#770088">class</span><spanstyle="color:#0000ff">ShoppingCart</span><spanstyle="color:#770088">implements</span><spanstyle="color:#000000">Serializable</span> { <spanstyle="color:#770088">private</span><spanstyle="color:#770088">static</span><spanstyle="color:#770088">final</span><spanstyle="color:#008855">long</span><spanstyle="color:#000000">serialVersionUID</span><spanstyle="color:#981a1a">=</span><spanstyle="color:#116644">1L</span>; <spanstyle="color:#770088">private</span><spanstyle="color:#008855">Long</span><spanstyle="color:#000000">id</span>; <spanstyle="color:#aa5500">//名称</span><spanstyle="color:#770088">private</span><spanstyle="color:#008855">String</span><spanstyle="color:#000000">name</span>; <spanstyle="color:#aa5500">//用户id</span><spanstyle="color:#770088">private</span><spanstyle="color:#008855">Long</span><spanstyle="color:#000000">userId</span>; <spanstyle="color:#aa5500">//菜品id</span><spanstyle="color:#770088">private</span><spanstyle="color:#008855">Long</span><spanstyle="color:#000000">dishId</span>; <spanstyle="color:#aa5500">//套餐id</span><spanstyle="color:#770088">private</span><spanstyle="color:#008855">Long</span><spanstyle="color:#000000">setmealId</span>; <spanstyle="color:#aa5500">//口味</span><spanstyle="color:#770088">private</span><spanstyle="color:#008855">String</span><spanstyle="color:#000000">dishFlavor</span>; <spanstyle="color:#aa5500">//数量</span><spanstyle="color:#770088">private</span><spanstyle="color:#008855">Integer</span><spanstyle="color:#000000">number</span>; <spanstyle="color:#aa5500">//金额</span><spanstyle="color:#770088">private</span><spanstyle="color:#000000">BigDecimal</span><spanstyle="color:#000000">amount</span>; <spanstyle="color:#aa5500">//图片</span><spanstyle="color:#770088">private</span><spanstyle="color:#008855">String</span><spanstyle="color:#000000">image</span>; <spanstyle="color:#770088">private</span><spanstyle="color:#000000">LocalDateTime</span><spanstyle="color:#000000">createTime</span>; }</span></span>
2). Mapper接口 ShoppingCartMapper
所属包: com.itheima.reggie.mapper
<spanstyle="background-color:#f8f8f8"><spanstyle="color:#333333">importcom.baomidou.mybatisplus.core.mapper.BaseMapper; importcom.itheima.reggie.entity.ShoppingCart; importorg.apache.ibatis.annotations.Mapper; publicinterfaceShoppingCartMapperextendsBaseMapper<ShoppingCart> { }</span></span>
3). 业务层接口 ShoppingCartService
所属包: com.itheima.reggie.service
<spanstyle="background-color:#f8f8f8"><spanstyle="color:#333333">importcom.baomidou.mybatisplus.extension.service.IService; importcom.itheima.reggie.entity.ShoppingCart; publicinterfaceShoppingCartServiceextendsIService<ShoppingCart> { }</span></span>
4). 业务层实现类 ShoppingCartServiceImpl
所属包: com.itheima.reggie.service.impl
<spanstyle="background-color:#f8f8f8"><spanstyle="color:#333333">importcom.baomidou.mybatisplus.extension.service.impl.ServiceImpl; importcom.itheima.reggie.entity.ShoppingCart; importcom.itheima.reggie.mapper.ShoppingCartMapper; importcom.itheima.reggie.service.ShoppingCartService; importorg.springframework.stereotype.Service; publicclassShoppingCartServiceImplextendsServiceImpl<ShoppingCartMapper, ShoppingCart>implementsShoppingCartService { }</span></span>
5). 控制层 ShoppingCartController
所属包: com.itheima.reggie.controller
<spanstyle="background-color:#f8f8f8"><spanstyle="color:#333333"><spanstyle="color:#770088">import</span><spanstyle="color:#000000">com</span>.<spanstyle="color:#000000">itheima</span>.<spanstyle="color:#000000">reggie</span>.<spanstyle="color:#000000">service</span>.<spanstyle="color:#000000">ShoppingCartService</span>; <spanstyle="color:#770088">import</span><spanstyle="color:#000000">lombok</span>.<spanstyle="color:#000000">extern</span>.<spanstyle="color:#000000">slf4j</span>.<spanstyle="color:#000000">Slf4j</span>; <spanstyle="color:#770088">import</span><spanstyle="color:#000000">org</span>.<spanstyle="color:#000000">springframework</span>.<spanstyle="color:#000000">beans</span>.<spanstyle="color:#000000">factory</span>.<spanstyle="color:#000000">annotation</span>.<spanstyle="color:#000000">Autowired</span>; <spanstyle="color:#770088">import</span><spanstyle="color:#000000">org</span>.<spanstyle="color:#000000">springframework</span>.<spanstyle="color:#000000">web</span>.<spanstyle="color:#000000">bind</span>.<spanstyle="color:#000000">annotation</span>.<spanstyle="color:#981a1a">*</span>; <spanstyle="color:#aa5500">/**</span><span style="color:#aa5500">* 购物车</span><span style="color:#aa5500">*/</span><spanstyle="color:#555555"></span><spanstyle="color:#555555"></span><spanstyle="color:#555555"></span>(<spanstyle="color:#aa1111">"/shoppingCart"</span>) <spanstyle="color:#770088">public</span><spanstyle="color:#770088">class</span><spanstyle="color:#0000ff">ShoppingCartController</span> { <spanstyle="color:#555555"></span><spanstyle="color:#770088">private</span><spanstyle="color:#000000">ShoppingCartService</span><spanstyle="color:#000000">shoppingCartService</span>; } </span></span>