苍穹外卖实操笔记六---缓存商品,购物车功能
一.缓存菜品
可以使用redis进行缓存;另外,在实现缓存套餐时可以使用spring cache提高开发效率;
通过缓存数据,降低访问数据库的次数;
使用的缓存逻辑:
1.每个分类下保存一份缓存数据;就是一对key-value(dish_1表示属于分类1的菜品列表)
2.数据库中的菜品有变更时,及时清理缓存数据;
1.1缓存菜品数据;直接使用redis即可;
java
@RestController("userDishController")
@RequestMapping("/user/dish")
@Slf4j
@Api(tags = "C端-菜品浏览接口")
public class DishController {
@Autowired
private DishService dishService;
@Autowired
private RedisTemplate redisTemplate;
/**
* 根据分类id查询菜品
*
* @param categoryId
* @return
*/
@GetMapping("/list")
@ApiOperation("根据分类id查询菜品")
public Result<List<DishVO>> list(Long categoryId) {
//构造redis中的key
String key="dish_"+categoryId;
//查询redis中是否存在菜品
List<DishVO> dishVOList = (List<DishVO>) redisTemplate.opsForValue().get(key);
//如果存在,直接返回,无需访问数据库
if (dishVOList!=null&&dishVOList.size()>0){
return Result.success(dishVOList);
}
Dish dish = new Dish();
dish.setCategoryId(categoryId);
dish.setStatus(StatusConstant.ENABLE);//查询起售中的菜品
//如果不存在,查询数据库,将查询到数据放入redis中
dishVOList = dishService.listWithFlavor(dish);
redisTemplate.opsForValue().set(key,dishVOList);
return Result.success(dishVOList);
}
}
1.2清理缓存菜品数据
新增菜品,修改菜品,批量删除菜品,起售,停售菜品都需要清理缓存数据;
二.缓存购物车
2.1 spring-cache
在启动类上开启缓存注解功能
java
@SpringBootApplication
@EnableTransactionManagement //开启注解方式的事务管理
@Slf4j
@EnableCaching //开启缓存注解功能
public class SkyApplication {
public static void main(String[] args) {
SpringApplication.run(SkyApplication.class, args);
log.info("server started");
}
@CachePut注解
将方法的返回值放到缓缓存中,Spring Cache有自己的命名规则:
比如@CachePut(cacheNames="userCache" , key="abc"),则缓存中的Key就是userCache::abc
另外,如果需要动态的进行拼接Key值可以使用Sring el表达式语言,从参数或返回值中获取内容;
java
//1.从参数中动态获取,key=后变的参数要与函数的形参一致;
@PostMapping
@CachePut(cacheNames="userCache" , key="#user.id")
public User save(@RequestBody User user){
userSerivce.insert(user);
return user;
}
//2.从返回值中动态获取,key=后边是固定的result
@PostMapping
@CachePut(cacheNames="userCache" , key="#result.id")
public User save(@RequestBody User user){
userSerivce.insert(user);
return user;
}
//3.从多个参数中动态获取,key=后边是#p0(表示第一个参数);#p1(表示第2个参数)
@PostMapping
@CachePut(cacheNames="userCache" , key="#p0.id")
public User save(@RequestBody User user,String dishName){
userSerivce.insert(user);
return user;
}
@Cacheable注解
用法大致宇@CachePut相同,效果不同,会先到redis中查询有无结果,如果有则不调用下边的方法,如果没有才调用,并随后将被调用的方法的返回值加入redis中;
java
@PostMapping
@Cacheable(cacheNames="userCache" , key="#user.id")
public User save(@RequestBody User user){
userSerivce.insert(user);
return user;
}
@CacheEvict注解
清理缓存数据
java
//该代码一次只清理一条数据,删除指定key的键值对;
@PostMapping
@CacheEvict(cacheNames="userCache" , key="#user.id")
public User save(@RequestBody User user){
userSerivce.insert(user);
return user;
}
//该代码一次能够清理所有的数据;
@PostMapping
@CacheEvict(cacheNames="userCache" , allEntries=true)
public User save(@RequestBody User user){
userSerivce.insert(user);
return user;
}
2.2 在项目中使用spring-cache
1.导入maven坐标;
xml
<!--redis对应的坐标-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--Spring Cache对应的坐标-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
2.在启动类上加上@EnableCaching
java
@SpringBootApplication
@EnableTransactionManagement //开启注解方式的事务管理
@Slf4j
@EnableCaching //开启缓存注解功能
public class SkyApplication {
public static void main(String[] args) {
SpringApplication.run(SkyApplication.class, args);
log.info("server started");
}
}
3.在用户端SetmealController的上list方法上加上@Cacheable注解
java
//当用户获取套餐列表时会将套餐内容设置到redis中
@GetMapping("/list")
@ApiOperation("根据分类id查询套餐")
@Cacheable(cacheNames = "setmealCache",key = "#categoryId") //key
public Result<List<Setmeal>> list(Long categoryId) {
Setmeal setmeal = new Setmeal();
setmeal.setCategoryId(categoryId);
setmeal.setStatus(StatusConstant.ENABLE);
List<Setmeal> list = setmealService.list(setmeal);
return Result.success(list);
}
4.在管理端SetmealController的save,delete,update,startOrStop等方法上加上CacheEvict注解;
java
//新增时,删除指定套餐;
@PostMapping
@ApiOperation("新增套餐")
@CacheEvict(cacheNames = "setmealCache",key = "#setmealDTO.categoryId")
public Result save(@RequestBody SetmealDTO setmealDTO) {
setmealService.saveWithDish(setmealDTO);
return Result.success();
}
//批量删除套餐时,删除缓存中所有的套餐数据;
@DeleteMapping
@ApiOperation("批量删除套餐")
@CacheEvict(cacheNames = "setmealCache",allEntries = true)
public Result delete(@RequestParam List<Long> ids){
setmealService.deleteBatch(ids);
return Result.success();
}