自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 Tomcat NIO 工作原理详解:从 Acceptor、Poller 到容器处理链

平时写 Spring Boot 接口时,我们通常只关心 Controller 能不能收到请求,很少去想 Tomcat 在这之前做了什么。没有把请求是如何流转的讲清楚。要理解 Tomcat NIO,抓住 Acceptor、Poller 和 Worker 三类线程就够了。

2026-09-04 23:09:41 304

原创 Tomcat 核心机制详解:Session、类加载器与高并发 Connector 调优

平时使用 Spring Boot 开发接口时,我们很少直接操作 Tomcat。项目启动后,接口能访问、Session 能保存、请求能被线程处理,看起来一切都是自动完成的。这篇文章聊一聊背后的Session、Web 应用类加载器以及 Connector 的工作方式。

2026-09-03 19:21:36 307

原创 Java 常用设计模式(二):装饰器、适配器、责任链、模板方法、策略与观察者

上一篇整理设计模式时,我越来越觉得,设计模式最难的部分不是代码,而是判断“这里到底需不需要用”。很多模式的结构看起来都像增加了一层接口和实现类,如果只背定义,到了项目里还是容易混淆。

2026-09-02 20:53:00 540

原创 Java 常用设计模式入门:建造者、工厂、单例、外观与代理

刚开始学习设计模式时,我经常有一种感觉:明明几行代码就能完成的功能,套上设计模式后反而多出了接口、实现类和工厂类。后来做项目才慢慢明白,设计模式不是为了把代码写得“高级”,而是为了解决代码变化后越来越难维护的问题。对象参数多了怎么办?支付方式不断增加怎么办?调用一个功能要协调五个系统怎么办?这些才是设计模式真正要处理的事情。本文挑选五种 Java 项目中经常见到的模式,用简单场景讲清楚它们分别解决什么问题。

2026-09-01 14:41:57 647

原创 MyBatis 三个容易混淆的核心问题:一级缓存、懒加载与参数占位符

刚开始用 MyBatis 时,我遇到过两个看起来相反的现象。有时候,同一个查询方法调用两次,日志里却只出现一条 SQL;有时候,主查询明明已经结束了,代码访问一个关联属性时,控制台又突然打印出一条查询。前一个现象与一级缓存有关,后一个现象则通常来自懒加载。至于 Mapper XML 中经常出现的 #{} 和 ${},表面上只是符号不同,背后却分别代表参数绑定和字符串替换,安全性也完全不同。

2026-08-31 20:21:48 513

原创 MyBatis 执行与扩展机制详解:插件、Executor、PageHelper 与批量插入

刚开始使用 MyBatis 时,我对插件的理解很简单:它可以在 SQL 执行前后“插一段逻辑”。后来接触 PageHelper、SQL 监控和批量写入,才发现这句话虽然没错,却解释不了几个实际问题:插件究竟拦截了谁?PageHelper 为什么调用一行 startPage() 就能修改下一条 SQL?BatchExecutor 和 <foreach> 批量插入又是不是同一回事?

2026-08-30 23:01:41 620

原创 LeetCode 141 环形链表:快慢指针为什么一定能相遇?

第一次接触环形链表时,快慢指针的代码并不难记:一个每次走一步,一个每次走两步,相遇就说明链表有环。真正让我不放心的是另一个问题:它们凭什么一定能相遇?快指针会不会刚好越过慢指针,每次都与它错开?把两个指针放到环里看,这个疑问其实很好解释。快指针每轮比慢指针多走一步,所以二者在环上的距离每轮都会缩短一个节点。只要链表有环,快指针就无法离开这个有限的范围,迟早会追上慢指针。本文就沿着这个思路,讲清楚 LeetCode 141“环形链表”的快慢指针解法。

2026-08-30 16:04:27 639

原创 MyBatis 核心原理详解:JPA、二级缓存、结果映射与 Mapper 代理

