苍穹外卖--开发记录day07

文章

苍穹外卖day07

一:导入商品浏览接口

跟着视频在资料包里导入就行了。和之前一样都是crud

二:缓存菜品

问题说明,我们将数据存放在数据库,当有大量的用户访问数据库时,数据库的性能会下降,压力提高;我们可以使用缓存,减少数据库访问的压力

实现思路,用户查询菜品,我们先看缓存中有没有菜品,如果没有就查询数据库,然后再存入缓存

将菜品保存在缓存中,我们在controller中找到查询所有菜品的方法,然后做判断,先通过key来获取缓存的value,如果缓存中存在这个key就获取,然后直接返回,如果不存在就调用方法查询数据库,获得的菜品再存入缓存:

java 复制代码
@GetMapping("/list")
@ApiOperation("根据分类id查询菜品")
public Result<List<DishVO>> list(Long categoryId) {
    String key ="dish_"+categoryId;
    ValueOperations valueOperations = redisTemplate.opsForValue();
    if (redisTemplate.hasKey(key)){
        List<DishVO> res = (List<DishVO>) valueOperations.get(key);
        return Result.success(res);
    }
    Dish dish = new Dish();
    dish.setCategoryId(categoryId);
    dish.setStatus(StatusConstant.ENABLE);//查询起售中的菜品
    List<DishVO> list = dishService.listWithFlavor(dish);
    valueOperations.set(key,list);
    return Result.success(list);
}

我们统一将redis中存储分类菜品数据的key变成"dish_"+categoryId,然后需要注意的是,我们从redis中获取到时候key必须的字符穿类型的,value可以是任意类型的,我们取得时候就按存入时的类型去强制类型转换就行;

然后我们要进行菜品信息修改的话,小程序还是会从缓存中取数据而我们数据库的信息已经修改了,这个时候就要进行清理缓存的操作了,我们要思考一下,进行添加菜品需要清理吗,需要;因为我们菜品分类下多了一个菜品,修改菜品也需要,而且如果是修改分类的话,那么就会影响到两个缓存数据,为了方便呢,我们直接清理全部缓存即可,然后批量删除菜品也是,可能同时影响多个分类,所以我们也要清理全部缓存;

我们再admin下的菜品管理接口下进行清理即可:

java 复制代码
private void clearCache(String pattern){
    Set keys = redisTemplate.keys(pattern);
    redisTemplate.delete(pattern);
}

定义一个方法,代表按照pattern的格式去清理缓存;

修改,删除操作:

java 复制代码
clearCache("dish_*");

清楚所有;

添加其实没必要进行清理,因为我们默认添加的菜品是禁售的;

三:springcache

1:enablecaching:开启缓存注解功能

2:cacheable:放在方法上看缓存中有没有数据,有直接返回,没有将方法的返回值放入缓存

3:cacheput:将方法的返回值放到缓存中;

4:cacheevict:清理缓存

具体使用:

java 复制代码
@Cacheable(cacheNames = "userCache",key = "#id" )

1:cacheable:这里放在方法上:通过userCache和key来拼接redis中的key,然后他会直接取redis中取查有没有存在我们拼接的这个key,如果有就直接返回,不调用方法,如果没有就通过反射来调用方法,然后将方法的返回值直接添加到我们拼接的key中;

java 复制代码
@CachePut(cacheNames = "userCache" ,key = "#user.id")

2:CachePut是直接将方法的返回值插入到redis中,然后前缀都是一样的,后面的key想要不一样就要动态设置,#后可以调用我们的参数,#result可以调用我们方法的返回值,然后#p可以知道是我们第几个参数,而且这个插入是当方法执行完毕后才会插入的;

java 复制代码
@CacheEvict(cacheNames = "userCache",key = "#id")
java 复制代码
@CacheEvict(cacheNames = "userCache",allEntries = true)

3:cacheEvict:这个就是清理缓存数据,我们可以一次清理一个和上面的命名方法一样,也可以使用allEntries将userCache下的全部数据清除;

四:缓存套餐

其实很简单只要再用户端查询套餐的接口上加上cacheable注解,这样,当我们的redis中没有时我们会执行方法,然后将返回值插入到redis,插入的时result对象,当然我们取出的也是result,前端需要的也是result,当我们redis中有key时就直接返回

java 复制代码
@Cacheable(cacheNames = "setmeal",key = "#categoryId")

