【项目实战 Day7】springboot + vue 苍穹外卖架构(微信小程序 + 微信登录模块 完结)

news/2025/9/27 11:31:57/文章来源:https://www.cnblogs.com/wzzkaifa/p/19114882

目录

一、缓存菜品模块(代码实现redis缓存)

1、问题分析

2、缓存菜品数据

3、清理缓存数据

为什么在管理员端对缓存数据进行清理?

二、缓存套餐模块(注解实现redis缓存)

1、Spring Cache框架

(1)常用注解

2、用注解方式实现缓存套餐功能

三、购物车模块

1、添加购物车 - POST接口

(1)需求分析

像name、image、amount这些属于冗余字段,为什么要设置冗余字段?

(2)代码开发

2、查看购物车 - GET接口

3、清空购物车 - DELETE接口

4、删除购物车中的一个商品 - POST接口


一、缓存菜品模块(代码实现redis缓存)

1、问题分析

  • 用户端小程序展示菜品数据都是通过查询数据库获得,如果用户访问量大,数据库访问压力就会随之增大
  • 因此我们通过 Redis 缓存菜品数据,可以减少数据库查询操作,提高效率

2、缓存菜品数据

  • 在DishController中加入查询Redis是否存在缓存的判断逻辑
  • 若Redis存在缓存数据,直接返回,否则查询数据库并存入Redis
@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(Long categoryId) {
//1.构造redis中的key,规则:dish_分类id
String key = "dish_" + categoryId;
//2.查询redis是否存在菜品数据
List list = (List) redisTemplate.opsForValue().get(key);
if(list != null && list.size() > 0){
//3.如果存在,直接返回,无需查询数据库
return Result.success(list);
}
//3.如果不存在,查询数据库,将查询的数据存入redis
Dish dish = new Dish();
dish.setCategoryId(categoryId);
dish.setStatus(StatusConstant.ENABLE);//查询起售中的菜品
list = dishService.listWithFlavor(dish);
redisTemplate.opsForValue().set(key,list);
return Result.success(list);
}
}

3、清理缓存数据

如果没有清理redis缓存,以下功能会出现问题:

  • 新增菜品:管理员虽然新增了菜品,但由于redis内旧数据未清理,用户仍然只能看到以前的菜品数据,看不到新增的菜品(controller层查询redis是否有对应数据,如果查到了直接在controller层返回,根本不会去数据库拿新增的数据)
  • 删除菜品:管理员虽然在后端删除了菜品,但由于redis内旧数据未清理,用户仍然还能看到被删除的菜品数据
  • 修改菜品:管理员虽然修改了菜品,但由于redis内旧数据未清理,用户看到的菜品数据依旧是未更新之前的
  • 菜品起售停售:管理员虽然更改了菜品状态,但由于redis内旧数据未清理,用户看到的菜品状态依旧是未更新之前的

所以我们需要在Admin端对缓存数据进行清理

为什么在管理员端对缓存数据进行清理?

因为管理员端需要清理缓存后,再进行增删改,这样用户端才能看到最新数据

下面是增加清理缓存功能的Admin - DishController