刚接触 MyBatis 时,我一直觉得 Mapper 接口有点“神奇”:接口明明没有实现类,注入后却能直接调用;XML 里写一段 SQL,返回值又能自动变成 Java 对象。后面再回头看,会发现 MyBatis 并没有凭空做什么。它的核心逻辑很清楚:启动时解析 SQL 和映射规则,运行时为 Mapper 接口创建代理对象,再由代理对象找到对应 SQL 并交给执行器处理。

2026-08-29 22:45:10 412

原创 LeetCode 238 除自身以外数组的乘积:前缀积与后缀积详解

本文围绕 LeetCode 238“除自身以外数组的乘积”展开,介绍不使用除法的前缀积与后缀积解法。通过分别保存当前位置左侧和右侧所有元素的乘积,再将两者相乘得到最终结果。文章结合示例演算与 Java 代码,该算法时间复杂度为 O(n),额外空间复杂度为 O(n)。

2026-08-29 14:53:58 482

原创 LeetCode 189 轮转数组:三次反转为什么能实现右旋?

第一次看到“三次反转就能完成数组轮转”时,我的第一反应其实是:这更像一个需要背下来的技巧。先反转整个数组,再反转前 k 个元素,最后反转剩余元素——步骤确实不多,但如果只记住这三行代码,过几天很容易把反转顺序或者区间边界写错。后来把数组拆成两部分重新看了一遍,才发现这并不是什么魔法。所谓向右轮转,本质上就是把数组末尾的一段搬到开头,同时保持前后两段内部的顺序不变。三次反转正好完成了这件事。本文就从这个角度,讲清楚 LeetCode 189“轮转数组”的原地反转解法。

2026-08-28 18:39:51 365 1

原创 LeetCode 438 找到字符串中所有字母异位词:滑动窗口与排序解法详解

本文围绕 LeetCode 438“找到字符串中所有字母异位词”展开,介绍固定长度滑动窗口与排序比较的解法。通过预先排序字符串 `p`,依次截取 `s` 中与其等长的子串并排序,再使用 `Arrays.equals()` 判断字符组成是否相同。文章结合示例演算和 Java 代码,讲解窗口移动、字符串截取、复杂度及常见边界错误。

2026-08-27 19:44:57 634

原创 微服务平滑发布与分布式链路追踪:SkyWalking、Zipkin、Sleuth、TraceId 与 SpanId

在微服务系统中,一个用户请求可能依次经过网关、订单、库存、支付、数据库和消息队列。当某个服务发版重启时,如果直接杀死旧进程,正在执行的请求就可能被中断;如果发生超时,又很难仅凭单个服务的日志判断问题出现在哪一段。因此,生产环境通常需要同时解决两个问题:通过平滑发布保护在途请求,通过分布式链路追踪还原请求在多个服务之间的完整路径。

2026-08-26 19:53:36 526

原创 LeetCode 121 买卖股票的最佳时机:一次遍历掌握贪心算法

本文围绕 LeetCode 121“买卖股票的最佳时机”展开,从暴力枚举入手,逐步推导一次遍历的贪心解法。通过维护历史最低买入价,并将当前价格作为卖出价计算利润,即可不断更新最大收益。文章结合示例演算、Java 代码和边界情况,重点说明买入日期必须早于卖出日期,并分析该题与最大子数组和之间的联系。

2026-08-25 18:08:16 627

原创 Spring Boot 启动流程与 @SpringBootApplication 核心原理详解

一个最简单的 Spring Boot 应用通常只有一个启动类和一行 SpringApplication.run()。但这行代码背后完成了环境准备、配置加载、容器创建、Bean 初始化、自动装配、Web 服务器启动以及事件发布等一系列工作。本文以 Spring Boot 3.x 为背景,从应用入口出发,梳理 Spring Boot 的启动流程,并解析 @SpringBootApplication 的三个核心组成部分。

2026-08-25 13:58:44 514

原创 LeetCode 3 无重复字符的最长子串:滑动窗口与双指针详解

文章主要讲了用滑动窗口与双指针解决无重复最长子串的问题,hashset用来存储不重复的字符

