前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >瑞吉外卖(终章)项目优化

瑞吉外卖(终章)项目优化

作者头像
小沐沐吖
发布2022-09-22 15:28:55
5540
发布2022-09-22 15:28:55
举报
文章被收录于专栏:小沐沐吖小沐沐吖

01、缓存优化

1、环境搭建

01.依赖

代码语言:javascript
复制
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

02.配置文件

代码语言:javascript
复制
spring: 
    redis:
        host: 192.168.136.200
        port: 6379
        password: 131400
        database: 0

03.配置类

代码语言:javascript
复制
package cn.mu00.reggie.config;

import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig extends CachingConfigurerSupport {

    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();

        //默认的Key序列化器为:JdkSerializationRedisSerializer
        redisTemplate.setKeySerializer(new StringRedisSerializer()); // key序列化
        //redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); // value序列化

        redisTemplate.setConnectionFactory(connectionFactory);
        return redisTemplate;
    }
}

2、缓存短信验证码

位置:UserController

代码语言:javascript
复制
@Autowired
private RedisTemplate redisTemplate;

 /**
 * 发送短信验证码
 * @param user
 * @return
 */
@PostMapping("/sendMsg")
public R<String> sendMsg(@RequestBody User user, HttpSession session){

    // 获取手机号
    String phone = user.getPhone();

    if (StringUtils.isNotEmpty(phone)){
        // 生成随机4为验证码
        String code = ValidateCodeUtils.generateValidateCode(4).toString();
        log.info("code={}", code);

        // 调用阿里云提供的短信服务API完成短信发送,为了不浪费钱,注释了,功能不影响
        // SMSUtils.sendMessage("小沐沐吖","SMS_248910220",phone,code);

        // 需要将生成的验证码保存到session
        // session.setAttribute(phone, code);

        // 将生成得验证码缓存发到Redis中,并且设置有效期5分钟
        redisTemplate.opsForValue().set(phone, code, 5, TimeUnit.MINUTES);

        return R.success("手机验证码短信发送成功!");
    }

    return R.error("短信发送失败");
}

/**
 * 移动端用户登录
 * @param user
 * @param session
 * @return
 */
@PostMapping("/login")
public R<User> login(@RequestBody Map map, HttpSession session){
    log.info(map.toString());

    // 获取手机号
    String phone = map.get("phone").toString();

    // 获取验证码
    String code = map.get("code").toString();

    // 从session中获取保存的验证码
    // String codeInSession = (String) session.getAttribute(phone);

    // 从Redis中获取缓存得验证码
    String codeInSession = (String) redisTemplate.opsForValue().get(phone);

    // 进行验证码校验
    if (codeInSession != null && codeInSession.equals(code)){
        // 比对成功,登录成功
        // 判断手机号是否存在(新用户)
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getPhone, phone);
        User user = userService.getOne(queryWrapper);
        if (user == null){
            // 若不存在则添加用户数据
            user = new User();
            user.setPhone(phone);
            userService.save(user);
        }
        session.setAttribute("user", user.getId());

        // 如果用户登录成功,删除Redis中缓存得验证码
        redisTemplate.delete(phone);
        return R.success(user);
    }
    return R.error("登录成功");
}

3、缓存菜品数据

位置:DishController 方法:list

代码语言:javascript
复制
/**
 * 根据条件查询菜品数据
 * @param dish
 * @return
 */