/**
* 菜品管理
*/
@RestController
@RequestMapping("/admin/dish")
@Api(tags = "菜品相关接口")
@Slf4j
public class DishController {
@Autowired
private DishService dishService;
@Autowired
private RedisTemplate redisTemplate;
/**
* 新增菜品
* @param dishDTO
* @return
*/
@PostMapping
@ApiOperation("新增菜品")
public Result save(@RequestBody DishDTO dishDTO){
log.info("新增菜品:{}",dishDTO);
dishService.saveWithFlavor(dishDTO);
//清理缓存数据
String key = "dish_" + dishDTO.getCategoryId();
cleanCache(key);
return Result.success();
}
/**
* 菜品分页查询
* @param dishPageQueryDTO
* @return
*/
@GetMapping("/page")
@ApiOperation("菜品分页查询")
public Result page(DishPageQueryDTO dishPageQueryDTO){
log.info("菜品分页查询:{}",dishPageQueryDTO);
PageResult pageResult = dishService.pageQuery(dishPageQueryDTO);
return Result.success(pageResult);
}
/**
* 批量删除菜品
* @param ids
* @return
*/
@DeleteMapping
@ApiOperation("批量删除菜品")
public Result detele(@RequestParam List ids){
log.info("批量删除:{}",ids);
dishService.deleteBatch(ids);
//将所有菜品缓存数据清除,所有以dish_开头的key
cleanCache("dish_*");
return Result.success();
}
/**
* 根据id查询菜品
* @param id
* @return
*/
@GetMapping("/{id}")
@ApiOperation("根据id查询菜品")
public Result getById(@PathVariable Long id){
log.info("根据id查询菜品:{}",id);
DishVO dishVO = dishService.getByIdWithFlavor(id);
return Result.success(dishVO);
}
/**
* 修改菜品
* @param dishDTO
* @return
*/
@PutMapping
@ApiOperation("修改菜品")
public Result update(@RequestBody DishDTO dishDTO){
log.info("修改菜品:{}",dishDTO);
dishService.updateWithFlavor(dishDTO);
//将所有菜品缓存数据清除,所有以dish_开头的key
cleanCache("dish_*");
return Result.success();
}
/**
* 菜品起售停售
* @param status
* @param id
* @return
*/
@PostMapping("/status/{status}")
@ApiOperation("起售停售菜品")
public Result startOrStop(@PathVariable Integer status, Long id){
log.info("起售停售菜品:{},{}",status,id);
dishService.startOrStop(status,id);
//将所有菜品缓存数据清除,所有以dish_开头的key
cleanCache("dish_*");
return Result.success();
}
/**
* 根据分类id查询菜品
* @param categoryId
* @return
*/
@GetMapping("/list")
@ApiOperation("根据分类id查询菜品")
public Result> list(Long categoryId){
List list = dishService.getByCategoryId(categoryId);
return Result.success(list);
}
/**
* 清除缓存数据
* @param pattern
*/
private void cleanCache(String pattern){
Set keys = redisTemplate.keys(pattern);
redisTemplate.delete(keys);
}
}

这样,当我们在后端修改、新增、删除、改变菜品状态时,用户端也能将数据及时更新

二、缓存套餐模块(注解实现redis缓存)

1、Spring Cache框架

Spring Cache 是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能。
Spring Cache 提供了一层抽象,底层可以切换不同的缓存实现,例如:EHCache、Caffeine、Redis

(1)常用注解

注解说明位置
@EnableCaching开启缓存注解功能放启动类上
@Cacheable

在方法执行前先查询缓存中是否有数据,如果有数据则直接返回缓存数据

如果没有缓存数据,调用方法并将方法返回值放到缓存中(既能取数据,又能放缓存)

放方法上
@CachePut将方法的返回值放到缓存中(只能放缓存)放方法上
@CacheEvict将一条或多条数据从缓存中删除放方法上








2、用注解方式实现缓存套餐功能

步骤:

  1. 导入Spring Cache和Redis相关maven坐标
  2. 在启动类上加入@EnableCaching注解,开启缓存注解功能
  3. 在用户端接口SetmealController的 list 方法上加入@Cacheable注解
  4. 在管理端接口SetmealController的 save、delete、update、startOrstop等方法上加入CacheEvict注解

(1)导入Spring Cache和Redis的maven

org.springframework.boot
spring-boot-starter-data-redis
org.springframework.boot
spring-boot-starter-cache

(2)在启动类上加入@EnableCaching注解

(3)用户端接口SetmealController的 list 方法上加入@Cacheable注解

为什么只在【根据分类id查询套餐】方法上加Cache注解?

  • 因为该方法是基础查询,用户可能会频繁访问查询套餐,因此需要在该方法上加入Cache注解,而下面【根据套餐id查询菜品】的功能,相对于该方法的访问就没有那么频繁,因此不加Cache注解
/**
* 条件查询
*
* @param categoryId
* @return
*/
@GetMapping("/list")
@ApiOperation("根据分类id查询套餐")
//查询前先在redis中查是否有相应数据,如果有,直接返回;如果没有,再从数据库查,查完存入redis缓存
@Cacheable(cacheNames = "setmealCache",key = "#categoryId") //生成key:setmealCache::100
public Result> list(Long categoryId) {
Setmeal setmeal = new Setmeal();
setmeal.setCategoryId(categoryId);
setmeal.setStatus(StatusConstant.ENABLE);
List list = setmealService.list(setmeal);
return Result.success(list);
}

