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、缓存短信验证码
代码语言:javascript复制位置:
UserController
@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、缓存菜品数据
代码语言:javascript复制位置:
DishController
方法:list
/**
* 根据条件查询菜品数据
* @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);
}
代码语言:javascript复制位置:
DishController
方法:save,update
清除缓存
// 清理指定分类下菜品得缓存
String key = "dish_" dishDto.getCategoryId() "_1";
redisTemplate.delete(key);
代码语言:javascript复制位置:
DishController
方法:delete,status
清除缓存
// 清理所有菜品得缓存
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、代码实现
代码语言:javascript复制01.在配置文件中添加
spring:
cache:
redis:
time-to-live: 1800000
代码语言:javascript复制02.在启动类添加注解
@EnableCaching
代码语言:javascript复制03.
R
实现序列号接口
public class R<T> implements Serializable{...}
代码语言:javascript复制04.位置:
SetmealController
方法list
@Cacheable(value = "setmealCache", key = "#setmeal.categoryId '_' #setmeal.status")
代码语言:javascript复制05.位置:
SetmealController
方法:delete、status、save
、update 清除所有缓存
@CacheEvict(value = "setmealCache", allEntries = true)