自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(44)
  • 收藏
  • 关注

原创 Spring AI 与 vLLM 交互踩坑记:HTTP/2 协议引发的“消失”的请求体

摘要: 在将Spring AI从云端API切换至本地vLLM服务时,出现请求体丢失的400错误{"object":"error","message":"[{'type': 'missing', 'loc': ('body',), 'msg': 'Field required', 'input': None}]","type":"Bad Request","param":。排查发现Spring AI和LangChain4j框架的请求能到达Mock服务却无法被vLLM接收,而原生HttpClient可正常工作。

2025-11-28 18:00:16 873

原创 「JMM+Java锁+AQS」 知识图谱

这张知识图谱系统展示了 Java 并发体系的全景逻辑:从顶层的 JMM 内存模型 定义三大特性(原子性、可见性、有序性)与 happens-before 规则,到中层的 synchronized 和 volatile 在语言层实现这些语义,再到底层的 AQS(AbstractQueuedSynchronizer) 与 LockSupport 提供并发包的核心机制支撑。它揭示了从“理论规范 → 语义规则 → 语言关键字 → 框架实现 → 底层算法”的完整演化路径,让人能一眼看清 Java 并发

2025-10-16 22:04:37 377

原创 Java 并发核心:Synchronized 的演化与优化

摘要:Java线程同步与锁机制解析 文章深入探讨了Java多线程编程中的同步问题。首先解释了并发与并行的区别,指出线程安全问题源于共享资源的竞争访问。通过计数器案例展示了竞态条件导致的数值不一致问题。随后介绍了线程同步的三大目标:互斥、可见性和有序性。文章重点分析了两种锁机制:JVM内置的synchronized关键字和JUC显式锁ReentrantLock,对比了它们的实现层次和特性分类。最后详细剖析了synchronized的底层原理,包括对象头的MarkWord结构和monitorenter/moni

2025-10-09 16:10:52 1057

原创 从线程封闭到 ThreadLocal:理解并发中的私有空间

本文探讨了并发编程中的线程封闭技术及其实现方式。线程封闭通过将数据限制在单个线程中访问,避免了同步开销,是最简单的线程安全策略之一。文章介绍了三种线程封闭方式:栈封闭(利用方法局部变量)、ThreadLocal(线程局部变量)和Ad-hoc(程序控制)。重点分析了ThreadLocal的实现原理,包括Thread类中的ThreadLocalMap、ThreadLocal的哈希算法以及设置/获取值的机制。ThreadLocal通过为每个线程维护独立的数据副本,实现了高效的线程封闭,特别适合存储线程独有上下文数

2025-09-12 15:26:05 1127

原创 掌握Java线程:实现原理、生命周期与并发编程研究

Java线程核心解析 本文深入探讨Java线程的基础理论与实现原理,涵盖线程实现方式、生命周期管理和基本操作。主要内容包括: 线程实现模型:详细对比内核线程、用户线程和混合模型的优缺点,解析1:1、1:N和N:M三种线程映射方式 线程生命周期:通过Thread.State枚举类分析NEW、RUNNABLE、BLOCKED等六种状态及其转换条件 线程操作方法:提供线程创建(继承Thread、实现Runnable/Callable)、启动、休眠、让步和等待等核心操作示例代码 并发编程基础:介绍线程与进程的关系,

2025-09-12 15:25:00 634

原创 Java内存模型解析:并发编程的基石

Java 内存模型(JMM)是 Java 并发编程的核心机制,它通过抽象内存访问规则,解决了多线程环境下的可见性、有序性和原子性问题。本文从物理机并发机制入手,介绍了缓存一致性等硬件挑战,并详细阐述了 JMM 如何通过主内存与工作内存的划分、八种原子操作以及 happens-before 规则,为 Java 程序提供了一套高效、可移植的并发编程框架。

2025-09-03 15:10:56 886

原创 Java内存可见性问题解析:从CPU缓存到并发解决方案

这段代码展示了Java中的内存可见性问题:当两个线程同时访问共享变量时,由于CPU缓存机制和缺乏同步,可能导致一个线程无法看到另一个线程对变量的修改。文章通过分析CPU缓存架构、缓存一致性协议等底层原理,解释了为何移除System.out.println()会导致程序陷入无限循环。最后介绍了四种解决方案:synchronized关键字、volatile变量、原子类和并发工具,它们都能通过不同机制保证内存可见性。文章深入浅出地揭示了并发编程中的常见陷阱及其解决之道。

2025-09-03 11:14:03 602

原创 用 Spring 思维快速上手 DDD——以 Kratos 为例的分层解读

本文从Spring开发者视角解析DDD领域驱动设计,通过与Kratos框架对比,帮助理解DDD的核心思想。文章指出,传统Spring MVC分层容易导致业务逻辑与技术实现耦合,而DDD通过严格分层(接口层、应用层、领域层、基础设施层)实现解耦。重点对比了两者在Repository实现、业务规则位置和应用服务职责上的差异,并通过锁单案例演示了DDD如何将业务逻辑封装在领域对象中。最后说明Kratos通过目录结构和依赖注入强制执行DDD分层原则,确保领域层不依赖具体技术实现。

2025-08-12 21:36:33 1052

原创 Go 语言中的结构体、切片与映射:构建高效数据模型的基石

本文介绍了Go语言中的两种复合数据类型:数组和切片。数组是固定长度的数据结构,元素类型统一,长度在创建时确定且不可更改。切片是动态数组,可以自动扩缩容,底层是数组的引用,包含指针、长度和容量三个元素。文章详细讲解了数组和切片的初始化方式、基本操作、传递机制以及切片扩容的原理。特别指出切片通过共享底层数组实现高效操作,但当容量不足时会触发扩容机制,分配新数组并拷贝数据。切片操作支持多种索引方式,类似Python的切片语法。文章最后提到切片扩容的源码实现位于runtime包的slice.go文件中。

2025-08-12 16:11:06 978

原创 【实战】多协议设备管理痛点?基于Redis打造统一上下线感知方案

Redis键空间通知在设备状态监测中的应用 本文介绍了如何利用Redis键空间通知机制实现设备上下线状态监测。Redis通过发布/订阅模式提供键空间和键事件两种通知通道,可监听键的set、expired等事件。文章详细说明了Redis配置方法(KEA参数组合)、测试流程,以及SpringBoot中的具体实现方案,包括事件监听器的创建与过滤逻辑。该方案解决了多协议设备管理中掉线检测的难题,通过监听Redis键变化事件实现协议无关的设备状态感知,适用于心跳机制下的设备在线状态管理场景。

2025-08-01 22:42:25 933

原创 从 XML 到 Bean 注入:一步步写出属于你的 IoC 框架

本文通过XML解析和反射机制实现了一个简易版的IoC容器。主要步骤包括:1)创建Person实体类;2)配置XML文件定义Bean;3)使用SAXReader解析XML配置;4)通过反射实例化对象并注入属性;5)将Bean存入Map容器实现单例模式。测试结果表明,该容器能正确创建Bean并实现单例管理,通过setter方法注入属性值。这个简易实现揭示了Spring IoC的核心原理,即通过配置文件+反射机制实现对象创建和依赖注入,为理解Spring框架底层机制提供了实践基础。

