苍穹外卖学习笔记(十五)

news/2024/10/8 15:00:42/

文章目录

  • 一. 缓存菜品
    • 缓存菜品
      • DishController.java
      • 清除缓存数据
    • 缓存套餐
      • Spring Cache
      • 入门案例
        • springcachedemo.sql
        • pom.xml
        • application.yml
        • CacheDemoApplication.java
        • WebMvcConfiguration.java
        • UserController.java
        • User.java
        • UserMapper.java
      • 套餐管理
        • SkyApplication
        • User的SetmealController
        • admin的SetmealController

一. 缓存菜品

通过Redis来缓存菜品数据,减少数据库查询操作

缓存菜品

根据分类ID缓存菜品
key : value

java_7">DishController.java

java">package com.sky.controller.user;import com.sky.constant.StatusConstant;
import com.sky.entity.Dish;
import com.sky.result.Result;
import com.sky.service.DishService;
import com.sky.vo.DishVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;/*** @author Jie.* @description: TODO* @date 2024/9/25* @version: 1.0*/
@RestController("userDishController")
@RequestMapping("/user/dish")
@Api(tags = "菜品管理")
@Slf4j
public class DishController {@Autowiredprivate DishService dishService;@Autowiredprivate RedisTemplate redisTemplate;/*** 根据分类id查询菜品*/@GetMapping("/list")@ApiOperation("根据分类id查询菜品")public Result<List<DishVO>> list(Long categoryId) {//构造redis keyString key = "dish_" + categoryId;//从redis中获取数据List<DishVO> list = (List<DishVO>) redisTemplate.opsForValue().get(key);if (list != null && !list.isEmpty()) {return Result.success(list);}Dish dish = new Dish();dish.setCategoryId(categoryId);dish.setStatus(StatusConstant.ENABLE);//如果缓存中没有数据,查询数据库list = dishService.listWithFlavor(dish);redisTemplate.opsForValue().set(key, list);return Result.success(list);}
}

清除缓存数据

当我们新增菜品、修改菜品、批量删除菜品、起售、停售菜品时清理缓存
DishController.java

java">package com.sky.controller.admin;import com.sky.dto.DishDTO;
import com.sky.dto.DishPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.DishService;
import com.sky.vo.DishVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;import java.util.List;
import java.util.Set;/*** @author Jie.* @description: TODO* @date 2024/9/13* @version: 1.0*/
/*** 菜品管理*/
@RestController("adminDishController")
@RequestMapping("/admin/dish")
@Slf4j
@Api(tags = "菜品管理")
public class DishController {@Autowiredprivate DishService dishService;@Autowiredprivate RedisTemplate redisTemplate;/*** 新增菜品*/@PostMapping@ApiOperation("新增菜品")public Result save(@RequestBody DishDTO dishDTO) {log.info("新增菜品:{}", dishDTO);dishService.saveWithFlavor(dishDTO);//清理缓存数据String key = "dish_" + dishDTO.getCategoryId();redisTemplate.delete(key);return Result.success();}/*** 分页查询菜品*/@GetMapping("/page")@ApiOperation("分页查询菜品")public Result<PageResult> page(DishPageQueryDTO dishPageQueryDTO) {log.info("分页查询菜品:{}", dishPageQueryDTO);PageResult pageResult = dishService.pageQuery(dishPageQueryDTO);return Result.success(pageResult);}/*** 删除菜品*/@DeleteMapping@ApiOperation("删除菜品")public Result delete(@RequestParam List<Long> ids) {//@RequestParam接收请求参数log.info("删除菜品:{}", ids);dishService.deleteBatch(ids);//清理缓存数据cleanCache("dish_*");return Result.success();}/*** 根据id查询菜品*/@GetMapping("/{id}")@ApiOperation("根据id查询菜品")public Result<DishVO> getById(@PathVariable Long id) {//@PathVariable接收请求路径中的参数log.info("根据id查询菜品:{}", id);DishVO dishVO = dishService.getByIdWithFlavor(id);return Result.success(dishVO);}/*** 修改菜品*/@PutMapping@ApiOperation("修改菜品")public Result update(@RequestBody DishDTO dishDTO) {log.info("修改菜品:{}", dishDTO);dishService.updateWithFlavor(dishDTO);//清理缓存数据cleanCache("dish_*");return Result.success();}/*** 修改菜品状态*/@PostMapping("/status/{status}")@ApiOperation("修改菜品状态")public Result updateStatus(@RequestParam Long id, @PathVariable Integer status) {//RequestParam接收请求参数,PathVariable接收请求路径中的参数log.info("修改菜品状态:{}", id);dishService.updateStatus(id, status);//清理缓存数据cleanCache("dish_*");return Result.success();}/*** 根据分类id查询菜品*/@GetMapping("/list")@ApiOperation("根据分类id查询菜品")public Result<List<Dish>> listResult(@RequestParam Long categoryId) {log.info("根据分类id查询菜品:{}", categoryId);List<Dish> list = dishService.listByCategoryId(categoryId);return Result.success(list);}//清理缓存private void cleanCache(String pattern) {Set keys = redisTemplate.keys(pattern);redisTemplate.delete(keys);}
}

缓存套餐

Spring Cache

Spring Cache是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能

Spring Cache提供了一层抽象,底层可以切换不同的缓存实现,例如:

  1. EHCache
  2. Caffeine
  3. Redis
maven_218">maven坐标
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId><version>2.7.3</version>
</dependency>
常用注解
注解说明
@EnableCaching开启缓存注解功能,通常加在启动类上
@Cacheable在方法执行前先查询缓存中是否有数据,如果有数据,则直接返回缓存数据;如果没有缓存数据,调用方法并将方法返回值放到缓存中
@CachePut将方法的返回值放到缓存中
@CacheEvict将一条或多条数据从缓存中删除
20241004152341)

入门案例

springcachedemo.sql
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (`id` bigint NOT NULL AUTO_INCREMENT,`name` varchar(45) DEFAULT NULL,`age` int DEFAULT NULL,PRIMARY KEY (`id`)
);
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.3</version><relativePath/></parent><groupId>com.itheima</groupId><artifactId>springcache-demo</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>11</maven.compiler.source><maven.compiler.target>11</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><scope>compile</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.20</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.76</version></dependency><dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId><version>2.6</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.0</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.1</version></dependency><dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version>3.0.2</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>2.7.3</version></plugin></plugins></build>
</project>
application.yml
server:port: 8888
spring:datasource:druid:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/spring_cache_demo?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=trueusername: rootpassword: 123456redis:host: localhostport: 6379database: 1
logging:level:com:itheima:mapper: debugservice: infocontroller: info
java_364">CacheDemoApplication.java
java">package com.itheima;import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;@Slf4j
@SpringBootApplication
@EnableCaching // 开启缓存
public class CacheDemoApplication {public static void main(String[] args) {SpringApplication.run(CacheDemoApplication.class,args);log.info("项目启动成功...");}
}
java_383">WebMvcConfiguration.java
java">package com.itheima.config;import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;@Configuration
@Slf4j
public class WebMvcConfiguration extends WebMvcConfigurationSupport {/*** 生成接口文档配置* @return*/@Beanpublic Docket docket(){log.info("准备生成接口文档...");ApiInfo apiInfo = new ApiInfoBuilder().title("接口文档").version("2.0").description("接口文档").build();Docket docket = new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo).select()//指定生成接口需要扫描的包.apis(RequestHandlerSelectors.basePackage("com.itheima.controller")).paths(PathSelectors.any()).build();return docket;}/*** 设置静态资源映射* @param registry*/protected void addResourceHandlers(ResourceHandlerRegistry registry) {log.info("开始设置静态资源映射...");registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");}
}
java_439">UserController.java
java">package com.itheima.controller;import com.itheima.entity.User;
import com.itheima.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {@Autowiredprivate UserMapper userMapper;@PostMapping@CachePut(cacheNames = "userCache", key = "#user.id")public User save(@RequestBody User user){userMapper.insert(user);return user;}@GetMapping@Cacheable(cacheNames = "userCache", key = "#id")public User getById(Long id){User user = userMapper.getById(id);return user;}@DeleteMapping@CacheEvict(cacheNames = "userCache", key = "#id")public void deleteById(Long id){userMapper.deleteById(id);}@DeleteMapping("/delAll")@CacheEvict(cacheNames = "userCache", allEntries = true)public void deleteAll(){userMapper.deleteAll();}
}
java_487">User.java
java">package com.itheima.entity;import lombok.Data;
import java.io.Serializable;@Data
public class User implements Serializable {private static final long serialVersionUID = 1L;private Long id;private String name;private int age;}
java_507">UserMapper.java
java">package com.itheima.mapper;import com.itheima.entity.User;
import org.apache.ibatis.annotations.*;@Mapper
public interface UserMapper{@Insert("insert into user(name,age) values (#{name},#{age})")@Options(useGeneratedKeys = true,keyProperty = "id")void insert(User user);@Delete("delete from user where id = #{id}")void deleteById(Long id);@Delete("delete from user")void deleteAll();@Select("select * from user where id = #{id}")User getById(Long id);
}

套餐管理