2026-08-25 10:52:25 284

原创 Spring Boot 核心机制详解:自动装配、事件监听、异步任务与请求映射

本文围绕 Spring Boot 核心开发机制展开,深入解析自动装配的执行流程与条件注解,介绍事件发布、监听及异步处理方式,并结合线程池说明 `@Async` 的实现原理和常见失效场景。同时对比 `@RequestMapping`、`@GetMapping` 与 `@PostMapping` 的作用及使用方式。

2026-08-24 20:03:53 427

原创 LeetCode 53 最大子数组和:一次遍历掌握 Kadane 算法

本文围绕 LeetCode 53“最大子数组和”展开,详细介绍 Kadane 算法的核心思想。通过定义以当前位置结尾的最大子数组和,判断是延续原有子数组还是从当前元素重新开始,并在遍历过程中维护全局最大值。文章结合示例演算、Java 代码和状态转移公式,分析全负数数组等边界情况,总结常见错误。该算法时间复杂度为 O(n),空间复杂度为 O(1)。

2026-08-23 17:03:56 648 1

原创 Spring Boot 工程化核心详解:Parent、Starter、热部署、事务与多数据源

本文围绕 Spring Boot 工程化开发中的核心机制展开,介绍 `spring-boot-starter-parent` 的依赖与插件管理作用、Starter 的依赖聚合和自动配置原理,以及 DevTools 基于双 ClassLoader 的快速重启机制。同时讲解 `@Transactional` 的实现原理、传播行为与常见失效场景,并结合代码说明多数据源、`JdbcTemplate` 和事务管理器的配置方式及跨库事务注意事项。

2026-08-23 11:18:54 523

原创 LeetCode 1143:最长公共子序列——Java 二维动态规划详解

本文介绍 LeetCode 1143“最长公共子序列”的二维动态规划解法。通过定义 `dp[i][j]` 表示两个字符串相应前缀的最长公共子序列长度,分别推导当前字符相同与不同时的状态转移。文章结合 `"abcde"` 和 `"ace"` 完整填写 DP 表,并讲解数组初始化、下标映射、遍历顺序、Java 代码、复杂度及常见错误。

2026-08-22 22:43:21 354

原创 Spring Boot 配置体系与扩展机制详解:属性注入、加载优先级、SPI 与内嵌容器

本文介绍了SpringBoot 3.x中的关键配置与容器技术。主要内容包括:1. @Value与@ConfigurationProperties的区别与适用场景,后者更适合管理结构化配置;2. 配置注入的多种方式,从简单属性到复杂嵌套配置的绑定方法;3. SpringBoot配置加载优先级机制,包括命令行参数、环境变量和配置文件的覆盖规则;4. SpringBoot的SPI扩展机制原理,特别是自动配置的实现方式;5. 三种主流内嵌Servlet容器(Tomcat、Jetty、Undertow)的特点和选型建

2026-08-22 15:03:12 452

原创 LeetCode 5:最长回文子串——Java 中心扩展法详解

本文介绍 LeetCode 5“最长回文子串”的中心扩展解法。通过枚举字符串中的每个位置,分别处理以单个字符为中心的奇数回文,以及以两个相邻字符为中心的偶数回文,并使用左右指针不断向两侧扩展。文章结合示例讲解最长回文起点与长度的记录方法,给出完整 Java 代码、复杂度分析及常见边界问题。

2026-08-22 11:48:45 310

原创 LeetCode 64:最小路径和——Java 原地动态规划详解

本文介绍 LeetCode 64“最小路径和”的动态规划解法。通过定义 `dp[i][j]` 表示从左上角到当前位置的最小路径和,推导出当前位置等于上方与左方状态中的较小值加上当前数字。文章结合示例讲解第一行、第一列的初始化和完整计算过程,并采用原地修改 `grid` 的方式,将额外空间复杂度降至 `O(1)`,同时分析遍历顺序、代码实现及常见错误。

2026-08-21 22:12:24 530

原创 Spring Boot 核心机制详解:可执行 JAR、CORS、静态资源与配置绑定