2025-07-31 14:51:10 950

原创 【 Java 】HTTP 通用请求工具类 —— RESTful

本文介绍了基于JDK17内置java.net.http.HttpClient封装的HTTP请求工具类,无需第三方依赖。工具类提供GET、POST(JSON/表单)和PUT请求方法,支持自定义请求头、超时时间(默认10秒)和请求参数。包含日志记录功能,自动处理URL编码和JSON验证,并对超时和异常进行统一处理。方法重载简化调用,如doGet()支持无参/带请求头调用,doPostJson()支持JSON字符串提交,doPostForm()支持表单参数处理。该封装简化了JDK原生HttpClient的使用

2025-07-31 14:46:51 300

原创 Go语言新手村:轻松理解变量、常量和枚举用法

本文介绍了Go语言的基础类型、变量与常量的定义和作用域,以及如何使用 const 和 iota 实现枚举。重点讲解了包级与局部作用域的区别,以及可导出变量/常量的规则。内容简洁清晰,适合Go初学者快速掌握核心概念。

2025-07-29 17:30:08 776

原创 为什么用了Spring,代码突然变干净了?

Spring框架通过控制反转(IoC)和面向切面编程(AOP)两大核心机制,显著提升了代码质量。IoC容器接管对象创建与依赖管理,消除硬编码耦合,使代码更灵活可扩展;AOP将横切关注点(如日志、事务)与业务逻辑解耦,通过动态织入实现功能增强。这些特性让开发者能专注于业务核心,减少重复代码,提高模块化程度,最终使代码更简洁、可维护性更强。Spring的模块化设计、轻量级特性和高复用性,使其成为Java企业级开发的首选框架。