清理缓存:当套餐增加了,对应的分类就要清除缓存,不然查询不到我们增加的套餐,当套餐修改了,如果修改的是套餐种类,那么可能会影响两个套餐种类,所有要清楚所有缓存,如果套餐批量删除,也可能会影响多个分类,所以,也要清楚全部缓存

java 复制代码
@CacheEvict(cacheNames = "setmeal",key = "#setmealDTO.categoryId")
java 复制代码
@CacheEvict(cacheNames = "setmeal",allEntries = true)

五:添加购物车

添加到购物车的service要麻烦一些:

controller:

java 复制代码
@PostMapping("/add")
public Result addCart(@RequestBody ShoppingCartDTO shoppingCartDTO){
    log.info("添加购物车{}",shoppingCartDTO);
    shopCartService.addCart(shoppingCartDTO);
    return Result.success();
}

我们接收的是一个dto对象,dto中有套餐id和菜品id,但是只会有一个,要么是套餐,要么是菜品;

service:

java 复制代码
@Override
public void addCart(ShoppingCartDTO shoppingCartDTO) {
    ShoppingCart shoppingCart = new ShoppingCart();
    BeanUtils.copyProperties(shoppingCartDTO,shoppingCart);
    shoppingCart.setUserId(BaseContext.getCurrentId());
    List<ShoppingCart> shoppingCarts= shopCartMapper.list(shoppingCart);
    //判断购物车是否已经存在菜品或者套餐
    if (shoppingCarts.size()>0&&shoppingCarts!=null){
        shopCartMapper.update(shoppingCart);
        return;
    }
    //将购物车中的信息插入到表中
    if (shoppingCartDTO.getDishId()!=null){//如果是菜品
        DishVO dishVO = dishMapper.selectById(shoppingCartDTO.getDishId());
        shoppingCart.setImage(dishVO.getImage());
        shoppingCart.setAmount(dishVO.getPrice());
        shoppingCart.setName(dishVO.getName());
        shoppingCart.setDishId(shoppingCartDTO.getDishId());
    }else if (shoppingCartDTO.getSetmealId()!=null) {//如果是套餐
        Setmeal setmeal = setmealMapper.selectById(shoppingCartDTO.getSetmealId());
        shoppingCart.setImage(setmeal.getImage());
        shoppingCart.setAmount(setmeal.getPrice());
        shoppingCart.setName(setmeal.getName());
        shoppingCart.setSetmealId(shoppingCartDTO.getSetmealId());
    }
    shoppingCart.setCreateTime(LocalDateTime.now());
    shopCartMapper.addCart(shoppingCart);
}

这边的业务逻辑比较复杂,我们要先看购物车里有没有当前传入的商品,如果有我们就只需要number+1就行了,然后我们先进行查询,看有没有我们当前传入的商品,我们根据dto中的菜品id或者套餐id,前边说过只会有一个所以sql这么写:

java 复制代码
<select id="list" resultType="com.sky.entity.ShoppingCart">
    select * from sky_take_out.shopping_cart
    <where>
        <if test="dishId!=null">
            dish_id=#{dishId}
        </if>
        <if test="setmealId!=null">
            setmeal_id=#{setmealId}
        </if>
           <if test="dishFlavor!=null">
                and dish_flavor=#{dishFlavor}
         </if>
        and user_id=#{userId}
    </where>
</select>

这里面的useid是我们通过treadlocal获取的;返回的虽然是一个集合,但是里面要么只有一个元素,要么就是没有元素,因为一个用户的一个菜品只会有一条数据,然后我们判断是否为空,如果不为空说明购物车中有该物品,我们只需要将number加一就行了,所以这边是update语句:

java 复制代码
<update id="update">
    update sky_take_out.shopping_cart set
    number= number+1
    where
    <if test="dishId!=null">
        dish_id=#{dishId}
    </if>
    <if test="setmealId!=null">
        setmeal_id=#{setmealId}
    </if>
    and user_id=#{userId}
</update>

可以看到我们通过用户id和商品id唯一的确定了一条数据,然后直接返回就行;

那么如果为空我们就要插入,这里可能是菜品,也可能是套餐,为方便后面调用相关的方法,我们分两种情况进行赋值,要赋值的有:商品名称,商品价格,商品的图片,商品的创建时间;

最后执行插入操作语句:

java 复制代码
@Insert("insert into sky_take_out.shopping_cart (name, image, user_id, dish_id, setmeal_id, dish_flavor, amount, create_time) " +
        "VALUES (#{name}, #{image}, #{userId}, #{dishId}, #{setmealId}, #{dishFlavor}, #{amount}, #{createTime})")
