简介《Java学习路线》PDF 面向Java初学者及希望系统补强的开发者用一条较完整的知识主线回答“先学什么、后学什么、如何查漏补缺”的问题。内容从基础语法、面向对象、容器、异常、泛型与反射讲起延伸至JVM类加载、内存模型、GC与调优并发编程、数据结构与算法、计算机网络、数据库与SQL并覆盖Web开发、Spring全家桶、微服务、前端基础、研发工具、Linux、设计模式、任务调度、链路追踪、ELK日志分析及Docker/Kubernetes容器化等后端常见技术栈。压缩包共1个PDF文件约92KB轻量便于随时查阅已有492人学习。其价值在于以模块化路线图呈现技能层级和学习顺序帮助读者建立全局认知、制定阶段目标并对照目录发现薄弱环节配合实际项目逐步深入。1. 一份 Java 后端路线图 PDF它更像施工图不是书单收藏夹里躺着几份 Java 学习路线 pdf 的人不少真正照着走完的没几个。这份资源的可用之处不在于列了多少名词而在于它按「能落地」的顺序把后端拆成编程基础、JVM、并发编程、数据结构与算法、计算机网络、数据库与 SQL、Web 开发、后端框架、微服务、前端、研发工具十一块每块下面直接点名到具体组件——缓存写的是 Redis 的五大类型、事务、持久化、集群微服务写的是 Eureka/Consul/Nacos 这一组注册中心分布式事务连 2PC、TCC、SAGA、LCN 几条实现路线都摆出来了。它回答的是「先学谁、学到什么程度算过关」这两个最容易卡住新人的问题而不是再给你一份更长的书单。适合入行一两年想补体系的后端、从别的方向转过来的自学者也适合带新人的组长拿它当排期底稿。指望存下来就会写代码的趁早别下。2. 把脑图拆成可执行清单从 Java 基础到 JVM 的四层递进拿到这类 PDF最常见的用法是扔进阅读器从头翻到尾翻完感觉学到了合上什么也没剩下。脑图类资源天生不适合线性阅读它的正确打开方式是拆——把每个节点拆成一个可以验收的小任务再按依赖关系重新排序。路线图里编程基础那一块列了语言基础、JVM、并发、数据结构与算法、计算机网络、数据库、操作系统、设计模式八个方向看着是并列的实际有严格的前后依赖没有容器和泛型的基础并发容器那节只能背结论没有线程和锁的直觉JVM 的 GC 日志看半天也看不出所以然。下面按我实际带人走的顺序拆一遍。2.1 语言基础与容器先保证写出来的代码不返工路线图把语言基础拆成基础语法、面向对象、接口、容器、异常、泛型、反射、注解八项很多人卡在反射和注解觉得这两块「工作中用不到」。恰恰相反Spring 的整个骨架就建在这两块上Component是注解Bean 的实例化和依赖注入靠反射。跳过它们直接学 Spring最后只能记住「加个注解就行」出问题连从哪儿查都不知道。我的建议是先花半天把注解和反射串成一个最小可运行的东西让「元数据 运行时读取」这件事变得具体。下面这段代码不依赖任何框架三十行就能跑出 Spring MVC 里 HandlerMapping 的雏形import java.lang.annotation.*; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; Retention(RetentionPolicy.RUNTIME) // 关键保留到运行期反射才读得到 Target(ElementType.METHOD) // 限定只能标在方法上 interface Route { String value(); } class Controller { Route(/user/list) public String list() { return user-list; } Route(/order/list) public String orders() { return order-list; } } public class MiniScanner { public static void main(String[] args) throws Exception { MapString, Method table new HashMap(); Class? clazz Controller.class; for (Method m : clazz.getDeclaredMethods()) { Route r m.getAnnotation(Route.class); if (r ! null) { table.put(r.value(), m); // 路径 - 方法等价于请求映射表 } } Object bean clazz.getDeclaredConstructor().newInstance(); // 反射调用等价于框架收到请求后分发到具体方法 System.out.println(table.get(/user/list).invoke(bean)); } }这段代码有三个参数值得抠。RetentionPolicy.RUNTIME决定注解能不能被getAnnotation读到写成CLASS就什么都拿不到Target(ElementType.METHOD)限定注解位置写错位置编译期就报错比运行期排查省事getDeclaredMethods只拿本类声明的方法父类继承来的要用getMethods这个差别在写通用工具时经常翻车。跑通之后再看 Spring 的RequestMappingHandlerMapping会发现它做的就是同一件事只是加了拦截器、参数解析和返回值处理。容器这一节的重点不是背 API而是搞清楚三件事ArrayList扩容时的数组拷贝代价、HashMap的容量与扩容因子对哈希冲突的影响、ConcurrentHashMap为什么不允许 null 键。这三个问题在面试里出现频率极高在工作中也真的会咬人——把一个几千元素的ArrayList频繁往中间插接口 P99 直接翻倍这种事故我见过不止一次。异常和泛型容易被当成语法糖跳过。异常的关键是分清「能恢复的」和「不能恢复的」不要在最外层catch (Exception e)一把梭那等于给自己埋了个黑匣子。泛型要理解类型擦除知道为什么ListString和ListInteger在运行期是同一个类这直接决定了你后面写通用返回体时会不会踩到桥接方法的坑。2.2 并发与 JVM路线图里最容易被跳过的两块硬骨头路线图把并发排在 JVM 前面这个顺序是对的。JVM 的内存模型、GC 日志、线程栈只有在你写过一段真实的并发代码之后才有观察价值。先啃 JVM 的人多半会陷入「记住了一堆名词但不知道用在哪」的状态。并发这块按「基础 → 线程池 → 并发容器 → 原子类 → JUC 工具类」推。基础的synchronized和volatile要能用javap -c看出字节码层面的monitorenter和内存屏障线程池要能说清七个参数在什么情况下生效JUC 那组工具类不用全背但CountDownLatch、Semaphore、CyclicBarrier三者的区别要能一句话讲明白。下面这段代码用来观察线程池的真实行为import java.util.concurrent.*; public class PoolProbe { public static void main(String[] args) throws Exception { ThreadPoolExecutor pool new ThreadPoolExecutor( 4, // corePoolSize 8, // maximumPoolSize 30, TimeUnit.SECONDS, // 非核心线程空闲存活时间 new ArrayBlockingQueue(16), // 有界队列避免无界堆积掩盖问题 new ThreadPoolExecutor.CallerRunsPolicy()); // 满了回退到调用线程 CountDownLatch latch new CountDownLatch(20); for (int i 0; i 20; i) { pool.execute(() - { try { Thread.sleep(50); } catch (InterruptedException e) { Thread.currentThread().interrupt(); // 恢复中断标记别吞掉 } finally { latch.countDown(); } }); } latch.await(5, TimeUnit.SECONDS); System.out.println(池大小 pool.getPoolSize() 活跃 pool.getActiveCount() 队列 pool.getQueue().size()); pool.shutdown(); } }参数怎么调路线图不会告诉你但这是实战里最常被问的。核心线程数按任务类型估CPU 密集型取核数加一IO 密集型可以放到核数的两倍起但真正的上限由下游决定——数据库连接池如果是 10你把线程池开到 200多出来的 190 个线程只是在等连接除了增加上下文切换没有别的用。队列一定要设边界LinkedBlockingQueue不传容量默认是Integer.MAX_VALUE等于把背压问题推迟到内存爆掉那一刻。拒绝策略里CallerRunsPolicy是最温和的一种它让提交任务的线程自己跑天然形成限流。JVM 那一段路线图列了类加载机制、字节码执行、内存模型、GC、性能监控、调优六项。前四项是理解后两项是手艺。类加载要能画出双亲委派的过程说清为什么自定义类加载器能实现热部署GC 要能根据日志判断是 Young GC 频繁还是 Full GC 频繁前者多半是新生代太小或者对象晋升太快后者要看是不是有大对象直接进了老年代。调优不要一上来就改参数。我一般的顺序是先看现象再动手# 每 2 秒采样一次共 10 次看 Eden/Old 使用率和 GC 次数增长 jstat -gcutil pid 2000 10 # 打印实际生效的 JVM 参数确认 -Xmx、收集器和你以为的一致 jcmd pid VM.flags # 线程栈排查死锁和长时间阻塞 jstack pid thread.txt # 堆快照配合 MAT 找大对象和泄漏点注意文件可能很大 jmap -dump:formatb,fileheap.hprof pidjstat的-gcutil输出的是百分比重点看O老年代使用率是不是只涨不跌、FGC次数是不是在短时间内快速增加。jcmd VM.flags比翻启动脚本可靠容器化部署时经常出现「脚本里写了但没生效」的情况原因多半是JAVA_TOOL_OPTIONS或者镜像里的默认参数覆盖了。jmap导出堆快照会触发一次较长的停顿生产环境执行前要掂量时间窗口。2.3 用脚本把 PDF 目录抽成 CSV让知识点变成可勾选的清单脑图类 PDF 有个麻烦内容明明都在但没法勾选进度。我习惯先把它转成一张 CSV 清单导入表格工具学完一条勾一条进度可视化的心理作用比想象中大。下面这段脚本用pdfplumber抽文本再按模块归类import csv import re import pdfplumber SRC java-roadmap.pdf # 路线图 PDF 路径 OUT checklist.csv # 导出的勾选清单 # 一级模块名按 PDF 里实际出现的标题微调 TOP re.compile(r^(编程基础|JVM|并发|数据结构|计算机网络|数据库|Web开发|后端框架|微服务|前端|研发工具)) rows, current [], with pdfplumber.open(SRC) as pdf: for page in pdf.pages: text page.extract_text() or for line in text.splitlines(): line line.strip() if not line: continue m TOP.match(line) if m: current m.group(1) continue # 过滤页脚、水印一类噪声行 if len(line) 2 or 扫码 in line: continue rows.append({module: current, item: line, done: 0}) with open(OUT, w, newline, encodingutf-8-sig) as f: w csv.DictWriter(f, fieldnames[module, item, done]) w.writeheader() w.writerows(rows) print(f导出 {len(rows)} 条 - {OUT})三个参数说明一下。encodingutf-8-sig不是可有可无不带 BOM 的 UTF-8 用表格软件直接打开大概率乱码TOP正则必须对着实际 PDF 的标题改脑图导出时模块名可能带序号前缀或者换行断开done列先全部置 0后面在表格里手动改成 1 就行。有两个坑提前说。第一如果 PDF 是扫描件或者脑图直接导出的图片型文件extract_text会返回空字符串得先走 OCR这一步的识别成本比想象中高纯图片版不如直接照着脑图手抄一遍。第二脑图导出 PDF 的文本顺序不一定是阅读顺序同一个模块的条目可能跨页散落跑完脚本务必人工扫一遍别把分类错误的行直接拿去用。3. 框架与中间件怎么排期Spring 家族、缓存、MQ 的依赖顺序路线图的后半段信息密度陡然上升Spring 家族、缓存、消息队列、RPC、数据库中间件、微服务组件全挤在一起新手看到这儿最容易犯的错是「并行开工」——今天摸摸 Redis明天装个 RabbitMQ一个月过去哪个都只会敲两条命令。这一段的正确姿势是排依赖先有 Web 容器和 Spring 的容器才谈得上整合先有一条能跑通的读写链路才谈得上选型。3.1 Spring 家族的正确打开顺序IoC 到 Boot 的依赖链路线图里 Spring 这一支列的是 IoC、AOP、Spring MVC、Spring Boot后面跟着「自动配置、开箱即用」和「整合 Web、数据库、权限、中间件」。这个顺序不能乱原因很实在IoC 解决对象怎么来AOP 解决横切逻辑往哪儿放MVC 解决请求怎么进来Boot 解决上面这些怎么少写配置。跳过前面直接上 Boot你会得到一堆「能跑但不知道为什么能跑」的代码出问题时连从哪个注解开始查都没有头绪。IoC 那一节我建议手写一个最简陋的容器扫描包、读注解、反射实例化、按类型注入。写完再回头看ApplicationContext的继承体系会顺畅很多。AOP 要理解代理的两种实现——JDK 动态代理基于接口CGLIB 基于继承这决定了你的类能不能被代理、final方法为什么切不到。这两点在第 4 章的排查里还会再出现一次。Spring MVC 的九大组件不用背名字但要能说清一个请求从DispatcherServlet进来之后经过了谁。整合数据库那一段重点是事务传播行为的七种取值里REQUIRED、REQUIRES_NEW、NESTED三个必须能讲出区别尤其是「同一个类内部方法自调用导致事务失效」这个经典问题它不是玄学是代理机制的直接后果。Boot 阶段的配置我一般会先落一份最小可用的spring: datasource: url: jdbc:mysql://127.0.0.1:3306/demo?useSSLfalseserverTimezoneAsia/Shanghai hikari: maximum-pool-size: 10 # 先和数据库最大连接数对齐不是越大越好 connection-timeout: 3000 # 拿不到连接时快速失败别让请求一直挂着 idle-timeout: 600000 data: redis: host: 127.0.0.1 port: 6379 timeout: 2s # 缓存超时要短挂了要能降级到数据库maximum-pool-size是最容易拍脑袋的参数。单实例 10 个连接四个实例就是 40数据库的max_connections如果只留了 50压测时必然出现「拿不到连接」。connection-timeout设成 3 秒是为了快速失败默认值往往长得多接口超时了还在等连接日志里什么都看不出来。Redis 的前缀在不同 Boot 大版本之间有变化早期是spring.redis.*后来迁到spring.data.redis.*照抄网上配置之前先确认自己引入的依赖版本这是踩过才知道的。整合权限那一节Shiro 和 Spring Security 选一个深入就够。Shiro 上手快、概念少适合中小项目Spring Security 跟 Spring 生态贴得紧OAuth2 和 SSO 那块能力更完整。两个都学个皮毛不如把其中一个的过滤器链吃透。3.2 缓存与消息队列先跑通一条链路再谈选型路线图把 Redis 拆成五大类型、事务、消息通知、管道、持久化、集群把 memcache 放在旁边做对照。这个拆法很实用说明作者默认你是要拿它干活而不是应付面试。学 Redis 的正确起点不是背命令是选一个真实场景把链路跑通比如「商品详情查询」先查缓存命中就返回未命中查库回填缓存并设过期时间更新时先改库再删缓存。这条链路跑通五大类型、过期策略、缓存穿透和雪崩才有附着点。环境我一般用 compose 一把起省得在安装上耗时间services: redis: image: redis:7-alpine ports: - 6379:6379 command: [redis-server, --appendonly, yes] # 开 AOF重启后数据还在 rabbitmq: image: rabbitmq:3-management-alpine ports: - 5672:5672 # 应用连接端口 - 15672:15672 # 管理台 environment: RABBITMQ_DEFAULT_USER: demo RABBITMQ_DEFAULT_PASS: demo123--appendonly yes决定重启后数据是否还在做实验时开着更省心但要知道 AOF 会带来额外的写放大。RabbitMQ 的管理台端口是 15672业务端口是 5672这两个搞混是新手常见的翻车点。消息队列这一节路线图列了 RocketMQ、RabbitMQ、Kafka 三个。选型不用纠结太久业务解耦和延迟消息看 RabbitMQ高吞吐日志和流式处理看 Kafka国内业务场景里 RocketMQ 的事务消息和顺序消息用得比较多。真正要练的不是装三个中间件是搞清三个问题——消息丢了怎么办生产确认 持久化 消费确认、重复消费怎么办幂等键、积压了怎么办扩消费者还是加分区。这三个问题在面试里几乎是必问在线上也是真会出事的地方。RPC 那一段列了 Dubbo、gRPC、Thrift 和 Netty。Netty 建议单独拎出来学它是很多 RPC 框架的底座理解 Reactor 模型和 ByteBuf 之后再看 Dubbo 的协议设计会轻松很多。3.3 微服务组件按「对」来记一个能力配一个最小验证微服务这块名词最密硬背必忘。我的办法是按「能力 → 组件 → 最小验证」三列做表每学一个能力就填一行填不出来的说明还没学透能力路线图里的组件最小验证方式服务注册与发现Eureka、Consul、Zookeeper、Nacos起两个实例停掉一个看调用方多久感知网关Zuul、Gateway配一条路由验证转发和鉴权过滤器顺序服务调用与负载Ribbon、Feign两个提供者实例观察请求是否轮询熔断降级Hystrix提供者人为sleep看调用方是否快速失败配置中心Config、Apollo、Nacos改配置不重启验证是否动态生效分布式事务Seata、TCC、SAGA、LCN造一个跨服务扣减验证异常时是否回滚表格里「最小验证方式」这一列才是重点。注册中心不看「能注册」看的是「宕机后多久摘除」默认的心跳和剔除时间往往比你预期的长压测时会造成一部分请求打到死实例上。熔断组件不看「能配」看的是超时和线程池隔离有没有生效很多线上雪崩就是因为熔断配了但阈值设得离谱。分布式事务那几种模式2PC 和 3PC 属于理论XA 是数据库层面的实现TCC 要自己写三个方法SAGA 靠补偿LCN 靠代理连接。真要动手挑 Seata 的 AT 模式跑一个跨服务扣减的例子比把六种模式的概念背一遍有用得多。跑完你会明白为什么大多数团队最后的选择是「尽量别用分布式事务能拆成最终一致就拆」。4. 落地排查照着路线图学最容易翻车的五件事4.1 翻车一把「收藏」当成「学会」现象PDF 存了三个版本每份都翻了前二十页问起来知识点都能说出名字写代码时一个都用不上。原因脑图给的是压缩后的结论缺少推导过程。看结论的成本极低大脑会误判为已掌握实际调用的路径根本没建立起来。解决强制产出。每学完一个模块写一段能跑的代码或者一篇三百字的笔记要求是「不看资料能讲出来」。第 5 章那张周计划表就是干这个用的每周必须留下一个可运行的东西。4.2 翻车二一上来就啃 JVM 调优现象刚学完基础语法就去找 GC 调优的文章参数改了十几个服务该卡还是卡。原因调优的前提是有可观测的故障现象和对照基线。没有真实压力、没有监控数据改参数全靠猜越调越乱。解决先补并发和监控。用jstat和jstack观察一个自己写的线程池程序看线程数、队列长度、GC 频率怎么变。有现象再谈参数第 2 章那组命令就够用。4.3 翻车三Spring 版本和教程对不上类找不到现象照着资料敲代码javax.servlet.http.HttpServletRequest爆红或者启动时报找不到自动配置类。原因Spring Boot 大版本之间存在包名迁移和配置前缀调整javax.*和jakarta.*分属不同代际spring.redis.*和spring.data.redis.*也是不同版本的事。资料不会标注版本照抄必踩。解决新建工程时锁死一条版本线用官方脚手架生成骨架而不是手写 POM遇到类找不到先看依赖树里实际引入的是哪个坐标mvn dependency:tree比搜索引擎快。4.4 翻车四事务在同类方法自调用时静默失效现象saveOrder里调了本类的deductStockdeductStock上标了Transactional抛异常后库存没回滚。原因Spring 的事务靠代理实现自调用走的是this引用绕过了代理对象注解等于没写。解决把方法拆到另一个 Bean 里或者注入自身代理或者用TransactionTemplate显式控制。这三种方案各有代价我一般选第一种结构上也更干净。排查时打开事务日志看有没有真的开启事务比盯着注解猜快得多。4.5 翻车五中间件装了一堆一条链路都没跑通现象本地起了 Redis、RabbitMQ、Elasticsearch每个都能连上但业务代码里一个都没用起来问起来只能说「环境搭好了」。原因把「安装」当成了「掌握」。中间件的价值在链路里脱离业务场景单独跑几条命令记不住也用不上。解决一次只跑一条完整链路。缓存就做「查询 → 未命中 → 回源 → 回填 → 更新失效」消息队列就做「下单 → 发消息 → 消费扣减 → 幂等校验」。一条链路打通比装五个中间件有用。5. 把路线图压进 12 周时间盒、周产出与自测口径路线图最大的问题是没有时间维度十一大块平铺在那儿看久了会产生「永远学不完」的压迫感。我的做法是把它折叠成 12 周每周只对一个主题且必须留下一个能跑的东西。周产出不为难人一个类、一段脚本、一份压测记录都算关键是「能拿出来给别人看」。5.1 周粒度排布每周对应一条可验收的产出周次主题周产出可验收第 1 周语法、面向对象、异常一个带自定义异常的 CLI 小工具第 2 周容器与泛型手写简化版 HashMap能说明扩容过程第 3 周反射与注解第 2 章那个路由扫描器加参数解析第 4 周并发基础与线程池一份线程池压测记录含队列长度变化曲线第 5 周JUC 与并发容器用 CountDownLatch 编排的多任务汇总程序第 6 周JVM 内存与 GC一次 OOM 复现 jmap 分析笔记第 7 周数据结构与算法三十道题的手写笔记按题型归类第 8 周网络与数据库一个带索引优化的慢查询改造案例第 9 周Spring IoC/AOP/MVC不依赖 Boot 的纯 Spring Web 小服务第 10 周Spring Boot 整合整合数据库、Redis、事务的完整 CRUD第 11 周缓存与消息队列一条带缓存和异步解耦的下单链路第 12 周微服务组件两个服务 注册中心 网关的最小集群这张表可以直接挪但有两处要按自己情况改。一是算法那周如果你目标岗位对算法要求不高可以压到半周把时间让给数据库和框架二是第 11、12 周如果手上没有合适的项目就用一个电商下单场景自己造别去追什么「高并发秒杀」场景越简单越容易跑完。排期还要留缓冲。12 周里有 2 周必然会因为工作加班或者卡在某个问题上停滞这是常态不用因为落后就推翻整张表。我一般把周末的半天固定成「补课时间」专门处理这周没搞定的部分。5.2 自测口径从「我看过」到「我能讲清」每周结束前问自己三个问题回答得磕巴就说明没过。第一这个知识点解决什么问题没有它会怎样第二它的边界在哪什么场景下不适用第三如果线上出了相关故障你的排查顺序是什么第三个问题最能筛出「假会」。比如学完线程池能不能说出「接口变慢、CPU 不高、线程数打满」这种情况该先看什么答案应该是先看队列长度和拒绝策略的触发次数再看下游依赖的响应时间最后才怀疑线程数不够。答不上来说明只是记住了参数名。再补一个笨办法找个不懂技术的朋友用五分钟把某个概念讲给他听讲不通的地方就是你的知识缺口。这招在 JVM 和分布式事务上特别管用因为这两块最容易背结论。5.3 项目经历与面试考点的映射路线图里的知识点和简历上的项目描述应该是一一对应的不对应就说明有块内容你只是「学过」而不是「做过」。做法很简单把项目里每个技术决策写一行后面跟上「为什么选它、替代方案是什么、出过什么问题、怎么解决的」。面试官追问的永远是后两问。举个例子简历写「使用 Redis 缓存热点数据」后面应该能接出为什么用 Redis 不用本地缓存多实例一致性、缓存key怎么设计业务前缀 版本号方便批量失效、更新策略是什么先更库后删缓存 过期时间兜底、出过什么问题缓存击穿导致数据库瞬时压力。这四问能答顺比在简历上堆十个中间件名字管用。6. 进阶用法给路线图建一张反向索引正着学是建立结构反着查才是留住知识。路线图十一大块学到后面一定会忘前面这时候别重头再翻建一张反向索引每次遇到问题记一行「现象 → 定位到的知识点 → 属于哪个模块」攒够三个月你就有了自己的故障字典。具体做法是建一个纯文本文件放在笔记目录每行一条格式固定成三段。比如「接口偶发超时线程栈里大量 WAITING 在连接池 → HikariCP 连接数配置 → 后端框架/数据库」或者「Full GC 频繁老年代增长快dump 里大量未释放的集合 → 大对象与引用泄漏 → JVM」。写的时候不用追求措辞追求的是下次能用关键词搜到。# 按关键词反查历史记录快速定位属于哪个模块 grep -rniE OOM|Full GC|连接池|死锁 ~/notes/incident.log | head -20 # 统计哪类问题出现最多作为下一阶段的复习重点 awk -F→ {print $3} ~/notes/incident.log | sort | uniq -c | sort -rn第二条命令是我自己加的-F→按箭头切段取第三段做频次统计跑出来的结果经常打脸——你以为自己薄弱的是微服务实际高频出现的是数据库和并发。索引跑满三个月复习计划就不用再拍脑袋了哪块记录多就回哪块。这套习惯是被一次线上事故逼出来的。当时一个 Full GC 问题查了整整两天最后发现半年前看过几乎一样的案例笔记里也记过但存在另一个文件夹里搜的时候没想到关键词。从那以后我每次排查完都强制往索引里补一行哪怕只写半句也一定写。希望帮到你。本文还有配套的精品资源点击获取