2025-07-28 10:59:27 667

原创 【实战】SpringBoot整合ffmpeg实现动态拉流转推

在最近的开发中,遇到一个 rtsp 协议的视频流,前端vue并不能直接播放,因此需要对流进行处理。在网上查阅后,ffmpeg和webrtc是最多的解决方案,但是使用webrtc的时候没成功,所以选择ffmpeg。免密登录需要将公钥复制到被登录的目标服务器,在现在需求中,需要在容器中远程登录宿主机,所以宿主机就是目标服务器,那么换个思路,将这里生成的私钥,放在容器中,就可以从容器中远程登录宿主机。下面介绍一下整体的实现步骤。现在最简单的demo就已经完成了,但是这样的实现方式需要手动控制,

2024-07-30 15:40:40 4194

原创 Docker 搭建 Redis 环境

Redis 是一个基于内存的高性能非关系型数据库,在后端开发中非常常用,本文介绍一下如何在 Linux 环境中搭建 Redis。注意容器和宿主机的端口映射,用云服务器的话需要打开宿主机的端口安全组。Linux环境安装Docker,参考。

2024-07-02 17:32:50 354

原创 Spring Boot 集成 MinIO 实现文件上传

MinIO的搭建过程参考。登录MinIO控制台,新建一个 Bucket,修改 Bucket 权限为公开。

2024-06-21 14:43:39 1208 1

原创 Docker 搭建 MinIO 对象存储

MinIO 是一个高性能的对象存储服务器,用于构建云存储解决方案。MinIO 允许你存储非结构化数据(如图片、视频、日志文件等)以对象的形式。MinIO 提供简单的部署选项和易于使用的界面,允许你快速设置和访问存储资源。本篇博客介绍一下使用 Docker 容器进行MinIO的安装与使用。部署方式采用单机单硬盘模式。服务器上没有 Docker 环境的可以参考。

2024-06-21 14:22:17 650

原创 【Java】时间工具类 —— 格式化,个性化,时间操作

在平常的编程中,经常会遇到时间的各种类型转化,避免每次都使用第三方库或者上网搜索,决定整理一下写篇博客,也是从各处收集或者让AI写的方法,应该可以涵盖平时所有的场景了

2024-05-17 14:46:22 1212

原创 【Linux】Docker搭建Mysql主从架构

Linux环境下(centos7.8)使用Docker搭建MySQL主从架构。

2023-12-18 16:47:15 708

原创 【踩坑记录】SpringBoot 3 统一处理 dubbo 3 接口异常和错误

经过搜索之后发现,dubbo提供了异常处理的类ExceptionFilter(org.apache.dubbo.rpc.filter.ExceptionFilter),大概功能就是对指定的一些异常放行,然后其他异常统一包装成RuntimeException返回。最近在学习Dubbo的时候,按照之前的习惯定义了自定义异常和统一异常处理,但是在进行接口测试的时候,发现并不是自定义的异常处理,而是被当做系统异常进行了处理。在经过debug和源码的阅读之后发现,虽然异常进入了自己写的过滤器,但是最后还是会回到。

2023-12-04 14:04:34 2259 1

原创 idea中mybatis的mapper.xml没有高亮显示

今天写代码的时候,生成完xml发现写SQL的时候没有高亮提示。修改了一下头部的url,去掉https的s就好了。

2023-11-21 10:54:43 1503 2

原创 【踩坑日记】关于时间戳的异常

