当前位置: 首页 > news >正文

ASP.NET Core 中服务生命周期详解:Scoped、Transient 和 Singleton 的业务场景分析

在这里插入图片描述

前言

在 ASP.NET Core 中,服务的生命周期直接影响应用的性能和行为。通过依赖注入容器 (Dependency Injection, DI),我们可以为服务定义其生命周期:ScopedTransientSingleton。本文将详细阐述这些生命周期的区别及其在实际业务中的应用场景。

服务生命周期简介

ASP.NET Core 中的服务生命周期分为以下三种:

  1. Scoped: 每次 HTTP 请求创建一个实例,在请求范围内共享。
  2. Transient: 每次请求服务时都会创建一个新的实例。
  3. Singleton: 应用程序启动时创建一个实例,整个应用生命周期内共享。

选择服务生命周期的基本原则:

  • Scoped:适用于在请求内共享服务的场景。
  • Transient:适用于短生命周期的无状态服务。
  • Singleton:适用于全局共享且线程安全的服务。

接下来,我们结合业务场景,详细分析这三种生命周期的具体使用方法。

场景分析

1. Scoped:每个请求共享一个实例

特点

  • 服务实例的生命周期与当前 HTTP 请求相同。
  • 同一个请求上下文中,依赖于此服务的组件共享实例。
  • 请求结束时,服务实例会被释放。

典型业务场景