(4)管理端接口SetmealController的 save、delete、update、startOrstop等方法上加入CacheEvict注解

【1】save

为什么key是setmealDTO.categoryId而不是setmealDTO.id?

  • 因为新增套餐前,需要把该套餐【所属分类下的所有套餐】缓存全部删除,否则新增后,用户界面读取的依旧是缓存内的旧数据
  • 比如:缓存内 → 分类A[套餐1,套餐2,套餐3],现在管理员新增套餐4,需要先将分类A下的套餐1、2、3缓存数据清理掉,再新增套餐4,此时用户查询分类A下的套餐,后端发现缓存中并没有分类A套餐信息,故从数据库中查询出数据 分类A[套餐1,套餐2,套餐3,套餐4],并将其存入redis缓存,这样用户端就能看到新增的套餐4
  • 如果key = setmealDTO.id会怎么样?
  • 比如新增套餐4,新增前删除缓存,key为套餐id,即删除【key=套餐4的id】这条缓存,问题是删除的时候套餐4还没加进来,哪里来的缓存?因此我们删除时应该采用分类id,这样删除的是该分类下的所有菜品缓存
/**
* 新增套餐
* @param setmealDTO
* @return
*/
@PostMapping
@ApiOperation("新增套餐")
@CacheEvict(cacheNames = "setmealCache",key = "#setmealDTO.categoryId")
public Result save(@RequestBody SetmealDTO setmealDTO){
log.info("新增套餐:{}",setmealDTO);
setmealService.saveWithDish(setmealDTO);
return Result.success();
}

【2】delete

/**
* 批量删除套餐
* @param ids
* @return
*/
@DeleteMapping
@ApiOperation("批量删除套餐")
@CacheEvict(cacheNames = "setmealCache",allEntries = true)
public Result delete(@RequestParam List ids){
log.info("批量删除:{}",ids);
setmealService.deleteBatch(ids);
return Result.success();
}

【3】update

/**
* 修改套餐
* @param setmealDTO
* @return
*/
@PutMapping
@ApiOperation("修改套餐")
@CacheEvict(cacheNames = "setmealCache",allEntries = true)
public Result update(@RequestBody SetmealDTO setmealDTO){
log.info("修改套餐信息:{}",setmealDTO);
setmealService.update(setmealDTO);
return Result.success();
}

【4】startOrstop

/**
* 起售停售套餐
* @param status
* @param id
* @return
*/
@PostMapping("/status/{status}")
@ApiOperation("起售停售套餐")
@CacheEvict(cacheNames = "setmealCache",allEntries = true)
public Result startOrStop(@PathVariable Integer status,Long id){
log.info("起售停售套餐:{},{}",status,id);
setmealService.startOrStop(status,id);
return Result.success();
}

三、购物车模块

1、添加购物车 - POST接口

(1)需求分析

像name、image、amount这些属于冗余字段,为什么要设置冗余字段?

设置冗余字段主要是为了用空间换时间,提升查询性能

冗余字段要求:不频繁改变、相对稳定

(2)代码开发

【1】controller层

/**
* 添加购物车
* @param shoppingCartDTO
* @return
*/
@PostMapping("/add")
@ApiOperation("添加购物车")
public Result add(@RequestBody ShoppingCartDTO shoppingCartDTO){
log.info("添加购物车:{}",shoppingCartDTO);
shoppingCartService.addShoppingCart(shoppingCartDTO);
return Result.success();
}

【2】service层

将菜品/套餐加入购物车时,需要进行以下判断:

  • 查询购物车中是否存在该菜品/套餐
    • DTO中只含dish_id菜品id、setmeal_id套餐id、dish_flavor口味表,但我们查询时需要通过【user_id】+【菜品/套餐id】,因此我们用实体类存数据,并用线程获取当前userid绑定在实体类中
    • 将该实体类传入mapper层进行条件查询
  • 如果购物车中存在该菜品/套餐
    • 获取该菜品/套餐数量,然后+1,更新这条购物车记录
  • 如果购物车中不存在该菜品/套餐
    • 判断一下添加到是套餐or菜品,然后通过获取菜品表/套餐表的image图片、amount价格、name名字,将其补充至这条购物车记录中(补充冗余数据)
    • 接着设置该商品数量为1,并设置记录创建时间
    • 最后将这条补充好的记录插入购物车表中