  1. 导入Spring Cache和Redis相关的Maven坐标
  2. 在启动类上加入@EnableCaching注解,开启缓存注解功能
  3. 在用户端接口SetmealController的list方法上加入@Cacheable注解
  4. 在管理端接口SetmealController的save、delete、update、updateStatus等方法上加入@CacheEvict注解
SkyApplication
java">package com.sky;import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;
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");}
}
User的SetmealController
java">package com.sky.controller.user;import com.sky.constant.StatusConstant;
import com.sky.entity.Setmeal;
import com.sky.result.Result;
import com.sky.service.SetmealService;
import com.sky.vo.DishItemVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;/*** @author Jie.* @description: TODO* @date 2024/9/25* @version: 1.0*/
@RestController("userSetmealController")
@RequestMapping("/user/setmeal")
@Api(tags = "套餐管理")
@Slf4j
public class SetmealController {@Autowiredprivate SetmealService setmealService;/*** 根据分类id查询套餐*/@GetMapping("/list")@ApiOperation("套餐列表")@Cacheable(cacheNames = "setmealCache", key = "#categoryId")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);}/*** 根据套餐id查询包含的菜品*/@GetMapping("/dish/{id}")@ApiOperation("根据套餐id查询包含的菜品")public Result<List<DishItemVO>> dishList(@PathVariable Long id) {List<DishItemVO> list = setmealService.getDishItemById(id);return Result.success(list);}
}
admin的SetmealController
java">package com.sky.controller.admin;import com.sky.dto.SetmealDTO;
import com.sky.dto.SetmealPageQueryDTO;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.SetmealService;
import com.sky.vo.SetmealVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.web.bind.annotation.*;import java.util.List;/*** @author Jie.* @description: TODO* @date 2024/9/16* @version: 1.0*/
@RestController("adminSetmealController")
@RequestMapping("/admin/setmeal")
@Api(tags = "套餐管理")
@Slf4j
public class SetmealController {@Autowiredprivate SetmealService setmealService;/*** 新增套餐*/@PostMapping@ApiOperation("新增套餐")@CacheEvict(cacheNames = "setmealCache", key = "#setmealDTO.categoryId")public Result save(@RequestBody SetmealDTO setmealDTO) {log.info("新增套餐");setmealService.saveWithDishes(setmealDTO);return Result.success();}/*** 分页查询套餐*/@GetMapping("/page")@ApiOperation("分页查询套餐")public Result<PageResult> page(SetmealPageQueryDTO setmealPageQueryDTO) {log.info("分页查询套餐:{}", setmealPageQueryDTO);PageResult pageResult = setmealService.pageQuery(setmealPageQueryDTO);return Result.success(pageResult);}/*** 删除套餐*/@DeleteMapping@ApiOperation("删除套餐")@CacheEvict(cacheNames = "setmealCache", allEntries = true)public Result delete(@RequestParam List<Long> ids) {log.info("删除套餐:{}", ids);setmealService.deleteBatch(ids);return Result.success();}/*** 根据id查询套餐*/@GetMapping("/{id}")@ApiOperation("根据id查询套餐")public Result<SetmealVO> getById(@PathVariable Long id) {log.info("根据id查询套餐:{}", id);SetmealVO setmealVO = setmealService.getByIdWithDish(id);return Result.success(setmealVO);}/*** 修改套餐*/@PutMapping@ApiOperation("修改套餐")@CacheEvict(cacheNames = "setmealCache", allEntries = true)public Result update(@RequestBody SetmealDTO setmealDTO) {log.info("修改套餐:{}", setmealDTO);setmealService.updateWithDishes(setmealDTO);return Result.success();}/*** 修改套餐状态*/@PostMapping("/status/{status}")@ApiOperation("修改套餐状态")@CacheEvict(cacheNames = "setmealCache", allEntries = true)public Result updateStatus(@PathVariable Integer status, Long id) {log.info("修改套餐状态:{}", id);setmealService.updateStatus(status, id);return Result.success();}
}