摘要:本文解析SpringBoot四个核心机制:1)可执行JAR通过JarLauncher启动嵌套依赖和应用主类;2)CORS支持通过@CrossOrigin局部配置或WebMvcConfigurer全局配置响应头;3)静态资源默认映射/resources/static等目录,支持路径自定义;4)配置注入推荐@ConfigurationProperties实现类型安全绑定,优于分散的@Value。全文结合目录结构、代码示例和配置对比,阐明SpringBoot"约定优于配置"背后的实现逻辑

2026-08-21 19:35:09 437

原创 LeetCode 62:不同路径——Java 二维动态规划详解

本文介绍了使用动态规划解决机器人网格路径问题的完整思路。关键点包括:1)定义dp[i][j]表示到达(i,j)的路径数;2)初始化首行首列为1;3)状态转移方程dp[i][j]=dp[i-1][j]+dp[i][j-1];4)按行从左到右填充表格。该解法时间复杂度O(mn),空间复杂度O(mn)。通过将问题分解为子问题并存储中间结果,避免了重复计算,体现了动态规划的核心思想。

2026-08-20 22:10:26 549 1

原创 Spring Boot 可执行 JAR 原理与应用启动速度优化

本文解析了SpringBoot可执行JAR与普通JAR的区别,并提供了启动优化的系统方法。SpringBoot JAR通过特殊结构(BOOT-INF目录和内置Loader)实现依赖打包和独立运行,而普通JAR仅是类库。针对启动慢问题,建议先分析耗时环节,再依次处理无用依赖、扫描范围、外部连接等关键因素,最后考虑懒加载等高级方案。强调优化需保持功能完整,通过基准测试验证效果,避免盲目调整配置。文末总结了面试常见问题,为开发者提供了实用指南。

2026-08-20 19:35:57 597 3

原创 Spring MVC 核心知识详解:请求数据获取、Model 体系、核心组件与异步处理

本文系统梳理了SpringMVC开发中的核心问题,涵盖请求头/Cookie读取、数据传递方式、请求处理流程、异步处理机制以及控制器的选择。详细讲解了@RequestHeader和@CookieValue的用法,比较了Model/ModelMap/ModelAndView的差异,分析了DispatcherServlet等五大核心组件的工作流程,并介绍了异步请求处理的Callable和DeferredResult实现方式。最后区分了@Controller和@RestController的使用场景,帮助开发者全面

2026-08-19 18:29:16 361

原创 LeetCode 322:零钱兑换——Java 动态规划详解

本文探讨了使用动态规划解决零钱兑换问题的方法。给定不同面额的硬币和目标金额,通过定义dp[i]为凑出金额i所需的最少硬币数,初始化dp[0]=0,其余为较大值。状态转移时枚举硬币面额coin,当coin≤i时,dp[i]=min(dp[i], dp[i-coin]+1)。最终若dp[amount]未被更新则返回-1。文章详细解释了算法思路,包括状态定义、初始化和转移过程,并分析了时间空间复杂度(O(amount×n)和O(amount)),指出了常见错误和贪心算法的局限性。该方法通过分解子问题有效解决了最少

2026-08-18 20:23:54 604

原创 Spring MVC 核心机制详解:全局异常处理、请求跳转与数据绑定

本文围绕 Spring MVC 开发中的三个核心问题展开:介绍如何通过 `@ExceptionHandler` 和 `@RestControllerAdvice` 实现全局异常处理与统一响应;结合代码说明 Controller 请求转发与重定向的实现方式,并比较二者在请求次数、地址栏和数据共享方面的区别;最后解析 Spring MVC 数据绑定流程,讲解参数解析、类型转换、对象填充及校验等关键环节,帮助读者系统掌握相关开发方法与底层机制。

2026-08-18 11:43:16 406

原创 LeetCode 198:打家劫舍——Java 动态规划详解

