领域驱动设计(DDD)技术分享:从三层架构到DDD的进化之旅
一、开篇话:我们为什么要聊DDD?
如果你像我一样有着Java开发背景,那Spring的三层架构可能是你的老朋友了。Controller-Service-DAO这种模式简直就像我们编程的"家常便饭"。但是,随着业务越来越复杂,你是否也感觉到传统三层架构有点"吃力"了?代码越写越乱,业务逻辑满天飞,改一个小功能要翻几十个文件…
今天,我想和大家聊聊领域驱动设计(DDD),这个听起来有点"高大上"但其实超实用的设计思想。不要被那些专业术语吓到,本质上DDD就是让代码更贴近业务、更容易理解和维护的一种方法。
二、三层架构:我们熟悉的老朋友
2.1 三层架构长啥样?
传统的Spring应用基本都是这三层结构:
- Controller层:接收请求,返回结果,就像餐厅的服务员
- Service层:处理业务逻辑,就像餐厅的厨师
- DAO/Repository层:负责数据存取,就像餐厅的采购和储藏室
┌─────────────────┐
│ Controller │ "您好,需要点什么?"
└────────┬────────┘│▼
┌─────────────────┐
│ Service │ "我来做一份红烧肉!"
└────────┬────────┘│▼
┌─────────────────┐
│ DAO/Repository │ "取出猪肉和调料..."
└────────┬────────┘│▼
┌─────────────────┐
│ Database │ 冰箱和储物柜
└─────────────────┘
2.2 三层架构在SpringBoot中的实际代码
// Controller层:负责接待客人
@RestController
@RequestMapping("/api/users")
public class UserController {@Autowiredprivate UserService userService;@GetMapping("/{id}")public ResponseEntity<User> getUser(@PathVariable Long id) {return ResponseEntity.ok(userService.findById(id));}
}// Service层:负责烹饪美食
@Service
public class UserService {@Autowiredprivate UserRepository userRepository;public User findById(Long id) {return userRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException("User not found"));}
}// DAO层:负责原料管理
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}
2.3 三层架构的好处
- 简单直接:结构清晰,容易理解,就像"老一辈"教我们做菜的固定步骤
- 分工明确:每一层各司其职,不乱来
- 容易测试:各层可以独立测试,不互相干扰
- 上手快:新人很容易理解和上手,开发效率高
2.4 三层架构的"软肋"
但是,随着"菜谱"(业务)越来越复杂,三层架构开始显露出一些问题:
- 业务逻辑到处飞:业务规则散布在各个Service中,就像食谱的步骤撕成几页放在不同的地方
- 实体类只有属性没有方法:User类只有getter/setter,没有行为,就像一堆食材却不知道怎么烹饪
- 模型与业务脱节:代码里的类和现实业务概念对不上号
- 与数据库强绑定:业务逻辑和数据库结构紧密相连,改一个影响另一个
- 复杂业务难以驾驭:业务规则变复杂时,代码组织乱如麻,无法维护
三、DDD:另一种思考软件的方式
3.1 DDD是怎么来的?
领域驱动设计是Eric Evans在2003年提出的一种设计方法。它不是什么神奇的技术框架,而是一种思考和组织软件的方法。就像我们不仅需要知道"怎么炒青菜",还要理解"为什么这样炒更好吃"一样,DDD帮助我们更深入地理解业务本身。
3.2 为啥我们需要DDD?
- 应对复杂性:现代系统越来越"大",需要更好的方法来应对
- 让技术与业务对话:技术人员和业务人员能用同一种语言沟通
- 软件如实反映现实:代码结构更贴近真实的业务模型
- 不被数据库绑架:业务逻辑不依赖特定的数据库技术
- 拥抱变化:更容易适应业务变化,减少"屎山"的产生
3.3 DDD的核心概念
- 统一语言:开发人员和业务人员统一用语,不各说各话
- 领域模型:用软件反映业务世界的模型
- 界限上下文:将大系统分解为小系统,互不干扰
- 上下文映射:定义小系统之间如何交流
- 实体:有唯一标识的对象,比如"用户张三"
- 值对象:没有标识的对象,比如"地址信息"
- 聚合:一组相关对象的集合,作为整体处理
- 领域事件:记录领域中发生的重要事情
- 领域服务:不属于任何对象的操作
- 资源库:提供对数据的访问
四、DDD怎么落地?实操指南
4.1 DDD的分层架构
DDD通常采用这样的分层:
┌─────────────────┐
│ 用户界面/接口层 │ "您好,请问需要什么服务?"
└────────┬────────┘│▼
┌─────────────────┐
│ 应用层 │ "我来协调一下各部门完成这个任务"
└────────┬────────┘│▼
┌─────────────────┐
│ 领域层 │ "这里是业务的核心知识和规则"
└────────┬────────┘│▼
┌─────────────────┐
│ 基础设施层 │ "我来提供技术支持和工具"
└─────────────────┘
4.2 Python实现的例子:账户管理
# 领域层 - 值对象:表示钱
class Money:def __init__(self, amount: Decimal, currency: str):self.amount = amountself.currency = currencydef __add__(self, other):if self.currency != other.currency:raise ValueError("不能把美元和人民币直接相加!")return Money(self.amount + other.amount, self.currency)# 领域层 - 实体:账户
class Account:def __init__(self, account_id: str, balance: Money, owner: str):self.id = account_idself.balance = balanceself.owner = ownerself.events = [] # 领域事件列表def deposit(self, amount: Money):# 存款必须是正数,这是业务规则if amount.amount <= 0:raise ValueError("存款金额必须大于零")self.balance += amount# 记录"存款成功"这个事件self.events.append(FundsDepositedEvent(self.id, amount))def withdraw(self, amount: Money):# 取款必须是正数if amount.amount <= 0:raise ValueError("取款金额必须大于零")# 账户余额必须足够if self.balance.amount < amount.amount:raise InsufficientFundsError(f"余额不足!想取{amount.amount},但只有{self.balance.amount}")self.balance -= amount# 记录"取款成功"这个事件self.events.append(FundsWithdrawnEvent(self.id, amount))# 领域层 - 领域事件:记录发生了什么
class FundsDepositedEvent:def __init__(self, account_id: str, amount: Money):self.account_id = account_idself.amount = amountself.occurred_on = datetime.now()# 基础设施层 - 仓储:负责数据存取
class AccountRepository:def __init__(self, db_session):self.db_session = db_sessiondef find_by_id(self, account_id) -> Account:# 从数据库找账户account_data = self.db_session.query(AccountModel).get(account_id)if not account_data:raise AccountNotFoundError(f"找不到账户 {account_id}")# 转换为领域对象return Account(account_id=account_data.id,balance=Money(account_data.balance_amount, account_data.balance_currency),owner=account_data.owner)def save(self, account: Account):# 保存账户数据# ...# 发布领域事件,通知其他系统for event in account.events:event_bus.publish(event)# 清空事件列表account.events.clear()# 应用层 - 应用服务:协调业务流程
class AccountService:def __init__(self, account_repository):self.account_repository = account_repositorydef transfer_money(self, from_account_id, to_account_id, amount):# 获取两个账户from_account = self.account_repository.find_by_id(from_account_id)to_account = self.account_repository.find_by_id(to_account_id)# 执行转账操作money = Money(amount, "USD")from_account.withdraw(money) # 从一个账户取钱to_account.deposit(money) # 存到另一个账户# 保存修改结果self.account_repository.save(from_account)self.account_repository.save(to_account)
4.3 实践DDD的关键点
- 模型要有血有肉:领域对象不只有数据,还有行为和规则
- 把变化关进笼子:将容易变化的业务规则封装在一个地方
- 用事件传递消息:通过事件告诉其他部分"发生了什么"
- 合理分组:将相关的对象组织在一起,保持数据一致性
- 数据访问要抽象:业务逻辑不应该依赖具体的数据库
- 应用服务做协调:应用服务像导演一样协调各个领域对象工作
五、DDD与自然界的相似之处:分形原理
DDD的设计理念与自然界的分形原理很像,这不是巧合!
5.1 什么是分形?
分形是自然界中常见的一种结构,无论放大多少倍,都能看到相似的图案。比如雪花、树叶脉络、山脉、海岸线等。想象一下:一棵树的整体形状,和它的一个分支形状很像;这个分支的形状,又和更小的分支形状相似。
5.2 DDD与分形的共同点
-
自相似性:
- 分形:看整体和局部,都是相似的图案
- DDD:从大的业务领域到小的对象,都遵循相同的设计原则
-
边界清晰:
- 分形:每个部分有明确的边界
- DDD:通过界限上下文和聚合根明确划分责任边界
-
简单规则产生复杂结构:
- 分形:简单的数学公式可以生成复杂美丽的图案
- DDD:清晰的领域规则组合起来构建复杂系统
-
适应性与进化:
- 分形:分形结构能适应环境变化(如树根寻找水源)
- DDD:领域模型能随业务变化而调整
-
局部自主:
- 分形:每个局部结构有一定的独立性
- DDD:每个聚合管理自己的规则和状态
5.3 用分形思维设计软件
用分形思维设计软件意味着:
- 划清界限,各管各的
- 让各部分能独立发展
- 大处着眼,小处也用心
- 用小积木搭建大城堡
- 让系统能自我调整适应变化
六、怎么从Spring三层架构过渡到DDD?
6.1 渐进式改造策略
- 统一语言先行:和业务专家达成共识,更新代码中的术语
- 找出核心领域:确定系统中最重要的业务部分
- 丰富领域模型:把业务逻辑从Service层移到领域对象中
- 划分上下文边界:将系统分解为相对独立的子系统
- 引入值对象:用不可变对象替代简单数据类型
- 实现领域事件:通过事件解耦各个组件
- 建防腐层:隔离外部系统和旧代码的影响
6.2 改造中会遇到的坑
- 思维转变难:从技术思维转向领域思维需要时间
- 容易过度设计:别把简单问题复杂化
- 学习曲线陡:DDD概念需要时间消化
- 性能平衡:富领域模型可能带来一些性能挑战
- 新旧代码共存:处理与现有系统的兼容问题
七、总结:DDD不是银弹,但值得一试
领域驱动设计(DDD)给我们提供了处理复杂业务系统的一套思路。相比传统的Spring三层架构,DDD更注重业务建模,更强调开发人员和业务人员的沟通,通过丰富的领域模型把业务规则明确地表达出来。
DDD和自然界的分形原理一样,都强调在不同层次上保持相似的结构,划定清晰的边界,通过简单规则构建复杂系统。这种思维方式有助于我们开发出更灵活、更可维护的软件。
对于习惯了Java Spring的开发者来说,转向DDD需要一些思维上的调整,但这个过程会让我们对业务有更深入的理解,写出更好的代码,应对不断变化的业务需求。
记住,DDD不是万能药,也不是所有项目都需要用DDD。对于简单的CRUD应用,传统三层架构可能就足够了。但对于复杂的业务系统,DDD绝对值得一试!
参考资料
- Eric Evans 的《领域驱动设计》
- Vaughn Vernon 的《实现领域驱动设计》
- Martin Fowler 的《企业应用架构模式》
- Benoit Mandelbrot 的《分形:大自然的奇妙几何学》
相关文章:
领域驱动设计(DDD)技术分享:从三层架构到DDD的进化之旅
一、开篇话:我们为什么要聊DDD? 如果你像我一样有着Java开发背景,那Spring的三层架构可能是你的老朋友了。Controller-Service-DAO这种模式简直就像我们编程的"家常便饭"。但是,随着业务越来越复杂,你是否也…...
LeetCode - #227 基于 Swift 实现基本计算器
摘要 在这篇文章中,我们将实现一个基于 Swift 语言的基本计算器。该计算器能够解析和计算包含 、-、* 和 / 的数学表达式,并且遵循运算符的优先级规则。整数除法仅保留整数部分,不能使用 eval() 这样的内置解析方法。 描述 给你一个字符串表…...
Elasticsearch Java High Level Client [7.17] 使用
es 的 HighLevelClient存在es源代码的引用,结合springboot使用时,会存在es版本的冲突,这里记录下解决冲突和使用方式(es已经不建议使用这个了)。 注意es服务端的版本需要与client的版本对齐,否则返回数据可…...
[多线程]基于环形队列(RingQueue)的生产者-消费者模型的实现
标题:[多线程]基于环形队列(RingQueue)的生产者-消费者模型 水墨不写bug 一、模型实现 接下来我们要实现一个基于环形队列(RingQueue)的生产者-消费者模型。该模型使用信号量和互斥锁来保证生产者和消费者之间的同步与…...
HAL库STM32常用外设—— CAN通信(一)
文章目录 一、CAN是什么?1.1 CAN应用场景1.2 CAN通信优势 二、CAN基础知识介绍2.1 CAN总线结构2.2 CAN总线特点2.2.1 CAN总线的数据传输特点2.2.2 位时序和波特率 2.3 CAN位时序和波特率2.3 CAN物理层2.3.1 CAN 物理层特性2.3.2 CAN 收发器芯片介绍 2.4 CAN协议层2.…...
分页查询的实现
目录 前言 一.问题描述 二.后端实现步骤 2.1配置PageHelper插件 ①导入依赖 ②在application.yml配置文件中添加相关配置 2.2编写一个入门的程序,体验分页过程 2.3定义一个vo,用来收集分页后的所有信息 2.4修改serviceImpl层的代码 2.5动态设…...
Sourcetree——使用.gitignore忽略文件或者文件夹
一、为何需要文件忽略机制? 1.1 为什么要会略? 对于开发者而言,明智地选择忽略某些文件类型,能带来三大核心优势: 仓库纯净性:避免二进制文件、编译产物等污染代码库 安全防护:防止敏感信息&…...
Thinkphp的belongsToMany(多对多) 和 hasManyThrough(远程一对多)的区别是什么?
虽然 belongsToMany(多对多) 和 hasManyThrough(远程一对多) 都会使用 JOIN 查询,但它们的核心区别在于 关联关系的本质不同,具体如下: 1️⃣ belongsToMany(多对多) &a…...
DataWhale 大语言模型 - 大模型技术基础
本课程围绕中国人民大学高瓴人工智能学院赵鑫教授团队出品的《大语言模型》书籍展开,覆盖大语言模型训练与使用的全流程,从预训练到微调与对齐,从使用技术到评测应用,帮助学员全面掌握大语言模型的核心技术。并且,课程…...
Docker+Flask 实战:打造高并发微服务架构
DockerFlask 实战:打造高并发微服务架构 今天我们要深入探讨一个非常热门且实用的主题:基于 Docker 部署 Python Flask 应用。Docker 作为当下最流行的容器化技术,已经广泛应用于各种开发和部署场景,尤其是在微服务架构中。而 Fl…...
前端跨域如何调试,以及相关概念梳理【环境变量 本地代理 正向代理 反向代理 OPTIONS请求 CDN 等】
跨域报错 一 前端日常开发时,项目的部署地址和接口请求的地址一般是同源的,不会跨域。 例如项目的测试环境部署在https://my-dev.BeatingWorldLine.com/xxx, 测试环境的访问接口域名也要相同来保证不跨域https://my-dev.BeatingWorldLine.com/api/xxx, …...
【区块链】以太坊
学习视频源链接: https://www.bilibili.com/video/BV1Vt411X7JF/ 本文是根据肖老师的视频进行的笔记记录 bitcoin 1.0 区块链 以太坊 2.0区块链 以太坊 设置了 memory hard mining puzzle ,这造成了asic resistance, 后续 proof of work &a…...
MCU的工作原理:嵌入式系统的控制核心
MCU的工作原理可以概括为以下几个步骤: 1. 初始化 上电后,MCU从Flash存储器中加载程序代码,并初始化外设和寄存器。 2. 任务执行 根据程序逻辑,MCU执行数据处理、外设控制和通信等任务。通过中断系统实时响应外部事件。 3. 低…...
离线服务器ollama新增qwen2:0.5b模型
离线服务器ollama新增qwen2:0.5b模型 Dify集成ollama前面已经介绍过离线服务器CentOS使用的docker安装的ollama,其中在ollama中已经安装了deepseek-r1:1.5b。目前的需求是需要再安装一个qwen2:0.5b的模型,那么如何安装呢? 1.首先在有网的服…...
Ubuntu20.04安装运行DynaSLAM
目录 一、安装Anaconda 二、相关依赖库安装 1、boost安装 2、Eigen 3安装 3、opencv安装 4、Pangolin安装 三、配置Mask_RCNN环境 四、DynaSLAM编译 五、DynaSLAM运行 一、安装Anaconda 打开以下链接: Index of / 下载和自己系统匹配的安装包。这里下…...
Apache Shiro反序列化漏洞深度剖析:从原理到利用
引言 在Web安全的世界里,反序列化漏洞一直是最危险的漏洞类型之一。今天,我们将深入探讨Apache Shiro框架中的两个著名反序列化漏洞.通过通俗易懂的解释和详细的实例,帮助你理解这类漏洞的本质和危害。 Shiro框架与"记住我"功能简…...
Android UI 组件系列(二):Button 进阶用法
引言 在上一篇博客中,我们介绍了 Button 的基本用法和常见属性,掌握了 Button 的基础知识。然而,在实际开发中,Button 远不止于简单的点击功能,它还可以支持不同的变体、丰富的自定义样式,以及更灵活的状态…...
CentOS-7安装Docker(更新时间:2025-03-12)
CentOS-7安装Docker 该文章记录在CentOS 7上安装Docker的过程和步骤,以及在安装过程中遇到的困难和解决方案。 目录 CentOS-7安装Docker一、环境准备二、安装Docker1.验证服务器是否接入互联网2. 检查CentOS内核版本3.使用root权限登录CentOS。确保yum包更新到最新…...
网络空间安全(31)安全巡检
一、定义与目的 定义: 安全巡检是指由专业人员或特定部门负责,对各类设施、设备、环境等进行全面或重点检查,及时发现潜在的安全隐患或问题。 目的: 预防事故发生:通过定期的安全巡检,及时发现并解决潜在的…...
Kubernetes学习笔记-移除Nacos迁移至K8s
项目服务的配置管理和服务注册发现由原先的Nacos全面迁移到Kubernetes上。 一、移除Nacos 移除Nacos组件依赖。 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <…...
Docker 构建 nginx-redis-alpine 项目详解
Docker 构建 nginx-redis-alpine 项目详解 一、课程概述 嘿,朋友们!今天咱们要深入探索一个超级实用的项目 ——nginx-redis-alpine!这个项目可不简单,它包含了好多重要的知识点,像文件目录结构、核心文件的作用及配…...
【教学类-43-26】20240312 数独4宫格的所有可能(图片版 576套样式,空1格-空8格,每套65534张*576小图=3千万张小图)
背景需求: 之前做了三宫格所有可能图片 510小图*12套6120图,所以3分钟就生成了 【教学类-43-25】20240311 数独3宫格的所有可能(图片版 12套样式,空1格-空8格,每套510张,共6120小图)-CSDN博客…...
ChromeOS 134 版本更新
ChromeOS 134 版本更新 一、ChromeOS 134 更新内容 1. ChromeOS 自助终端(Kiosk)模式支持隔离 Web 应用(Isolated Web Apps) 从 ChromeOS 134 开始,自助终端(Kiosk)模式支持 隔离 Web 应用&a…...
Redis面试篇
目录 Redis面试篇 1.什么是Redis?作用是什么? 2.什么是缓存穿透、缓存击穿、缓存雪崩 2.1缓存穿透 2.2缓存击穿 2.3缓存雪崩 3.redis如何持久化 1. RDB(快照存储) 2. AOF(追加日志) 4.Redis 的过…...
C#中通过Response.Headers设置自定义参数
一、基础设置方法 1. 直接添加自定义头 // ASP.NET Core方案 Response.Headers.Append("X-API-Version", "2.3.1"); Response.Headers.Append("Custom-Auth-Token", Guid.NewGuid().ToString());• 底层原理:通过IHeaderDictionary…...
C++标准模板库学习--函数模板返回值参数类型
template<typename T1, typename T2> 2 T1 max (T1 a, T2 b) 3 { 4 return b < a ? a : b; 5 } 6 ... 7 auto m ::max(4, 7.2); // OK, 不过返回类型与第一个参数类型一样 如何解决模板的返回类型 法一,使用decltype进行类型推断,在编译时…...
BUG修复 | 一次钉钉工作台应用远程调试实战(开发者工具)
#1 ℹ️背景故事 最近用户反馈,钉钉工作台的应用无法正常使用,卡在自动登录页面。 天,这是运行10年的老程序😱,我当时真是吓得不轻。这老古董完全不记得怎么改了😂。 #2 🐞开启远程调试 钉钉…...
[目标检测] 训练之前要做什么
背景:训练一个Yolo8模型,在训练之前,数据集的处理是影响效果的关键因素。 Step1 定义规则 什么是人/车,比如人的话可能是站着的人,如果是骑电动车/自行车就不算是人。 Step2 收集数据集 1. 自己标注。如果是自己标…...
一窥DeepSeek开源EPLB项目:揭开技术背后的面纱
摘要 在DeepSeek开源DualPipe项目的同一天,EPLB项目也正式对外公开。EPLB(Enhanced Pipeline Balancing)并非一蹴而就的奇迹,而是经过长时间的研发与优化。该项目旨在通过改进管道平衡机制,提升系统的稳定性和效率。本…...
达梦数据库中插入导出图片的方法与应用
达梦数据库中插入导出图片的方法与应用 在数据库的实际应用场景中,图片存储是一项常见且重要的需求。以电商平台为例,商品展示图片是吸引消费者的关键元素;而在社交软件里,用户头像更是个人形象的直观体现。针对达梦数据库&#…...
问deepseek: OpenFOAM并行分区后,是如何实现ldumatrix矩阵向量乘法计算逻辑的?
在OpenFOAM中,lduMatrix 是用于存储稀疏矩阵的类,支持并行计算。并行分区后,lduMatrix 的矩阵向量乘法通过以下步骤实现: 1. 矩阵分区 分区:将矩阵和向量分配到多个处理器上,每个处理器负责一部分。接口&…...
linux(ubuntu)中Conda、CUDA安装Xinference报错ERROR: Failed to build (llama-cpp-python)
文章目录 一、常规办法二、继续三、继续四、缺少 libgomp库(最终解决)在 Conda 环境中安装 libgomp 如果符合标题情况 执行的: pip install "xinference[all]"大概率是最终解决的情况。 一、常规办法 llama-cpp-python 依赖 CMak…...
蓝耘携手通义万象 2.1 图生视频:开启创意无限的共享新时代
在科技飞速发展的今天,各种新奇的技术不断涌现,改变着我们的生活和工作方式。蓝耘和通义万象 2.1 图生视频就是其中两项非常厉害的技术。蓝耘就像是一个超级大管家,能把各种资源管理得井井有条;而通义万象 2.1 图生视频则像是一个…...
04 1个路由器配置一个子网的dhcp服务
前言 这是最近一个朋友的 ensp 相关的问题, 这里来大致了解一下 ensp, 计算机网络拓扑 相关基础知识 这里一系列文章, 主要是参照了这位博主的 ensp 专栏 这里 我只是做了一个记录, 自己实际操作了一遍, 增强了一些 自己的理解 当然 这里仅仅是一个 简单的示例, 实际场景…...
Android studio运行报错处理
没装HAXM报错: Intel HAXM 7.6.5 下载 下载链接: https://www.filehorse.com/download-intel-haxm/54766/download/#google_vignette 运行时弹窗提示:Device manager The emulator process for AVD Pixel_3a_API_34_extension_level_7_x86_6…...
【CXX】6.7 SharedPtr<T> — std::shared_ptr<T>
std::shared_ptr 的 Rust 绑定称为 SharedPtr。 限制: SharedPtr 不支持 T 为不透明的 Rust 类型。对于在语言边界上传递不透明 Rust 类型的所有权,应改用 Box(C 中的 rust::Box)。 示例 // src/main.rsuse std::ops::Deref; …...
NocoBase 本周更新汇总:双因素身份认证(2FA)
原文链接:https://www.nocobase.com/cn/blog/weekly-updates-202503013 汇总一周产品更新日志,最新发布可以前往我们的博客查看。 本周我们发布了 NocoBase 1.6.0 版本,带来集群模式部署、安全策略优化和迁移管理等多项新特性。 NocoBase …...
【Go学习】04-1-Gin框架-路由请求响应参数
【Go学习】04-1-Gin框架 初识框架go流行的web框架GinirisBeegofiber Gin介绍Gin快速入门 路由RESTful API规范请求方法URI静态url路径参数模糊匹配 处理函数分组路由 请求参数GET请求参数普通参数数组参数map参数 POST请求参数表单参数JSON参数 路径参数文件参数 响应字符串方式…...
DataX的python3使用
datax这东西本身是python2写的,这导致python3,就各种语法报错,问题是,现在的工程都是python3搞的,这就很难受.... 网上找到一篇帖子,可以解决这个问题: 原帖:python3执行datax报错…...
部署项目至服务器:响应时间太长,无法访问此页面?
在我们部署项目到服务器上的时候,一顿操作猛如虎,打开页面..... 这里记录一下这种情况是怎么回事。一般就是服务器上的安全组没有放行端口。 因为我是用宝塔进行项目部署的。所以遇到这种情况,要去操作两边(宝塔and服务器所属平台…...
Map<String,Object>中Fastjson提取entrys对应的值
今天在处理接口数据时,需要解析出对方传入的json数据,并需要取出其中一个字段的值来判断,记录下我的步骤,提供参考: 1.json数据准备 {"hrOrgUnit": "00000000-0000-0000-0000-000000000000CCE7AED4&q…...
【毕业论文格式】word分页符后的标题段前间距消失
文章目录 【问题描述】 分页符之后的段落开头,明明设置了标题有段前段后间距,但是没有显示间距: 【解决办法】 选中标题,选择边框 3. 选择段前间距,1~31磅的一个数 结果...
Android,Java,Kotlin 确保线程顺序执行的多种实现方式
在多线程编程中,有时需要确保一个线程必须等待另一个线程执行完毕后再执行。本文将介绍几种常见的方法来实现这一需求,并提供详细的代码示例。 1. 使用 Thread.join() Thread.join() 是最简单直接的方法,它会让当前线程等待目标线程执行完毕…...
AWK 入门教程:强大的文本处理工具
AWK 是一种强大的文本处理工具,广泛用于 Linux/Unix 系统中对文本文件或数据流进行操作。它能够基于条件筛选、统计字段、重新排列数据等。主要特点包括: 2. AWK 的基本语法 2.1 AWK 程序的结构 AWK 程序的结构: awk pattern { action } file 2.2 常…...
【Linux】在VMWare中安装Ubuntu操作系统(2025最新_Ubuntu 24.04.2)#VMware安装Ubuntu实战分享#
今天田辛老师为大家带来一篇关于在VMWare虚拟机上安装Ubuntu系统的详细教程。无论是学习、开发还是测试,虚拟机都是一个非常实用的工具,它允许我们在同一台物理机上运行多个操作系统。Ubuntu作为一款开源、免费且用户友好的Linux发行版,深受广…...
基于yolov8+streamlit实现目标检测系统带漂亮登录界面
【项目介绍】 基于YOLOv8和Streamlit实现的目标检测系统,结合了YOLOv8先进的目标检测能力与Streamlit快速构建交互式Web应用的优势,为用户提供了一个功能强大且操作简便的目标检测平台。该系统不仅具备高精度的目标检测功能,还拥有一个漂亮且…...
安装 Powerlevel10k 及 Oh My Zsh 的使用
1. 简介 Powerlevel10k 是 Oh My Zsh 最流行的终端主题,它不仅美观,还提供 Git 状态显示、命令执行时间、网络状态、Python 虚拟环境指示等 实用功能。相比其他主题,Powerlevel10k 速度更快、可定制性更强。 本教程将详细介绍如何安装 Powe…...
虚拟机下ubuntu进不了图形界面
6.844618] piix4_smbus 0000:07.3: SMBus Host ContrFoller not enabled! 7.859836] sd 2:0:0:0:0: [sda] Assuming drive cache: wirite through /dev/sda1: clean, 200424/1966080 files, 4053235/7864064 blocks ubuntu启动时,卡在上面输出位置 当前遇到的原因…...
从 root 一滴水看 Spring Data JPA 的汪洋大海
🔥 从 root 一滴水看 Spring Data JPA 的汪洋大海 🌊 在 Spring Data JPA 的世界里,Specification 是个让人又爱又恨的家伙 💡。它能帮你动态构建查询,但那个神秘的 Root<T> root 却总让人摸不着头脑࿱…...
二进制安装指定版本的MariaDBv10.11.6
一、官网下载mariadb安装包 Download MariaDB Server - MariaDB.org 找到对应的版本 下载安装包后上传到服务器这里不再赘述。 二、安装二进制包 1、解压安装包 2、查看安装包内的安装提示文档根据提示文档进行安装 # 解压安装包 tar xf mariadb-10.11.6-linux-systemd-x8…...