• 瑞吉外卖优化


    1.缓存问题

    • 用户数量多,系统访问量大频繁访问数据库,系统性能下降,用户体验差

    2.导入依赖 和配置

    1. org.springframework.boot
    2. spring-boot-starter-data-redis
    1. spring:
    2. redis:
    3. host: 自己的地址
    4. password: 自己的密码
    5. database: 0
    6. port: 6379

    3.key序列化配置类

    1. @Configuration
    2. public class RedisConfig extends CachingConfigurerSupport {
    3. @Bean
    4. public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory){
    5. RedisTemplate redisTemplate=new RedisTemplate<>();
    6. //默认的key序列化器为:JdkSerializationRedisSerializer
    7. redisTemplate.setKeySerializer(new StringRedisSerializer());
    8. redisTemplate.setHashValueSerializer(new StringRedisSerializer());
    9. return redisTemplate;
    10. }
    11. }

    4.缓存短信验证码

    4.1实现思路

    1.引入RedisTemplate

    2.设置验证码缓存到redis

    3.登陆成功删除redis中的验证码

    4.2代码 

    1. @Slf4j
    2. @RestController
    3. @RequestMapping("/user")
    4. public class UserController {
    5. @Autowired
    6. private UserService userService;
    7. @Autowired
    8. private RedisTemplate redisTemplate;
    9. /**
    10. * 发送手机短信验证码
    11. *
    12. * @param user
    13. * @return
    14. */
    15. @PostMapping("/sendMsg")
    16. public R sendMsg(@RequestBody User user, HttpSession session) {
    17. //1.获取手机号
    18. String phone = user.getPhone();
    19. if (StringUtils.isNotEmpty(phone)) {
    20. //2.生成四位的验证码
    21. String code = ValidateCodeUtils.generateValidateCode(4).toString();
    22. //查看验证码
    23. log.info("code={}", code);
    24. //3.调用阿里云短信服务完成发送
    25. //若要真的发送,执行下面
    26. // SMSUtils.sendMessage("签名","",phone,code);
    27. //4.生成的验证码保存到session
    28. // session.setAttribute(phone, code);
    29. //优化,将生成的验证码缓存到redis中,有效期5分钟
    30. redisTemplate.opsForValue().set(phone, code, 5, TimeUnit.MINUTES);
    31. return R.success("发送验证码发送成功");
    32. }
    33. return R.success("发送失败");
    34. }
    35. /**
    36. * 移动端登录
    37. */
    38. @PostMapping("/login")
    39. public R login(@RequestBody Map map, HttpSession session) {
    40. //1.获取手机号
    41. String phone = map.get("phone").toString();
    42. //2.获取验证码
    43. String code = map.get("code").toString();
    44. //3.从Session中获取保存的验证码进行比对
    45. // Object codeInSession = session.getAttribute(phone);
    46. //优化:从redis中获取缓存验证码
    47. Object codeInSession = redisTemplate.opsForValue().get(phone);
    48. //4.如果比对成功,判断手机号是否在用户表中
    49. if (codeInSession != null && codeInSession.equals(code)) {//登陆成功
    50. LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
    51. queryWrapper.eq(User::getPhone, phone);
    52. User user = userService.getOne(queryWrapper);
    53. if (user == null) {//新用户
    54. //5.如果不在用户表,则自动完成注册
    55. user = new User();
    56. user.setPhone(phone);
    57. user.setStatus(1);
    58. userService.save(user);
    59. }
    60. session.setAttribute("user", user.getId());
    61. //优化:如果用户登陆成功,删除redis缓存的验证码
    62. redisTemplate.delete(phone);
    63. return R.success(user);
    64. }
    65. return R.error("登陆失败");
    66. }
    67. }

    4.3测试

    已经存到redis中

    5.缓存菜品数据

    5.1实现思路

    1、改造DishController的list方法,先从Redis中获取菜品数据,如果有则直接返回,无需查询数据库;如果没有则查询数据库,并将查询到的菜品数据放入Redis。

    2、改造DishController的save和update方法,加入清理缓存的逻辑、

    注意:在使用缓存过程中,要注意保证数据库中的数据和缓存中的数据一致,如果数据库中的数据发生变化,需要及时清理缓存数据。

    5.2代码风暴

    1. @GetMapping("/list")
    2. public R> list(Dish dish) {
    3. List dishDtoList = null;
    4. //动态构造key
    5. String key = "dish_" + dish.getCategoryId() + "_" + dish.getStatus();
    6. //1.先从redis中获取缓存数据
    7. dishDtoList = (List) redisTemplate.opsForValue().get(key);
    8. if (dishDtoList != null) {
    9. //2.如果存在,直接返回,无需查询数据库
    10. return R.success(dishDtoList);
    11. }
    12. //3.如果不存在,查询数据库,再缓存到redis
    13. LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
    14. queryWrapper.eq(dish.getCategoryId() != null, Dish::getCategoryId, dish.getCategoryId());
    15. queryWrapper.eq(Dish::getStatus, 1);
    16. queryWrapper.orderByDesc(Dish::getSort).orderByAsc(Dish::getUpdateTime);
    17. List list = dishService.list(queryWrapper);
    18. dishDtoList = list.stream().map((item) -> {
    19. DishDto dishDto = new DishDto();
    20. //拷贝
    21. BeanUtils.copyProperties(item, dishDto);
    22. Long categoryId = item.getCategoryId();//分类id
    23. Category category = categoryService.getById(categoryId);
    24. if (category != null) {
    25. String categoryName = category.getName();
    26. dishDto.setCategoryName(categoryName);
    27. }
    28. Long dishId = item.getId();
    29. LambdaQueryWrapper queryWrapper1 = new LambdaQueryWrapper<>();
    30. queryWrapper1.eq(DishFlavor::getDishId, dishId);
    31. List dishFlavors = dishFlavorService.list(queryWrapper1);
    32. dishDto.setFlavors(dishFlavors);
    33. return dishDto;
    34. }).collect(Collectors.toList());
    35. //查询完数据库,在将数据缓存到redis
    36. redisTemplate.opsForValue().set(key,dishDtoList,60, TimeUnit.MINUTES);
    37. return R.success(dishDtoList);
    38. }

     5.3测试

    再次查询时就是从redis缓存中获取了

    5.3更新菜品时删除对应的redis缓存 

    1. @PutMapping()
    2. public R put(@RequestBody DishDto dishDto) {
    3. dishService.updateWithFlavor(dishDto);
    4. //清理所有菜品的缓存数据
    5. // Set keys = redisTemplate.keys("dish_*");
    6. // redisTemplate.delete(keys);
    7. //精确清理,清理某个分类下面的缓存
    8. String key="dish_"+dishDto.getCategoryId()+"_1";
    9. redisTemplate.delete(key);
    10. return R.success("修改成功");
    11. }

    5.4添加菜品时删除对应的redis缓存

    1. @PostMapping()
    2. public R save(@RequestBody DishDto dishDto) {
    3. dishService.saveWithFlavor(dishDto);
    4. //清理所有菜品的缓存数据
    5. // Set keys = redisTemplate.keys("dish_*");
    6. // redisTemplate.delete(keys);
    7. //精确清理,清理某个分类下面的缓存
    8. String key="dish_"+dishDto.getCategoryId()+"_1";
    9. redisTemplate.delete(key);
    10. return R.success("新增菜品成功");
    11. }

    6.缓存套餐数据【注解】

    • 1、导入Spring Cache和Redis相关maven坐标
    • 2、在application.yml中配置缓存数据的过期时间
    • 3、在启动类上加入@EnableCaching注解,开启缓存注解功能
    • 4、在SetmealController的list方法上加入@Cacheable注解
    • 5、在SetmealController的save和delete方法上加入CacheEvict注解

    6.1引入依赖 

    1. org.springframework.boot
    2. spring-boot-starter-data-redis
    3. org.springframework.boot
    4. spring-boot-starter-cache

    6.2开启注解缓存

    1. @Slf4j
    2. @SpringBootApplication
    3. @ServletComponentScan
    4. @EnableTransactionManagement
    5. @EnableCaching //开启注解缓存
    6. public class ProductRuijiApplication {
    7. public static void main(String[] args) {
    8. SpringApplication.run(ProductRuijiApplication.class, args);
    9. log.info("程序启动成功");
    10. }
    11. }

    6.3查询套餐时加入缓存

    1. @Cacheable(value = "setmealCache",key = "#setmeal.categoryId+'_'+#setmeal.status")
    2. @GetMapping("/list")
    3. public R> list( Setmeal setmeal) {
    4. LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
    5. queryWrapper.eq(setmeal.getCategoryId() != null, Setmeal::getCategoryId, setmeal.getCategoryId());
    6. queryWrapper.eq(setmeal.getStatus() != null, Setmeal::getStatus, setmeal.getStatus());
    7. queryWrapper.orderByDesc(Setmeal::getUpdateTime);
    8. List list = setmealService.list(queryWrapper);
    9. return R.success(list);
    10. }

    6.4删除套餐时删除缓存

    1. @CacheEvict(value = "setmealCache",allEntries = true)
    2. @DeleteMapping
    3. public R delete(@RequestParam List ids) {
    4. setmealService.removeWithDish(ids);
    5. return R.success("删除套餐成功");
    6. }

  • 相关阅读:
    React-18--css in js
    postman7种断言的使用
    Springboot整合HBase
    以 Golang 为例详解 AST 抽象语法树
    java计算机毕业设计桂林恒保健康防护有限公司官网MyBatis+系统+LW文档+源码+调试部署
    细说react源码中的合成事件
    【flask入门系列】Flask-SQLAlchemy的使用
    css 优惠券样式大全
    学习springboot杂乱无章的笔记
    git clone失败
  • 原文地址:https://blog.csdn.net/dfdg345/article/details/134535951