在最近的一次作业中,保存时间的时候,由于懒得改前端组件时间,默认用了1970-01-01(只有年月日)上传数据,但是遇到了问题`Data truncation: Incorrect datetime value: '1970-01-01 08:00:00' for column 'create_time' at row 1`。但是改一下时间就可以正常提交,引发思考。时间戳不能存 0。

2023-11-16 23:01:53 983

原创 【LeetCode刷题记录】 热题 100 —— 滑动窗口

3. 无重复字符的最长子串,438. 找到字符串中所有字母异位词如果它在子串中已经存在,那么就判断当前无重复子串的长度和维护的最长长度,并且删掉子串中这个字符以及它之前的字符,并且拼接上新的字符。优化之后确实快了很多,但是500ms还是有点慢的,毕竟只击败了不到20%,所以继续想办法优化。现在的解法中,每次都要重新构造一个子串的数组,有没有办法和上一题那样,通过滑动窗口来维护,每次删去不在窗口里的元素并且添加新进入窗口的元素,所以得到下面的解法。回想之前也做过一个异位词的算法题,可以通过数组来判断异位词,

2023-11-11 17:02:53 197

原创 若依分离版 docker 一键部署踩坑记录

前置工作按照流程操作,在最后docker compose运行的时候发现 ruoyi-server (也就是后端项目的服务) 会启动失败。查看容器启动情况的话会发现除了后端服务异常,其他容器都在正常运行。这时候有两种情况下面针对这两种情况分别进行分析。

2023-11-10 18:18:37 1170 1

原创 【LeetCode刷题记录】 热题 100 —— 双指针

力扣:283. 移动零,11. 盛最多水的容器,15. 三数之和,42. 接雨水,双指针

2023-11-06 15:30:07 476

原创 Java集合框架 ——— LinkedList 源码分析

LinkedList是一个基于双向链表实现的集合类,经常被拿来和ArrayList做比较。LinkedList 继承自,它决定了 LinkedList 只能支持按次序访问。此外 LinkedList 还实现了Deque接口,它具有双端队列的特性,支持从两端插入和删除元素,方便实现栈和队列等数据结构。因此 LinkedList 实现了很多队列的方法,在开发中也可以当做一个堆栈来使用。

2023-10-31 08:26:15 416 1

原创 Java集合框架 ——— LinkedList 基础使用

采用链表存储,所以在头尾插入或者删除元素不受元素位置的影响,时间复杂度为 O(1);如果是要在指定位置 i 插入和删除元素的话, 时间复杂度为 O(n) ,因为需要先移动到指定位置再插入和删除。我们在项目中一般是不会使用到 LinkedList 的,需要用到 LinkedList 的场景几乎都可以使用 ArrayList 来代替,并且,性能通常会更好。

2023-10-30 14:25:02 472 1

原创 Java集合框架 ——— HashMap 源码分析(二)

这两篇博客对 HashMap 的常用方法源码做了一些分析,扩容和插入方法的内容比较多,特别是插入操作,理解了插入之后,查找和删除的代码阅读起来也相对容易很多。

2023-10-26 08:05:54 227

原创 【LeetCode刷题记录】 热题 100 —— 哈希

两数之和,字母异位词分组,最长连续序列这道题的暴力解法相信看到这题的所有人都能想到,使用双重 for 循环进行枚举,算出所有的结果。提交发现耗时还是有些长,并且当前的在热题100的分类中,这道题被分在了哈希,那么很明显这一题可以使用哈希表解决。在这一题中,对于每一个元素 n ,都存在一个另一个数,使他们求和可以得到目标值,那个数就是差 diff。而这个差也需要在数组里找,所以将数组里全部的数存到 HashMap 中。

2023-10-23 13:50:11 248

原创 微服务网关整合 Knife4j

微服务架构下,每个服务都有自己的接口文档,但是需要访问不同的地址。如果想通过网关作为统一入口将所有文档聚合在一起,就需要使用 knife4j 提供的网关进行聚合组件。系统版本项目准备。

2023-10-19 14:00:43 911

原创 微服务实战项目 —— 知识分享应用(三)