/**
* 添加购物车
* @param shoppingCartDTO
*/
public void addShoppingCart(ShoppingCartDTO shoppingCartDTO) {
//1.判断购物车中,该商品是否存在
// 因为DTO中只有dishid、setmealid、dishFlavor,而我们需要userid查询
// 所以将DTO转为实体类,如果数据库表结构变化,只需要调整Entity和转换逻辑,不影响对外的DTO接口,保持接口稳定性
ShoppingCart shoppingCart = new ShoppingCart();
BeanUtils.copyProperties(shoppingCartDTO,shoppingCart);
Long currentId = BaseContext.getCurrentId();
shoppingCart.setUserId(currentId);
//为什么用list集合?
//返回集合是为了接口通用,后面查询购物车也能用,但是这里只会有一个数据
List list = shoppingCartMapper.list(shoppingCart);
//2.如果存在,商品数量+1
if(list != null && list.size() > 0){
//每一次请求操作只会传入一条数据,也就是第一条
ShoppingCart cart = list.get(0);
cart.setNumber(cart.getNumber() + 1);
//更新一下商品数量
shoppingCartMapper.updateNumberById(cart);
}else{
//3.如果不存在,添加进购物车
//判断一下新增的是菜品or套餐
Long dishId = shoppingCart.getDishId();
if(dishId != null){
//本次加入购物车的是菜品
Dish dish = dishMapper.getById(dishId);
//加入一些原本购物车内没有的元素:照片、价格、菜名
shoppingCart.setImage(dish.getImage());
shoppingCart.setAmount(dish.getPrice());
shoppingCart.setName(dish.getName());
}else{
//本次加入购物车的是套餐
Long setmealId = shoppingCart.getSetmealId();
Setmeal setmeal = setmealMapper.getById(setmealId);
shoppingCart.setImage(setmeal.getImage());
shoppingCart.setAmount(setmeal.getPrice());
shoppingCart.setName(setmeal.getName());
}
shoppingCart.setNumber(1); //新加入购物车的数量为1
shoppingCart.setCreateTime(LocalDateTime.now());
shoppingCartMapper.insert(shoppingCart);
}
}

【3】mapper层

@Mapper
public interface ShoppingCartMapper {
/**
* 条件查询
* @param shoppingCart
* @return
*/
List list(ShoppingCart shoppingCart);
/**
* 修改购物车数量
* @param shoppingCart
*/
@Update("update sky_take_out.shopping_cart set number = #{number} where id = #{id}")
void updateNumberById(ShoppingCart shoppingCart);
/**
* 插入购物车数据
* @param shoppingCart
*/
@Insert("insert into sky_take_out.shopping_cart (name,user_id,dish_id,setmeal_id,dish_flavor,number,amount,image,create_time)" +
"values (#{name},#{userId},#{dishId},#{setmealId},#{dishFlavor},#{number},#{amount},#{image},#{createTime})" )
void insert(ShoppingCart shoppingCart);
}

【4】mybatis文件

select * from sky_take_out.shopping_cart
and user_id = #{userId}
and dish_id = #{dishId}
and setmeal_id = #{setmealId}
and dish_flavor = #{dishFlavor}

2、查看购物车 - GET接口

【1】controller层

/**
* 查看购物车
* @return
*/
@GetMapping("/list")
@ApiOperation("查看购物车")
public Result> list(){
List list = shoppingCartService.showShoppingCart();
return Result.success(list);
}

【2】service层

/**
* 查看购物车
* @return
*/
public List showShoppingCart() {
ShoppingCart shoppingCart = new ShoppingCart();
Long currentId = BaseContext.getCurrentId();
shoppingCart.setUserId(currentId);
List list = shoppingCartMapper.list(shoppingCart);
return list;
}

3、清空购物车 - DELETE接口

【1】controller层

/**
* 清空购物车
* @return
*/
@DeleteMapping("/clean")
@ApiOperation("清空购物车")
public Result delete(){
shoppingCartService.deleteAll();
return Result.success();
}

【2】service层

/**
* 清空购物车
*/
public void deleteAll() {
Long user_id = BaseContext.getCurrentId();
shoppingCartMapper.deleteAllByUserId(user_id);
}

【3】mapper层

