• 【java】【项目实战】[外卖九]项目优化(缓存)


    目录

    一、问题说明

    二、环境搭建

    2.1 Git管理代码

    2.1.1 创建本地仓库

    2.1.2 创建远程仓库

    2.1.3 创建分支--》推送到远程仓库

    2.2 maven坐标

    2.3 配置文件application.yml

    2.4 配置类RedisConfig

    三、缓存短信验证码

    3.1 实现思路

    3.2 代码改造

    3.2.1 UserController

    3.3 功能测试

    四、缓存菜品数据

    4.1 实现思路

    4.2 代码改造

    4.2.1 第一步改造DishController 中list方法

    4.2.2 第三步改造DishController中的save和update方法 

    4.3 功能测试

    五、Spring Cache

    5.1 Spring Cache介绍

    5.2 Spring Cache常用注解

    5.3 Spring Cache使用方式

     5.3.1 pom

    六、缓存套餐数据

    6.1 实现思路

    6.2 代码改造

     6.2.1 pom 坐标

    6.2.2 application.yml配置缓存数据过期时间

    6.2.3 开启缓存注解功能 ReggieApplication

     6.2.4  R实现 Serializable 接口

     6.2.5 在SetmealController的list方法加入@Cacheable注解

    6.2.6 在SetmealController的delete方法加入@CacheEvict注解

    6.2.7 在SetmealController的save方法加入@CacheEvict注解

    6.3 功能测试


    前言:使用缓存进行项目优化

    一、问题说明

    二、环境搭建

    2.1 Git管理代码

    2.1.1 创建本地仓库

    2.1.2 创建远程仓库

    略。。后续都省略

    2.1.3 创建分支--》推送到远程仓库

    2.2 maven坐标

    1. <dependency>
    2. <groupId>org.springframework.bootgroupId>
    3. <artifactId>spring-boot-starter-data-redisartifactId>
    4. dependency>

    2.3 配置文件application.yml

    1. server:
    2. port: 8080
    3. spring:
    4. application:
    5. # 应用名称 可选
    6. name: reggie_take_out_spuer
    7. datasource:
    8. druid:
    9. driver-class-name: com.mysql.cj.jdbc.Driver
    10. url: jdbc:mysql://localhost:3306/reggie?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
    11. username: rot
    12. password: ru
    13. redis:
    14. host: 127.0.0.1
    15. port: 6379
    16. password: 123
    17. database: 0
    18. mybatis-plus:
    19. configuration:
    20. #在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射
    21. map-underscore-to-camel-case: true
    22. log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    23. global-config:
    24. db-config:
    25. id-type: ASSIGN_ID
    26. # 文件上传目录
    27. reggie:
    28. path: D:\images\

    2.4 配置类RedisConfig

    1. package com.runa.reggie.config;
    2. import org.springframework.cache.annotation.CachingConfigurerSupport;
    3. import org.springframework.context.annotation.Bean;
    4. import org.springframework.context.annotation.Configuration;
    5. import org.springframework.data.redis.connection.RedisConnectionFactory;
    6. import org.springframework.data.redis.core.RedisTemplate;
    7. import org.springframework.data.redis.serializer.StringRedisSerializer;
    8. @Configuration
    9. public class RedisConfig extends CachingConfigurerSupport {
    10. @Bean
    11. public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) {
    12. RedisTemplate redisTemplate = new RedisTemplate<>();
    13. //默认的Key序列化器为:JdkSerializationRedisSerializer
    14. redisTemplate.setKeySerializer(new StringRedisSerializer());
    15. redisTemplate.setConnectionFactory(connectionFactory);
    16. return redisTemplate;
    17. }
    18. }

    三、缓存短信验证码

    3.1 实现思路

    3.2 代码改造

    3.2.1 UserController

    1. package com.runa.reggie.controller;
    2. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    3. import com.runa.reggie.common.R;
    4. import com.runa.reggie.entity.User;
    5. import com.runa.reggie.service.UserService;
    6. import com.runa.reggie.utils.SMSUtils;
    7. import com.runa.reggie.utils.ValidateCodeUtils;
    8. import lombok.extern.slf4j.Slf4j;
    9. import org.apache.commons.lang.StringUtils;
    10. import org.springframework.beans.factory.annotation.Autowired;
    11. import org.springframework.data.redis.core.RedisTemplate;
    12. import org.springframework.web.bind.annotation.PostMapping;
    13. import org.springframework.web.bind.annotation.RequestBody;
    14. import org.springframework.web.bind.annotation.RequestMapping;
    15. import org.springframework.web.bind.annotation.RestController;
    16. import javax.servlet.http.HttpSession;
    17. import java.util.Map;
    18. import java.util.concurrent.TimeUnit;
    19. @RestController
    20. @RequestMapping("/user")
    21. @Slf4j
    22. public class UserController {
    23. @Autowired
    24. private UserService userService;
    25. @Autowired
    26. private RedisTemplate redisTemplate;
    27. /**
    28. * 发送手机短信验证码
    29. * @param user
    30. * @return
    31. */
    32. @PostMapping("/sendMsg")
    33. public R sendMsg(@RequestBody User user, HttpSession session){
    34. //获取手机号
    35. String phone = user.getPhone();
    36. if(StringUtils.isNotEmpty(phone)){
    37. //生成随机的4位验证码
    38. String code = ValidateCodeUtils.generateValidateCode(4).toString();
    39. log.info("code={}",code);
    40. //调用阿里云提供的短信服务API完成发送短信
    41. //SMSUtils.sendMessage("瑞吉外卖","",phone,code);
    42. //需要将生成的验证码保存到Session
    43. // session.setAttribute(phone,code);
    44. // 将生成的验证码缓存到Redis中,并且设置有效期为5分钟
    45. redisTemplate.opsForValue().set(phone,code,5, TimeUnit.MINUTES);
    46. return R.success("手机验证码短信发送成功");
    47. }
    48. return R.error("短信发送失败");
    49. }
    50. /**
    51. * 移动端用户登录
    52. * @param map
    53. * @param session
    54. * @return
    55. */
    56. @PostMapping("/login")
    57. public R login(@RequestBody Map map, HttpSession session){
    58. log.info(map.toString());
    59. //获取手机号
    60. String phone = map.get("phone").toString();
    61. //获取验证码
    62. String code = map.get("code").toString();
    63. //从Session中获取保存的验证码
    64. // Object codeInSession = session.getAttribute(phone);
    65. //从redis中获取缓存的验证码
    66. Object codeInSession = redisTemplate.opsForValue().get(phone);
    67. //进行验证码的比对(页面提交的验证码和Session中保存的验证码比对)
    68. if(codeInSession != null && codeInSession.equals(code)){
    69. //如果能够比对成功,说明登录成功
    70. LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
    71. queryWrapper.eq(User::getPhone,phone);
    72. User user = userService.getOne(queryWrapper);
    73. if(user == null){
    74. //判断当前手机号对应的用户是否为新用户,如果是新用户就自动完成注册
    75. user = new User();
    76. user.setPhone(phone);
    77. user.setStatus(1);
    78. userService.save(user);
    79. }
    80. session.setAttribute("user",user.getId());
    81. // 如果用户登录成功,删除redis缓存的验证码
    82. redisTemplate.delete(phone);
    83. return R.success(user);
    84. }
    85. return R.error("登录失败");
    86. }
    87. }

    3.3 功能测试

    启动后端服务、启动redis

    http://localhost:8080/front/page/login.html

    四、缓存菜品数据

    4.1 实现思路

    4.2 代码改造

    4.2.1 第一步改造DishController 中list方法

    1. package com.runa.reggie.controller;
    2. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    3. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
    4. import com.runa.reggie.common.R;
    5. import com.runa.reggie.dto.DishDto;
    6. import com.runa.reggie.entity.Category;
    7. import com.runa.reggie.entity.Dish;
    8. import com.runa.reggie.entity.DishFlavor;
    9. import com.runa.reggie.service.CategoryService;
    10. import com.runa.reggie.service.DishFlavorService;
    11. import com.runa.reggie.service.DishService;
    12. import lombok.extern.slf4j.Slf4j;
    13. import org.springframework.beans.BeanUtils;
    14. import org.springframework.beans.factory.annotation.Autowired;
    15. import org.springframework.data.redis.core.RedisTemplate;
    16. import org.springframework.web.bind.annotation.*;
    17. import java.util.List;
    18. import java.util.concurrent.TimeUnit;
    19. import java.util.stream.Collectors;
    20. /**
    21. * 菜品管理
    22. */
    23. @RestController
    24. @RequestMapping("/dish")
    25. @Slf4j
    26. public class DishController {
    27. @Autowired
    28. private DishService dishService;
    29. @Autowired
    30. private DishFlavorService dishFlavorService;
    31. @Autowired
    32. private CategoryService categoryService;
    33. @Autowired
    34. private RedisTemplate redisTemplate;
    35. /**
    36. * 新增菜品
    37. * @param dishDto
    38. * @return
    39. */
    40. @PostMapping
    41. public R save(@RequestBody DishDto dishDto){
    42. log.info(dishDto.toString());
    43. dishService.saveWithFlavor(dishDto);
    44. return R.success("新增菜品成功");
    45. }
    46. @GetMapping("/page")
    47. public R page(int page, int pageSize, String name){
    48. // 构造分页构造器对象
    49. Page pageInfo = new Page<>(page, pageSize);
    50. Page dishDtoPage = new Page<>();
    51. //条件构造器
    52. LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
    53. // 添加过滤条件
    54. queryWrapper.like(name != null,Dish::getName,name);
    55. // 添加排序条件
    56. queryWrapper.orderByDesc(Dish::getUpdateTime);
    57. //执行分页查询
    58. dishService.page(pageInfo,queryWrapper);
    59. // 对象拷贝
    60. BeanUtils.copyProperties(pageInfo, dishDtoPage,"records");
    61. List records = pageInfo.getRecords();
    62. List list = records.stream().map((item) -> {
    63. DishDto dishDto = new DishDto();
    64. BeanUtils.copyProperties(item,dishDto);
    65. Long categoryId = item.getCategoryId();// 分类id
    66. Category category = categoryService.getById(categoryId);
    67. String categoryName = category.getName();
    68. dishDto.setCategoryName(categoryName);
    69. return dishDto;
    70. }).collect(Collectors.toList());
    71. dishDtoPage.setRecords(list);
    72. return R.success(dishDtoPage);
    73. }
    74. /**
    75. * 根据ID 查询菜品和对应口味信息 回显
    76. * @param id
    77. * @return
    78. */
    79. @GetMapping("/{id}")
    80. public R get(@PathVariable Long id){
    81. log.info("要查询显示的菜品信息是:{}",id);
    82. DishDto dishDto = dishService.getByIdWithFlavor(id);
    83. return R.success(dishDto);
    84. }
    85. /**
    86. * 修改菜品
    87. * @param dishDto
    88. * @return
    89. */
    90. @PutMapping
    91. public R update(@RequestBody DishDto dishDto){
    92. log.info(dishDto.toString());
    93. dishService.updateWithFlavor(dishDto);
    94. return R.success("修改菜品成功");
    95. }
    96. // /**
    97. // * 根据条件查询对于菜品数据
    98. // * @param dish
    99. // * @return
    100. // */
    101. // @GetMapping("/list")
    102. // public R> list(Dish dish){
    103. //
    104. // // 构造查询条件
    105. // LambdaQueryWrapper queryWrapper =new LambdaQueryWrapper<>();
    106. // queryWrapper.eq(dish.getCategoryId() != null,Dish::getCategoryId,dish.getCategoryId());
    107. // // 添加条件,查询状态为1(起售状态)的菜品
    108. // queryWrapper.eq(Dish::getStatus,1);
    109. // // 天添加排序条件
    110. // queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);
    111. // List list = dishService.list(queryWrapper);
    112. // return R.success(list);
    113. // }
    114. //}
    115. /**
    116. * 根据条件查询对于菜品数据
    117. * @param dish
    118. * @return
    119. */
    120. @GetMapping("/list")
    121. public R> list(Dish dish){
    122. List dishDtoList = null;
    123. // 动态构造key
    124. String key = "dish_" + dish.getCategoryId() + "_" + dish.getStatus();
    125. // 先从redis获取缓存数据
    126. dishDtoList = (List) redisTemplate.opsForValue().get(key);
    127. if(dishDtoList != null){
    128. // 1 如果存在,直接返回,无需查询数据库
    129. return R.success(dishDtoList);
    130. }
    131. // 2 如果不存在,需要查询数据库,
    132. // 构造查询条件
    133. LambdaQueryWrapper queryWrapper =new LambdaQueryWrapper<>();
    134. queryWrapper.eq(dish.getCategoryId() != null,Dish::getCategoryId,dish.getCategoryId());
    135. // 添加条件,查询状态为1(起售状态)的菜品
    136. queryWrapper.eq(Dish::getStatus,1);
    137. // 天添加排序条件
    138. queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);
    139. List list = dishService.list(queryWrapper);
    140. dishDtoList = list.stream().map((item) -> {
    141. DishDto dishDto = new DishDto();
    142. BeanUtils.copyProperties(item,dishDto);
    143. Long categoryId = item.getCategoryId();// 分类id
    144. //根据id查询分类对象
    145. Category category = categoryService.getById(categoryId);
    146. if(category != null){
    147. String categoryName = category.getName();
    148. dishDto.setCategoryName(categoryName);
    149. }
    150. // 当前菜品的id
    151. Long dishId = item.getId();
    152. LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>();
    153. lambdaQueryWrapper.eq(DishFlavor::getDishId,dishId);
    154. List dishFlavorList = dishFlavorService.list(lambdaQueryWrapper);
    155. dishDto.setFlavors(dishFlavorList);
    156. return dishDto;
    157. }).collect(Collectors.toList());
    158. // 2-1 不存在,将查询到的菜品数据缓存到redis
    159. redisTemplate.opsForValue().set(key,dishDtoList,60, TimeUnit.MINUTES);
    160. return R.success(dishDtoList);
    161. }
    162. }

    4.2.2 第三步改造DishController中的save和update方法 

    1. package com.runa.reggie.controller;
    2. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    3. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
    4. import com.runa.reggie.common.R;
    5. import com.runa.reggie.dto.DishDto;
    6. import com.runa.reggie.entity.Category;
    7. import com.runa.reggie.entity.Dish;
    8. import com.runa.reggie.entity.DishFlavor;
    9. import com.runa.reggie.service.CategoryService;
    10. import com.runa.reggie.service.DishFlavorService;
    11. import com.runa.reggie.service.DishService;
    12. import lombok.extern.slf4j.Slf4j;
    13. import org.springframework.beans.BeanUtils;
    14. import org.springframework.beans.factory.annotation.Autowired;
    15. import org.springframework.data.redis.core.RedisTemplate;
    16. import org.springframework.web.bind.annotation.*;
    17. import java.util.List;
    18. import java.util.Set;
    19. import java.util.concurrent.TimeUnit;
    20. import java.util.stream.Collectors;
    21. /**
    22. * 菜品管理
    23. */
    24. @RestController
    25. @RequestMapping("/dish")
    26. @Slf4j
    27. public class DishController {
    28. @Autowired
    29. private DishService dishService;
    30. @Autowired
    31. private DishFlavorService dishFlavorService;
    32. @Autowired
    33. private CategoryService categoryService;
    34. @Autowired
    35. private RedisTemplate redisTemplate;
    36. /**
    37. * 新增菜品
    38. * @param dishDto
    39. * @return
    40. */
    41. @PostMapping
    42. public R save(@RequestBody DishDto dishDto){
    43. log.info(dishDto.toString());
    44. dishService.saveWithFlavor(dishDto);
    45. // 清理Redis所有菜品的缓存数据
    46. // Set keys = redisTemplate.keys("dish_*");
    47. // 清理Redis某个分类下的菜品的缓存数据
    48. // 动态构造key
    49. String key = "dish_" + dishDto.getCategoryId() + "_1";
    50. redisTemplate.delete(key);
    51. return R.success("新增菜品成功");
    52. }
    53. @GetMapping("/page")
    54. public R page(int page, int pageSize, String name){
    55. // 构造分页构造器对象
    56. Page pageInfo = new Page<>(page, pageSize);
    57. Page dishDtoPage = new Page<>();
    58. //条件构造器
    59. LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
    60. // 添加过滤条件
    61. queryWrapper.like(name != null,Dish::getName,name);
    62. // 添加排序条件
    63. queryWrapper.orderByDesc(Dish::getUpdateTime);
    64. //执行分页查询
    65. dishService.page(pageInfo,queryWrapper);
    66. // 对象拷贝
    67. BeanUtils.copyProperties(pageInfo, dishDtoPage,"records");
    68. List records = pageInfo.getRecords();
    69. List list = records.stream().map((item) -> {
    70. DishDto dishDto = new DishDto();
    71. BeanUtils.copyProperties(item,dishDto);
    72. Long categoryId = item.getCategoryId();// 分类id
    73. Category category = categoryService.getById(categoryId);
    74. String categoryName = category.getName();
    75. dishDto.setCategoryName(categoryName);
    76. return dishDto;
    77. }).collect(Collectors.toList());
    78. dishDtoPage.setRecords(list);
    79. return R.success(dishDtoPage);
    80. }
    81. /**
    82. * 根据ID 查询菜品和对应口味信息 回显
    83. * @param id
    84. * @return
    85. */
    86. @GetMapping("/{id}")
    87. public R get(@PathVariable Long id){
    88. log.info("要查询显示的菜品信息是:{}",id);
    89. DishDto dishDto = dishService.getByIdWithFlavor(id);
    90. return R.success(dishDto);
    91. }
    92. /**
    93. * 修改菜品
    94. * @param dishDto
    95. * @return
    96. */
    97. @PutMapping
    98. public R update(@RequestBody DishDto dishDto){
    99. log.info(dishDto.toString());
    100. dishService.updateWithFlavor(dishDto);
    101. // 清理Redis所有菜品的缓存数据
    102. // Set keys = redisTemplate.keys("dish_*");
    103. // 清理Redis某个分类下的菜品的缓存数据
    104. // 动态构造key
    105. String key = "dish_" + dishDto.getCategoryId() + "_1";
    106. redisTemplate.delete(key);
    107. return R.success("修改菜品成功");
    108. }
    109. // /**
    110. // * 根据条件查询对于菜品数据
    111. // * @param dish
    112. // * @return
    113. // */
    114. // @GetMapping("/list")
    115. // public R> list(Dish dish){
    116. //
    117. // // 构造查询条件
    118. // LambdaQueryWrapper queryWrapper =new LambdaQueryWrapper<>();
    119. // queryWrapper.eq(dish.getCategoryId() != null,Dish::getCategoryId,dish.getCategoryId());
    120. // // 添加条件,查询状态为1(起售状态)的菜品
    121. // queryWrapper.eq(Dish::getStatus,1);
    122. // // 天添加排序条件
    123. // queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);
    124. // List list = dishService.list(queryWrapper);
    125. // return R.success(list);
    126. // }
    127. //}
    128. /**
    129. * 根据条件查询对于菜品数据
    130. * @param dish
    131. * @return
    132. */
    133. @GetMapping("/list")
    134. public R> list(Dish dish){
    135. List dishDtoList = null;
    136. // 动态构造key
    137. String key = "dish_" + dish.getCategoryId() + "_" + dish.getStatus();
    138. // 先从redis获取缓存数据
    139. dishDtoList = (List) redisTemplate.opsForValue().get(key);
    140. if(dishDtoList != null){
    141. // 1 如果存在,直接返回,无需查询数据库
    142. return R.success(dishDtoList);
    143. }
    144. // 2 如果不存在,需要查询数据库,
    145. // 构造查询条件
    146. LambdaQueryWrapper queryWrapper =new LambdaQueryWrapper<>();
    147. queryWrapper.eq(dish.getCategoryId() != null,Dish::getCategoryId,dish.getCategoryId());
    148. // 添加条件,查询状态为1(起售状态)的菜品
    149. queryWrapper.eq(Dish::getStatus,1);
    150. // 天添加排序条件
    151. queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);
    152. List list = dishService.list(queryWrapper);
    153. dishDtoList = list.stream().map((item) -> {
    154. DishDto dishDto = new DishDto();
    155. BeanUtils.copyProperties(item,dishDto);
    156. Long categoryId = item.getCategoryId();// 分类id
    157. //根据id查询分类对象
    158. Category category = categoryService.getById(categoryId);
    159. if(category != null){
    160. String categoryName = category.getName();
    161. dishDto.setCategoryName(categoryName);
    162. }
    163. // 当前菜品的id
    164. Long dishId = item.getId();
    165. LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>();
    166. lambdaQueryWrapper.eq(DishFlavor::getDishId,dishId);
    167. List dishFlavorList = dishFlavorService.list(lambdaQueryWrapper);
    168. dishDto.setFlavors(dishFlavorList);
    169. return dishDto;
    170. }).collect(Collectors.toList());
    171. // 2-1 不存在,将查询到的菜品数据缓存到redis
    172. redisTemplate.opsForValue().set(key,dishDtoList,60, TimeUnit.MINUTES);
    173. return R.success(dishDtoList);
    174. }
    175. }

    4.3 功能测试

    1. http://localhost:8080/front/page/login.html
    2. http://localhost:8080/backend/index.html

     

    五、Spring Cache

    5.1 Spring Cache介绍

    5.2 Spring Cache常用注解

    5.3 Spring Cache使用方式

     5.3.1 pom

    1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    3. <modelVersion>4.0.0modelVersion>
    4. <groupId>com.runagroupId>
    5. <artifactId>reggie_take_out_spuerartifactId>
    6. <version>1.0-SNAPSHOTversion>
    7. <packaging>jarpackaging>
    8. <parent>
    9. <groupId>org.springframework.bootgroupId>
    10. <artifactId>spring-boot-starter-parentartifactId>
    11. <version>2.4.5version>
    12. <relativePath/>
    13. parent>
    14. <name>reggie_take_out_spuername>
    15. <url>http://maven.apache.orgurl>
    16. <properties>
    17. <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
    18. <java.version>1.8java.version>
    19. properties>
    20. <dependencies>
    21. <dependency>
    22. <groupId>com.aliyungroupId>
    23. <artifactId>aliyun-java-sdk-coreartifactId>
    24. <version>4.5.16version>
    25. dependency>
    26. <dependency>
    27. <groupId>com.aliyungroupId>
    28. <artifactId>aliyun-java-sdk-dysmsapiartifactId>
    29. <version>2.1.0version>
    30. dependency>
    31. <dependency>
    32. <groupId>org.springframework.bootgroupId>
    33. <artifactId>spring-boot-starterartifactId>
    34. dependency>
    35. <dependency>
    36. <groupId>org.springframework.bootgroupId>
    37. <artifactId>spring-boot-starter-testartifactId>
    38. <scope>testscope>
    39. dependency>
    40. <dependency>
    41. <groupId>org.springframework.bootgroupId>
    42. <artifactId>spring-boot-starter-webartifactId>
    43. <scope>compilescope>
    44. dependency>
    45. <dependency>
    46. <groupId>com.baomidougroupId>
    47. <artifactId>mybatis-plus-boot-starterartifactId>
    48. <version>3.4.2version>
    49. dependency>
    50. <dependency>
    51. <groupId>org.projectlombokgroupId>
    52. <artifactId>lombokartifactId>
    53. <version>1.18.20version>
    54. dependency>
    55. <dependency>
    56. <groupId>com.alibabagroupId>
    57. <artifactId>fastjsonartifactId>
    58. <version>1.2.76version>
    59. dependency>
    60. <dependency>
    61. <groupId>commons-langgroupId>
    62. <artifactId>commons-langartifactId>
    63. <version>2.6version>
    64. dependency>
    65. <dependency>
    66. <groupId>mysqlgroupId>
    67. <artifactId>mysql-connector-javaartifactId>
    68. <scope>runtimescope>
    69. dependency>
    70. <dependency>
    71. <groupId>com.alibabagroupId>
    72. <artifactId>druid-spring-boot-starterartifactId>
    73. <version>1.1.23version>
    74. dependency>
    75. <dependency>
    76. <groupId>junitgroupId>
    77. <artifactId>junitartifactId>
    78. <version>3.8.1version>
    79. <scope>testscope>
    80. dependency>
    81. <dependency>
    82. <groupId>org.springframework.bootgroupId>
    83. <artifactId>spring-boot-starter-data-redisartifactId>
    84. dependency>
    85. <dependency>
    86. <groupId>org.springframework.bootgroupId>
    87. <artifactId>spring-boot-starter-cacheartifactId>
    88. dependency>
    89. dependencies>
    90. <build>
    91. <plugins>
    92. <plugin>
    93. <groupId>org.springframework.bootgroupId>
    94. <artifactId>spring-boot-maven-pluginartifactId>
    95. <version>2.4.5version>
    96. plugin>
    97. plugins>
    98. build>
    99. project>

    六、缓存套餐数据

    6.1 实现思路

    6.2 代码改造

     6.2.1 pom 坐标

    1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    3. <modelVersion>4.0.0modelVersion>
    4. <groupId>com.runagroupId>
    5. <artifactId>reggie_take_out_spuerartifactId>
    6. <version>1.0-SNAPSHOTversion>
    7. <packaging>jarpackaging>
    8. <parent>
    9. <groupId>org.springframework.bootgroupId>
    10. <artifactId>spring-boot-starter-parentartifactId>
    11. <version>2.4.5version>
    12. <relativePath/>
    13. parent>
    14. <name>reggie_take_out_spuername>
    15. <url>http://maven.apache.orgurl>
    16. <properties>
    17. <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
    18. <java.version>1.8java.version>
    19. properties>
    20. <dependencies>
    21. <dependency>
    22. <groupId>com.aliyungroupId>
    23. <artifactId>aliyun-java-sdk-coreartifactId>
    24. <version>4.5.16version>
    25. dependency>
    26. <dependency>
    27. <groupId>com.aliyungroupId>
    28. <artifactId>aliyun-java-sdk-dysmsapiartifactId>
    29. <version>2.1.0version>
    30. dependency>
    31. <dependency>
    32. <groupId>org.springframework.bootgroupId>
    33. <artifactId>spring-boot-starterartifactId>
    34. dependency>
    35. <dependency>
    36. <groupId>org.springframework.bootgroupId>
    37. <artifactId>spring-boot-starter-testartifactId>
    38. <scope>testscope>
    39. dependency>
    40. <dependency>
    41. <groupId>org.springframework.bootgroupId>
    42. <artifactId>spring-boot-starter-webartifactId>
    43. <scope>compilescope>
    44. dependency>
    45. <dependency>
    46. <groupId>com.baomidougroupId>
    47. <artifactId>mybatis-plus-boot-starterartifactId>
    48. <version>3.4.2version>
    49. dependency>
    50. <dependency>
    51. <groupId>org.projectlombokgroupId>
    52. <artifactId>lombokartifactId>
    53. <version>1.18.20version>
    54. dependency>
    55. <dependency>
    56. <groupId>com.alibabagroupId>
    57. <artifactId>fastjsonartifactId>
    58. <version>1.2.76version>
    59. dependency>
    60. <dependency>
    61. <groupId>commons-langgroupId>
    62. <artifactId>commons-langartifactId>
    63. <version>2.6version>
    64. dependency>
    65. <dependency>
    66. <groupId>mysqlgroupId>
    67. <artifactId>mysql-connector-javaartifactId>
    68. <scope>runtimescope>
    69. dependency>
    70. <dependency>
    71. <groupId>com.alibabagroupId>
    72. <artifactId>druid-spring-boot-starterartifactId>
    73. <version>1.1.23version>
    74. dependency>
    75. <dependency>
    76. <groupId>junitgroupId>
    77. <artifactId>junitartifactId>
    78. <version>3.8.1version>
    79. <scope>testscope>
    80. dependency>
    81. <dependency>
    82. <groupId>org.springframework.bootgroupId>
    83. <artifactId>spring-boot-starter-data-redisartifactId>
    84. dependency>
    85. <dependency>
    86. <groupId>org.springframework.bootgroupId>
    87. <artifactId>spring-boot-starter-cacheartifactId>
    88. dependency>
    89. dependencies>
    90. <build>
    91. <plugins>
    92. <plugin>
    93. <groupId>org.springframework.bootgroupId>
    94. <artifactId>spring-boot-maven-pluginartifactId>
    95. <version>2.4.5version>
    96. plugin>
    97. plugins>
    98. build>
    99. project>

    6.2.2 application.yml配置缓存数据过期时间

    1. server:
    2. port: 8080
    3. spring:
    4. application:
    5. # 应用名称 可选
    6. name: reggie_take_out_spuer
    7. datasource:
    8. druid:
    9. driver-class-name: com.mysql.cj.jdbc.Driver
    10. url: jdbc:mysql://localhost:3306/reggie?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
    11. username: root
    12. password: runa#2050
    13. redis:
    14. host: 127.0.0.1
    15. port: 6379
    16. password: 123456
    17. database: 0
    18. cache:
    19. redis:
    20. time-to-live: 1800000 # 设置缓存数据的过期时间
    21. mybatis-plus:
    22. configuration:
    23. #在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射
    24. map-underscore-to-camel-case: true
    25. log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    26. global-config:
    27. db-config:
    28. id-type: ASSIGN_ID
    29. # 文件上传目录
    30. reggie:
    31. path: D:\images\

    6.2.3 开启缓存注解功能 ReggieApplication

     

    1. package com.runa.reggie;
    2. import lombok.extern.slf4j.Slf4j;
    3. import org.springframework.boot.SpringApplication;
    4. import org.springframework.boot.autoconfigure.SpringBootApplication;
    5. import org.springframework.boot.web.servlet.ServletComponentScan;
    6. import org.springframework.cache.annotation.EnableCaching;
    7. import org.springframework.transaction.annotation.EnableTransactionManagement;
    8. @Slf4j
    9. @SpringBootApplication
    10. @ServletComponentScan
    11. @EnableTransactionManagement
    12. @EnableCaching // 开启spring Cache注解方式的缓存功能
    13. public class ReggieApplication {
    14. public static void main(String[] args) {
    15. SpringApplication.run(ReggieApplication.class,args);
    16. log.info("项目启动成功~~~");
    17. }
    18. }

     6.2.4  R实现 Serializable 接口

    1. package com.runa.reggie.common;
    2. import lombok.Data;
    3. import java.io.Serializable;
    4. import java.util.HashMap;
    5. import java.util.Map;
    6. /**
    7. * 通用返回结果,服务端响应的数据最终都会封装成此对象
    8. * @param
    9. */
    10. @Data
    11. public class R implements Serializable {
    12. private Integer code; //编码:1成功,0和其它数字为失败
    13. private String msg; //错误信息
    14. private T data; //数据
    15. private Map map = new HashMap(); //动态数据
    16. public static R success(T object) {
    17. R r = new R();
    18. r.data = object;
    19. r.code = 1;
    20. return r;
    21. }
    22. public static R error(String msg) {
    23. R r = new R();
    24. r.msg = msg;
    25. r.code = 0;
    26. return r;
    27. }
    28. public R add(String key, Object value) {
    29. this.map.put(key, value);
    30. return this;
    31. }
    32. }

     6.2.5 在SetmealController的list方法加入@Cacheable注解

    1. package com.runa.reggie.controller;
    2. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    3. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
    4. import com.runa.reggie.common.R;
    5. import com.runa.reggie.dto.SetmealDto;
    6. import com.runa.reggie.entity.Category;
    7. import com.runa.reggie.entity.Setmeal;
    8. import com.runa.reggie.service.CategoryService;
    9. import com.runa.reggie.service.SetmealDishService;
    10. import com.runa.reggie.service.SetmealService;
    11. import lombok.extern.slf4j.Slf4j;
    12. import org.springframework.beans.BeanUtils;
    13. import org.springframework.beans.factory.annotation.Autowired;
    14. import org.springframework.cache.annotation.Cacheable;
    15. import org.springframework.web.bind.annotation.*;
    16. import java.util.List;
    17. import java.util.stream.Collectors;
    18. @RestController
    19. @RequestMapping("/setmeal")
    20. @Slf4j
    21. public class SetmealController {
    22. @Autowired
    23. private SetmealService setmealService;
    24. @Autowired
    25. private CategoryService categoryService;
    26. @Autowired
    27. private SetmealDishService setmealDishService;
    28. /**
    29. * 新增套餐
    30. * @param setmealDto
    31. * @return
    32. */
    33. @PostMapping
    34. public R save(@RequestBody SetmealDto setmealDto){
    35. log.info("套餐信息:{}",setmealDto);
    36. setmealService.saveWithDish(setmealDto);
    37. return R.success("新增套餐成功");
    38. }
    39. /**
    40. * 套餐分页查询
    41. * @param page
    42. * @param pageSize
    43. * @param name
    44. * @return
    45. */
    46. @GetMapping("/page")
    47. public R page(int page, int pageSize, String name){
    48. //分页构造器对象
    49. Page pageInfo = new Page<>(page,pageSize);
    50. Page dtoPage = new Page<>();
    51. LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
    52. //添加查询条件,根据name进行like模糊查询
    53. queryWrapper.like(name != null,Setmeal::getName,name);
    54. //添加排序条件,根据更新时间降序排列
    55. queryWrapper.orderByDesc(Setmeal::getUpdateTime);
    56. setmealService.page(pageInfo,queryWrapper);
    57. //对象拷贝
    58. BeanUtils.copyProperties(pageInfo,dtoPage,"records");
    59. List records = pageInfo.getRecords();
    60. List list = records.stream().map((item) -> {
    61. SetmealDto setmealDto = new SetmealDto();
    62. //对象拷贝
    63. BeanUtils.copyProperties(item,setmealDto);
    64. //分类id
    65. Long categoryId = item.getCategoryId();
    66. //根据分类id查询分类对象
    67. Category category = categoryService.getById(categoryId);
    68. if(category != null){
    69. //分类名称
    70. String categoryName = category.getName();
    71. setmealDto.setCategoryName(categoryName);
    72. }
    73. return setmealDto;
    74. }).collect(Collectors.toList());
    75. dtoPage.setRecords(list);
    76. return R.success(dtoPage);
    77. }
    78. /**
    79. * 删除套餐
    80. * @param ids
    81. * @return
    82. */
    83. @DeleteMapping
    84. public R delete(@RequestParam List ids){
    85. log.info("ids:{}",ids);
    86. setmealService.removeWithDish(ids);
    87. return R.success("套餐数据删除成功");
    88. }
    89. /**
    90. * 根据条件查询套餐数据
    91. * @param setmeal
    92. * @return
    93. */
    94. @GetMapping("/list")
    95. @Cacheable(value = "setmealCache", key = "#setmeal.categoryId + '_' + #setmeal.status")
    96. public R> list(Setmeal setmeal){
    97. LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
    98. queryWrapper.eq(setmeal.getCategoryId() != null,Setmeal::getCategoryId,setmeal.getCategoryId());
    99. queryWrapper.eq(setmeal.getStatus() != null,Setmeal::getStatus,setmeal.getStatus());
    100. queryWrapper.orderByDesc(Setmeal::getUpdateTime);
    101. List list = setmealService.list(queryWrapper);
    102. return R.success(list);
    103. }
    104. }

    6.2.6 在SetmealController的delete方法加入@CacheEvict注解

    1. package com.runa.reggie.controller;
    2. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    3. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
    4. import com.runa.reggie.common.R;
    5. import com.runa.reggie.dto.SetmealDto;
    6. import com.runa.reggie.entity.Category;
    7. import com.runa.reggie.entity.Setmeal;
    8. import com.runa.reggie.service.CategoryService;
    9. import com.runa.reggie.service.SetmealDishService;
    10. import com.runa.reggie.service.SetmealService;
    11. import lombok.extern.slf4j.Slf4j;
    12. import org.springframework.beans.BeanUtils;
    13. import org.springframework.beans.factory.annotation.Autowired;
    14. import org.springframework.cache.annotation.CacheEvict;
    15. import org.springframework.cache.annotation.Cacheable;
    16. import org.springframework.web.bind.annotation.*;
    17. import java.util.List;
    18. import java.util.stream.Collectors;
    19. @RestController
    20. @RequestMapping("/setmeal")
    21. @Slf4j
    22. public class SetmealController {
    23. @Autowired
    24. private SetmealService setmealService;
    25. @Autowired
    26. private CategoryService categoryService;
    27. @Autowired
    28. private SetmealDishService setmealDishService;
    29. /**
    30. * 新增套餐
    31. * @param setmealDto
    32. * @return
    33. */
    34. @PostMapping
    35. public R save(@RequestBody SetmealDto setmealDto){
    36. log.info("套餐信息:{}",setmealDto);
    37. setmealService.saveWithDish(setmealDto);
    38. return R.success("新增套餐成功");
    39. }
    40. /**
    41. * 套餐分页查询
    42. * @param page
    43. * @param pageSize
    44. * @param name
    45. * @return
    46. */
    47. @GetMapping("/page")
    48. public R page(int page, int pageSize, String name){
    49. //分页构造器对象
    50. Page pageInfo = new Page<>(page,pageSize);
    51. Page dtoPage = new Page<>();
    52. LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
    53. //添加查询条件,根据name进行like模糊查询
    54. queryWrapper.like(name != null,Setmeal::getName,name);
    55. //添加排序条件,根据更新时间降序排列
    56. queryWrapper.orderByDesc(Setmeal::getUpdateTime);
    57. setmealService.page(pageInfo,queryWrapper);
    58. //对象拷贝
    59. BeanUtils.copyProperties(pageInfo,dtoPage,"records");
    60. List records = pageInfo.getRecords();
    61. List list = records.stream().map((item) -> {
    62. SetmealDto setmealDto = new SetmealDto();
    63. //对象拷贝
    64. BeanUtils.copyProperties(item,setmealDto);
    65. //分类id
    66. Long categoryId = item.getCategoryId();
    67. //根据分类id查询分类对象
    68. Category category = categoryService.getById(categoryId);
    69. if(category != null){
    70. //分类名称
    71. String categoryName = category.getName();
    72. setmealDto.setCategoryName(categoryName);
    73. }
    74. return setmealDto;
    75. }).collect(Collectors.toList());
    76. dtoPage.setRecords(list);
    77. return R.success(dtoPage);
    78. }
    79. /**
    80. * 删除套餐
    81. * @param ids
    82. * @return
    83. */
    84. @DeleteMapping
    85. @CacheEvict(value = "setmealCache" , allEntries = true)
    86. public R delete(@RequestParam List ids){
    87. log.info("ids:{}",ids);
    88. setmealService.removeWithDish(ids);
    89. return R.success("套餐数据删除成功");
    90. }
    91. /**
    92. * 根据条件查询套餐数据
    93. * @param setmeal
    94. * @return
    95. */
    96. @GetMapping("/list")
    97. @Cacheable(value = "setmealCache", key = "#setmeal.categoryId + '_' + #setmeal.status")
    98. public R> list(Setmeal setmeal){
    99. LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
    100. queryWrapper.eq(setmeal.getCategoryId() != null,Setmeal::getCategoryId,setmeal.getCategoryId());
    101. queryWrapper.eq(setmeal.getStatus() != null,Setmeal::getStatus,setmeal.getStatus());
    102. queryWrapper.orderByDesc(Setmeal::getUpdateTime);
    103. List list = setmealService.list(queryWrapper);
    104. return R.success(list);
    105. }
    106. }

    6.2.7 在SetmealController的save方法加入@CacheEvict注解

    1. package com.runa.reggie.controller;
    2. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    3. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
    4. import com.runa.reggie.common.R;
    5. import com.runa.reggie.dto.SetmealDto;
    6. import com.runa.reggie.entity.Category;
    7. import com.runa.reggie.entity.Setmeal;
    8. import com.runa.reggie.service.CategoryService;
    9. import com.runa.reggie.service.SetmealDishService;
    10. import com.runa.reggie.service.SetmealService;
    11. import lombok.extern.slf4j.Slf4j;
    12. import org.springframework.beans.BeanUtils;
    13. import org.springframework.beans.factory.annotation.Autowired;
    14. import org.springframework.cache.annotation.CacheEvict;
    15. import org.springframework.cache.annotation.Cacheable;
    16. import org.springframework.web.bind.annotation.*;
    17. import java.util.List;
    18. import java.util.stream.Collectors;
    19. @RestController
    20. @RequestMapping("/setmeal")
    21. @Slf4j
    22. public class SetmealController {
    23. @Autowired
    24. private SetmealService setmealService;
    25. @Autowired
    26. private CategoryService categoryService;
    27. @Autowired
    28. private SetmealDishService setmealDishService;
    29. /**
    30. * 新增套餐
    31. * @param setmealDto
    32. * @return
    33. */
    34. @PostMapping
    35. @CacheEvict(value = "setmealCache" , allEntries = true)
    36. public R save(@RequestBody SetmealDto setmealDto){
    37. log.info("套餐信息:{}",setmealDto);
    38. setmealService.saveWithDish(setmealDto);
    39. return R.success("新增套餐成功");
    40. }
    41. /**
    42. * 套餐分页查询
    43. * @param page
    44. * @param pageSize
    45. * @param name
    46. * @return
    47. */
    48. @GetMapping("/page")
    49. public R page(int page, int pageSize, String name){
    50. //分页构造器对象
    51. Page pageInfo = new Page<>(page,pageSize);
    52. Page dtoPage = new Page<>();
    53. LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
    54. //添加查询条件,根据name进行like模糊查询
    55. queryWrapper.like(name != null,Setmeal::getName,name);
    56. //添加排序条件,根据更新时间降序排列
    57. queryWrapper.orderByDesc(Setmeal::getUpdateTime);
    58. setmealService.page(pageInfo,queryWrapper);
    59. //对象拷贝
    60. BeanUtils.copyProperties(pageInfo,dtoPage,"records");
    61. List records = pageInfo.getRecords();
    62. List list = records.stream().map((item) -> {
    63. SetmealDto setmealDto = new SetmealDto();
    64. //对象拷贝
    65. BeanUtils.copyProperties(item,setmealDto);
    66. //分类id
    67. Long categoryId = item.getCategoryId();
    68. //根据分类id查询分类对象
    69. Category category = categoryService.getById(categoryId);
    70. if(category != null){
    71. //分类名称
    72. String categoryName = category.getName();
    73. setmealDto.setCategoryName(categoryName);
    74. }
    75. return setmealDto;
    76. }).collect(Collectors.toList());
    77. dtoPage.setRecords(list);
    78. return R.success(dtoPage);
    79. }
    80. /**
    81. * 删除套餐
    82. * @param ids
    83. * @return
    84. */
    85. @DeleteMapping
    86. @CacheEvict(value = "setmealCache" , allEntries = true)
    87. public R delete(@RequestParam List ids){
    88. log.info("ids:{}",ids);
    89. setmealService.removeWithDish(ids);
    90. return R.success("套餐数据删除成功");
    91. }
    92. /**
    93. * 根据条件查询套餐数据
    94. * @param setmeal
    95. * @return
    96. */
    97. @GetMapping("/list")
    98. @Cacheable(value = "setmealCache", key = "#setmeal.categoryId + '_' + #setmeal.status")
    99. public R> list(Setmeal setmeal){
    100. LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
    101. queryWrapper.eq(setmeal.getCategoryId() != null,Setmeal::getCategoryId,setmeal.getCategoryId());
    102. queryWrapper.eq(setmeal.getStatus() != null,Setmeal::getStatus,setmeal.getStatus());
    103. queryWrapper.orderByDesc(Setmeal::getUpdateTime);
    104. List list = setmealService.list(queryWrapper);
    105. return R.success(list);
    106. }
    107. }

    6.3 功能测试

    1. http://localhost:8080/front/page/login.html
    2. http://localhost:8080/backend/index.html

  • 相关阅读:
    C++之STL
    华为联机对战如何提升玩家匹配成功几率
    网络编程【TCP单向通信、TCP双向通信、一对多应用、一对多聊天服务器】(二)-全面详解(学习总结---从入门到深化)
    【排序算法】详解直接插入排序和希尔排序原理及其性能分析
    前端基础入门之JS 正则表达式
    Day10:图形用户界面和游戏开发
    Golang字符串处理
    Bugly iOS自动导入符号表
    C语言——文件
    一个简单的HTML网页 故宫学生网页设计作品 dreamweaver作业静态HTML网页设计模板 旅游景点网页作业制作
  • 原文地址:https://blog.csdn.net/legend818/article/details/132606895