我的兑换列表需要查询到 MidUserShare 中间表的数据后再查询 share 的具体信息,ShareService 创建方法。积分明细列表只需要简单的分页查询积分日志表,UserService 实现 userBonusLog 方法。注意:修改博客中两处主机地址,并且打开四个端口:9999,10909,10911,9876。用户中心不需要主动调用,写一个监听器,只要消息队列有了某个用户的积分,就会通知他去消费加分。重启服务,可以看到用户中心已经监听到,并且已经增加了积分,日志表也插入了日志。

2023-10-15 12:50:31 236 1

原创 微服务实战项目 —— 知识分享应用(二)

修改 http 登录接口测试代码,在 /login 登录接口响应成功后,将 token 存入 client.global 全局,然后就可以在 /client 接口请求中使用 {{ token }} 的形式使用它。JavaBean 方式比 yml 配置方式在多模块的微服务架构下实现更加便捷,只需要在公共模块写一个配置类就可以在全部模块(引入了公共模块的全部模块)实现时间的格式化。仿照 user 模块实现启动类。(此处需要用到用户中心的实体类 User,就先复制一份过来,结合前面的学习,思考最终的解决方案)

2023-10-13 10:11:08 429

原创 微服务实战项目 —— 知识分享应用(一)

share-common 模块新建 enums 子包,新建异常枚举类 BusinessExceptionEnum.java@GetterPHONE_NOT_EXIST("手机号不存在"),PASSWORD_ERROR("密码错误");share-common 模块新建 exception 子包,编写自定义异常类 BusinessException.java@Setter在全局统一异常处理类 ControllerExceptionHandler 中添加对自定义异常的处理/**

2023-10-08 15:34:21 307 1

原创 Java集合框架 ——— HashMap 源码分析(一)

在 JDK 1.8 之前,HashMap 底层数据结构为数组 + 链表实现。HashMap 使用这种数据结构来解决哈希冲突,在每个数组元素后面跟上一个链表,在添加元素的时候会根据 Key 的 HashCode 确定存放位置。一般来说,不同的键的 HashCode 是不同的,但是如果出现了相同的情况,我们称之为哈希碰撞,此时就会把新的键值接在原来的键值的链表后面。在 JDK 1.8 之后,Java 在原来的底层实现基础上,如果链表的长度过长(超过一定的阈值,并且满足一定条件后)会将链表转换为红黑树。

2023-10-07 16:31:53 234 1

原创 Java集合框架 ——— HashMap 基础使用

HashMap 是一种常用的数据结构,是一个非线程安全的集合,主要用来存放键值对。在 JDK1.8 之前 HashMap 由数组+链表 实现,链表主要用于解决哈希冲突;在 JDK1.8 之后,JDK 选择了新的哈希冲突解决方式,当链表长度大于一定阈值,HashMap 会将链表转化为红黑树,以此提高 HashMap 的效率。

2023-10-01 17:29:55 200

原创 容器化技术 —— 自定义镜像并发布到公服

为了从根本上解决开发和运维环境不一致的问题。也就是说,在安装时,把原始环境一模一样地复制过来,开发人员利用 Docker 可以消除协作编码时“在我的机器上可正常工作”的问题。开发在打包应用时,将应用所需要的文件打包成一个镜像文件,将镜像运行在docker中。从而达到一次镜像,处处运行。这也是 Docker 官方的口号:Build once,Run anywhere.

2023-09-28 22:09:26 229

原创 云原生浪潮下的容器化技术 —— Docker

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的操作系统机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。Docker官方的口号 : " Build once,Run anywhere,Configure once,Run anything " 。

2023-09-27 14:21:15 449

原创 Java集合框架 ——— ArrayList 源码分析

本文以 JDK1.8为例,分析ArrayList的源码。扩容机制,overflow-conscious code,int 溢出

2023-09-26 18:25:00 207

原创 Java 集合框架 ——— ArrayList 基础使用

数组的长度是固定的,无法适应数据变化的需求,因此Java提供了 ArrayList 集合类来解决这个问题。ArrayList 是大小可变的数组的实现,比数组使用起来更加灵活,它的容量能动态增长。ArrayList 对象不能存储基本类型,只能存储引用类型的数据。因此不能使用 int,double 等基本数据类型。

2023-09-25 19:46:12 235 1

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除