/**
* 删除当前用户的全部购物车数据
* @param user_id
*/
@Delete("delete from sky_take_out.shopping_cart where user_id = #{user_id}")
void deleteAllByUserId(Long user_id);

4、删除购物车中的一个商品 - POST接口

【1】controller层

/**
* 删除购物车的一个商品
* @param shoppingCartDTO
* @return
*/
@PostMapping("/sub")
@ApiOperation("删除购物车的一个商品")
public Result delete(@RequestBody ShoppingCartDTO shoppingCartDTO){
shoppingCartService.delete(shoppingCartDTO);
return Result.success();
}

【2】service层

这里逻辑和添加购物车差不多

  • 添加购物车时要先看该商品是否在车里,同理,在删除该商品前,要先看该商品是否在车里
  • 如何查询该商品是否在车里?
    • 将DTO中存在的【dish_id、setmeal_id、dish_flavor】 + 线程获得的【user_id】加入购物车实体类
    • 将这个购物车实体传入mapper层的条件查询list中
    • 如果该商品存在车内,那么list查询返回的列表不为空,且商品唯一,我们就进行删除;否则就不需要做删除操作
    • 当确定商品存在购物车内,又分两种情况:
      • 1、该商品只有1件,此时只需要根据【当前购物车记录id】直接删除这条商品购物车记录即可
      • 2、该商品有多件,此时只需要修改商品数量为原来-1即可
/**
* 删除购物车的一个商品
* @param shoppingCartDTO
*/
public void delete(ShoppingCartDTO shoppingCartDTO) {
//删除前先看一下购物车内是否有该商品
ShoppingCart shoppingCart = new ShoppingCart();
BeanUtils.copyProperties(shoppingCartDTO,shoppingCart);
shoppingCart.setUserId(BaseContext.getCurrentId());
//获取当前匹配的购物车记录(只有一条)
List list = shoppingCartMapper.list(shoppingCart);
//如果存在该商品,就删掉
if(list != null && list.size() > 0){
shoppingCart = list.get(0);
Integer num = shoppingCart.getNumber();
if(num == 1){
//如果该商品只有一个,直接删掉该商品
shoppingCartMapper.deleteById(shoppingCart.getId());
}else{
//其他情况修改份数
shoppingCart.setNumber(num - 1);
shoppingCartMapper.updateNumberById(shoppingCart);
}
}
}

【2】mapper层

/**
* 根据id删除购物车记录
* @param id
*/
@Delete("delete from sky_take_out.shopping_cart where id = #{id}")
void deleteById(Long id);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/919401.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入解析:Pytorch框架笔记

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

网站建设服务标准ui网页界面设计素材

文章目录 一、stack的使用1.stack的介绍2.stack的使用 二、queue的使用1.queue的护额晒2.queue的使用 三、stack和queue相关算法题1.最小栈2.栈的压入、弹出序列3.逆波兰表达式4.两个栈实现一个队列5.用两个队列实现栈6.二叉树的层序遍历1.双队列2.用一个变量levelSize去控制 7…

北极通讯网络题解(做题记录)

北极通讯网络题解(做题记录) 前言 本文以一道 Kruskal 的好题实例来讲一下 Kruskal 的过程,对于初学 Kruskal 的OIer们有很大的帮助。 luogu 相似题:P1991 无线通讯网。 题目简述 有 n 座村庄,每座村庄的坐标用一对…

如何在局域网中做网站wordpress怎样发布时间

SpringMVC 的入门 1环境搭建 1.1.创建工程 1.2.添加web支持 右键项目选择Add framework support... 2.添加web支持 ​ 3.效果 注意&#xff1a; 不要先添加打包方式将web目录要拖拽到main目录下&#xff0c;并改名为webapp 1.3.pom.xml <?xml version"1.0&q…

elasticsearch安装插件 - 实践

elasticsearch安装插件 - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco"…

个人学习——前端react项目框架

文件作用 package.json npm脚本部分"scripts" 项目启动与打包"dev": "vite" 启动 开发环境,开启本地服务器,支持热更新。 用法:npm run dev "build": "tsc &&…

软件基础第一次作业

这个作业属于哪个课程 https://edu.cnblogs.com/campus/zjlg/25rjjc这个作业的目标 对自我进行分析和评估,了解博客使用方法,说明对课程的想法姓名-学号 林子渊 2023333503079自我介绍: 我叫林子渊,来自 23 自动化…