@GetMapping("/list")
public R<List<DishDto>> list(Dish dish){

    List<DishDto> dishDtoList = null;

    String key = "dish" + dish.getCategoryId() + "-" + dish.getStatus();

    // 先从redis中获取缓存数据
    dishDtoList = (List<DishDto>) redisTemplate.opsForValue().get(key);

    if (dishDtoList != null){
        // 存在,直接返回数据
        return R.success(dishDtoList);
    }
    // 不存在,则查询数据库,缓存数据

    // 构造查询条件
    LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper.eq(dish.getCategoryId() != null, Dish::getCategoryId, dish.getCategoryId());
    // 查询状态为 1(起售)
    queryWrapper.eq(Dish::getStatus, 1);

    // 添加排序条件
    queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);

    List<Dish> list = dishService.list(queryWrapper);

    dishDtoList = list.stream().map((item) -> {
        DishDto dishDto = new DishDto();

        BeanUtils.copyProperties(item, dishDto);

        // 分类id
        Long categoryId = item.getCategoryId();
        // 根据id查询分类对象
        Category category = categoryService.getById(categoryId);

        if (category != null){
            String categoryName = category.getName();
            dishDto.setCategoryName(categoryName);
        }
        // 当前菜品id
        Long dishId = item.getId();
        LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(DishFlavor::getDishId, dishId);

        List<DishFlavor> dishFlavorList = dishFlavorService.list(lambdaQueryWrapper);

        dishDto.setFlavors(dishFlavorList);

        return dishDto;
    }).collect(Collectors.toList());

    // 缓存数据
    redisTemplate.opsForValue().set(key, dishDtoList, 60, TimeUnit.MINUTES);

    return R.success(dishDtoList);
}

位置:DishController 方法:save,update 清除缓存

代码语言:javascript
复制
// 清理指定分类下菜品得缓存
String key = "dish_" + dishDto.getCategoryId() + "_1";
redisTemplate.delete(key);

位置:DishController 方法:delete,status 清除缓存

代码语言:javascript
复制
// 清理所有菜品得缓存
Set keys = redisTemplate.keys("dish_*");
redisTemplate.delete(keys);

4、Spring Cache

1、介绍

Spring Cache是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能。

Spring Cache提供了一层抽象,底层可以切换不同的Cache实现。具体就是通过CacheManager接口来统一不同的缓存技术

Spring Cache是SPring提供的各种缓存技术抽象接口

针对不同的缓存技术需要实现不同的CacheManager

CacheManager

描述

EhCacheCacheManager

使用EhCache作为缓存技术

GuavaCacheManager

使用谷歌的GuavaCache作为缓存技术

RedisCacheManager

使用Redis作为缓存技术

2、常用注解

注解

说明

@EnableCaching

开启缓存注解功能

@Cacheable

在方法执行前spring先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;若没有数据,调用方法并将返回值放到缓存中

@CachePut

将方法的返回值放到缓存中

@CacheEvict

将一条或多条数据从缓存中删除

spring boot项目中,使用缓存技术只需在项目中导入相关缓存技术的依赖包,并在启动类上使用@EnableCaching开启缓存支持即可

例如,使用Redis作为缓存技术,只需要导入Spring data Redis的maven坐标即可

5、缓存套餐数据

1、添加依赖

代码语言:javascript
复制
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

2、代码实现

01.在配置文件中添加

代码语言:javascript
复制
spring: 
    cache:
        redis:
            time-to-live: 1800000

02.在启动类添加注解

代码语言:javascript
复制
@EnableCaching

03.R实现序列号接口

代码语言:javascript
复制
public class R<T> implements Serializable{...}

04.位置:SetmealController 方法list

代码语言:javascript
复制
@Cacheable(value = "setmealCache", key = "#setmeal.categoryId + '_' + #setmeal.status")

05.位置:SetmealController 方法:delete、status、save、update 清除所有缓存

代码语言:javascript
复制
@CacheEvict(value = "setmealCache", allEntries = true)
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022 年 08 月,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 01、缓存优化
    • 1、环境搭建
      • 01.依赖
      • 02.配置文件
      • 03.配置类
    • 2、缓存短信验证码
      • 3、缓存菜品数据
        • 4、Spring Cache
          • 1、介绍
          • 2、常用注解
        • 5、缓存套餐数据
          • 1、添加依赖
          • 2、代码实现
      相关产品与服务
      云数据库 Redis
      腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档