1.1 数据库访问服务(如 DbContext
  • 原因DbContext 是线程不安全的,需要为每个 HTTP 请求创建独立实例,避免并发问题。
  • 应用场景:当需要访问数据库时,每个请求创建一个新的 DbContext
  • 代码示例
    services.AddScoped<DbContext>();
    
    在 Controller 中:
    public class ProductsController : ControllerBase
    {private readonly DbContext_context;public ProductsController(DbContext context){_context = context;}public IActionResult GetProducts() => Ok(_context.Products.ToList());
    }
    
1.2 用户状态管理
  • 原因:用户特定信息(如用户 ID)通常需要在请求生命周期内共享,而不是全局共享。
  • 应用场景:用于跟踪用户的会话状态。
  • 代码示例
    services.AddScoped<IUserSessionService, UserSessionService>();
    
    Service 实现:
    public class UserSessionService : IUserSessionService
    {public string UserId { get; set; }
    }
    
1.3 中间件共享上下文
  • 原因:多个中间件可能需要共享日志上下文或其他临时数据。
  • 代码示例
    services.AddScoped<ILoggingContext, LoggingContext>();
    

2. Transient:每次调用都会创建新实例

特点

  • 每次请求服务时都会创建一个新的对象实例。
  • 不共享状态,适合轻量级的无状态服务。

典型业务场景

2.1 工具类(如加解密服务)
  • 原因:工具类通常无状态,每次调用都应生成新实例,避免潜在的状态共享问题。
  • 应用场景:用户密码加密、解密。
  • 代码示例
    services.AddTransient<IEncryptionService, EncryptionService>();
    
2.2 动态报告生成
  • 原因:生成 PDF 或 Excel 报告时,需要为每个任务创建独立上下文。
  • 代码示例
    services.AddTransient<IReportGenerator, PdfReportGenerator>();
    
2.3 邮件发送服务
  • 原因:每封邮件通常是独立的任务,不应共享实例。
  • 代码示例
    services.AddTransient<IEmailService, EmailService>();
    

3. Singleton:整个应用程序共享一个实例

特点

  • 在应用程序启动时创建实例,并在整个应用生命周期中保持存在。
  • 适合全局共享且线程安全的服务。

典型业务场景

3.1 配置服务
  • 原因:应用程序配置是全局的,单例生命周期可以减少重复加载。
  • 代码示例
    services.AddSingleton<IConfiguration>(Configuration);
    
3.2 缓存服务
  • 原因:缓存需要在多个请求之间共享。
  • 应用场景:全局数据缓存(如 Redis 或内存缓存)。
  • 代码示例
    services.AddSingleton<ICacheService, MemoryCacheService>();
    
3.3 日志服务
  • 原因:日志服务是无状态的,全局单例可以减少实例化的性能开销。
  • 代码示例
    services.AddSingleton<ILogger, Logger>();
    
3.4 HTTP 客户端
  • 原因HttpClient 是线程安全的,推荐作为单例使用以节省资源。
  • 代码示例
    services.AddSingleton<HttpClient>();
    

4. 场景小结

服务类型生命周期典型场景
Scoped每个请求共享实例数据库上下文、用户状态管理、中间件共享数据
Transient每次调用新建实例工具类、邮件发送服务、动态报告生成
Singleton全局共享实例配置服务、缓存服务、日志服务、HTTP 客户端

组合场景

在实际开发中,示例一中的 DbContext 通常不会直接注入到控制器中,而是通过业务服务(Service)间接使用。这种做法更符合分层架构的设计理念,也便于维护和测试。那么一共有几种方式进行组合?

1. Scoped + Scoped

在这种组合中, Scoped 生命周期的服务和 DbContext 都是按请求(Request)创建的,即在同一个请求的整个生命周期内,共享同一个实例。通常,DbContextScoped 生命周期的,因为它依赖于数据库连接池,且每个请求中只需要一个数据库上下文实例来执行操作。这种方式适用于大多数需要数据库访问的场景。

分析:
  • DbContext 是线程不安全的,Scoped 生命周期确保每个 HTTP 请求拥有独立的实例。
  • DbContext 注入到 Service 中,而非直接注入控制器,能够实现更清晰的分层结构:
  • 控制器负责处理 HTTP 请求。
  • Service 负责业务逻辑处理。
  • DbContext 负责数据访问。
注入形式:
public void ConfigureServices(IServiceCollection services)
{services.AddScoped<DbContext>();services.AddScoped<IProductService,ProductService>();
}

ProductService

    public class ProductService:IProductService{private readonly DbContext _context;public ProductService(DbContext context){_context = context;}public IEnumerable<Product> GetProducts(){return _context.Products.ToList();}}
适用场景:

推荐用于需要数据库访问并且依赖于多个服务的业务逻辑。

2. Transient + Scoped

在这种组合中,每次请求时,Service 会创建新的实例,但它会共享同一个 DbContext 实例。Transient 服务通常用于无状态的轻量级任务,而 Scoped 生命周期的 DbContext 则是按请求范围共享的,这种组合适用于那些轻量且无状态的操作,但又需要在多个服务间共享数据库上下文。

分析:
  • DbContext 的生命周期是 Scoped
  • 每个 HTTP 请求范围内只有一个 DbContext 实例。
  • 即使多个 Transient Service 依赖 DbContext,它们共享同一个实例。
  • Service 的生命周期是 Transient
  • 每次请求 Service 时都会创建一个新的实例。
  • 适合无状态的服务,但共享 DbContext 实例。
注入形式:
public void ConfigureServices(IServiceCollection services)
{services.AddScoped<DbContext>();services.AddTransient<IProductService,ProductService>();
}

ProductService

 public class ProductService:IProductionService{private readonly DbContext _context;public ProductService(DbContext context){_context = context;}public void AddProduct(string productName){var product = new Product { Name = productName };_context.Products.Add(product);_context.SaveChanges();}}
适用场景:

适合无状态的轻量级任务或简单的业务逻辑,如某些简单的服务层操作。

Transient Service 的潜在问题

虽然这种设计是可行的,但需要注意以下潜在问题:

多个 Transient Service 共享 DbContext 的问题
  • 如果多个 Transient Service 在同一个请求中依赖 DbContext,它们共享同一个实例。
  • 如果其中一个 Service 修改了 DbContext 的状态,其他 Service 会感知到这些更改。
    services.AddTransient<IProductService, ProductService>();
    services.AddTransient<IOrderService, OrderService>();
    
    如果 ProductServiceOrderService 都依赖于 DbContext,它们共享同一个实例,可能导致意外的并发问题。
生命周期与状态
  • Transient Service 是无状态的,但 DbContext 是有状态的(如跟踪实体)。
  • 如果一个 Transient Service 修改了 DbContext 的状态,而其他 Service 对此不了解,可能导致数据一致性问题。

3. Singleton + Scoped

这种组合通常会引发生命周期冲突问题。Singleton 服务在整个应用程序生命周期内只会创建一个实例,而 Scoped 生命周期的服务(如 DbContext)每个请求都会创建新的实例。Singleton 依赖于 Scoped 服务时,如果没有通过工厂或 IServiceProvider 动态解析,它会导致生命周期不一致的问题,可能导致意外的行为和线程安全问题。

分析:
  • 如果 IProductService 被注册为 Singleton,而它依赖于 Scoped 的DbContext,会导致生命周期不匹配的问题。
  • DbContext 是 Scoped 的,但被 Singleton 的服务持有。
  • 在多个请求中,Service 会共享一个 DbContext 实例,导致线程安全问题。
注入形式:
public void ConfigureServices(IServiceCollection services)
{services.AddScoped<DbContext>();services.AddSingleton<IProductService,ProductService>();
}
  • 适用场景
    不推荐,除非有明确需求且能够确保线程安全。通常需要通过工厂方法或显式依赖注入来解决这种问题。
    使用 IServiceProvider 动态解析
 public void ConfigureServices(IServiceCollection services){services.AddScoped<DbContext>();services.AddSingleton<SingletonService>();}public class SingletonService{private readonly IServiceProvider _serviceProvider;public SingletonService(IServiceProvider serviceProvider){_serviceProvider = serviceProvider;}public void ExecuteDatabaseOperation(){// 动态解析 Scoped 的 DbContext 实例using (var scope = _serviceProvider.CreateScope()){var context = scope.ServiceProvider.GetRequiredService<DbContext>();// 执行数据库操作var product = context.Products.FirstOrDefault();}}}
使用工厂方法解决生命周期冲突
  • 如果必须将 Service 注册为 Singleton(例如缓存某些只初始化一次的资源),可以通过 IServiceProvider 动态获取 Scoped 的 DbContext 实例。
    services.AddSingleton<IProductService>(provider =>
    {var dbContext = provider.GetRequiredService<DbContext>();return new ProductService(dbContext);
    });
    

4. 组合使用小结

  • Scoped + Scoped:适合大多数需要数据库访问的业务逻辑。服务和 DbContext 同一生命周期,推荐使用。
  • Transient + Scoped:适合无状态、轻量级的任务,同时共享同一个 DbContext 实例。适用于轻量级操作,如简化的业务逻辑。
  • Singleton + Scoped:不推荐使用,容易产生生命周期冲突。需要通过工厂模式或 DbContext 动态解析来处理这种组合。
生命周期组合行为分析适用场景
Scoped + ScopedService 和 DbContext 生命周期一致,同一请求范围内共享实例。推荐用于大多数需要数据库访问的业务逻辑场景。
Transient + Scoped每次请求 Service 都会创建新的实例,但共享同一个 DbContext适用于无状态的轻量级任务或简单的业务逻辑。
Singleton + Scoped生命周期冲突,需要通过工厂或 IServiceProvider 动态解析DbContext不推荐,除非有非常明确的需求且确保线程安全。

解决方案与最佳实践

控制 DbContext 的使用范围

如果 Service 是 Transient,但 DbContext 是 Scoped,确保 DbContext 的生命周期受控,避免在多个 Service 中被过度修改。

明确职责分离

在设计 Service 时,确保每个 Transient Service 的职责单一,尽量避免跨 Service 的 DbContext 操作。

避免生命周期冲突

如果 Service 的任务需要长期共享状态(如缓存或事务管理),考虑将其生命周期改为 Scoped,而非 Transient。

相关文章:

ASP.NET Core 中服务生命周期详解:Scoped、Transient 和 Singleton 的业务场景分析

前言 在 ASP.NET Core 中&#xff0c;服务的生命周期直接影响应用的性能和行为。通过依赖注入容器 (Dependency Injection, DI)&#xff0c;我们可以为服务定义其生命周期&#xff1a;Scoped、Transient 和 Singleton。本文将详细阐述这些生命周期的区别及其在实际业务中的应用…...

鼠标自动移动防止锁屏的办公神器 —— 定时执行专家

目录 ◆ 如何设置 ◇ 方法1&#xff1a;使用【执行Nircmd命令】任务 ◇ 方法2&#xff1a;使用【模拟键盘输入】任务 ◆ 定时执行专家介绍 ◆ 定时执行专家最新版下载 ◆ 如何设置 ◇ 方法1&#xff1a;使用【执行Nircmd命令】任务 1、点击工具栏第一个图标【新建任务】&…...

开源库:jcon-cpp

说明 jcon-cpp 是一个用于 C 的 JSON-RPC 库&#xff0c;它允许开发者通过 JSON-RPC 协议进行进程间通信&#xff08;IPC&#xff09;。JSON-RPC 是一种轻量级的远程过程调用协议&#xff0c;基于 JSON 格式数据进行通信。基于MIT协议&#xff0c;最新代码基于Qt6实现。可通过…...

Docker入门之docker基本命令

Docker入门之docker基本命令 官方网站&#xff1a;https://www.docker.com/ 1. 拉取官方镜像并创建容器&#xff08;以redis为例&#xff09; 拉取官方镜像 docker pull redis# 如果不需要添加到自定义网络使用这个命令&#xff0c;如需要&#xff0c;直接看第二步 docker r…...

C++ Qt练习项目 QChar功能测试

个人学习笔记 代码仓库 GitCode - 全球开发者的开源社区,开源代码托管平台 新建项目 设计UI 1、拖入group box去掉名字 2、拖入2个LineEdit 3、拖入两个Label 4、拖入两个PushButton 5、点栅格布局 1、拖入GroupBox 2、拖入4个PushButton 3、点栅格布局 1、拖入GroupBo…...

Taro+react 开发第一节创建 带有redux状态管理的项目

Taro 项目基于 node&#xff0c;请确保已具备较新的 node 环境&#xff08;>16.20.0&#xff09;&#xff0c;推荐使用 node 版本管理工具 nvm 来管理 node&#xff0c;这样不仅可以很方便地切换 node 版本&#xff0c;而且全局安装时候也不用加 sudo 了。 1.安装 npm inf…...

【SOC 芯片设计 DFT 学习专栏 -- RTL 中的信号名和 Netlist 中的信号名差异】

Overview 本文将介绍 soc 设计中 RTL-to-Netlist 映射及 RTL 中的信号名和 Netlist 中的信号名差异&#xff0c; 在 SoC设计中&#xff0c;RTL-to-Netlist映射 是从RTL&#xff08;Register Transfer Level&#xff09;代码转换为Netlist的过程。这通常涉及将用硬件描述语言&…...

551 灌溉

常规解法&#xff1a; #include<bits/stdc.h> using namespace std; int n,m,k,t; const int N105; bool a[N][N],b[N][N]; int cnt; //设置滚动数组来存贮当前和下一状态的条件 //处理传播扩散问题非常有效int main() {cin>>n>>m>>t;for(int i1;i&l…...

计算机网络之---OSI七层模型

为什么会有七层模型 OSI七层模型的出现源于计算机网络技术的发展需求&#xff0c;主要解决以下几个问题&#xff1a; 标准化与互操作性 随着计算机网络的快速发展&#xff0c;不同厂商、不同技术之间的设备和系统需要能够无缝通信。而不同厂商在网络硬件、软件、协议等方面存在…...

spring task使用

Spring Task 简介 Spring Task 是 Spring 框架原生自带的任务调度框架&#xff0c;它犹如一把瑞士军刀&#xff0c;为开发者提供了丰富多样的功能&#xff0c;助力轻松创建和管理定时任务。相较于其他一些第三方任务调度框架&#xff0c;Spring Task 最大的优势在于其与 Sprin…...

ADB->查看进程并强杀进程

查看进程 adb shell ps | findstr com.example.myapplication// result u0_a275 26312 914 17185988 193260 do_freezer_trap 0 S com.example.myapplication用户USER: u0_a275 该字段表示运行此进程的用户。在 Android 中&#xff0c;应用通常以 uN_aM 的格式表…...

Qt重写webrtc的demo peerconnection

整个demo为&#xff1a; 可以选择多个编码方式&#xff1a; cmake_minimum_required(VERSION 3.5)project(untitled LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) set(CMAKE_INCLUDE_CURRENT_DIR ON)set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON)set(CMA…...

comfyui精准作图之gligen

简介 在 Stable Diffusion&#xff08;SD&#xff09;中&#xff0c;GLIGEN 是一种用于增强文本到图像生成模型可控性的技术。它通过在现有的预训练扩散模型&#xff08;如 Stable Diffusion&#xff09;基础上&#xff0c;引入额外的定位输入&#xff08;如边界框、关键点或参…...

再次梳理ISP的大致流程

前言&#xff1a; 随着智能手机的普及&#xff0c;相机与我们的生活越来越紧密相关。在日常生活中&#xff0c;我们只需要轻轻按下手机上的拍照按钮&#xff0c;就能记录下美好时刻。那么问题来了&#xff1a;从我们指尖按下拍照按钮到一张色彩丰富的照片呈现在我们面前&#x…...

系统思考与因果智慧

“众生畏果&#xff0c;菩萨畏因”&#xff0c;这句话蕴藏着深厚的因果智慧&#xff0c;与系统思考不谋而合。 众生畏果&#xff0c;体现了大多数人的行为模式&#xff1a;关注的是眼前的问题与结果&#xff0c;比如失败、冲突、痛苦。正如在系统思考中&#xff0c;我们称之为…...

k8s排错集:zk集群的pod报错 Init:CrashLoopBackOff无法启动

zk三节点集群&#xff0c;zk-0无法启动 statefulset 进到该node节点上查看容器的报错日志&#xff0c;发现在初始化container的时候一个命令有问题 查看正常zk集群的pod的资源配置文件 解决办法&#xff1a; 修改资源配置文件 应该修改为 chown -R 1000:1000 /zkenv kubec…...

商品详情API接口数据解析,API接口系列(示例返回数据(JSON格式))

商品详情API接口是用于获取特定商品详细信息的编程接口。它通常返回JSON格式的数据&#xff0c;包含商品的各种属性&#xff0c;如名称、价格、描述、库存状态、图片URL等。以下是一个典型的商品详情API接口数据解析示例&#xff0c;以及如何调用和使用这些数据的基本步骤。 示…...

Qt官方下载地址

1. 最新版本 Qt官方最新版本下载地址&#xff1a;https://www.qt.io/download-qt-installer 当前最新版本Qt6.8.* 如下图&#xff1a; 2. 历史版本 如果你要下载历史版本安装工具或者源码编译方式安装&#xff0c;请转至此链接进行下载&#xff1a;https://download.qt.i…...

Python自学 - 类进阶(可调用对象)

返回目录 1 Python自学 - 类进阶(可调用对象) 可调用对象在Python中有很重要的作用&#xff0c;那什么是可调用对象呢&#xff1f; 可以简单的理解为&#xff0c;凡是对象可以加括号给参数的都叫可调用对象&#xff0c;如&#xff1a;obj(x)中obj就是可调用对象&#xff0c;因…...

键盘过滤驱动

文章目录 概述注意源码参考资料 概述 irp请求会从io管理器中传递到设备栈中依次向下发送&#xff0c;当到达底层真实设备处理完成后&#xff0c;会依次返回&#xff0c;这时如果在设备栈中有我们自己注册的设备&#xff0c;就可以起到一个过滤的功能。键盘过滤驱动就是如此&am…...

Type-C单口便携显示器-LDR6021

Type-C单口便携显示器是一种新兴的显示设备&#xff0c;它凭借其便携性、高性能和广泛的应用场景等优势&#xff0c;正在成为市场的新宠。以下是Type-C单口便携显示器的具体运用方式&#xff1a; 一、连接与传输 1. **设备连接**&#xff1a;Type-C单口便携显示器通过Type-C接…...

ClickHouse vs StarRocks 选型对比

一、面向列存的 DBMS 新的选择 Hadoop 从诞生已经十三年了&#xff0c;Hadoop 的供应商争先恐后的为 Hadoop 贡献各种开源插件&#xff0c;发明各种的解决方案技术栈&#xff0c;一方面确实帮助很多用户解决了问题&#xff0c;但另一方面因为繁杂的技术栈与高昂的维护成本&…...

服务器数据恢复—raid5故障导致上层ORACLE无法启动的数据恢复案例

服务器数据恢复环境&故障&#xff1a; 一台服务器上的8块硬盘组建了一组raid5磁盘阵列。上层安装windows server操作系统&#xff0c;部署了oracle数据库。 raid5阵列中有2块硬盘的硬盘指示灯显示异常报警。服务器操作系统无法启动&#xff0c;ORACLE数据库也无法启动。 服…...

鼠标过滤驱动

文章目录 概述代码参考资料 概述 其编写过程大体与键盘过滤驱动相似&#xff0c;只需要切换一下附加的目标设备以及创建的设备类型等。但在该操作后依然无法捕获到Vmware创建的win7操作系统的鼠标irp信息&#xff0c;于是通过在获取鼠标驱动&#xff0c;遍历其所有的设备进而附…...

SQL进阶实战技巧:LeetCode2201. 统计可以提取的工件?

目录 0 题目描述 1 数据准备 2 问题分析 第一步:生成每个工件的所有单元格 第二步:标记被挖掘的单元格...

Supermaven 加入 Cursor:AI 编码新篇章

引言 2024 年 11 月 11 日&#xff0c;我们迎来了一个激动人心的时刻——Supermaven 正式加入 Cursor&#xff01; 这一合作标志着 AI 编程工具进入了一个新的发展阶段&#xff0c;为开发者提供更智能、更高效的编码体验。本文将带您了解此次合并的背景、意义以及未来的发展方…...

金融项目实战 01|功能测试分析与设计

前置内容&#xff1a;金融项目准备的内容笔记可直接看如下笔记 只看&#xff1a;一、投资专业术语 和 二、项目简介 两部分文章浏览阅读2.3k次&#xff0c;点赞70次&#xff0c;收藏67次。安享智慧理财金融系统测试项目&#xff0c;测试用例&#xff0c;接口测试&#xff0c;金…...

阿里云直播互动Web

官方文档&#xff1a;互动消息Web端集成方法_视频直播(LIVE)-阿里云帮助中心 以下是代码实现&#xff1a; <!-- 引入阿里云互动文件 --> <script src"https://g.alicdn.com/code/lib/jquery/3.7.1/jquery.min.js"></script> <script src&quo…...

python【输入和输出】

Python 有三种输出值的方式&#xff1a; 表达式语句print() 函数使用文件对象的 write() 方法&#xff0c;标准输出文件可以用 sys.stdout 引用。 ① 将输出的值转成字符串&#xff0c;可以使用 repr() 或 str() 函数来实现&#xff1a; str()&#xff1a; 函数返回一个用户易…...

网络安全建设方案,信息安全风险评估报告,信息安全检测文档(Word原件完整版)

一、概述 1.1工作方法 1.2评估依据 1.3评估范围 1.4评估方法 1.5基本信息 二、资产分析 2.1 信息资产识别概述 2.2 信息资产识别 三、评估说明 3.1无线网络安全检查项目评估 3.2无线网络与系统安全评估 3.3 ip管理与补丁管理 3.4防火墙 四、威胁细…...

nexus搭建maven私服

说到maven私服每个公司都有&#xff0c;比如我上一篇文章介绍的自定义日志starter&#xff0c;就可以上传到maven私服供大家使用&#xff0c;每次更新只需deploy一下就行&#xff0c;以下就是本人搭建私服的步骤 使用docker安装nexus #拉取镜像 docker pull sonatype/nexus3:…...

Redis为 List/Set/Hash 的元素设置单独的过期时间

一.业务简介 我们知道&#xff0c;Redis 里面暂时没有接口给 List、Set 或者 Hash 的 field 单独设置过期时间&#xff0c;只能给整个列表、集合或者 Hash 设置过期时间。 这样&#xff0c;当 List/Set/Hash 过期时&#xff0c;里面的所有 field 元素就全部过期了。但这样并不…...

高比例压缩:Linux 中的压缩命令与技巧

文章目录 高比例压缩&#xff1a;Linux 中的压缩命令与技巧1. 压缩格式的选择2. gzip 命令示例&#xff1a;压缩文件示例&#xff1a;解压文件 3. bzip2 命令示例&#xff1a;压缩文件示例&#xff1a;解压文件 4. xz 命令示例&#xff1a;压缩文件示例&#xff1a;解压文件 5.…...

73.矩阵置零 python

矩阵置零 题目题目描述示例 1&#xff1a;示例 2&#xff1a;提示&#xff1a; 题解思路分析Python 实现代码代码解释提交结果 题目 题目描述 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例…...

工业互联网项目开发工作流及各阶段核心关注点

工业互联网项目开发全流程V3.0 工业互联网项目开发工作流程及核心问题 一、需求分析 1、共享平台需求分析 这个平台要解决什么问题&#xff1f; 这个平台的用户群体是谁&#xff1f; 这个平台应该具备哪些主要功能&#xff1f; 这个平台的使用场景是什么&#xff1f; 这个平…...

简单易用的PDF工具箱

软件介绍 PDF24 Creator是一款简单易用的PDF工具箱&#xff0c;而且完全免费&#xff0c;没有任何功能限制。既可以访问官网在线使用各种PDF工具&#xff0c;也可以下载软件离线使用各种PDF工具。 软件功能 1、PDF转换 支持将多种文件格式&#xff08;Word、PowerPoint、Exc…...

氧化铌在光学领域的独特贡献与应用拓展-京煌科技

在当今科技日新月异、各领域不断寻求突破创新的时代背景下&#xff0c;众多材料因其独特的性能而备受关注&#xff0c;氧化铌便是其中极具代表性的一种。作为铌的氧化物&#xff0c;其化学式为 Nb₂O₅&#xff0c;以无色或白色固体的形态存在&#xff0c;正凭借着优良的热稳定…...

EXCEL技巧

1. EXCEL技巧 1.1. 截取表格内某个字符之前的所有字符 1.1.1.样例 在单元格内输入函数&#xff1a; # 截取A1单元格内“分”字符左边的所有字符 LEFT(A1,FIND("分",A1)-1)1.1.2.截图...

Java 将RTF文档转换为Word、PDF、HTML、图片

RTF文档因其跨平台兼容性而广泛使用&#xff0c;但有时在不同的应用场景可能需要特定的文档格式。例如&#xff0c;Word文档适合编辑和协作&#xff0c;PDF文档适合打印和分发&#xff0c;HTML文档适合在线展示&#xff0c;图片格式则适合社交媒体分享。因此我们可能会需要将RT…...

shell的变量

在程序设计语言中&#xff0c;变量是一个非常重要的概念。也是初学者在进行Shell程序设计之前必须掌 握的一个非常基础的概念。只有理解变量的使用方法&#xff0c;才能设计出良好的程序。本节将介绍Shell中变量 的相关知识。 1、什么是变量 顾名思义&#xff0c;变量就是程序…...

【STM32】利用SysTick定时器定时1s

1.SysTick简单介绍 SysTick定时器是一个24位的倒计数定时器&#xff0c;当计数到0时&#xff0c;将从RELOAD寄存器中自动重装载定时初值&#xff0c;开始新一轮计数。 SysTick定时器用于在每隔一定的时间产生一个中断&#xff0c;即使在系统睡眠模式下也能工作。 关于SysTic…...

halcon3d 如何计算平面法向量!确实很简单

这个问题其实一直困扰了我很长时间,之前是怎么算的呢 对于一个平面,我会先求它的fit_primitives_object_model_3d去将它拟合,接下来用surface_normals_object_model_3d 算子生成它的法线,后用get_object_model_3d_params (ObjectModel3DNormals, ‘point_normal_x’, GenP…...

计算机网络_物理层

2.1物理层的基本概念 传输媒体 导引型传输媒体 双绞线 ​ 同轴电缆 ​ 光纤 非导引型传输媒体 微波通信 ​ 2~40GHz 物理层协议的主要任务 机械特性 ​ 电器特性 ​ 功能特性 ​ 过程特性 物理层概述 物理层考虑是怎样才能在连接各种计算机的传输媒体上传输数据比特流…...

Springboot——钉钉(站内)实现登录第三方应用

文章目录 前言准备1、创建钉钉应用&#xff0c;并开放网页应用2、配置网页应用各项参数发布版本 前端改造后端逻辑1、获取应用免登录 Access_token2、通过免登录 Access_token 和 Auth_Code 获取对应登录人信息 注意事项 前言 PC端的钉钉中工作台&#xff0c;增加第三方应用&a…...

libusb学习——简单介绍

文章目录 libusb 简介libusb 编译libusb 源码目录介绍核心代码文件平台支持例子 API使用libusb初始化和去初始化libusb设备处理和枚举libusb 杂项libusb USB描述符libusb 设备热插拔事件通知libusb 异步设备I/Olibusb 同步设备I/Olibusb 轮询与定时 libusb 涉及技术参考 libusb…...

Vue进阶(贰幺叁)node 版本切换

文章目录 一、前言1.1 什么是nvm? 二、查看已安装好的 node 版本三、下载 node 版本四、切换 node 版本五、查看在用 node 版本六、拓展阅读 一、前言 项目开发阶段&#xff0c;会涉及多node版本切换应用场景&#xff0c;可应用nvm实现node版本切换。 1.1 什么是nvm? nvm是…...

[AI] 大模型提示词:理解与高效使用指南

随着大模型&#xff08;如GPT、Claude、PaLM等&#xff09;在各领域的应用逐步普及&#xff0c;**提示词&#xff08;Prompt&#xff09;**的重要性愈发凸显。提示词作为与大模型交互的主要方式&#xff0c;不仅直接影响生成结果的质量&#xff0c;还决定了模型在特定任务中的适…...

关于linux网桥(Linux Bridge)的一些个人记录

文章目录 1. Linux Bridge简述2. 网桥创建创建配置持久化在Debian/Ubuntu系统上&#xff1a;在CentOS/RHEL系统上&#xff1a; 启用和验证 3. 关于linux网桥不转发ip帧的问题原因解决配置持久化 4. 查看网桥学习交换表手动添加或删除条目添加条目删除条目 配置静态条目设置条目…...

黑马天机学堂学习计划模块

核心功能 系统设计思路 ​​​​​​​ 代码分析 1. 学习记录管理 • 存储学习记录到 Redis&#xff1a; 利用 Redis 缓存学习记录&#xff0c;减少频繁的数据库访问。 public void writeRecordCache(LearningRecord record) {String key String.format("LEARNING:R…...

【华为云开发者学堂】基于华为云 CodeArts CCE 开发微服务电商平台

实验目的 通过完成本实验&#xff0c;在 CodeArts 平台完成基于微服务的应用开发&#xff0c;构建和部署。 ● 理解微服务应用架构和微服务模块组件 ● 掌握 CCE 平台创建基于公共镜像的应用的操作 ● 掌握 CodeArts 平台编译构建微服务应用的操作 ● 掌握 CodeArts 平台部署微…...