网站建设7个基本流程分析统一门户登录

一、简述 这里的代码主要是基于图像的推荐系统,该系统利用 ResNet-50 深度学习模型作为特征提取器,并采用余弦相似度来查找给定输入图像的最相似嵌入。 该系统旨在根据所提供图像的视觉内容为用户提供个性化推荐。 二、所需环境 Python 3.x tensorflow ==2.5.0 numpy==1.21.…

.net商城网站模板下载宁乡电商网站建设收费

title: URL编码&#xff1a;原理、应用与安全性 date: 2024/3/29 18:32:42 updated: 2024/3/29 18:32:42 tags: URL编码百分号编码特殊字符处理网络安全应用场景标准演变未来发展 在网络世界中&#xff0c;URL&#xff08;统一资源定位符&#xff09;是我们访问网页、发送请求…

LGP9755 [CSP-S 2023] 种树 学习笔记

LGP9755 [CSP-S 2023] 种树 学习笔记 Luogu Link 前言 故地重游。 巧合的是,上次写这道题刚好是在去年的九月二十七日,整整一年前。 题意简述 给定一个 \(n\) 个点,\(n-1\) 条边的简单无向连通图。好吧,这片地本身…

7、revision 是 Maven 3.5+ 引入的现代版本管理机制 - 实践

7、revision 是 Maven 3.5+ 引入的现代版本管理机制 - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consol…

P1731 生日蛋糕 做题记录

洛谷P1731 生日蛋糕 做题记录 题意简述 一个生日蛋糕由几个圆柱体组成,每个圆柱体的底面半径和高从下到上严格递减,现给出蛋糕的体积 N pi 以及层数 M,试求蛋糕的最小表面积。 思路速通 基本为 DFS ,对于每层的半径…

详细介绍:【MySQL】MySQL数据库入门指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

如何有效提升代码覆盖率:从单元测试到集成测试的实践指南

Go语言代码覆盖率实现 一、什么是代码覆盖率代码覆盖率是软件测试中的一种白盒测试度量指标,表示程序源代码中被执行的比例。简单来说,就是“我的测试到底跑过多少代码”。 覆盖率常见的几种标准:语句覆盖(段覆盖、…

深入解析:SSM网络游戏交易系统a9n72(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面

深入解析:SSM网络游戏交易系统a9n72(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto …

Spring知识点(2)

一、有哪些依赖注入方式?构造方法注入:通过调用类的构造方法,推荐用于强依赖(没有依赖对象就没法工作)。这也是官方推荐的注入方式。好处:依赖不可变(final修饰)、更安全。@Component public class UserServic…

成都电子商务网站建设非寻服饰网站建设规划书

文章目录 “预训练微调大模型”的模式以提示/指令模式直接使用大模型“预训练微调大模型”模式和Prompt/Instruct模式的异同小结 “预训练微调大模型”的模式 经过预训练的大模型所习得的语义信息和所蕴含的语言知识&#xff0c;很容易向下游任务迁移。NLP应用人员可以根据自己…

超越实习期的AI自动化工具:播客工作流与Slack导出器实战

本文详细介绍实习期间基于Claude AI模型开发的两个自动化工具:播客工作流年省1250小时人工,Slack导出器实现智能知识检索。包含技术架构、问题解决方案和实际应用效果,展现AI如何增强企业工作效率。超越实习期的实习…

调度器的各项指标以及计算方式

CPU利用率 \[利用率=\frac{忙碌的时间}{总时间} \]系统吞吐量 单位时间内完成作业的数量 \[系统吞吐量=\frac{总共完成了多少道作业}{总共花了多少时间} \]周转时间 1.周转时间-平均周转时间\[作业周转时间=作业完成时…

​CentOS 7 安装 net-tools.rpm 包步骤详解(附 rpm 命令和 yum 方法)​附安装包

​CentOS 7 安装 net-tools.rpm 包步骤详解(附 rpm 命令和 yum 方法)​附安装包​一、先确认你的系统是 CentOS 7 或 RHEL 7 这个包是专门给 ​CentOS 7​ 或者 ​RHEL 7​(也就是 64 位系统)用的,文件名里的 el7…