这是一道经典的动态规划问题,用于求解在不触发警报的情况下,偷窃房屋能获得的最大金额。解题思路是定义dp[i]表示前i间房屋的最高金额,通过状态转移公式dp[i] = max(dp[i-1], dp[i-2]+nums[i-1])进行计算。初始状态为dp[0]=0和dp[1]=nums[0],最终返回dp[n]。该方法时间复杂度O(n),空间复杂度O(n)。示例展示了如何通过动态规划逐步求解,如输入[1,2,3,1]得到最大金额4。

2026-08-17 23:00:26 664 1

原创 evans在进步|实习日记,Mentor看完我的 AI 开发流程,建议我先学会写 Skill

实习生分享SpringBoot3集成Swagger的踩坑经验:最初直接让AI生成代码导致版本不兼容(误用Springfox),后改用Springdoc方案并整理出标准流程:1)判断SpringBoot版本;2)添加正确依赖;3)使用OpenAPI3注解;4)验证访问路径。关键收获是将成功经验转化为可复用的"Skill",避免重复解释开发步骤,使AI能按已验证流程高效完成任务,同时补充了依赖冲突检查等验证环节。

2026-08-17 21:24:23 454

原创 LeetCode 347:前 K 个高频元素——Java HashMap 与小顶堆详解

摘要:本文详细讲解了如何解决「返回数组中频率最高的k个元素」问题。首先使用HashMap统计元素频率,然后通过维护大小为k的小顶堆高效筛选出前k个高频元素。小顶堆的设计能确保堆顶始终保存当前候选中的最低频率元素,便于适时淘汰。文章包含完整Java代码、复杂度分析(时间O(nlogk),空间O(n))、常见错误示例以及推演过程。关键点在于理解使用小顶堆而非大顶堆来维护TopK元素的策略,这种方法既节省空间又提高效率。

2026-08-16 10:49:13 461

原创 一文讲透 Spring AOP、Bean 作用域与事务:从代理机制到事务失效

《Spring核心机制解析:AOP、Bean作用域与事务的协同关系》 摘要:本文系统解析Spring框架中AOP、Bean作用域与事务机制的协同工作原理。Spring AOP通过动态代理实现横切逻辑,核心要素包括连接点、切点、通知和切面,其代理机制直接影响事务注解的生效方式。Bean作用域中,prototype适用于有状态场景但非线程安全万能方案,单例模式下需注意状态管理。声明式事务作为AOP典型应用,其自调用失效问题源于代理机制限制,可通过职责拆分、代理调用或AspectJ模式解决。三者本质都依赖Spri

2026-08-15 22:22:57 778

原创 LeetCode 394:字符串解码——Java 单栈模拟与嵌套解析详解

摘要:本文介绍了一种使用栈结构解码嵌套编码字符串的算法。编码格式为k[encoded_string],表示括号内字符串重复k次。算法通过栈处理嵌套结构,遵循"后进先出"原则:遇到非右括号字符直接入栈;遇到右括号时,依次弹出字符构建子串,获取重复次数,解码后重新入栈。该方法能正确处理嵌套表达式(如"3[a2[c]]"→"accaccacc")和并列结构(如"3[a]2[bc]"→"aaabcbc")。文中详细说

2026-08-15 13:55:03 265

原创 一文讲透 Spring IoC 与 Bean:依赖注入、容器区别及单例线程安全

Spring框架的核心是IoC容器,它通过控制反转(IoC)和依赖注入(DI)机制管理对象的创建和依赖关系。IoC将对象的控制权从业务代码转移给容器,DI则通过构造器注入(推荐方式)、Setter注入、字段注入等方式实现依赖关系。Spring提供BeanFactory和ApplicationContext两种容器,后者功能更丰富。需要注意的是,Spring单例Bean默认不保证线程安全,无状态Bean通常是安全的,而有状态Bean需要采取额外措施(如使用线程安全工具、调整作用域等)确保线程安全。开发中应优先

2026-08-14 21:10:59 498

原创 LeetCode 33:搜索旋转排序数组——Java 两阶段二分查找详解

