EMall实践DDD模拟电商系统总结
目录
一、事件风暴
二、系统用例
三、领域上下文
四、架构设计
(一)六边形架构
(二)系统分层
五、系统实现
(一)项目结构
(二)提交订单功能实现
(三)领域层实现
聚合
聚合根、实体、值对象
(四)Repository层实现
CQRS模式
缓存实现
Unit Of Work模式
数据并发更新控制
(五)领域事件实现
六、总结
干货分享,感谢您的阅读!
在这个信息化爆炸的时代,软件开发就像是烹饪一顿大餐,尤其是对于复杂的电商系统E-Mall而言。你得准备好各种“食材”,从用户需求、系统架构到领域模型,少了哪一样,整个“菜单”可就难以下咽了!而我们的厨房——事件风暴(Event Storming),就是一个绝妙的集思广益的环节,人人都是大厨,尽情挥舞着“锅铲”,共同烹制出一道色香味俱全的系统设计大餐。
但别担心,咱们不是要把你弄得一头雾水。相反,我们会用一种轻松幽默的方式,带你走进系统分析的世界,像讲故事一样剖析复杂的概念。想象一下,你正在与小伙伴们一起玩一场解谜游戏,破解那些神秘的业务需求,发现隐藏的领域上下文,最终打造出一个能让用户眼前一亮的电商平台。
准备好了吗?让我们一起在这场系统设计的盛宴中,开启“食材”之旅,探索如何用合理的架构和设计理念,将E-Mall打造成“软件界的美食大师”!针对项目源码roc-emall进行的一些总结。
一、事件风暴
事件风暴(Event Storming)是一种系统分析方法,由 Alberto Brandolini 开发,旨在帮助团队理解和识别系统中的事件、业务功能和边界。它通常与领域驱动设计(DDD)概念结合使用,以加速系统设计和开发的过程。 详细的解释可以参考它的官方网站: Event Storming。
事件风暴的核心思想是通过协作的方式,将参与者集合在一起,共同探讨和记录系统中发生的事件。以下是事件风暴的一些关键要点:
-
事件驱动:事件风暴强调事件作为系统的关键组成部分。事件是用户操作或系统状态更改的结果,这些事件可以帮助理解系统中的业务流程。
-
合作工作坊:事件风暴通常作为一个工作坊进行,邀请各种利益相关者参与,包括业务分析师、开发人员、设计师等。这有助于促进跨职能团队的合作和理解。
-
大白纸:事件风暴使用大型纸张或墙壁来记录事件和相关信息。参与者可以使用便利贴、标记笔等工具来记录事件,定义业务流程,绘制关系图等。
-
时间线:事件风暴通常将事件按照时间线的方式排列,以帮助理清事件发生的顺序和逻辑。
-
聚焦领域:事件风暴有助于识别领域中的限界上下文(bounded context),这是DDD中的一个重要概念,用于定义业务功能的边界。
-
快速迭代:事件风暴是一个迭代过程,可以多次进行,以不断完善对系统的理解,发现潜在的业务问题和机会。
事件风暴的目标是促进对系统的共享理解,减少误解,发现潜在问题,以及为设计和开发提供清晰的指导。它是一种轻量级、可视化的方法,有助于团队在项目早期阶段快速建立共识,加速开发过程,提高项目成功的机会。
所谓“事件”,即系统中一系列的行为(用户操作)导致系统状态更改的结果。例如,用户“提交订单”这一行为导致系统生成了新订单,发生了“订单已提交”事件;仓库发货员将包果交给快递员后,在系统“填写了快递单号”后,导致系统状态发生更改,触发了“已发货”事件。
通过分析系统中发生的“事件”,能够挖掘和识别出系统的业务功能,梳理出业务边界。下图展示了E-Mall系统的事件风暴
二、系统用例
系统用例是用户与系统交互的一种表示形式,它们有助于识别和记录系统的功能需求,并可用于用户需求分析、系统设计和软件开发的各个阶段。以下是有关系统用例的一些关键要点:
-
用户需求分析: 通过系统用例,分析人员可以捕捉用户与系统之间的交互,以了解用户期望系统执行的各种操作。这有助于确保系统开发满足用户需求。
-
功能识别: 用例图用于识别系统的各种功能或操作。每个用例代表一个特定的功能或行为,而用例之间的关系描述了它们之间的依赖性和交互。
-
可视化: 用例图提供了一种可视化方式,以便项目团队、利益相关者和开发人员更容易理解系统功能和交互。
-
系统边界: 用例图通常包括一个系统边界,用于明确界定系统与外部实体之间的交互,帮助确定哪些操作属于系统的范围。
-
用例描述: 每个用例通常附带用例描述,其中包括用例的名称、目标、前提条件、主要流程和可能的替代流程。这些描述提供了对用例的详细说明。
-
角色: 用例图还包括与系统交互的各种角色,这些角色代表用户、外部系统或其他实体。
-
交互关系: 用例图展示了各个用例之间的关系,如包含关系、扩展关系和依赖关系。这有助于理解用例之间的交互方式。
-
迭代和演化: 用例图是一个灵活的工具,可以在项目的不同阶段进行更新和演化,以反映新的需求或发现的变化。
总之,系统用例图是一种强大的工具,用于捕捉、可视化和分析系统的功能需求,有助于确保开发团队理解用户期望的系统行为,从而成功交付符合需求的软件系统。下图展示了E-Mall系统的用例:
三、领域上下文
根据事件风暴推断,系统中应该包含的界限上下文有:Order、SKU、Price、Payment等。
对系统进行Context划分:
-
Order Context(订单上下文): 这是处理与订单相关的所有功能的上下文,包括提交订单、取消订单和查询订单等操作。它在业务中负责订单的生命周期管理。
-
SKU Context(SKU上下文): 这个上下文主要涉及商品(Stock Keeping Unit)的管理,包括库存管理、商品数量校验以及订单的商品处理。此外,SKU上下文还涉及订单的打包和发货等操作,以确保订单的正确处理。
-
Price Context(价格上下文): 价格上下文负责管理商品的价格,计算订单金额以及维护价格计算策略。它为订单上下文提供了订单金额计算所需的功能。
-
Payment Context(支付上下文): 这个上下文主要关注支付功能,包括维护交易记录等。它确保订单支付的安全性和可追踪性。
四、架构设计
(一)六边形架构
六边形架构是一种用于构建可扩展和灵活的应用程序的架构风格,强调了分离关注点和对外部系统和客户的透明性。以下是一些关键要点:
-
六边形的对称性: 在六边形架构中,系统被视为一个多边形,其边界上有各种端口(Port),而系统的核心是领域层。这个多边形的对称性意味着客户和外部系统可以以一种对等的方式与系统交互,而系统核心不受特定的客户或外部技术的依赖。
-
输入端口: 输入端口用于接受外部客户系统的请求或输入,并将其转化为内部可理解的请求。这可以是系统提供的服务接口,用于接受来自外部的命令或查询。
-
输出端口: 输出端口用于与外部系统进行通信,如数据库、消息队列、远程服务等。它负责将系统内部的状态或数据发送到外部系统或进行持久化。
-
应用层: 应用层是系统的服务层,定义了系统可以执行的工作。它协调领域对象和领域服务,处理业务逻辑,并通过输入端口接受请求并使用输出端口与外部系统通信。应用层通常非常薄,不包含业务逻辑,而是将请求委托给领域层处理。
-
领域层: 领域层包含系统的核心业务逻辑,它负责表示业务概念、规则和状态。领域层的模型是应用程序的核心,通常包括实体、值对象、聚合根等领域对象。
-
适配器: 适配器在输入和输出端口之间进行数据转换和交互。输入适配器将来自客户的请求转化为系统可理解的形式,输出适配器将系统的响应转化为外部系统或客户可理解的形式。这使得系统能够与各种客户和外部系统进行无缝的交互。
六边形架构的优点包括良好的可扩展性、可维护性和适应性,因为它使不同部分之间的关注点清晰分离。它也使系统更容易进行单元测试,因为领域逻辑可以在不涉及外部系统的情况下进行测试。这种架构风格对于构建复杂应用程序和微服务架构非常有用。
(二)系统分层
领域驱动设计(DDD)架构常见的四层架构:
-
基础设施层(Infrastructure Layer): 这一层提供与业务逻辑无关的功能和工具,通常包括实用程序类、工具类、数据库连接、日志记录、缓存、消息队列等。在这一层中,你还可以找到仓储(Repository)接口和数据库访问的实现,用于与持久化存储交互。基础设施层通常是技术相关的,但它们需要被领域层和应用层所依赖。
-
领域层(Domain Layer): 领域层包含了系统的核心业务逻辑。这是应用程序的灵魂,它包括领域模型、实体、值对象、聚合根、领域服务等。这一层与特定的业务领域密切相关,它不包含技术相关的内容,而是关注如何解决业务问题。领域层通常不依赖于其他层,而其他层依赖于领域层。
-
应用层(Application Layer): 应用层位于领域层之上,它是系统的服务层,负责协调领域逻辑的执行。应用层包括应用服务(Application Services),这些服务定义了系统可以执行的各种用例或操作,它们接受来自展示层的请求,协调领域层的操作,处理事务管理,发布领域事件等。应用层通常依赖于基础设施层和领域层。
-
展示层(Presentation Layer): 这是系统与用户或外部系统进行交互的接口层。展示层可以是用户界面(UI)层,如Web界面或移动应用,也可以是API层,用于提供外部系统访问应用程序的接口。展示层通常不直接与领域层交互,而是通过应用层来协调和处理请求。
这种四层架构的分层方法有助于实现领域驱动设计的原则,如分离关注点、保持业务逻辑的纯洁性以及提高系统的可维护性和可扩展性。通过将不同关注点分离到不同的层级,可以更容易地管理和扩展应用程序,同时也使系统的架构更清晰和可维护。
五、系统实现
(一)项目结构
-
Roc.EMall.Infra,即DDD分层中的“基础设施层”,提供一些业务无关的扩展或帮助方法。
-
Roc.EMall.Repository,仓储层(属于基础设施层)负责与数据库交互,通过Dapper和MySql.Data库读取和写入数据到MySQL数据库中。对外仅暴露IRepository及其子接口,隐藏具体实现。
-
Roc.EMall.Domain,领域层包含所有的核心业务,通过充血模型实现业务逻辑。
贫血模型
贫血模型:是指领域对象里只有get和set方法,或者包含少量的CRUD方法,所有的业务逻辑都不包含在内而是放在Business Logic层。
优点是系统的层次结构清楚,各层之间单向依赖,Client->(Business Facade)->Business Logic->Data Access(ADO.NET)。当然Business Logic是依赖Domain Object的。似乎现在流行的架构就是这样,当然层次还可以细分。
该模型的缺点是不够面向对象,领域对象只是作为保存状态或者传递状态使用,所以就说只有数据没有行为的对象不是真正的对象。在Business Logic里面处理所有的业务逻辑,在POEAA(企业应用架构模式)一书中被称为Transaction Script模式。
充血模型
充血模型: 层次结构和上面的差不多,不过大多业务逻辑和持久化放在Domain Object里面,Business Logic只是简单封装部分业务逻辑以及控制事务、权限等,这样层次结构就变成Client->(Business Facade)->Business Logic->Domain Object->Data Access。
优点是面向对象,Business Logic符合单一职责,不像在贫血模型里面那样包含所有的业务逻辑太过沉重。
参考:充血模型和贫血模型 - 简书
-
Roc.EMall.Application,应用层负责向展示层(WebApi)提供应用服务,调用领域层完成业务功能,协调多个领域对象,调用Repository层完成数据的读取和保存,调用外部接口完成相关验证,发布领域事件。
-
Roc.EMall.WebApi,展示层负责接收用户请求,调用应用层,并返回相关数据给用户。
(二)提交订单功能实现
(三)领域层实现
聚合
聚合Aggregate就是一组相关对象的集合,我们把它作为数据修改和访问的单元。一个聚合包含聚合根、实体和值对象。
每个聚合都会有一个聚合根和聚合的边界Boundary,边界定义了在一个聚合里面内部应该有哪些实体,哪些子实体对象。定义边界的原因是,我们期望对一个聚合的访问是通过聚合根来进行的,聚合里面的子实体对外界是完全封闭的。对于外部对象不应该去访问到一个聚合边界里面的子实体。
按实际对象分析思路,在领域模型中的领域对象分析应该按照从顶向下的思路进行展开,如果这样的话首先识别到的就是聚合根对象,然后再考虑对聚合根对象进行展开,在聚合根对象的展开过程中进一步细化子实体之间的关联和依赖关系。
聚合根、实体、值对象
聚合的特点:高内聚低耦合,是领域模型中最底层的边界,可以作为拆分限界上文的最小单位,一个限界上文可以包含多个聚合,聚合之间的边界是逻辑最天然的边界,有了这个逻辑边界,就可以在微服务拆分的时候作为拆分和组合的依据,推动系统服务化演进。
实体:具有唯一标识(ID),通过ID进行相等性比较,依附于聚合根,生命周期由聚合根来管理。实体和聚合根存在依赖或聚合关系。例如,在Order聚合中,Order类是聚合根,LineItem是实体;
聚合根:聚合根是实体,具备唯一标识,有独立的生命周期,一个聚合只有一个聚合根,聚合根在聚合之内采用引用依赖的方式对实体和值对象进行组织和协调,聚合根和聚合根之间通过唯一id进行聚合之间的协同;
值对象:没有唯一标识(ID),不可变,无生命周期,用完即失效,值对象之间通过属性值判断相等性。值对象的核心是值,是一组概念完整的属性集合,用于描述实体的特征和状态。
为什么要在实体和限界上下文之间增加聚合和聚合根,作用是什么?
在实体和限界上下文之间增加聚合和聚合根的原因是:让实体和值对象协同工作,在实现公共业务逻辑的时候,可以保证数据的一致性。
如何设计聚合?
过程是:通过事件风暴(用例分析,场景分析)得到实体和值对象,然后找出聚合根,按照高内聚低耦合的设计原则,找出跟聚合根紧密关联的实体和值对象,即形成聚合,并画出聚合内的实体和值对象的引用依赖关系,最后把业务关联紧密的聚合画在同一个限界上线文中,即完成了领域建模。
聚合的设计原则: 高内聚,聚合尽量小,聚合之间通过id关联,边界之外使用最终一致性,在应用层实现跨聚合的调用。
(四)Repository层实现
Repository一般是根据领域层中的聚合根维度来划分的。例如,E-Mall系统中,在领域层中Order是聚合根,因此Repsository层中存在对应的OrderRepository,负责Order对象存储和读取工作。
CQRS模式
CQRS — Command Query Responsibility Segregation,故名思义是将 command 与 query 分离的一种模式。
CQRS 将系统中的操作分为两类,即「命令」(Command) 与「查询」(Query)。命令则是对会引起数据发生变化操作的总称,即我们常说的新增,更新,删除这些操作,都是命令。而查询则和字面意思一样,即不会对数据产生变化的操作,只是按照某些条件查找数据。使用CQRS模式,由于将读和写分成两个路径,系统天然地支持读写分离。
在CQRS中,Command直接将数据写入主库(可写),然后通过EventSourcing将变化的数据写入只读库。缺点是,使用EventSourcing增加了系统的复杂度,可能出主库和只读库数据不一致的情况。
在E-Mall项目中,并未采用EventSourcing对主库和只读库进行分离。项目中,在Repository层,将读和写分存两类不同的Repository: IRepository和IQueryRepository,所有Command操作均通过IRepository进行,所有Query操作均通过IQueryRepository操作。
缓存实现
由于采用了CQRS模式,Query Repository和Command Repository是相互独立。因此,缓存只需要在IQueryRepository的实现类上使用装饰者模式,对结果进行缓存即可。对于缓存数据的刷新,只要在对应的Command Repository上也使用装饰者模式即可实现。
Unit Of Work模式
单个Repository只负责维护单个聚合根的读写操作,当一个业务功能需要同时操作多个聚合根,且需要保证数据操作的原子性,那么单个Repository实现起来就比较困难。这时,就需要使用Unit Of Work(工作单元)模式了,Unit Of Work包装了数据库事务,保证多个聚合根操作的原子性。
Unit Of Work(工作单元)模式用来维护一个由已经被业务事物修改(增加、删除或更新)的业务对象组成的列表。Unit Of Work模式负责协调这些修改的持久化工作以及所有标记的并发问题。在数据访问层中采用Unit Of Work模式带来的好处是能够确保数据完整性。如果在持久化一系列业务对象(他们属于同一个事物)的过程中出现问题,那么应该将所有的修改回滚,以确保数据始终处于有效状态。
数据并发更新控制
通常情况,系统先通过Repository从数据库中加载现有数据并构建聚合根对象,应用层调用聚合根的方法执行业务逻辑,更改状态,最后再调用Repository保存到数据库中。
例如,用户提交订单时,应用层服务调用Repository.GetAsync方法获取Sku对象,并调用Sku.Occupy()方法锁定库存,最后再调用Repository.StoreAsync方法保存数据。
在并发较高中的业务场景中,多个用户购买同一个商品时,可能会更出并发锁定库存的现象。为了确保商品不出现“超卖”现象,必须对Sku.Occupy()方法进行并发控制。并发控制方案,一般有两种:
- 乐观并发:适用于并发冲突较少的业务场景,整体效率较高。但是,由于并发时总有一方必定失败,因此需要配合重试机制,提高系统体验。可以通过给数据行增加版本号实现。
- 悲观并发:适用于并发冲突较高的业务场景,并发请求分先后串行执行,整体效率不高。可以通过数据事务隔离级别实现。
E-Mall系统中采用乐观并发控制方案,配合并发重试机制,解决偶发并发失败场景。每个聚合根对象,在从Repository中加载后,都会带上ConVersion字段。更新数据时,将ConVersion字段作为额外的条件。
(五)领域事件实现
领域事件的发布一般放在应用层,通常在事务提交成功之后。领域事件的对象,则由应用层调用聚合根的方法获取,因为领域事件对象属于领域层职责。
在系统中,功能对系统的状态(数据)进行更改后,需要发布领域事件。相关的子系统或模块订阅相关的领域事件,对领域事件做出响应。
例如,对于用户新提交的订单,会要求在30分钟内完成付款,否则订单自动取消,并释放相应的库存。实现这样的功能,一般使用延时队列,30分钟后运行Job检查订单状态,未支付则取消订单,但是这样的逻辑不应该侵入到“提交订单”的业务逻辑中,而应该订阅“新增订单”的领域事件来实现。
六、总结
在我们对E-Mall项目的深度剖析中,似乎不仅仅是一次系统设计的旅程,更是一场关于团队合作与创新的盛宴。从事件风暴的初步探索,到清晰的系统用例,再到领域上下文的精确划分,每一步都像是在绘制一幅复杂而美丽的画卷。
通过引入六边形架构,我们将系统的各个部分有效地分离,确保每个组件都能专注于自己的职责,这就像是将各类食材按照最佳配比精心搭配,使得最终的“菜肴”更加美味可口。而在实现层面,我们通过聚合、仓储模式以及CQRS的运用,让系统不仅在理论上完美,更在实际操作中游刃有余。
当然,在这趟旅程中,我们也得到了对系统实现细节的深刻理解,特别是在面对高并发情况下的乐观和悲观控制策略,让我们的E-Mall不仅能在“厨房”中大显身手,还能在真实的市场环境中应对挑战。
总的来说,E-Mall项目不仅是一段技术探索之旅,更是对团队协作、架构设计和系统实现的全面反思。希望这篇总结能够为你提供灵感,助力你在未来的项目中继续创造出更具竞争力的产品。感谢您的阅读,期待与您在下一个项目中再次相见,共同烹制出更多精彩的“美食”!
相关文章:
EMall实践DDD模拟电商系统总结
目录 一、事件风暴 二、系统用例 三、领域上下文 四、架构设计 (一)六边形架构 (二)系统分层 五、系统实现 (一)项目结构 (二)提交订单功能实现 (三࿰…...
基于多VSG独立微网的多目标二次控制MATLAB仿真模型
“电气仔推送”获得资料(专享优惠) 模型简介 本文将一致性算法引入微电网的二次频率和电压控制,自适应调节功率参考值和补偿电压,同时实现频率电压恢复、有功 无功功率的比例均分以及功率振荡抑制,提高系统的暂态和稳…...
自动化运维(k8s)之微服务信息自动抓取:namespaceName、deploymentName等全解析
前言:公司云原生k8s二开工程师发了一串通用性命令用来查询以下数值,我想着能不能将这命令写成一个自动化脚本。 起初设计的 版本一:开头加一条环境变量,执行脚本后,提示输入:需要查询的命名空间,…...
nginx 代理 web service 提供 soap + xml 服务
nginx 代理 web service 提供 soap xml 服务 最关键的配置: # Nginx默认反向后的端口为80,因此存在被代理后的端口为80的问题,这就导致访问出错。主要原因在Nginx的配置文件的host配置时没有设置响应的端口。Host配置只有host,没有对应的p…...
深入理解 MongoDB:一款灵活高效的 NoSQL 数据库
在现代应用程序开发中,数据存储技术已经从传统的关系型数据库(RDBMS)扩展到多样化的 NoSQL 数据库。MongoDB 作为一款广泛使用的文档型数据库,以其灵活性、高性能和易用性成为开发者的首选之一。本篇博文将从 MongoDB 的核心概念、…...
vue3 + vite + antdv 项目中自定义图标
前言: 去iconfont-阿里巴巴矢量图标库 下载自己需要的icon图标,下载格式为svg;项目中在存放静态资源的文件夹下 assets 创建一个存放svg格式的图片的文件夹。 步骤: 1、安装vite-plugin-svg-icons npm i vite-plugin-svg-icons …...
PDF版地形图矢量出现的问题
项目描述:已建风电场道路测绘项目,收集到的数据为PDF版本的地形图,图上标注了项目竣工时期的现状,之后项目对施工区域进行了复垦恢复地貌,现阶段需要准确的知道实际复垦修复之后的道路及其它临时用地的面积 解决方法&…...
JavaScript 高级教程:异步编程、面向对象与性能优化
在前两篇教程中,我们学习了 JavaScript 的基础和进阶内容。这篇文章将带领你进入更深层次,学习 JavaScript 的异步编程模型、面向对象编程(OOP),以及性能优化的技巧。这些内容对于构建复杂、流畅的前端应用至关重要。 …...
有一个已经排好序的数组。现输入一个数,要求按原来的规律将它插入数组中。-多语言
目录 C 语言实现 Python 实现 Java 实现 Js 实现 题目:有一个已经排好序的数组。现输入一个数,要求按原来的规律将它插入数组中。 程序分析:首先判断此数是否大于最后一个数,然后再考虑插入中间的数的情况,插入后此元素之后的数,依次后移…...
OCR实现微信截图改名
pip install paddlepaddle -i https://pypi.tuna.tsinghua.edu.cn/simple/ ──(Sat,Nov30)─┘ pip install shapely -i https://pypi.tuna.tsinghua.edu.cn/simple/ pip install paddleo…...
c++stl模板总结
stl 总结stl模板vectordequelistforward_liststl集合类set&unorder_setmap&unorder_map 自适应容器栈和队列stackqueuepriority_queue 总结stl模板 vector 1.初始化 vector具有多个重载的构造函数,可以在实例化vector时指定他开始时应该包含的元素个数以…...
文本生成类(机器翻译)系统评估
在机器翻译任务中常用评价指标:BLEU、ROGUE、METEOR、PPL。 这些指标的缺点:只能反应模型输出是否类似于测试文本。 BLUE(Bilingual Evaluation Understudy):是用于评估模型生成的句子(candidate)和实际句子(referen…...
Harmony NEXT-越过相机读写权限上传图片至项目云存储中
问题成因 在制作用户注册登录界面时想要实现用户头像上传共能,查询API文档,发现有picker和PhotoAccessHelper两个包可以选择使用,但是在使用PhotoAccessHelper包拉起相册并读入所选的照片后将该照片传入云存储中产生报错,需要相册…...
C++算法练习-day53——17.电话号码的字母组合
题目来源:. - 力扣(LeetCode) 题目思路分析 题目要求我们将一个数字字符串(每个数字对应一组字母,如2对应abc,3对应def等)转换成所有可能的字母组合。这是一个典型的组合生成问题,…...
计算机网络性能
任何一个系统都可以或需要不同的指标来度量系统的优劣、状态或特性。计算机网络是综合计算机技术与通信技术的复杂系统,可以通过许多指标对一个计算机网络的整体或局部、全面或部分、静态或动态等不同方面的性能进行度量与评价 1、传输时延 当一个分组在输出链路发…...
MAC卸载Vmware Fusion后无法再安装解决方案
MAC卸载Vmware Fusion后无法再安装解决方案 执行脚本 sudo rm -rf /Library/Application Support/VMware/VMware Fusion sudo rm -rf /Library/Application Support/VMware/Usbarb.rules sudo rm -rf /Library/Application Support/VMware Fusion sudo rm -rf /Library/Prefe…...
windows 服务器角色
windows 服务器角色 Active Directory Rights Management Services Active Directory RightsManagement Services (AD RS)帮助保护信息,防止未授权使用。AD RMS 将建立用户标识,并为授权用户提供受保护信息的许可证。 ServicesActive Directory 联合身…...
NAT学习手册
NAT(Network Address Translation,网络地址转换)是一种在局域网(LAN)内部使用私有地址,而在连接到互联网时将这些私有地址转换为全球唯一且有效的公网地址的技术。这种技术的主要目的是解决IPv4地址空间不足…...
python -从文件夹批量提取pdf文章的第n页,并存储起来
python -从文件夹批量提取pdf文章的第n页,并存储起来 废话不多说,看下面代码 讲解一下下面代码 reader PyPDF2.PdfReader (file) 将文件转化为PdfReader 对象,方便使用内置方法。 first_page reader.pages[0] 提取第一页 writer PyPDF…...
RPC中定时器制作思路
定时器设计 time_event time_event 类用来封装定时时间,内部需要包含一个任务执行时间,是否重复标记、是否取消标记,对于重复任务,还需要一个重复间隔时间。以及一个回调函数,用来执行任务到期后需要执行的动作。 构…...
Flutter简单实现滑块验证
现在实现一个 Flutter 滑动验证组件,类似于许多网站和应用程序中常见的“滑动以验证”功能。它通过滑动一个滑块来完成验证操作,用户需要将滑块拖动到指定位置以完成验证。 前置知识点整理 StatefulWidget 在 Flutter 中,StatefulWidget 是…...
第33周:运动鞋识别(Tensorflow实战第五周)
目录 前言 一、前期工作 1.1 设置GPU 1.2 导入数据 1.3 查看数据 二、数据预处理 2.1 加载数据 2.2 可视化数据 2.3 再次检查数据 2.4 配置数据集 2.4.1 基本概念介绍 2.4.2 代码完成 三、构建CNN网络 四、训练模型 4.1 设置动态学习率 4.2 早停与保存最佳模型…...
C#中switch语句使用
编写一个程序,使用switch语句将用户输入的分数转换成等级,如表 private static void Main(string[] args) { Console.WriteLine("请输入分数:"); int score int.Parse(Console.ReadLine()); switch (score) …...
2024.11.28(作业)
思维导图 功能函数声明文件 #ifndef _FUN_H__ #define _FUN_H__ #include <myhead.h>#define MAX 50 //数组大小 #define QAZ 20 //长度和字符串大小typedef int datatype; //数据元素类型//2.1 定义顺序表类型 typedef struct {datatype data[MAX];int len; }S…...
充分统计量(Sufficient Statistic)概念与应用: 中英双语
充分统计量:概念与应用 在统计学中,充分统计量(Sufficient Statistic) 是一个核心概念。它是从样本中计算得出的函数,能够完整且无损地表征样本中与分布参数相关的信息。在参数估计中,充分统计量能够帮助我…...
2. STM32_中断
中断 中断是什么: 打断CPU执行正常的程序,转而处理紧急程序,然后返回原暂停的程序继续运行,就叫中断。 中断的意义: 中断可以高效处理紧急程序,不会一直占用CPU资源。如实时控制、故障处理、处理不确定…...
CAD 文件 批量转为PDF或批量打印
CAD 文件 批量转为PDF或批量打印,还是比较稳定的 1.需要本地安装CAD软件 2.通过 Everything 搜索工具搜索,DWG To PDF.pc3 ,获取到文件目录 ,替换到代码中, originalValue ACADPref.PrinterConfigPath \ r"C:…...
明明的随机数
题目描述 明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的随机整数(N≤100),对于其中重复的数字,只保留一个,把其余相同的数去掉ÿ…...
2024金盾信安杯线上赛 MISC ezpng[wp]
下载题目发现给了个password和png 图片发现损坏的 password丢随波逐流一键解 base64 给出解码的结果是 cimbar搜索发现在Github有工具 然后对附件中的图片进行小厨房xor 得到一张新图片 利用工具进行跑出答案...
C与指针。
目录 1_指针理解 1.1变量的值 1.2变量的地址 1.3指针 1.4取变量的地址 2_分析指针 2.1分析指针变量的要素 2.2根据需求定义指针变量 3_指针的使用 3.1指针对变量的读操作 3.2指针对变量的写操作 4_指针占用空间的大小与位移 4.1指针占用空间的大小 4.2指针的位移…...
使用 Selenium 和 Python 爬取腾讯新闻:从基础到实践
使用 Selenium 和 Python 爬取腾讯新闻:从基础到实践 在这篇博客中,我们将介绍如何利用 Selenium 和 Python 爬取腾讯新闻的内容,并将结果保存到 CSV 文件中。本教程包含以下内容: 项目简介依赖安装实现功能的代码实现中的关键技…...
ElasticSearch的下载和基本使用(通过apifox)
1.概述 一个开源的高扩展的分布式全文检索引擎,近乎实时的存储,检索数据 2.安装路径 Elasticsearch 7.8.0 | Elastic 安装后启动elasticsearch-7.8.0\bin里的elasticsearch.bat文件, 启动后就可以访问本地的es库http://localhost:9200/ …...
处理HTTP请求的两种常见方式:多个处理器(Handler)、多个处理函数(HandleFunc),两者有什么区别
一、多个处理器(Handler)、多个处理函数(HandleFunc),两者的区别: 在Go语言中,处理HTTP请求的两种常见方式是使用http.Handler接口和http.HandleFunc函数。它们都用于定义如何处理HTTP请求,但它们之间有一些关键的区别࿱…...
在oracle下载jdk显示400 Bad Request Request Header Or Cookie Too Large
下载JDK17,官网地址:【https://www.oracle.com/cn/java/technologies/downloads/#jdk17-windows】 问题: 出现 400 Bad Request: Request Header Or Cookie Too Large 错误,通常是由于浏览器存储的 Cookies 或请求头过大所导致的…...
机器学习与深度学习-2-Softmax回归从零开始实现
机器学习与深度学习-2-Softmax回归从零开始实现 1 前言 内容来源于沐神的《动手学习深度学习》课程,本篇博客对于Softmax回归从零开始实现进行重述,依旧是根据Python编程的PEP8规范,将沐神的template代码进行简单的修改。近期有点懒散哈哈哈…...
Vue3之弹窗
文章目录 第一步、引入JS第二步、弹框 在前端开发语言Vue3,在管理端如何进行弹窗?下面根据API实现效果。 Element API文档: Element-plus文档 搭建环境可参考博客【 初探Vue3环境搭建与nvm使用】 第一步、引入JS <script lang"ts&…...
计算机的错误计算(一百七十一)
摘要 探讨 MATLAB 中秦九韶(Horner)多项式的错误计算。 例1. 用秦九韶(Horner)算法计算(一百零七)例1中多项式 直接贴图吧: 这样,MATLAB 给出的仍然是错误结果,因为准…...
利用Python爬虫精准获取淘宝商品详情的深度解析
在数字化时代,数据的价值日益凸显,尤其是在电子商务领域。淘宝作为中国最大的电商平台之一,拥有海量的商品数据,对于研究市场趋势、分析消费者行为等具有重要意义。本文将详细介绍如何使用Python编写爬虫程序,精准获取…...
_C#_串口助手_字符串拼接缺失问题(未知原理)
最近使用WPF开发串口助手时,遇到一个很奇怪的问题,无论是主线程、异步还是多线程,当串口接收速度达到0.016s一次以上,就会发生字符串缺失问题并且很卡。而0.016s就一切如常,仿佛0.015s与0.016s是天堑之隔。 同一份代码…...
volcano k8s 部署
下载volcano-development文件 官网 https://volcano.sh/zh/docs/installation/volcano-development.yaml wget https://raw.githubusercontent.com/volcano-sh/volcano/master/installer/volcano-development.yaml部署volcano 查下需要下载的镜像 grep vc- volcano-develo…...
Linux---对时/定时服务
文章目录 目录 文章目录 前言 一.对时服务 服务端配置 客户端配置 二.定时服务 单次定时任务 循环定时任务 前言 在当今信息化高速发展的时代,时间的准确性和任务的定时执行对于各种系统和服务来说至关重要。Linux操作系统,凭借其强大的功能和灵活的…...
13 设计模式之外观模式(家庭影院案例)
一、什么是外观模式? 1.定义 在日常生活中,许多人喜欢通过遥控器来控制家中的电视、音响、DVD 播放器等设备。虽然这些设备各自独立工作,但遥控器提供了一个简洁的界面,让用户可以轻松地操作多个设备。而这一设计理念正是 外观模…...
spring boot整合ArtemisMQ进行手动消息确认
1、SpringBoot整合ArtemisMQ进行手动消息确认使用的是: factory.setSessionTransacted(false); factory.setSessionAcknowledgeMode(ActiveMQJMSConstants.INDIVIDUAL_ACKNOWLEDGE); 2、SpringBoot整合ActiveMQ进行手动消息确认使用的是: factory.setSe…...
dpwwn02靶场
靶机下载地址:https://download.vulnhub.com/dpwwn/dpwwn-02.zip 信息收集 ip add 查看kali Linux虚拟机的IP为:10.10.10.128 https://vulnhub.com/entry/dpwwn-2,343/中查看靶机的信息,IP固定为10.10.10.10 所以kali Linux添加仅主机网卡…...
展示和添加篮球队信息--laravel与elementplus
之前使用laravel与inertia来做过一样的功能,感觉不满意,因此再结合elementplus重做一遍,先展示下重做后的效果。重写后的代码相比之下比较优雅。 球队首页 球队添加页 球员首页 很明显的改变,我新增了侧栏菜单来控制局部模块(这里是指NBABasketba…...
K8S疑难概念理解——Pod,应该以哪种Kind来部署应用,为什么不直接Pod这种kind?
文章目录 一、Pod概念深度理解,为什么一般不直接以kindPod资源类型来部署应用?二、究竟应该以哪种资源类型来部署应用 一、Pod概念深度理解,为什么一般不直接以kindPod资源类型来部署应用? Pod是Kubernetes中的最小部署单元,可以包含一个或…...
centos7怎么安装keepalive+nginx
在CentOS 7上安装Keepalived和Nginx,可以按照以下步骤进行: 安装Nginx 添加Nginx到Yum源: rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm安装Nginx: yum install -y ng…...
DevOps工程技术价值流:Jenkins驱动的持续集成与交付实践
一、Jenkins系统概述 Jenkins:开源CI/CD引擎的佼佼者 Jenkins,作为一款基于Java的开源持续集成(CI)与持续交付(CD)系统,凭借其强大的插件生态系统,成为DevOps实践中不可或缺的核心…...
el-select 修改样式
这样漂亮的页面,搭配的却是一个白色风格的下拉框 ,这也过于刺眼。。。 调整后样式为: 灯红酒绿总有人看着眼杂,但将风格统一终究是上上选择。下面来处理这个问题。 分为两部分。 第一部分:是修改触发框的样式 第二部…...
文本内容处理命令和正则表达式
文本内容处理命令 grep 用来过滤文本内容,以匹配要查询的结果。 -m 数字 匹配几次后停止: grep -m 1 /root/etc/passwd #查找包含root的行 -v 取反 -i 忽略字符的大小写,默认的,可以不加 -n 显示匹配的行号 -c 统计匹配的…...