在java中操作Redis
Controller
package com.zsh.controller.user; @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(Integer categoryId) { // 查询 List<DishVO> dishVO = dishService.findByCategoryId(categoryId); // 返回结果 return Result.success(dishVO); } }
ServiceImpl
package com.zsh.service.impl; import java.util.List; import java.util.Set; @Service public class DishServiceImpl implements DishService { @Autowired private DishMapper dishMapper; @Autowired private DishFlavorMapper dishFlavorMapper; @Autowired private SetmealDishMapper setmealDishMapper; @Autowired private RedisTemplate redisTemplate; /** * 新增菜品 * @param dishDTO */ @Transactional @Override public void addDish(DishDTO dishDTO) { // 创建新增需要用到的对象 Dish dish = new Dish(); // 拷贝对象 BeanUtils.copyProperties(dishDTO,dish); // 新增菜品 dishMapper.addDish(dish); // 获取insert语句生成的主键值 Long dishId = dish.getId(); // 取出前台传过来的口味表数据 List<DishFlavor> flavors = dishDTO.getFlavors(); // 判断前端前台是否添加了口味表数据 if(flavors != null && flavors.size() > 0){ flavors.forEach(flavor -> { flavor.setDishId(dishId); }); } // 新增口味 dishFlavorMapper.addDishFlavor(flavors); } /** * 菜品分页查询 * @param dishPageQueryDTO * @return */ @Override public PageResult pageDish(DishPageQueryDTO dishPageQueryDTO) { // 开启分页查询 PageHelper.startPage(dishPageQueryDTO.getPage(),dishPageQueryDTO.getPageSize()); // 条件查询 List<DishVO> list = dishMapper.pageDish(dishPageQueryDTO); // 获取分页结果 Page page = (Page) list; // 封装结果 PageResult pageResult = new PageResult(page.getTotal(),page.getResult()); return pageResult; } /** * 根据id查询菜品 * @param id * @return */ @Override public DishVO findByIdDish(Integer id) { // 查询菜品 Dish dish = dishMapper.findById(id); // 根据菜品id查询口味 List<DishFlavor> flavors = dishFlavorMapper.findByDishId(id); // 封装返回结果 DishVO dishVO = new DishVO(); // 拷贝对象 BeanUtils.copyProperties(dish,dishVO); // 给对象的属性赋值 dishVO.setFlavors(flavors); // 返回结果 return dishVO; } /** * 修改菜品 * @param dishDTO */ @Override @Transactional public void updateDish(DishDTO dishDTO) { // 创建修改需要用到的对象 Dish dish = new Dish(); // 拷贝对象 BeanUtils.copyProperties(dishDTO,dish); // 修改菜品 dishMapper.updateDish(dish); // 删除口味 dishFlavorMapper.deleteByDishId(dishDTO.getId()); // 取出修改后的口味数组 List<DishFlavor> flavors = dishDTO.getFlavors(); // 判断口味是否修改 if(flavors != null && flavors.size()>0){ // 遍历将id放数组 flavors.forEach(flavor -> { flavor.setDishId(dishDTO.getId()); }); // 添加新的口味 dishFlavorMapper.addDishFlavor(flavors); } //将所有的菜品缓存数据清理掉,所有以dish_开头的key cleanCache("dish_*"); } /** * 批量删除菜品 * @param ids */ @Transactional @Override public void deleteDish(List<Integer> ids) { // 判断菜品是否起售,如果起售则不删除 for (Integer id : ids) { // 根据id查询菜品 Dish dish = dishMapper.findById(id); // 判断菜品是否起售 if (dish.getStatus() == StatusConstant.ENABLE) { throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE); } } // TODO这里要判断菜品是否被套餐关联,关联则不能删除 List<Setmeal> list = setmealDishMapper.findByDishId(ids); if(list != null && list.size() > 0){ throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL); } for (Integer id : ids) { // 删除菜品 dishMapper.deleteById(id); // 删除口味 dishFlavorMapper.deleteByDishId(Long.valueOf(id)); } // 将所有的菜品缓存数据清理掉,所有以dish_开头的key cleanCache("dish_*"); } /** * 菜品起售、停售 * @param status * @param id */ @Override public void okAndNo(Integer status, Integer id) { // 创建修改要用到的对象 Dish dish = new Dish(); // 设置状态 dish.setStatus(status); // 设置id dish.setId(Long.valueOf(id)); // 修改 dishMapper.updateDish(dish); // 将所有的菜品缓存数据清理掉,所有以dish_开头的key cleanCache("dish_*"); } /** * 根据分类id查询菜品 * @param categoryId * @return */ @Override public List<DishVO> findByCategoryId(Integer categoryId) { // 构造redis中的key,规则dish_分类id String key = "dish_"+ categoryId; // 查询redis中是否存在菜品数据 List<DishVO> redisList = (List<DishVO>) redisTemplate.opsForValue().get(key); // 判断redis数据库是否存在数据,存在则无序查询mysql if(redisList != null && redisList.size() > 0){ return redisList; } // 查询MySQL数据库 List<DishVO> list = dishMapper.findByCategoryId(categoryId); // 获取菜品id for (DishVO dish : list) { // 根据菜品id查询菜品口味 List<DishFlavor> disFlavor = dishFlavorMapper.findByDishId(Math.toIntExact(dish.getId())); // 将口味放入对应的菜品 dish.setFlavors(disFlavor); } // 如果redis数据库中没有查到数据,就把查到的数据保存到数据库 redisTemplate.opsForValue().set(key,list); // 返回结果 return list; } /** * 清理缓存数据 * @param pattern */ private void cleanCache(String pattern){ Set keys = redisTemplate.keys(pattern); redisTemplate.delete(keys); } }
SpringCache
Spring Cache 是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能。
1、 导入Spring Cache和Redis相关maven坐标
<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、在启动类上加入@EnableCaching注解,开启缓存注解功能
package com.zsh; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; import org.springframework.transaction.annotation.EnableTransactionManagement; @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注解
/** * 条件查询 * * @param categoryId * @return */ @GetMapping("/list") @ApiOperation("根据分类id查询套餐") @Cacheable(cacheNames = "setmealCache",key = "#categoryId") //key: setmealCache::100 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注解
/** * 新增套餐 * * @param setmealDTO * @return */ @PostMapping @ApiOperation("新增套餐") @CacheEvict(cacheNames = "setmealCache",key = "#setmealDTO.categoryId")//key: setmealCache::100 public Result save(@RequestBody SetmealDTO setmealDTO) { setmealService.saveWithDish(setmealDTO); return Result.success(); } /** * 批量删除套餐 * * @param ids * @return */ @DeleteMapping @ApiOperation("批量删除套餐") @CacheEvict(cacheNames = "setmealCache",allEntries = true) public Result delete(@RequestParam List<Long> ids) { setmealService.deleteBatch(ids); return Result.success(); } /** * 修改套餐 * * @param setmealDTO * @return */ @PutMapping @ApiOperation("修改套餐") @CacheEvict(cacheNames = "setmealCache",allEntries = true) public Result update(@RequestBody SetmealDTO setmealDTO) { setmealService.update(setmealDTO); return Result.success(); } /** * 套餐起售停售 * * @param status * @param id * @return */ @PostMapping("/status/{status}") @ApiOperation("套餐起售停售") @CacheEvict(cacheNames = "setmealCache",allEntries = true) public Result startOrStop(@PathVariable Integer status, Long id) { setmealService.startOrStop(status, id); return Result.success(); }