该文章摘要介绍了如何在旋转后的有序数组中高效查找目标值。算法分为三步:首先通过二分查找定位旋转点(最小值下标),将数组划分为两个升序区间;然后比较目标值与数组末元素,确定目标所在区间;最后在选定区间执行标准二分查找。这种方法的时间复杂度为O(logn),空间复杂度O(1)。文章详解了算法实现、边界条件处理,并通过示例演示了执行过程,同时指出了常见错误和优化要点,适用于元素互不相同的旋转有序数组场景。

2026-08-14 19:33:33 507

原创 一文讲透 Spring 事务:传播行为、隔离级别与底层原理

本文系统介绍了Spring事务的核心机制与应用要点。主要内容包括:1)事务类型(本地/全局)与管理方式(编程式/声明式);2)7种传播行为的区别,重点对比REQUIRES_NEW与NESTED;3)@Transactional的AOP代理实现原理及ThreadLocal同步机制;4)隔离级别选择与异常回滚规则;5)代理方式选择(JDK/CGLIB)及注意事项;6)AOP通知执行顺序的最新规范。文章强调理解传播行为、回滚规则和代理边界对避免事务失效的重要性,指出Spring事务本质是通过统一抽象层简化数据库事

2026-08-13 22:42:06 10439 10

原创 LeetCode 34:在排序数组中查找元素的首尾位置——Java 两次二分查找详解

文章摘要:题目要求在有序数组中使用O(logn)时间复杂度查找目标值的起始和结束位置。通过两次二分查找分别定位左右边界:查找左边界时命中后继续左移,右边界则继续右移,并用tempIndex记录候选位置。标准二分查找需修改为不立即返回,而是持续搜索直至确定边界。最终组合两次结果,若未找到则返回[-1,-1]。关键点在于区分搜索方向并正确处理命中后的区间更新,避免常见错误如方向混淆或线性扫描。

2026-08-13 19:13:03 310

原创 LeetCode 74:搜索二维矩阵——Java 虚拟一维数组与二分查找详解

该题要求在一个具有特定有序特性的二维矩阵中查找目标值。由于矩阵每行从左到右非严格递增,且每行首元素大于前一行末元素,因此可将整个矩阵视为一个虚拟的一维有序数组。通过二分查找在逻辑上展开的数组,利用下标映射(行=mid/列数,列=mid%列数)直接访问矩阵元素,无需额外空间。算法时间复杂度为O(log(mn)),空间复杂度O(1)。关键点在于理解二维到一维的坐标转换,并正确处理二分边界更新。

2026-08-12 23:10:43 462

原创 LeetCode 39:组合总和——Java DFS 回溯与剪枝详解

本文详细讲解了如何解决组合总和问题,即在给定无重复元素的正整数数组和目标值的情况下,找出所有数字之和等于目标的组合。文章通过决策树模型分析问题,强调使用DFS回溯算法和start参数来避免重复组合。核心思路是每层递归从指定位置开始选择数字,允许重复使用当前数字,并通过剪枝优化效率。文中提供了完整的Java代码实现,并通过示例演示执行过程,最后总结了常见错误和解题要点。该算法的时间复杂度与目标值相关,空间复杂度由递归深度决定。

2026-08-12 20:38:13 365 2

原创 一文讲透 MySQL 锁、事务日志与索引优化:从 ACID 到两阶段提交

本文系统梳理了MySQL面试中的核心知识点,围绕InnoDB存储引擎展开。首先解析ACID特性实现机制:原子性依赖undolog回滚,隔离性通过锁和MVCC实现,持久性由redolog保证。详细介绍了InnoDB的锁机制(共享/排他锁、意向锁、临键锁)及其应用场景。深入讲解了三种关键日志:undolog支持事务回滚和MVCC,redolog确保崩溃恢复,binlog用于主从复制和数据恢复,并通过两阶段提交保证日志一致性。此外,还总结了索引失效的常见情况、UNION与UNIONALL的区别、去重方法比较,并澄

2026-08-11 22:25:12 664

空空如也

空空如也

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

TA关注的人

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