void addCart(ShoppingCart shoppingCart);

就完成了!

mapper:见上;

六:查看购物车

controller:

java 复制代码
@GetMapping("/list")
public Result select(){
  List<ShoppingCart>shoppingCarts= shopCartService.select();
  return Result.success(shoppingCarts);
}

service:

java 复制代码
public List<ShoppingCart> select() {
    ShoppingCart shoppingCart = new ShoppingCart();
    shoppingCart.setUserId(BaseContext.getCurrentId());
    List<ShoppingCart> list = shopCartMapper.list(shoppingCart);
    return list;
}

直接调用我们之前已经定义的list方法就行;

mapper:

java 复制代码
<select id="list" resultType="com.sky.entity.ShoppingCart">
    select * from sky_take_out.shopping_cart
    <where>
        <if test="dishId!=null">
            dish_id=#{dishId}
        </if>
        <if test="setmealId!=null">
            setmeal_id=#{setmealId}
        </if>
        <if test="dishFlavor!=null">
            and dish_flavor=#{dishFlavor}
        </if>
        and user_id=#{userId}
    </where>
</select>

七:清空购物车

controller:

java 复制代码
@DeleteMapping("/clean")
public Result clean(){
    shopCartService.clean();
    return Result.success();
}

service:

java 复制代码
@Override
public void clean() {

    shopCartMapper.clean(BaseContext.getCurrentId());

}

mapper:

java 复制代码
@Delete("delete from sky_take_out.shopping_cart where user_id=#{currentId}")
    void clean(Long currentId);

八:删除一个商品

这里其实是商品的数量-1,并且还有一个逻辑就是,当商品的数量为0时就删除这个商品

controller:

@PostMapping ("/sub")
public Result deleteOne(@RequestBody ShoppingCartDTO shoppingCartDTO){
    shopCartService.updateOne(shoppingCartDTO);
    return Result.success();
}

service:

java 复制代码
@Override
public void updateOne(ShoppingCartDTO shoppingCartDTO) {
    ShoppingCart shoppingCart = new ShoppingCart();
    BeanUtils.copyProperties(shoppingCartDTO,shoppingCart);
    shoppingCart.setUserId(BaseContext.getCurrentId());
    shopCartMapper.updateOne(shoppingCart);
    List<ShoppingCart> list = shopCartMapper.list(shoppingCart);
    ShoppingCart shoppingCart1 = list.get(0);
    if (shoppingCart1.getNumber()==0){
        shopCartMapper.deleteById(shoppingCart1.getId());
    }
}

这里做了判断,更改完数量后,如果数量为0就直接删除;

mapper:

java 复制代码
<update id="updateOne">
    update sky_take_out.shopping_cart
    set number=number - 1
    <where>
        <if test="dishId!=null">
            dish_id=#{dishId}
        </if>
        <if test="setmealId!=null">
            setmeal_id=#{setmealId}
        </if>
        <if test="dishFlavor!=null">
            and dish_flavor=#{dishFlavor}
        </if>
        and user_id=#{userId}
    </where>
</update>

更改数量

java 复制代码
@Delete("delete from sky_take_out.shopping_cart where id=#{id}")
void deleteById(Long id);

删除数量为0的商品;

总结

今天学习了springcache进行注解缓存开发,然后利用redis缓存菜品和套餐,添加购物车,查看购物车等功能;

相关推荐
dazhong20121 小时前
PLSQL 客户端连接 Oracle 数据库配置
数据库·oracle
了一li3 小时前
Qt中的QProcess与Boost.Interprocess:实现多进程编程
服务器·数据库·qt
码农君莫笑3 小时前
信管通低代码信息管理系统应用平台
linux·数据库·windows·低代码·c#·.net·visual studio
别致的影分身4 小时前
使用C语言连接MySQL
数据库·mysql
w_31234545 小时前
自定义一个maven骨架 | 最佳实践
java·maven·intellij-idea
京东零售技术5 小时前
“慢”增长时代的企业数据体系建设:超越数据中台
数据库
sdaxue.com6 小时前
帝国CMS:如何去掉帝国CMS登录界面的认证码登录
数据库·github·网站·帝国cms·认证码
o(╥﹏╥)6 小时前
linux(ubuntu )卡死怎么强制重启
linux·数据库·ubuntu·系统安全
海海不掉头发7 小时前
苍穹外卖-day05redis 缓存的学习
学习·缓存
阿里嘎多学长7 小时前
docker怎么部署高斯数据库
运维·数据库·docker·容器