http://www.ppmy.cn/news/1536182.html

相关文章

在Ubuntu 18.04上安装Webmin的方法

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 介绍 Webmin 是一个基于 Web 的控制面板&#xff0c;适用于任何 Linux 机器&#xff0c;它可以让你通过现代化的 Web 界面管理服务器。…

解锁空间距离计算的多种方式-含前端、空间数据库、后端

目录 前言 一、空间数据库求解 1、PostGIS实现 二、GIS前端组件求解 1、Leaflet.js距离测算 2、Turf.js前端计算 三、后台距离计算生成 1、欧式距离 2、Haversice球面距离 3、GeoTools距离计算 4、Gdal距离生成 5、geodesy距离计算 四、成果与生成对比 1、Java不…

深度学习-20-深入理解基于Streamlit和minimind小模型开发本地聊天工具

文章目录 1 Streamlit开发聊天工具1.1 初始化聊天信息1.2 渲染历史信息1.3 接收用户输入1.4 模拟调用LLM1.5 整体代码2 使用minimind2.1 下载模型2.2 使用模型3 Streamlit与minimind3.1 Streamlit相关知识点3.2 示例代码4 参考附录1 Streamlit开发聊天工具 Streamlit是一个开源…

FPGA时序分析和约束学习笔记(1、FPGA基本原理)

FPGA时序分析和约束学习笔记-&#xff08;1、FPGA基本原理&#xff09; Field现场Programmable可编程Gate门Array阵列 1、FPGA基本资源组成 可编程逻辑功能块&#xff08;logic elements &#xff0c;缩写LE&#xff09; 片内互联线&#xff08;interconnect&#xff0c;缩写…

Nginx的核心架构和设计原理

Nginx 是一个免费的、开源的、高性能 Http 服务器和反向代理。Nginx 的架构设计是为了提供高性能、稳定性和可扩展性。 Nginx 的主要架构组件和工作原理&#xff1a; 1、Master 进程&#xff1a;Nginx 的运行始于一个 master 进程&#xff0c;它负责管理所有的工作进程。mast…

基于少样本(小样本)的图像分割

在少样本学习&#xff08;尤其是少样本分割&#xff09;中&#xff0c;query branch 和 support branch 分别承担不同的任务&#xff0c;目的是通过少量标注的样本来实现对新图像的分割。它们的具体作用如下&#xff1a; Support Branch&#xff08;支持分支&#xff09;&#…

低代码可视化-UniApp二维码可视化-代码生成器

市面上提供了各种各样的二维码组件&#xff0c;做了一简单的uniapp二维码组件&#xff0c;二维码实现依赖davidshimjs/qrcodejs。 组件特点 跨浏览器支持&#xff1a;利用Canvas元素实现二维码的跨浏览器兼容性&#xff0c;兼容微信小程序、h5、app。 无依赖性&#xff1a;QR…

【PyTorch】图像分割

图像分割是什么 Image Segmentation 将图像每一个像素分类 图像分割分类 超像素分割&#xff1a;少量超像素代替大量像素&#xff0c;常用于图像预处理语义分割&#xff1a;逐像素分类&#xff0c;无法区分个体实例分割&#xff1a;对个体目标进行分割全景分割&#xff1a;…