目录
2.4、在SetmealController控制类中加入缓存注解
一、环境搭建
1、maven坐标
<!-- redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2、配置文件
spring:
redis:
host: localhost # 本地IP 或是 虚拟机IP
port: 6379
# password: root
database: 0 # 默认使用 0号db
cache:
redis:
time-to-live: 1800000 # 设置缓存数据的过期时间,30分钟
二、缓存短信验证码
1、实现思路
2、代码改造
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {
@Autowired
private UserService userService;
@Autowired
private StringRedisTemplate stringRedisTemplate;
/**
* 发送邮箱短信验证码
* @param user
* @return
*/
@PostMapping("/sendMsg")
public R<String> sendMsg(@RequestBody User user, HttpSession session){
//获取邮箱
String phone = user.getPhone();
if(StringUtils.isNotEmpty(phone)){
//发送验证码到邮箱
String code = userService.send(user);
//需要将生成的验证码保存到Session
// session.setAttribute(phone,code);
//将生成的验证码缓存到redis中,并且设置有效期为5分钟
stringRedisTemplate.opsForValue().set(phone,code,5, TimeUnit.MINUTES);
return R.success("手机验证码短信发送成功");
}
return R.error("短信发送失败");
}
/**
* 移动端登录
* @param map
* @param session
* @return
*/
@PostMapping("/login")
public R<User> sendMsg(@RequestBody Map map, HttpSession session){
//获取邮箱
String phone = map.get("phone").toString();
//获取验证码
String code = map.get("code").toString();
//从Session中获取保存的验证码
// Object codeInSession = session.getAttribute(phone);
//从redis中获取缓存的验证码
String s = stringRedisTemplate.opsForValue().get(phone);
//进行验证码的比对(页面提交的验证码和Session中保存的验证码比对)
if(s != null && s.equals(code)){
//如果能够比对成功,说明登录成功
LambdaQueryWrapper<User> eq = Wrappers.lambdaQuery(User.class)
.eq(User::getPhone, phone);
User user = userService.getOne(eq);
if(user == null){
//判断当前邮箱账号对应的用户是否为新用户,如果是新用户就自动完成注册
user = new User();
user.setPhone(phone);
user.setStatus(1);
userService.save(user);
}
session.setAttribute("user",user.getId());
//如果用户登录成功,删除Redis中缓存的验证码
stringRedisTemplate.delete(phone);
return R.success(user);
}
return R.error("登录失败");
}
}
三、缓存菜品数据
1、实现思路
2、代码改造
@RestController
@Slf4j
@RequestMapping("/dish")
public class DishController {
@Autowired
private DishService dishService;
@Autowired
private DishFlavorService dishFlavorService;
@Autowired
private CategoryService categoryService;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private RedisTemplate redisTemplate;
/**
* 分页查找
* @param page
* @param pageSize
* @param name
* @return
*/
@GetMapping("/page")
public R<Page> page(int page,int pageSize,String name){
//构造分页对象
Page<Dish> dishPage = new Page<>(page, pageSize);
Page<DishDto> dishDtoPage = new Page<>();
//条件构造器:过滤和排序
LambdaQueryWrapper<Dish> like = Wrappers.lambdaQuery(Dish.class)
.like(StringUtils.isNotEmpty(name),Dish::getName, name)
.orderByDesc(Dish::getUpdateTime);
//执行分页查询
dishService.page(dishPage,like);
//对象拷贝:将第一个参数对象,拷贝到第二个参数的对象中,第三个参数表示忽略拷贝的内容
BeanUtils.copyProperties(dishPage,dishDtoPage,"records");
List<Dish> records = dishPage.getRecords();
List<DishDto> list = records.stream().map((item) -> {
DishDto dishDto = new DishDto();
BeanUtils.copyProperties(item,dishDto);
Long categoryId = item.getCategoryId(); //分类id
//根据id查询分类对象
Category byId = categoryService.getById(categoryId);
if(byId != null){
String byIdName = byId.getName();
dishDto.setCategoryName(byIdName);
}
return dishDto;
}).collect(Collectors.toList());
dishDtoPage.setRecords(list);
return R.success(dishDtoPage);
}
/**
* 新增菜品
* @param dishDto
* @return
*/
@PostMapping
public R<String> save(@RequestBody DishDto dishDto){
dishService.saveWithFlavor(dishDto);
//清理所有菜品的缓存数据
// Set<String> keys = stringRedisTemplate.keys("dish_*");
// stringRedisTemplate.delete(keys);
//清理某个分类下面的菜品缓存数据
String key = "dish_" + dishDto.getCategoryId() + "_1";
stringRedisTemplate.delete(key);
return R.success("新增菜品成功");
}
/**
* 根据id查询菜品信息和对应的口味信息
* @param id
* @return
*/
@GetMapping("/{id}")
public R<DishDto> get(@PathVariable Long id){
DishDto byIdWithFlavor = dishService.getByIdWithFlavor(id);
return R.success(byIdWithFlavor);
}
/**
* 修改菜品
* @return
*/
@PutMapping
public R<String> update(@RequestBody DishDto dishDto){
dishService.updateWithFlavor(dishDto);
//清理某个分类下面的菜品缓存数据
String key = "dish_" + dishDto.getCategoryId() + "_1";
stringRedisTemplate.delete(key);
return R.success("修改菜品成功");
}
/**
* 根据条件查询对应的菜品数据
* @param dish
* @return
*/
@GetMapping("list")
public R<List<DishDto>> list(Dish dish){
List<DishDto> collect = null;
//dish_1397844391040167938_1(动态构造key)
String key = "dish_" + dish.getCategoryId() + "_" + dish.getStatus();
//先从redis中获取缓存数据
collect = JSON.parseArray(stringRedisTemplate.opsForValue().get(key), DishDto.class);
if(collect != null){
//如果存在,直接返回,无需查询数据库
return R.success(collect);
}
//构造查询条件,并添加排序条件,再查询状态为1(起售状态)的菜品
LambdaQueryWrapper<Dish> dishLambdaQueryWrapper = Wrappers.lambdaQuery(Dish.class)
.eq(dish.getCategoryId() != null, Dish::getCategoryId, dish.getCategoryId())
.eq(Dish::getStatus,1)
.orderByAsc(Dish::getSort)
.orderByDesc(Dish::getUpdateTime);
List<Dish> list = dishService.list(dishLambdaQueryWrapper);
collect = list.stream().map((item) -> {
DishDto dishDto = new DishDto();
BeanUtils.copyProperties(item, dishDto);
Long categoryId = item.getCategoryId(); //分类id
//根据id查询分类对象
Category byId = categoryService.getById(categoryId);
if (byId != null) {
String byIdName = byId.getName();
dishDto.setCategoryName(byIdName);
}
//当前菜品的id
Long dishId = item.getId();
//获取当前菜品口味
LambdaQueryWrapper<DishFlavor> eq = Wrappers.lambdaQuery(DishFlavor.class)
.eq(DishFlavor::getDishId, dishId);
List<DishFlavor> dishFlavorsList = dishFlavorService.list(eq);
dishDto.setFlavors(dishFlavorsList);
return dishDto;
}).collect(Collectors.toList());
//如果不存在,需要查询数据库,将查询到的菜品数据缓存到Redis
stringRedisTemplate.opsForValue().set(key, JSON.toJSONString(collect),60, TimeUnit.MINUTES);
return R.success(collect);
}
/**
* 菜品起售停售功能 status:0 停售 1 起售
* @param ids
* @return
*/
@PostMapping("/status/{status}")
public R<String> status(@PathVariable int status,@RequestParam List<Long> ids){
ids.stream().forEach((item) -> {
LambdaUpdateWrapper<Dish> set = Wrappers.lambdaUpdate(Dish.class)
.eq(item != null, Dish::getId, item);
if(status == 0){
set.ne(Dish::getStatus,0).set(Dish::getStatus, 0);
dishService.update(set);
}else{
set.ne(Dish::getStatus,1).set(Dish::getStatus, 1);
dishService.update(set);
}
Dish byId = dishService.getById(item);
//清理某个分类下面的菜品缓存数据
String key = "dish_" + byId.getCategoryId() + "_1";
if(stringRedisTemplate.opsForValue().get(key) != null) {
stringRedisTemplate.delete(key);
}
});
return R.success("菜品已更改为停售");
}
/**
* 菜品删除
* @param ids
* @return
*/
@DeleteMapping
public R<String> delete(@RequestParam List<Long> ids){
ids.stream().forEach((item) -> {
Dish byId = dishService.getById(item);
//清理某个分类下面的菜品缓存数据
String key = "dish_" + byId.getCategoryId() + "_1";
if(stringRedisTemplate.opsForValue().get(key) != null) {
stringRedisTemplate.delete(key);
}
dishService.removeById(item);
});
return R.success("删除菜品成功");
}
}
四、SpringCache
1、介绍
2、常用注解
3、注解的使用:
4、spring boot中使用spring cache
五、缓存套餐数据
1、实现思路
2、代码改造
2.1、导入坐标
<!-- redis-->
<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>
<version>2.7.3</version>
</dependency>
2.2、配置文件
spring
redis:
host: localhost # 本地IP 或是 虚拟机IP
port: 6379
# password: root
database: 0 # 默认使用 0号db
cache:
redis:
time-to-live: 1800000 # 设置缓存数据的过期时间,30分钟
2.3、在启动类加入注解,开启缓存注解功能
@SpringBootApplication
@ServletComponentScan
@EnableTransactionManagement
@MapperScan(basePackages = "com.itheima.reggie.mapper")
@EnableCaching //开启缓存注解
public class ReggieApplication {
public static void main(String[] args) {
SpringApplication.run(ReggieApplication.class, args);
}
}
2.4、在SetmealController控制类中加入缓存注解
/**
* 套餐管理
*/
@Slf4j
@RestController
@RequestMapping("/setmeal")
public class SetmealController {
@Autowired
private SetmealService setmealService;
@Autowired
private SetmealDishService setmealDishService;
@Autowired
private CategoryService categoryService;
/**
* 套餐分页查询
* @param page
* @param pageSize
* @param name
* @return
*/
@GetMapping("/page")
public R<Page> page(int page, int pageSize, String name){
//构造分页对象
Page<Setmeal> setmealPage = new Page<>(page, pageSize);
Page<SetmealDto> SetmealDtoPage = new Page<>();
//条件构造器:过滤和排序
LambdaQueryWrapper<Setmeal> like = Wrappers.lambdaQuery(Setmeal.class)
.like(StringUtils.isNotEmpty(name),Setmeal::getName, name)
.orderByDesc(Setmeal::getUpdateTime);
//执行分页查询
setmealService.page(setmealPage,like);
//对象拷贝:将第一个参数对象,拷贝到第二个参数的对象中,第三个参数表示忽略拷贝的内容
BeanUtils.copyProperties(setmealPage,SetmealDtoPage,"records");
List<Setmeal> records = setmealPage.getRecords();
List<SetmealDto> list = records.stream().map((item) -> {
SetmealDto setmealDto = new SetmealDto();
BeanUtils.copyProperties(item,setmealDto);
Long categoryId = item.getCategoryId(); //分类id
//根据id查询分类对象
Category byId = categoryService.getById(categoryId);
if(byId != null){
String byIdName = byId.getName();
setmealDto.setCategoryName(byIdName);
}
return setmealDto;
}).collect(Collectors.toList());
SetmealDtoPage.setRecords(list);
return R.success(SetmealDtoPage);
}
/**
* 新增套餐
* @param setmealDto
* @return
*/
@CacheEvict(value = "setmealCache",allEntries = true)
@PostMapping
public R<String> save(@RequestBody SetmealDto setmealDto){
setmealService.saveWithDish(setmealDto);
return R.success("新增套餐成功");
}
/**
* 根据条件查询套餐数据
* @return
*/
@Cacheable(value = "setmealCache",key = "#setmeal.categoryId + '_' + #setmeal.status")
@GetMapping("list")
public R<List<Setmeal>> list(Setmeal setmeal){
LambdaQueryWrapper<Setmeal> eq = Wrappers.lambdaQuery(Setmeal.class)
.eq(setmeal.getCategoryId() != null,Setmeal::getCategoryId,setmeal.getCategoryId())
.eq(setmeal.getStatus() != null,Setmeal::getStatus, setmeal.getStatus())
.orderByDesc(Setmeal::getUpdateTime);
List<Setmeal> list = setmealService.list(eq);
return R.success(list);
}
/**
* 删除套餐
* @param ids
* @return
*/
//allENtries = true表示删除全部
@CacheEvict(value = "setmealCache",allEntries = true)
@DeleteMapping
public R<String> delete(@RequestParam List<Long> ids){
setmealService.removeWithDish(ids);
return R.success("套餐数据删除成功");
}
/**
* 套餐起售停售功能 status:0 停售 1 起售
* @param ids
* @return
*/
@CacheEvict(value = "setmealCache",allEntries = true)
@PostMapping("/status/{status}")
public R<String> status(@PathVariable int status,@RequestParam List<Long> ids){
ids.stream().forEach((item) -> {
LambdaUpdateWrapper<Setmeal> set = Wrappers.lambdaUpdate(Setmeal.class)
.eq(item != null, Setmeal::getId, item);
if(status == 0){
set.ne(Setmeal::getStatus,0).set(Setmeal::getStatus, 0);
setmealService.update(set);
}else{
set.ne(Setmeal::getStatus,1).set(Setmeal::getStatus, 1);
setmealService.update(set);
}
});
return R.success("菜品已更改为停售");
}
}