From d32b48dadb3bfc97e6ec5d61f9f5eb7c48f66ecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E5=B0=8F=E6=96=9C?= <362294931@qq.com> Date: Sun, 9 Apr 2023 16:56:27 +0800 Subject: [PATCH 01/39] modify db --- ...01\347\232\204\345\205\263\347\263\273.md" | 18 ++++++++-- ...47\345\210\253\345\256\236\346\210\230.md" | 1 + ...33\346\227\245\345\277\227\344\273\254.md" | 12 +++++++ ...45\344\270\216\345\256\236\350\267\265.md" | 4 +-- ...30\345\202\250\345\216\237\347\220\206.md" | 33 ++++++++++++++++++- ...23\346\236\204\347\256\227\346\263\225.md" | 3 +- ...272\343\200\217MySQL\345\222\214InnoDB.md" | 2 +- ...30\345\214\226\345\274\200\345\247\213.md" | 14 ++++---- ...20\344\270\216\344\274\230\345\214\226.md" | 3 +- ...04\351\224\201\345\256\236\347\216\260.md" | 2 +- src/main/java/md/mdToc.java | 2 +- 11 files changed, 75 insertions(+), 19 deletions(-) diff --git "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Innodb\344\270\255\347\232\204\344\272\213\345\212\241\351\232\224\347\246\273\347\272\247\345\210\253\345\222\214\351\224\201\347\232\204\345\205\263\347\263\273.md" "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Innodb\344\270\255\347\232\204\344\272\213\345\212\241\351\232\224\347\246\273\347\272\247\345\210\253\345\222\214\351\224\201\347\232\204\345\205\263\347\263\273.md" index 41157d3..b796526 100644 --- "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Innodb\344\270\255\347\232\204\344\272\213\345\212\241\351\232\224\347\246\273\347\272\247\345\210\253\345\222\214\351\224\201\347\232\204\345\205\263\347\263\273.md" +++ "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Innodb\344\270\255\347\232\204\344\272\213\345\212\241\351\232\224\347\246\273\347\272\247\345\210\253\345\222\214\351\224\201\347\232\204\345\205\263\347\263\273.md" @@ -1,3 +1,17 @@ +# Table of Contents + + * [Innodb中的事务隔离级别和锁的关系](#innodb中的事务隔离级别和锁的关系) + * [事务中的加锁方式](#事务中的加锁方式) + * [MySQL中锁的种类](#mysql中锁的种类) + * [Read Committed(读取提交内容)](#read-committed(读取提交内容)) + * [Repeatable Read(可重读)](#repeatable-read(可重读)) + * [不可重复读和幻读的区别](#不可重复读和幻读的区别) + * [悲观锁和乐观锁](#悲观锁和乐观锁) + * [MVCC在MySQL的InnoDB中的实现](#mvcc在mysql的innodb中的实现) + * [“读”与“读”的区别](#读与读的区别) + * [](#-2) + + 本文转自互联网 本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看 @@ -265,9 +279,9 @@ RC(不可重读)模式下的展现 事务的隔离级别实际上都是定义了当前读的级别,MySQL为了减少锁处理(包括等待其它锁)的时间,提升并发能力,引入了快照读的概念,使得select不用加锁。而update、insert这些“当前读”,就需要另外的模块来解决了。 -###写("当前读")事务的隔离级别中虽然只定义了读数据的要求,实际上这也可以说是写数据的要求。上文的“读”,实际是讲的快照读;而这里说的“写”就是当前读了。为了解决当前读中的幻读问题,MySQL事务使用了Next-Key锁。 +写("当前读")事务的隔离级别中虽然只定义了读数据的要求,实际上这也可以说是写数据的要求。上文的“读”,实际是讲的快照读;而这里说的“写”就是当前读了。为了解决当前读中的幻读问题,MySQL事务使用了Next-Key锁。 -####Next-Key锁Next-Key锁是行锁和GAP(间隙锁)的合并,行锁上文已经介绍了,接下来说下GAP间隙锁。 +Next-Key锁Next-Key锁是行锁和GAP(间隙锁)的合并,行锁上文已经介绍了,接下来说下GAP间隙锁。 行锁可以防止不同事务版本的数据修改提交时造成数据冲突的情况。但如何避免别的事务插入数据就成了问题。我们可以看看RR级别和RC级别的对比 diff --git "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232MySQL\347\232\204\344\272\213\345\212\241\351\232\224\347\246\273\347\272\247\345\210\253\345\256\236\346\210\230.md" "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232MySQL\347\232\204\344\272\213\345\212\241\351\232\224\347\246\273\347\272\247\345\210\253\345\256\236\346\210\230.md" index 026a50a..d048c74 100644 --- "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232MySQL\347\232\204\344\272\213\345\212\241\351\232\224\347\246\273\347\272\247\345\210\253\345\256\236\346\210\230.md" +++ "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232MySQL\347\232\204\344\272\213\345\212\241\351\232\224\347\246\273\347\272\247\345\210\253\345\256\236\346\210\230.md" @@ -1,3 +1,4 @@ + # 目录 * [事务的基本要素(ACID)](#事务的基本要素(acid)) * [事务的并发问题](#事务的并发问题) diff --git "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232MySQL\351\207\214\347\232\204\351\202\243\344\272\233\346\227\245\345\277\227\344\273\254.md" "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232MySQL\351\207\214\347\232\204\351\202\243\344\272\233\346\227\245\345\277\227\344\273\254.md" index 347ecee..3469a48 100644 --- "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232MySQL\351\207\214\347\232\204\351\202\243\344\272\233\346\227\245\345\277\227\344\273\254.md" +++ "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232MySQL\351\207\214\347\232\204\351\202\243\344\272\233\346\227\245\345\277\227\344\273\254.md" @@ -1,3 +1,15 @@ +# Table of Contents + +* [目录](#目录) + * [重新学习MySQL数据库10:MySQL里的那些日志们](#重新学习mysql数据库10:mysql里的那些日志们) + * [1.MySQL日志文件系统的组成](#1mysql日志文件系统的组成) + * [2.错误日志](#2错误日志) + * [3.InnoDB中的日志](#3innodb中的日志) + * [4- 慢查询日志](#4--慢查询日志) + * [5.二进制日志](#5二进制日志) + * [总结](#总结) + + # 目录 * [重新学习MySQL数据库10:MySQL里的那些日志们](#重新学习mysql数据库10:mysql里的那些日志们) * [1.MySQL日志文件系统的组成](#1mysql日志文件系统的组成) diff --git "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Mysql\344\270\273\344\273\216\345\244\215\345\210\266\357\274\214\350\257\273\345\206\231\345\210\206\347\246\273\357\274\214\345\210\206\350\241\250\345\210\206\345\272\223\347\255\226\347\225\245\344\270\216\345\256\236\350\267\265.md" "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Mysql\344\270\273\344\273\216\345\244\215\345\210\266\357\274\214\350\257\273\345\206\231\345\210\206\347\246\273\357\274\214\345\210\206\350\241\250\345\210\206\345\272\223\347\255\226\347\225\245\344\270\216\345\256\236\350\267\265.md" index 53a3fc9..6a2ae30 100644 --- "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Mysql\344\270\273\344\273\216\345\244\215\345\210\266\357\274\214\350\257\273\345\206\231\345\210\206\347\246\273\357\274\214\345\210\206\350\241\250\345\210\206\345\272\223\347\255\226\347\225\245\344\270\216\345\256\236\350\267\265.md" +++ "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Mysql\344\270\273\344\273\216\345\244\215\345\210\266\357\274\214\350\257\273\345\206\231\345\210\206\347\246\273\357\274\214\345\210\206\350\241\250\345\210\206\345\272\223\347\255\226\347\225\245\344\270\216\345\256\236\350\267\265.md" @@ -11,8 +11,6 @@ * [三、Mycat 垂直切分、水平切分实战](#三、mycat-垂直切分、水平切分实战) * [1、垂直切分](#1、垂直切分) * [2、水平切分](#2、水平切分) -* [range start-end ,data node index](#range-start-end-data-node-index) -* [K=1000,M=10000.](#k1000m10000) * [为什么需要读写分离](#为什么需要读写分离) * [MySQL主从复制](#mysql主从复制) * [Mycat读写分离设置](#mycat读写分离设置) @@ -627,4 +625,4 @@ Mycat的配置有很多,不过因为我们只是使用Mycat的读写分类的 前面已经差不多都解释清楚了,因为我只是用的基本的主从复制,所以我的将`dataHost`的`balance`设置成了3 -启动mycat,然后用数据库连接工具连接到mycat,可以测试是否配置成功,最简单的就是通过修改从库的数据,这样方便查看到底是运行到哪个库上面了,另外由于我是基于docker启动的mycat,所以如果是直接在系统中运行的mycat的,可以去看官方文档,看看到底怎么启动mycat \ No newline at end of file +启动mycat,然后用数据库连接工具连接到mycat,可以测试是否配置成功,最简单的就是通过修改从库的数据,这样方便查看到底是运行到哪个库上面了,另外由于我是基于docker启动的mycat,所以如果是直接在系统中运行的mycat的,可以去看官方文档,看看到底怎么启动mycat diff --git "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Mysql\345\255\230\345\202\250\345\274\225\346\223\216\344\270\216\346\225\260\346\215\256\345\255\230\345\202\250\345\216\237\347\220\206.md" "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Mysql\345\255\230\345\202\250\345\274\225\346\223\216\344\270\216\346\225\260\346\215\256\345\255\230\345\202\250\345\216\237\347\220\206.md" index 64db961..4763b48 100644 --- "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Mysql\345\255\230\345\202\250\345\274\225\346\223\216\344\270\216\346\225\260\346\215\256\345\255\230\345\202\250\345\216\237\347\220\206.md" +++ "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Mysql\345\255\230\345\202\250\345\274\225\346\223\216\344\270\216\346\225\260\346\215\256\345\255\230\345\202\250\345\216\237\347\220\206.md" @@ -1,3 +1,34 @@ +# Table of Contents + + * [**一、 MySQL记录存储(页为单位)**](#一、-mysql记录存储(页为单位)) + * [**页头**](#页头) + * [**虚记录**](#虚记录) + * [**记录堆**](#记录堆) + * [**自由空间链表**](#自由空间链表) + * [**未分配空间**](#未分配空间) + * [**Slot区**](#slot区) + * [**页内记录维护**](#页内记录维护) + * [**二、 MySQL InnoDB存储引擎内存管理**](#二、-mysql-innodb存储引擎内存管理) + * [**预分配内存空间**](#预分配内存空间) + * [**数据以页为单位加载 (减少io访问次数)**](#数据以页为单位加载-(减少io访问次数)) + * [**数据内外存交换**](#数据内外存交换) + * [**页面管理**](#页面管理) + * [**页面淘汰**](#页面淘汰) + * [**全表扫描对内存的影响?**](#全表扫描对内存的影响?) + * [**页面淘汰**](#页面淘汰-1) + * [**位置移动**](#位置移动) + * [**三、MySQL事务实现原理**](#三、mysql事务实现原理) + * [**1、事务特性**](#1、事务特性) + * [**2、并发问题**](#2、并发问题) + * [**3、隔离级别**](#3、隔离级别) + * [**MySQL事务实现原理(事务管理机制)**](#mysql事务实现原理(事务管理机制)) + * [**1、MVCC 多版本并发控制**](#1、mvcc-多版本并发控制) + * [**2、undo log**](#2、undo-log) + * [**3、redo log**](#3、redo-log) + * [**意义**](#意义) + * [**四、MySQL锁实现原理**](#四、mysql锁实现原理) + + ## **一、 MySQL记录存储(页为单位)**  @@ -255,4 +286,4 @@ RR级别下 死锁在库表中有记录,通过kill 那个锁删除。 - \ No newline at end of file + diff --git "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Mysql\347\264\242\345\274\225\345\256\236\347\216\260\345\216\237\347\220\206\345\222\214\347\233\270\345\205\263\346\225\260\346\215\256\347\273\223\346\236\204\347\256\227\346\263\225.md" "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Mysql\347\264\242\345\274\225\345\256\236\347\216\260\345\216\237\347\220\206\345\222\214\347\233\270\345\205\263\346\225\260\346\215\256\347\273\223\346\236\204\347\256\227\346\263\225.md" index c404f1e..7bd83de 100644 --- "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Mysql\347\264\242\345\274\225\345\256\236\347\216\260\345\216\237\347\220\206\345\222\214\347\233\270\345\205\263\346\225\260\346\215\256\347\273\223\346\236\204\347\256\227\346\263\225.md" +++ "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Mysql\347\264\242\345\274\225\345\256\236\347\216\260\345\216\237\347\220\206\345\222\214\347\233\270\345\205\263\346\225\260\346\215\256\347\273\223\346\236\204\347\256\227\346\263\225.md" @@ -1,3 +1,4 @@ + # 目录 * [MySQL索引](#mysql索引) @@ -904,4 +905,4 @@ title的选择性不足0.0001(精确值为0.00001579),所以实在没有 [5] Codd, E. F. (1970). "A relational model of data for large shared data banks". Communications of the ACM, , Vol. 13, No. 6, pp. 377-387 -[6] MySQL5.1参考手册 - [http://dev.mysql.com/doc/refman/5.1/zh/index.html](http://dev.mysql.com/doc/refman/5.1/zh/index.html "http://dev.mysql.com/doc/refman/5.1/zh/index.html") \ No newline at end of file +[6] MySQL5.1参考手册 - [http://dev.mysql.com/doc/refman/5.1/zh/index.html](http://dev.mysql.com/doc/refman/5.1/zh/index.html "http://dev.mysql.com/doc/refman/5.1/zh/index.html") diff --git "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232\343\200\216\346\265\205\345\205\245\346\265\205\345\207\272\343\200\217MySQL\345\222\214InnoDB.md" "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232\343\200\216\346\265\205\345\205\245\346\265\205\345\207\272\343\200\217MySQL\345\222\214InnoDB.md" index d8eaa99..8e3991b 100644 --- "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232\343\200\216\346\265\205\345\205\245\346\265\205\345\207\272\343\200\217MySQL\345\222\214InnoDB.md" +++ "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232\343\200\216\346\265\205\345\205\245\346\265\205\345\207\272\343\200\217MySQL\345\222\214InnoDB.md" @@ -22,7 +22,7 @@ * [不可重复读](#不可重复读) * [幻读](#幻读) * [总结](#总结) - * [[Innodb与Myisam引擎的区别与应用场景](https://www.cnblogs.com/changna1314/p/6878900.html)](#[innodb与myisam引擎的区别与应用场景]httpswwwcnblogscomchangna1314p6878900html) + * [Innodb与Myisam引擎的区别与应用场景](#[innodb与myisam引擎的区别与应用场景]) 本文转自互联网 diff --git "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232\344\273\216\345\256\236\350\267\265sql\350\257\255\345\217\245\344\274\230\345\214\226\345\274\200\345\247\213.md" "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232\344\273\216\345\256\236\350\267\265sql\350\257\255\345\217\245\344\274\230\345\214\226\345\274\200\345\247\213.md" index 7155755..f3bd6d8 100644 --- "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232\344\273\216\345\256\236\350\267\265sql\350\257\255\345\217\245\344\274\230\345\214\226\345\274\200\345\247\213.md" +++ "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232\344\273\216\345\256\236\350\267\265sql\350\257\255\345\217\245\344\274\230\345\214\226\345\274\200\345\247\213.md" @@ -8,9 +8,9 @@ * [InnoDB](#innodb) * [0、自己写的海量数据sql优化实践](#0、自己写的海量数据sql优化实践) * [mysql百万级分页优化](#mysql百万级分页优化) - * [ 普通分页](# 普通分页) - * [ 优化分页](# -优化分页) -* [ 总结](# 总结) + * [普通分页](#普通分页) + * [优化分页](#优化分页) +* [总结](#总结) 本文转自互联网 @@ -667,7 +667,7 @@ SELECT s.* from Student s INNER JOIN SC sc on sc.s_id = s.s_id where sc.c_id=0 ## mysql百万级分页优化 -### 普通分页 +### 普通分页 数据分页在网页中十分多见,分页一般都是limit start,offset,然后根据页码page计算start @@ -681,7 +681,7 @@ SELECT * from user limit **100001**,**20**; //time **0**.151s explain SELECT * f  -### 优化分页 +### 优化分页 使用主键索引来优化数据分页 @@ -693,10 +693,10 @@ SELECT * from user limit **100001**,**20**; //time **0**.151s explain SELECT * f  -## 总结 +## 总结 在数据量比较大的时候,我们尽量去利用索引来优化语句。上面的优化方法如果id不是主键索引,查询效率比第一种还要低点。我们可以先使用explain来分析语句,查看语句的执行顺序和执行性能。 -转载于:https://my.oschina.net/alicoder/blog/3097141 \ No newline at end of file +转载于:https://my.oschina.net/alicoder/blog/3097141 diff --git "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232\346\240\271\346\215\256MySQL\347\264\242\345\274\225\345\216\237\347\220\206\350\277\233\350\241\214\345\210\206\346\236\220\344\270\216\344\274\230\345\214\226.md" "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232\346\240\271\346\215\256MySQL\347\264\242\345\274\225\345\216\237\347\220\206\350\277\233\350\241\214\345\210\206\346\236\220\344\270\216\344\274\230\345\214\226.md" index e90f560..3dd0dbf 100644 --- "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232\346\240\271\346\215\256MySQL\347\264\242\345\274\225\345\216\237\347\220\206\350\277\233\350\241\214\345\210\206\346\236\220\344\270\216\344\274\230\345\214\226.md" +++ "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232\346\240\271\346\215\256MySQL\347\264\242\345\274\225\345\216\237\347\220\206\350\277\233\350\241\214\345\210\206\346\236\220\344\270\216\344\274\230\345\214\226.md" @@ -1,5 +1,4 @@ # 目录 - * [一:Mysql原理与慢查询](#一:mysql原理与慢查询) * [一个慢查询引发的思考](#一个慢查询引发的思考) * [二:索引建立](#二:索引建立) @@ -523,4 +522,4 @@ title的选择性不足0.0001(精确值为0.00001579),所以实在没有 此时MySQL不得不为了将新记录插到合适位置而移动数据,甚至目标页面可能已经被回写到磁盘上而从缓存中清掉,此时又要从磁盘上读回来,这增加了很多开销,同时频繁的移动、分页操作造成了大量的碎片,得到了不够紧凑的索引结构,后续不得不通过OPTIMIZE TABLE来重建表并优化填充页面。 -因此,只要可以,请尽量在InnoDB上采用自增字段做主键。 \ No newline at end of file +因此,只要可以,请尽量在InnoDB上采用自增字段做主键。 diff --git "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232\350\257\246\350\247\243MyIsam\344\270\216InnoDB\345\274\225\346\223\216\347\232\204\351\224\201\345\256\236\347\216\260.md" "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232\350\257\246\350\247\243MyIsam\344\270\216InnoDB\345\274\225\346\223\216\347\232\204\351\224\201\345\256\236\347\216\260.md" index 473146f..3b3fb32 100644 --- "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232\350\257\246\350\247\243MyIsam\344\270\216InnoDB\345\274\225\346\223\216\347\232\204\351\224\201\345\256\236\347\216\260.md" +++ "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232\350\257\246\350\247\243MyIsam\344\270\216InnoDB\345\274\225\346\223\216\347\232\204\351\224\201\345\256\236\347\216\260.md" @@ -326,4 +326,4 @@ InnoDB在绝大部分情况会使用行级锁,因为事务和行锁往往是 2、在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁产生概率; -3、对于非常容易产生死锁的业务部分,可以尝试使用升级锁定颗粒度,通过表级锁定来减少死锁产生的概率; \ No newline at end of file +3、对于非常容易产生死锁的业务部分,可以尝试使用升级锁定颗粒度,通过表级锁定来减少死锁产生的概率; diff --git a/src/main/java/md/mdToc.java b/src/main/java/md/mdToc.java index 05650b7..6dbcab7 100644 --- a/src/main/java/md/mdToc.java +++ b/src/main/java/md/mdToc.java @@ -4,7 +4,7 @@ public class mdToc { public static void main(String[] args) { - String path = "D:\\idea_project\\javaTutorial\\docs\\big-backEnd\\temp"; + String path = "D:\\idea_project\\javaTutorial\\docs\\database"; AtxMarkdownToc.newInstance().genTocDir(path); } } From 19319b2c0b986bc5eee13bc6fe868aa5364046cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E5=B0=8F=E6=96=9C?= <362294931@qq.com> Date: Sun, 9 Apr 2023 17:10:48 +0800 Subject: [PATCH 02/39] modify distributed mds --- ReadMe.md | 2 +- ...46\344\271\240\346\200\273\347\273\223.md" | 20 +++++------ ...45\237\272\347\241\200 \357\274\232CAP.md" | 27 +++++++++----- ...46\200\247\343\200\201PC\345\222\214PC.md" | 23 ++++++++---- ...13\344\273\266\351\241\272\345\272\217.md" | 21 +++++++---- ...5\237\272\347\241\200\357\274\232Paxos.md" | 16 ++++++--- ...241\200\357\274\232Raft\343\200\201Zab.md" | 19 +++++++--- ...17\350\260\203\346\234\215\345\212\241.md" | 25 ++++++++----- ...76\345\222\214\347\247\237\347\272\246.md" | 16 ++++++--- ...15\345\222\214\344\274\230\345\214\226.md" | 20 +++++++---- ...06\350\256\272\346\200\273\347\273\223.md" | 0 ...44\270\200\350\207\264\346\200\247hash.md" | 35 +++++++------------ ...43\345\206\263\346\226\271\346\241\210.md" | 1 + ...03\345\274\217\344\272\213\345\212\241.md" | 22 ++++++------ ...6\201\257\346\212\200\346\234\257Kafka.md" | 20 +++++------ ...40\347\247\215\346\226\271\346\241\210.md" | 16 ++++----- ...00\344\275\263\345\256\236\350\267\265.md" | 8 ++--- src/main/java/md/mdToc.java | 2 +- 18 files changed, 177 insertions(+), 116 deletions(-) rename "docs/distributed/\345\210\206\345\270\203\345\274\217\347\220\206\350\256\272\346\200\273\347\273\223.md" => "docs/distributed/practice/\345\210\206\345\270\203\345\274\217\347\220\206\350\256\272\346\200\273\347\273\223.md" (100%) diff --git a/ReadMe.md b/ReadMe.md index dc53ae6..484bbda 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -317,7 +317,7 @@ todo * [分布式系统理论进阶:Paxos变种和优化 ](docs/distributed/basic/分布式系统理论进阶:Paxos变种和优化.md) * [分布式系统理论基础:zookeeper分布式协调服务 ](docs/distributed/basic/分布式系统理论基础:zookeeper分布式协调服务.md) -* [分布式技术实践总结](docs/distributed/分布式理论总结.md) +* [分布式技术实践总结](docs/distributed/practice/分布式理论总结.md) ### 技术 * [搞懂分布式技术:分布式系统的一些基本概念](docs/distributed/practice/搞懂分布式技术:分布式系统的一些基本概念.md ) diff --git "a/docs/cs/operating-system/Linux\345\206\205\346\240\270\344\270\216\345\237\272\347\241\200\345\221\275\344\273\244\345\255\246\344\271\240\346\200\273\347\273\223.md" "b/docs/cs/operating-system/Linux\345\206\205\346\240\270\344\270\216\345\237\272\347\241\200\345\221\275\344\273\244\345\255\246\344\271\240\346\200\273\347\273\223.md" index 4a366fc..3cf91e6 100644 --- "a/docs/cs/operating-system/Linux\345\206\205\346\240\270\344\270\216\345\237\272\347\241\200\345\221\275\344\273\244\345\255\246\344\271\240\346\200\273\347\273\223.md" +++ "b/docs/cs/operating-system/Linux\345\206\205\346\240\270\344\270\216\345\237\272\347\241\200\345\221\275\344\273\244\345\255\246\344\271\240\346\200\273\347\273\223.md" @@ -309,7 +309,7 @@ linux使用inode来标识任意一个文件。inode存储除了文件名以外 -
#include+#includessize_t write(int filedes, void *buf, size_t nbytes); // 返回:若成功则返回写入的字节数,若出错则返回-1 // filedes:文件描述符 // buf:待写入数据缓存区 // nbytes:要写入的字节数
1 ssize_t /* Write "n" bytes to a descriptor. */
+ 1 ssize_t /* Write "n" bytes to a descriptor. */
2 writen(int fd, const void *vptr, size_t n)
3 {
4 size_t nleft;
@@ -335,7 +335,7 @@ linux使用inode来标识任意一个文件。inode存储除了文件名以外
18 nleft -= nwritten; 19 ptr += nwritten; 20 } 21 return(n); 22 } 23 /* end writen */
24
25 void
-26 Writen(int fd, void *ptr, size_t nbytes) 27 { 28 if (writen(fd, ptr, nbytes) != nbytes) 29 err_sys("writen error"); 30 }
+26 Writen(int fd, void *ptr, size_t nbytes) 27 { 28 if (writen(fd, ptr, nbytes) != nbytes) 29 err_sys("writen error"); 30 }目录

@@ -349,7 +349,7 @@ linux使用inode来标识任意一个文件。inode存储除了文件名以外
-#include+#includessize_t read(int filedes, void *buf, size_t nbytes); // 返回:若成功则返回读到的字节数,若已到文件末尾则返回0,若出错则返回-1 // filedes:文件描述符 // buf:读取数据缓存区 // nbytes:要读取的字节数
1 ssize_t /* Read "n" bytes from a descriptor. */
+ 1 ssize_t /* Read "n" bytes from a descriptor. */
2 readn(int fd, void *vptr, size_t n)
3 {
4 size_t nleft;
@@ -390,7 +390,7 @@ linux使用inode来标识任意一个文件。inode存储除了文件名以外
23 } 24 /* end readn */
25
26 ssize_t 27 Readn(int fd, void *ptr, size_t nbytes) 28 { 29 ssize_t n; 30
-31 if ( (n = readn(fd, ptr, nbytes)) < 0) 32 err_sys("readn error"); 33 return(n); 34 }
+31 if ( (n = readn(fd, ptr, nbytes)) < 0) 32 err_sys("readn error"); 33 return(n); 34 }目录

@@ -406,7 +406,7 @@ linux使用inode来标识任意一个文件。inode存储除了文件名以外
-#include+#includessize_t write(int fd, const void *buf, size_t count);
# 获取socket的发送/接受缓冲区的大小:(后面的值是在Linux 2.6.38 x86_64上测试的结果)+# 获取socket的发送/接受缓冲区的大小:(后面的值是在Linux 2.6.38 x86_64上测试的结果)目录 -
sysctl net.core.wmem_default #126976 -sysctl net.core.wmem_max #131071+sysctl net.core.wmem_default #126976 +sysctl net.core.wmem_max #131071目录 diff --git "a/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200 \357\274\232CAP.md" "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200 \357\274\232CAP.md" index 8d61a51..268f008 100644 --- "a/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200 \357\274\232CAP.md" +++ "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200 \357\274\232CAP.md" @@ -1,3 +1,14 @@ +# Table of Contents + + * [**引言**](#引言) + * [**CAP定理**](#cap定理) + * [**CAP的工程启示**](#cap的工程启示) + * [**1、关于 P 的理解**](#1、关于-p-的理解) + * [**2、CA非0/1的选择**](#2、ca非01的选择) + * [**3、跳出CAP**](#3、跳出cap) + * [**小结**](#小结) + + 本文转自:https://www.cnblogs.com/bangerlee/p/5328888.html 本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看 @@ -17,11 +28,11 @@ 如果对本系列文章有什么建议,或者是有什么疑问的话,也可以关注公众号【Java技术江湖】联系作者,欢迎你参与本系列博文的创作和修订。 -**引言** +## **引言** CAP是分布式系统、特别是分布式存储领域中被讨论最多的理论,“[什么是CAP定理?](https://www.quora.com/What-Is-CAP-Theorem-1)”在Quora 分布式系统分类下排名 FAQ 的 No.1。CAP在程序员中也有较广的普及,它不仅仅是“C、A、P不能同时满足,最多只能3选2”,以下尝试综合各方观点,从发展历史、工程实践等角度讲述CAP理论。希望大家透过本文对CAP理论有更多地了解和认识。 -**CAP定理** +## **CAP定理** CAP由[Eric Brewer](https://en.wikipedia.org/wiki/Eric_Brewer_(scientist))在2000年PODC会议上提出[1][2],是Eric Brewer在Inktomi[3]期间研发搜索引擎、分布式web缓存时得出的关于数据一致性(consistency)、服务可用性(availability)、分区容错性(partition-tolerance)的猜想: @@ -38,13 +49,13 @@ C、A、P三者最多只能满足其中两个,和FLP定理一样,CAP定理  -**CAP的工程启示** +## **CAP的工程启示** CAP理论提出7、8年后,NoSql圈将CAP理论当作对抗传统关系型数据库的依据、阐明自己放宽对数据一致性(consistency)要求的正确性[6],随后引起了大范围关于CAP理论的讨论。 CAP理论看似给我们出了一道3选2的选择题,但在工程实践中存在很多现实限制条件,需要我们做更多地考量与权衡,避免进入CAP认识误区[7]。 -**1、关于 P 的理解** +### **1、关于 P 的理解** Partition字面意思是网络分区,即因网络因素将系统分隔为多个单独的部分,有人可能会说,网络分区的情况发生概率非常小啊,是不是不用考虑P,保证CA就好[8]。要理解P,我们看回CAP证明[4]中P的定义: @@ -56,7 +67,7 @@ Partition字面意思是网络分区,即因网络因素将系统分隔为多 > In a network subject to communication failures, it is impossible for any web service to implement an atomic read/write shared memory that guarantees a response to every request. -**2、CA非0/1的选择** +### **2、CA非0/1的选择** P 是必选项,那3选2的选择题不就变成数据一致性(consistency)、服务可用性(availability) 2选1?工程实践中一致性有不同程度,可用性也有不同等级,在保证分区容错性的前提下,放宽约束后可以兼顾一致性和可用性,两者不是非此即彼[12]。 @@ -71,7 +82,7 @@ CAP定理证明中的一致性指强一致性,强一致性要求多节点组 工程实践中,较常见的做法是通过异步拷贝副本(asynchronous replication)、quorum/NRW,实现在调用端看来数据强一致、被调端最终一致,在调用端看来服务可用、被调端允许部分节点不可用(或被网络分隔)的效果[15]。 -**3、跳出CAP** +### **3、跳出CAP** CAP理论对实现分布式系统具有指导意义,但CAP理论并没有涵盖分布式工程实践中的所有重要因素。 @@ -79,7 +90,7 @@ CAP理论对实现分布式系统具有指导意义,但CAP理论并没有涵 延时与数据一致性也是一对“冤家”,如果要达到强一致性、多个副本数据一致,必然增加延时。加上延时的考量,我们得到一个CAP理论的修改版本PACELC[17]:如果出现P(网络分区),如何在A(服务可用性)、C(数据一致性)之间选择;否则,如何在L(延时)、C(数据一致性)之间选择。 -**小结** +### **小结** 以上介绍了CAP理论的源起和发展,介绍了CAP理论给分布式系统工程实践带来的启示。 @@ -125,4 +136,4 @@ CAP理论对分布式系统实现有非常重大的影响,我们可以根据 [19] [How to beat the CAP theorem](http://nathanmarz.com/blog/how-to-beat-the-cap-theorem.html), nathanmarz , 2011 -[20] [The CAP FAQ](https://github.com/henryr/cap-faq), Henry Robinson \ No newline at end of file +[20] [The CAP FAQ](https://github.com/henryr/cap-faq), Henry Robinson diff --git "a/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232 \344\270\200\350\207\264\346\200\247\343\200\201PC\345\222\214PC.md" "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232 \344\270\200\350\207\264\346\200\247\343\200\201PC\345\222\214PC.md" index 8041d4d..9b94bed 100644 --- "a/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232 \344\270\200\350\207\264\346\200\247\343\200\201PC\345\222\214PC.md" +++ "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232 \344\270\200\350\207\264\346\200\247\343\200\201PC\345\222\214PC.md" @@ -1,3 +1,12 @@ +# Table of Contents + + * [**引言**](#引言) + * [**一致性(consensus)**](#一致性consensus) + * [**2PC**](#2pc) + * [**3PC**](#3pc) + * [**小结**](#小结) + + 本文转自 https://www.cnblogs.com/bangerlee/p/5268485.html 本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看 @@ -31,7 +40,7 @@ 一致性是分布式理论中的根本性问题,近半个世纪以来,科学家们围绕着一致性问题提出了很多理论模型,依据这些理论模型,业界也出现了很多工程实践投影。下面我们从一致性问题、特定条件下解决一致性问题的两种方法(2PC、3PC)入门,了解最基础的分布式系统理论。 -**一致性(consensus)** +### **一致性(consensus)** 何为一致性问题?简单而言,一致性问题就是相互独立的节点之间如何达成一项决议的问题。分布式系统中,进行数据库事务提交(commit transaction)、Leader选举、序列号生成等都会遇到一致性问题。这个问题在我们的日常生活中也很常见,比如牌友怎么商定几点在哪打几圈麻将: @@ -60,7 +69,7 @@ _《赌圣》,1990_ -
我: 老王,今晚7点老地方,搓够48圈不见不散! +我: 老王,今晚7点老地方,搓够48圈不见不散! …… (第二天凌晨3点) 隔壁老王: 没问题! // 消息延迟 我: …… @@ -71,7 +80,7 @@ _《赌圣》,1990_ 我: …… ----------------------------------------------- 我: 老李头,今晚7点老地方,搓够48圈不见不散! -老李: 必须的,大保健走起! // 拜占庭将军 (这是要打麻将呢?还是要大保健?还是一边打麻将一边大保健……)+老李: 必须的,大保健走起! // 拜占庭将军 (这是要打麻将呢?还是要大保健?还是一边打麻将一边大保健……)目录 @@ -94,7 +103,7 @@ FLP定理是分布式系统理论中的基础理论,正如物理学中的能 _《怦然心动 (Flipped)》,2010_ 工程实践上根据具体的业务场景,或保证强一致(safety),或在节点宕机、网络分化的时候保证可用(liveness)。2PC、3PC是相对简单的解决一致性问题的协议,下面我们就来了解2PC和3PC。 -**2PC** +### **2PC** 2PC(tow phase commit)两阶段提交[5]顾名思义它分成两个阶段,先由一方进行提议(propose)并收集其他节点的反馈(vote),再根据反馈决定提交(commit)或中止(abort)事务。我们将提议的节点称为协调者(coordinator),其他参与决议节点称为参与者(participants, 或cohorts): @@ -116,7 +125,7 @@ coordinator如果在发起提议后宕机,那么participant将进入阻塞(blo 从coordinator接收到一次事务请求、发起提议到事务完成,经过2PC协议后增加了2次RTT(propose+commit),带来的时延(latency)增加相对较少。 -**3PC** +### **3PC** 3PC(three phase commit)即三阶段提交[6][7],既然2PC可以在异步网络+节点宕机恢复的模型下实现一致性,那还需要3PC做什么,3PC是什么鬼? @@ -141,7 +150,7 @@ participant如果在不同阶段宕机,我们来看看3PC如何应对: 因为有了准备提交(prepare to commit)阶段,3PC的事务处理延时也增加了1个RTT,变为3个RTT(propose+precommit+commit),但是它防止participant宕机后整个系统进入阻塞态,增强了系统的可用性,对一些现实业务场景是非常值得的。 -**小结** +### **小结** 以上介绍了分布式系统理论中的部分基础知识,阐述了一致性(consensus)的定义和实现一致性所要面临的问题,最后讨论在异步网络(asynchronous)、节点宕机恢复(fail-recover)模型下2PC、3PC怎么解决一致性问题。 @@ -159,4 +168,4 @@ participant如果在不同阶段宕机,我们来看看3PC如何应对: [6][Consensus Protocols: Three-phase Commit](http://the-paper-trail.org/blog/consensus-protocols-three-phase-commit/),Henry Robinson, 2008 -[7][Three-phase commit protocol](https://en.wikipedia.org/wiki/Three-phase_commit_protocol),Wikipedia \ No newline at end of file +[7][Three-phase commit protocol](https://en.wikipedia.org/wiki/Three-phase_commit_protocol),Wikipedia diff --git "a/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232 \346\227\266\351\227\264\343\200\201\346\227\266\351\222\237\345\222\214\344\272\213\344\273\266\351\241\272\345\272\217.md" "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232 \346\227\266\351\227\264\343\200\201\346\227\266\351\222\237\345\222\214\344\272\213\344\273\266\351\241\272\345\272\217.md" index 47b12a6..47d52a7 100644 --- "a/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232 \346\227\266\351\227\264\343\200\201\346\227\266\351\222\237\345\222\214\344\272\213\344\273\266\351\241\272\345\272\217.md" +++ "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232 \346\227\266\351\227\264\343\200\201\346\227\266\351\222\237\345\222\214\344\272\213\344\273\266\351\241\272\345\272\217.md" @@ -1,3 +1,12 @@ +# Table of Contents + + * [**物理时钟 vs 逻辑时钟**](#物理时钟-vs-逻辑时钟) + * [**Lamport timestamps**](#lamport-timestamps) + * [**Vector clock**](#vector-clock) + * [**Version vector**](#version-vector) + * [**小结**](#小结) + + 转自:https://www.cnblogs.com/bangerlee/p/5448766.html 本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看 @@ -21,7 +30,7 @@ 现实生活中时间是很重要的概念,时间可以记录事情发生的时刻、比较事情发生的先后顺序。分布式系统的一些场景也需要记录和比较不同节点间事件发生的顺序,但不同于日常生活使用物理时钟记录时间,分布式系统使用逻辑时钟记录事件顺序关系,下面我们来看分布式系统中几种常见的逻辑时钟。 -**物理时钟 vs 逻辑时钟** +## **物理时钟 vs 逻辑时钟** 可能有人会问,为什么分布式系统不使用物理时钟(physical clock)记录事件?每个事件对应打上一个时间戳,当需要比较顺序的时候比较相应时间戳就好了。 @@ -29,7 +38,7 @@  -**Lamport timestamps** +## **Lamport timestamps** [Leslie](https://en.wikipedia.org/wiki/Leslie_Cheung)[Lamport](https://en.wikipedia.org/wiki/Leslie_Lamport)在1978年提出逻辑时钟的概念,并描述了一种逻辑时钟的表示方法,这个方法被称为Lamport时间戳(Lamport timestamps)[3]。 @@ -50,7 +59,7 @@ _图1: Lamport timestamps space time (图片来源: wikipedia)_ 通过以上定义,我们可以对所有事件排序、获得事件的[全序关系](https://en.wikipedia.org/wiki/Total_order)(total order)。上图例子,我们可以从C1到A4进行排序。 -**Vector clock** +## **Vector clock** Lamport时间戳帮助我们得到事件顺序关系,但还有一种顺序关系不能用Lamport时间戳很好地表示出来,那就是同时发生关系(concurrent)[4]。例如图1中事件B4和事件C3没有因果关系,属于同时发生事件,但Lamport时间戳定义两者有先后顺序。 @@ -64,7 +73,7 @@ _图2: Vector clock space time (_图片来源: wikipedia)__ 如果Tb[Q] > Ta[Q] 并且 Tb[P] < Ta[P],则认为a、b同时发生,记作 a <-> b。例如图2中节点B上的第4个事件 (A:2,B:4,C:1) 与节点C上的第2个事件 (B:3,C:2) 没有因果关系、属于同时发生事件。 -**Version vector** +## **Version vector** 基于Vector clock我们可以获得任意两个事件的顺序关系,结果或为先后顺序或为同时发生,识别事件顺序在工程实践中有很重要的引申应用,最常见的应用是发现数据冲突(detect conflict)。 @@ -85,7 +94,7 @@ Vector clock只用于发现数据冲突,不能解决数据冲突。如何解 解决该问题的方法是使用server id取代client id创建vector (因为server的数量相对client稳定),或设定最大的size、如果超过该size值则淘汰最旧的vector信息[10][13]。 -**小结** +## **小结** 以上介绍了分布式系统里逻辑时钟的表示方法,通过Lamport timestamps可以建立事件的全序关系,通过Vector clock可以比较任意两个事件的顺序关系并且能表示无因果关系的事件,将Vector clock的方法用于发现数据版本冲突,于是有了Version vector。 @@ -113,4 +122,4 @@ Vector clock只用于发现数据冲突,不能解决数据冲突。如何解 [12][Why Vector Clocks Are Hard](http://basho.com/posts/technical/why-vector-clocks-are-hard/), Justin Sheehy, 2010 -[13][Causality Is Expensive (and What To Do About It)](http://www.bailis.org/blog/causality-is-expensive-and-what-to-do-about-it/), Peter Bailis ,2014 \ No newline at end of file +[13][Causality Is Expensive (and What To Do About It)](http://www.bailis.org/blog/causality-is-expensive-and-what-to-do-about-it/), Peter Bailis ,2014 diff --git "a/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232Paxos.md" "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232Paxos.md" index 5171749..030e7ac 100644 --- "a/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232Paxos.md" +++ "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232Paxos.md" @@ -1,3 +1,11 @@ +# Table of Contents + + * [**引言**](#引言) + * [**Basic Paxos**](#basic-paxos) + * [**Multi Paxos**](#multi-paxos) + * [**小结**](#小结) + + 本文转自:https://www.cnblogs.com/bangerlee/p/5655754.html 本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看 @@ -23,7 +31,7 @@ Paxos协议同时又以其“艰深晦涩”著称,下面结合[Paxos Made Simple](http://research.microsoft.com/en-us/um/people/lamport/pubs/paxos-simple.pdf)、[The Part-Time Parliament](http://research.microsoft.com/en-us/um/people/lamport/pubs/lamport-paxos.pdf)两篇论文,尝试通过Paxos推演、学习和了解Paxos协议。 -**Basic Paxos** +## **Basic Paxos** 何为一致性问题?简单而言,一致性问题是在节点宕机、消息无序等场景可能出现的情况下,相互独立的节点之间如何达成决议的问题,作为解决一致性问题的协议,Paxos的核心是节点间如何确定并只确定一个值(value)。 @@ -125,7 +133,7 @@ _(注: 希腊字母ß表示多轮决议的集合,字母B表示一轮决议)_ 最后我们再引入一个新的角色:learner,learner依附于acceptor,用于习得已确定的决议。以上决议过程都只要求acceptor多数派参与,而我们希望尽量所有acceptor的状态一致。如果部分acceptor因宕机等原因未知晓已确定决议,宕机恢复后可经本机learner采用pull的方式从其他acceptor习得。 -**Multi Paxos** +## **Multi Paxos** 通过以上步骤分布式系统已经能确定一个值,“只确定一个值有什么用?这可解决不了我面临的问题。” 你心中可能有这样的疑问。 @@ -139,7 +147,7 @@ _(注: 希腊字母ß表示多轮决议的集合,字母B表示一轮决议)_ proposer leader在Multi Paxos中还有助于提升性能,常态下统一由leader发起提议,可节省prepare步骤(leader不用问询acceptor曾接受过的ID最大的提议、只有leader提议也不需要acceptor进行promise)直至发生leader宕机、重新选主。 -**小结** +## **小结** 以上介绍了Paxos的推演过程、如何在Basic Paxos的基础上通过状态机构建Multi Paxos。Paxos协议比较“艰深晦涩”,但多读几遍论文一般能理解其内涵,更难的是如何将Paxos真正应用到工程实践。 @@ -155,4 +163,4 @@ proposer leader在Multi Paxos中还有助于提升性能,常态下统一由lea [《分布式系统理论基础 - 时间、时钟和事件顺序》](http://www.cnblogs.com/bangerlee/p/5448766.html) -[《分布式系统理论基础 - CAP》](http://www.cnblogs.com/bangerlee/p/5328888.html) \ No newline at end of file +[《分布式系统理论基础 - CAP》](http://www.cnblogs.com/bangerlee/p/5328888.html) diff --git "a/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232Raft\343\200\201Zab.md" "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232Raft\343\200\201Zab.md" index a03b394..a774ab2 100644 --- "a/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232Raft\343\200\201Zab.md" +++ "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232Raft\343\200\201Zab.md" @@ -1,3 +1,12 @@ +# Table of Contents + + * [**引言**](#引言) + * [**Raft**](#raft) + * [**Zab**](#zab) + * [**Paxos、Raft、Zab再比较**](#paxos、raft、zab再比较) + * [**小结**](#小结) + + 本文转自:[https://www.cnblogs.com/bangerlee/p/5991417.html](https://www.cnblogs.com/bangerlee/p/5991417.html) 本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看 @@ -22,7 +31,7 @@ [《分布式系统理论进阶 - Paxos》](http://www.cnblogs.com/bangerlee/p/5655754.html)介绍了一致性协议Paxos,今天我们来学习另外两个常见的一致性协议——Raft和Zab。通过与Paxos对比,了解Raft和Zab的核心思想、加深对一致性协议的认识。 -**Raft** +## **Raft** Paxos偏向于理论、对如何应用到工程实践提及较少。理解的难度加上现实的骨感,在生产环境中基于Paxos实现一个正确的分布式系统非常难[1]: @@ -51,7 +60,7 @@ Raft[2](#)在2013年提出,提出的时间虽然不长,但已经有很多系 Paxos中Leader的存在是为了提升决议效率,Leader的有无和数目并不影响决议一致性,Raft要求具备唯一Leader,并把一致性问题具体化为保持日志副本的一致性,以此实现相较Paxos而言更容易理解、更容易实现的目标。 -**Zab** +## **Zab** Zab[5](#)的全称是Zookeeper atomic broadcast protocol,是Zookeeper内部用到的一致性协议。相比Paxos,Zab最大的特点是保证强一致性(strong consistency,或叫线性一致性linearizable consistency)。 @@ -85,7 +94,7 @@ Zab中每个事务对应一个zxid,它由两部分组成:
Annotation[] annotations = field.getDeclaredAnnotations();
+Field field = ... //获取方法对象目录
+Annotation[] annotations = field.getDeclaredAnnotations();
for(Annotation annotation : annotations){
if(annotation instanceof MyAnnotation){
@@ -418,8 +418,8 @@ for(Annotation annotation : annotations){
你可以像这样访问指定的变量注解:
```
-Field field = ...//获取方法对象
-
+Field field = ...//获取方法对象目录
+
Annotation annotation = field.getAnnotation(MyAnnotation.class);
if(annotation instanceof MyAnnotation){
diff --git a/src/main/java/md/mdToc.java b/src/main/java/md/mdToc.java
index 6dbcab7..a5216f0 100644
--- a/src/main/java/md/mdToc.java
+++ b/src/main/java/md/mdToc.java
@@ -4,7 +4,7 @@
public class mdToc {
public static void main(String[] args) {
- String path = "D:\\idea_project\\javaTutorial\\docs\\database";
+ String path = "D:\\idea_project\\JavaTutorial\\docs\\distributed\\basic";
AtxMarkdownToc.newInstance().genTocDir(path);
}
}
From 33753f61770dfef23ad54e1e4342f54df88d7fb7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=BB=84=E5=B0=8F=E6=96=9C?= <362294931@qq.com>
Date: Sun, 9 Apr 2023 17:15:21 +0800
Subject: [PATCH 03/39] modify distributed mds
---
ReadMe.md | 2 +-
...06\350\256\272\346\200\273\347\273\223.md" | 11 ++++++-
...06\344\270\216\345\256\236\350\267\265.md" | 3 +-
...6\210\220Redis\347\274\223\345\255\230.md" | 2 ++
...01\347\250\213\350\257\246\350\247\243.md" | 30 ++++++++++++++++++-
...57\345\217\212\345\256\236\350\267\265.md" | 3 +-
...41\347\220\206\345\256\236\346\210\230.md" | 4 ++-
...03\345\274\217\344\272\213\345\212\241.md" | 1 +
...44\270\200\350\207\264\346\200\247hash.md" | 20 ++++++++++++-
...57\274\214Raft\347\256\227\346\263\225.md" | 4 ++-
...43\345\206\263\346\226\271\346\241\210.md" | 15 +++++++++-
...72\346\234\254\346\246\202\345\277\265.md" | 1 +
...0\203\346\234\215\345\212\241zookeeper.md" | 11 ++++++-
...03\345\274\217\344\272\213\345\212\241.md" | 16 ++++++++++
...6\201\257\346\212\200\346\234\257Kafka.md" | 17 ++++++++++-
...40\347\247\215\346\226\271\346\241\210.md" | 12 ++++++++
...40\344\275\225\350\200\214\347\224\237.md" | 4 +--
...60\347\232\204\345\245\227\350\267\257.md" | 3 +-
...37\346\210\220\346\226\271\346\241\210.md" | 23 ++++++++------
src/main/java/md/mdToc.java | 2 +-
20 files changed, 160 insertions(+), 24 deletions(-)
rename "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217ID\347\224\237\346\210\220\346\226\271\346\241\210.md" => "docs/distributed/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217ID\347\224\237\346\210\220\346\226\271\346\241\210.md" (94%)
diff --git a/ReadMe.md b/ReadMe.md
index 484bbda..ee75d4c 100644
--- a/ReadMe.md
+++ b/ReadMe.md
@@ -334,7 +334,7 @@ todo
[//]: # (* [搞懂分布式技术:Nginx负载均衡原理与实践 ]docs/distributed/practice/搞懂分布式技术:Nginx负载均衡原理与实践.md)
* [搞懂分布式技术:LVS实现负载均衡的原理与实践 ](docs/distributed/practice/搞懂分布式技术:LVS实现负载均衡的原理与实践.md )
* [搞懂分布式技术:分布式session解决方案与一致性hash](docs/distributed/practice/搞懂分布式技术:分布式session解决方案与一致性hash.md)
-* [搞懂分布式技术:分布式ID生成方案 ](docs/distributed/practice/搞懂分布式技术:分布式ID生成方案.md )
+* [搞懂分布式技术:分布式ID生成方案 ](docs/distributed/搞懂分布式技术:分布式ID生成方案.md )
* [搞懂分布式技术:缓存的那些事](docs/distributed/practice/搞懂分布式技术:缓存的那些事.md)
* [搞懂分布式技术:SpringBoot使用注解集成Redis缓存](docs/distributed/practice/搞懂分布式技术:SpringBoot使用注解集成Redis缓存.md)
* [搞懂分布式技术:缓存更新的套路 ](docs/distributed/practice/搞懂分布式技术:缓存更新的套路.md )
diff --git "a/docs/distributed/practice/\345\210\206\345\270\203\345\274\217\347\220\206\350\256\272\346\200\273\347\273\223.md" "b/docs/distributed/practice/\345\210\206\345\270\203\345\274\217\347\220\206\350\256\272\346\200\273\347\273\223.md"
index ff2647f..d7b5027 100644
--- "a/docs/distributed/practice/\345\210\206\345\270\203\345\274\217\347\220\206\350\256\272\346\200\273\347\273\223.md"
+++ "b/docs/distributed/practice/\345\210\206\345\270\203\345\274\217\347\220\206\350\256\272\346\200\273\347\273\223.md"
@@ -1,3 +1,12 @@
+# Table of Contents
+
+ * [六、Raft](#六、raft)
+ * [单个 Candidate 的竞选](#单个-candidate-的竞选)
+ * [多个 Candidate 竞选](#多个-candidate-竞选)
+ * [数据同步](#数据同步)
+ * [参考](#参考)
+
+
## 六、Raft
Raft 也是分布式一致性协议,主要是用来竞选主节点。
@@ -63,4 +72,4 @@ Raft 也是分布式一致性协议,主要是用来竞选主节点。
- [深入理解分布式事务](https://juejin.im/entry/577c6f220a2b5800573492be)
- [What is CAP theorem in distributed database system?](http://www.colooshiki.com/index.php/2017/04/20/what-is-cap-theorem-in-distributed-database-system/)
- [NEAT ALGORITHMS - PAXOS](http://harry.me/blog/2014/12/27/neat-algorithms-paxos/)
-- [Paxos By Example](https://angus.nyc/2012/paxos-by-example/)
\ No newline at end of file
+- [Paxos By Example](https://angus.nyc/2012/paxos-by-example/)
diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232LVS\345\256\236\347\216\260\350\264\237\350\275\275\345\235\207\350\241\241\347\232\204\345\216\237\347\220\206\344\270\216\345\256\236\350\267\265.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232LVS\345\256\236\347\216\260\350\264\237\350\275\275\345\235\207\350\241\241\347\232\204\345\216\237\347\220\206\344\270\216\345\256\236\350\267\265.md"
index 29837ba..6983151 100644
--- "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232LVS\345\256\236\347\216\260\350\264\237\350\275\275\345\235\207\350\241\241\347\232\204\345\216\237\347\220\206\344\270\216\345\256\236\350\267\265.md"
+++ "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232LVS\345\256\236\347\216\260\350\264\237\350\275\275\345\235\207\350\241\241\347\232\204\345\216\237\347\220\206\344\270\216\345\256\236\350\267\265.md"
@@ -1,3 +1,4 @@
+
# 目录
* [负载均衡的原理](#负载均衡的原理)
@@ -555,4 +556,4 @@ public class TestIpHash {
}
}
-````
\ No newline at end of file
+````
diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232SpringBoot\344\275\277\347\224\250\346\263\250\350\247\243\351\233\206\346\210\220Redis\347\274\223\345\255\230.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232SpringBoot\344\275\277\347\224\250\346\263\250\350\247\243\351\233\206\346\210\220Redis\347\274\223\345\255\230.md"
index 5bc10ee..adb2c2c 100644
--- "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232SpringBoot\344\275\277\347\224\250\346\263\250\350\247\243\351\233\206\346\210\220Redis\347\274\223\345\255\230.md"
+++ "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232SpringBoot\344\275\277\347\224\250\346\263\250\350\247\243\351\233\206\346\210\220Redis\347\274\223\345\255\230.md"
@@ -1,3 +1,5 @@
+
+
# 目录
* [Redis配置](#redis配置)
diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232ZAB\345\215\217\350\256\256\346\246\202\350\277\260\344\270\216\351\200\211\344\270\273\346\265\201\347\250\213\350\257\246\350\247\243.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232ZAB\345\215\217\350\256\256\346\246\202\350\277\260\344\270\216\351\200\211\344\270\273\346\265\201\347\250\213\350\257\246\350\247\243.md"
index 01a7be8..4a62581 100644
--- "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232ZAB\345\215\217\350\256\256\346\246\202\350\277\260\344\270\216\351\200\211\344\270\273\346\265\201\347\250\213\350\257\246\350\247\243.md"
+++ "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232ZAB\345\215\217\350\256\256\346\246\202\350\277\260\344\270\216\351\200\211\344\270\273\346\265\201\347\250\213\350\257\246\350\247\243.md"
@@ -1,3 +1,31 @@
+# Table of Contents
+
+ * [ZAB协议](#zab协议)
+ * [消息广播模式](#消息广播模式)
+ * [崩溃恢复](#崩溃恢复)
+ * [数据同步](#数据同步)
+ * [ZAB协议原理](#zab协议原理)
+ * [Zookeeper设计目标](#zookeeper设计目标)
+* [ZAB与FastLeaderElection选主算法流程详解](#zab与fastleaderelection选主算法流程详解)
+ * [选择机制中的概念](#选择机制中的概念)
+ * [服务器ID](#服务器id)
+ * [数据ID](#数据id)
+ * [逻辑时钟](#逻辑时钟)
+ * [选举状态](#选举状态)
+ * [选举消息内容](#选举消息内容)
+ * [选举流程图](#选举流程图)
+ * [判断是否已经胜出](#判断是否已经胜出)
+ * [选举流程简述](#选举流程简述)
+ * [几种领导选举场景](#几种领导选举场景)
+ * [集群启动领导选举](#集群启动领导选举)
+ * [Follower重启](#follower重启)
+ * [Leader重启](#leader重启)
+* [一致性保证](#一致性保证)
+ * [Commit过的数据不丢失](#commit过的数据不丢失)
+ * [未Commit过的消息对客户端不可见")未Commit过的消息对客户端不可见](#未commit过的消息对客户端不可见未commit过的消息对客户端不可见)
+* [总结](#总结)
+
+
本文内容参考网络,侵删
本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看
@@ -348,4 +376,4 @@ ZAB协议保证了在Leader选举的过程中,已经被Commit的数据不会
* 由于使用主从复制模式,所有的写操作都要由Leader主导完成,而读操作可通过任意节点完成,因此Zookeeper读性能远好于写性能,更适合读多写少的场景
* 虽然使用主从复制模式,同一时间只有一个Leader,但是Failover机制保证了集群不存在单点失败(SPOF)的问题
* ZAB协议保证了Failover过程中的数据一致性
-* 服务器收到数据后先写本地文件再进行处理,保证了数据的持久性
\ No newline at end of file
+* 服务器收到数据后先写本地文件再进行处理,保证了数据的持久性
diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232Zookeeper\345\205\270\345\236\213\345\272\224\347\224\250\345\234\272\346\231\257\345\217\212\345\256\236\350\267\265.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232Zookeeper\345\205\270\345\236\213\345\272\224\347\224\250\345\234\272\346\231\257\345\217\212\345\256\236\350\267\265.md"
index 7e5a1bf..e007cd6 100644
--- "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232Zookeeper\345\205\270\345\236\213\345\272\224\347\224\250\345\234\272\346\231\257\345\217\212\345\256\236\350\267\265.md"
+++ "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232Zookeeper\345\205\270\345\236\213\345\272\224\347\224\250\345\234\272\346\231\257\345\217\212\345\256\236\350\267\265.md"
@@ -1,3 +1,4 @@
+
# 目录
* [一.ZooKeeper典型应用场景实践](#一zookeeper典型应用场景实践)
@@ -479,4 +480,4 @@ Master选举
第二类,和分布式锁服务中的控制时序场景基本原理一致,入列有编号,出列按编号。
-同步队列。一个job由多个task组成,只有所有任务完成后,job才运行完成。可为job创建一个/job目录,然后在该目录下,为每个完成的task创建一个临时znode,一旦临时节点数目达到task总数,则job运行完成。
\ No newline at end of file
+同步队列。一个job由多个task组成,只有所有任务完成后,job才运行完成。可为job创建一个/job目录,然后在该目录下,为每个完成的task创建一个临时znode,一旦临时节点数目达到task总数,则job运行完成。
diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232Zookeeper\347\232\204\351\205\215\347\275\256\344\270\216\351\233\206\347\276\244\347\256\241\347\220\206\345\256\236\346\210\230.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232Zookeeper\347\232\204\351\205\215\347\275\256\344\270\216\351\233\206\347\276\244\347\256\241\347\220\206\345\256\236\346\210\230.md"
index 70fce53..a810400 100644
--- "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232Zookeeper\347\232\204\351\205\215\347\275\256\344\270\216\351\233\206\347\276\244\347\256\241\347\220\206\345\256\236\346\210\230.md"
+++ "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232Zookeeper\347\232\204\351\205\215\347\275\256\344\270\216\351\233\206\347\276\244\347\256\241\347\220\206\345\256\236\346\210\230.md"
@@ -1,3 +1,5 @@
+
+
# 目录
* [4.1 配置文件](#41-配置文件)
@@ -347,4 +349,4 @@ server.3=127.0.0.1:2890:3890
)
-可见,关闭zk3以后,由于集群中的可用Server只剩下一台(达不到集群总数的半数以上),**集群将处于不可用的状态。**
\ No newline at end of file
+可见,关闭zk3以后,由于集群中的可用Server只剩下一台(达不到集群总数的半数以上),**集群将处于不可用的状态。**
diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\344\275\277\347\224\250RocketMQ\344\272\213\345\212\241\346\266\210\346\201\257\350\247\243\345\206\263\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\344\275\277\347\224\250RocketMQ\344\272\213\345\212\241\346\266\210\346\201\257\350\247\243\345\206\263\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md"
index 15d55a7..decea79 100644
--- "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\344\275\277\347\224\250RocketMQ\344\272\213\345\212\241\346\266\210\346\201\257\350\247\243\345\206\263\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md"
+++ "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\344\275\277\347\224\250RocketMQ\344\272\213\345\212\241\346\266\210\346\201\257\350\247\243\345\206\263\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md"
@@ -1,3 +1,4 @@
+
# 目录
* [初步认识RocketMQ的核心模块](#初步认识rocketmq的核心模块)
diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217session\350\247\243\345\206\263\346\226\271\346\241\210\344\270\216\344\270\200\350\207\264\346\200\247hash.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217session\350\247\243\345\206\263\346\226\271\346\241\210\344\270\216\344\270\200\350\207\264\346\200\247hash.md"
index 08a10af..2c8510e 100644
--- "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217session\350\247\243\345\206\263\346\226\271\346\241\210\344\270\216\344\270\200\350\207\264\346\200\247hash.md"
+++ "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217session\350\247\243\345\206\263\346\226\271\346\241\210\344\270\216\344\270\200\350\207\264\346\200\247hash.md"
@@ -1,3 +1,21 @@
+# Table of Contents
+
+* [一、问题的提出](#一、问题的提出)
+ * [1. 什么是Session?](#1-什么是session?)
+ * [2. 什么是Session一致性问题?](#2-什么是session一致性问题?)
+* [二、Session一致性解决方案](#二、session一致性解决方案)
+ * [1. Session Stiky](#1-session-stiky)
+ * [2. Session Replication](#2-session-replication)
+ * [3. Session数据集中存储](#3-session数据集中存储)
+ * [4. Cookie Based](#4-cookie-based)
+* [三、总结](#三、总结)
+ * [一致性Hash概述](#一致性hash概述)
+ * [一致性hash的特性](#一致性hash的特性)
+ * [虚拟节点](#虚拟节点)
+ * [均匀一致性hash](#均匀一致性hash)
+ * [总结](#总结)
+
+
本文内容参考网络,侵删
@@ -182,4 +200,4 @@ hash环上顺时针从整数0开始,一直到最大正整数,我们根据四
## 总结
-在分布式系统中一致性hash起着不可忽略的地位,无论是分布式缓存,还是分布式Rpc框架的负载均衡策略都有所使用。
\ No newline at end of file
+在分布式系统中一致性hash起着不可忽略的地位,无论是分布式缓存,还是分布式Rpc框架的负载均衡策略都有所使用。
diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217\344\270\200\350\207\264\346\200\247\345\215\217\350\256\256\344\270\216Paxos\357\274\214Raft\347\256\227\346\263\225.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217\344\270\200\350\207\264\346\200\247\345\215\217\350\256\256\344\270\216Paxos\357\274\214Raft\347\256\227\346\263\225.md"
index 18256b0..c4a809d 100644
--- "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217\344\270\200\350\207\264\346\200\247\345\215\217\350\256\256\344\270\216Paxos\357\274\214Raft\347\256\227\346\263\225.md"
+++ "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217\344\270\200\350\207\264\346\200\247\345\215\217\350\256\256\344\270\216Paxos\357\274\214Raft\347\256\227\346\263\225.md"
@@ -1,3 +1,5 @@
+
+
# 目录
* [2PC](#2pc)
@@ -481,4 +483,4 @@ Leader 会等待大多数的 Follower 也进行了修改,然后才将修改提
What is CAP theorem in distributed database system?
NEAT ALGORITHMS - PAXOS
Raft: Understandable Distributed Consensus
- Paxos By Example
\ No newline at end of file
+ Paxos By Example
diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241\345\270\270\347\224\250\350\247\243\345\206\263\346\226\271\346\241\210.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241\345\270\270\347\224\250\350\247\243\345\206\263\346\226\271\346\241\210.md"
index fde3361..21a891b 100644
--- "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241\345\270\270\347\224\250\350\247\243\345\206\263\346\226\271\346\241\210.md"
+++ "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241\345\270\270\347\224\250\350\247\243\345\206\263\346\226\271\346\241\210.md"
@@ -1,3 +1,16 @@
+# Table of Contents
+
+* [一、概述](#一、概述)
+* [二、理论](#二、理论)
+ * [2.1、二阶段提交](#21、二阶段提交)
+ * [2.2、三阶段提交](#22、三阶段提交)
+ * [2.3、TCC柔性事务](#23、tcc柔性事务)
+ * [2.4、Seata](#24、seata)
+* [三、应用场景](#三、应用场景)
+* [四、总结](#四、总结)
+* [五、参考源码](#五、参考源码)
+
+
> 数据不会无缘无故丢失,也不会莫名其妙增加
@@ -155,4 +168,4 @@ CREATE TABLE `tb_notice_message` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT
编程文档:https://gitee.com/cicadasmile/butte-java-note应用仓库:https://gitee.com/cicadasmile/butte-flyer-parent
```
-本文转载自 https://mp.weixin.qq.com/s/xa9Giv9xdSM3AahwN3WckQ
\ No newline at end of file
+本文转载自 https://mp.weixin.qq.com/s/xa9Giv9xdSM3AahwN3WckQ
diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\232\204\344\270\200\344\272\233\345\237\272\346\234\254\346\246\202\345\277\265.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\232\204\344\270\200\344\272\233\345\237\272\346\234\254\346\246\202\345\277\265.md"
index d364788..e3e51ac 100644
--- "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\232\204\344\270\200\344\272\233\345\237\272\346\234\254\346\246\202\345\277\265.md"
+++ "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\232\204\344\270\200\344\272\233\345\237\272\346\234\254\346\246\202\345\277\265.md"
@@ -1,3 +1,4 @@
+
# 目录
* [1、分布式](#1、分布式)
* [2、集群(Cluster)](#2、集群(cluster))
diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\235\346\216\242\345\210\206\345\270\203\345\274\217\345\215\217\350\260\203\346\234\215\345\212\241zookeeper.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\235\346\216\242\345\210\206\345\270\203\345\274\217\345\215\217\350\260\203\346\234\215\345\212\241zookeeper.md"
index f25a7d8..f8699df 100644
--- "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\235\346\216\242\345\210\206\345\270\203\345\274\217\345\215\217\350\260\203\346\234\215\345\212\241zookeeper.md"
+++ "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\235\346\216\242\345\210\206\345\270\203\345\274\217\345\215\217\350\260\203\346\234\215\345\212\241zookeeper.md"
@@ -1,3 +1,12 @@
+# Table of Contents
+
+* [目录](#目录)
+ * [小梁的邮件](#小梁的邮件)
+ * [小王的Master选举](#小王的master选举)
+ * [小蔡的分布式锁](#小蔡的分布式锁)
+ * [Zookeeper](#zookeeper)
+
+
# 目录
本文转自:微信公众号【码农翻身】
@@ -152,4 +161,4 @@ Zookeeper 所使用的树形结构和自己想象的非常类似,更重要的
_后记:本文从使用者的角度描述了Zookeeper有什么用处,至于它内部是如何工作,那是另外一个Big topic了,我们以后再讲。___
-(完)
\ No newline at end of file
+(完)
diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\265\205\346\236\220\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\265\205\346\236\220\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md"
index a8b04d7..147a92e 100644
--- "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\265\205\346\236\220\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md"
+++ "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\265\205\346\236\220\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md"
@@ -1,3 +1,19 @@
+# Table of Contents
+
+* [目录](#目录)
+ * [什么是事务?](#什么是事务?)
+ * [事务的四大特性 ACID](#事务的四大特性-acid)
+ * [事务的隔离级别](#事务的隔离级别)
+ * [事务并发执行会出现的问题](#事务并发执行会出现的问题)
+ * [数据库的四种隔离级别](#数据库的四种隔离级别)
+ * [什么是分布式事务?](#什么是分布式事务?)
+ * [CAP理论](#cap理论)
+ * [BASE理论](#base理论)
+ * [分布式事务协议](#分布式事务协议)
+ * [2PC](#2pc)
+ * [3PC](#3pc)
+
+
# 目录
本文转载自 linkedkeeper.com
diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\346\266\210\346\201\257\346\212\200\346\234\257Kafka.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\346\266\210\346\201\257\346\212\200\346\234\257Kafka.md"
index 36240f2..7e54e71 100644
--- "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\346\266\210\346\201\257\346\212\200\346\234\257Kafka.md"
+++ "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\346\266\210\346\201\257\346\212\200\346\234\257Kafka.md"
@@ -1,3 +1,18 @@
+# Table of Contents
+
+* [目录](#目录)
+ * [**Kafka的基本介绍**](#kafka的基本介绍)
+ * [**Kafka的设计原理分析**](#kafka的设计原理分析)
+ * [**Kafka数据传输的事务特点**](#kafka数据传输的事务特点)
+ * [**Kafka消息存储格式**](#kafka消息存储格式)
+ * [**副本(replication)策略**](#副本(replication)策略)
+ * [**Kafka消息分组,消息消费原理**](#kafka消息分组,消息消费原理)
+ * [**Push vs. Pull**](#push-vs-pull)
+ * [**Kafak顺序写入与数据读取**](#kafak顺序写入与数据读取)
+ * [**消费者(读取数据)**](#消费者(读取数据))
+ * [**Reference**](#reference)
+
+
# 目录
本文转载自 linkedkeeper.com
@@ -281,4 +296,4 @@ https://my.oschina.net/silence88/blog/856195
https://toutiao.io/posts/508935/app_preview
-转载请并标注: “本文转载自 linkedkeeper.com ”
\ No newline at end of file
+转载请并标注: “本文转载自 linkedkeeper.com ”
diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\351\224\201\347\232\204\345\207\240\347\247\215\346\226\271\346\241\210.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\351\224\201\347\232\204\345\207\240\347\247\215\346\226\271\346\241\210.md"
index 904e4b9..701bde3 100644
--- "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\351\224\201\347\232\204\345\207\240\347\247\215\346\226\271\346\241\210.md"
+++ "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\351\224\201\347\232\204\345\207\240\347\247\215\346\226\271\346\241\210.md"
@@ -1,3 +1,15 @@
+# Table of Contents
+
+* [目录](#目录)
+ * [前言](#前言)
+ * [分布式一致性问题](#分布式一致性问题)
+ * [分布式锁需要具备哪些条件](#分布式锁需要具备哪些条件)
+ * [分布式锁实现方式](#分布式锁实现方式)
+ * [解决上述问题有两种方案](#解决上述问题有两种方案)
+ * [zookeeper分布式锁](#zookeeper分布式锁)
+ * [小结](#小结)
+
+
# 目录
本文内容参考网络,侵删
diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\266\210\346\201\257\351\230\237\345\210\227\345\233\240\344\275\225\350\200\214\347\224\237.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\266\210\346\201\257\351\230\237\345\210\227\345\233\240\344\275\225\350\200\214\347\224\237.md"
index c2dd051..b47f00d 100644
--- "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\266\210\346\201\257\351\230\237\345\210\227\345\233\240\344\275\225\350\200\214\347\224\237.md"
+++ "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\266\210\346\201\257\351\230\237\345\210\227\345\233\240\344\275\225\350\200\214\347\224\237.md"
@@ -1,5 +1,5 @@
-#目录
+# 目录
* [何时需要消息队列](#何时需要消息队列)
* [解耦](#解耦)
* [最终一致性](#最终一致性)
@@ -404,4 +404,4 @@ Future future = request(server);//server立刻返回future return future
# 总结
-本文从为何使用消息队列开始讲起,然后主要介绍了如何从零开始设计一个消息队列,包括RPC、事务、最终一致性、广播、消息确认等关键问题。并对消息队列的push、pull模型做了简要分析,最后从批量和异步角度,分析了消息队列性能优化的思路。下篇会着重介绍一些高级话题,如存储系统的设计、流控和错峰的设计、公平调度等。希望通过这些,让大家对消息队列有个提纲挈领的整体认识,并给自主开发消息队列提供思路。另外,本文主要是源自自己在开发消息队列中的思考和读源码时的体会,比较不"官方",也难免会存在一些漏洞,欢迎大家多多交流。
\ No newline at end of file
+本文从为何使用消息队列开始讲起,然后主要介绍了如何从零开始设计一个消息队列,包括RPC、事务、最终一致性、广播、消息确认等关键问题。并对消息队列的push、pull模型做了简要分析,最后从批量和异步角度,分析了消息队列性能优化的思路。下篇会着重介绍一些高级话题,如存储系统的设计、流控和错峰的设计、公平调度等。希望通过这些,让大家对消息队列有个提纲挈领的整体认识,并给自主开发消息队列提供思路。另外,本文主要是源自自己在开发消息队列中的思考和读源码时的体会,比较不"官方",也难免会存在一些漏洞,欢迎大家多多交流。
diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\347\274\223\345\255\230\346\233\264\346\226\260\347\232\204\345\245\227\350\267\257.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\347\274\223\345\255\230\346\233\264\346\226\260\347\232\204\345\245\227\350\267\257.md"
index 61ed18f..77fc50a 100644
--- "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\347\274\223\345\255\230\346\233\264\346\226\260\347\232\204\345\245\227\350\267\257.md"
+++ "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\347\274\223\345\255\230\346\233\264\346\226\260\347\232\204\345\245\227\350\267\257.md"
@@ -1,3 +1,4 @@
+
# 目录
* [缓存更新的套路](#缓存更新的套路)
@@ -106,4 +107,4 @@ Write Back套路,一句说就是,在更新数据的时候,只更新缓存
4)上面,我们没有考虑缓存(Cache)和持久层(Repository)的整体事务的问题。比如,更新Cache成功,更新数据库失败了怎么吗?或是反过来。关于这个事,如果你需要强一致性,你需要使用“两阶段提交协议”——prepare, commit/rollback,比如Java 7 的[XAResource](http://docs.oracle.com/javaee/7/api/javax/transaction/xa/XAResource.html),还有MySQL 5.7的 [XA Transaction](http://dev.mysql.com/doc/refman/5.7/en/xa.html),有些cache也支持XA,比如[EhCache](http://www.ehcache.org/documentation/3.0/xa.html)。当然,XA这样的强一致性的玩法会导致性能下降,关于分布式的事务的相关话题,你可以看看《[分布式系统的事务处理](https://coolshell.cn/articles/10910.html)》一文。
-(全文完)
\ No newline at end of file
+(全文完)
diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217ID\347\224\237\346\210\220\346\226\271\346\241\210.md" "b/docs/distributed/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217ID\347\224\237\346\210\220\346\226\271\346\241\210.md"
similarity index 94%
rename from "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217ID\347\224\237\346\210\220\346\226\271\346\241\210.md"
rename to "docs/distributed/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217ID\347\224\237\346\210\220\346\226\271\346\241\210.md"
index 2ea07c4..95caec7 100644
--- "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217ID\347\224\237\346\210\220\346\226\271\346\241\210.md"
+++ "b/docs/distributed/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217ID\347\224\237\346\210\220\346\226\271\346\241\210.md"
@@ -1,6 +1,12 @@
-# 目录
+# Table of Contents
+
+ * [**一、需求缘起**](#一、需求缘起)
+ * [**二、常见方法、不足与优化**](#二、常见方法、不足与优化)
+ * [**方法二:单点批量ID生成服务**](#方法二:单点批量id生成服务)
+ * [**方法三:uuid/guid**](#方法三:uuidguid)
+ * [**方法四:取当前毫秒数**](#方法四:取当前毫秒数)
+
-* [分布式ID生成器 | 架构师之路](#分布式id生成器--架构师之路)
本文内容参考网络,侵删
@@ -19,11 +25,10 @@
如果对本系列文章有什么建议,或者是有什么疑问的话,也可以关注公众号【Java技术江湖】联系作者,欢迎你参与本系列博文的创作和修订。
-## 分布式ID生成器 | 架构师之路
转自:58沈剑架构师之路2017-06-25
-**一、需求缘起**
+## **一、需求缘起**
几乎所有的业务系统,都有生成一个唯一记录标识的需求,例如:
@@ -65,7 +70,7 @@ select message-id/ (order by message-id)/limit 100
这也是本文要讨论的核心问题:**如何高效生成趋势有序的全局唯一ID。**
-**二、常见方法、不足与优化**
+## **二、常见方法、不足与优化**
**方法一:使用数据库的auto_increment来生成全局唯一递增ID**
@@ -103,7 +108,7 @@ select message-id/ (order by message-id)/limit 100
为了解决上述两个问题,引出了第二个常见的方案。
-**方法二:单点批量ID生成服务**
+## **方法二:单点批量ID生成服务**
分布式系统之所以难,很重要的原因之一是“没有一个全局时钟,难以保证绝对的时序”,要想保证绝对的时序,还是只能使用单点服务,用本地时钟保证“绝对时序”。
@@ -143,7 +148,7 @@ ID生成服务假设每次批量拉取6个ID,服务访问数据库,将当前
另外,ID-gen-service也可以实施水平扩展,以解决上述缺点(3),但会引发一致性问题,具体解决方案详见《》。
-**方法三:uuid/guid**
+## **方法三:uuid/guid**
不管是通过数据库,还是通过服务来生成ID,业务方Application都需要进行一次远程调用,比较耗时。
@@ -165,7 +170,7 @@ string ID =GenUUID();
* uuid过长,往往用字符串表示,作为主键建立索引查询效率低,常见优化方案为“转化为两个uint64整数存储”或者“折半存储”(折半后不能保证唯一性)
-**方法四:取当前毫秒数**
+## **方法四:取当前毫秒数**
uuid是一个本地算法,生成性能高,但无法保证趋势递增,且作为字符串ID检索效率低,有没有一种能保证递增的本地算法呢?
@@ -237,4 +242,4 @@ snowflake是twitter开源的分布式ID生成算法,其**核心思想为,**
**缺点**:
-* 由于“没有一个全局时钟”,每台服务器分配的ID是绝对递增的,但从全局看,生成的ID只是趋势递增的(有些服务器的时间早,有些服务器的时间晚)
\ No newline at end of file
+* 由于“没有一个全局时钟”,每台服务器分配的ID是绝对递增的,但从全局看,生成的ID只是趋势递增的(有些服务器的时间早,有些服务器的时间晚)
diff --git a/src/main/java/md/mdToc.java b/src/main/java/md/mdToc.java
index a5216f0..f449fef 100644
--- a/src/main/java/md/mdToc.java
+++ b/src/main/java/md/mdToc.java
@@ -4,7 +4,7 @@
public class mdToc {
public static void main(String[] args) {
- String path = "D:\\idea_project\\JavaTutorial\\docs\\distributed\\basic";
+ String path = "D:\\idea_project\\JavaTutorial\\docs\\distributed\\practice\\temp";
AtxMarkdownToc.newInstance().genTocDir(path);
}
}
From a157e8e8bcd13569a8213dee30d22c5865a292b5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=BB=84=E5=B0=8F=E6=96=9C?= <362294931@qq.com>
Date: Sun, 9 Apr 2023 17:16:51 +0800
Subject: [PATCH 04/39] modify distributed mds
---
ReadMe.md | 4 ++--
...47\224\237\346\210\220\346\226\271\346\241\210.md" | 0
...45\256\236\350\267\265\346\200\273\347\273\223.md" | 11 -----------
...47\220\206\350\256\272\346\200\273\347\273\223.md" | 0
4 files changed, 2 insertions(+), 13 deletions(-)
rename "docs/distributed/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217ID\347\224\237\346\210\220\346\226\271\346\241\210.md" => "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217ID\347\224\237\346\210\220\346\226\271\346\241\210.md" (100%)
rename "docs/distributed/practice/\345\210\206\345\270\203\345\274\217\347\220\206\350\256\272\346\200\273\347\273\223.md" => "docs/distributed/\345\210\206\345\270\203\345\274\217\347\220\206\350\256\272\346\200\273\347\273\223.md" (100%)
diff --git a/ReadMe.md b/ReadMe.md
index ee75d4c..dc53ae6 100644
--- a/ReadMe.md
+++ b/ReadMe.md
@@ -317,7 +317,7 @@ todo
* [分布式系统理论进阶:Paxos变种和优化 ](docs/distributed/basic/分布式系统理论进阶:Paxos变种和优化.md)
* [分布式系统理论基础:zookeeper分布式协调服务 ](docs/distributed/basic/分布式系统理论基础:zookeeper分布式协调服务.md)
-* [分布式技术实践总结](docs/distributed/practice/分布式理论总结.md)
+* [分布式技术实践总结](docs/distributed/分布式理论总结.md)
### 技术
* [搞懂分布式技术:分布式系统的一些基本概念](docs/distributed/practice/搞懂分布式技术:分布式系统的一些基本概念.md )
@@ -334,7 +334,7 @@ todo
[//]: # (* [搞懂分布式技术:Nginx负载均衡原理与实践 ]docs/distributed/practice/搞懂分布式技术:Nginx负载均衡原理与实践.md)
* [搞懂分布式技术:LVS实现负载均衡的原理与实践 ](docs/distributed/practice/搞懂分布式技术:LVS实现负载均衡的原理与实践.md )
* [搞懂分布式技术:分布式session解决方案与一致性hash](docs/distributed/practice/搞懂分布式技术:分布式session解决方案与一致性hash.md)
-* [搞懂分布式技术:分布式ID生成方案 ](docs/distributed/搞懂分布式技术:分布式ID生成方案.md )
+* [搞懂分布式技术:分布式ID生成方案 ](docs/distributed/practice/搞懂分布式技术:分布式ID生成方案.md )
* [搞懂分布式技术:缓存的那些事](docs/distributed/practice/搞懂分布式技术:缓存的那些事.md)
* [搞懂分布式技术:SpringBoot使用注解集成Redis缓存](docs/distributed/practice/搞懂分布式技术:SpringBoot使用注解集成Redis缓存.md)
* [搞懂分布式技术:缓存更新的套路 ](docs/distributed/practice/搞懂分布式技术:缓存更新的套路.md )
diff --git "a/docs/distributed/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217ID\347\224\237\346\210\220\346\226\271\346\241\210.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217ID\347\224\237\346\210\220\346\226\271\346\241\210.md"
similarity index 100%
rename from "docs/distributed/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217ID\347\224\237\346\210\220\346\226\271\346\241\210.md"
rename to "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217ID\347\224\237\346\210\220\346\226\271\346\241\210.md"
diff --git "a/docs/distributed/\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\345\256\236\350\267\265\346\200\273\347\273\223.md" "b/docs/distributed/\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\345\256\236\350\267\265\346\200\273\347\273\223.md"
index d73b1e8..8fb1dc1 100644
--- "a/docs/distributed/\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\345\256\236\350\267\265\346\200\273\347\273\223.md"
+++ "b/docs/distributed/\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\345\256\236\350\267\265\346\200\273\347\273\223.md"
@@ -25,17 +25,6 @@
* [好了,最后是数据库层](#好了,最后是数据库层)
* [总结](#总结)
-
-
----
-title: 分布式技术实践总结
-date: 2018-07-08 22:15:36
-tags:
-- 分布式系统
- categories:
-- 后端
-- 技术总结
----
本文基于之前的分布式系统理论系列文章总结而成,本部分主要是实践内容,详细内容可见我的专栏:分布式系统理论与实践
https://blog.csdn.net/column/details/24090.html
diff --git "a/docs/distributed/practice/\345\210\206\345\270\203\345\274\217\347\220\206\350\256\272\346\200\273\347\273\223.md" "b/docs/distributed/\345\210\206\345\270\203\345\274\217\347\220\206\350\256\272\346\200\273\347\273\223.md"
similarity index 100%
rename from "docs/distributed/practice/\345\210\206\345\270\203\345\274\217\347\220\206\350\256\272\346\200\273\347\273\223.md"
rename to "docs/distributed/\345\210\206\345\270\203\345\274\217\347\220\206\350\256\272\346\200\273\347\273\223.md"
From 0de98139346d866e2f40af3170994567f6defaa2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=BB=84=E5=B0=8F=E6=96=9C?= <362294931@qq.com>
Date: Sun, 9 Apr 2023 17:19:22 +0800
Subject: [PATCH 05/39] modify mds toc
---
...207\357\274\232\344\273\200\344\271\210\346\230\257Redis.md" | 2 +-
...\215\256\347\273\223\346\236\204\346\246\202\350\247\210.md" | 2 +-
...\216ACID\347\211\271\346\200\247\344\273\213\347\273\215.md" | 2 +-
...\204\350\257\246\350\247\243\342\200\224\342\200\224dict.md" | 2 +-
...04\350\257\246\350\247\243\342\200\224\342\200\224intset.md" | 2 +-
...350\257\246\350\247\243\342\200\224\342\200\224quicklist.md" | 2 +-
...6\204\350\257\246\350\247\243\342\200\224\342\200\224sds.md" | 2 +-
...\350\257\246\350\247\243\342\200\224\342\200\224skiplist.md" | 2 +-
...4\350\257\246\350\247\243\342\200\224\342\200\224ziplist.md" | 2 +-
...\274\217\351\224\201\350\277\233\345\214\226\345\217\262.md" | 2 +-
...\236\204\346\274\224\350\277\233\345\256\236\344\276\213.md" | 2 +-
...\214\226\345\210\260\347\241\254\347\233\230\344\270\255.md" | 2 +-
...\234\237\345\210\240\351\231\244\347\255\226\347\225\245.md" | 2 +-
...220Redis\344\270\273\344\273\216\345\244\215\345\210\266.md" | 2 +-
...\204\346\225\260\346\215\256\347\273\223\346\236\204robj.md" | 2 +-
"docs/cs/algorithms/\345\211\221\346\214\207offer.md" | 2 +-
...\273\234\345\255\246\344\271\240\346\200\273\347\273\223.md" | 2 +-
...\273\244\345\255\246\344\271\240\346\200\273\347\273\223.md" | 2 +-
...\273\237\345\255\246\344\271\240\346\200\273\347\273\223.md" | 2 +-
...\222\214\351\224\201\347\232\204\345\205\263\347\263\273.md" | 2 +-
...\202\243\344\272\233\346\227\245\345\277\227\344\273\254.md" | 2 +-
...\215\256\345\255\230\345\202\250\345\216\237\347\220\206.md" | 2 +-
...\206\350\256\272\345\237\272\347\241\200 \357\274\232CAP.md" | 2 +-
...\200\350\207\264\346\200\247\343\200\201PC\345\222\214PC.md" | 2 +-
...\222\214\344\272\213\344\273\266\351\241\272\345\272\217.md" | 2 +-
...206\350\256\272\345\237\272\347\241\200\357\274\232Paxos.md" | 2 +-
...2\345\237\272\347\241\200\357\274\232Raft\343\200\201Zab.md" | 2 +-
...\274\217\345\215\217\350\260\203\346\234\215\345\212\241.md" | 2 +-
...\225\260\346\264\276\345\222\214\347\247\237\347\272\246.md" | 2 +-
...\217\230\347\247\215\345\222\214\344\274\230\345\214\226.md" | 2 +-
...\270\273\346\265\201\347\250\213\350\257\246\350\247\243.md" | 2 +-
...74\217ID\347\224\237\346\210\220\346\226\271\346\241\210.md" | 2 +-
...\210\344\270\216\344\270\200\350\207\264\346\200\247hash.md" | 2 +-
...\224\250\350\247\243\345\206\263\346\226\271\346\241\210.md" | 2 +-
...345\215\217\350\260\203\346\234\215\345\212\241zookeeper.md" | 2 +-
...\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" | 2 +-
...217\346\266\210\346\201\257\346\212\200\346\234\257Kafka.md" | 2 +-
...\232\204\345\207\240\347\247\215\346\226\271\346\241\210.md" | 2 +-
...\274\217\347\220\206\350\256\272\346\200\273\347\273\223.md" | 2 +-
...\210\260\345\210\206\345\270\203\345\274\217\357\274\211.md" | 2 +-
...\240\241\346\213\233\346\200\273\347\273\223\357\274\211.md" | 2 +-
...60 Java \350\277\231\346\235\241\350\267\257\357\274\237.md" | 2 +-
...\271\240\350\265\204\346\272\220\346\270\205\345\215\225.md" | 2 +-
...\277\231\344\270\200\345\274\240\345\233\276\357\274\201.md" | 2 +-
...\235\242\347\273\217\345\244\247\345\220\210\351\233\206.md" | 2 +-
docs/hxx/think/copy.md | 2 +-
"docs/hxx/\347\224\265\345\255\220\344\271\246.md" | 2 +-
docs/interview/BATJ-Experience/alipay-pinduoduo-toutiao.md | 2 +-
...3(\345\267\262\346\213\277\345\217\243\345\244\264offer).md" | 2 +-
...42\351\230\277\351\207\214,\347\273\210\350\216\267offer.md" | 2 +-
...\277\203\346\212\200\346\234\257\346\200\273\347\273\223.md" | 2 +-
docs/interview/PreparingForInterview/JavaInterviewLibrary.md | 2 +-
docs/interview/PreparingForInterview/JavaProgrammerNeedKnow.md | 2 +-
docs/interview/PreparingForInterview/interviewPrepare.md | 2 +-
...\257\245\345\246\202\344\275\225\345\233\236\347\255\224.md" | 2 +-
...\232\204\347\256\200\345\216\206\344\271\213\351\201\223.md" | 2 +-
...\247\201\351\227\256\351\242\230\346\200\273\347\273\223.md" | 2 +-
"docs/java/jvm/JVM\346\200\273\347\273\223.md" | 2 +-
58 files changed, 58 insertions(+), 58 deletions(-)
diff --git "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\345\274\200\347\257\207\357\274\232\344\273\200\344\271\210\346\230\257Redis.md" "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\345\274\200\347\257\207\357\274\232\344\273\200\344\271\210\346\230\257Redis.md"
index fe6dad0..51ba773 100644
--- "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\345\274\200\347\257\207\357\274\232\344\273\200\344\271\210\346\230\257Redis.md"
+++ "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\345\274\200\347\257\207\357\274\232\344\273\200\344\271\210\346\230\257Redis.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [redis 学习笔记](#redis-学习笔记)
* [redis 是什么?](#redis-是什么)
diff --git "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis \347\232\204\345\237\272\347\241\200\346\225\260\346\215\256\347\273\223\346\236\204\346\246\202\350\247\210.md" "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis \347\232\204\345\237\272\347\241\200\346\225\260\346\215\256\347\273\223\346\236\204\346\246\202\350\247\210.md"
index 57151b7..9102d4d 100644
--- "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis \347\232\204\345\237\272\347\241\200\346\225\260\346\215\256\347\273\223\346\236\204\346\246\202\350\247\210.md"
+++ "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis \347\232\204\345\237\272\347\241\200\346\225\260\346\215\256\347\273\223\346\236\204\346\246\202\350\247\210.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [SDS](#sds)
* [链表](#链表)
diff --git "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\344\272\213\345\212\241\346\265\205\346\236\220\344\270\216ACID\347\211\271\346\200\247\344\273\213\347\273\215.md" "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\344\272\213\345\212\241\346\265\205\346\236\220\344\270\216ACID\347\211\271\346\200\247\344\273\213\347\273\215.md"
index 1ec7a8e..f9aef55 100644
--- "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\344\272\213\345\212\241\346\265\205\346\236\220\344\270\216ACID\347\211\271\346\200\247\344\273\213\347\273\215.md"
+++ "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\344\272\213\345\212\241\346\265\205\346\236\220\344\270\216ACID\347\211\271\346\200\247\344\273\213\347\273\215.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [事务](#事务)
* [用法](#用法)
diff --git "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224dict.md" "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224dict.md"
index b5918f8..97fbd0e 100644
--- "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224dict.md"
+++ "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224dict.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [dict的数据结构定义](#dict的数据结构定义)
* [dict的创建(dictCreate)](#dict的创建(dictcreate))
diff --git "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224intset.md" "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224intset.md"
index b1a6fc3..95204c4 100644
--- "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224intset.md"
+++ "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224intset.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [intset数据结构简介](#intset数据结构简介)
* [intset的查找和添加操作](#intset的查找和添加操作)
diff --git "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224quicklist.md" "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224quicklist.md"
index 9070b83..80bba2e 100644
--- "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224quicklist.md"
+++ "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224quicklist.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [quicklist概述](#quicklist概述)
* [quicklist的数据结构定义](#quicklist的数据结构定义)
diff --git "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224sds.md" "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224sds.md"
index 3c940c8..f9d1726 100644
--- "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224sds.md"
+++ "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224sds.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [前言](#前言)
* [sds的数据结构定义](#sds的数据结构定义)
diff --git "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224skiplist.md" "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224skiplist.md"
index d463e4a..d419a09 100644
--- "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224skiplist.md"
+++ "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224skiplist.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [skiplist数据结构简介](#skiplist数据结构简介)
* [skiplist的算法性能分析](#skiplist的算法性能分析)
diff --git "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224ziplist.md" "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224ziplist.md"
index d1130f9..ea7ce4b 100644
--- "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224ziplist.md"
+++ "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224ziplist.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [什么是ziplist](#什么是ziplist)
* [ziplist的数据结构定义](#ziplist的数据结构定义)
diff --git "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\210\206\345\270\203\345\274\217\351\224\201\350\277\233\345\214\226\345\217\262.md" "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\210\206\345\270\203\345\274\217\351\224\201\350\277\233\345\214\226\345\217\262.md"
index 9f3d353..628426d 100644
--- "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\210\206\345\270\203\345\274\217\351\224\201\350\277\233\345\214\226\345\217\262.md"
+++ "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\210\206\345\270\203\345\274\217\351\224\201\350\277\233\345\214\226\345\217\262.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [Redis分布式锁进化史](#redis分布式锁进化史)
* [各个版本的Redis分布式锁](#各个版本的redis分布式锁)
diff --git "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\351\233\206\347\276\244\346\234\272\345\210\266\345\217\212\344\270\200\344\270\252Redis\346\236\266\346\236\204\346\274\224\350\277\233\345\256\236\344\276\213.md" "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\351\233\206\347\276\244\346\234\272\345\210\266\345\217\212\344\270\200\344\270\252Redis\346\236\266\346\236\204\346\274\224\350\277\233\345\256\236\344\276\213.md"
index dc6c078..5d84b69 100644
--- "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\351\233\206\347\276\244\346\234\272\345\210\266\345\217\212\344\270\200\344\270\252Redis\346\236\266\346\236\204\346\274\224\350\277\233\345\256\236\344\276\213.md"
+++ "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\351\233\206\347\276\244\346\234\272\345\210\266\345\217\212\344\270\200\344\270\252Redis\346\236\266\346\236\204\346\274\224\350\277\233\345\256\236\344\276\213.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [Replication(主从复制)](#replication(主从复制))
* [配置主服务器](#配置主服务器)
diff --git "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232\344\275\277\347\224\250\345\277\253\347\205\247\345\222\214AOF\345\260\206Redis\346\225\260\346\215\256\346\214\201\344\271\205\345\214\226\345\210\260\347\241\254\347\233\230\344\270\255.md" "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232\344\275\277\347\224\250\345\277\253\347\205\247\345\222\214AOF\345\260\206Redis\346\225\260\346\215\256\346\214\201\344\271\205\345\214\226\345\210\260\347\241\254\347\233\230\344\270\255.md"
index 119f43b..92e1875 100644
--- "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232\344\275\277\347\224\250\345\277\253\347\205\247\345\222\214AOF\345\260\206Redis\346\225\260\346\215\256\346\214\201\344\271\205\345\214\226\345\210\260\347\241\254\347\233\230\344\270\255.md"
+++ "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232\344\275\277\347\224\250\345\277\253\347\205\247\345\222\214AOF\345\260\206Redis\346\225\260\346\215\256\346\214\201\344\271\205\345\214\226\345\210\260\347\241\254\347\233\230\344\270\255.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [前言](#前言)
* [快照持久化](#快照持久化)
diff --git "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232\346\225\260\346\215\256\345\272\223redisDb\344\270\216\351\224\256\350\277\207\346\234\237\345\210\240\351\231\244\347\255\226\347\225\245.md" "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232\346\225\260\346\215\256\345\272\223redisDb\344\270\216\351\224\256\350\277\207\346\234\237\345\210\240\351\231\244\347\255\226\347\225\245.md"
index d176fc1..3f14892 100644
--- "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232\346\225\260\346\215\256\345\272\223redisDb\344\270\216\351\224\256\350\277\207\346\234\237\345\210\240\351\231\244\347\255\226\347\225\245.md"
+++ "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232\346\225\260\346\215\256\345\272\223redisDb\344\270\216\351\224\256\350\277\207\346\234\237\345\210\240\351\231\244\347\255\226\347\225\245.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [一. 数据库](#一-数据库)
* [二、切换数据库原理](#二、切换数据库原理)
diff --git "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232\346\265\205\346\236\220Redis\344\270\273\344\273\216\345\244\215\345\210\266.md" "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232\346\265\205\346\236\220Redis\344\270\273\344\273\216\345\244\215\345\210\266.md"
index d23323b..393e8ac 100644
--- "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232\346\265\205\346\236\220Redis\344\270\273\344\273\216\345\244\215\345\210\266.md"
+++ "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232\346\265\205\346\236\220Redis\344\270\273\344\273\216\345\244\215\345\210\266.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [Redis复制概论](#redis复制概论)
* [Redis复制方式](#redis复制方式)
diff --git "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232\350\277\236\346\216\245\345\272\225\345\261\202\344\270\216\350\241\250\351\235\242\347\232\204\346\225\260\346\215\256\347\273\223\346\236\204robj.md" "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232\350\277\236\346\216\245\345\272\225\345\261\202\344\270\216\350\241\250\351\235\242\347\232\204\346\225\260\346\215\256\347\273\223\346\236\204robj.md"
index ffc8fe4..e8823f6 100644
--- "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232\350\277\236\346\216\245\345\272\225\345\261\202\344\270\216\350\241\250\351\235\242\347\232\204\346\225\260\346\215\256\347\273\223\346\236\204robj.md"
+++ "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232\350\277\236\346\216\245\345\272\225\345\261\202\344\270\216\350\241\250\351\235\242\347\232\204\346\225\260\346\215\256\347\273\223\346\236\204robj.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [robj的数据结构定义](#robj的数据结构定义)
* [string robj的编码过程](#string-robj的编码过程)
diff --git "a/docs/cs/algorithms/\345\211\221\346\214\207offer.md" "b/docs/cs/algorithms/\345\211\221\346\214\207offer.md"
index 3147337..7952448 100644
--- "a/docs/cs/algorithms/\345\211\221\346\214\207offer.md"
+++ "b/docs/cs/algorithms/\345\211\221\346\214\207offer.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [数论和数字规律](#数论和数字规律)
* [从1到n整数中1出现的次数](#从1到n整数中1出现的次数)
diff --git "a/docs/cs/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\345\255\246\344\271\240\346\200\273\347\273\223.md" "b/docs/cs/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\345\255\246\344\271\240\346\200\273\347\273\223.md"
index 0ee5021..6f4ee49 100644
--- "a/docs/cs/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\345\255\246\344\271\240\346\200\273\347\273\223.md"
+++ "b/docs/cs/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\345\255\246\344\271\240\346\200\273\347\273\223.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [网卡和路由器](#网卡和路由器)
* [交换机](#交换机)
diff --git "a/docs/cs/operating-system/Linux\345\206\205\346\240\270\344\270\216\345\237\272\347\241\200\345\221\275\344\273\244\345\255\246\344\271\240\346\200\273\347\273\223.md" "b/docs/cs/operating-system/Linux\345\206\205\346\240\270\344\270\216\345\237\272\347\241\200\345\221\275\344\273\244\345\255\246\344\271\240\346\200\273\347\273\223.md"
index 3cf91e6..4dd7996 100644
--- "a/docs/cs/operating-system/Linux\345\206\205\346\240\270\344\270\216\345\237\272\347\241\200\345\221\275\344\273\244\345\255\246\344\271\240\346\200\273\347\273\223.md"
+++ "b/docs/cs/operating-system/Linux\345\206\205\346\240\270\344\270\216\345\237\272\347\241\200\345\221\275\344\273\244\345\255\246\344\271\240\346\200\273\347\273\223.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [文件系统和VFS](#文件系统和vfs)
* [进程和线程](#进程和线程)
diff --git "a/docs/cs/operating-system/\346\223\215\344\275\234\347\263\273\347\273\237\345\255\246\344\271\240\346\200\273\347\273\223.md" "b/docs/cs/operating-system/\346\223\215\344\275\234\347\263\273\347\273\237\345\255\246\344\271\240\346\200\273\347\273\223.md"
index 97cd45f..4c97490 100644
--- "a/docs/cs/operating-system/\346\223\215\344\275\234\347\263\273\347\273\237\345\255\246\344\271\240\346\200\273\347\273\223.md"
+++ "b/docs/cs/operating-system/\346\223\215\344\275\234\347\263\273\347\273\237\345\255\246\344\271\240\346\200\273\347\273\223.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [CPU](#cpu)
* [程序执行过程](#程序执行过程)
diff --git "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Innodb\344\270\255\347\232\204\344\272\213\345\212\241\351\232\224\347\246\273\347\272\247\345\210\253\345\222\214\351\224\201\347\232\204\345\205\263\347\263\273.md" "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Innodb\344\270\255\347\232\204\344\272\213\345\212\241\351\232\224\347\246\273\347\272\247\345\210\253\345\222\214\351\224\201\347\232\204\345\205\263\347\263\273.md"
index b796526..5223578 100644
--- "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Innodb\344\270\255\347\232\204\344\272\213\345\212\241\351\232\224\347\246\273\347\272\247\345\210\253\345\222\214\351\224\201\347\232\204\345\205\263\347\263\273.md"
+++ "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Innodb\344\270\255\347\232\204\344\272\213\345\212\241\351\232\224\347\246\273\347\272\247\345\210\253\345\222\214\351\224\201\347\232\204\345\205\263\347\263\273.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [Innodb中的事务隔离级别和锁的关系](#innodb中的事务隔离级别和锁的关系)
* [事务中的加锁方式](#事务中的加锁方式)
diff --git "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232MySQL\351\207\214\347\232\204\351\202\243\344\272\233\346\227\245\345\277\227\344\273\254.md" "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232MySQL\351\207\214\347\232\204\351\202\243\344\272\233\346\227\245\345\277\227\344\273\254.md"
index 3469a48..6f69233 100644
--- "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232MySQL\351\207\214\347\232\204\351\202\243\344\272\233\346\227\245\345\277\227\344\273\254.md"
+++ "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232MySQL\351\207\214\347\232\204\351\202\243\344\272\233\346\227\245\345\277\227\344\273\254.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [目录](#目录)
* [重新学习MySQL数据库10:MySQL里的那些日志们](#重新学习mysql数据库10:mysql里的那些日志们)
diff --git "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Mysql\345\255\230\345\202\250\345\274\225\346\223\216\344\270\216\346\225\260\346\215\256\345\255\230\345\202\250\345\216\237\347\220\206.md" "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Mysql\345\255\230\345\202\250\345\274\225\346\223\216\344\270\216\346\225\260\346\215\256\345\255\230\345\202\250\345\216\237\347\220\206.md"
index 4763b48..3d694e3 100644
--- "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Mysql\345\255\230\345\202\250\345\274\225\346\223\216\344\270\216\346\225\260\346\215\256\345\255\230\345\202\250\345\216\237\347\220\206.md"
+++ "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Mysql\345\255\230\345\202\250\345\274\225\346\223\216\344\270\216\346\225\260\346\215\256\345\255\230\345\202\250\345\216\237\347\220\206.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [**一、 MySQL记录存储(页为单位)**](#一、-mysql记录存储(页为单位))
* [**页头**](#页头)
diff --git "a/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200 \357\274\232CAP.md" "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200 \357\274\232CAP.md"
index 268f008..545e034 100644
--- "a/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200 \357\274\232CAP.md"
+++ "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200 \357\274\232CAP.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [**引言**](#引言)
* [**CAP定理**](#cap定理)
diff --git "a/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232 \344\270\200\350\207\264\346\200\247\343\200\201PC\345\222\214PC.md" "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232 \344\270\200\350\207\264\346\200\247\343\200\201PC\345\222\214PC.md"
index 9b94bed..b2ac551 100644
--- "a/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232 \344\270\200\350\207\264\346\200\247\343\200\201PC\345\222\214PC.md"
+++ "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232 \344\270\200\350\207\264\346\200\247\343\200\201PC\345\222\214PC.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [**引言**](#引言)
* [**一致性(consensus)**](#一致性consensus)
diff --git "a/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232 \346\227\266\351\227\264\343\200\201\346\227\266\351\222\237\345\222\214\344\272\213\344\273\266\351\241\272\345\272\217.md" "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232 \346\227\266\351\227\264\343\200\201\346\227\266\351\222\237\345\222\214\344\272\213\344\273\266\351\241\272\345\272\217.md"
index 47d52a7..d8f2e21 100644
--- "a/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232 \346\227\266\351\227\264\343\200\201\346\227\266\351\222\237\345\222\214\344\272\213\344\273\266\351\241\272\345\272\217.md"
+++ "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232 \346\227\266\351\227\264\343\200\201\346\227\266\351\222\237\345\222\214\344\272\213\344\273\266\351\241\272\345\272\217.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [**物理时钟 vs 逻辑时钟**](#物理时钟-vs-逻辑时钟)
* [**Lamport timestamps**](#lamport-timestamps)
diff --git "a/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232Paxos.md" "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232Paxos.md"
index 030e7ac..603d2d2 100644
--- "a/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232Paxos.md"
+++ "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232Paxos.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [**引言**](#引言)
* [**Basic Paxos**](#basic-paxos)
diff --git "a/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232Raft\343\200\201Zab.md" "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232Raft\343\200\201Zab.md"
index a774ab2..4530e9d 100644
--- "a/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232Raft\343\200\201Zab.md"
+++ "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232Raft\343\200\201Zab.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [**引言**](#引言)
* [**Raft**](#raft)
diff --git "a/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232zookeeper\345\210\206\345\270\203\345\274\217\345\215\217\350\260\203\346\234\215\345\212\241.md" "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232zookeeper\345\210\206\345\270\203\345\274\217\345\215\217\350\260\203\346\234\215\345\212\241.md"
index 1696d11..4dd3007 100644
--- "a/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232zookeeper\345\210\206\345\270\203\345\274\217\345\215\217\350\260\203\346\234\215\345\212\241.md"
+++ "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232zookeeper\345\210\206\345\270\203\345\274\217\345\215\217\350\260\203\346\234\215\345\212\241.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [**ZK API**](#zk-api)
* [**ZK应用场景**](#zk应用场景)
diff --git "a/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232\351\200\211\344\270\276\343\200\201\345\244\232\346\225\260\346\264\276\345\222\214\347\247\237\347\272\246.md" "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232\351\200\211\344\270\276\343\200\201\345\244\232\346\225\260\346\264\276\345\222\214\347\247\237\347\272\246.md"
index 5c388e5..1455063 100644
--- "a/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232\351\200\211\344\270\276\343\200\201\345\244\232\346\225\260\346\264\276\345\222\214\347\247\237\347\272\246.md"
+++ "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\200\357\274\232\351\200\211\344\270\276\343\200\201\345\244\232\346\225\260\346\264\276\345\222\214\347\247\237\347\272\246.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [**选举(electioin)**](#选举electioin)
* [**多数派(quorum)**](#多数派quorum)
diff --git "a/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\350\277\233\351\230\266\357\274\232Paxos\345\217\230\347\247\215\345\222\214\344\274\230\345\214\226.md" "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\350\277\233\351\230\266\357\274\232Paxos\345\217\230\347\247\215\345\222\214\344\274\230\345\214\226.md"
index 1af9cc3..abc4289 100644
--- "a/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\350\277\233\351\230\266\357\274\232Paxos\345\217\230\347\247\215\345\222\214\344\274\230\345\214\226.md"
+++ "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\350\277\233\351\230\266\357\274\232Paxos\345\217\230\347\247\215\345\222\214\344\274\230\345\214\226.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [**引言**](#引言)
* [**Multi Paxos**](#multi-paxos)
* [**Fast Paxos**](#fast-paxos)
diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232ZAB\345\215\217\350\256\256\346\246\202\350\277\260\344\270\216\351\200\211\344\270\273\346\265\201\347\250\213\350\257\246\350\247\243.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232ZAB\345\215\217\350\256\256\346\246\202\350\277\260\344\270\216\351\200\211\344\270\273\346\265\201\347\250\213\350\257\246\350\247\243.md"
index 4a62581..5212a27 100644
--- "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232ZAB\345\215\217\350\256\256\346\246\202\350\277\260\344\270\216\351\200\211\344\270\273\346\265\201\347\250\213\350\257\246\350\247\243.md"
+++ "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232ZAB\345\215\217\350\256\256\346\246\202\350\277\260\344\270\216\351\200\211\344\270\273\346\265\201\347\250\213\350\257\246\350\247\243.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [ZAB协议](#zab协议)
* [消息广播模式](#消息广播模式)
diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217ID\347\224\237\346\210\220\346\226\271\346\241\210.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217ID\347\224\237\346\210\220\346\226\271\346\241\210.md"
index 95caec7..1563d5a 100644
--- "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217ID\347\224\237\346\210\220\346\226\271\346\241\210.md"
+++ "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217ID\347\224\237\346\210\220\346\226\271\346\241\210.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [**一、需求缘起**](#一、需求缘起)
* [**二、常见方法、不足与优化**](#二、常见方法、不足与优化)
diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217session\350\247\243\345\206\263\346\226\271\346\241\210\344\270\216\344\270\200\350\207\264\346\200\247hash.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217session\350\247\243\345\206\263\346\226\271\346\241\210\344\270\216\344\270\200\350\207\264\346\200\247hash.md"
index 2c8510e..50e6f52 100644
--- "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217session\350\247\243\345\206\263\346\226\271\346\241\210\344\270\216\344\270\200\350\207\264\346\200\247hash.md"
+++ "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217session\350\247\243\345\206\263\346\226\271\346\241\210\344\270\216\344\270\200\350\207\264\346\200\247hash.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [一、问题的提出](#一、问题的提出)
* [1. 什么是Session?](#1-什么是session?)
diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241\345\270\270\347\224\250\350\247\243\345\206\263\346\226\271\346\241\210.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241\345\270\270\347\224\250\350\247\243\345\206\263\346\226\271\346\241\210.md"
index 21a891b..77adff5 100644
--- "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241\345\270\270\347\224\250\350\247\243\345\206\263\346\226\271\346\241\210.md"
+++ "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241\345\270\270\347\224\250\350\247\243\345\206\263\346\226\271\346\241\210.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [一、概述](#一、概述)
* [二、理论](#二、理论)
diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\235\346\216\242\345\210\206\345\270\203\345\274\217\345\215\217\350\260\203\346\234\215\345\212\241zookeeper.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\235\346\216\242\345\210\206\345\270\203\345\274\217\345\215\217\350\260\203\346\234\215\345\212\241zookeeper.md"
index f8699df..45da3d8 100644
--- "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\235\346\216\242\345\210\206\345\270\203\345\274\217\345\215\217\350\260\203\346\234\215\345\212\241zookeeper.md"
+++ "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\345\210\235\346\216\242\345\210\206\345\270\203\345\274\217\345\215\217\350\260\203\346\234\215\345\212\241zookeeper.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [目录](#目录)
* [小梁的邮件](#小梁的邮件)
diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\265\205\346\236\220\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\265\205\346\236\220\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md"
index 147a92e..3f1f40d 100644
--- "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\265\205\346\236\220\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md"
+++ "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\265\205\346\236\220\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [目录](#目录)
* [什么是事务?](#什么是事务?)
diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\346\266\210\346\201\257\346\212\200\346\234\257Kafka.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\346\266\210\346\201\257\346\212\200\346\234\257Kafka.md"
index 7e54e71..28fc2ff 100644
--- "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\346\266\210\346\201\257\346\212\200\346\234\257Kafka.md"
+++ "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\346\266\210\346\201\257\346\212\200\346\234\257Kafka.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [目录](#目录)
* [**Kafka的基本介绍**](#kafka的基本介绍)
diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\351\224\201\347\232\204\345\207\240\347\247\215\346\226\271\346\241\210.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\351\224\201\347\232\204\345\207\240\347\247\215\346\226\271\346\241\210.md"
index 701bde3..b9e4ea5 100644
--- "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\351\224\201\347\232\204\345\207\240\347\247\215\346\226\271\346\241\210.md"
+++ "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\351\224\201\347\232\204\345\207\240\347\247\215\346\226\271\346\241\210.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [目录](#目录)
* [前言](#前言)
diff --git "a/docs/distributed/\345\210\206\345\270\203\345\274\217\347\220\206\350\256\272\346\200\273\347\273\223.md" "b/docs/distributed/\345\210\206\345\270\203\345\274\217\347\220\206\350\256\272\346\200\273\347\273\223.md"
index d7b5027..9e341f3 100644
--- "a/docs/distributed/\345\210\206\345\270\203\345\274\217\347\220\206\350\256\272\346\200\273\347\273\223.md"
+++ "b/docs/distributed/\345\210\206\345\270\203\345\274\217\347\220\206\350\256\272\346\200\273\347\273\223.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [六、Raft](#六、raft)
* [单个 Candidate 的竞选](#单个-candidate-的竞选)
diff --git "a/docs/hxx/java/Java\345\220\216\347\253\257\345\267\245\347\250\213\345\270\210\345\277\205\345\244\207\344\271\246\345\215\225\357\274\210\344\273\216Java\345\237\272\347\241\200\345\210\260\345\210\206\345\270\203\345\274\217\357\274\211.md" "b/docs/hxx/java/Java\345\220\216\347\253\257\345\267\245\347\250\213\345\270\210\345\277\205\345\244\207\344\271\246\345\215\225\357\274\210\344\273\216Java\345\237\272\347\241\200\345\210\260\345\210\206\345\270\203\345\274\217\357\274\211.md"
index 7b4490d..65b42bb 100644
--- "a/docs/hxx/java/Java\345\220\216\347\253\257\345\267\245\347\250\213\345\270\210\345\277\205\345\244\207\344\271\246\345\215\225\357\274\210\344\273\216Java\345\237\272\347\241\200\345\210\260\345\210\206\345\270\203\345\274\217\357\274\211.md"
+++ "b/docs/hxx/java/Java\345\220\216\347\253\257\345\267\245\347\250\213\345\270\210\345\277\205\345\244\207\344\271\246\345\215\225\357\274\210\344\273\216Java\345\237\272\347\241\200\345\210\260\345\210\206\345\270\203\345\274\217\357\274\211.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [网络](#网络)
* [1 TCP/IP卷一](#1-tcpip卷一)
diff --git "a/docs/hxx/java/Java\345\267\245\347\250\213\345\270\210\344\277\256\347\202\274\344\271\213\350\267\257\357\274\210\346\240\241\346\213\233\346\200\273\347\273\223\357\274\211.md" "b/docs/hxx/java/Java\345\267\245\347\250\213\345\270\210\344\277\256\347\202\274\344\271\213\350\267\257\357\274\210\346\240\241\346\213\233\346\200\273\347\273\223\357\274\211.md"
index 1432c75..221cd8f 100644
--- "a/docs/hxx/java/Java\345\267\245\347\250\213\345\270\210\344\277\256\347\202\274\344\271\213\350\267\257\357\274\210\346\240\241\346\213\233\346\200\273\347\273\223\357\274\211.md"
+++ "b/docs/hxx/java/Java\345\267\245\347\250\213\345\270\210\344\277\256\347\202\274\344\271\213\350\267\257\357\274\210\346\240\241\346\213\233\346\200\273\347\273\223\357\274\211.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [前言](#前言)
* [大学时期的迷茫与坚定](#大学时期的迷茫与坚定)
diff --git "a/docs/hxx/java/\344\270\272\344\273\200\344\271\210\346\210\221\344\274\232\351\200\211\346\213\251\350\265\260 Java \350\277\231\346\235\241\350\267\257\357\274\237.md" "b/docs/hxx/java/\344\270\272\344\273\200\344\271\210\346\210\221\344\274\232\351\200\211\346\213\251\350\265\260 Java \350\277\231\346\235\241\350\267\257\357\274\237.md"
index c72b4dd..ed2fe79 100644
--- "a/docs/hxx/java/\344\270\272\344\273\200\344\271\210\346\210\221\344\274\232\351\200\211\346\213\251\350\265\260 Java \350\277\231\346\235\241\350\267\257\357\274\237.md"
+++ "b/docs/hxx/java/\344\270\272\344\273\200\344\271\210\346\210\221\344\274\232\351\200\211\346\213\251\350\265\260 Java \350\277\231\346\235\241\350\267\257\357\274\237.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [谈谈我的技术方向选择](#谈谈我的技术方向选择)
* [谈谈各个技术方向的前景](#谈谈各个技术方向的前景)
diff --git "a/docs/hxx/java/\344\275\240\344\270\215\345\217\257\351\224\231\350\277\207\347\232\204Java\345\255\246\344\271\240\350\265\204\346\272\220\346\270\205\345\215\225.md" "b/docs/hxx/java/\344\275\240\344\270\215\345\217\257\351\224\231\350\277\207\347\232\204Java\345\255\246\344\271\240\350\265\204\346\272\220\346\270\205\345\215\225.md"
index b4a6a53..0b41820 100644
--- "a/docs/hxx/java/\344\275\240\344\270\215\345\217\257\351\224\231\350\277\207\347\232\204Java\345\255\246\344\271\240\350\265\204\346\272\220\346\270\205\345\215\225.md"
+++ "b/docs/hxx/java/\344\275\240\344\270\215\345\217\257\351\224\231\350\277\207\347\232\204Java\345\255\246\344\271\240\350\265\204\346\272\220\346\270\205\345\215\225.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [Java入门学习资源](#java入门学习资源)
* [Java后端技术专栏](#java后端技术专栏)
diff --git "a/docs/hxx/java/\346\203\263\344\272\206\350\247\243Java\345\220\216\347\253\257\345\255\246\344\271\240\350\267\257\347\272\277\357\274\237\344\275\240\345\217\252\351\234\200\350\246\201\350\277\231\344\270\200\345\274\240\345\233\276\357\274\201.md" "b/docs/hxx/java/\346\203\263\344\272\206\350\247\243Java\345\220\216\347\253\257\345\255\246\344\271\240\350\267\257\347\272\277\357\274\237\344\275\240\345\217\252\351\234\200\350\246\201\350\277\231\344\270\200\345\274\240\345\233\276\357\274\201.md"
index 202769b..3da5c3d 100644
--- "a/docs/hxx/java/\346\203\263\344\272\206\350\247\243Java\345\220\216\347\253\257\345\255\246\344\271\240\350\267\257\347\272\277\357\274\237\344\275\240\345\217\252\351\234\200\350\246\201\350\277\231\344\270\200\345\274\240\345\233\276\357\274\201.md"
+++ "b/docs/hxx/java/\346\203\263\344\272\206\350\247\243Java\345\220\216\347\253\257\345\255\246\344\271\240\350\267\257\347\272\277\357\274\237\344\275\240\345\217\252\351\234\200\350\246\201\350\277\231\344\270\200\345\274\240\345\233\276\357\274\201.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [](#[]httpsmmbizqpiccnmmbiz_jpgxhh0sksqzpniac1cdgficiqdtr2poaq2jmvd3jnkuoiabzxgzdjh9pcics0rckcgawvgvnm7zh2lvlodkatzanldzg640wx_fmtjpegtpwebpwxfrom5wx_lazy1wx_co1)
* [前言](#前言)
diff --git "a/docs/hxx/java/\346\210\221\347\232\204Java\347\247\213\346\213\233\351\235\242\347\273\217\345\244\247\345\220\210\351\233\206.md" "b/docs/hxx/java/\346\210\221\347\232\204Java\347\247\213\346\213\233\351\235\242\347\273\217\345\244\247\345\220\210\351\233\206.md"
index 3b54d0f..cbe57c4 100644
--- "a/docs/hxx/java/\346\210\221\347\232\204Java\347\247\213\346\213\233\351\235\242\347\273\217\345\244\247\345\220\210\351\233\206.md"
+++ "b/docs/hxx/java/\346\210\221\347\232\204Java\347\247\213\346\213\233\351\235\242\347\273\217\345\244\247\345\220\210\351\233\206.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [阿里面经 ](#阿里面经 )
* [腾讯面经 ](#腾讯面经 )
diff --git a/docs/hxx/think/copy.md b/docs/hxx/think/copy.md
index c62954a..813a411 100644
--- a/docs/hxx/think/copy.md
+++ b/docs/hxx/think/copy.md
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [微信公众号](#微信公众号)
* [个人公众号:黄小斜](#个人公众号:黄小斜)
diff --git "a/docs/hxx/\347\224\265\345\255\220\344\271\246.md" "b/docs/hxx/\347\224\265\345\255\220\344\271\246.md"
index 5e77629..b80bf2e 100644
--- "a/docs/hxx/\347\224\265\345\255\220\344\271\246.md"
+++ "b/docs/hxx/\347\224\265\345\255\220\344\271\246.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [《菜鸟程序员成长之路:从技术小白到阿里巴巴Java工程师》](#《菜鸟程序员成长之路:从技术小白到阿里巴巴java工程师》)
* [Java学习](#java学习)
diff --git a/docs/interview/BATJ-Experience/alipay-pinduoduo-toutiao.md b/docs/interview/BATJ-Experience/alipay-pinduoduo-toutiao.md
index 1db1539..27df6fa 100644
--- a/docs/interview/BATJ-Experience/alipay-pinduoduo-toutiao.md
+++ b/docs/interview/BATJ-Experience/alipay-pinduoduo-toutiao.md
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [2019年蚂蚁金服、头条、拼多多的面试总结](#2019年蚂蚁金服、头条、拼多多的面试总结)
* [准备过程](#准备过程)
diff --git "a/docs/interview/BATJ-Experience/\350\232\202\350\232\201\351\207\221\346\234\215\345\256\236\344\271\240\347\224\237\351\235\242\347\273\217\346\200\273\347\273\223(\345\267\262\346\213\277\345\217\243\345\244\264offer).md" "b/docs/interview/BATJ-Experience/\350\232\202\350\232\201\351\207\221\346\234\215\345\256\236\344\271\240\347\224\237\351\235\242\347\273\217\346\200\273\347\273\223(\345\267\262\346\213\277\345\217\243\345\244\264offer).md"
index 95f8403..61fb537 100644
--- "a/docs/interview/BATJ-Experience/\350\232\202\350\232\201\351\207\221\346\234\215\345\256\236\344\271\240\347\224\237\351\235\242\347\273\217\346\200\273\347\273\223(\345\267\262\346\213\277\345\217\243\345\244\264offer).md"
+++ "b/docs/interview/BATJ-Experience/\350\232\202\350\232\201\351\207\221\346\234\215\345\256\236\344\271\240\347\224\237\351\235\242\347\273\217\346\200\273\347\273\223(\345\267\262\346\213\277\345\217\243\345\244\264offer).md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [一面 (37 分钟左右)](#一面-37-分钟左右)
* [二面 (33 分钟左右)](#二面-33-分钟左右)
diff --git "a/docs/interview/BATJ-Experience/\351\235\242\351\230\277\351\207\214,\347\273\210\350\216\267offer.md" "b/docs/interview/BATJ-Experience/\351\235\242\351\230\277\351\207\214,\347\273\210\350\216\267offer.md"
index 5a6e7e3..b06c915 100644
--- "a/docs/interview/BATJ-Experience/\351\235\242\351\230\277\351\207\214,\347\273\210\350\216\267offer.md"
+++ "b/docs/interview/BATJ-Experience/\351\235\242\351\230\277\351\207\214,\347\273\210\350\216\267offer.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [前言](#前言)
* [一面(技术面)](#一面技术面)
diff --git "a/docs/interview/InterviewQuestions/Java\346\240\270\345\277\203\346\212\200\346\234\257\346\200\273\347\273\223.md" "b/docs/interview/InterviewQuestions/Java\346\240\270\345\277\203\346\212\200\346\234\257\346\200\273\347\273\223.md"
index d624749..bc89b6d 100644
--- "a/docs/interview/InterviewQuestions/Java\346\240\270\345\277\203\346\212\200\346\234\257\346\200\273\347\273\223.md"
+++ "b/docs/interview/InterviewQuestions/Java\346\240\270\345\277\203\346\212\200\346\234\257\346\200\273\347\273\223.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [Java基础学习总结](#java基础学习总结)
* [面向对象三大特性](#面向对象三大特性)
diff --git a/docs/interview/PreparingForInterview/JavaInterviewLibrary.md b/docs/interview/PreparingForInterview/JavaInterviewLibrary.md
index e3d4e1d..2325618 100644
--- a/docs/interview/PreparingForInterview/JavaInterviewLibrary.md
+++ b/docs/interview/PreparingForInterview/JavaInterviewLibrary.md
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [知识点相关](#知识点相关)
* [1.JavaGuide](#1javaguide)
diff --git a/docs/interview/PreparingForInterview/JavaProgrammerNeedKnow.md b/docs/interview/PreparingForInterview/JavaProgrammerNeedKnow.md
index 417d1f9..3997584 100644
--- a/docs/interview/PreparingForInterview/JavaProgrammerNeedKnow.md
+++ b/docs/interview/PreparingForInterview/JavaProgrammerNeedKnow.md
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [Question1:我是双非/三本/专科学校的,我有机会进入大厂吗?](#question1我是双非三本专科学校的,我有机会进入大厂吗?)
* [Question2:非计算机专业的学生能学好Java后台吗?我能进大厂吗?](#question2非计算机专业的学生能学好java后台吗?我能进大厂吗?)
diff --git a/docs/interview/PreparingForInterview/interviewPrepare.md b/docs/interview/PreparingForInterview/interviewPrepare.md
index 89a3dc6..72201be 100644
--- a/docs/interview/PreparingForInterview/interviewPrepare.md
+++ b/docs/interview/PreparingForInterview/interviewPrepare.md
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [1 如何获取大厂面试机会?](#1-如何获取大厂面试机会?)
* [2 面试前的准备](#2--面试前的准备)
diff --git "a/docs/interview/PreparingForInterview/\345\246\202\346\236\234\351\235\242\350\257\225\345\256\230\351\227\256\344\275\240\342\200\234\344\275\240\346\234\211\344\273\200\344\271\210\351\227\256\351\242\230\351\227\256\346\210\221\345\220\227\357\274\237\342\200\235\346\227\266\357\274\214\344\275\240\350\257\245\345\246\202\344\275\225\345\233\236\347\255\224.md" "b/docs/interview/PreparingForInterview/\345\246\202\346\236\234\351\235\242\350\257\225\345\256\230\351\227\256\344\275\240\342\200\234\344\275\240\346\234\211\344\273\200\344\271\210\351\227\256\351\242\230\351\227\256\346\210\221\345\220\227\357\274\237\342\200\235\346\227\266\357\274\214\344\275\240\350\257\245\345\246\202\344\275\225\345\233\236\347\255\224.md"
index 0dc99b2..c1f742b 100644
--- "a/docs/interview/PreparingForInterview/\345\246\202\346\236\234\351\235\242\350\257\225\345\256\230\351\227\256\344\275\240\342\200\234\344\275\240\346\234\211\344\273\200\344\271\210\351\227\256\351\242\230\351\227\256\346\210\221\345\220\227\357\274\237\342\200\235\346\227\266\357\274\214\344\275\240\350\257\245\345\246\202\344\275\225\345\233\236\347\255\224.md"
+++ "b/docs/interview/PreparingForInterview/\345\246\202\346\236\234\351\235\242\350\257\225\345\256\230\351\227\256\344\275\240\342\200\234\344\275\240\346\234\211\344\273\200\344\271\210\351\227\256\351\242\230\351\227\256\346\210\221\345\220\227\357\274\237\342\200\235\346\227\266\357\274\214\344\275\240\350\257\245\345\246\202\344\275\225\345\233\236\347\255\224.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [这个问题对最终面试结果的影响到底大不大?](#这个问题对最终面试结果的影响到底大不大)
* [真诚一点,不要问太 Low 的问题](#真诚一点不要问太-low-的问题)
diff --git "a/docs/interview/PreparingForInterview/\347\250\213\345\272\217\345\221\230\347\232\204\347\256\200\345\216\206\344\271\213\351\201\223.md" "b/docs/interview/PreparingForInterview/\347\250\213\345\272\217\345\221\230\347\232\204\347\256\200\345\216\206\344\271\213\351\201\223.md"
index 096ecaf..f391399 100644
--- "a/docs/interview/PreparingForInterview/\347\250\213\345\272\217\345\221\230\347\232\204\347\256\200\345\216\206\344\271\213\351\201\223.md"
+++ "b/docs/interview/PreparingForInterview/\347\250\213\345\272\217\345\221\230\347\232\204\347\256\200\345\216\206\344\271\213\351\201\223.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [程序员简历就该这样写](#程序员简历就该这样写)
* [为什么说简历很重要?](#为什么说简历很重要?)
diff --git "a/docs/interview/PreparingForInterview/\347\276\216\345\233\242\351\235\242\350\257\225\345\270\270\350\247\201\351\227\256\351\242\230\346\200\273\347\273\223.md" "b/docs/interview/PreparingForInterview/\347\276\216\345\233\242\351\235\242\350\257\225\345\270\270\350\247\201\351\227\256\351\242\230\346\200\273\347\273\223.md"
index 4e62535..8b51c2a 100644
--- "a/docs/interview/PreparingForInterview/\347\276\216\345\233\242\351\235\242\350\257\225\345\270\270\350\247\201\351\227\256\351\242\230\346\200\273\347\273\223.md"
+++ "b/docs/interview/PreparingForInterview/\347\276\216\345\233\242\351\235\242\350\257\225\345\270\270\350\247\201\351\227\256\351\242\230\346\200\273\347\273\223.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [一 基础篇](#一-基础篇)
* [1. `System.out.println(3|9)`输出什么?](#1-`systemoutprintln39`输出什么)
diff --git "a/docs/java/jvm/JVM\346\200\273\347\273\223.md" "b/docs/java/jvm/JVM\346\200\273\347\273\223.md"
index 9a1cdad..60b89e6 100644
--- "a/docs/java/jvm/JVM\346\200\273\347\273\223.md"
+++ "b/docs/java/jvm/JVM\346\200\273\347\273\223.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [JVM介绍和源码](#jvm介绍和源码)
* [JVM内存模型](#jvm内存模型)
From 88e6f706f84c4d40ec55bdd0f35d732f550f72a8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=BB=84=E5=B0=8F=E6=96=9C?= <362294931@qq.com>
Date: Sun, 9 Apr 2023 17:52:09 +0800
Subject: [PATCH 06/39] modify jvm mds
---
ReadMe.md | 4 +-
...37\345\214\226\346\212\200\346\234\257.md" | 2 +-
...23\346\236\204\346\246\202\350\247\210.md" | 2 +-
...\247\243\342\200\224\342\200\224intset.md" | 8 +-
...247\243\342\200\224\342\200\224ziplist.md" | 6 +-
...01\350\277\233\345\214\226\345\217\262.md" | 6 +-
...60\347\241\254\347\233\230\344\270\255.md" | 16 ++--
...33\346\227\245\345\277\227\344\273\254.md" | 12 ---
...23\346\236\204\347\256\227\346\263\225.md" | 2 +-
...60\347\232\204\345\245\227\350\267\257.md" | 2 +-
...33\346\200\273\347\273\223\357\274\211.md" | 10 +-
...04\346\272\220\346\270\205\345\215\225.md" | 24 ++---
...17\345\244\247\345\220\210\351\233\206.md" | 24 ++---
.../\347\224\265\345\255\220\344\271\246.md" | 12 +--
...67\346\261\202\350\275\254\345\217\221.md" | 4 +-
...5\277\265\344\270\216DispatcherServlet.md" | 2 +-
...274\232Mybatis\345\205\245\351\227\250.md" | 2 +-
...5\273\272\345\267\245\345\205\267Maven.md" | 4 +-
...\215\347\275\256\347\232\204SpringBoot.md" | 14 +--
"docs/java/basic/javac\345\222\214javap.md" | 9 +-
...47\350\241\214\351\241\272\345\272\217.md" | 2 +-
.../\345\244\232\347\272\277\347\250\213.md" | 4 +-
...55\347\232\204\345\233\236\350\260\203.md" | 5 +-
...16\346\257\224\350\276\203\345\231\250.md" | 12 +--
...36\347\216\260\345\216\237\347\220\206.md" | 9 +-
...71\263\351\224\201\357\274\214Condtion.md" | 4 +-
...27\346\263\225\345\211\226\346\236\220.md" | 6 +-
...56\345\255\227\350\247\243\346\236\220.md" | 11 ++-
...ap\345\205\250\350\247\243\346\236\220.md" | 12 +--
...20\347\240\201\345\210\206\346\236\220.md" | 12 +--
...357\274\214CAS\346\223\215\344\275\234.md" | 1 -
...345\255\230\346\250\241\345\236\213JMM.md" | 2 +-
...20\347\240\201\345\256\236\347\216\260.md" | 12 +--
...46\344\271\240\346\200\273\347\273\223.md" | 1 -
...76\350\256\241\346\250\241\345\274\217.md" | 91 +++++++++++++------
...70\347\224\250\345\267\245\345\205\267.md" | 23 ++++-
...03\344\274\230\345\256\236\350\267\265.md" | 37 ++++----
...75\345\231\250\345\256\236\347\216\260.md" | 2 +-
...06\345\222\214\347\256\227\346\263\225.md" | 2 +-
...14\346\234\237\344\274\230\345\214\226.md" | 6 +-
...\345\217\212GC\345\256\236\350\267\265.md" | 2 +-
...26\347\250\213\346\250\241\345\236\213.md" | 4 +-
...\345\222\214\345\274\202\346\255\245IO.md" | 8 +-
...7\250\213\346\241\206\346\236\266Netty.md" | 2 +-
src/main/java/md/mdToc.java | 2 +-
45 files changed, 234 insertions(+), 203 deletions(-)
rename "docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232GC\350\260\203\344\274\230\346\200\235\350\267\257\344\270\216\345\270\270\347\224\250\345\267\245\345\205\267.md" => "docs/java/jvm/temp/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232GC\350\260\203\344\274\230\346\200\235\350\267\257\344\270\216\345\270\270\347\224\250\345\267\245\345\205\267.md" (98%)
rename "docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232JVM\345\270\270\347\224\250\345\217\202\346\225\260\344\273\245\345\217\212\350\260\203\344\274\230\345\256\236\350\267\265.md" => "docs/java/jvm/temp/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232JVM\345\270\270\347\224\250\345\217\202\346\225\260\344\273\245\345\217\212\350\260\203\344\274\230\345\256\236\350\267\265.md" (98%)
diff --git a/ReadMe.md b/ReadMe.md
index dc53ae6..1a6c3a5 100644
--- a/ReadMe.md
+++ b/ReadMe.md
@@ -204,11 +204,11 @@ todo
* [深入理解JVM虚拟机:JNDI,OSGI,Tomcat类加载器实现](docs/java/jvm/深入理解JVM虚拟机:JNDI,OSGI,Tomcat类加载器实现.md)
* [深入了解JVM虚拟机:Java的编译期优化与运行期优化](docs/java/jvm/深入理解JVM虚拟机:Java的编译期优化与运行期优化.md)
* [深入理解JVM虚拟机:JVM监控工具与诊断实践](docs/java/jvm/深入理解JVM虚拟机:JVM监控工具与诊断实践.md)
-* [深入理解JVM虚拟机:JVM常用参数以及调优实践](docs/java/jvm/深入理解JVM虚拟机:JVM常用参数以及调优实践.md)
+* [深入理解JVM虚拟机:JVM常用参数以及调优实践](docs/java/jvm/temp/深入理解JVM虚拟机:JVM常用参数以及调优实践.md)
* [深入理解JVM虚拟机:Java内存异常原理与实践](docs/java/jvm/深入理解JVM虚拟机:Java内存异常原理与实践.md)
* [深入理解JVM虚拟机:JVM性能管理神器VisualVM介绍与实战](docs/java/jvm/深入理解JVM虚拟机:JVM性能管理神器VisualVM介绍与实战.md)
* [深入理解JVM虚拟机:再谈四种引用及GC实践](docs/java/jvm/深入理解JVM虚拟机:再谈四种引用及GC实践.md)
-* [深入理解JVM虚拟机:GC调优思路与常用工具](docs/java/jvm/深入理解JVM虚拟机:GC调优思路与常用工具.md)
+* [深入理解JVM虚拟机:GC调优思路与常用工具](docs/java/jvm/temp/深入理解JVM虚拟机:GC调优思路与常用工具.md)
### Java网络编程
diff --git "a/docs/big-backEnd/\345\220\216\347\253\257\346\212\200\346\234\257\346\235\202\350\260\210\357\274\232\347\231\275\350\257\235\350\231\232\346\213\237\345\214\226\346\212\200\346\234\257.md" "b/docs/big-backEnd/\345\220\216\347\253\257\346\212\200\346\234\257\346\235\202\350\260\210\357\274\232\347\231\275\350\257\235\350\231\232\346\213\237\345\214\226\346\212\200\346\234\257.md"
index ec768cb..7896eb0 100644
--- "a/docs/big-backEnd/\345\220\216\347\253\257\346\212\200\346\234\257\346\235\202\350\260\210\357\274\232\347\231\275\350\257\235\350\231\232\346\213\237\345\214\226\346\212\200\346\234\257.md"
+++ "b/docs/big-backEnd/\345\220\216\347\253\257\346\212\200\346\234\257\346\235\202\350\260\210\357\274\232\347\231\275\350\257\235\350\231\232\346\213\237\345\214\226\346\212\200\346\234\257.md"
@@ -103,7 +103,7 @@
对于虚拟机内核来讲,只要将标志位设为虚拟机状态,则可以直接在CPU上执行大部分的指令,不需要虚拟化软件在中间转述,除非遇到特别敏感的指令,才需要将标志位设为物理机内核态运行,这样大大提高了效率。
-所以安装虚拟机的时候,务必要将物理CPU的这个标志位打开,是否打开对于Intel可以查看grep "vmx" /proc/cpuinfo,对于AMD可以查看grep "svm" /proc/cpuinfo
+所以安装虚拟机的时候,务必要将物理CPU的这个标志位打开,是否打开对于Intel可以查看grep"vmx" /proc/cpuinfo,对于AMD可以查看grep "svm" /proc/cpuinfo
这叫做硬件辅助虚拟化。
diff --git "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis \347\232\204\345\237\272\347\241\200\346\225\260\346\215\256\347\273\223\346\236\204\346\246\202\350\247\210.md" "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis \347\232\204\345\237\272\347\241\200\346\225\260\346\215\256\347\273\223\346\236\204\346\246\202\350\247\210.md"
index 9102d4d..9d78bed 100644
--- "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis \347\232\204\345\237\272\347\241\200\346\225\260\346\215\256\347\273\223\346\236\204\346\246\202\350\247\210.md"
+++ "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis \347\232\204\345\237\272\347\241\200\346\225\260\346\215\256\347\273\223\346\236\204\346\246\202\350\247\210.md"
@@ -114,7 +114,7 @@ Redis的字典由三个基础的数据结构组成。最底层的单位是哈希
union { void *val; uint64_t u64; int64_t s64; } v; // 指向下个哈希表节点,形成链表
struct dictEntry *next; } dictEntry;
````
-实际上哈希表节点就是一个单项列表的节点。保存了一下下一个节点的指针。 key 就是节点的键,v是这个节点的值。这个 v 既可以是一个指针,也可以是一个 `uint64_t`或者 `int64_t` 整数。*next 指向下一个节点。
+实际上哈希表节点就是一个单项列表的节点。保存了一下下一个节点的指针。 key 就是节点的键,v是这个节点的值。这个 v 既可以是一个指针,也可以是一个`uint64_t`或者`int64_t`整数。*next 指向下一个节点。
通过一个哈希表的数组把各个节点链接起来:
````
diff --git "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224intset.md" "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224intset.md"
index 95204c4..b8ffc6e 100644
--- "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224intset.md"
+++ "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224intset.md"
@@ -84,7 +84,7 @@ typedef struct intset {
* `encoding`: 数据编码,表示intset中的每个数据元素用几个字节来存储。它有三种可能的取值:INTSET_ENC_INT16表示每个元素用2个字节存储,INTSET_ENC_INT32表示每个元素用4个字节存储,INTSET_ENC_INT64表示每个元素用8个字节存储。因此,intset中存储的整数最多只能占用64bit。
* `length`: 表示intset中的元素个数。`encoding`和`length`两个字段构成了intset的头部(header)。
-* `contents`: 是一个柔性数组([flexible array member](https://en.wikipedia.org/wiki/Flexible_array_member)),表示intset的header后面紧跟着数据元素。这个数组的总长度(即总字节数)等于`encoding * length`。柔性数组在Redis的很多数据结构的定义中都出现过(例如[sds](http://zhangtielei.com/posts/blog-redis-sds.html), [quicklist](http://zhangtielei.com/posts/blog-redis-quicklist.html), [skiplist](http://zhangtielei.com/posts/blog-redis-skiplist.html)),用于表达一个偏移量。`contents`需要单独为其分配空间,这部分内存不包含在intset结构当中。
+* `contents`: 是一个柔性数组([flexible array member](https://en.wikipedia.org/wiki/Flexible_array_member)),表示intset的header后面紧跟着数据元素。这个数组的总长度(即总字节数)等于`encoding * length`。柔性数组在Redis的很多数据结构的定义中都出现过(例如[sds](http://zhangtielei.com/posts/blog-redis-sds.html),[quicklist](http://zhangtielei.com/posts/blog-redis-quicklist.html),[skiplist](http://zhangtielei.com/posts/blog-redis-skiplist.html)),用于表达一个偏移量。`contents`需要单独为其分配空间,这部分内存不包含在intset结构当中。
其中需要注意的是,intset可能会随着数据的添加而改变它的数据编码:
@@ -97,7 +97,7 @@ typedef struct intset {
在上图中:
-* 新创建的intset只有一个header,总共8个字节。其中`encoding` = 2, `length` = 0。
+* 新创建的intset只有一个header,总共8个字节。其中`encoding`= 2,`length`= 0。
* 添加13, 5两个元素之后,因为它们是比较小的整数,都能使用2个字节表示,所以`encoding`不变,值还是2。
* 当添加32768的时候,它不再能用2个字节来表示了(2个字节能表达的数据范围是-215~215-1,而32768等于215,超出范围了),因此`encoding`必须升级到INTSET_ENC_INT32(值为4),即用4个字节表示一个元素。
* 在添加每个元素的过程中,intset始终保持从小到大有序。
@@ -247,11 +247,11 @@ intset *intsetAdd(intset *is, int64_t value, uint8_t *success) {
* `sadd`用于分别向集合`s1`和`s2`中添加元素。添加的元素既有数字,也有非数字(”a”和”b”)。
* `sismember`用于判断指定的元素是否在集合内存在。
-* `sinter`, `sunion`和`sdiff`分别用于计算集合的交集、并集和差集。
+* `sinter`,`sunion`和`sdiff`分别用于计算集合的交集、并集和差集。
我们前面提到过,set的底层实现,随着元素类型是否是整型以及添加的元素的数目多少,而有所变化。例如,具体到上述命令的执行过程中,集合`s1`的底层数据结构会发生如下变化:
-* 在开始执行完`sadd s1 13 5`之后,由于添加的都是比较小的整数,所以`s1`底层是一个intset,其数据编码`encoding` = 2。
+* 在开始执行完`sadd s1 13 5`之后,由于添加的都是比较小的整数,所以`s1`底层是一个intset,其数据编码`encoding`= 2。
* 在执行完`sadd s1 32768 10 100000`之后,`s1`底层仍然是一个intset,但其数据编码`encoding`从2升级到了4。
* 在执行完`sadd s1 a b`之后,由于添加的元素不再是数字,`s1`底层的实现会转成一个dict。
diff --git "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224ziplist.md" "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224ziplist.md"
index ea7ce4b..85e3de6 100644
--- "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224ziplist.md"
+++ "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\206\205\351\203\250\346\225\260\346\215\256\347\273\223\346\236\204\350\257\246\350\247\243\342\200\224\342\200\224ziplist.md"
@@ -69,7 +69,7 @@ ziplist的数据结构组成是本文要讨论的重点。实际上,ziplist还
* ``: 表示真正存放数据的数据项,长度不定。一个数据项(entry)也有它自己的内部结构,这个稍后再解释。
* ``: ziplist最后1个字节,是一个结束标记,值固定等于255。
-上面的定义中还值得注意的一点是:``, ``, ``既然占据多个字节,那么在存储的时候就有大端(big endian)和小端(little endian)的区别。ziplist采取的是小端模式来存储,这在下面我们介绍具体例子的时候还会再详细解释。
+上面的定义中还值得注意的一点是:``,``,``既然占据多个字节,那么在存储的时候就有大端(big endian)和小端(little endian)的区别。ziplist采取的是小端模式来存储,这在下面我们介绍具体例子的时候还会再详细解释。
我们再来看一下每一个数据项``的构成:
@@ -207,7 +207,7 @@ static unsigned char *__ziplistInsert(unsigned char *zl, unsigned char *p, unsig
* 这个函数是在指定的位置p插入一段新的数据,待插入数据的地址指针是s,长度为slen。插入后形成一个新的数据项,占据原来p的配置,原来位于p位置的数据项以及后面的所有数据项,需要统一向后移动,给新插入的数据项留出空间。参数p指向的是ziplist中某一个数据项的起始位置,或者在向尾端插入的时候,它指向ziplist的结束标记``。
* 函数开始先计算出待插入位置前一个数据项的长度`prevlen`。这个长度要存入新插入的数据项的``字段。
-* 然后计算当前数据项占用的总字节数`reqlen`,它包含三部分:``, ``和真正的数据。其中的数据部分会通过调用`zipTryEncoding`先来尝试转成整数。
+* 然后计算当前数据项占用的总字节数`reqlen`,它包含三部分:``,``和真正的数据。其中的数据部分会通过调用`zipTryEncoding`先来尝试转成整数。
* 由于插入导致的ziplist对于内存的新增需求,除了待插入数据项占用的`reqlen`之外,还要考虑原来p位置的数据项(现在要排在待插入数据项之后)的``字段的变化。本来它保存的是前一项的总长度,现在变成了保存当前插入的数据项的总长度。这样它的``字段本身需要的存储空间也可能发生变化,这个变化可能是变大也可能是变小。这个变化了多少的值`nextdiff`,是调用`zipPrevLenByteDiff`计算出来的。如果变大了,`nextdiff`是正值,否则是负值。
* 现在很容易算出来插入后新的ziplist需要多少字节了,然后调用`ziplistResize`来重新调整大小。ziplistResize的实现里会调用allocator的`zrealloc`,它有可能会造成数据拷贝。
* 现在额外的空间有了,接下来就是将原来p位置的数据项以及后面的所有数据都向后挪动,并为它设置新的``字段。此外,还可能需要调整ziplist的``字段。
@@ -223,7 +223,7 @@ hash是Redis中可以用来存储一个对象结构的比较理想的数据类
实际上,hash随着数据的增大,其底层数据结构的实现是会发生变化的,当然存储效率也就不同。在field比较少,各个value值也比较小的时候,hash采用ziplist来实现;而随着field增多和value值增大,hash可能会变成dict来实现。当hash底层变成dict来实现的时候,它的存储效率就没法跟那些序列化方式相比了。
-当我们为某个key第一次执行 `hset key field value` 命令的时候,Redis会创建一个hash结构,这个新创建的hash底层就是一个ziplist。
+当我们为某个key第一次执行`hset key field value`命令的时候,Redis会创建一个hash结构,这个新创建的hash底层就是一个ziplist。
diff --git "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\210\206\345\270\203\345\274\217\351\224\201\350\277\233\345\214\226\345\217\262.md" "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\210\206\345\270\203\345\274\217\351\224\201\350\277\233\345\214\226\345\217\262.md"
index 628426d..4a2ea7d 100644
--- "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\210\206\345\270\203\345\274\217\351\224\201\350\277\233\345\214\226\345\217\262.md"
+++ "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232Redis\345\210\206\345\270\203\345\274\217\351\224\201\350\277\233\345\214\226\345\217\262.md"
@@ -101,7 +101,7 @@ release(){
tryLock(){ SETNX Key 1 Seconds}release(){ DELETE Key}
```
-Redis 2.6.12版本后SETNX增加过期时间参数,这样就解决了两条命令无法保证原子性的问题。但是设想下面一个场景:
+Redis 2.6.12版本后SETNX增加过期时间参数,这样就解决了两条命令无法保证原子性的问题。但是设想下面一个场景:
1\. C1成功获取到了锁,之后C1因为GC进入等待或者未知原因导致任务执行过长,最后在锁失效前C1没有主动释放锁
@@ -167,7 +167,7 @@ release(){
```
-Redis 2.6.12后[SET](https://redis.io/commands/set)同样提供了一个NX参数,等同于SETNX命令,官方文档上提醒后面的版本有可能去掉[SETNX](https://redis.io/commands/setnx), [SETEX](https://redis.io/commands/setex), [PSETEX](https://redis.io/commands/psetex),并用SET命令代替,另外一个优化是使用一个自增的唯一UniqId代替时间戳来规避V3.0提到的时钟问题。
+Redis 2.6.12后[SET](https://redis.io/commands/set)同样提供了一个NX参数,等同于SETNX命令,官方文档上提醒后面的版本有可能去掉[SETNX](https://redis.io/commands/setnx),[SETEX](https://redis.io/commands/setex),[PSETEX](https://redis.io/commands/psetex),并用SET命令代替,另外一个优化是使用一个自增的唯一UniqId代替时间戳来规避V3.0提到的时钟问题。
这个方案是目前最优的分布式锁方案,但是如果在Redis集群环境下依然存在问题:
@@ -175,7 +175,7 @@ Redis 2.6.12后[SET](https://redis.io/commands/set)同样提供了一个NX参数
### 分布式Redis锁:Redlock
-V3.1的版本仅在单实例的场景下是安全的,针对如何实现分布式Redis的锁,国外的分布式专家有过激烈的讨论, antirez提出了分布式锁算法Redlock,在[distlock](https://redis.io/topics/distlock)话题下可以看到对Redlock的详细说明,下面是Redlock算法的一个中文说明(引用)
+V3.1的版本仅在单实例的场景下是安全的,针对如何实现分布式Redis的锁,国外的分布式专家有过激烈的讨论,antirez提出了分布式锁算法Redlock,在[distlock](https://redis.io/topics/distlock)话题下可以看到对Redlock的详细说明,下面是Redlock算法的一个中文说明(引用)
假设有N个独立的Redis节点
diff --git "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232\344\275\277\347\224\250\345\277\253\347\205\247\345\222\214AOF\345\260\206Redis\346\225\260\346\215\256\346\214\201\344\271\205\345\214\226\345\210\260\347\241\254\347\233\230\344\270\255.md" "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232\344\275\277\347\224\250\345\277\253\347\205\247\345\222\214AOF\345\260\206Redis\346\225\260\346\215\256\346\214\201\344\271\205\345\214\226\345\210\260\347\241\254\347\233\230\344\270\255.md"
index 92e1875..b239d06 100644
--- "a/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232\344\275\277\347\224\250\345\277\253\347\205\247\345\222\214AOF\345\260\206Redis\346\225\260\346\215\256\346\214\201\344\271\205\345\214\226\345\210\260\347\241\254\347\233\230\344\270\255.md"
+++ "b/docs/cache/\346\216\242\347\264\242Redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260\357\274\232\344\275\277\347\224\250\345\277\253\347\205\247\345\222\214AOF\345\260\206Redis\346\225\260\346\215\256\346\214\201\344\271\205\345\214\226\345\210\260\347\241\254\347\233\230\344\270\255.md"
@@ -39,7 +39,7 @@
```
-Redis给我们提供了两种不同方式的持久化方法:快照(Snapshotting) 和 只追加文件(append-only-file)。
+Redis给我们提供了两种不同方式的持久化方法:快照(Snapshotting)和只追加文件(append-only-file)。
(1)名词简介
@@ -71,17 +71,17 @@ appendonly no #是否使用AOF持久化appendfsync everysec #多久执行一
一、创建快照的方式:
-(1)客户端通过向Redis发送`BGSAVE` 命令来创建快照。
+(1)客户端通过向Redis发送`BGSAVE`命令来创建快照。
使用BGSAVE的时候,Redis会调用fork来创建一个子进程,然后子进程负责将快照写到硬盘中,而父进程则继续处理命令请求。
使用场景:
-如果用户使用了save设置,例如:`save 60 1000` ,那么从Redis最近一次创建快照之后开始计算,当“60秒之内有1000次写入操作”这个条件满足的时候,Redis就会自动触发BGSAVE命令。
+如果用户使用了save设置,例如:`save 60 1000`,那么从Redis最近一次创建快照之后开始计算,当“60秒之内有1000次写入操作”这个条件满足的时候,Redis就会自动触发BGSAVE命令。
如果用户使用了多个save设置,那么当任意一个save配置满足条件的时候,Redis都会触发一次BGSAVE命令。
-(2)客户端通过向Redis发送`SAVE` 命令来创建快照。
+(2)客户端通过向Redis发送`SAVE`命令来创建快照。
接收到SAVE命令的Redis服务器在快照创建完毕之前将不再响应任何其他命令的请求。SAVE命令并不常用,我们通常只在没有足够的内存去执行BGSAVE命令的时候才会使用SAVE命令,或者即使等待持久化操作执行完毕也无所谓的情况下,才会使用这个命令;
@@ -149,7 +149,7 @@ Redis以每秒同步一次AOF文件的性能和不使用任何持久化特性时
三、重写/压缩AOF文件
-随着数据量的增大,AOF的文件可能会很大,这样在每次进行数据恢复的时候就会进行很长的时间,为了解决日益增大的AOF文件,用户可以向Redis发送`BGREWRITEAOF` 命令,这个命令会通过移除AOF文件中的冗余命令来重写AOF文件,是AOF文件的体检变得尽可能的小。
+随着数据量的增大,AOF的文件可能会很大,这样在每次进行数据恢复的时候就会进行很长的时间,为了解决日益增大的AOF文件,用户可以向Redis发送`BGREWRITEAOF`命令,这个命令会通过移除AOF文件中的冗余命令来重写AOF文件,是AOF文件的体检变得尽可能的小。
BGREWRITEAOF的工作原理和BGSAVE的原理很像:Redis会创建一个子进程,然后由子进程负责对AOF文件的重写操作。
@@ -157,7 +157,7 @@ BGREWRITEAOF的工作原理和BGSAVE的原理很像:Redis会创建一个子进
四、触发重写/压缩AOF文件条件设定
-AOF通过设置`auto-aof-rewrite-percentage` 和 `auto-aof-rewrite-min-size` 选项来自动执行BGREWRITEAOF。
+AOF通过设置`auto-aof-rewrite-percentage`和`auto-aof-rewrite-min-size`选项来自动执行BGREWRITEAOF。
其具体含义,通过实例可以看出,如下配置:
@@ -167,7 +167,7 @@ auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb
表示当前AOF的文件体积大于64MB,并且AOF文件的体积比上一次重写之后的体积变大了至少一倍(100%)的时候,Redis将执行重写BGREWRITEAOF命令。
-如果AOF重写执行的过于频繁的话,可以将`auto-aof-rewrite-percentage` 选项的值设置为100以上,这种最偶发就可以让Redis在AOF文件的体积变得更大之后才执行重写操作,不过,这也使得在进行数据恢复的时候执行的时间变得更加长一些。
+如果AOF重写执行的过于频繁的话,可以将`auto-aof-rewrite-percentage`选项的值设置为100以上,这种最偶发就可以让Redis在AOF文件的体积变得更大之后才执行重写操作,不过,这也使得在进行数据恢复的时候执行的时间变得更加长一些。
## 验证快照文件和AOF文件
@@ -179,7 +179,7 @@ redis-check-aofredis-check-dump
他们可以再系统发生故障的时候,检查快照和AOF文件的状态,并对有需要的情况对文件进行修复。
-如果用户在运行redis-check-aof命令的时候,指定了`--fix` 参数,那么程序将对AOF文件进行修复。
+如果用户在运行redis-check-aof命令的时候,指定了`--fix`参数,那么程序将对AOF文件进行修复。
程序修复AOF文件的方法很简单:他会扫描给定的AOF文件,寻找不正确或者不完整的命令,当发现第一个出现错误命令的时候,程序会删除出错命令以及出错命令之后的所有命令,只保留那些位于出错命令之前的正确命令。大部分情况,被删除的都是AOF文件末尾的不完整的写命令。
diff --git "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232MySQL\351\207\214\347\232\204\351\202\243\344\272\233\346\227\245\345\277\227\344\273\254.md" "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232MySQL\351\207\214\347\232\204\351\202\243\344\272\233\346\227\245\345\277\227\344\273\254.md"
index 6f69233..347ecee 100644
--- "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232MySQL\351\207\214\347\232\204\351\202\243\344\272\233\346\227\245\345\277\227\344\273\254.md"
+++ "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232MySQL\351\207\214\347\232\204\351\202\243\344\272\233\346\227\245\345\277\227\344\273\254.md"
@@ -1,15 +1,3 @@
-# 目录
-
-* [目录](#目录)
- * [重新学习MySQL数据库10:MySQL里的那些日志们](#重新学习mysql数据库10:mysql里的那些日志们)
- * [1.MySQL日志文件系统的组成](#1mysql日志文件系统的组成)
- * [2.错误日志](#2错误日志)
- * [3.InnoDB中的日志](#3innodb中的日志)
- * [4- 慢查询日志](#4--慢查询日志)
- * [5.二进制日志](#5二进制日志)
- * [总结](#总结)
-
-
# 目录
* [重新学习MySQL数据库10:MySQL里的那些日志们](#重新学习mysql数据库10:mysql里的那些日志们)
* [1.MySQL日志文件系统的组成](#1mysql日志文件系统的组成)
diff --git "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Mysql\347\264\242\345\274\225\345\256\236\347\216\260\345\216\237\347\220\206\345\222\214\347\233\270\345\205\263\346\225\260\346\215\256\347\273\223\346\236\204\347\256\227\346\263\225.md" "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Mysql\347\264\242\345\274\225\345\256\236\347\216\260\345\216\237\347\220\206\345\222\214\347\233\270\345\205\263\346\225\260\346\215\256\347\273\223\346\236\204\347\256\227\346\263\225.md"
index 7bd83de..b522104 100644
--- "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Mysql\347\264\242\345\274\225\345\256\236\347\216\260\345\216\237\347\220\206\345\222\214\347\233\270\345\205\263\346\225\260\346\215\256\347\273\223\346\236\204\347\256\227\346\263\225.md"
+++ "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240MySQL\346\225\260\346\215\256\345\272\223\357\274\232Mysql\347\264\242\345\274\225\345\256\236\347\216\260\345\216\237\347\220\206\345\222\214\347\233\270\345\205\263\346\225\260\346\215\256\347\273\223\346\236\204\347\256\227\346\263\225.md"
@@ -905,4 +905,4 @@ title的选择性不足0.0001(精确值为0.00001579),所以实在没有
[5] Codd, E. F. (1970). "A relational model of data for large shared data banks". Communications of the ACM, , Vol. 13, No. 6, pp. 377-387
-[6] MySQL5.1参考手册 - [http://dev.mysql.com/doc/refman/5.1/zh/index.html](http://dev.mysql.com/doc/refman/5.1/zh/index.html "http://dev.mysql.com/doc/refman/5.1/zh/index.html")
+[6] MySQL5.1参考手册 -[http://dev.mysql.com/doc/refman/5.1/zh/index.html](http://dev.mysql.com/doc/refman/5.1/zh/index.html "http://dev.mysql.com/doc/refman/5.1/zh/index.html")
diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\347\274\223\345\255\230\346\233\264\346\226\260\347\232\204\345\245\227\350\267\257.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\347\274\223\345\255\230\346\233\264\346\226\260\347\232\204\345\245\227\350\267\257.md"
index 77fc50a..22c4550 100644
--- "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\347\274\223\345\255\230\346\233\264\346\226\260\347\232\204\345\245\227\350\267\257.md"
+++ "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\357\274\232\347\274\223\345\255\230\346\233\264\346\226\260\347\232\204\345\245\227\350\267\257.md"
@@ -105,6 +105,6 @@ Write Back套路,一句说就是,在更新数据的时候,只更新缓存
3)在软件开发或设计中,我非常建议在之前先去参考一下已有的设计和思路,**看看相应的guideline,best practice或design pattern,吃透了已有的这些东西,再决定是否要重新发明轮子**。千万不要似是而非地,想当然的做软件设计。
-4)上面,我们没有考虑缓存(Cache)和持久层(Repository)的整体事务的问题。比如,更新Cache成功,更新数据库失败了怎么吗?或是反过来。关于这个事,如果你需要强一致性,你需要使用“两阶段提交协议”——prepare, commit/rollback,比如Java 7 的[XAResource](http://docs.oracle.com/javaee/7/api/javax/transaction/xa/XAResource.html),还有MySQL 5.7的 [XA Transaction](http://dev.mysql.com/doc/refman/5.7/en/xa.html),有些cache也支持XA,比如[EhCache](http://www.ehcache.org/documentation/3.0/xa.html)。当然,XA这样的强一致性的玩法会导致性能下降,关于分布式的事务的相关话题,你可以看看《[分布式系统的事务处理](https://coolshell.cn/articles/10910.html)》一文。
+4)上面,我们没有考虑缓存(Cache)和持久层(Repository)的整体事务的问题。比如,更新Cache成功,更新数据库失败了怎么吗?或是反过来。关于这个事,如果你需要强一致性,你需要使用“两阶段提交协议”——prepare, commit/rollback,比如Java 7 的[XAResource](http://docs.oracle.com/javaee/7/api/javax/transaction/xa/XAResource.html),还有MySQL 5.7的[XA Transaction](http://dev.mysql.com/doc/refman/5.7/en/xa.html),有些cache也支持XA,比如[EhCache](http://www.ehcache.org/documentation/3.0/xa.html)。当然,XA这样的强一致性的玩法会导致性能下降,关于分布式的事务的相关话题,你可以看看《[分布式系统的事务处理](https://coolshell.cn/articles/10910.html)》一文。
(全文完)
diff --git "a/docs/hxx/java/Java\345\267\245\347\250\213\345\270\210\344\277\256\347\202\274\344\271\213\350\267\257\357\274\210\346\240\241\346\213\233\346\200\273\347\273\223\357\274\211.md" "b/docs/hxx/java/Java\345\267\245\347\250\213\345\270\210\344\277\256\347\202\274\344\271\213\350\267\257\357\274\210\346\240\241\346\213\233\346\200\273\347\273\223\357\274\211.md"
index 221cd8f..cd1bd87 100644
--- "a/docs/hxx/java/Java\345\267\245\347\250\213\345\270\210\344\277\256\347\202\274\344\271\213\350\267\257\357\274\210\346\240\241\346\213\233\346\200\273\347\273\223\357\274\211.md"
+++ "b/docs/hxx/java/Java\345\267\245\347\250\213\345\270\210\344\277\256\347\202\274\344\271\213\350\267\257\357\274\210\346\240\241\346\213\233\346\200\273\347\273\223\357\274\211.md"
@@ -173,7 +173,7 @@
具体的面经都比较长,这里大概介绍一下面试的情况,然后我会放上面经的链接供大家查阅。
-**1 阿里面经**
+**1 阿里面经**
[阿里中间件研发面经](http://mp.weixin.qq.com/s?__biz=MzUyMDc5MTYxNA==&mid=2247483852&idx=1&sn=9ec90620478b35d63a4a971a2222095d&chksm=f9e5b29dce923b8b2b080151e4b6b78373ee3f3e6f75b69252fc00b1a009d85c6f96944ed6e6&scene=21#wechat_redirect)
@@ -189,7 +189,7 @@
阿里的面试体验还是比较好的,至少不要求手写算法,但是非常注重Java基础,中间件部门还会特别安排Java基础笔试。
-**2 腾讯面经**
+**2 腾讯面经**
[腾讯研发面经](http://mp.weixin.qq.com/s?__biz=MzUyMDc5MTYxNA==&mid=2247483849&idx=1&sn=f81fd42954589fb2deaf128026ddd856&chksm=f9e5b298ce923b8ef02ae36f7e9029fef0ddb7d5ae456dfa9d64c0073bebaacfb78fac4c8035&scene=21#wechat_redirect)
@@ -201,7 +201,7 @@ SNG的部门捞了我的简历,开始了面试,他们的技术栈主要是Ja
腾讯的面试一如既往地注重考查网络和操作系统,并且喜欢问Linux底层的一些知识,在这方面我还是有很多不足的。
-**3 百度面经**
+**3 百度面经**
[百度研发面经](http://mp.weixin.qq.com/s?__biz=MzUyMDc5MTYxNA==&mid=2247483857&idx=1&sn=214b0f93db93407a7ac5a5149778cbad&chksm=f9e5b280ce923b96fcd535b2ef639fee2de78f12aa961d525b21760b11a3b95c0879113c2944&scene=21#wechat_redirect)
@@ -213,7 +213,7 @@ SNG的部门捞了我的简历,开始了面试,他们的技术栈主要是Ja
百度的面试风格非常统一,每次面试基本都要到电脑上写算法,所以那段时间写算法写的头皮发麻。
-**4 网易面经**
+**4 网易面经**
[网易研发面经](http://mp.weixin.qq.com/s?__biz=MzUyMDc5MTYxNA==&mid=2247483875&idx=1&sn=fa9eaedd9cc3da172ad71d360c46a054&chksm=f9e5b2b2ce923ba443b91d56b24486d22b15bea16a4788e5ed3421906e84f8edd9ee10b2b306&scene=21#wechat_redirect)
@@ -225,7 +225,7 @@ SNG的部门捞了我的简历,开始了面试,他们的技术栈主要是Ja
网易的面试比我想象中的要难,面试官会问的问题都比较深,并且会让你写一些结合实践的代码。
-**5 头条面经**
+**5 头条面经**
[今日头条研发面经](http://mp.weixin.qq.com/s?__biz=MzUyMDc5MTYxNA==&mid=2247483869&idx=1&sn=eedb7aebcb90cf3d4fe2450ef2d99947&chksm=f9e5b28cce923b9a9b0852a1c998ec014eb1aeb0442916c9028da276be8db0b2934c92292961&scene=21#wechat_redirect)
diff --git "a/docs/hxx/java/\344\275\240\344\270\215\345\217\257\351\224\231\350\277\207\347\232\204Java\345\255\246\344\271\240\350\265\204\346\272\220\346\270\205\345\215\225.md" "b/docs/hxx/java/\344\275\240\344\270\215\345\217\257\351\224\231\350\277\207\347\232\204Java\345\255\246\344\271\240\350\265\204\346\272\220\346\270\205\345\215\225.md"
index 0b41820..2885cab 100644
--- "a/docs/hxx/java/\344\275\240\344\270\215\345\217\257\351\224\231\350\277\207\347\232\204Java\345\255\246\344\271\240\350\265\204\346\272\220\346\270\205\345\215\225.md"
+++ "b/docs/hxx/java/\344\275\240\344\270\215\345\217\257\351\224\231\350\277\207\347\232\204Java\345\255\246\344\271\240\350\265\204\346\272\220\346\270\205\345\215\225.md"
@@ -38,25 +38,25 @@ https://blog.csdn.net/a724888
总的来说算是比较全面了,做后端方向的同学可以参考一下。
-深入浅出Java核心技术
+深入浅出Java核心技术
https://blog.csdn.net/column/details/21930.html
本专栏主要介绍Java基础,并且会结合实现原理以及具体实例来讲解。同时还介绍了Java集合类,设计模式以及Java8的相关知识。
-深入理解JVM虚拟机
+深入理解JVM虚拟机
https://blog.csdn.net/column/details/21960.html
带你走进JVM的世界,整合高质量文章以阐述虚拟机的原理及相关技术,让开发者更好地了解Java的底层运行原理以及相应的调优方法。
-Java并发指南
+Java并发指南
https://blog.csdn.net/column/details/21961.html
本专栏主要介绍Java并发编程相关的基本原理以及进阶知识。主要包括Java多线程基础,Java并发编程基本原理以及JUC并发包的使用和源码解析。
-Java网络编程与NIO
+Java网络编程与NIO
https://blog.csdn.net/column/details/21963.html
@@ -64,7 +64,7 @@ Java网络编程一直是很重要的一部分内容,其中涉及了socket的
了解这部分知识对于理解网络编程有很多帮助。另外还补充了两个涉及NIO的重要技术:Tomcat和Netty。
-JavaWeb技术世界
+JavaWeb技术世界
https://blog.csdn.net/column/details/21850.html
@@ -72,7 +72,7 @@ https://blog.csdn.net/column/details/21850.html
我们不仅要了解怎么使用它们,更要去了解它们为什么出现,其中一些技术的实现原理是什么。
-Spring与SpringMVC源码解析
+Spring与SpringMVC源码解析
https://blog.csdn.net/column/details/21851.html
@@ -108,7 +108,7 @@ https://blog.csdn.net/column/details/25481.html
## Java工程师书单
-我之前专门写了一篇文章介绍了Java工程师的书单,可以这里重点列举一些好书,推荐给大家。
+我之前专门写了一篇文章介绍了Java工程师的书单,可以这里重点列举一些好书,推荐给大家。
完整内容可以参考这篇文章:
@@ -126,15 +126,15 @@ Java工程师必备书单
《Java核心技术卷一》 这本书还是比较适合入门的,当然,这种厚皮书要看完还是很有难度的,不过比起上面那本要简单一些
-《深入理解JVM虚拟机》 这本书是Java开发者必须看的书,很多jvm的文章都是提取这本书的内容。JVM是Java虚拟机,赋予了Java程序生命,所以好好看看把,我自己就已经看了三遍了。
+《深入理解JVM虚拟机》 这本书是Java开发者必须看的书,很多jvm的文章都是提取这本书的内容。JVM是Java虚拟机,赋予了Java程序生命,所以好好看看把,我自己就已经看了三遍了。
《Java并发编程艺术》 这本书是国内作者写的Java并发书籍,比上面那一本更简单易懂,适合作为并发编程的入门书籍,当然,学习并发原理之前,还是先把Java的多线程搞懂吧。
-《深入JavaWeb技术内幕》 这本书是Java Web的集大成之作,涵盖了大部分Java Web开发的知识点,不过一本书显然无法把所有细节都讲完,但是作为Java Web的入门或者进阶书籍来看的话还是很不错的。
+《深入JavaWeb技术内幕》 这本书是Java Web的集大成之作,涵盖了大部分Java Web开发的知识点,不过一本书显然无法把所有细节都讲完,但是作为Java Web的入门或者进阶书籍来看的话还是很不错的。
《Redis设计与实现》 该书全面而完整地讲解了 Redis 的内部运行机制,对 Redis 的大多数单机功能以及所有多机功能的实现原理进行了介绍。这本书把Redis的基本原理讲的一清二楚,包括数据结构,持久化,集群等内容,有空应该看看。
-《大型网站技术架构》 这本淘宝系技术指南还是非常值得推崇的,可以说是把大型网站的现代架构进行了一次简单的总结,内容涵盖了各方面,主要讲的是概念,很适合没接触过架构的同学入门。看完以后你会觉得后端技术原来这么博大精深。
+《大型网站技术架构》 这本淘宝系技术指南还是非常值得推崇的,可以说是把大型网站的现代架构进行了一次简单的总结,内容涵盖了各方面,主要讲的是概念,很适合没接触过架构的同学入门。看完以后你会觉得后端技术原来这么博大精深。
《分布式服务框架原理与实践》 上面那本书讲的是分布式架构的实践,而这本书更专注于分布式服务的原理讲解和对应实践,很好地讲述了分布式服务的基本概念,相关技术,以及解决方案等,对于想要学习分布式服务框架的同学来说是本好书。
@@ -176,9 +176,9 @@ https://www.zhihu.com/people/h2pl
## 技术大牛推荐
-1 江南白衣这位大大绝对是我的Java启蒙导师,他推荐的Java后端书架让我受益匪浅。
+1 江南白衣这位大大绝对是我的Java启蒙导师,他推荐的Java后端书架让我受益匪浅。
-2 码农翻身刘欣,一位工作15年的IBM架构师,用最浅显易懂的文章讲解技术的那些事,力荐,他的文章帮我解决了很多困惑。
+2 码农翻身刘欣,一位工作15年的IBM架构师,用最浅显易懂的文章讲解技术的那些事,力荐,他的文章帮我解决了很多困惑。
3 CoolShell陈皓老师的博客相信大家都看过,干货很多,酷壳应该算是国内最有影响力的个人博客了。
diff --git "a/docs/hxx/java/\346\210\221\347\232\204Java\347\247\213\346\213\233\351\235\242\347\273\217\345\244\247\345\220\210\351\233\206.md" "b/docs/hxx/java/\346\210\221\347\232\204Java\347\247\213\346\213\233\351\235\242\347\273\217\345\244\247\345\220\210\351\233\206.md"
index cbe57c4..ca3dce9 100644
--- "a/docs/hxx/java/\346\210\221\347\232\204Java\347\247\213\346\213\233\351\235\242\347\273\217\345\244\247\345\220\210\351\233\206.md"
+++ "b/docs/hxx/java/\346\210\221\347\232\204Java\347\247\213\346\213\233\351\235\242\347\273\217\345\244\247\345\220\210\351\233\206.md"
@@ -1,11 +1,11 @@
# 目录
-* [阿里面经 ](#阿里面经 )
-* [腾讯面经 ](#腾讯面经 )
-* [百度面经 ](#百度面经 )
-* [网易面经 ](#网易面经 )
-* [头条面经 ](#头条面经 )
-* [快手&拼多多面经 ](#快手拼多多面经 )
+* [阿里面经](#阿里面经)
+* [腾讯面经](#腾讯面经)
+* [百度面经](#百度面经)
+* [网易面经](#网易面经)
+* [头条面经](#头条面经)
+* [快手&拼多多面经](#快手拼多多面经)
* [京东&美团面经](#京东美团面经)
* [斗鱼面经](#斗鱼面经)
* [有赞面经](#有赞面经)
@@ -20,7 +20,7 @@

-# 阿里面经
+# 阿里面经
[阿里中间件研发面经](http://mp.weixin.qq.com/s?__biz=MzUyMDc5MTYxNA==&mid=2247483852&idx=1&sn=9ec90620478b35d63a4a971a2222095d&chksm=f9e5b29dce923b8b2b080151e4b6b78373ee3f3e6f75b69252fc00b1a009d85c6f96944ed6e6&scene=21#wechat_redirect)
@@ -36,7 +36,7 @@
阿里的面试体验还是比较好的,至少不要求手写算法,但是非常注重Java基础,中间件部门还会特别安排Java基础笔试。
-# 腾讯面经
+# 腾讯面经
[腾讯研发面经](http://mp.weixin.qq.com/s?__biz=MzUyMDc5MTYxNA==&mid=2247483849&idx=1&sn=f81fd42954589fb2deaf128026ddd856&chksm=f9e5b298ce923b8ef02ae36f7e9029fef0ddb7d5ae456dfa9d64c0073bebaacfb78fac4c8035&scene=21#wechat_redirect)
@@ -48,7 +48,7 @@ SNG的部门捞了我的简历,开始了面试,他们的技术栈主要是Ja
腾讯的面试一如既往地注重考查网络和操作系统,并且喜欢问Linux底层的一些知识,在这方面我还是有很多不足的。
-# 百度面经
+# 百度面经
[百度研发面经](http://mp.weixin.qq.com/s?__biz=MzUyMDc5MTYxNA==&mid=2247483857&idx=1&sn=214b0f93db93407a7ac5a5149778cbad&chksm=f9e5b280ce923b96fcd535b2ef639fee2de78f12aa961d525b21760b11a3b95c0879113c2944&scene=21#wechat_redirect)
@@ -60,7 +60,7 @@ SNG的部门捞了我的简历,开始了面试,他们的技术栈主要是Ja
百度的面试风格非常统一,每次面试基本都要到电脑上写算法,所以那段时间写算法写的头皮发麻。
-# 网易面经
+# 网易面经
[网易研发面经](http://mp.weixin.qq.com/s?__biz=MzUyMDc5MTYxNA==&mid=2247483875&idx=1&sn=fa9eaedd9cc3da172ad71d360c46a054&chksm=f9e5b2b2ce923ba443b91d56b24486d22b15bea16a4788e5ed3421906e84f8edd9ee10b2b306&scene=21#wechat_redirect)
@@ -72,7 +72,7 @@ SNG的部门捞了我的简历,开始了面试,他们的技术栈主要是Ja
网易的面试比我想象中的要难,面试官会问的问题都比较深,并且会让你写一些结合实践的代码。
-# 头条面经
+# 头条面经
[今日头条研发面经](http://mp.weixin.qq.com/s?__biz=MzUyMDc5MTYxNA==&mid=2247483869&idx=1&sn=eedb7aebcb90cf3d4fe2450ef2d99947&chksm=f9e5b28cce923b9a9b0852a1c998ec014eb1aeb0442916c9028da276be8db0b2934c92292961&scene=21#wechat_redirect)
@@ -82,7 +82,7 @@ SNG的部门捞了我的简历,开始了面试,他们的技术栈主要是Ja
然后就开始了一下午的视频面试,一共三轮技术面试,每一轮都要写代码,问问题的风格有点像腾讯,也喜欢问一些底层知识,让我有点懵逼。
-# 快手&拼多多面经
+# 快手&拼多多面经
[拼多多&快手研发面经](http://mp.weixin.qq.com/s?__biz=MzUyMDc5MTYxNA==&mid=2247483878&idx=1&sn=aaafff4b1171361ccd1d94708d2beaa0&chksm=f9e5b2b7ce923ba10140dff71dd3a0f9a20593434a32cec66929116bba196dc7496abf502884&scene=21#wechat_redirect)
diff --git "a/docs/hxx/\347\224\265\345\255\220\344\271\246.md" "b/docs/hxx/\347\224\265\345\255\220\344\271\246.md"
index b80bf2e..5908230 100644
--- "a/docs/hxx/\347\224\265\345\255\220\344\271\246.md"
+++ "b/docs/hxx/\347\224\265\345\255\220\344\271\246.md"
@@ -45,7 +45,7 @@
### 新手上路
- [用大白话告诉你 :Java 后端到底是在做什么?](http://mp.weixin.qq.com/s?__biz=MzUyOTk5NDQwOA==&mid=2247485885&idx=1&sn=0b3e02d09559ad0fe371ce915a77d7e0&chksm=fa59ce7acd2e476c501ca68b311de5abaf8021c5baa96fa24e0ca621acaaf4b1c64e2e16f3cb&scene=21#wechat_redirect)
+[用大白话告诉你 :Java 后端到底是在做什么?](http://mp.weixin.qq.com/s?__biz=MzUyOTk5NDQwOA==&mid=2247485885&idx=1&sn=0b3e02d09559ad0fe371ce915a77d7e0&chksm=fa59ce7acd2e476c501ca68b311de5abaf8021c5baa96fa24e0ca621acaaf4b1c64e2e16f3cb&scene=21#wechat_redirect)
[Java工程师学习指南(入门篇)](http://mp.weixin.qq.com/s?__biz=MzUyOTk5NDQwOA==&mid=2247484573&idx=2&sn=7baf8dfe36357264ab25010429644792&chksm=fa59c35acd2e4a4c24c5b55003136b6b8c5e778273714093b2df7a016d3bb0ed0c774573a7a4&scene=21#wechat_redirect)
@@ -198,15 +198,15 @@
[马云退隐前,在年会上说了最重要的三件事](http://mp.weixin.qq.com/s?__biz=MzUyOTk5NDQwOA==&mid=2247486268&idx=1&sn=dd13517634cd4f72f824278f93edebef&chksm=fa59ccfbcd2e45ed522c377ab3fa4554632f36c836e9b2e1490fb4748f4c0cdee9a4a99c91a6&scene=21#wechat_redirect)
- [那些拼命加班的程序员们,后来都怎么样了?](http://mp.weixin.qq.com/s?__biz=MzUyOTk5NDQwOA==&mid=2247485861&idx=1&sn=e90ac488593b4b7adb4ac46303e715be&chksm=fa59ce62cd2e477410c26233ed6518e34fdd772e27ea7538bddfac36a549a50cab29b27881f4&scene=21#wechat_redirect)
+[那些拼命加班的程序员们,后来都怎么样了?](http://mp.weixin.qq.com/s?__biz=MzUyOTk5NDQwOA==&mid=2247485861&idx=1&sn=e90ac488593b4b7adb4ac46303e715be&chksm=fa59ce62cd2e477410c26233ed6518e34fdd772e27ea7538bddfac36a549a50cab29b27881f4&scene=21#wechat_redirect)
- [互联网浪潮之下,聊聊 90 后所面临的困境](http://mp.weixin.qq.com/s?__biz=MzUyOTk5NDQwOA==&mid=2247485843&idx=1&sn=492c9d3f7c9e32de9da7d833013cb9b9&chksm=fa59ce54cd2e4742939a5eb42a470bf282dbc79cb6f38ac9ec0112af5282091a9f2cd3615104&scene=21#wechat_redirect)
+[互联网浪潮之下,聊聊 90 后所面临的困境](http://mp.weixin.qq.com/s?__biz=MzUyOTk5NDQwOA==&mid=2247485843&idx=1&sn=492c9d3f7c9e32de9da7d833013cb9b9&chksm=fa59ce54cd2e4742939a5eb42a470bf282dbc79cb6f38ac9ec0112af5282091a9f2cd3615104&scene=21#wechat_redirect)
- [程序员的工资到底花到哪里去了?](http://mp.weixin.qq.com/s?__biz=MzUyOTk5NDQwOA==&mid=2247485826&idx=1&sn=cc13da981115341666ae919dd2646cb4&chksm=fa59ce45cd2e475344776b1f7f52a6d281d96210e21229c5d2f300cfad585f712b636cf60427&scene=21#wechat_redirect)
+[程序员的工资到底花到哪里去了?](http://mp.weixin.qq.com/s?__biz=MzUyOTk5NDQwOA==&mid=2247485826&idx=1&sn=cc13da981115341666ae919dd2646cb4&chksm=fa59ce45cd2e475344776b1f7f52a6d281d96210e21229c5d2f300cfad585f712b636cf60427&scene=21#wechat_redirect)
- [互联网公司里都有哪些潜规则?](http://mp.weixin.qq.com/s?__biz=MzUyOTk5NDQwOA==&mid=2247485819&idx=1&sn=816e20fa37a2abd99fa714c1c13e0402&chksm=fa59cebccd2e47aa8572071dadbb301008cd425cf0de4d71978af82b44bd3554faacfa8ad462&scene=21#wechat_redirect)
+[互联网公司里都有哪些潜规则?](http://mp.weixin.qq.com/s?__biz=MzUyOTk5NDQwOA==&mid=2247485819&idx=1&sn=816e20fa37a2abd99fa714c1c13e0402&chksm=fa59cebccd2e47aa8572071dadbb301008cd425cf0de4d71978af82b44bd3554faacfa8ad462&scene=21#wechat_redirect)
- [大厂程序员的一天是如何度过的?](http://mp.weixin.qq.com/s?__biz=MzUyOTk5NDQwOA==&mid=2247485803&idx=1&sn=5814daaa71fb164d33d858311708f1c3&chksm=fa59ceaccd2e47baf573c73fcefbdc93e74becd8b9d4c533cf79404a3f90b2b6cdb46eee4e40&scene=21#wechat_redirect)
+[大厂程序员的一天是如何度过的?](http://mp.weixin.qq.com/s?__biz=MzUyOTk5NDQwOA==&mid=2247485803&idx=1&sn=5814daaa71fb164d33d858311708f1c3&chksm=fa59ceaccd2e47baf573c73fcefbdc93e74becd8b9d4c533cf79404a3f90b2b6cdb46eee4e40&scene=21#wechat_redirect)
### 职场心得:
diff --git "a/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232DispatcherServlet\347\232\204\345\210\235\345\247\213\345\214\226\344\270\216\350\257\267\346\261\202\350\275\254\345\217\221.md" "b/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232DispatcherServlet\347\232\204\345\210\235\345\247\213\345\214\226\344\270\216\350\257\267\346\261\202\350\275\254\345\217\221.md"
index df95f75..6390f87 100644
--- "a/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232DispatcherServlet\347\232\204\345\210\235\345\247\213\345\214\226\344\270\216\350\257\267\346\261\202\350\275\254\345\217\221.md"
+++ "b/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232DispatcherServlet\347\232\204\345\210\235\345\247\213\345\214\226\344\270\216\350\257\267\346\261\202\350\275\254\345\217\221.md"
@@ -160,12 +160,12 @@ initFrameworkServlet()方法是一个没有任何实现的空方法,除去一
this.webApplicationContext = initWebApplicationContext();
```
-这一句简单直白的代码,道破了FrameworkServlet这个类,在SpringMVC类体系中的设计目的,它是 用来抽离出建立 WebApplicationContext 上下文这个过程的。
+这一句简单直白的代码,道破了FrameworkServlet这个类,在SpringMVC类体系中的设计目的,它是用来抽离出建立WebApplicationContext上下文这个过程的。
initWebApplicationContext()方法,封装了建立Spring容器上下文的整个过程,方法内的逻辑如下:
1. 获取由ContextLoaderListener初始化并注册在ServletContext中的根上下文,记为rootContext
-2. 如果webApplicationContext已经不为空,表示这个Servlet类是通过编程式注册到容器中的(Servlet 3.0+中的ServletContext.addServlet() ),上下文也由编程式传入。若这个传入的上下文还没被初始化,将rootContext上下文设置为它的父上下文,然后将其初始化,否则直接使用。
+2. 如果webApplicationContext已经不为空,表示这个Servlet类是通过编程式注册到容器中的(Servlet 3.0+中的ServletContext.addServlet()),上下文也由编程式传入。若这个传入的上下文还没被初始化,将rootContext上下文设置为它的父上下文,然后将其初始化,否则直接使用。
3. 通过wac变量的引用是否为null,判断第2步中是否已经完成上下文的设置(即上下文是否已经用编程式方式传入),如果wac==null成立,说明该Servlet不是由编程式注册到容器中的。此时以contextAttribute属性的值为键,在ServletContext中查找上下文,查找得到,说明上下文已经以别的方式初始化并注册在contextAttribute下,直接使用。
4. 检查wac变量的引用是否为null,如果wac==null成立,说明2、3两步中的上下文初始化策略都没成功,此时调用createWebApplicationContext(rootContext),建立一个全新的以rootContext为父上下文的上下文,作为SpringMVC配置元素的容器上下文。大多数情况下我们所使用的上下文,就是这个新建的上下文。
5. 以上三种初始化上下文的策略,都会回调onRefresh(ApplicationContext context)方法(回调的方式根据不同策略有不同),onRefresh方法在DispatcherServlet类中被覆写,以上面得到的上下文为依托,完成SpringMVC中默认实现类的初始化。
diff --git "a/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\350\256\276\350\256\241\347\220\206\345\277\265\344\270\216DispatcherServlet.md" "b/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\350\256\276\350\256\241\347\220\206\345\277\265\344\270\216DispatcherServlet.md"
index 665ed2f..a33c502 100644
--- "a/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\350\256\276\350\256\241\347\220\206\345\277\265\344\270\216DispatcherServlet.md"
+++ "b/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\350\256\276\350\256\241\347\220\206\345\277\265\344\270\216DispatcherServlet.md"
@@ -106,7 +106,7 @@ HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}
```
-是的,第一步处理就这么简单的完成了。一个web请求经过处理后,会得到一个HandlerExecutionChain对象,这就是SpringMVC对URl映射给出的回答。需要留意的是,HandlerMapping接口的getHandler方法参数是HttpServletRequest,这意味着,HandlerMapping的实现类可以利用HttpServletRequest中的 所有信息来做出这个HandlerExecutionChain对象的生成”决策“。这包括,请求头、url路径、cookie、session、参数等等一切你从一个web请求中可以得到的任何东西(最常用的是url路径)。
+是的,第一步处理就这么简单的完成了。一个web请求经过处理后,会得到一个HandlerExecutionChain对象,这就是SpringMVC对URl映射给出的回答。需要留意的是,HandlerMapping接口的getHandler方法参数是HttpServletRequest,这意味着,HandlerMapping的实现类可以利用HttpServletRequest中的所有信息来做出这个HandlerExecutionChain对象的生成”决策“。这包括,请求头、url路径、cookie、session、参数等等一切你从一个web请求中可以得到的任何东西(最常用的是url路径)。
SpirngMVC的第一个扩展点,就出现在这里。我们可以编写任意的HandlerMapping实现类,依据任何策略来决定一个web请求到HandlerExecutionChain对象的生成。可以说,从第一个核心接口的声明开始,SpringMVC就把自己的灵活性和野心暴露无疑:哥玩的就是”Open-Closed“。
diff --git "a/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232Mybatis\345\205\245\351\227\250.md" "b/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232Mybatis\345\205\245\351\227\250.md"
index 77b8926..fa50a2b 100644
--- "a/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232Mybatis\345\205\245\351\227\250.md"
+++ "b/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232Mybatis\345\205\245\351\227\250.md"
@@ -252,7 +252,7 @@ Mybatis通过执行器与Mappered Statement的结合实现与数据库的交互
## 测试工程搭建
-1. 新建maven工程
+1.新建maven工程

diff --git "a/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232\344\273\216\346\211\213\345\212\250\347\274\226\350\257\221\346\211\223\345\214\205\345\210\260\351\241\271\347\233\256\346\236\204\345\273\272\345\267\245\345\205\267Maven.md" "b/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232\344\273\216\346\211\213\345\212\250\347\274\226\350\257\221\346\211\223\345\214\205\345\210\260\351\241\271\347\233\256\346\236\204\345\273\272\345\267\245\345\205\267Maven.md"
index d04ef0d..7f80e4f 100644
--- "a/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232\344\273\216\346\211\213\345\212\250\347\274\226\350\257\221\346\211\223\345\214\205\345\210\260\351\241\271\347\233\256\346\236\204\345\273\272\345\267\245\345\205\267Maven.md"
+++ "b/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232\344\273\216\346\211\213\345\212\250\347\274\226\350\257\221\346\211\223\345\214\205\345\210\260\351\241\271\347\233\256\346\236\204\345\273\272\345\267\245\345\205\267Maven.md"
@@ -90,7 +90,7 @@ Maven不仅是构建工具,还是一个依赖管理工具和项目管理工具
[](http://upload-images.jianshu.io/upload_images/5811881-7482108a7ff71031.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "image.png")
-三:最后设置一下环境变量,将Maven安装配置到操作系统环境中,主要就是配置M2_HOME 和PATH两项,如图
+三:最后设置一下环境变量,将Maven安装配置到操作系统环境中,主要就是配置M2_HOME和PATH两项,如图
[](http://upload-images.jianshu.io/upload_images/5811881-ffdf167e64415703.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "image.png")
都搞定后,验证一下,打开doc输入 mvn -v如何得到下面信息就说明配置成功了
@@ -187,7 +187,7 @@ name元素生命了一个对于用户更为友好的项目名称,虽然这不
依赖范围就是用来控制依赖和三种classpath(编译classpath,测试classpath、运行classpath)的关系,Maven有如下几种依赖范围:
* compile:编译依赖范围。如果没有指定,就会默认使用该依赖范围。使用此依赖范围的Maven依赖,对于编译、测试、运行三种classpath都有效。典型的例子是spring-code,在编译、测试和运行的时候都需要使用该依赖。
-* test: 测试依赖范围。使用次依赖范围的Maven依赖,只对于测试classpath有效,在编译主代码或者运行项目的使用时将无法使用此依赖。典型的例子是Jnuit,它只有在编译测试代码及运行测试的时候才需要。
+* test:测试依赖范围。使用次依赖范围的Maven依赖,只对于测试classpath有效,在编译主代码或者运行项目的使用时将无法使用此依赖。典型的例子是Jnuit,它只有在编译测试代码及运行测试的时候才需要。
* provided:已提供依赖范围。使用此依赖范围的Maven依赖,对于编译和测试classpath有效,但在运行时候无效。典型的例子是servlet-api,编译和测试项目的时候需要该依赖,但在运行项目的时候,由于容器以及提供,就不需要Maven重复地引入一遍。
* runtime:运行时依赖范围。使用此依赖范围的Maven依赖,对于测试和运行classpath有效,但在编译主代码时无效。典型的例子是JDBC驱动实现,项目主代码的编译只需要JDK提供的JDBC接口,只有在执行测试或者运行项目的时候才需要实现上述接口的具体JDBC驱动。
* system:系统依赖范围。该依赖与三种classpath的关系,和provided依赖范围完全一致,但是,使用system范围的依赖时必须通过systemPath元素显示地指定依赖文件的路径。由于此类依赖不是通过Maven仓库解析的,而且往往与本机系统绑定,可能构成构建的不可移植,因此应该谨慎使用。systemPath元素可以引用环境变量,如:
diff --git "a/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232\346\236\201\347\256\200\351\205\215\347\275\256\347\232\204SpringBoot.md" "b/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232\346\236\201\347\256\200\351\205\215\347\275\256\347\232\204SpringBoot.md"
index 8384ba1..adaa923 100644
--- "a/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232\346\236\201\347\256\200\351\205\215\347\275\256\347\232\204SpringBoot.md"
+++ "b/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232\346\236\201\347\256\200\351\205\215\347\275\256\347\232\204SpringBoot.md"
@@ -120,7 +120,7 @@ public class HelloController {
@RequestMapping("/hello") public String hello() { return "Hello Spring Boot!"; }}
```
-* **@RestController 注解:** 该注解是 @Controller 和 @ResponseBody 注解的合体版
+* **@RestController 注解:**该注解是 @Controller 和 @ResponseBody 注解的合体版
#### 第三步:利用 IDEA 启动 Spring Boot
@@ -163,7 +163,7 @@ public class HelloController {
org.springframework.boot spring-boot-maven-plugin
```
-我们可以看到一个比较陌生一些的标签 `` ,这个标签是在配置 Spring Boot 的父级依赖:
+我们可以看到一个比较陌生一些的标签``,这个标签是在配置 Spring Boot 的父级依赖:
```
@@ -176,12 +176,12 @@ public class HelloController {
#### 应用入口类
-Spring Boot 项目通常有一个名为 *Application 的入口类,入口类里有一个 main 方法, **这个 main 方法其实就是一个标准的 Javay 应用的入口方法。**
+Spring Boot 项目通常有一个名为 *Application 的入口类,入口类里有一个 main 方法,**这个 main 方法其实就是一个标准的 Javay 应用的入口方法。**
-**@SpringBootApplication** 是 Spring Boot 的核心注解,它是一个组合注解,该注解组合了:**@Configuration、@EnableAutoConfiguration、@ComponentScan;** 若不是用 @SpringBootApplication 注解也可以使用这三个注解代替。
+**@SpringBootApplication**是 Spring Boot 的核心注解,它是一个组合注解,该注解组合了:**@Configuration、@EnableAutoConfiguration、@ComponentScan;**若不是用 @SpringBootApplication 注解也可以使用这三个注解代替。
* 其中,**@EnableAutoConfiguration 让 Spring Boot 根据类路径中的 jar 包依赖为当前项目进行自动配置**,例如,添加了 spring-boot-starter-web 依赖,会自动添加 Tomcat 和 Spring MVC 的依赖,那么 Spring Boot 会对 Tomcat 和 Spring MVC 进行自动配置。
-* **Spring Boot 还会自动扫描 @SpringBootApplication 所在类的同级包以及下级包里的 Bean** ,所以入口类建议就配置在 grounpID + arctifactID 组合的包名下(这里为 cn.wmyskxz.springboot 包)
+* **Spring Boot 还会自动扫描 @SpringBootApplication 所在类的同级包以及下级包里的 Bean**,所以入口类建议就配置在 grounpID + arctifactID 组合的包名下(这里为 cn.wmyskxz.springboot 包)
#### Spring Boot 的配置文件
@@ -209,7 +209,7 @@ Spring Boot 的全局配置文件的作用是对一些默认配置的配置值

-* **注意:** 我们并没有在 yml 文件中注明属性的类型,而是在使用的时候定义的。
+* **注意:**我们并没有在 yml 文件中注明属性的类型,而是在使用的时候定义的。
你也可以在配置文件中使用当前配置:
@@ -219,7 +219,7 @@ Spring Boot 的全局配置文件的作用是对一些默认配置的配置值

-* **问题:** 这样写配置文件繁琐而且可能会造成类的臃肿,因为有许许多多的 @Value 注解。
+* **问题:**这样写配置文件繁琐而且可能会造成类的臃肿,因为有许许多多的 @Value 注解。
> * 封装配置信息
diff --git "a/docs/java/basic/javac\345\222\214javap.md" "b/docs/java/basic/javac\345\222\214javap.md"
index 5f85010..f797af7 100644
--- "a/docs/java/basic/javac\345\222\214javap.md"
+++ "b/docs/java/basic/javac\345\222\214javap.md"
@@ -18,14 +18,7 @@
* [-encoding](#-encoding)
* [-verbose](#-verbose)
* [其他命令](#其他命令)
- * [使用javac构建项目](#使用javac构建项目)
- * [](#)
-* [java文件列表目录](#java文件列表目录)
- * [放入列表文件中](#放入列表文件中)
- * [生成bin目录](#生成bin目录)
- * [列表](#列表)
- * [通过-cp指定所有的引用jar包,将src下的所有java文件进行编译](#通过-cp指定所有的引用jar包,将src下的所有java文件进行编译)
- * [通过-cp指定所有的引用jar包,指定入口函数运行](#通过-cp指定所有的引用jar包,指定入口函数运行)
+ * [使用javac构建项目](#使用javac构建项目)
* [javap 的使用](#javap-的使用)
* [参考文章](#参考文章)
diff --git "a/docs/java/basic/\344\273\243\347\240\201\345\235\227\345\222\214\344\273\243\347\240\201\346\211\247\350\241\214\351\241\272\345\272\217.md" "b/docs/java/basic/\344\273\243\347\240\201\345\235\227\345\222\214\344\273\243\347\240\201\346\211\247\350\241\214\351\241\272\345\272\217.md"
index 2e51bc0..7ebb784 100644
--- "a/docs/java/basic/\344\273\243\347\240\201\345\235\227\345\222\214\344\273\243\347\240\201\346\211\247\350\241\214\351\241\272\345\272\217.md"
+++ "b/docs/java/basic/\344\273\243\347\240\201\345\235\227\345\222\214\344\273\243\347\240\201\346\211\247\350\241\214\351\241\272\345\272\217.md"
@@ -38,7 +38,7 @@
## Java中的构造方法
### 构造方法简介
-构造方法是类的一种特殊方法,用来初始化类的一个新的对象。[Java](http://c.biancheng.net/java/) 中的每个类都有一个默认的构造方法,它必须具有和类名相同的名称,而且没有返回类型。构造方法的默认返回类型就是对象类型本身,并且构造方法不能被 static、final、synchronized、abstract 和 native 修饰。
+构造方法是类的一种特殊方法,用来初始化类的一个新的对象。[Java](http://c.biancheng.net/java/)中的每个类都有一个默认的构造方法,它必须具有和类名相同的名称,而且没有返回类型。构造方法的默认返回类型就是对象类型本身,并且构造方法不能被 static、final、synchronized、abstract 和 native 修饰。
提示:构造方法用于初始化一个新对象,所以用 static 修饰没有意义;构造方法不能被子类继承,所以用 final 和 abstract 修饰没有意义;多个线程不会同时创建内存地址相同的同一个对象,所以用 synchronized 修饰没有必要。
diff --git "a/docs/java/basic/\345\244\232\347\272\277\347\250\213.md" "b/docs/java/basic/\345\244\232\347\272\277\347\250\213.md"
index e40b5d0..35e3ada 100644
--- "a/docs/java/basic/\345\244\232\347\272\277\347\250\213.md"
+++ "b/docs/java/basic/\345\244\232\347\272\277\347\250\213.md"
@@ -80,7 +80,7 @@ Java 给多线程编程提供了内置的支持。 一条线程指的是进程
* **新建状态:**
- 使用 **new** 关键字和 **Thread** 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 **start()** 这个线程。
+ 使用**new**关键字和**Thread**类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序**start()**这个线程。
* **就绪状态:**
@@ -88,7 +88,7 @@ Java 给多线程编程提供了内置的支持。 一条线程指的是进程
* **运行状态:**
- 如果就绪状态的线程获取 CPU 资源,就可以执行 **run()**,此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
+ 如果就绪状态的线程获取 CPU 资源,就可以执行**run()**,此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
* **阻塞状态:**
diff --git "a/docs/java/basic/\350\247\243\350\257\273Java\344\270\255\347\232\204\345\233\236\350\260\203.md" "b/docs/java/basic/\350\247\243\350\257\273Java\344\270\255\347\232\204\345\233\236\350\260\203.md"
index 8a672ed..57e5237 100644
--- "a/docs/java/basic/\350\247\243\350\257\273Java\344\270\255\347\232\204\345\233\236\350\260\203.md"
+++ "b/docs/java/basic/\350\247\243\350\257\273Java\344\270\255\347\232\204\345\233\236\350\260\203.md"
@@ -3,9 +3,8 @@
* [多线程中的“回调”](#多线程中的回调)
* [Java回调机制实战](#java回调机制实战)
* [实例一 : 同步调用](#实例一-:-同步调用)
- * [1.1 同步调用代码](#11-同步调用代码)
- * [实例二:由浅入深](#实例二:由浅入深)
- * [实例三:Tom做题](#实例三:tom做题)
+ * [实例二:由浅入深](#实例二:由浅入深)
+ * [实例三:Tom做题](#实例三:tom做题)
* [参考文章](#参考文章)
diff --git "a/docs/java/collection/Java\351\233\206\345\220\210\350\257\246\350\247\243\357\274\232Iterator\357\274\214fail-fast\346\234\272\345\210\266\344\270\216\346\257\224\350\276\203\345\231\250.md" "b/docs/java/collection/Java\351\233\206\345\220\210\350\257\246\350\247\243\357\274\232Iterator\357\274\214fail-fast\346\234\272\345\210\266\344\270\216\346\257\224\350\276\203\345\231\250.md"
index c89b6ae..95169c6 100644
--- "a/docs/java/collection/Java\351\233\206\345\220\210\350\257\246\350\247\243\357\274\232Iterator\357\274\214fail-fast\346\234\272\345\210\266\344\270\216\346\257\224\350\276\203\345\231\250.md"
+++ "b/docs/java/collection/Java\351\233\206\345\220\210\350\257\246\350\247\243\357\274\232Iterator\357\274\214fail-fast\346\234\272\345\210\266\344\270\216\346\257\224\350\276\203\345\231\250.md"
@@ -6,12 +6,12 @@
* [fail-fast示例](#fail-fast示例)
* [fail-fast产生原因](#fail-fast产生原因)
* [fail-fast解决办法](#fail-fast解决办法)
-* [Comparable 和 Comparator](#comparable-和-comparator)
- * [Comparable](#comparable)
- * [Comparator](#comparator)
- * [Java8中使用lambda实现比较器](#java8中使用lambda实现比较器)
- * [总结](#总结)
- * [参考文章](#参考文章)
+ * [Comparable 和 Comparator](#comparable-和-comparator)
+ * [Comparable](#comparable)
+ * [Comparator](#comparator)
+ * [Java8中使用lambda实现比较器](#java8中使用lambda实现比较器)
+ * [总结](#总结)
+ * [参考文章](#参考文章)
本文参考 cmsblogs.com/p=1185
diff --git "a/docs/java/collection/Java\351\233\206\345\220\210\350\257\246\350\247\243\357\274\232\344\270\200\346\226\207\350\257\273\346\207\202ArrayList,Vector\344\270\216Stack\344\275\277\347\224\250\346\226\271\346\263\225\345\222\214\345\256\236\347\216\260\345\216\237\347\220\206.md" "b/docs/java/collection/Java\351\233\206\345\220\210\350\257\246\350\247\243\357\274\232\344\270\200\346\226\207\350\257\273\346\207\202ArrayList,Vector\344\270\216Stack\344\275\277\347\224\250\346\226\271\346\263\225\345\222\214\345\256\236\347\216\260\345\216\237\347\220\206.md"
index e228969..ed04968 100644
--- "a/docs/java/collection/Java\351\233\206\345\220\210\350\257\246\350\247\243\357\274\232\344\270\200\346\226\207\350\257\273\346\207\202ArrayList,Vector\344\270\216Stack\344\275\277\347\224\250\346\226\271\346\263\225\345\222\214\345\256\236\347\216\260\345\216\237\347\220\206.md"
+++ "b/docs/java/collection/Java\351\233\206\345\220\210\350\257\246\350\247\243\357\274\232\344\270\200\346\226\207\350\257\273\346\207\202ArrayList,Vector\344\270\216Stack\344\275\277\347\224\250\346\226\271\346\263\225\345\222\214\345\256\236\347\216\260\345\216\237\347\220\206.md"
@@ -13,9 +13,8 @@
* [初始容量和扩容](#初始容量和扩容)
* [线程安全](#线程安全-1)
* [Stack](#stack)
-* [Stack](#stack-1)
- * [三个集合类之间的区别](#三个集合类之间的区别)
- * [参考文章](#参考文章)
+ * [三个集合类之间的区别](#三个集合类之间的区别)
+ * [参考文章](#参考文章)
本文参考多篇优质技术博客,参考文章请在文末查看
@@ -464,11 +463,11 @@ vector大部分方法都使用了synchronized修饰符,所以他是线层安
# Stack
- 如果我们去查jdk的文档,我们会发现stack是在java.util这个包里。它对应的一个大致的类关系图如下:
+ 如果我们去查jdk的文档,我们会发现stack是在java.util这个包里。它对应的一个大致的类关系图如下:

- 通过继承Vector类,Stack类可以很容易的实现他本身的功能。因为大部分的功能在Vector里面已经提供支持了。
+ 通过继承Vector类,Stack类可以很容易的实现他本身的功能。因为大部分的功能在Vector里面已经提供支持了。
在Java中Stack类表示后进先出(LIFO)的对象堆栈。栈是一种非常常见的数据结构,它采用典型的先进后出的操作方式完成的。
diff --git "a/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232AQS\344\270\255\347\232\204\345\205\254\345\271\263\351\224\201\344\270\216\351\235\236\345\205\254\345\271\263\351\224\201\357\274\214Condtion.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232AQS\344\270\255\347\232\204\345\205\254\345\271\263\351\224\201\344\270\216\351\235\236\345\205\254\345\271\263\351\224\201\357\274\214Condtion.md"
index 7cacaae..eb10601 100644
--- "a/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232AQS\344\270\255\347\232\204\345\205\254\345\271\263\351\224\201\344\270\216\351\235\236\345\205\254\345\271\263\351\224\201\357\274\214Condtion.md"
+++ "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232AQS\344\270\255\347\232\204\345\205\254\345\271\263\351\224\201\344\270\216\351\235\236\345\205\254\345\271\263\351\224\201\357\274\214Condtion.md"
@@ -8,8 +8,8 @@
* [5\. 唤醒后检查中断状态](#5-唤醒后检查中断状态)
* [6\. 获取独占锁](#6-获取独占锁)
* [7\. 处理中断状态](#7-处理中断状态)
- * [* 带超时机制的 await](#-带超时机制的-await)
- * [* 不抛出 InterruptedException 的 await](#-不抛出-interruptedexception-的-await)
+ * [带超时机制的 await](#-带超时机制的-await)
+ * [不抛出 InterruptedException 的 await](#-不抛出-interruptedexception-的-await)
* [AbstractQueuedSynchronizer 独占锁的取消排队](#abstractqueuedsynchronizer-独占锁的取消排队)
* [再说 java 线程中断和 InterruptedException 异常](#再说-java-线程中断和-interruptedexception-异常)
* [线程中断](#线程中断)
diff --git "a/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232ForkJoin\345\271\266\345\217\221\346\241\206\346\236\266\344\270\216\345\267\245\344\275\234\347\252\203\345\217\226\347\256\227\346\263\225\345\211\226\346\236\220.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232ForkJoin\345\271\266\345\217\221\346\241\206\346\236\266\344\270\216\345\267\245\344\275\234\347\252\203\345\217\226\347\256\227\346\263\225\345\211\226\346\236\220.md"
index ca072a2..74fa6a0 100644
--- "a/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232ForkJoin\345\271\266\345\217\221\346\241\206\346\236\266\344\270\216\345\267\245\344\275\234\347\252\203\345\217\226\347\256\227\346\263\225\345\211\226\346\236\220.md"
+++ "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232ForkJoin\345\271\266\345\217\221\346\241\206\346\236\266\344\270\216\345\267\245\344\275\234\347\252\203\345\217\226\347\256\227\346\263\225\345\211\226\346\236\220.md"
@@ -27,7 +27,7 @@ Fork/Join框架是Java7提供的一个用于并行执行任务的框架, 是
## 简介
-通常,使用Java来开发一个简单的并发应用程序时,会创建一些**Runnable**对象,然后创建对应的**Thread** 对象来控制程序中这些线程的创建、执行以及线程的状态。自从Java 5开始引入了**Executor**和**ExecutorService**接口以及实现这两个接口的类(比如**ThreadPoolExecutor**)之后,使得Java在并发支持上得到了进一步的提升。
+通常,使用Java来开发一个简单的并发应用程序时,会创建一些**Runnable**对象,然后创建对应的**Thread**对象来控制程序中这些线程的创建、执行以及线程的状态。自从Java 5开始引入了**Executor**和**ExecutorService**接口以及实现这两个接口的类(比如**ThreadPoolExecutor**)之后,使得Java在并发支持上得到了进一步的提升。
**执行器框架(Executor Framework)**将任务的创建和执行进行了分离,通过这个框架,只需要实现**Runnable**接口的对象和使用**Executor**对象,然后将**Runnable**对象发送给执行器。执行器再负责运行这些任务所需要的线程,包括线程的创建,线程的管理以及线程的结束。
@@ -37,7 +37,7 @@ Fork/Join框架是Java7提供的一个用于并行执行任务的框架, 是

-没有固定的公式来决定问题的**参考大小(Reference Size)**,从而决定一个任务是需要进行拆分或不需要拆分,拆分与否仍是依赖于任务本身的特性。可以使用在任务中将要处理的元素的数目和任务执行所需要的时间来决定参考大小。测试不同的参考大小来决定解决问题最好的一个方案,将**ForkJoinPool**类看作一个特殊的 **Executor** 执行器类型。这个框架基于以下两种操作。
+没有固定的公式来决定问题的**参考大小(Reference Size)**,从而决定一个任务是需要进行拆分或不需要拆分,拆分与否仍是依赖于任务本身的特性。可以使用在任务中将要处理的元素的数目和任务执行所需要的时间来决定参考大小。测试不同的参考大小来决定解决问题最好的一个方案,将**ForkJoinPool**类看作一个特殊的**Executor**执行器类型。这个框架基于以下两种操作。
* **分解(Fork)**操作:当需要将一个任务拆分成更小的多个任务时,在框架中执行这些任务;
* **合并(Join)**操作:当一个主任务等待其创建的多个子任务的完成执行。
@@ -46,7 +46,7 @@ Fork/Join框架是Java7提供的一个用于并行执行任务的框架, 是
为了达到这个目标,通过**Fork/Join框架**执行的任务有以下限制。
-* 任务只能使用**fork()**和**join()** 操作当作同步机制。如果使用其他的同步机制,工作者线程就不能执行其他任务,当然这些任务是在同步操作里时。比如,如果在**Fork/Join 框架**中将一个任务休眠,正在执行这个任务的工作者线程在休眠期内不能执行另一个任务。
+* 任务只能使用**fork()**和**join()**操作当作同步机制。如果使用其他的同步机制,工作者线程就不能执行其他任务,当然这些任务是在同步操作里时。比如,如果在**Fork/Join 框架**中将一个任务休眠,正在执行这个任务的工作者线程在休眠期内不能执行另一个任务。
* 任务不能执行I/O操作,比如文件数据的读取与写入。
* 任务不能抛出非运行时异常(Checked Exception),必须在代码中处理掉这些异常。
diff --git "a/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232JMM\344\270\255\347\232\204final\345\205\263\351\224\256\345\255\227\350\247\243\346\236\220.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232JMM\344\270\255\347\232\204final\345\205\263\351\224\256\345\255\227\350\247\243\346\236\220.md"
index 2d825d4..f7fe31b 100644
--- "a/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232JMM\344\270\255\347\232\204final\345\205\263\351\224\256\345\255\227\350\247\243\346\236\220.md"
+++ "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232JMM\344\270\255\347\232\204final\345\205\263\351\224\256\345\255\227\350\247\243\346\236\220.md"
@@ -1,3 +1,12 @@
+# Table of Contents
+
+ * [一、properly constructed / this对象逸出](#一、properly-constructed--this对象逸出)
+ * [二、对象的安全发布](#二、对象的安全发布)
+ * [三、 final 关键字的内存语义](#三、-final-关键字的内存语义)
+ * [四、HotSpot VM中对final内存语义的实现](#四、hotspot-vm中对final内存语义的实现)
+* [参考文献](#参考文献)
+
+
**本文转载自互联网,侵删**
本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看
@@ -215,4 +224,4 @@ JSR 133 (Java Memory Model) FAQ
Java Concurrency in Practice
The JSR-133 Cookbook for Compiler Writers
-Intel® 64 and IA-32 ArchitecturesvSoftware Developer’s Manual Volume 3A: System Programming Guide, Part 1
\ No newline at end of file
+Intel® 64 and IA-32 ArchitecturesvSoftware Developer’s Manual Volume 3A: System Programming Guide, Part 1
diff --git "a/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232Java\344\270\255\347\232\204HashMap\345\222\214ConcurrentHashMap\345\205\250\350\247\243\346\236\220.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232Java\344\270\255\347\232\204HashMap\345\222\214ConcurrentHashMap\345\205\250\350\247\243\346\236\220.md"
index 6314e77..dff6cc3 100644
--- "a/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232Java\344\270\255\347\232\204HashMap\345\222\214ConcurrentHashMap\345\205\250\350\247\243\346\236\220.md"
+++ "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232Java\344\270\255\347\232\204HashMap\345\222\214ConcurrentHashMap\345\205\250\350\247\243\346\236\220.md"
@@ -345,7 +345,7 @@ public V put(K key, V value) {
第一层皮很简单,根据 hash 值很快就能找到相应的 Segment,之后就是 Segment 内部的 put 操作了。
-Segment 内部是由 **数组+链表** 组成的。
+Segment 内部是由**数组+链表**组成的。
```
final V put(K key, int hash, V value, boolean onlyIfAbsent) {
@@ -640,11 +640,11 @@ public V get(Object key) {
## Java8 HashMap
-Java8 对 HashMap 进行了一些修改,最大的不同就是利用了红黑树,所以其由 **数组+链表+红黑树** 组成。
+Java8 对 HashMap 进行了一些修改,最大的不同就是利用了红黑树,所以其由**数组+链表+红黑树**组成。
-根据 Java7 HashMap 的介绍,我们知道,查找的时候,根据 hash 值我们能够快速定位到数组的具体下标,但是之后的话,需要顺着链表一个个比较下去才能找到我们需要的,时间复杂度取决于链表的长度,为 **O(n)**。
+根据 Java7 HashMap 的介绍,我们知道,查找的时候,根据 hash 值我们能够快速定位到数组的具体下标,但是之后的话,需要顺着链表一个个比较下去才能找到我们需要的,时间复杂度取决于链表的长度,为**O(n)**。
-为了降低这部分的开销,在 Java8 中,当链表中的元素达到了 8 个时,会将链表转换为红黑树,在这些位置进行查找的时候可以降低时间复杂度为 **O(logN)**。
+为了降低这部分的开销,在 Java8 中,当链表中的元素达到了 8 个时,会将链表转换为红黑树,在这些位置进行查找的时候可以降低时间复杂度为**O(logN)**。
来一张图简单示意一下吧:
@@ -654,7 +654,7 @@ Java8 对 HashMap 进行了一些修改,最大的不同就是利用了红黑
下面,我们还是用代码来介绍吧,个人感觉,Java8 的源码可读性要差一些,不过精简一些。
-Java7 中使用 Entry 来代表每个 HashMap 中的数据节点,Java8 中使用 **Node**,基本没有区别,都是 key,value,hash 和 next 这四个属性,不过,Node 只能用于链表的情况,红黑树的情况需要使用 **TreeNode**。
+Java7 中使用 Entry 来代表每个 HashMap 中的数据节点,Java8 中使用**Node**,基本没有区别,都是 key,value,hash 和 next 这四个属性,不过,Node 只能用于链表的情况,红黑树的情况需要使用**TreeNode**。
我们根据数组元素中,第一个节点数据类型是 Node 还是 TreeNode 来判断该位置下是链表还是红黑树的。
@@ -1145,7 +1145,7 @@ private final void tryPresize(int size) {
这个方法的核心在于 sizeCtl 值的操作,首先将其设置为一个负数,然后执行 transfer(tab, null),再下一个循环将 sizeCtl 加 1,并执行 transfer(tab, nt),之后可能是继续 sizeCtl 加 1,并执行 transfer(tab, nt)。
-所以,可能的操作就是执行 **1 次 transfer(tab, null) + 多次 transfer(tab, nt)**,这里怎么结束循环的需要看完 transfer 源码才清楚。
+所以,可能的操作就是执行**1 次 transfer(tab, null) + 多次 transfer(tab, nt)**,这里怎么结束循环的需要看完 transfer 源码才清楚。
#### 数据迁移:transfer
diff --git "a/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232Java\350\257\273\345\206\231\351\224\201ReentrantReadWriteLock\346\272\220\347\240\201\345\210\206\346\236\220.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232Java\350\257\273\345\206\231\351\224\201ReentrantReadWriteLock\346\272\220\347\240\201\345\210\206\346\236\220.md"
index 50c20d6..a357d88 100644
--- "a/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232Java\350\257\273\345\206\231\351\224\201ReentrantReadWriteLock\346\272\220\347\240\201\345\210\206\346\236\220.md"
+++ "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232Java\350\257\273\345\206\231\351\224\201ReentrantReadWriteLock\346\272\220\347\240\201\345\210\206\346\236\220.md"
@@ -91,7 +91,7 @@ ReentrantReadWriteLock 分为读锁和写锁两个实例,读锁是共享锁,
很清楚了,ReadLock 和 WriteLock 中的方法都是通过 Sync 这个类来实现的。Sync 是 AQS 的子类,然后再派生了公平模式和不公平模式。
-从它们调用的 Sync 方法,我们可以看到: **ReadLock 使用了共享模式,WriteLock 使用了独占模式**。
+从它们调用的 Sync 方法,我们可以看到:**ReadLock 使用了共享模式,WriteLock 使用了独占模式**。
等等,**同一个 AQS 实例怎么可以同时使用共享模式和独占模式**???
@@ -99,7 +99,7 @@ ReentrantReadWriteLock 分为读锁和写锁两个实例,读锁是共享锁,

-AQS 的精髓在于内部的属性 **state**:
+AQS 的精髓在于内部的属性**state**:
1. 对于独占模式来说,通常就是 0 代表可获取锁,1 代表锁被别人获取了,重入例外
2. 而共享模式下,每个线程都可以对 state 进行加减操作
@@ -168,9 +168,9 @@ abstract static class Sync extends AbstractQueuedSynchronizer {
1. state 的高 16 位代表读锁的获取次数,包括重入次数,获取到读锁一次加 1,释放掉读锁一次减 1
2. state 的低 16 位代表写锁的获取次数,因为写锁是独占锁,同时只能被一个线程获得,所以它代表重入次数
-3. 每个线程都需要维护自己的 HoldCounter,记录该线程获取的读锁次数,这样才能知道到底是不是读锁重入,用 ThreadLocal 属性 **readHolds** 维护
-4. **cachedHoldCounter** 有什么用?其实没什么用,但能提示性能。将最后一次获取读锁的线程的 HoldCounter 缓存到这里,这样比使用 ThreadLocal 性能要好一些,因为 ThreadLocal 内部是基于 map 来查询的。但是 cachedHoldCounter 这一个属性毕竟只能缓存一个线程,所以它要起提升性能作用的依据就是:通常读锁的获取紧随着就是该读锁的释放。我这里可能表达不太好,但是大家应该是懂的吧。
-5. **firstReader** 和 **firstReaderHoldCount** 有什么用?其实也没什么用,但是它也能提示性能。将"第一个"获取读锁的线程记录在 firstReader 属性中,这里的**第一个**不是全局的概念,等这个 firstReader 当前代表的线程释放掉读锁以后,会有后来的线程占用这个属性的。**firstReader 和 firstReaderHoldCount 使得在读锁不产生竞争的情况下,记录读锁重入次数非常方便快速**
+3. 每个线程都需要维护自己的 HoldCounter,记录该线程获取的读锁次数,这样才能知道到底是不是读锁重入,用 ThreadLocal 属性**readHolds**维护
+4. **cachedHoldCounter**有什么用?其实没什么用,但能提示性能。将最后一次获取读锁的线程的 HoldCounter 缓存到这里,这样比使用 ThreadLocal 性能要好一些,因为 ThreadLocal 内部是基于 map 来查询的。但是 cachedHoldCounter 这一个属性毕竟只能缓存一个线程,所以它要起提升性能作用的依据就是:通常读锁的获取紧随着就是该读锁的释放。我这里可能表达不太好,但是大家应该是懂的吧。
+5. **firstReader**和**firstReaderHoldCount**有什么用?其实也没什么用,但是它也能提示性能。将"第一个"获取读锁的线程记录在 firstReader 属性中,这里的**第一个**不是全局的概念,等这个 firstReader 当前代表的线程释放掉读锁以后,会有后来的线程占用这个属性的。**firstReader 和 firstReaderHoldCount 使得在读锁不产生竞争的情况下,记录读锁重入次数非常方便快速**
6. 如果一个线程使用了 firstReader,那么它就不需要占用 cachedHoldCounter
7. 个人认为,读写锁源码中最让初学者头疼的就是这几个用于提升性能的属性了,使得大家看得云里雾里的。主要是因为 ThreadLocal 内部是通过一个 ThreadLocalMap 来操作的,会增加检索时间。而很多场景下,执行 unlock 的线程往往就是刚刚最后一次执行 lock 的线程,中间可能没有其他线程进行 lock。还有就是很多不怎么会发生读锁竞争的场景。
@@ -498,7 +498,7 @@ protected final boolean tryAcquire(int acquires) {
}
```
-下面看一眼 **writerShouldBlock()** 的判定,然后你再回去看一篇写锁获取过程。
+下面看一眼**writerShouldBlock()**的判定,然后你再回去看一篇写锁获取过程。
```
static final class NonfairSync extends Sync {
diff --git "a/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232\345\271\266\345\217\221\344\270\211\345\244\247\351\227\256\351\242\230\344\270\216volatile\345\205\263\351\224\256\345\255\227\357\274\214CAS\346\223\215\344\275\234.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232\345\271\266\345\217\221\344\270\211\345\244\247\351\227\256\351\242\230\344\270\216volatile\345\205\263\351\224\256\345\255\227\357\274\214CAS\346\223\215\344\275\234.md"
index 0abdbe8..60a9c3e 100644
--- "a/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232\345\271\266\345\217\221\344\270\211\345\244\247\351\227\256\351\242\230\344\270\216volatile\345\205\263\351\224\256\345\255\227\357\274\214CAS\346\223\215\344\275\234.md"
+++ "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232\345\271\266\345\217\221\344\270\211\345\244\247\351\227\256\351\242\230\344\270\216volatile\345\205\263\351\224\256\345\255\227\357\274\214CAS\346\223\215\344\275\234.md"
@@ -9,7 +9,6 @@
* [volatile写-读的内存语义](#volatile写-读的内存语义)
* [volatile内存语义的实现](#volatile内存语义的实现)
* [JSR-133为什么要增强volatile的内存语义](#jsr-133为什么要增强volatile的内存语义)
- * [](#)
* [引言](#引言)
* [术语定义](#术语定义)
* [3 处理器如何实现原子操作](#3-处理器如何实现原子操作)
diff --git "a/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232\346\267\261\345\205\245\347\220\206\350\247\243Java\345\206\205\345\255\230\346\250\241\345\236\213JMM.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232\346\267\261\345\205\245\347\220\206\350\247\243Java\345\206\205\345\255\230\346\250\241\345\236\213JMM.md"
index 0856914..a9aad6e 100644
--- "a/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232\346\267\261\345\205\245\347\220\206\350\247\243Java\345\206\205\345\255\230\346\250\241\345\236\213JMM.md"
+++ "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232\346\267\261\345\205\245\347\220\206\350\247\243Java\345\206\205\345\255\230\346\250\241\345\236\213JMM.md"
@@ -176,7 +176,7 @@ Java 语言在遵循内存模型的基础上推出了 JMM 规范,目的是解
我们知道,Java程序是需要运行在Java虚拟机上面的,**Java内存模型(Java Memory Model ,JMM)就是一种符合内存模型规范的,屏蔽了各种硬件和操作系统的访问差异的,保证了Java程序在各种平台下对内存的访问都能保证效果一致的机制及规范。**
-提到Java内存模型,一般指的是JDK 5 开始使用的新的内存模型,主要由[JSR-133: JavaTM Memory Model and Thread Specification](http://www.cs.umd.edu/~pugh/java/memoryModel/jsr133.pdf) 描述。感兴趣的可以参看下这份PDF文档([http://www.cs.umd.edu/~pugh/java/memoryModel/jsr133.pdf](http://www.cs.umd.edu/~pugh/java/memoryModel/jsr133.pdf))
+提到Java内存模型,一般指的是JDK 5 开始使用的新的内存模型,主要由[JSR-133: JavaTM Memory Model and Thread Specification](http://www.cs.umd.edu/~pugh/java/memoryModel/jsr133.pdf)描述。感兴趣的可以参看下这份PDF文档([http://www.cs.umd.edu/~pugh/java/memoryModel/jsr133.pdf](http://www.cs.umd.edu/~pugh/java/memoryModel/jsr133.pdf))
Java内存模型规定了所有的变量都存储在主内存中,每条线程还有自己的工作内存,线程的工作内存中保存了该线程中是用到的变量的主内存副本拷贝,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存。不同的线程之间也无法直接访问对方工作内存中的变量,线程间变量的传递均需要自己的工作内存和主存之间进行数据同步进行。
diff --git "a/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232\346\267\261\345\272\246\350\247\243\350\257\273Java\347\272\277\347\250\213\346\261\240\350\256\276\350\256\241\346\200\235\346\203\263\345\217\212\346\272\220\347\240\201\345\256\236\347\216\260.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232\346\267\261\345\272\246\350\247\243\350\257\273Java\347\272\277\347\250\213\346\261\240\350\256\276\350\256\241\346\200\235\346\203\263\345\217\212\346\272\220\347\240\201\345\256\236\347\216\260.md"
index b318132..aa025c9 100644
--- "a/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232\346\267\261\345\272\246\350\247\243\350\257\273Java\347\272\277\347\250\213\346\261\240\350\256\276\350\256\241\346\200\235\346\203\263\345\217\212\346\272\220\347\240\201\345\256\236\347\216\260.md"
+++ "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232\346\267\261\345\272\246\350\247\243\350\257\273Java\347\272\277\347\250\213\346\261\240\350\256\276\350\256\241\346\200\235\346\203\263\345\217\212\346\272\220\347\240\201\345\256\236\347\216\260.md"
@@ -92,7 +92,7 @@ public interface Executor {
}
```
-我们可以看到 Executor 接口非常简单,就一个 `void execute(Runnable command)` 方法,代表提交一个任务。为了让大家理解 java 线程池的整个设计方案,我会按照 Doug Lea 的设计思路来多说一些相关的东西。
+我们可以看到 Executor 接口非常简单,就一个`void execute(Runnable command)`方法,代表提交一个任务。为了让大家理解 java 线程池的整个设计方案,我会按照 Doug Lea 的设计思路来多说一些相关的东西。
我们经常这样启动一个线程:
@@ -171,7 +171,7 @@ class SerialExecutor implements Executor {
}
```
-当然了,Executor 这个接口只有提交任务的功能,太简单了,我们想要更丰富的功能,比如我们想知道执行结果、我们想知道当前线程池有多少个线程活着、已经完成了多少任务等等,这些都是这个接口的不足的地方。接下来我们要介绍的是继承自 `Executor` 接口的 `ExecutorService` 接口,这个接口提供了比较丰富的功能,也是我们最常使用到的接口。
+当然了,Executor 这个接口只有提交任务的功能,太简单了,我们想要更丰富的功能,比如我们想知道执行结果、我们想知道当前线程池有多少个线程活着、已经完成了多少任务等等,这些都是这个接口的不足的地方。接下来我们要介绍的是继承自`Executor`接口的`ExecutorService`接口,这个接口提供了比较丰富的功能,也是我们最常使用到的接口。
## ExecutorService
@@ -277,13 +277,13 @@ public interface Callable {
在这里,就不展开说 FutureTask 类了,因为本文篇幅本来就够大了,这里我们需要知道怎么用就行了。
-下面,我们来看看 `ExecutorService` 的抽象实现 `AbstractExecutorService` 。
+下面,我们来看看`ExecutorService`的抽象实现`AbstractExecutorService`。
## AbstractExecutorService
AbstractExecutorService 抽象类派生自 ExecutorService 接口,然后在其基础上实现了几个实用的方法,这些方法提供给子类进行调用。
-这个抽象类实现了 invokeAny 方法和 invokeAll 方法,这里的两个 newTaskFor 方法也比较有用,用于将任务包装成 FutureTask。定义于最上层接口 Executor中的 `void execute(Runnable command)` 由于不需要获取结果,不会进行 FutureTask 的包装。
+这个抽象类实现了 invokeAny 方法和 invokeAll 方法,这里的两个 newTaskFor 方法也比较有用,用于将任务包装成 FutureTask。定义于最上层接口 Executor中的`void execute(Runnable command)`由于不需要获取结果,不会进行 FutureTask 的包装。
> 需要获取结果(FutureTask),用 submit 方法,不需要获取结果,可以用 execute 方法。
@@ -600,7 +600,7 @@ public Future submit(Callable task) {
当然,上图没有考虑队列是否有界,提交任务时队列满了怎么办?什么情况下会创建新的线程?提交任务时线程池满了怎么办?空闲线程怎么关掉?这些问题下面我们会一一解决。
-我们经常会使用 `Executors` 这个工具类来快速构造一个线程池,对于初学者而言,这种工具类是很有用的,开发者不需要关注太多的细节,只要知道自己需要一个线程池,仅仅提供必需的参数就可以了,其他参数都采用作者提供的默认值。
+我们经常会使用`Executors`这个工具类来快速构造一个线程池,对于初学者而言,这种工具类是很有用的,开发者不需要关注太多的细节,只要知道自己需要一个线程池,仅仅提供必需的参数就可以了,其他参数都采用作者提供的默认值。
```
public static ExecutorService newFixedThreadPool(int nThreads) {
@@ -659,7 +659,7 @@ public static ExecutorService newCachedThreadPool() {
* keepAliveTime
- > 空闲线程的保活时间,如果某线程的空闲时间超过这个值都没有任务给它做,那么可以被关闭了。注意这个值并不会对所有线程起作用,如果线程池中的线程数少于等于核心线程数 corePoolSize,那么这些线程不会因为空闲太长时间而被关闭,当然,也可以通过调用 `allowCoreThreadTimeOut(true)`使核心线程数内的线程也可以被回收。
+ > 空闲线程的保活时间,如果某线程的空闲时间超过这个值都没有任务给它做,那么可以被关闭了。注意这个值并不会对所有线程起作用,如果线程池中的线程数少于等于核心线程数 corePoolSize,那么这些线程不会因为空闲太长时间而被关闭,当然,也可以通过调用`allowCoreThreadTimeOut(true)`使核心线程数内的线程也可以被回收。
* threadFactory
diff --git "a/docs/java/concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\255\246\344\271\240\346\200\273\347\273\223.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\255\246\344\271\240\346\200\273\347\273\223.md"
index f5ab376..98f3e38 100644
--- "a/docs/java/concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\255\246\344\271\240\346\200\273\347\273\223.md"
+++ "b/docs/java/concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\255\246\344\271\240\346\200\273\347\273\223.md"
@@ -9,7 +9,6 @@
* [Lock类](#lock类)
* [AQS](#aqs)
* [锁Lock和Conditon](#锁lock和conditon)
- * [](#)
* [并发工具类](#并发工具类)
* [原子数据类型](#原子数据类型)
* [同步容器](#同步容器)
diff --git "a/docs/java/design-parttern/\345\210\235\346\216\242Java\350\256\276\350\256\241\346\250\241\345\274\217\357\274\232JDK\344\270\255\347\232\204\350\256\276\350\256\241\346\250\241\345\274\217.md" "b/docs/java/design-parttern/\345\210\235\346\216\242Java\350\256\276\350\256\241\346\250\241\345\274\217\357\274\232JDK\344\270\255\347\232\204\350\256\276\350\256\241\346\250\241\345\274\217.md"
index dc643c3..61748b1 100644
--- "a/docs/java/design-parttern/\345\210\235\346\216\242Java\350\256\276\350\256\241\346\250\241\345\274\217\357\274\232JDK\344\270\255\347\232\204\350\256\276\350\256\241\346\250\241\345\274\217.md"
+++ "b/docs/java/design-parttern/\345\210\235\346\216\242Java\350\256\276\350\256\241\346\250\241\345\274\217\357\274\232JDK\344\270\255\347\232\204\350\256\276\350\256\241\346\250\241\345\274\217.md"
@@ -1,3 +1,34 @@
+# Table of Contents
+
+ * [**一,结构型模式**](#一,结构型模式)
+ * [**1,适配器模式**](#1,适配器模式)
+ * [**2,桥接模式**](#2,桥接模式)
+ * [**3,组合模式**](#3,组合模式)
+ * [**4,装饰者模式**](#4,装饰者模式)
+ * [**5,门面模式**](#5,门面模式)
+ * [**6,享元模式**](#6,享元模式)
+ * [**7,代理模式**](#7,代理模式)
+ * [**二,创建模式**](#二,创建模式)
+ * [**1,抽象工厂模式**](#1,抽象工厂模式)
+ * [**2,建造模式(Builder)**](#2,建造模式builder)
+ * [**3,工厂方法**](#3,工厂方法)
+ * [**4,原型模式**](#4,原型模式)
+ * [**5,单例模式**](#5,单例模式)
+ * [**三,行为模式**](#三,行为模式)
+ * [**1,责任链模式**](#1,责任链模式)
+ * [**2,命令模式**](#2,命令模式)
+ * [**3,解释器模式**](#3,解释器模式)
+ * [**4,迭代器模式**](#4,迭代器模式)
+ * [**5,中介者模式**](#5,中介者模式)
+ * [**6,备忘录模式**](#6,备忘录模式)
+ * [**7,空对象模式**](#7,空对象模式)
+ * [**8,观察者模式**](#8,观察者模式)
+ * [**9,状态模式**](#9,状态模式)
+ * [**10,策略模式**](#10,策略模式)
+ * [**11,模板方法模式**](#11,模板方法模式)
+ * [**12,访问者模式**](#12,访问者模式)
+
+
本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看
@@ -12,9 +43,9 @@
本文转自https://www.cnblogs.com/LinkinPark/p/5233075.html
-**一,结构型模式**
+## **一,结构型模式**
-**1,适配器模式**
+### **1,适配器模式**
**用来把一个接口转化成另一个接口**
@@ -30,7 +61,7 @@
>
> **javax.xml.bind.annotation.adapters.XmlAdapter#unmarshal()**
-**2,桥接模式**
+### **2,桥接模式**
**这个模式将抽象和抽象操作的实现进行了解耦,这样使得抽象和实现可以独立地变化**
@@ -38,7 +69,7 @@
>
> **JDBC**
-**3,组合模式**
+### **3,组合模式**
**使得客户端看来单个对象和对象的组合是同等的。换句话说,某个类型的方法同时也接受自身类型作为参数**
@@ -52,7 +83,7 @@
>
> **java.util.Set#addAll(Collection)**
-**4,装饰者模式**
+### **4,装饰者模式**
**动态的给一个对象附加额外的功能,这也是子类的一种替代方式。可以看到,在创建一个类型的时候,同时也传入同一类型的对象。这在JDK里随处可见,你会发现它无处不在,所以下面这个列表只是一小部分**
@@ -64,9 +95,9 @@
>
> **java.util.zip.ZipOutputStream(OutputStream)**
>
-> **java.util.Collections#checked**
+> **java.util.Collections#checked**
-**5,门面模式**
+### **5,门面模式**
**给一组组件,接口,抽象,或者子系统提供一个简单的接口**
@@ -74,7 +105,7 @@
>
> **javax.faces.webapp.FacesServlet**
-**6,享元模式**
+### **6,享元模式**
**使用缓存来加速大量小对象的访问时间**
@@ -86,7 +117,7 @@
>
> **java.lang.Character#valueOf(char)**
-**7,代理模式**
+### **7,代理模式**
**代理模式是用一个简单的对象来代替一个复杂的或者创建耗时的对象。**
@@ -94,11 +125,11 @@
>
> **RMI**
-** **
+****
-**二,创建模式**
+## **二,创建模式**
-**1,抽象工厂模式**
+### **1,抽象工厂模式**
**抽象工厂模式提供了一个协议来生成一系列的相关或者独立的对象,而不用指定具体对象的类型。它使得应用程序能够和使用的框架的具体实现进行解耦。这在JDK或者许多框架比如Spring中都随处可见。它们也很容易识别,一个创建新对象的方法,返回的却是接口或者抽象类的,就是抽象工厂模式了**
@@ -118,7 +149,7 @@
>
> **javax.xml.transform.TransformerFactory#newInstance()**
-**2,建造模式(Builder)**
+### **2,建造模式(Builder)**
**定义了一个新的类来构建另一个类的实例,以简化复杂对象的创建。建造模式通常也使用方法链接来实现**
@@ -130,7 +161,7 @@
>
> **javax.swing.GroupLayout.Group#addComponent()**
-**3,工厂方法**
+### **3,工厂方法**
**就是一个返回具体对象的方法**
@@ -148,7 +179,7 @@
>
> **java.lang.Class#forName()**
-**4,原型模式**
+### **4,原型模式**
**使得类的实例能够生成自身的拷贝。如果创建一个对象的实例非常复杂且耗时时,就可以使用这种模式,而不重新创建一个新的实例,你可以拷贝一个对象并直接修改它**
@@ -156,7 +187,7 @@
>
> **java.lang.Cloneable**
-**5,单例模式**
+### **5,单例模式**
**用来确保类只有一个实例。Joshua Bloch在Effetive Java中建议到,还有一种方法就是使用枚举**
@@ -168,11 +199,11 @@
>
> **java.awt.Desktop#getDesktop()**
-** **
+****
-**三,行为模式**
+## **三,行为模式**
-**1,责任链模式**
+### **1,责任链模式**
**通过把请求从一个对象传递到链条中下一个对象的方式,直到请求被处理完毕,以实现对象间的解耦**
@@ -180,7 +211,7 @@
>
> **javax.servlet.Filter#doFilter()**
-**2,命令模式**
+### **2,命令模式**
**将操作封装到对象内,以便存储,传递和返回**
@@ -188,7 +219,7 @@
>
> **javax.swing.Action**
-**3,解释器模式**
+### **3,解释器模式**
**这个模式通常定义了一个语言的语法,然后解析相应语法的语句**
@@ -198,7 +229,7 @@
>
> **java.text.Format**
-**4,迭代器模式**
+### **4,迭代器模式**
**提供一个一致的方法来顺序访问集合中的对象,这个方法与底层的集合的具体实现无关**
@@ -206,7 +237,7 @@
>
> **java.util.Enumeration**
-**5,中介者模式**
+### **5,中介者模式**
**通过使用一个中间对象来进行消息分发以及减少类之间的直接依赖**
@@ -218,7 +249,7 @@
>
> **java.lang.reflect.Method#invoke()**
-**6,备忘录模式**
+### **6,备忘录模式**
**生成对象状态的一个快照,以便对象可以恢复原始状态而不用暴露自身的内容。Date对象通过自身内部的一个long值来实现备忘录模式**
@@ -226,7 +257,7 @@
>
> **java.io.Serializable**
-**7,空对象模式**
+### **7,空对象模式**
**这个模式通过一个无意义的对象来代替没有对象这个状态。它使得你不用额外对空对象进行处理**
@@ -236,7 +267,7 @@
>
> **java.util.Collections#emptySet()**
-**8,观察者模式**
+### **8,观察者模式**
**它使得一个对象可以灵活的将消息发送给感兴趣的对象**
@@ -248,7 +279,7 @@
>
> **javax.faces.event.PhaseListener**
-**9,状态模式**
+### **9,状态模式**
**通过改变对象内部的状态,使得你可以在运行时动态改变一个对象的行为**
@@ -256,7 +287,7 @@
>
> **javax.faces.lifecycle.LifeCycle#execute()**
-**10,策略模式**
+### **10,策略模式**
**使用这个模式来将一组算法封装成一系列对象。通过传递这些对象可以灵活的改变程序的功能**
@@ -266,7 +297,7 @@
>
> **javax.servlet.Filter#doFilter()**
-**11,模板方法模式**
+### **11,模板方法模式**
**让子类可以重写方法的一部分,而不是整个重写,你可以控制子类需要重写那些操作**
@@ -278,7 +309,7 @@
>
> **java.util.AbstractList#indexOf()**
-**12,访问者模式**
+### **12,访问者模式**
**提供一个方便的可维护的方式来操作一组对象。它使得你在不改变操作的对象前提下,可以修改或者扩展对象的行为**
diff --git "a/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232GC\350\260\203\344\274\230\346\200\235\350\267\257\344\270\216\345\270\270\347\224\250\345\267\245\345\205\267.md" "b/docs/java/jvm/temp/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232GC\350\260\203\344\274\230\346\200\235\350\267\257\344\270\216\345\270\270\347\224\250\345\267\245\345\205\267.md"
similarity index 98%
rename from "docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232GC\350\260\203\344\274\230\346\200\235\350\267\257\344\270\216\345\270\270\347\224\250\345\267\245\345\205\267.md"
rename to "docs/java/jvm/temp/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232GC\350\260\203\344\274\230\346\200\235\350\267\257\344\270\216\345\270\270\347\224\250\345\267\245\345\205\267.md"
index 341f675..30d3350 100644
--- "a/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232GC\350\260\203\344\274\230\346\200\235\350\267\257\344\270\216\345\270\270\347\224\250\345\267\245\345\205\267.md"
+++ "b/docs/java/jvm/temp/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232GC\350\260\203\344\274\230\346\200\235\350\267\257\344\270\216\345\270\270\347\224\250\345\267\245\345\205\267.md"
@@ -1,4 +1,23 @@
-# 目录
+# Table of Contents
+
+* [核心概念(Core Concepts)](#核心概念core-concepts)
+ * [Latency(延迟)](#latency延迟)
+ * [Throughput(吞吐量)](#throughput吞吐量)
+ * [Capacity(系统容量)](#capacity系统容量)
+* [相关示例](#相关示例)
+ * [Tuning for Latency(调优延迟指标)](#tuning-for-latency调优延迟指标)
+ * [Tuning for Throughput(吞吐量调优)](#tuning-for-throughput吞吐量调优)
+ * [Tuning for Capacity(调优系统容量)](#tuning-for-capacity调优系统容量)
+ * [6\. GC 调优(工具篇) - GC参考手册](#6-gc-调优工具篇---gc参考手册)
+ * [JMX API](#jmx-api)
+ * [JVisualVM](#jvisualvm)
+ * [jstat](#jstat)
+ * [GC日志(GC logs)](#gc日志gc-logs)
+ * [GCViewer](#gcviewer)
+ * [分析器(Profilers)](#分析器profilers)
+ * [hprof](#hprof)
+ * [Java VisualVM](#java-visualvm)
+ * [AProf](#aprof)
* [参考文章](#参考文章)
@@ -18,8 +37,6 @@
-## 5\. GC 调优(基础篇) - GC参考手册
-
> **说明**:
>
> **Capacity**: 性能,能力,系统容量; 文中翻译为”**系统容量**“; 意为硬件配置。
diff --git "a/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232JVM\345\270\270\347\224\250\345\217\202\346\225\260\344\273\245\345\217\212\350\260\203\344\274\230\345\256\236\350\267\265.md" "b/docs/java/jvm/temp/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232JVM\345\270\270\347\224\250\345\217\202\346\225\260\344\273\245\345\217\212\350\260\203\344\274\230\345\256\236\350\267\265.md"
similarity index 98%
rename from "docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232JVM\345\270\270\347\224\250\345\217\202\346\225\260\344\273\245\345\217\212\350\260\203\344\274\230\345\256\236\350\267\265.md"
rename to "docs/java/jvm/temp/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232JVM\345\270\270\347\224\250\345\217\202\346\225\260\344\273\245\345\217\212\350\260\203\344\274\230\345\256\236\350\267\265.md"
index 987466f..5b7c03c 100644
--- "a/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232JVM\345\270\270\347\224\250\345\217\202\346\225\260\344\273\245\345\217\212\350\260\203\344\274\230\345\256\236\350\267\265.md"
+++ "b/docs/java/jvm/temp/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232JVM\345\270\270\347\224\250\345\217\202\346\225\260\344\273\245\345\217\212\350\260\203\344\274\230\345\256\236\350\267\265.md"
@@ -1,24 +1,21 @@
+# Table of Contents
+ * [JVM优化的必要性](#jvm优化的必要性)
+ * [JVM调优原则](#jvm调优原则)
+ * [JVM运行参数设置](#jvm运行参数设置)
+ * [JVM性能调优工具](#jvm性能调优工具)
+ * [常用调优策略](#常用调优策略)
+ * [六、JVM调优实例](#六、jvm调优实例)
+ * [七、一个具体的实战案例分析](#七、一个具体的实战案例分析)
+ * [参考资料](#参考资料)
+ * [参考文章](#参考文章)
-
-
-**目录**
-
-一. JVM优化的必要性
-
-二. JVM调优原则
-三. JVM运行参数设置
-四. JVM性能调优工具
-五. 常用调优策略
-
-六. JVM调优实例
-
-七. 一个具体的实战案例分析
+
-### JVM优化的必要性
+## JVM优化的必要性
**1.1: 项目上线后,什么原因使得我们需要进行jvm调优**
@@ -58,7 +55,7 @@ Jvm堆内存不能设置太大,否则会导致寻址垃圾的时间过长,
* 系统吞吐量与响应性能不高或下降。
-### JVM调优原则
+## JVM调优原则

@@ -254,13 +251,13 @@ TLAB空间一般不会太大,当大对象无法在TLAB分配时,则会直接
-### 四.JVM性能调优工具
+## JVM性能调优工具
这个篇幅在这里就不过多介绍了,可以参照:
深入理解JVM虚拟机——Java虚拟机的监控及诊断工具大全
-### 五.常用调优策略
+## 常用调优策略
这里还是要提一下,及时确定要进行JVM调优,也不要陷入“知见障”,进行分析之后,发现可以通过优化程序提升性能,仍然首选优化程序。
@@ -410,7 +407,7 @@ CPU多核,关注用户停顿时间,JDK1.8及以上,JVM可用内存6G以上
> XX:MaxDirectMemorySize
-### 六、JVM调优实例
+## 六、JVM调优实例
整理的一些JVM调优实例:
@@ -533,7 +530,7 @@ CPU多核,关注用户停顿时间,JDK1.8及以上,JVM可用内存6G以上
系统对外提供各种账号鉴权服务,使用时发现系统经常服务不可用,通过 Zabbix 的监控平台监控发现系统频繁发生长时间 Full GC,且触发时老年代的堆内存通常并没有占满,发现原来是业务代码中调用了
-### 七、一个具体的实战案例分析
+## 七、一个具体的实战案例分析
**7.1 典型调优参数设置**
diff --git "a/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232JNDI\357\274\214OSGI\357\274\214Tomcat\347\261\273\345\212\240\350\275\275\345\231\250\345\256\236\347\216\260.md" "b/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232JNDI\357\274\214OSGI\357\274\214Tomcat\347\261\273\345\212\240\350\275\275\345\231\250\345\256\236\347\216\260.md"
index b48b79b..6c1b066 100644
--- "a/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232JNDI\357\274\214OSGI\357\274\214Tomcat\347\261\273\345\212\240\350\275\275\345\231\250\345\256\236\347\216\260.md"
+++ "b/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232JNDI\357\274\214OSGI\357\274\214Tomcat\347\261\273\345\212\240\350\275\275\345\231\250\345\256\236\347\216\260.md"
@@ -1,7 +1,7 @@
# 目录
* [打破双亲委派模型](#打破双亲委派模型)
* [JNDI](#jndi)
- * [[JNDI 的理解](https://yq.aliyun.com/go/articleRenderRedirect?url=https%3A%2F%2Fwww.cnblogs.com%2Fzhchoutai%2Fp%2F7389089.html)](#[jndi-的理解]httpsyqaliyuncomgoarticlerenderredirecturlhttps3a2f2fwwwcnblogscom2fzhchoutai2fp2f7389089html)
+ * [JNDI 的理解](#[jndi-的理解])
* [OSGI](#osgi)
* [1.如何正确的理解和认识OSGI技术?](#1如何正确的理解和认识osgi技术?)
* [Tomcat类加载器以及应用间class隔离与共享](#tomcat类加载器以及应用间class隔离与共享)
diff --git "a/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232JVM\345\236\203\345\234\276\345\233\236\346\224\266\345\237\272\346\234\254\345\216\237\347\220\206\345\222\214\347\256\227\346\263\225.md" "b/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232JVM\345\236\203\345\234\276\345\233\236\346\224\266\345\237\272\346\234\254\345\216\237\347\220\206\345\222\214\347\256\227\346\263\225.md"
index 65e4869..8048fb5 100644
--- "a/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232JVM\345\236\203\345\234\276\345\233\236\346\224\266\345\237\272\346\234\254\345\216\237\347\220\206\345\222\214\347\256\227\346\263\225.md"
+++ "b/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232JVM\345\236\203\345\234\276\345\233\236\346\224\266\345\237\272\346\234\254\345\216\237\347\220\206\345\222\214\347\256\227\346\263\225.md"
@@ -14,7 +14,7 @@
* [垃圾回收中实例的终结](#垃圾回收中实例的终结)
* [对象什么时候符合垃圾回收的条件?](#对象什么时候符合垃圾回收的条件?)
* [GC Scope 示例程序](#gc-scope-示例程序)
- * [[JVM GC算法](https://www.cnblogs.com/wupeixuan/p/8670341.html)](#[jvm-gc算法]httpswwwcnblogscomwupeixuanp8670341html)
+ * [JVM GC算法](#JVM GC算法)
* [JVM垃圾判定算法](#jvm垃圾判定算法)
* [引用计数算法(Reference Counting)](#引用计数算法reference-counting)
* [可达性分析算法(根搜索算法)](#可达性分析算法(根搜索算法))
diff --git "a/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232Java\347\232\204\347\274\226\350\257\221\346\234\237\344\274\230\345\214\226\344\270\216\350\277\220\350\241\214\346\234\237\344\274\230\345\214\226.md" "b/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232Java\347\232\204\347\274\226\350\257\221\346\234\237\344\274\230\345\214\226\344\270\216\350\277\220\350\241\214\346\234\237\344\274\230\345\214\226.md"
index 0a1c3ac..58b8166 100644
--- "a/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232Java\347\232\204\347\274\226\350\257\221\346\234\237\344\274\230\345\214\226\344\270\216\350\277\220\350\241\214\346\234\237\344\274\230\345\214\226.md"
+++ "b/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232Java\347\232\204\347\274\226\350\257\221\346\234\237\344\274\230\345\214\226\344\270\216\350\277\220\350\241\214\346\234\237\344\274\230\345\214\226.md"
@@ -1,5 +1,5 @@
# 目录
- * [[java编译期优化](https://www.cnblogs.com/LeonNew/p/6187411.html)](#[java编译期优化]httpswwwcnblogscomleonnewp6187411html)
+ * [java编译期优化](#[java编译期优化])
* [早期(编译期)优化](#早期(编译期)优化)
* [泛型与类型擦除](#泛型与类型擦除)
* [自动装箱、拆箱与遍历循环](#自动装箱、拆箱与遍历循环)
@@ -41,7 +41,7 @@ java语言的编译期其实是一段不确定的操作过程,因为它可以
2.后端编译:把字节码转变为机器码
3.静态提前编译:直接把*.java文件编译成本地机器代码
从JDK1.3开始,虚拟机设计团队就把对性能的优化集中到了后端的即时编译中,这样可以让那些不是由Javac产生的Class文件(如JRuby、Groovy等语言的Class文件)也能享受到编译期优化所带来的好处
-**Java中即时编译在运行期的优化过程对于程序运行来说更重要,而前端编译期在编译期的优化过程对于程序编码来说关系更加密切 **
+**Java中即时编译在运行期的优化过程对于程序运行来说更重要,而前端编译期在编译期的优化过程对于程序编码来说关系更加密切**
### 早期(编译期)优化
@@ -102,7 +102,7 @@ public static void main(String[] args) {
##### 解释器与编译器
-Java程序最初是通过解释器进行解释执行的,当程序需要迅速启动和执行时,解释器可以首先发挥作用,省去编译时间,立即执行;当程序运行后,随着时间的推移,编译期逐渐发挥作用,把越来越多的代码编译成本地代码,获得更高的执行效率。**解释执行节约内存,编译执行提升效率。** 同时,解释器可以作为编译器激进优化时的一个“逃生门”,让编译器根据概率选择一些大多数时候都能提升运行速度的优化手段,当激进优化的假设不成立,则通过逆优化退回到解释状态继续执行。
+Java程序最初是通过解释器进行解释执行的,当程序需要迅速启动和执行时,解释器可以首先发挥作用,省去编译时间,立即执行;当程序运行后,随着时间的推移,编译期逐渐发挥作用,把越来越多的代码编译成本地代码,获得更高的执行效率。**解释执行节约内存,编译执行提升效率。**同时,解释器可以作为编译器激进优化时的一个“逃生门”,让编译器根据概率选择一些大多数时候都能提升运行速度的优化手段,当激进优化的假设不成立,则通过逆优化退回到解释状态继续执行。
HotSpot虚拟机中内置了两个即时编译器,分别称为Client Compiler(C1编译器)和Server Compiler(C2编译器),默认采用解释器与其中一个编译器直接配合的方式工作,使用哪个编译器取决于虚拟机运行的模式,也可以自己去指定。若强制虚拟机运行与“解释模式”,编译器完全不介入工作,若强制虚拟机运行于“编译模式”,则优先采用编译方式执行程序,解释器仍然要在编译无法进行的情况下介入执行过程。

diff --git "a/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232\345\206\215\350\260\210\345\233\233\347\247\215\345\274\225\347\224\250\345\217\212GC\345\256\236\350\267\265.md" "b/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232\345\206\215\350\260\210\345\233\233\347\247\215\345\274\225\347\224\250\345\217\212GC\345\256\236\350\267\265.md"
index 08cc449..cca62d4 100644
--- "a/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232\345\206\215\350\260\210\345\233\233\347\247\215\345\274\225\347\224\250\345\217\212GC\345\256\236\350\267\265.md"
+++ "b/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232\345\206\215\350\260\210\345\233\233\347\247\215\345\274\225\347\224\250\345\217\212GC\345\256\236\350\267\265.md"
@@ -32,7 +32,7 @@
## 一、背景
-Java的内存回收不需要程序员负责,JVM会在必要时启动Java GC完成垃圾回收。Java以便我们控制对象的生存周期,提供给了我们四种引用方式,引用强度从强到弱分别为:强引用、软引用、弱引用、虚引用。
+Java的内存回收不需要程序员负责,JVM会在必要时启动Java GC完成垃圾回收。Java以便我们控制对象的生存周期,提供给了我们四种引用方式,引用强度从强到弱分别为:强引用、软引用、弱引用、虚引用。
## 二、简介
diff --git "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232IO\346\250\241\345\236\213\344\270\216Java\347\275\221\347\273\234\347\274\226\347\250\213\346\250\241\345\236\213.md" "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232IO\346\250\241\345\236\213\344\270\216Java\347\275\221\347\273\234\347\274\226\347\250\213\346\250\241\345\236\213.md"
index 8bdf054..838c7d7 100644
--- "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232IO\346\250\241\345\236\213\344\270\216Java\347\275\221\347\273\234\347\274\226\347\250\213\346\250\241\345\236\213.md"
+++ "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232IO\346\250\241\345\236\213\344\270\216Java\347\275\221\347\273\234\347\274\226\347\250\213\346\250\241\345\236\213.md"
@@ -90,7 +90,7 @@ asynchronous IO
**_当一个read操作发生时,它会经历两个阶段:_**
-* 等待数据准备,比如accept(), recv()等待数据 `(Waiting for the data to be ready)`
+* 等待数据准备,比如accept(), recv()等待数据`(Waiting for the data to be ready)`
* 将数据从内核拷贝到进程中, 比如 accept()接受到请求,recv()接收连接发送的数据后需要复制到内核,再从内核复制到进程用户空间`(Copying the data from the kernel to the process)`
**_对于socket流而言,数据的流向经历两个阶段:_**
@@ -206,7 +206,7 @@ linux下的asynchronous IO其实用得很少。先看一下它的流程:
同步IO VS 异步IO:
概念:
-同步与异步同步和异步关注的是___消息通信机制 ___(synchronous communication/ asynchronous communication)所谓同步,就是在发出一个_调用_时,在没有得到结果之前,该_调用_就不返回。但是一旦调用返回,就得到返回值了。换句话说,就是由_调用者_主动等待这个_调用_的结果。而异步则是相反,_调用_在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在_调用_发出后,_被调用者_通过状态、通知来通知调用者,或通过回调函数处理这个调用。
+同步与异步同步和异步关注的是___消息通信机制___(synchronous communication/ asynchronous communication)所谓同步,就是在发出一个_调用_时,在没有得到结果之前,该_调用_就不返回。但是一旦调用返回,就得到返回值了。换句话说,就是由_调用者_主动等待这个_调用_的结果。而异步则是相反,_调用_在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在_调用_发出后,_被调用者_通过状态、通知来通知调用者,或通过回调函数处理这个调用。
典型的异步编程模型比如Node.js举个通俗的例子:你打电话问书店老板有没有《分布式系统》这本书,如果是同步通信机制,书店老板会说,你稍等,”我查一下",然后开始查啊查,等查好了(可能是5秒,也可能是一天)告诉你结果(返回结果)。而异步通信机制,书店老板直接告诉你我查一下啊,查好了打电话给你,然后直接挂电话了(不返回结果)。然后查好了,他会主动打电话给你。在这里老板通过“回电”这种方式来回调。
diff --git "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232Java\351\235\236\351\230\273\345\241\236IO\345\222\214\345\274\202\346\255\245IO.md" "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232Java\351\235\236\351\230\273\345\241\236IO\345\222\214\345\274\202\346\255\245IO.md"
index 4ec65bc..2837b73 100644
--- "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232Java\351\235\236\351\230\273\345\241\236IO\345\222\214\345\274\202\346\255\245IO.md"
+++ "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232Java\351\235\236\351\230\273\345\241\236IO\345\222\214\345\274\202\346\255\245IO.md"
@@ -32,7 +32,7 @@
上一篇文章介绍了 Java NIO 中 Buffer、Channel 和 Selector 的基本操作,主要是一些接口操作,比较简单。
-本文将介绍**非阻塞 IO** 和**异步 IO**,也就是大家耳熟能详的 NIO 和 AIO。很多初学者可能分不清楚异步和非阻塞的区别,只是在各种场合能听到**异步非阻塞**这个词。
+本文将介绍**非阻塞 IO**和**异步 IO**,也就是大家耳熟能详的 NIO 和 AIO。很多初学者可能分不清楚异步和非阻塞的区别,只是在各种场合能听到**异步非阻塞**这个词。
本文会先介绍并演示阻塞模式,然后引入非阻塞模式来对阻塞模式进行优化,最后再介绍 JDK7 引入的异步 IO,由于网上关于异步 IO 的介绍相对较少,所以这部分内容我会介绍得具体一些。
@@ -160,7 +160,7 @@ select 和 poll 都有一个共同的问题,那就是**它们都只会告诉
**epoll**:2002 年随 Linux 内核 2.5.44 发布,epoll 能直接返回具体的准备好的通道,时间复杂度 O(1)。
-除了 Linux 中的 epoll,2000 年 FreeBSD 出现了 **Kqueue**,还有就是,Solaris 中有 **/dev/poll**。
+除了 Linux 中的 epoll,2000 年 FreeBSD 出现了**Kqueue**,还有就是,Solaris 中有**/dev/poll**。
> 前面说了那么多实现,但是没有出现 Windows,Windows 平台的非阻塞 IO 使用 select,我们也不必觉得 Windows 很落后,在 Windows 中 IOCP 提供的异步 IO 是比较强大的。
@@ -239,13 +239,13 @@ More New IO,或称 NIO.2,随 JDK 1.7 发布,包括了引入异步 IO 接
**在 Unix/Linux 等系统中,JDK 使用了并发包中的线程池来管理任务**,具体可以查看 AsynchronousChannelGroup 的源码。
-在 Windows 操作系统中,提供了一个叫做 [I/O Completion Ports](https://msdn.microsoft.com/en-us/library/windows/desktop/aa365198.aspx) 的方案,通常简称为 **IOCP**,操作系统负责管理线程池,其性能非常优异,所以**在 Windows 中 JDK 直接采用了 IOCP 的支持**,使用系统支持,把更多的操作信息暴露给操作系统,也使得操作系统能够对我们的 IO 进行一定程度的优化。
+在 Windows 操作系统中,提供了一个叫做[I/O Completion Ports](https://msdn.microsoft.com/en-us/library/windows/desktop/aa365198.aspx)的方案,通常简称为**IOCP**,操作系统负责管理线程池,其性能非常优异,所以**在 Windows 中 JDK 直接采用了 IOCP 的支持**,使用系统支持,把更多的操作信息暴露给操作系统,也使得操作系统能够对我们的 IO 进行一定程度的优化。
> 在 Linux 中其实也是有异步 IO 系统实现的,但是限制比较多,性能也一般,所以 JDK 采用了自建线程池的方式。
本文还是以实用为主,想要了解更多信息请自行查找其他资料,下面对 Java 异步 IO 进行实践性的介绍。
-总共有三个类需要我们关注,分别是 **AsynchronousSocketChannel**,**AsynchronousServerSocketChannel** 和 **AsynchronousFileChannel**,只不过是在之前介绍的 FileChannel、SocketChannel 和 ServerSocketChannel 的类名上加了个前缀 **Asynchronous**。
+总共有三个类需要我们关注,分别是**AsynchronousSocketChannel**,**AsynchronousServerSocketChannel**和**AsynchronousFileChannel**,只不过是在之前介绍的 FileChannel、SocketChannel 和 ServerSocketChannel 的类名上加了个前缀**Asynchronous**。
Java 异步 IO 提供了两种使用方式,分别是返回 Future 实例和使用回调函数。
diff --git "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232\345\237\272\344\272\216NIO\347\232\204\347\275\221\347\273\234\347\274\226\347\250\213\346\241\206\346\236\266Netty.md" "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232\345\237\272\344\272\216NIO\347\232\204\347\275\221\347\273\234\347\274\226\347\250\213\346\241\206\346\236\266Netty.md"
index e21ceef..fd4cdf2 100644
--- "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232\345\237\272\344\272\216NIO\347\232\204\347\275\221\347\273\234\347\274\226\347\250\213\346\241\206\346\236\266Netty.md"
+++ "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232\345\237\272\344\272\216NIO\347\232\204\347\275\221\347\273\234\347\274\226\347\250\213\346\241\206\346\236\266Netty.md"
@@ -169,7 +169,7 @@ Encoders和Decoders
因为我们在网络传输时只能传输字节流,因此,在发送数据之前,我们必须把我们的message型转换为bytes,与之对应,我们在接收数据后,必须把接收到的bytes再转换成message。我们把bytes to message这个过程称作Decode(解码成我们可以理解的),把message to bytes这个过程成为Encode。
-Netty中提供了很多现成的编码/解码器,我们一般从他们的名字中便可知道他们的用途,如**ByteToMessageDecoder**、**MessageToByteEncoder**,如专门用来处理Google Protobuf协议的**ProtobufEncoder**、 **ProtobufDecoder**。
+Netty中提供了很多现成的编码/解码器,我们一般从他们的名字中便可知道他们的用途,如**ByteToMessageDecoder**、**MessageToByteEncoder**,如专门用来处理Google Protobuf协议的**ProtobufEncoder**、**ProtobufDecoder**。
我们前面说过,具体是哪种Handler就要看它们继承的是InboundAdapter还是OutboundAdapter,对于**Decoders**,很容易便可以知道它是继承自**ChannelInboundHandlerAdapter**或 ChannelInboundHandler,因为解码的意思是把ChannelPipeline**传入的bytes解码成我们可以理解的message**(即Java Object),而ChannelInboundHandler正是处理Inbound Event,而Inbound Event中传入的正是字节流。Decoder会覆盖其中的“ChannelRead()”方法,在这个方法中来调用具体的decode方法解码传递过来的字节流,然后通过调用ChannelHandlerContext.fireChannelRead(decodedMessage)方法把编码好的Message传递给下一个Handler。与之类似,Encoder就不必多少了。
diff --git a/src/main/java/md/mdToc.java b/src/main/java/md/mdToc.java
index f449fef..0cf8f98 100644
--- a/src/main/java/md/mdToc.java
+++ b/src/main/java/md/mdToc.java
@@ -4,7 +4,7 @@
public class mdToc {
public static void main(String[] args) {
- String path = "D:\\idea_project\\JavaTutorial\\docs\\distributed\\practice\\temp";
+ String path = "D:\\idea_project\\JavaTutorial\\docs\\java\\jvm\\temp";
AtxMarkdownToc.newInstance().genTocDir(path);
}
}
From 93ba2f44e6890c207597da394aa5c233deb3486e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=BB=84=E5=B0=8F=E6=96=9C?= <362294931@qq.com>
Date: Sun, 9 Apr 2023 18:03:01 +0800
Subject: [PATCH 07/39] modify mds
---
ReadMe.md | 4 +-
...70\345\277\203\346\265\201\347\250\213.md" | 1 -
...45\350\257\206\346\270\205\345\215\225.md" | 31 --------
...67\346\261\202\350\275\254\345\217\221.md" | 4 -
...4\232SpringMVC\346\246\202\350\277\260.md" | 77 ++++++++++++++++++-
...43\346\236\220\345\216\237\347\220\206.md" | 2 -
...6@ResponseBody\346\263\250\350\247\243.md" | 13 +---
...43\345\274\217\345\274\200\345\217\221.md" | 3 -
...274\232Mybatis\345\205\245\351\227\250.md" | 3 -
...66\346\236\204\345\211\226\346\236\220.md" | 8 +-
...5\273\272\345\267\245\345\205\267Maven.md" | 2 -
...0\257\225\346\241\206\346\236\266Junit.md" | 3 -
...\215\347\275\256\347\232\204SpringBoot.md" | 3 -
...72\346\234\254\345\216\237\347\220\206.md" | 4 -
...56\345\255\227\350\247\243\346\236\220.md" | 2 +-
...76\350\256\241\346\250\241\345\274\217.md" | 2 +-
...70\347\224\250\345\267\245\345\205\267.md" | 2 +-
...03\344\274\230\345\256\236\350\267\265.md" | 2 +-
...344\270\216NIO\346\200\273\347\273\223.md" | 14 ++++
...26\347\250\213\346\250\241\345\236\213.md" | 18 +++++
...32\344\277\241\346\234\272\345\210\266.md" | 10 +++
...67\346\261\202\346\250\241\345\236\213.md" | 12 ++-
...\345\222\214\345\274\202\346\255\245IO.md" | 15 ++++
...37\347\220\206\350\257\246\350\247\243.md" | 11 +++
...346\236\220\357\274\210NIO\357\274\211.md" | 14 ++++
...7\250\213\346\241\206\346\236\266Netty.md" | 20 +++++
...343\200\201Channel\345\222\214Selector.md" | 19 +++++
...46\236\220mmap\345\222\214DirectBuffer.md" | 27 +++++++
...36\347\216\260\345\216\237\347\220\206.md" | 19 +++++
...347\232\204NIO\346\250\241\345\236\213.md" | 13 ++++
src/main/java/md/mdToc.java | 2 +-
31 files changed, 280 insertions(+), 80 deletions(-)
rename "docs/java/jvm/temp/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232GC\350\260\203\344\274\230\346\200\235\350\267\257\344\270\216\345\270\270\347\224\250\345\267\245\345\205\267.md" => "docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232GC\350\260\203\344\274\230\346\200\235\350\267\257\344\270\216\345\270\270\347\224\250\345\267\245\345\205\267.md" (99%)
rename "docs/java/jvm/temp/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232JVM\345\270\270\347\224\250\345\217\202\346\225\260\344\273\245\345\217\212\350\260\203\344\274\230\345\256\236\350\267\265.md" => "docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232JVM\345\270\270\347\224\250\345\217\202\346\225\260\344\273\245\345\217\212\350\260\203\344\274\230\345\256\236\350\267\265.md" (99%)
diff --git a/ReadMe.md b/ReadMe.md
index 1a6c3a5..dc53ae6 100644
--- a/ReadMe.md
+++ b/ReadMe.md
@@ -204,11 +204,11 @@ todo
* [深入理解JVM虚拟机:JNDI,OSGI,Tomcat类加载器实现](docs/java/jvm/深入理解JVM虚拟机:JNDI,OSGI,Tomcat类加载器实现.md)
* [深入了解JVM虚拟机:Java的编译期优化与运行期优化](docs/java/jvm/深入理解JVM虚拟机:Java的编译期优化与运行期优化.md)
* [深入理解JVM虚拟机:JVM监控工具与诊断实践](docs/java/jvm/深入理解JVM虚拟机:JVM监控工具与诊断实践.md)
-* [深入理解JVM虚拟机:JVM常用参数以及调优实践](docs/java/jvm/temp/深入理解JVM虚拟机:JVM常用参数以及调优实践.md)
+* [深入理解JVM虚拟机:JVM常用参数以及调优实践](docs/java/jvm/深入理解JVM虚拟机:JVM常用参数以及调优实践.md)
* [深入理解JVM虚拟机:Java内存异常原理与实践](docs/java/jvm/深入理解JVM虚拟机:Java内存异常原理与实践.md)
* [深入理解JVM虚拟机:JVM性能管理神器VisualVM介绍与实战](docs/java/jvm/深入理解JVM虚拟机:JVM性能管理神器VisualVM介绍与实战.md)
* [深入理解JVM虚拟机:再谈四种引用及GC实践](docs/java/jvm/深入理解JVM虚拟机:再谈四种引用及GC实践.md)
-* [深入理解JVM虚拟机:GC调优思路与常用工具](docs/java/jvm/temp/深入理解JVM虚拟机:GC调优思路与常用工具.md)
+* [深入理解JVM虚拟机:GC调优思路与常用工具](docs/java/jvm/深入理解JVM虚拟机:GC调优思路与常用工具.md)
### Java网络编程
diff --git "a/docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232\345\210\235\346\216\242SpringIOC\346\240\270\345\277\203\346\265\201\347\250\213.md" "b/docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232\345\210\235\346\216\242SpringIOC\346\240\270\345\277\203\346\265\201\347\250\213.md"
index 2ffdb35..ba4415e 100644
--- "a/docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232\345\210\235\346\216\242SpringIOC\346\240\270\345\277\203\346\265\201\347\250\213.md"
+++ "b/docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232\345\210\235\346\216\242SpringIOC\346\240\270\345\277\203\346\265\201\347\250\213.md"
@@ -4,7 +4,6 @@
* [读取](#读取)
* [解析](#解析)
* [注册](#注册)
- * [注入依赖](#注入依赖)
本文转载自互联网,侵删
diff --git "a/docs/java-web/Spring/\347\273\231\344\275\240\344\270\200\344\273\275SpringBoot\347\237\245\350\257\206\346\270\205\345\215\225.md" "b/docs/java-web/Spring/\347\273\231\344\275\240\344\270\200\344\273\275SpringBoot\347\237\245\350\257\206\346\270\205\345\215\225.md"
index 8564da9..96260af 100644
--- "a/docs/java-web/Spring/\347\273\231\344\275\240\344\270\200\344\273\275SpringBoot\347\237\245\350\257\206\346\270\205\345\215\225.md"
+++ "b/docs/java-web/Spring/\347\273\231\344\275\240\344\270\200\344\273\275SpringBoot\347\237\245\350\257\206\346\270\205\345\215\225.md"
@@ -8,7 +8,6 @@
* [2.3、@Import](#23、import)
* [2.4、@Conditional](#24、conditional)
* [2.5、@ConfigurationProperties与@EnableConfigurationProperties](#25、configurationproperties与enableconfigurationproperties)
- * [](#)
* [三、削铁如泥:SpringFactoriesLoader详解](#三、削铁如泥:springfactoriesloader详解)
* [四、另一件武器:Spring容器的事件监听机制](#四、另一件武器:spring容器的事件监听机制)
* [Spring容器内的事件监听机制](#spring容器内的事件监听机制)
@@ -17,9 +16,6 @@
* [6.1 SpringApplication初始化](#61-springapplication初始化)
* [6.2 Spring Boot启动流程](#62-spring-boot启动流程)
* [参考文章](#参考文章)
-* [微信公众号](#微信公众号)
- * [个人公众号:黄小斜](#个人公众号:黄小斜)
- * [技术公众号:Java技术江湖](#技术公众号:java技术江湖)
本文转自互联网,侵删
@@ -806,30 +802,3 @@ public void initialize(ConfigurableApplicationContext context) {
[5][spring boot实战:自动配置原理分析](https://link.jianshu.com/?t=http%3A%2F%2Fblog.csdn.net%2Fliaokailin%2Farticle%2Fdetails%2F49559951):[http://blog.csdn.net/liaokailin/article/details/49559951](https://link.jianshu.com/?t=http%3A%2F%2Fblog.csdn.net%2Fliaokailin%2Farticle%2Fdetails%2F49559951)
[6][spring boot实战:Spring boot Bean加载源码分析](https://link.jianshu.com/?t=http%3A%2F%2Fblog.csdn.net%2Fliaokailin%2Farticle%2Fdetails%2F49107209):[http://blog.csdn.net/liaokailin/article/details/49107209](https://link.jianshu.com/?t=http%3A%2F%2Fblog.csdn.net%2Fliaokailin%2Farticle%2Fdetails%2F49107209)
-
-
-## 微信公众号
-
-### 个人公众号:黄小斜
-
-黄小斜是跨考软件工程的 985 硕士,自学 Java 两年,拿到了 BAT 等近十家大厂 offer,从技术小白成长为阿里工程师。
-
-作者专注于 JAVA 后端技术栈,热衷于分享程序员干货、学习经验、求职心得和程序人生,目前黄小斜的CSDN博客有百万+访问量,知乎粉丝2W+,全网已有10W+读者。
-
-黄小斜是一个斜杠青年,坚持学习和写作,相信终身学习的力量,希望和更多的程序员交朋友,一起进步和成长!
-
-**原创电子书:**
-关注公众号【黄小斜】后回复【原创电子书】即可领取我原创的电子书《菜鸟程序员修炼手册:从技术小白到阿里巴巴Java工程师》
-
-**程序员3T技术学习资源:** 一些程序员学习技术的资源大礼包,关注公众号后,后台回复关键字 **“资料”** 即可免费无套路获取。
-**考研复习资料:** 计算机考研大礼包,都是我自己考研复习时用的一些复习资料,包括公共课和专业的复习视频,这里也推荐给大家,关注公众号后,后台回复关键字 **“考研”** 即可免费获取。
-
-
-
-### 技术公众号:Java技术江湖
-
-如果大家想要实时关注我更新的文章以及分享的干货的话,可以关注我的公众号【Java技术江湖】一位阿里 Java 工程师的技术小站,作者黄小斜,专注 Java 相关技术:SSM、SpringBoot、MySQL、分布式、中间件、集群、Linux、网络、多线程,偶尔讲点Docker、ELK,同时也分享技术干货和学习经验,致力于Java全栈开发!
-
-**Java工程师必备学习资源:** 一些Java工程师常用学习资源,关注公众号后,后台回复关键字 **“Java”** 即可免费无套路获取。
-
-
\ No newline at end of file
diff --git "a/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232DispatcherServlet\347\232\204\345\210\235\345\247\213\345\214\226\344\270\216\350\257\267\346\261\202\350\275\254\345\217\221.md" "b/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232DispatcherServlet\347\232\204\345\210\235\345\247\213\345\214\226\344\270\216\350\257\267\346\261\202\350\275\254\345\217\221.md"
index 6390f87..1ae0ed4 100644
--- "a/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232DispatcherServlet\347\232\204\345\210\235\345\247\213\345\214\226\344\270\216\350\257\267\346\261\202\350\275\254\345\217\221.md"
+++ "b/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232DispatcherServlet\347\232\204\345\210\235\345\247\213\345\214\226\344\270\216\350\257\267\346\261\202\350\275\254\345\217\221.md"
@@ -1,11 +1,7 @@
# 目录
* [前言](#前言)
- * [配置元素读取 ](#init-param配置元素读取init-param)
* [容器上下文的建立](#容器上下文的建立)
* [初始化SpringMVC默认实现类](#初始化springmvc默认实现类)
-* [Default implementation classes for DispatcherServlet's strategy interfaces.](#default-implementation-classes-for-dispatcherservlets-strategy-interfaces)
-* [Used as fallback when no matching beans are found in the DispatcherServlet context.](#used-as-fallback-when-no-matching-beans-are-found-in-the-dispatcherservlet-context)
-* [Not meant to be customized by application developers.](#not-meant-to-be-customized-by-application-developers)
* [总结](#总结)
diff --git "a/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\346\246\202\350\277\260.md" "b/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\346\246\202\350\277\260.md"
index 2345fe8..fb7f88e 100644
--- "a/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\346\246\202\350\277\260.md"
+++ "b/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\346\246\202\350\277\260.md"
@@ -1,4 +1,77 @@
-[## 一、SpringMVC简介
+# 目录
+
+ * [1.1、SpringMVC引言](#11、springmvc引言)
+ * [1.2、SpringMVC的优势](#12、springmvc的优势)
+ * [二、SpringMVC入门](#二、springmvc入门)
+ * [2.1、环境搭建](#21、环境搭建)
+ * [2.1.1、引入依赖](#211、引入依赖)
+ * [2.1.2、编写配置文件](#212、编写配置文件)
+ * [2.1.3、配置web.xml](#213、配置webxml)
+ * [2.1.4、编写控制器](#214、编写控制器)
+ * [2.2、注解详解](#22、注解详解)
+ * [2.2.1、@Controller](#221、controller)
+ * [2.2.2、@RequestMapping](#222、requestmapping)
+ * [2.3、SpringMVC的跳转方式](#23、springmvc的跳转方式)
+ * [2.3.1、Controller ——>前台页面](#231、controller-前台页面)
+ * [2.3.1.1、forward](#2311、forward)
+ * [2.3.1.2、redirect](#2312、redirect)
+ * [2.3.1Controller ——>Controller](#231controller-controller)
+ * [2.3.1.1、forward](#2311、forward-1)
+ * [2.3.1.2、redirect](#2312、redirect-1)
+ * [2.4、SpringMVC的参数接收](#24、springmvc的参数接收)
+ * [2.4.1、Servlet接收参数的方式](#241、servlet接收参数的方式)
+ * [2.4.2、SpringMVC的参数接收](#242、springmvc的参数接收)
+ * [2.4.2.1、基本数据类型](#2421、基本数据类型)
+ * [2.4.2.2、对象类型](#2422、对象类型)
+ * [2.4.2.3、数组类型](#2423、数组类型)
+ * [2.4.2.4、集合类型](#2424、集合类型)
+ * [2.5、SpringMVC接收参数中文乱码问题](#25、springmvc接收参数中文乱码问题)
+ * [2.5.1、GET请求](#251、get请求)
+ * [2.5.2、POST请求](#252、post请求)
+ * [2.5.2.1、自定义过滤器解决POST乱码请求](#2521、自定义过滤器解决post乱码请求)
+ * [2.5.2.2、使用CharacterEncodingFilter解决POST乱码请求](#2522、使用characterencodingfilter解决post乱码请求)
+ * [2.6、SpringMVC中数据传递机制](#26、springmvc中数据传递机制)
+ * [2.6.1、什么事数据传递机制](#261、什么事数据传递机制)
+ * [2.6.2、Servlet的数据传递机制](#262、servlet的数据传递机制)
+ * [三、前端控制器](#三、前端控制器)
+ * [3.1、什么是前端控制器](#31、什么是前端控制器)
+ * [3.2、代码实现](#32、代码实现)
+ * [3.3、注意](#33、注意)
+ * [3.4、映射路径](#34、映射路径)
+ * [3.4.1、访问静态资源和 JSP 被拦截的原因](#341、访问静态资源和-jsp-被拦截的原因)
+ * [3.4.2、如何解决](#342、如何解决)
+ * [3.4.2.1、方式一](#3421、方式一)
+ * [3.4.2.2、方式二](#3422、方式二)
+ * [3.5、@ModelAttribute 注解](#35、modelattribute-注解)
+ * [四、处理响应](#四、处理响应)
+ * [4.1、返回 ModelAndView](#41、返回-modelandview)
+ * [4.2、返回String](#42、返回string)
+ * [4.3、改进](#43、改进)
+ * [五、请求转发和重定向](#五、请求转发和重定向)
+ * [5.1、请求转发和重定向的区别](#51、请求转发和重定向的区别)
+ * [5.2、请求转发](#52、请求转发)
+ * [5.3、重定向](#53、重定向)
+ * [5.4、请求路径](#54、请求路径)
+ * [六、参数处理](#六、参数处理)
+ * [6.1、处理简单类型的请求参数](#61、处理简单类型的请求参数)
+ * [6.1.1、请求参数名和控制器方法参数列表形参同名](#611、请求参数名和控制器方法参数列表形参同名)
+ * [6.1.2、请求参数名和控制器方法参数列表形参不同名](#612、请求参数名和控制器方法参数列表形参不同名)
+ * [6.2、处理复杂类型的请求参数](#62、处理复杂类型的请求参数)
+ * [6.2.1、数组类型](#621、数组类型)
+ * [6.2.2、自定义类型](#622、自定义类型)
+ * [6.3、处理日期类型的请求参数](#63、处理日期类型的请求参数)
+ * [6.3.1、日期在请求参数上](#631、日期在请求参数上)
+ * [6.3.2、在封装的对象上](#632、在封装的对象上)
+ * [七、文件上传与下载](#七、文件上传与下载)
+ * [7.1、文件上传](#71、文件上传)
+ * [7.1.1、编写表单](#711、编写表单)
+ * [7.1.2、修改web.xml](#712、修改webxml)
+ * [7.1.3、配置上传解析器](#713、配置上传解析器)
+ * [7.1.4、配置上传控制器](#714、配置上传控制器)
+ * [7.2、文件下载](#72、文件下载)
+ * [7.2.1、开发控制器](#721、开发控制器)
+
+
## 1.1、SpringMVC引言
@@ -942,5 +1015,3 @@ package cn.linstudy.controller;
return null;
}
```
-
-]([]())
\ No newline at end of file
diff --git "a/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\347\232\204\350\247\206\345\233\276\350\247\243\346\236\220\345\216\237\347\220\206.md" "b/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\347\232\204\350\247\206\345\233\276\350\247\243\346\236\220\345\216\237\347\220\206.md"
index 6a3357f..cb28598 100644
--- "a/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\347\232\204\350\247\206\345\233\276\350\247\243\346\236\220\345\216\237\347\220\206.md"
+++ "b/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\347\232\204\350\247\206\345\233\276\350\247\243\346\236\220\345\216\237\347\220\206.md"
@@ -4,8 +4,6 @@
* [重要接口和类介绍](#重要接口和类介绍)
* [源码分析](#源码分析)
* [编码自定义的ViewResolver](#编码自定义的viewresolver)
- * [This is jsp page](#this-is-jsp-page)
- * [This is freemarker page](#this-is-freemarker-page)
* [总结](#总结)
diff --git "a/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232\346\266\210\346\201\257\350\275\254\346\215\242\345\231\250HttpMessageConverter\344\270\216@ResponseBody\346\263\250\350\247\243.md" "b/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232\346\266\210\346\201\257\350\275\254\346\215\242\345\231\250HttpMessageConverter\344\270\216@ResponseBody\346\263\250\350\247\243.md"
index f34de3a..d4cb3bc 100644
--- "a/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232\346\266\210\346\201\257\350\275\254\346\215\242\345\231\250HttpMessageConverter\344\270\216@ResponseBody\346\263\250\350\247\243.md"
+++ "b/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232\346\266\210\346\201\257\350\275\254\346\215\242\345\231\250HttpMessageConverter\344\270\216@ResponseBody\346\263\250\350\247\243.md"
@@ -1,5 +1,4 @@
# 目录
-* [目录](#目录)
* [前言](#前言)
* [现象](#现象)
* [源码分析](#源码分析)
@@ -29,17 +28,7 @@
如果对本系列文章有什么建议,或者是有什么疑问的话,也可以关注公众号【Java技术江湖】联系作者,欢迎你参与本系列博文的创作和修订。
-
-
-## 目录
-
-* [前言](http://www.cnblogs.com/fangjian0423/p/springMVC-xml-json-convert.html#preface)
-* [现象](http://www.cnblogs.com/fangjian0423/p/springMVC-xml-json-convert.html#phenomenon)
-* [源码分析](http://www.cnblogs.com/fangjian0423/p/springMVC-xml-json-convert.html#analysis)
-* [实例讲解](http://www.cnblogs.com/fangjian0423/p/springMVC-xml-json-convert.html#demo)
-* [关于配置](http://www.cnblogs.com/fangjian0423/p/springMVC-xml-json-convert.html#config)
-* [总结](http://www.cnblogs.com/fangjian0423/p/springMVC-xml-json-convert.html#summary)
-* [参考资料](http://www.cnblogs.com/fangjian0423/p/springMVC-xml-json-convert.html#reference)
+
## 前言
diff --git "a/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232Hibernate\345\205\245\351\227\250\347\273\217\345\205\270\344\270\216\346\263\250\350\247\243\345\274\217\345\274\200\345\217\221.md" "b/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232Hibernate\345\205\245\351\227\250\347\273\217\345\205\270\344\270\216\346\263\250\350\247\243\345\274\217\345\274\200\345\217\221.md"
index e9ff30d..76dfece 100644
--- "a/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232Hibernate\345\205\245\351\227\250\347\273\217\345\205\270\344\270\216\346\263\250\350\247\243\345\274\217\345\274\200\345\217\221.md"
+++ "b/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232Hibernate\345\205\245\351\227\250\347\273\217\345\205\270\344\270\216\346\263\250\350\247\243\345\274\217\345\274\200\345\217\221.md"
@@ -5,9 +5,6 @@
* [相关类](#相关类)
* [扩展](#扩展)
* [参考文章](#参考文章)
-* [微信公众号](#微信公众号)
- * [个人公众号:程序员黄小斜](#个人公众号:程序员黄小斜)
- * [技术公众号:Java技术江湖](#技术公众号:java技术江湖)
本文转载自互联网,侵删
diff --git "a/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232Mybatis\345\205\245\351\227\250.md" "b/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232Mybatis\345\205\245\351\227\250.md"
index fa50a2b..bc23655 100644
--- "a/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232Mybatis\345\205\245\351\227\250.md"
+++ "b/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232Mybatis\345\205\245\351\227\250.md"
@@ -18,9 +18,6 @@
* [3.会话工厂与会话](#3会话工厂与会话)
* [4.运行流程](#4运行流程)
* [测试工程搭建](#测试工程搭建)
- * [微信公众号](#微信公众号-1)
- * [个人公众号:程序员黄小斜](#个人公众号:程序员黄小斜)
- * [技术公众号:Java技术江湖](#技术公众号:java技术江湖)
本文转载自互联网,侵删
diff --git "a/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232Tomcat5\346\200\273\344\275\223\346\236\266\346\236\204\345\211\226\346\236\220.md" "b/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232Tomcat5\346\200\273\344\275\223\346\236\266\346\236\204\345\211\226\346\236\220.md"
index fa1490e..5937ec0 100644
--- "a/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232Tomcat5\346\200\273\344\275\223\346\236\266\346\236\204\345\211\226\346\236\220.md"
+++ "b/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232Tomcat5\346\200\273\344\275\223\346\236\266\346\236\204\345\211\226\346\236\220.md"
@@ -1,3 +1,9 @@
+# 目录
+
+ * [连接器(Connector)](#连接器(connector))
+ * [容器(Container)](#容器(container))
+
+
本文转载自互联网,侵删
本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看
@@ -187,4 +193,4 @@ Container[] conHosts = engine.findChildren();
定位 Servlet 的流程图:
-
\ No newline at end of file
+
diff --git "a/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232\344\273\216\346\211\213\345\212\250\347\274\226\350\257\221\346\211\223\345\214\205\345\210\260\351\241\271\347\233\256\346\236\204\345\273\272\345\267\245\345\205\267Maven.md" "b/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232\344\273\216\346\211\213\345\212\250\347\274\226\350\257\221\346\211\223\345\214\205\345\210\260\351\241\271\347\233\256\346\236\204\345\273\272\345\267\245\345\205\267Maven.md"
index 7f80e4f..d6cfa8c 100644
--- "a/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232\344\273\216\346\211\213\345\212\250\347\274\226\350\257\221\346\211\223\345\214\205\345\210\260\351\241\271\347\233\256\346\236\204\345\273\272\345\267\245\345\205\267Maven.md"
+++ "b/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232\344\273\216\346\211\213\345\212\250\347\274\226\350\257\221\346\211\223\345\214\205\345\210\260\351\241\271\347\233\256\346\236\204\345\273\272\345\267\245\345\205\267Maven.md"
@@ -9,8 +9,6 @@
* [maven目录](#maven目录)
* [Maven常用命令说明](#maven常用命令说明)
* [Maven使用](#maven使用)
- * [[](http://tengj.top/2018/01/01/maven/#%E4%BE%9D%E8%B5%96%E7%9A%84%E9%85%8D%E7%BD%AE "依赖的配置")依赖的配置](#[]httptengjtop20180101mavene4be9de8b596e79a84e9858de7bdae-依赖的配置依赖的配置)
- * [[](http://tengj.top/2018/01/01/maven/#%E4%BE%9D%E8%B5%96%E8%8C%83%E5%9B%B4 "依赖范围")依赖范围](#[]httptengjtop20180101mavene4be9de8b596e88c83e59bb4-依赖范围依赖范围)
* [传递性依赖](#传递性依赖)
* [依赖范围](#依赖范围)
* [Maven和Gradle的比较](#maven和gradle的比较)
diff --git "a/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232\345\215\225\345\205\203\346\265\213\350\257\225\346\241\206\346\236\266Junit.md" "b/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232\345\215\225\345\205\203\346\265\213\350\257\225\346\241\206\346\236\266Junit.md"
index 0732005..ee6dffc 100644
--- "a/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232\345\215\225\345\205\203\346\265\213\350\257\225\346\241\206\346\236\266Junit.md"
+++ "b/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232\345\215\225\345\205\203\346\265\213\350\257\225\346\241\206\346\236\266Junit.md"
@@ -16,9 +16,6 @@
* [5.1 示例一:简单的 JUnit 3.X 测试](#51-示例一:简单的-junit-3x-测试)
* [6 个人建议](#6-个人建议)
* [8 大单元测试框架](#8-大单元测试框架)
-* [微信公众号](#微信公众号)
- * [个人公众号:程序员黄小斜](#个人公众号:程序员黄小斜)
- * [技术公众号:Java技术江湖](#技术公众号:java技术江湖)
diff --git "a/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232\346\236\201\347\256\200\351\205\215\347\275\256\347\232\204SpringBoot.md" "b/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232\346\236\201\347\256\200\351\205\215\347\275\256\347\232\204SpringBoot.md"
index adaa923..e98f6e8 100644
--- "a/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232\346\236\201\347\256\200\351\205\215\347\275\256\347\232\204SpringBoot.md"
+++ "b/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232\346\236\201\347\256\200\351\205\215\347\275\256\347\232\204SpringBoot.md"
@@ -15,9 +15,6 @@
* [Spring Boot 支持 JSP](#spring-boot-支持-jsp)
* [集成 MyBatis](#集成-mybatis)
* [springMVC和springboot的区别](#springmvc和springboot的区别)
-* [微信公众号](#微信公众号)
- * [个人公众号:程序员黄小斜](#个人公众号:程序员黄小斜)
- * [技术公众号:Java技术江湖](#技术公众号:java技术江湖)
本文转载自互联网,侵删
diff --git "a/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232\346\267\261\345\205\245\346\265\205\345\207\272Mybatis\345\237\272\346\234\254\345\216\237\347\220\206.md" "b/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232\346\267\261\345\205\245\346\265\205\345\207\272Mybatis\345\237\272\346\234\254\345\216\237\347\220\206.md"
index 1b37c95..7556dc4 100644
--- "a/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232\346\267\261\345\205\245\346\265\205\345\207\272Mybatis\345\237\272\346\234\254\345\216\237\347\220\206.md"
+++ "b/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\214\357\274\232\346\267\261\345\205\245\346\265\205\345\207\272Mybatis\345\237\272\346\234\254\345\216\237\347\220\206.md"
@@ -1,5 +1,4 @@
# 目录
-
* [引言](#引言)
* [工作原理原型图](#工作原理原型图)
* [工作原理解析](#工作原理解析)
@@ -8,9 +7,6 @@
* [MyBatis的配置](#mybatis的配置)
* [MyBatis的主要成员](#mybatis的主要成员)
* [参考文章](#参考文章)
-* [微信公众号](#微信公众号)
- * [个人公众号:程序员黄小斜](#个人公众号:程序员黄小斜)
- * [技术公众号:Java技术江湖](#技术公众号:java技术江湖)
本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看
diff --git "a/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232JMM\344\270\255\347\232\204final\345\205\263\351\224\256\345\255\227\350\247\243\346\236\220.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232JMM\344\270\255\347\232\204final\345\205\263\351\224\256\345\255\227\350\247\243\346\236\220.md"
index f7fe31b..c9a13f8 100644
--- "a/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232JMM\344\270\255\347\232\204final\345\205\263\351\224\256\345\255\227\350\247\243\346\236\220.md"
+++ "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\227\357\274\232JMM\344\270\255\347\232\204final\345\205\263\351\224\256\345\255\227\350\247\243\346\236\220.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [一、properly constructed / this对象逸出](#一、properly-constructed--this对象逸出)
* [二、对象的安全发布](#二、对象的安全发布)
diff --git "a/docs/java/design-parttern/\345\210\235\346\216\242Java\350\256\276\350\256\241\346\250\241\345\274\217\357\274\232JDK\344\270\255\347\232\204\350\256\276\350\256\241\346\250\241\345\274\217.md" "b/docs/java/design-parttern/\345\210\235\346\216\242Java\350\256\276\350\256\241\346\250\241\345\274\217\357\274\232JDK\344\270\255\347\232\204\350\256\276\350\256\241\346\250\241\345\274\217.md"
index 61748b1..ab7b901 100644
--- "a/docs/java/design-parttern/\345\210\235\346\216\242Java\350\256\276\350\256\241\346\250\241\345\274\217\357\274\232JDK\344\270\255\347\232\204\350\256\276\350\256\241\346\250\241\345\274\217.md"
+++ "b/docs/java/design-parttern/\345\210\235\346\216\242Java\350\256\276\350\256\241\346\250\241\345\274\217\357\274\232JDK\344\270\255\347\232\204\350\256\276\350\256\241\346\250\241\345\274\217.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [**一,结构型模式**](#一,结构型模式)
* [**1,适配器模式**](#1,适配器模式)
diff --git "a/docs/java/jvm/temp/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232GC\350\260\203\344\274\230\346\200\235\350\267\257\344\270\216\345\270\270\347\224\250\345\267\245\345\205\267.md" "b/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232GC\350\260\203\344\274\230\346\200\235\350\267\257\344\270\216\345\270\270\347\224\250\345\267\245\345\205\267.md"
similarity index 99%
rename from "docs/java/jvm/temp/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232GC\350\260\203\344\274\230\346\200\235\350\267\257\344\270\216\345\270\270\347\224\250\345\267\245\345\205\267.md"
rename to "docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232GC\350\260\203\344\274\230\346\200\235\350\267\257\344\270\216\345\270\270\347\224\250\345\267\245\345\205\267.md"
index 30d3350..ceda305 100644
--- "a/docs/java/jvm/temp/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232GC\350\260\203\344\274\230\346\200\235\350\267\257\344\270\216\345\270\270\347\224\250\345\267\245\345\205\267.md"
+++ "b/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232GC\350\260\203\344\274\230\346\200\235\350\267\257\344\270\216\345\270\270\347\224\250\345\267\245\345\205\267.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [核心概念(Core Concepts)](#核心概念core-concepts)
* [Latency(延迟)](#latency延迟)
diff --git "a/docs/java/jvm/temp/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232JVM\345\270\270\347\224\250\345\217\202\346\225\260\344\273\245\345\217\212\350\260\203\344\274\230\345\256\236\350\267\265.md" "b/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232JVM\345\270\270\347\224\250\345\217\202\346\225\260\344\273\245\345\217\212\350\260\203\344\274\230\345\256\236\350\267\265.md"
similarity index 99%
rename from "docs/java/jvm/temp/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232JVM\345\270\270\347\224\250\345\217\202\346\225\260\344\273\245\345\217\212\350\260\203\344\274\230\345\256\236\350\267\265.md"
rename to "docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232JVM\345\270\270\347\224\250\345\217\202\346\225\260\344\273\245\345\217\212\350\260\203\344\274\230\345\256\236\350\267\265.md"
index 5b7c03c..caac027 100644
--- "a/docs/java/jvm/temp/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232JVM\345\270\270\347\224\250\345\217\202\346\225\260\344\273\245\345\217\212\350\260\203\344\274\230\345\256\236\350\267\265.md"
+++ "b/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232JVM\345\270\270\347\224\250\345\217\202\346\225\260\344\273\245\345\217\212\350\260\203\344\274\230\345\256\236\350\267\265.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [JVM优化的必要性](#jvm优化的必要性)
* [JVM调优原则](#jvm调优原则)
diff --git "a/docs/java/network-programming/Java\347\275\221\347\273\234\344\270\216NIO\346\200\273\347\273\223.md" "b/docs/java/network-programming/Java\347\275\221\347\273\234\344\270\216NIO\346\200\273\347\273\223.md"
index 634e1c6..15c003a 100644
--- "a/docs/java/network-programming/Java\347\275\221\347\273\234\344\270\216NIO\346\200\273\347\273\223.md"
+++ "b/docs/java/network-programming/Java\347\275\221\347\273\234\344\270\216NIO\346\200\273\347\273\223.md"
@@ -1,3 +1,17 @@
+# 目录
+
+* [目录](#目录)
+ * [Java IO](#java-io)
+ * [Socket编程](#socket编程)
+ * [客户端,服务端的线程模型](#客户端,服务端的线程模型)
+ * [IO模型](#io模型)
+ * [NIO](#nio)
+ * [AIO](#aio)
+ * [Tomcat中的NIO模型](#tomcat中的nio模型)
+ * [Tomcat的container](#tomcat的container)
+ * [netty](#netty)
+
+
# 目录
* [Java IO](#java-io)
* [Socket编程](#socket编程)
diff --git "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232IO\346\250\241\345\236\213\344\270\216Java\347\275\221\347\273\234\347\274\226\347\250\213\346\250\241\345\236\213.md" "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232IO\346\250\241\345\236\213\344\270\216Java\347\275\221\347\273\234\347\274\226\347\250\213\346\250\241\345\236\213.md"
index 838c7d7..deca42f 100644
--- "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232IO\346\250\241\345\236\213\344\270\216Java\347\275\221\347\273\234\347\274\226\347\250\213\346\250\241\345\236\213.md"
+++ "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232IO\346\250\241\345\236\213\344\270\216Java\347\275\221\347\273\234\347\274\226\347\250\213\346\250\241\345\236\213.md"
@@ -1,3 +1,21 @@
+# 目录
+
+* [目录](#目录)
+ * [IO模型介绍](#io模型介绍)
+ * [阻塞 I/O(blocking IO)](#阻塞-io(blocking-io))
+ * [非阻塞 I/O(nonblocking IO)](#非阻塞-io(nonblocking-io))
+ * [I/O 多路复用( IO multiplexing)](#io-多路复用(-io-multiplexing))
+ * [异步 I/O(asynchronous IO)](#异步-io(asynchronous-io))
+ * [阻塞IO,非阻塞IO 与 同步IO, 异步IO的区别和联系](#阻塞io非阻塞io-与-同步io-异步io的区别和联系)
+ * [IO模型的形象举例](#io模型的形象举例)
+ * [Select/Poll/Epoll 轮询机制](#selectpollepoll-轮询机制)
+ * [Java网络编程模型](#java网络编程模型)
+ * [BIO](#bio)
+ * [NIO](#nio)
+ * [AIO](#aio)
+ * [对比](#对比)
+
+
# 目录
* [IO模型介绍](#io模型介绍)
* [阻塞 I/O(blocking IO)](#阻塞-io(blocking-io))
diff --git "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232JAVA\344\270\255\345\216\237\347\224\237\347\232\204socket\351\200\232\344\277\241\346\234\272\345\210\266.md" "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232JAVA\344\270\255\345\216\237\347\224\237\347\232\204socket\351\200\232\344\277\241\346\234\272\345\210\266.md"
index 32a6684..04f25ab 100644
--- "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232JAVA\344\270\255\345\216\237\347\224\237\347\232\204socket\351\200\232\344\277\241\346\234\272\345\210\266.md"
+++ "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232JAVA\344\270\255\345\216\237\347\224\237\347\232\204socket\351\200\232\344\277\241\346\234\272\345\210\266.md"
@@ -1,3 +1,13 @@
+# 目录
+
+ * [当前环境](#当前环境)
+ * [处理 socket 输入输出流](#处理-socket-输入输出流)
+ * [结果展示](#结果展示)
+ * [请求模型优化](#请求模型优化)
+ * [补充1:TCP客户端与服务端](#补充1:tcp客户端与服务端)
+ * [补充2:UDP客户端和服务端](#补充2:udp客户端和服务端)
+
+
本文转自:https://github.com/jasonGeng88/blog
本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看
diff --git "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232JavaNIO\344\270\200\346\255\245\346\255\245\346\236\204\345\273\272IO\345\244\232\350\267\257\345\244\215\347\224\250\347\232\204\350\257\267\346\261\202\346\250\241\345\236\213.md" "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232JavaNIO\344\270\200\346\255\245\346\255\245\346\236\204\345\273\272IO\345\244\232\350\267\257\345\244\215\347\224\250\347\232\204\350\257\267\346\261\202\346\250\241\345\236\213.md"
index 65d0917..47e6d17 100644
--- "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232JavaNIO\344\270\200\346\255\245\346\255\245\346\236\204\345\273\272IO\345\244\232\350\267\257\345\244\215\347\224\250\347\232\204\350\257\267\346\261\202\346\250\241\345\236\213.md"
+++ "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232JavaNIO\344\270\200\346\255\245\346\255\245\346\236\204\345\273\272IO\345\244\232\350\267\257\345\244\215\347\224\250\347\232\204\350\257\267\346\261\202\346\250\241\345\236\213.md"
@@ -1,3 +1,13 @@
+# 目录
+
+ * [当前环境](#当前环境)
+ * [代码地址](#代码地址)
+ * [知识点](#知识点)
+ * [获取 socket 连接](#获取-socket-连接)
+ * [完整示例](#完整示例)
+ * [处理连接就绪事件](#处理连接就绪事件)
+
+
本文转载自:[https://github.com/jasonGeng88/blog](https://github.com/jasonGeng88/blog)
本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看
@@ -474,4 +484,4 @@ public class NioNonBlockingHttpClient {
````

-本文从 nio 的阻塞方式讲起,介绍了阻塞 I/O 与非阻塞 I/O 的区别,以及在 nio 下是如何一步步构建一个 IO 多路复用的模型的客户端。文中需要理解的内容比较多,如果有理解错误的地方,欢迎指正~
\ No newline at end of file
+本文从 nio 的阻塞方式讲起,介绍了阻塞 I/O 与非阻塞 I/O 的区别,以及在 nio 下是如何一步步构建一个 IO 多路复用的模型的客户端。文中需要理解的内容比较多,如果有理解错误的地方,欢迎指正~
diff --git "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232Java\351\235\236\351\230\273\345\241\236IO\345\222\214\345\274\202\346\255\245IO.md" "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232Java\351\235\236\351\230\273\345\241\236IO\345\222\214\345\274\202\346\255\245IO.md"
index 2837b73..35be566 100644
--- "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232Java\351\235\236\351\230\273\345\241\236IO\345\222\214\345\274\202\346\255\245IO.md"
+++ "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232Java\351\235\236\351\230\273\345\241\236IO\345\222\214\345\274\202\346\255\245IO.md"
@@ -1,3 +1,18 @@
+# 目录
+
+* [目录](#目录)
+ * [阻塞模式 IO](#阻塞模式-io)
+ * [非阻塞 IO](#非阻塞-io)
+ * [NIO.2 异步 IO](#nio2-异步-io)
+ * [1、返回 Future 实例](#1、返回-future-实例)
+ * [2、提供 CompletionHandler 回调函数](#2、提供-completionhandler-回调函数)
+ * [AsynchronousFileChannel](#asynchronousfilechannel)
+ * [AsynchronousServerSocketChannel](#asynchronousserversocketchannel)
+ * [AsynchronousSocketChannel](#asynchronoussocketchannel)
+ * [Asynchronous Channel Groups](#asynchronous-channel-groups)
+ * [小结](#小结)
+
+
# 目录
* [阻塞模式 IO](#阻塞模式-io)
* [非阻塞 IO](#非阻塞-io)
diff --git "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232LinuxEpoll\345\256\236\347\216\260\345\216\237\347\220\206\350\257\246\350\247\243.md" "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232LinuxEpoll\345\256\236\347\216\260\345\216\237\347\220\206\350\257\246\350\247\243.md"
index 8a4ec27..41852cd 100644
--- "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232LinuxEpoll\345\256\236\347\216\260\345\216\237\347\220\206\350\257\246\350\247\243.md"
+++ "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232LinuxEpoll\345\256\236\347\216\260\345\216\237\347\220\206\350\257\246\350\247\243.md"
@@ -1,3 +1,14 @@
+# 目录
+
+ * [为什么要 I/O 多路复用](#为什么要-io-多路复用)
+ * [select](#select)
+ * [poll](#poll)
+ * [epoll](#epoll)
+ * [epoll_create 用来创建一个 epoll 描述符:](#epoll_create-用来创建一个-epoll-描述符:)
+ * [epoll_ctl 用来增/删/改内核中的事件表:](#epoll_ctl-用来增删改内核中的事件表:)
+ * [epoll_wait 用来等待事件](#epoll_wait-用来等待事件)
+
+
本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看
> https://github.com/h2pl/Java-Tutorial
diff --git "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232Tomcat\344\270\255\347\232\204Connector\346\272\220\347\240\201\345\210\206\346\236\220\357\274\210NIO\357\274\211.md" "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232Tomcat\344\270\255\347\232\204Connector\346\272\220\347\240\201\345\210\206\346\236\220\357\274\210NIO\357\274\211.md"
index 2a3740d..7404a6e 100644
--- "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232Tomcat\344\270\255\347\232\204Connector\346\272\220\347\240\201\345\210\206\346\236\220\357\274\210NIO\357\274\211.md"
+++ "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232Tomcat\344\270\255\347\232\204Connector\346\272\220\347\240\201\345\210\206\346\236\220\357\274\210NIO\357\274\211.md"
@@ -1,3 +1,17 @@
+# 目录
+
+* [目录](#目录)
+ * [前言](#前言)
+ * [源码环境准备](#源码环境准备)
+ * [endpoint](#endpoint)
+ * [init 过程分析](#init-过程分析)
+ * [start 过程分析](#start-过程分析)
+ * [Acceptor](#acceptor)
+ * [Poller](#poller)
+ * [processKey](#processkey)
+ * [总结](#总结)
+
+
# 目录
* [前言](#前言)
* [源码环境准备](#源码环境准备)
diff --git "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232\345\237\272\344\272\216NIO\347\232\204\347\275\221\347\273\234\347\274\226\347\250\213\346\241\206\346\236\266Netty.md" "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232\345\237\272\344\272\216NIO\347\232\204\347\275\221\347\273\234\347\274\226\347\250\213\346\241\206\346\236\266Netty.md"
index fd4cdf2..f2d39e8 100644
--- "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232\345\237\272\344\272\216NIO\347\232\204\347\275\221\347\273\234\347\274\226\347\250\213\346\241\206\346\236\266Netty.md"
+++ "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232\345\237\272\344\272\216NIO\347\232\204\347\275\221\347\273\234\347\274\226\347\250\213\346\241\206\346\236\266Netty.md"
@@ -1,3 +1,23 @@
+# 目录
+
+* [目录](#目录)
+ * [Netty概述](#netty概述)
+ * [Netty简介](#netty简介)
+ * [Netty都有哪些组件?](#netty都有哪些组件?)
+ * [Netty是如何处理连接请求和业务逻辑的呢?](#netty是如何处理连接请求和业务逻辑的呢?)
+ * [如何配置一个Netty应用?](#如何配置一个netty应用?)
+ * [Netty是如何处理数据的?](#netty是如何处理数据的?)
+ * [如何处理我们的业务逻辑?](#如何处理我们的业务逻辑?)
+ * [ByteBuf](#bytebuf)
+ * [Channel](#channel)
+ * [ChannelHandler](#channelhandler)
+ * [ChannelPipeline](#channelpipeline)
+ * [EventLoop](#eventloop)
+ * [Bootstrap](#bootstrap)
+ * [Echo示例](#echo示例)
+ * [参考文献](#参考文献)
+
+
# 目录
* [Netty概述](#netty概述)
* [etty简介](#etty简介)
diff --git "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232\346\265\205\346\236\220NIO\345\214\205\344\270\255\347\232\204Buffer\343\200\201Channel\345\222\214Selector.md" "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232\346\265\205\346\236\220NIO\345\214\205\344\270\255\347\232\204Buffer\343\200\201Channel\345\222\214Selector.md"
index 020f65f..5d47624 100644
--- "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232\346\265\205\346\236\220NIO\345\214\205\344\270\255\347\232\204Buffer\343\200\201Channel\345\222\214Selector.md"
+++ "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232\346\265\205\346\236\220NIO\345\214\205\344\270\255\347\232\204Buffer\343\200\201Channel\345\222\214Selector.md"
@@ -1,3 +1,22 @@
+# 目录
+
+* [目录](#目录)
+ * [Buffer](#buffer)
+ * [position、limit、capacity](#position、limit、capacity)
+ * [初始化 Buffer](#初始化-buffer)
+ * [填充 Buffer](#填充-buffer)
+ * [提取 Buffer 中的值](#提取-buffer-中的值)
+ * [mark() & reset()](#mark--reset)
+ * [rewind() & clear() & compact()](#rewind--clear--compact)
+ * [Channel](#channel)
+ * [FileChannel](#filechannel)
+ * [SocketChannel](#socketchannel)
+ * [ServerSocketChannel](#serversocketchannel)
+ * [DatagramChannel](#datagramchannel)
+ * [Selector](#selector)
+ * [小结](#小结)
+
+
# 目录
* [Buffer](#buffer)
* [position、limit、capacity](#position、limit、capacity)
diff --git "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232\346\265\205\346\236\220mmap\345\222\214DirectBuffer.md" "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232\346\265\205\346\236\220mmap\345\222\214DirectBuffer.md"
index f50c0df..8256703 100644
--- "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232\346\265\205\346\236\220mmap\345\222\214DirectBuffer.md"
+++ "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232\346\265\205\346\236\220mmap\345\222\214DirectBuffer.md"
@@ -1,3 +1,30 @@
+# 目录
+
+* [目录](#目录)
+* [mmap基础概念](#mmap基础概念)
+* [mmap内存映射原理](#mmap内存映射原理)
+* [mmap和常规文件操作的区别](#mmap和常规文件操作的区别)
+* [mmap优点总结](#mmap优点总结)
+* [mmap使用细节](#mmap使用细节)
+ * [堆外内存](#堆外内存)
+ * [在讲解DirectByteBuffer之前,需要先简单了解两个知识点](#在讲解directbytebuffer之前,需要先简单了解两个知识点)
+ * [java引用类型,因为DirectByteBuffer是通过虚引用(Phantom Reference)来实现堆外内存的释放的。](#java引用类型,因为directbytebuffer是通过虚引用phantom-reference来实现堆外内存的释放的。)
+ * [关于linux的内核态和用户态](#关于linux的内核态和用户态)
+ * [DirectByteBuffer ———— 直接缓冲](#directbytebuffer--直接缓冲)
+ * [DirectByteBuffer堆外内存的创建和回收的源码解读](#directbytebuffer堆外内存的创建和回收的源码解读)
+ * [堆外内存分配](#堆外内存分配)
+ * [Bits.reserveMemory(size, cap) 方法](#bitsreservememorysize-cap-方法)
+ * [堆外内存回收](#堆外内存回收)
+ * [通过配置参数的方式来回收堆外内存](#通过配置参数的方式来回收堆外内存)
+ * [堆外内存那些事](#堆外内存那些事)
+ * [使用堆外内存的原因](#使用堆外内存的原因)
+ * [什么情况下使用堆外内存](#什么情况下使用堆外内存)
+ * [堆外内存 VS 内存池](#堆外内存-vs-内存池)
+ * [堆外内存的特点](#堆外内存的特点)
+ * [堆外内存的一些问题](#堆外内存的一些问题)
+ * [参考文章](#参考文章)
+
+
# 目录
* [mmap基础概念](#mmap基础概念)
* [mmap内存映射原理](#mmap内存映射原理)
diff --git "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232\346\265\205\350\260\210Linux\344\270\255Selector\347\232\204\345\256\236\347\216\260\345\216\237\347\220\206.md" "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232\346\265\205\350\260\210Linux\344\270\255Selector\347\232\204\345\256\236\347\216\260\345\216\237\347\220\206.md"
index 02dc4e4..550f7ab 100644
--- "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232\346\265\205\350\260\210Linux\344\270\255Selector\347\232\204\345\256\236\347\216\260\345\216\237\347\220\206.md"
+++ "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232\346\265\205\350\260\210Linux\344\270\255Selector\347\232\204\345\256\236\347\216\260\345\216\237\347\220\206.md"
@@ -1,3 +1,22 @@
+# 目录
+
+* [目录](#目录)
+ * [概述](#概述)
+ * [Selector的中的重要属性](#selector的中的重要属性)
+ * [Selector 源码解析](#selector-源码解析)
+ * [1、Selector的构建](#1、selector的构建)
+ * [接下来看下 selector.open():](#接下来看下-selectoropen:)
+ * [EPollSelectorImpl](#epollselectorimpl)
+ * [EPollArrayWrapper](#epollarraywrapper)
+ * [ServerSocketChannel的构建](#serversocketchannel的构建)
+ * [将ServerSocketChannel注册到Selector](#将serversocketchannel注册到selector)
+ * [EPollSelectorImpl. implRegister](#epollselectorimpl-implregister)
+ * [Selection操作](#selection操作)
+ * [epoll原理](#epoll原理)
+ * [后记](#后记)
+ * [参考文章](#参考文章)
+
+
# 目录
* [概述](#概述)
* [Selector的中的重要属性](#selector的中的重要属性)
diff --git "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232\346\267\261\345\272\246\350\247\243\350\257\273Tomcat\344\270\255\347\232\204NIO\346\250\241\345\236\213.md" "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232\346\267\261\345\272\246\350\247\243\350\257\273Tomcat\344\270\255\347\232\204NIO\346\250\241\345\236\213.md"
index ad909d5..65f5206 100644
--- "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232\346\267\261\345\272\246\350\247\243\350\257\273Tomcat\344\270\255\347\232\204NIO\346\250\241\345\236\213.md"
+++ "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\243\357\274\232\346\267\261\345\272\246\350\247\243\350\257\273Tomcat\344\270\255\347\232\204NIO\346\250\241\345\236\213.md"
@@ -1,3 +1,16 @@
+# 目录
+
+* [目录](#目录)
+ * [一、I/O复用模型解读](#一、io复用模型解读)
+ * [二、TOMCAT对IO模型的支持](#二、tomcat对io模型的支持)
+ * [三、TOMCAT中NIO的配置与使用](#三、tomcat中nio的配置与使用)
+ * [四、NioEndpoint组件关系图解读](#四、nioendpoint组件关系图解读)
+ * [五、NioEndpoint执行序列图](#五、nioendpoint执行序列图)
+ * [六、NioEndpoint源码解读](#六、nioendpoint源码解读)
+ * [七、关于性能](#七、关于性能)
+ * [八、总结](#八、总结)
+
+
# 目录
* [一、I/O复用模型解读](#一、io复用模型解读)
* [二、TOMCAT对IO模型的支持](#二、tomcat对io模型的支持)
diff --git a/src/main/java/md/mdToc.java b/src/main/java/md/mdToc.java
index 0cf8f98..2fb42bd 100644
--- a/src/main/java/md/mdToc.java
+++ b/src/main/java/md/mdToc.java
@@ -4,7 +4,7 @@
public class mdToc {
public static void main(String[] args) {
- String path = "D:\\idea_project\\JavaTutorial\\docs\\java\\jvm\\temp";
+ String path = "D:\\idea_project\\JavaTutorial\\docs\\java-web\\temp";
AtxMarkdownToc.newInstance().genTocDir(path);
}
}
From 928058d55cc5f6bb6ed77dc7f6d8504d8c708d75 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=BB=84=E5=B0=8F=E6=96=9C?= <362294931@qq.com>
Date: Sat, 15 Apr 2023 11:48:55 +0800
Subject: [PATCH 08/39] add SpringBoot1
---
ReadMe.md | 32 +--
...15\344\270\226\344\273\212\347\224\237.md" | 246 ++++++++++++++++++
...37\347\220\206\350\257\246\350\247\243.md" | 0
...37\347\220\206\350\257\246\350\247\243.md" | 0
...4\232SpringAOP\346\246\202\350\277\260.md" | 0
...40\350\275\275\350\277\207\347\250\213.md" | 0
...13\345\212\241\346\246\202\350\277\260.md" | 0
...20\347\240\201\345\211\226\346\236\220.md" | 0
...\274\232Spring\346\246\202\350\277\260.md" | 0
...70\345\277\203\346\265\201\347\250\213.md" | 0
...07\347\250\213\345\210\206\346\236\220.md" | 0
...\243\347\241\256\347\232\204Controller.md" | 0
...67\346\261\202\350\275\254\345\217\221.md" | 0
...4\232SpringMVC\346\246\202\350\277\260.md" | 0
...43\346\236\220\345\216\237\347\220\206.md" | 0
...5\277\265\344\270\216DispatcherServlet.md" | 0
...6@ResponseBody\346\263\250\350\247\243.md" | 0
...45\350\257\206\346\270\205\345\215\225.md" | 0
18 files changed, 262 insertions(+), 16 deletions(-)
create mode 100644 "docs/spring/SpringBoot/SpringBoot\347\232\204\345\211\215\344\270\226\344\273\212\347\224\237.md"
rename "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232AOP\345\256\236\347\216\260\345\216\237\347\220\206\350\257\246\350\247\243.md" => "docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232AOP\345\256\236\347\216\260\345\216\237\347\220\206\350\257\246\350\247\243.md" (100%)
rename "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232JDK\345\222\214cglib\345\212\250\346\200\201\344\273\243\347\220\206\345\216\237\347\220\206\350\257\246\350\247\243.md" => "docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232JDK\345\222\214cglib\345\212\250\346\200\201\344\273\243\347\220\206\345\216\237\347\220\206\350\257\246\350\247\243.md" (100%)
rename "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232SpringAOP\346\246\202\350\277\260.md" => "docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232SpringAOP\346\246\202\350\277\260.md" (100%)
rename "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232SpringIOC\345\256\271\345\231\250\347\232\204\345\212\240\350\275\275\350\277\207\347\250\213.md" => "docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232SpringIOC\345\256\271\345\231\250\347\232\204\345\212\240\350\275\275\350\277\207\347\250\213.md" (100%)
rename "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232Spring\344\272\213\345\212\241\346\246\202\350\277\260.md" => "docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232Spring\344\272\213\345\212\241\346\246\202\350\277\260.md" (100%)
rename "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232Spring\344\272\213\345\212\241\346\272\220\347\240\201\345\211\226\346\236\220.md" => "docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232Spring\344\272\213\345\212\241\346\272\220\347\240\201\345\211\226\346\236\220.md" (100%)
rename "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232Spring\346\246\202\350\277\260.md" => "docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232Spring\346\246\202\350\277\260.md" (100%)
rename "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232\345\210\235\346\216\242SpringIOC\346\240\270\345\277\203\346\265\201\347\250\213.md" => "docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232\345\210\235\346\216\242SpringIOC\346\240\270\345\277\203\346\265\201\347\250\213.md" (100%)
rename "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232\346\207\222\345\212\240\350\275\275\347\232\204\345\215\225\344\276\213Bean\350\216\267\345\217\226\350\277\207\347\250\213\345\210\206\346\236\220.md" => "docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232\346\207\222\345\212\240\350\275\275\347\232\204\345\215\225\344\276\213Bean\350\216\267\345\217\226\350\277\207\347\250\213\345\210\206\346\236\220.md" (100%)
rename "docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232DispatcherServlet\345\246\202\344\275\225\346\211\276\345\210\260\346\255\243\347\241\256\347\232\204Controller.md" => "docs/spring/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232DispatcherServlet\345\246\202\344\275\225\346\211\276\345\210\260\346\255\243\347\241\256\347\232\204Controller.md" (100%)
rename "docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232DispatcherServlet\347\232\204\345\210\235\345\247\213\345\214\226\344\270\216\350\257\267\346\261\202\350\275\254\345\217\221.md" => "docs/spring/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232DispatcherServlet\347\232\204\345\210\235\345\247\213\345\214\226\344\270\216\350\257\267\346\261\202\350\275\254\345\217\221.md" (100%)
rename "docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\346\246\202\350\277\260.md" => "docs/spring/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\346\246\202\350\277\260.md" (100%)
rename "docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\347\232\204\350\247\206\345\233\276\350\247\243\346\236\220\345\216\237\347\220\206.md" => "docs/spring/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\347\232\204\350\247\206\345\233\276\350\247\243\346\236\220\345\216\237\347\220\206.md" (100%)
rename "docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\350\256\276\350\256\241\347\220\206\345\277\265\344\270\216DispatcherServlet.md" => "docs/spring/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\350\256\276\350\256\241\347\220\206\345\277\265\344\270\216DispatcherServlet.md" (100%)
rename "docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232\346\266\210\346\201\257\350\275\254\346\215\242\345\231\250HttpMessageConverter\344\270\216@ResponseBody\346\263\250\350\247\243.md" => "docs/spring/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232\346\266\210\346\201\257\350\275\254\346\215\242\345\231\250HttpMessageConverter\344\270\216@ResponseBody\346\263\250\350\247\243.md" (100%)
rename "docs/java-web/Spring/\347\273\231\344\275\240\344\270\200\344\273\275SpringBoot\347\237\245\350\257\206\346\270\205\345\215\225.md" => "docs/spring/\347\273\231\344\275\240\344\270\200\344\273\275SpringBoot\347\237\245\350\257\206\346\270\205\345\215\225.md" (100%)
diff --git a/ReadMe.md b/ReadMe.md
index dc53ae6..c83ee64 100644
--- a/ReadMe.md
+++ b/ReadMe.md
@@ -144,28 +144,28 @@
### Spring
-* [Spring源码剖析:Spring概述](docs/java-web/Spring/Spring源码剖析:Spring概述.md)
-* [Spring源码剖析:初探SpringIOC核心流程](docs/java-web/Spring/Spring源码剖析:初探SpringIOC核心流程.md)
-* [Spring源码剖析:SpringIOC容器的加载过程 ](docs/java-web/Spring/Spring源码剖析:SpringIOC容器的加载过程.md)
-* [Spring源码剖析:懒加载的单例Bean获取过程分析](docs/java-web/Spring/Spring源码剖析:懒加载的单例Bean获取过程分析.md)
-* [Spring源码剖析:JDK和cglib动态代理原理详解 ](docs/java-web/Spring/Spring源码剖析:JDK和cglib动态代理原理详解.md)
-* [Spring源码剖析:SpringAOP概述](docs/java-web/Spring/Spring源码剖析:SpringAOP概述.md)
-* [Spring源码剖析:AOP实现原理详解 ](docs/java-web/Spring/Spring源码剖析:AOP实现原理详解.md)
-* [Spring源码剖析:Spring事务概述](docs/java-web/Spring/Spring源码剖析:Spring事务概述.md)
-* [Spring源码剖析:Spring事务源码剖析](docs/java-web/Spring/Spring源码剖析:Spring事务源码剖析.md)
+* [Spring源码剖析:Spring概述](docs/spring/Spring源码剖析:Spring概述.md)
+* [Spring源码剖析:初探SpringIOC核心流程](docs/spring/Spring源码剖析:初探SpringIOC核心流程.md)
+* [Spring源码剖析:SpringIOC容器的加载过程 ](docs/spring/Spring源码剖析:SpringIOC容器的加载过程.md)
+* [Spring源码剖析:懒加载的单例Bean获取过程分析](docs/spring/Spring源码剖析:懒加载的单例Bean获取过程分析.md)
+* [Spring源码剖析:JDK和cglib动态代理原理详解 ](docs/spring/Spring源码剖析:JDK和cglib动态代理原理详解.md)
+* [Spring源码剖析:SpringAOP概述](docs/spring/Spring源码剖析:SpringAOP概述.md)
+* [Spring源码剖析:AOP实现原理详解 ](docs/spring/Spring源码剖析:AOP实现原理详解.md)
+* [Spring源码剖析:Spring事务概述](docs/spring/Spring源码剖析:Spring事务概述.md)
+* [Spring源码剖析:Spring事务源码剖析](docs/spring/Spring源码剖析:Spring事务源码剖析.md)
### SpringMVC
-* [SpringMVC源码分析:SpringMVC概述](docs/java-web/SpringMVC/SpringMVC源码分析:SpringMVC概述.md)
-* [SpringMVC源码分析:SpringMVC设计理念与DispatcherServlet](docs/java-web/SpringMVC/SpringMVC源码分析:SpringMVC设计理念与DispatcherServlet.md)
-* [SpringMVC源码分析:DispatcherServlet的初始化与请求转发 ](docs/java-web/SpringMVC/SpringMVC源码分析:DispatcherServlet的初始化与请求转发.md)
-* [SpringMVC源码分析:DispatcherServlet如何找到正确的Controller ](docs/java-web/SpringMVC/SpringMVC源码分析:DispatcherServlet如何找到正确的Controller.md)
-* [SpringMVC源码剖析:消息转换器HttpMessageConverter与@ResponseBody注解](docs/java-web/SpringMVC/SpringMVC源码剖析:消息转换器HttpMessageConverter与@ResponseBody注解.md)
-* [SpringMVC源码分析:SpringMVC的视图解析原理 ](docs/java-web/SpringMVC/SpringMVC源码分析:SpringMVC的视图解析原理.md)
+* [SpringMVC源码分析:SpringMVC概述](docs/spring/springMVC/SpringMVC源码分析:SpringMVC概述.md)
+* [SpringMVC源码分析:SpringMVC设计理念与DispatcherServlet](docs/spring/springMVC/SpringMVC源码分析:SpringMVC设计理念与DispatcherServlet.md)
+* [SpringMVC源码分析:DispatcherServlet的初始化与请求转发 ](docs/spring/springMVC/SpringMVC源码分析:DispatcherServlet的初始化与请求转发.md)
+* [SpringMVC源码分析:DispatcherServlet如何找到正确的Controller ](docs/spring/springMVC/SpringMVC源码分析:DispatcherServlet如何找到正确的Controller.md)
+* [SpringMVC源码剖析:消息转换器HttpMessageConverter与@ResponseBody注解](docs/spring/springMVC/SpringMVC源码剖析:消息转换器HttpMessageConverter与@ResponseBody注解.md)
+* [SpringMVC源码分析:SpringMVC的视图解析原理 ](docs/spring/springMVC/SpringMVC源码分析:SpringMVC的视图解析原理.md)
### SpringBoot
-todo
+* [SpringBoot系列:SpringBoot的前世今生](docs/spring/SpringBoot/SpringBoot的前世今生.md)
### SpringCloud
diff --git "a/docs/spring/SpringBoot/SpringBoot\347\232\204\345\211\215\344\270\226\344\273\212\347\224\237.md" "b/docs/spring/SpringBoot/SpringBoot\347\232\204\345\211\215\344\270\226\344\273\212\347\224\237.md"
new file mode 100644
index 0000000..c524bd5
--- /dev/null
+++ "b/docs/spring/SpringBoot/SpringBoot\347\232\204\345\211\215\344\270\226\344\273\212\347\224\237.md"
@@ -0,0 +1,246 @@
+# SpringBootǰ
+
+Spring Boot 2.0 Ƴּһѧϰ Spring Boot ȣ͵Ҹ˵IJ͵ķӾͿԸܵҶѧϰ Spring Boot 飬ôôѧϰ Spring Boot ֮ʱԼҲ˼ Spring Boot ıʲôSpring ҵǻʲôĿǴ Spring Boot? ͳҵʹ Spring Boot Ǵʲô?
+
+Щ⣬һ˽ Spring Boot ʲô?
+
+## Spring ʷ
+
+˵ Spring Boot Dzò˽һ Spring ҵΪ Spring Boot Դ Spirng 壬 Spring Boot ĵ Sping ܵķչϢϢء
+
+ʱص2002꣬ʱ Java EE EJB ʱ֪ܶ˾Dzô˼ĿʱһСΪ EJB ̫ӷףеĿҪʹ EJB ִͿܣӦûһָõķ⡣
+
+Ϊ֤뷨ȷģ200210дһ顶 Expert One-on-One J2EE ˵ʱ Java ҵӦóָ Java EE EJB дڵһЩҪȱݡⱾУһͨ Java עĸĽ
+
+Уչʾڲʹ EJB ¹չλԤϵͳΪ˹Ӧóд˳ 30,000 еĻṹ룬ĿеĸΪ com.interface21ԴΪ interface21Ҳ Spring ǰ
+
+˭أǴ Rod Johnson ͼ, Rod Johnson Ϥѧ˼ѧλͬʱѧλ˳Ծڻص֮ǰѧIJʿѧλ Rod Johnson Ѿ뿪 Spring ΪһʹͶˣͬʱҲǶ˾Ķ£۷塣
+
+
+
+Ȿ鷢һһ J2EE ƺͿһڶ졣ⱾṩĴֻܹ붼Ǹ߶ȿõġ 2003 Rod Johnson ͬڴ˿ܵĻϿһȫµĿΪ Spring , Rod Johnson Spring Ǵͳ J2EE µĿʼ Spring չ쳵
+
+* 2004 03 £1.0 淢
+* 2006 10 £2.0 淢
+* 2007 11 ¸Ϊ SpringSourceͬʱ Spring 2.5
+* 2009 12 £Spring 3.0
+* 2013 12 £Pivotal Spring 4.0
+* 2017 09 £Spring 5.0
+
+## Spring Boot ĵ
+
+ʹ Spring пĸ˺ҵԽԽ࣬Spring ҲһһСܱһȫĿԴSpring ı߽粻ϵĽ䣬˺ Spring κˣĿԴм Spring Ӧ֧֣ Spring ֱ֮ҲһЩ⡣
+
+Spring ÿһԴҪһЩãǿĿԽԽӴҪɺܶԴ˺ʹ Spirng ĿҪܶļ̫÷dz⣬ó˺ Spring Ϊõ
+
+Spring ƺҲʶЩ⣬ôһԽЩ⣬ʱĸҲ𣬿ٿСӦñøΪȣSpring պôôһϣ 2013 ʼ Spring Boot Ŀз20144£Spring Boot 1.0.0
+
+Spring Boot ֮ܵԴijע½һЩ˺ҵʹ Spring BootѸϲԴֱ2016꣬ڹ Spring Boot űʹڼܶо Spring Boot Ŀд˴ Spring Boot £ͬʱһЩ˾ҵڲСģʹãʹþ˳2016굽2018꣬ʹ Spring Boot ҵ˿ԽԽ࣬Ǵ Spring Boot ؼֵİٶָͿԿ
+
+
+
+ͼΪ2014굽2018 Spring Boot İٶָԿ Spring Boot 2.0 Ƴ߷塣
+
+Ȼ Spring Boot Ϊȡ Spring ,Spring Boot Spring ΪǸʹ Spring Spring Boot гӦSpring ٷҲdz Spring Boot ĺչѾ Spring Boot Ϊ˾Ŀƹ㣬ŵ˹ϵһλã˺ Spring Boot ijչҲá
+
+#
+
+
+
+springspringbootĻ
+
+Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can "just run".
+
+We take an opinionated view of the Spring platform and third-party libraries so you can get started with minimum fuss. Most Spring Boot applications need minimal Spring configuration.
+
+֮ڸǣspringbootǿٹӦ
+
+ֻҪһ@SpringBootApplication עӦڣɱʶΪһspringbootӦ
+
+ңspringboot̳˴ĵ⣬ǽȫҪãͿԽӦôΪspringbootܱѾú˴Ĭá
+
+#
+
+Features
+
+* Create stand-alone Spring applications
+* Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files)
+* Provide opinionated 'starter' dependencies to simplify your build configuration
+* Automatically configure Spring and 3rd party libraries whenever possible
+* Provide production-ready features such as metrics, health checks, and externalized configuration
+* Absolutely no code generation and no requirement for XML configuration
+
+ٷspringbootԵ
+
+1һspringӦãڶһwebӦ
+
+2õtomcatҲҪspringӦôwarֻҪjarвɡ
+
+3ṩstarterӼspringboot̬еã統ʹspringwebʱDzҪӶspringmvcصmavenֱspring-boot-starter-webͿˣstarterԶصҰ汾ţؼŻmaven
+
+4Զװspring͵⣬ҪָͨעļԶװ䣬һһЩǻԼԶװƣǽʡĶãҲԶװⲿjarṩspringbeaná
+
+5ṩصԣءָ㡢ȹܣspringbootṩǿ̬ﲻspringbootԼҲһЩⲿ̬
+
+6ڴɣҲҪxmlļ֤springbootĿȣԼüļǽҪapplication.propertiesлòҲspringbootҵ̬ɵĶclassļ
+
+# SpringĹϵ
+
+
+
+## SpringFrameworkʲô⣿
+
+SpringJavaҵ棨Java Enterprise EditionJEEҲJ2EEƷ迪EnterpriseJavaBeanEJBSpringΪҵJavaṩһԼķͨע̣üJavaPlain Old Java ObjectPOJOʵEJBĹܡ
+
+1.ʹSpringIOC,֮ϵSpring,֮,ǸרעӦ
+
+2.ṩڶ,,WSȡ
+
+3.ܺõ֧AOP,̡
+
+4.Ŀṩ˺ܺõļ֧,Hibernate,Struts2,JPA
+
+5.Spring DIƽҵ滻ĸԡ
+
+6.Springڵ,Ⱦ͡
+
+7.Springĸ߶ȿɿ,ǿSpring,߿ѡSpringֻȫ
+
+## SpringFrameworkûнʲô⣿
+
+ȻSpringģȴġһʼSpringXMLãǺܶXMLáSpring 2.5˻עɨ裬˴ӦóʽXMLáSpring 3.0˻JavaãһͰȫĿع÷ʽԴXML
+
+Щö˿ʱġΪ˼Springúͽҵ֮Ҫ˼άлԱдüռ˱дӦóʱ䡣пһSpringʵãͬʱҪĻرҲ١
+
+֮⣬ĿҲһʱ顣ڻʱҪҪЩ꣬һҪ֮ϵ꣬һѡİ汾֮IJͻ谭ĿĿȡ
+
+## SpringBootSpringȱ
+
+SpringBootSpringȱеĸƺŻԼõ˼룬ÿԱҵ֮˼άлȫĵͶ뵽ҵĴдУӶ˿Чʣһ̶Ŀڡ
+
+ʹSpringܽпĹУҪúܶSpringܰspring-corespring-beanspring-contextȣЩͨظӵģҪܶʹüظã翪ע⡢־ȡSpring BootЩҪIJṩĬãȻЩĬǿĵģٴSpringӦ
+
+# SpringMVCĹϵ
+
+
+
+Spring BootSpring BootʹͿʼSpringӦóס ˺ܶ롣 Ļ˺ܶิԣ˿ԱԿֲɿSpringӦó
+
+Spring MVCSpring MVCڹWebӦóWeb MVCܡ ڸֹܵļ һHTTPWebӦóܡ
+
+
+
+Spring BootSpring MVCڲͬĿĶڡ Spring BootSpring MVC֮Ҫ
+
+
+
+| Spring Boot | Spring MVC |
+| --- | --- |
+| Spring BootʹúĬֵSpringӦó | Spring MVCSpring»ģͼWebܡ |
+| ṩĬSpringֵ֧Ŀܡ | ṩڹWebӦóļܡ |
+| ֶá | Ҫֶйá |
+| Ҫ | DZġ |
+| 룬װһԪС | ֱָÿ |
+| ˿ʱ䲢ʡ | ʵͬĿҪʱ䡣 |
+
+# SpringCloudĹϵ
+
+Spring BootSpringijԱһȫµĿܣĿǾܼͿٵĿSpringӦóáΪ߿ݵʹSpringؿṩ˱ĿܣֻΪܵʹҲṩ˺ܺõĽּܡ
+
+
+
+
+ͼߵĻspringbootڹӦãҲdz˵
+
+springcloudڷҲǴЭspringbootӦó
+
+springcloudаڶصAPISpringcloud GatewayConfig Serever·Circuit BreakerעService RegisttySleuth
+
+# ʹSpringboot8ԭ
+
+## Ŀ
+
+Spring Boot Spring ̬ϵͳ˺ִܶĬá ڿԱòͶ뿪
+
+磬Spring MVC ͨ XML bean Զ servlet ʵ֡ ʹ Spring Bootһ ԲҪ XML á
+
+## һнȻ
+
+Spring Boot Starters ǰǵһЩԶõ Maven ңЩΪ Spring Boot Ӧóṩܡ Ҫݿӣ һ Ϣͨ͵ʼ Spring Boot һС
+
+ڼе Spring ģ飬һΪݡ һЩҲͨǵģṩ Spring ֧֡ ûЩΪԱòά XML á Ӧʹ Spring Boot һԭ
+
+## Ƕʽ
+
+Spring Boot ΪǶʽ TomcatJetty Undertow ṩ伴õ֧֡ ԱͲصڴͳӦ÷в Web Ӧó ͨʵԽһַ ʵյõһκ JAR һе JAR ļ ʱJAR 㹻ĿΪӦó
+
+ǶʽȤʱ Spring Boot Ӧó JAR תΪ WARDzͳ
+
+## IDE Spring Boot ֧
+
+Ҫ IDE ṩ Spring Boot ֧֡ 磬IntelliJ IDEA Ultimate Ϊ Spring Boot Ŀṩ˳ɫĴɺ͵ܡ֮⣬VSCode Eclipse Ҳṩ˷ḻĹ֧֡
+
+## ù
+
+Spring Boot ṩԣءָͿ伴õע ЩԣԱԱá 磬ִ˵ȹʹӦó״̬سΪܡ 磬
+
+ Prometheus ĹռӦóָ
+
+ Kubernetes Openshift ʹþԺͻԾȽ˵㡣
+
+ֻԻͨ /actuator/logging ˵㼴ɸ־¼
+
+⣬ԱʹԼԶ彡˵Щִ˵㡣
+
+## 伴õ JUnit ֧
+
+Ĭ£ Spring Boot Ŀ JUnit 5 ⣬Spring Boot ṩ@SpringBootTest עҪʱʼġ ԿԱֻҪд DzٵIJĸ spring ġ
+
+磬ԶɵIJԽǷȷء
+
+````
+@SpringBootTest
+class SpringBootDerbyDatabaseApplicationTests {
+
+ @
+ void contextLoads() {
+ }
+
+}
+````
+
+## Spring Profiles
+
+Spring Profiles spring Boot һǿԣڸӦóеIJͬ ʹļضû ضʹòͬʱܻó
+````
+@Profile(value = {"prod","uat"})
+class RabbitMQConfig {
+
+//
+
+}
+````
+
+ĴУĽھ prod uat ΪļĻС
+
+## ִͲѡ
+
+ÿṩ˶ַʽӦó ֮ǰ˵Ӧó JAR WAR ļ ͨһЩúͲԴ伴õĸ docker
+
+ֹͣ Spring Boot Ӧódz ⣬ͨIJ轫Щ JAR ļΪ linux JAR ļΪ FAT jarǰӦóص ʹò̲ôӡ ʵϣЩκװ Java 8 ߰汾ĻС
+
+# ο
+
+[https://spring.io/](https://spring.io/)
+
+[https://pdai.tech/md/spring/springboot/springboot-x-overview.html](https://pdai.tech/md/spring/springboot/springboot-x-overview.html)
+
+[https://springhow.com/why-use-spring-boot/](https://springhow.com/why-use-spring-boot/)
+
+[https://dzone.com/articles/why-springboot](https://dzone.com/articles/why-springboot)
+
+[https://scand.com/company/blog/pros-and-cons-of-using-spring-boot/](https://scand.com/company/blog/pros-and-cons-of-using-spring-boot/)
+
+[https://cloud.tencent.com/developer/article/1620255](https://cloud.tencent.com/developer/article/1620255)
+
+[https://www.yiibai.com/spring-boot/spring-vs-spring-boot-vs-spring-mvc.html](https://www.yiibai.com/spring-boot/spring-vs-spring-boot-vs-spring-mvc.html)
\ No newline at end of file
diff --git "a/docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232AOP\345\256\236\347\216\260\345\216\237\347\220\206\350\257\246\350\247\243.md" "b/docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232AOP\345\256\236\347\216\260\345\216\237\347\220\206\350\257\246\350\247\243.md"
similarity index 100%
rename from "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232AOP\345\256\236\347\216\260\345\216\237\347\220\206\350\257\246\350\247\243.md"
rename to "docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232AOP\345\256\236\347\216\260\345\216\237\347\220\206\350\257\246\350\247\243.md"
diff --git "a/docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232JDK\345\222\214cglib\345\212\250\346\200\201\344\273\243\347\220\206\345\216\237\347\220\206\350\257\246\350\247\243.md" "b/docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232JDK\345\222\214cglib\345\212\250\346\200\201\344\273\243\347\220\206\345\216\237\347\220\206\350\257\246\350\247\243.md"
similarity index 100%
rename from "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232JDK\345\222\214cglib\345\212\250\346\200\201\344\273\243\347\220\206\345\216\237\347\220\206\350\257\246\350\247\243.md"
rename to "docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232JDK\345\222\214cglib\345\212\250\346\200\201\344\273\243\347\220\206\345\216\237\347\220\206\350\257\246\350\247\243.md"
diff --git "a/docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232SpringAOP\346\246\202\350\277\260.md" "b/docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232SpringAOP\346\246\202\350\277\260.md"
similarity index 100%
rename from "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232SpringAOP\346\246\202\350\277\260.md"
rename to "docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232SpringAOP\346\246\202\350\277\260.md"
diff --git "a/docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232SpringIOC\345\256\271\345\231\250\347\232\204\345\212\240\350\275\275\350\277\207\347\250\213.md" "b/docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232SpringIOC\345\256\271\345\231\250\347\232\204\345\212\240\350\275\275\350\277\207\347\250\213.md"
similarity index 100%
rename from "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232SpringIOC\345\256\271\345\231\250\347\232\204\345\212\240\350\275\275\350\277\207\347\250\213.md"
rename to "docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232SpringIOC\345\256\271\345\231\250\347\232\204\345\212\240\350\275\275\350\277\207\347\250\213.md"
diff --git "a/docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232Spring\344\272\213\345\212\241\346\246\202\350\277\260.md" "b/docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232Spring\344\272\213\345\212\241\346\246\202\350\277\260.md"
similarity index 100%
rename from "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232Spring\344\272\213\345\212\241\346\246\202\350\277\260.md"
rename to "docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232Spring\344\272\213\345\212\241\346\246\202\350\277\260.md"
diff --git "a/docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232Spring\344\272\213\345\212\241\346\272\220\347\240\201\345\211\226\346\236\220.md" "b/docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232Spring\344\272\213\345\212\241\346\272\220\347\240\201\345\211\226\346\236\220.md"
similarity index 100%
rename from "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232Spring\344\272\213\345\212\241\346\272\220\347\240\201\345\211\226\346\236\220.md"
rename to "docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232Spring\344\272\213\345\212\241\346\272\220\347\240\201\345\211\226\346\236\220.md"
diff --git "a/docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232Spring\346\246\202\350\277\260.md" "b/docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232Spring\346\246\202\350\277\260.md"
similarity index 100%
rename from "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232Spring\346\246\202\350\277\260.md"
rename to "docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232Spring\346\246\202\350\277\260.md"
diff --git "a/docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232\345\210\235\346\216\242SpringIOC\346\240\270\345\277\203\346\265\201\347\250\213.md" "b/docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232\345\210\235\346\216\242SpringIOC\346\240\270\345\277\203\346\265\201\347\250\213.md"
similarity index 100%
rename from "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232\345\210\235\346\216\242SpringIOC\346\240\270\345\277\203\346\265\201\347\250\213.md"
rename to "docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232\345\210\235\346\216\242SpringIOC\346\240\270\345\277\203\346\265\201\347\250\213.md"
diff --git "a/docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232\346\207\222\345\212\240\350\275\275\347\232\204\345\215\225\344\276\213Bean\350\216\267\345\217\226\350\277\207\347\250\213\345\210\206\346\236\220.md" "b/docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232\346\207\222\345\212\240\350\275\275\347\232\204\345\215\225\344\276\213Bean\350\216\267\345\217\226\350\277\207\347\250\213\345\210\206\346\236\220.md"
similarity index 100%
rename from "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232\346\207\222\345\212\240\350\275\275\347\232\204\345\215\225\344\276\213Bean\350\216\267\345\217\226\350\277\207\347\250\213\345\210\206\346\236\220.md"
rename to "docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232\346\207\222\345\212\240\350\275\275\347\232\204\345\215\225\344\276\213Bean\350\216\267\345\217\226\350\277\207\347\250\213\345\210\206\346\236\220.md"
diff --git "a/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232DispatcherServlet\345\246\202\344\275\225\346\211\276\345\210\260\346\255\243\347\241\256\347\232\204Controller.md" "b/docs/spring/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232DispatcherServlet\345\246\202\344\275\225\346\211\276\345\210\260\346\255\243\347\241\256\347\232\204Controller.md"
similarity index 100%
rename from "docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232DispatcherServlet\345\246\202\344\275\225\346\211\276\345\210\260\346\255\243\347\241\256\347\232\204Controller.md"
rename to "docs/spring/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232DispatcherServlet\345\246\202\344\275\225\346\211\276\345\210\260\346\255\243\347\241\256\347\232\204Controller.md"
diff --git "a/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232DispatcherServlet\347\232\204\345\210\235\345\247\213\345\214\226\344\270\216\350\257\267\346\261\202\350\275\254\345\217\221.md" "b/docs/spring/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232DispatcherServlet\347\232\204\345\210\235\345\247\213\345\214\226\344\270\216\350\257\267\346\261\202\350\275\254\345\217\221.md"
similarity index 100%
rename from "docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232DispatcherServlet\347\232\204\345\210\235\345\247\213\345\214\226\344\270\216\350\257\267\346\261\202\350\275\254\345\217\221.md"
rename to "docs/spring/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232DispatcherServlet\347\232\204\345\210\235\345\247\213\345\214\226\344\270\216\350\257\267\346\261\202\350\275\254\345\217\221.md"
diff --git "a/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\346\246\202\350\277\260.md" "b/docs/spring/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\346\246\202\350\277\260.md"
similarity index 100%
rename from "docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\346\246\202\350\277\260.md"
rename to "docs/spring/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\346\246\202\350\277\260.md"
diff --git "a/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\347\232\204\350\247\206\345\233\276\350\247\243\346\236\220\345\216\237\347\220\206.md" "b/docs/spring/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\347\232\204\350\247\206\345\233\276\350\247\243\346\236\220\345\216\237\347\220\206.md"
similarity index 100%
rename from "docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\347\232\204\350\247\206\345\233\276\350\247\243\346\236\220\345\216\237\347\220\206.md"
rename to "docs/spring/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\347\232\204\350\247\206\345\233\276\350\247\243\346\236\220\345\216\237\347\220\206.md"
diff --git "a/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\350\256\276\350\256\241\347\220\206\345\277\265\344\270\216DispatcherServlet.md" "b/docs/spring/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\350\256\276\350\256\241\347\220\206\345\277\265\344\270\216DispatcherServlet.md"
similarity index 100%
rename from "docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\350\256\276\350\256\241\347\220\206\345\277\265\344\270\216DispatcherServlet.md"
rename to "docs/spring/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\350\256\276\350\256\241\347\220\206\345\277\265\344\270\216DispatcherServlet.md"
diff --git "a/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232\346\266\210\346\201\257\350\275\254\346\215\242\345\231\250HttpMessageConverter\344\270\216@ResponseBody\346\263\250\350\247\243.md" "b/docs/spring/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232\346\266\210\346\201\257\350\275\254\346\215\242\345\231\250HttpMessageConverter\344\270\216@ResponseBody\346\263\250\350\247\243.md"
similarity index 100%
rename from "docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232\346\266\210\346\201\257\350\275\254\346\215\242\345\231\250HttpMessageConverter\344\270\216@ResponseBody\346\263\250\350\247\243.md"
rename to "docs/spring/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232\346\266\210\346\201\257\350\275\254\346\215\242\345\231\250HttpMessageConverter\344\270\216@ResponseBody\346\263\250\350\247\243.md"
diff --git "a/docs/java-web/Spring/\347\273\231\344\275\240\344\270\200\344\273\275SpringBoot\347\237\245\350\257\206\346\270\205\345\215\225.md" "b/docs/spring/\347\273\231\344\275\240\344\270\200\344\273\275SpringBoot\347\237\245\350\257\206\346\270\205\345\215\225.md"
similarity index 100%
rename from "docs/java-web/Spring/\347\273\231\344\275\240\344\270\200\344\273\275SpringBoot\347\237\245\350\257\206\346\270\205\345\215\225.md"
rename to "docs/spring/\347\273\231\344\275\240\344\270\200\344\273\275SpringBoot\347\237\245\350\257\206\346\270\205\345\215\225.md"
From 525265639ede5463e64125a6f82ababf1c609ef1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=BB=84=E5=B0=8F=E6=96=9C?= <362294931@qq.com>
Date: Sat, 15 Apr 2023 22:19:42 +0800
Subject: [PATCH 09/39] add spring content
---
ReadMe.md | 4 +
...65\344\270\216\344\275\234\347\224\250.md" | 621 +++++++++
...10\346\240\270\345\277\203\357\274\211.md" | 182 +++
...70\350\247\201\346\263\250\350\247\243.md" | 158 +++
...72\346\234\254\344\275\277\347\224\250.md" | 152 +++
...45\220\253Spring+SpringMVC+SpringBoot).md" | 1112 ++++++++++++++++
...23\347\232\204\350\256\277\351\227\256.md" | 1183 +++++++++++++++++
...75\347\232\204\346\224\257\346\214\201.md" | 715 ++++++++++
...57\345\242\203\345\217\230\351\207\217.md" | 852 ++++++++++++
...04\347\220\206\346\234\272\345\210\266.md" | 270 ++++
...04\346\272\220\347\256\241\347\220\206.md" | 309 +++++
...54\346\225\260\346\215\256\357\274\211.md" | 298 +++++
...72\346\234\254\347\224\250\346\263\225.md" | 430 ++++++
.../spring/Spring\345\220\210\351\233\206.md" | 22 +
...345\256\271\345\231\250\344\270\216IOC.md" | 157 +++
...70\350\247\201\346\263\250\350\247\243.md" | 724 ++++++++++
.../spring/Spring\346\246\202\350\277\260.md" | 145 ++
...70\350\247\201\346\263\250\350\247\243.md" | 232 ++++
...\270\252Spring\345\272\224\347\224\250.md" | 70 +
pom.xml | 28 +
src/main/java/Test.java | 22 +
21 files changed, 7686 insertions(+)
create mode 100644 "docs/spring/SpringAOP\347\232\204\346\246\202\345\277\265\344\270\216\344\275\234\347\224\250.md"
create mode 100644 "docs/spring/SpringBean\347\232\204\345\256\232\344\271\211\344\270\216\347\256\241\347\220\206\357\274\210\346\240\270\345\277\203\357\274\211.md"
create mode 100644 "docs/spring/SpringBoot/SpringBoot\345\270\270\350\247\201\346\263\250\350\247\243.md"
create mode 100644 "docs/spring/SpringBoot/SpringBoot\347\232\204\345\237\272\346\234\254\344\275\277\347\224\250.md"
create mode 100644 "docs/spring/SpringBoot/Spring\345\270\270\350\247\201\346\263\250\350\247\243\344\275\277\347\224\250\346\214\207\345\215\227(\345\214\205\345\220\253Spring+SpringMVC+SpringBoot).md"
create mode 100644 "docs/spring/Spring\344\270\255\345\257\271\344\272\216\346\225\260\346\215\256\345\272\223\347\232\204\350\256\277\351\227\256.md"
create mode 100644 "docs/spring/Spring\344\270\255\345\257\271\344\272\216\346\240\241\351\252\214\345\212\237\350\203\275\347\232\204\346\224\257\346\214\201.md"
create mode 100644 "docs/spring/Spring\344\270\255\347\232\204Environment\347\216\257\345\242\203\345\217\230\351\207\217.md"
create mode 100644 "docs/spring/Spring\344\270\255\347\232\204\344\272\213\344\273\266\345\244\204\347\220\206\346\234\272\345\210\266.md"
create mode 100644 "docs/spring/Spring\344\270\255\347\232\204\350\265\204\346\272\220\347\256\241\347\220\206.md"
create mode 100644 "docs/spring/Spring\344\270\255\347\232\204\351\205\215\347\275\256\345\205\203\346\225\260\346\215\256\357\274\210\347\256\241\347\220\206\351\205\215\347\275\256\347\232\204\345\237\272\346\234\254\346\225\260\346\215\256\357\274\211.md"
create mode 100644 "docs/spring/Spring\344\272\213\345\212\241\345\237\272\346\234\254\347\224\250\346\263\225.md"
create mode 100644 "docs/spring/Spring\345\220\210\351\233\206.md"
create mode 100644 "docs/spring/Spring\345\256\271\345\231\250\344\270\216IOC.md"
create mode 100644 "docs/spring/Spring\345\270\270\350\247\201\346\263\250\350\247\243.md"
create mode 100644 "docs/spring/Spring\346\246\202\350\277\260.md"
create mode 100644 "docs/spring/springMVC/SpringMVC\345\270\270\350\247\201\346\263\250\350\247\243.md"
create mode 100644 "docs/spring/\347\254\254\344\270\200\344\270\252Spring\345\272\224\347\224\250.md"
create mode 100644 src/main/java/Test.java
diff --git a/ReadMe.md b/ReadMe.md
index c83ee64..c8ec78e 100644
--- a/ReadMe.md
+++ b/ReadMe.md
@@ -144,6 +144,10 @@
### Spring
+* [Spring常见注解.md](docs/spring/Spring常见注解.md)
+
+
+
* [Spring源码剖析:Spring概述](docs/spring/Spring源码剖析:Spring概述.md)
* [Spring源码剖析:初探SpringIOC核心流程](docs/spring/Spring源码剖析:初探SpringIOC核心流程.md)
* [Spring源码剖析:SpringIOC容器的加载过程 ](docs/spring/Spring源码剖析:SpringIOC容器的加载过程.md)
diff --git "a/docs/spring/SpringAOP\347\232\204\346\246\202\345\277\265\344\270\216\344\275\234\347\224\250.md" "b/docs/spring/SpringAOP\347\232\204\346\246\202\345\277\265\344\270\216\344\275\234\347\224\250.md"
new file mode 100644
index 0000000..26e828a
--- /dev/null
+++ "b/docs/spring/SpringAOP\347\232\204\346\246\202\345\277\265\344\270\216\344\275\234\347\224\250.md"
@@ -0,0 +1,621 @@
+# Spring ܵ AOP
+
+## Spring ܵ AOP
+
+Spring ܵһؼ**ı**(AOP)ܡıҪѳֽɲͬIJֳΪνĹע㡣һӦóĶĹܱΪ**йע**Щйעڸ϶Ӧóҵиָĺܺõӣ־¼ơʽȫԺͻȡ
+
+ OOP УؼԪģ࣬ AOP еԪģ档עӦóϣAOP ӰĶжԺйעAOP DZԵĴ Perl.NETJava ԡ
+
+Spring AOP ģṩһӦó磬ִһʱڷִ֮ǰ֮ӶĹܡ
+
+## AOP
+
+ǿʼʹ AOP ֮ǰϤһ AOP Щﲢض Spring AOP йصġ
+
+| | |
+| --- | --- |
+| Aspect | һģһṩ APIs磬һ־ģΪ˼¼־ AOP áӦóӵķ棬ȡ |
+| Join point | Ӧóһ㣬ڲ AOP 档Ҳ˵ʵʵӦóУһʹ Spring AOP ܡ |
+| Advice | ʵж֮ǰִ֮еķڳִڼͨ Spring AOP ʵʱõĴ롣 |
+| Pointcut | һһӵ㣬֪ͨӦñִСʹñʽģʽָǽ AOP пġ |
+| Introduction | ·ԵеС |
+| Target object | һ߶֪ͨĶԶһҲΪ֪ͨ |
+| Weaving | Weaving ѷӵӦóͻ߶ϣһ֪ͨĶЩڱʱʱʱɡ |
+
+## ֪ͨ
+
+Spring ʹᵽ֪ͨ
+
+| ֪ͨ | |
+| --- | --- |
+| ǰ֪ͨ | һִ֮ǰִ֪ͨ |
+| ֪ͨ | һִִ֪֮ͨ |
+| غ֪ͨ | һִֻ֮ڷɹʱִ֪ͨ |
+| ׳쳣֪ͨ | һִֻ֮ڷ˳׳쳣ʱִ֪ͨ |
+| ֪ͨ | ڽ鷽֮ǰִ֪֮ͨ |
+
+## ʵԶ巽
+
+Spring ֧ **@AspectJ annotation style** ķ**ģʽ**ķʵԶ巽档ַѾӽڽϸ͡
+
+| | |
+| --- | --- |
+| [XML Schema based](https://www.w3cschool.cn/wkspring/omps1mm6.html) | ʹóԼõ XML ʵֵġ |
+| [@AspectJ based](https://www.w3cschool.cn/wkspring/k4q21mm8.html) | @AspectJ һķΪ Java 5 ע͵ij Java ע͡ |
+
+
+
+## Spring л AOP XMLܹ
+
+Ϊڱڵʹ aop ռǩҪ spring-aop ܹ
+
+```
+
+
+
+
+
+
+
+```
+
+㻹ҪӦó CLASSPATH ʹ AspectJ ļЩļһ AspectJ װõ lib Ŀ¼ǿõģ Internet ǡ(עaspectjweaver.jar Ѱ)
+
+* aspectjrt.jar
+
+* aspectjweaver.jar
+
+* aspectj.jar
+
+* aopalliance.jar
+
+## һ aspect
+
+һ **aspect** ʹ Ԫģֵ֧ bean ʹ **ref** õģʾ
+
+```
+
+
+ ...
+
+
+
+...
+
+```
+
+aBean úע룬ǰ½㿴 Spring bean һ
+
+## һ
+
+һ****ȷʹòִͬеĸȤӵ㣨ڴõ XML ܹʱ㽫ᰴʾ壺
+
+```
+
+
+
+ ...
+
+
+
+...
+
+```
+
+ʾһΪ businessService 㣬㽫 com.tutorialspoint µ Student е getName() ƥ䣺
+
+```
+
+
+
+ ...
+
+
+
+...
+
+```
+
+##
+
+ʹԪ͵֪ͨ£
+
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ...
+
+
+
+...
+
+```
+
+ԶԲͬĽʹͬ **doRequiredTask** ߲ͬķЩΪ aspect ģһ塣
+
+## AOP XML ܹʾ
+
+ΪᵽĻ AOP XML ܹĸDZдһʾʵּ顣Ϊǵʾʹü飬ʹ Eclipse IDE ڹ״̬Ȼ²贴һ Spring Ӧó
+
+| | |
+| --- | --- |
+| 1 | һΪ _SpringExample_ ĿĿ **src** ļ´һΪ _com.tutorialspoint_ İ |
+| 2 | ʹ _Add External JARs_ ѡ Spring ļ _Spring Hello World Example_ ½н͵ |
+| 3 | Ŀ Spring AOP ָĿļ **aspectjrt.jar aspectjweaver.jar** **aspectj.jar** |
+| 4 | _com.tutorialspoint_ ´ Java **Logging** _Student_ _MainApp_ |
+| 5 | **src** ļ´ Beans ļ _Beans.xml_ |
+| 6 | һǴ Java ļ Bean ļݣҰ½͵Ӧó |
+
+ **Logging.java** ļݡʵ aspect ģһʾڸõķ
+
+```
+package com.tutorialspoint;
+public class Logging {
+ /**
+ * This is the method which I would like to execute
+ * before a selected method execution.
+ */
+ public void beforeAdvice(){
+ System.out.println("Going to setup student profile.");
+ }
+ /**
+ * This is the method which I would like to execute
+ * after a selected method execution.
+ */
+ public void afterAdvice(){
+ System.out.println("Student profile has been setup.");
+ }
+ /**
+ * This is the method which I would like to execute
+ * when any method returns.
+ */
+ public void afterReturningAdvice(Object retVal){
+ System.out.println("Returning:" + retVal.toString() );
+ }
+ /**
+ * This is the method which I would like to execute
+ * if there is an exception raised.
+ */
+ public void AfterThrowingAdvice(IllegalArgumentException ex){
+ System.out.println("There has been an exception: " + ex.toString());
+ }
+}
+```
+
+ **Student.java** ļݣ
+
+```
+package com.tutorialspoint;
+public class Student {
+ private Integer age;
+ private String name;
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+ public Integer getAge() {
+ System.out.println("Age : " + age );
+ return age;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+ public String getName() {
+ System.out.println("Name : " + name );
+ return name;
+ }
+ public void printThrowException(){
+ System.out.println("Exception raised");
+ throw new IllegalArgumentException();
+ }
+}
+```
+
+ **MainApp.java** ļݣ
+
+```
+package com.tutorialspoint;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+public class MainApp {
+ public static void main(String[] args) {
+ ApplicationContext context =
+ new ClassPathXmlApplicationContext("Beans.xml");
+ Student student = (Student) context.getBean("student");
+ student.getName();
+ student.getAge();
+ student.printThrowException();
+ }
+}
+```
+
+ļ **Beans.xml**
+
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+һѾɵĴԴļ bean ļһӦóӦóһжĻ⽫Ϣ
+
+```
+Going to setup student profile.
+Name : Zara
+Student profile has been setup.
+Returning:Zara
+Going to setup student profile.
+Age : 11
+Student profile has been setup.
+Returning:11
+Going to setup student profile.
+Exception raised
+Student profile has been setup.
+There has been an exception: java.lang.IllegalArgumentException
+.....
+other exception content
+```
+
+һ涨 com.tutorialspoint ѡз Ǽһ£Ҫһķ֮ǰִ֮Ľ飬ͨ滻ʹʵͷƵ㶨еǺţ*ִС
+
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+ҪִͨЩ֮ʾӦó⽫Ϣ
+
+```
+Going to setup student profile.
+Name : Zara
+Student profile has been setup.
+Age : 11
+Exception raised
+.....
+other exception content
+```
+
+
+
+## Spring л AOP @AspectJ
+
+@AspectJ Ϊͨ Java 5 עע͵ͨ Java ָ࣬ aspects һַͨĻڼܹ XML ļаԪأ@AspectJ ֧ǿõġ
+
+```
+
+```
+
+㻹ҪӦó CLASSPATH ʹ AspectJ ļЩļһ AspectJ װõ lib Ŀ¼ǿõģûУ Internet ǡ
+
+* aspectjrt.jar
+
+* aspectjweaver.jar
+
+* aspectj.jar
+
+* aopalliance.jar
+
+## һ aspect
+
+Aspects κ bean һǽ @AspectJ ע֮⣬һзֶΣʾ
+
+```
+package org.xyz;
+import org.aspectj.lang.annotation.Aspect;
+@Aspect
+public class AspectModule {
+}
+```
+
+ǽ XML а½ãͺκ bean һ
+
+```
+
+
+
+
+```
+
+## һ
+
+һ****ȷʹòִͬеĸȤӵ㣨ڴõ XML ܹʱ֣
+
+* һʽǸȤĸִС
+
+* һǩһƺIJDzɵģʵӦǿյġ
+
+ʾжһΪ businessService 㣬㽫 com.xyz.myapp.service µпõÿһƥ䣺
+
+```
+import org.aspectj.lang.annotation.Pointcut;
+@Pointcut("execution(* com.xyz.myapp.service.*.*(..))") // expression
+private void businessService() {} // signature
+```
+
+ʾжһΪ getname 㣬㽫 com.tutorialspoint µ Student е getName() ƥ䣺
+
+```
+import org.aspectj.lang.annotation.Pointcut;
+@Pointcut("execution(* com.tutorialspoint.Student.getName(..))")
+private void getname() {}
+```
+
+##
+
+ʹ @{ADVICE-NAME} עеһʾѾһǩ businessService()
+
+```
+@Before("businessService()")
+public void doBeforeTask(){
+ ...
+}
+@After("businessService()")
+public void doAfterTask(){
+ ...
+}
+@AfterReturning(pointcut = "businessService()", returning="retVal")
+public void doAfterReturnningTask(Object retVal){
+ // you can intercept retVal here.
+ ...
+}
+@AfterThrowing(pointcut = "businessService()", throwing="ex")
+public void doAfterThrowingTask(Exception ex){
+ // you can intercept thrown exception here.
+ ...
+}
+@Around("businessService()")
+public void doAroundTask(){
+ ...
+}
+```
+
+Ϊһ鶨ڽ֮ǰһʾ
+
+```
+@Before("execution(* com.xyz.myapp.service.*.*(..))")
+public doBeforeTask(){
+ ...
+}
+```
+
+## AOP @AspectJ ʾ
+
+ΪᵽĹڻ AOP @AspectJ ĸDZдһʾʵּ顣Ϊǵʾʹü飬ʹ Eclipse IDE ڹ״̬Ȼ²贴һ Spring Ӧó
+
+| | |
+| --- | --- |
+| 1 | һΪ _SpringExample_ ĿĿ **src** ļ´һΪ _com.tutorialspoint_ İ |
+| 2 | ʹ _Add External JARs_ ѡ Spring ļ _Spring Hello World Example_ ½н͵ |
+| 3 | Ŀ Spring AOP ָĿļ **aspectjrt.jar aspectjweaver.jar** **aspectj.jar** |
+| 4 | _com.tutorialspoint_ ´ Java **Logging** _Student_ _MainApp_ |
+| 5 | **src** ļ´ Beans ļ _Beans.xml_ |
+| 6 | һǴ Java ļ Bean ļݣҰ½͵Ӧó |
+
+ **Logging.java** ļݡʵ aspect ģһʾڸõķ
+
+```
+package com.tutorialspoint;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.After;
+import org.aspectj.lang.annotation.AfterThrowing;
+import org.aspectj.lang.annotation.AfterReturning;
+import org.aspectj.lang.annotation.Around;
+@Aspect
+public class Logging {
+ /** Following is the definition for a pointcut to select
+ * all the methods available. So advice will be called
+ * for all the methods.
+ */
+ @Pointcut("execution(* com.tutorialspoint.*.*(..))")
+ private void selectAll(){}
+ /**
+ * This is the method which I would like to execute
+ * before a selected method execution.
+ */
+ @Before("selectAll()")
+ public void beforeAdvice(){
+ System.out.println("Going to setup student profile.");
+ }
+ /**
+ * This is the method which I would like to execute
+ * after a selected method execution.
+ */
+ @After("selectAll()")
+ public void afterAdvice(){
+ System.out.println("Student profile has been setup.");
+ }
+ /**
+ * This is the method which I would like to execute
+ * when any method returns.
+ */
+ @AfterReturning(pointcut = "selectAll()", returning="retVal")
+ public void afterReturningAdvice(Object retVal){
+ System.out.println("Returning:" + retVal.toString() );
+ }
+ /**
+ * This is the method which I would like to execute
+ * if there is an exception raised by any method.
+ */
+ @AfterThrowing(pointcut = "selectAll()", throwing = "ex")
+ public void AfterThrowingAdvice(IllegalArgumentException ex){
+ System.out.println("There has been an exception: " + ex.toString());
+ }
+}
+```
+
+ **Student.java** ļݣ
+
+```
+package com.tutorialspoint;
+public class Student {
+ private Integer age;
+ private String name;
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+ public Integer getAge() {
+ System.out.println("Age : " + age );
+ return age;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+ public String getName() {
+ System.out.println("Name : " + name );
+ return name;
+ }
+ public void printThrowException(){
+ System.out.println("Exception raised");
+ throw new IllegalArgumentException();
+ }
+}
+```
+
+ **MainApp.java** ļݣ
+
+```
+package com.tutorialspoint;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+public class MainApp {
+ public static void main(String[] args) {
+ ApplicationContext context =
+ new ClassPathXmlApplicationContext("Beans.xml");
+ Student student = (Student) context.getBean("student");
+ student.getName();
+ student.getAge();
+ student.printThrowException();
+ }
+}
+```
+
+ļ **Beans.xml**
+
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+һѾɵĴԴļ bean ļһӦóӦóһжĻ⽫Ϣ
+
+```
+Going to setup student profile.
+Name : Zara
+Student profile has been setup.
+Returning:Zara
+Going to setup student profile.
+Age : 11
+Student profile has been setup.
+Returning:11
+Going to setup student profile.
+Exception raised
+Student profile has been setup.
+There has been an exception: java.lang.IllegalArgumentException
+.....
+other exception content
+```
+
+
+
+
+
+# ο
+https://www.w3cschool.cn/wkspring
+https://www.runoob.com/w3cnote/basic-knowledge-summary-of-spring.html
+http://codepub.cn/2015/06/21/Basic-knowledge-summary-of-Spring
+https://dunwu.github.io/spring-tutorial
+https://mszlu.com/java/spring
+http://c.biancheng.net/spring/aop-module.html
\ No newline at end of file
diff --git "a/docs/spring/SpringBean\347\232\204\345\256\232\344\271\211\344\270\216\347\256\241\347\220\206\357\274\210\346\240\270\345\277\203\357\274\211.md" "b/docs/spring/SpringBean\347\232\204\345\256\232\344\271\211\344\270\216\347\256\241\347\220\206\357\274\210\346\240\270\345\277\203\357\274\211.md"
new file mode 100644
index 0000000..a684554
--- /dev/null
+++ "b/docs/spring/SpringBean\347\232\204\345\256\232\344\271\211\344\270\216\347\256\241\347\220\206\357\274\210\346\240\270\345\277\203\357\274\211.md"
@@ -0,0 +1,182 @@
+### ע
+
+SpringܵĺĹ
+
+* SpringΪеJavaЩJavaΪBean
+* SpringBean֮ϵSpringʹһֱΪ"ע"ķʽBean֮ϵ
+
+ʹע룬ΪBeanעֵͨעBeanáעһĽʽBeanļ֯һ𣬶Ӳķʽһ
+
+#### ע
+
+Rod Johnsonǵһ߶ļJavaʵЭϵˣַʽһ֣ƷתInverse of ControlIoCMartine FowlerΪַʽһƣע루Dependency Injection˲ע룬ǿƷת京ȫͬijJavaߣҪһJavaķʱڴͳģʽͨ
+
+1. ԭʼ: ****Ȼٵñķ
+2. ģʽ: ҵĹȻ****ͨȥȡٵñķ
+
+ע****֣Ȼᵼµ뱻ʵӲϣdzĿάʹSpring֮****ȡֻҪ****SpringΪߵijԱֵɣɴ˿ɼʹSpringȡķʽԭȡ˱ܡRod Johnson֮ΪƷת
+
+SpringĽǶSpringֵߵijԱ൱ΪעʵMartine Fowler֮Ϊע롣
+
+#### ֵע
+
+ֵעָIoCͨԱsetterע뱻ע뷽ʽֱۣSpringעʹá
+
+#### ע
+
+ùϵķʽΪע롣ͨ˵SpringڵײԷ䷽ʽִдָĹִдĹʱͿùԳԱִгʼǹעıʡ
+
+#### ע뷽ʽĶԱ
+
+ֵעŵ㣺
+
+* 봫ͳJavaBeanдƣԱ⡢ܡͨsetter趨ϵԵøֱۡȻ
+* ڸӵϵùע룬ᵼ¹ӷףĶSpringڴBeanʵʱҪͬʱʵȫʵ½ʹֵע룬ܱЩ⡣
+* ijЩԱѡ£Ĺӱء
+
+ע£
+
+* עڹоϵע˳ע롣
+* ϵ仯BeanעôΪûsetterеϵȫڹ趨뵣ĺĴϵƻ
+* ϵֻڹ趨ֻĴ߲ܸıϵĵ߶ԣڲϵȫϸھ۵ԭ
+
+**_ע⣺_**
+ֵעΪעΪעԡϵ仯ע룬ùע룻ϵע룬Dzֵע롣
+
+### SpringеBean
+
+ڿ˵ʹSpringҪ£ٿBeanBeanSpring˵ҪľǸļBeanʵBeanʵķ"ע"νIoCıʡ
+
+#### Bean
+
+ͨSpringһBeanʵʱBeanʵʵΪBeanָضSpring֧
+
+1. singleton: ģʽSpring IoCУsingletonBeanֻһʵ
+2. prototype: ÿͨgetBean()ȡprototypeBeanʱһµBeanʵ
+3. request: һHTTPrequestBeanֻһʵζţͬһHTTPڣÿBeanõͬһʵֻWebӦʹSpringʱЧ
+4. session bean ĶΪ HTTP Ự ֻweb-aware Spring ApplicationContextЧ
+5. global session: ÿȫֵHTTP SessionӦһBeanʵڵ͵£ʹportlet contextʱЧֻͬWebӦЧ
+
+ָBeanSpringĬʹsingletonprototypeBeanĴٴ۱ȽϴsingletonBeanʵһɹͿظʹáˣӦþ⽫Beanóprototype
+
+### ʹԶװעBean
+
+SpringԶװBeanBean֮ϵʹrefʽָBeanSpringXMLļݣijֹΪBeanע뱻Bean
+SpringԶװͨ` `Ԫص`default-autowire`ָԶļеBeanãҲͨ` `Ԫص`autowire`ָֻԸBeaná
+
+`autowire``default-autowire`Խֵ
+
+* `no`: ʹԶװ䡣BeanͨrefԪض塣ĬãڽϴIJвıãʽúܹõϵ
+* `byName`: setterԶװ䡣SpringȫBeanҳidsetterȥsetǰСдĸͬBeanע롣ûҵƥBeanʵSpringκע롣
+* `byType`: setterβԶװ䡣SpringеȫBeanһBeansetterβƥ䣬ԶעBeanҵBean׳һ쳣ûҵBeanʲôᷢsetterᱻá
+* `constructor`: byTypeƣԶƥ乹IJǡҵһ빹ƥBean׳һ쳣
+* `autodetect`: SpringBeanڲṹоʹconstructorbyTypeԡҵһĬϵĹ캯ôͻӦbyTypeԡ
+
+**һBeanʹԶװʹrefʽָʱʽָԶװڴ͵ӦãʹԶװ䡣ȻʹԶװɼļĹϵԺԡϵװԴļͣBeanBean֮Ͻ͵Σڸ߲ν**
+
+
+
+## Bean3ַʽ
+
+### ʹùBeanʵ
+
+ʹùBeanʵùע룬SpringײBeanʵҪBeanṩĹ
+
+ĬϵĹBeanʵSpringBeanʵִĬϳʼеĻ͵ֵʼΪ0falseе͵ֵʼΪnull
+
+### ʹþ̬Bean
+
+ʹþ̬BeanʵʱclassҲָʱclassԲָBeanʵʵ࣬Ǿ̬࣬Spring֪ͨĸBeanʵ
+
+֮⣬Ҫʹfactory-methodָ̬Springþ̬һBeanʵһָBeanʵSpringĴͨBeanʵȫһ̬Ҫʹ` `Ԫָ̬IJ
+
+### ʵBean
+
+ʵ뾲ֻ̬һͬþֻ̬ʹù༴ɣʵҪʵʹʵʱBeanʵ` `Ԫclassԣʵʹ`factory-bean`ָʵ
+ʵBean` `ԪʱҪָԣ
+
+* factory-bean: ԵֵΪBeanid
+* factory-method: ָʵĹ
+
+ʵʱҪʹ` `Ԫȷֵ
+
+## ЭͬBean
+
+singletonBeanprototypeBeanʱͬԭΪSpringʼʱԤʼе`singleton Bean``singleton Bean``prototype Bean`Springڳʼ`singleton Bean`֮ǰȴ`prototypeBean`ȻŴ`singleton Bean`ォ`prototype Bean`ע`singleton Bean`
+ͬķ֣
+
+* ע: singletonBeanÿҪprototypeBeanʱµBeanʵɱ֤ÿע`prototype Bean`ʵµʵ
+* ÷ע: עͨʹlookupע룬ʹlookupעSpringдBeanij巽زBeanĽҵBeanͨһ`non-singleton Bean`SpringͨʹJDK̬cglibĿͻ˵Ķ룬ӶʵҪ
+
+õڶַʹ÷ע롣Ϊʹlookupע룬Ҫ
+
+1. BeanʵඨΪ࣬һȡBean
+2. ` `Ԫ` `ԪSpringΪBeanʵʵָij
+
+**_ע⣺_**
+
+> Springʱ̬ǿķʽʵ` `ԪָijĿʵֹӿڣSpringJDK̬ʵָó࣬Ϊ֮ʵֳĿûʵֹӿڣSpringcglibʵָó࣬Ϊ֮ʵֳSpring4.0spring-core-xxx.jarѾcglib⡣
+
+## ֺ
+
+Springṩֳõĺ
+
+* Bean: ֺBeanкBeanжǿ
+* : ֺIoCкǿܡ
+
+### Bean
+
+BeanһBeanBeanṩidԣҪеBeanִкΪеĿBeanɴȣBeanΪBeanBeanBeanʵɹ֮BeanʵнһǿBeanʵ`BeanPostProcessor`ӿڣͬʱʵָýӿڵ
+
+1. `Object postProcessBeforeInitialization(Object bean, String name) throws BeansException`: ÷ĵһϵͳкBeanʵڶǸBeanid
+2. `Object postProcessAfterinitialization(Object bean, String name) throws BeansException`: ÷ĵһϵͳкBeanʵڶǸBeanid
+
+һעBeanBeanͻԶÿBeanʱԶBeanĻصʱͼ
+
+
+
+עһ㣬ʹ`BeanFactory`ΪSpringֶעBeanȡBeanʵȻֶעᡣ
+
+ BeanPostProcessor bp = (BeanPostProcessor)beanFactory.getBean("bp"); beanFactory.addBeanPostProcessor(bp); Person p = (Person)beanFactory.getBean("person");
+
+###
+
+BeanеBeanʵʵ`BeanFactoryPostProcessor`ӿڣʵָýӿڵһ`postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)`ʵָ÷ķǶSpringеĴִԶSpringԶչȻҲԶSpringκδ
+
+`BeanPostProcessor``ApplicationContext`ԶеԶעʹ`BeanFactory`ΪSpringֶø`BeanFactory`
+
+## Spring""֧
+
+### Bean
+
+Springṩ¼AnnotationעSpring Bean
+
+* `@Component`: עһͨSpring Bean
+* `@Controller`: עһ
+* `@Service`: עһҵ
+* `@Repository`: עһDAO
+
+SpringļãָԶɨİ
+
+
+
+### ʹ@Resource
+
+`@Resource`λ`javax.annotation`£JavaEE淶һ`Annotation`Springֱӽ˸`Annotation`ͨʹø`Annotation`ΪĿBeanָЭBeanʹ`@Resource`` `ԪصrefͬЧ
+`@Resource`setterҲֱʵʹ`@Resource`ʵӼʱSpringֱʹJavaEE淶Fieldע룬ʱsetterԲҪ
+
+### ʹ@PostConstruct@PreDestroyΪ
+
+`@PostConstruct``@PreDestroy`ͬλjavax.annotation£ҲJavaEE淶AnnotationSpringֱӽǣڶSpringBeanΪǶηκԡǰεķʱBeanijʼεķʱBean֮ǰķ
+
+### Spring4.0ǿԶװ;ȷװ
+
+Springṩ`@Autowired`עָԶװ䣬`@Autowired`setterͨʵȡʹ`@Autowired`עsetterʱĬϲbyTypeԶװԡֲ£Զװ͵ĺѡBeanʵжʱͿ쳣Ϊʵ־ȷԶװ䣬Springṩ`@Qualifier`ע⣬ͨʹ`@Qualifier`BeanidִԶװ䡣
+
+# ο
+https://www.w3cschool.cn/wkspring
+https://www.runoob.com/w3cnote/basic-knowledge-summary-of-spring.html
+http://codepub.cn/2015/06/21/Basic-knowledge-summary-of-Spring
+https://dunwu.github.io/spring-tutorial
+https://mszlu.com/java/spring
+http://c.biancheng.net/spring/aop-module.html
\ No newline at end of file
diff --git "a/docs/spring/SpringBoot/SpringBoot\345\270\270\350\247\201\346\263\250\350\247\243.md" "b/docs/spring/SpringBoot/SpringBoot\345\270\270\350\247\201\346\263\250\350\247\243.md"
new file mode 100644
index 0000000..c699974
--- /dev/null
+++ "b/docs/spring/SpringBoot/SpringBoot\345\270\270\350\247\201\346\263\250\350\247\243.md"
@@ -0,0 +1,158 @@
+## 1
+Spring Boot ͨԶùʹ Spring øס
+
+ڱٽ̳Уǽ̽ org.springframework.boot.autoconfigure org.springframework.boot.autoconfigure.condition еע⡣
+
+## 2 @SpringBootApplication
+ʹע Spring Boot Ӧóࣺ
+
+@SpringBootApplication
+ʹע Spring Boot Ӧóࣺ
+````
+@SpringBootApplication
+class VehicleFactoryApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(VehicleFactoryApplication.class, args);
+ }
+}
+````
+@SpringBootApplication װ@Configuration@EnableAutoConfiguration @ComponentScan ע⼰Ĭԡ
+
+## 3 @EnableAutoConfiguration
+
+@EnableAutoConfiguration˼壬Զá ζ Spring Boot ·вԶ bean ԶӦǡ
+
+ע⣬DZ뽫ע@Configuration һʹã
+
+````
+@Configuration
+@EnableAutoConfiguration
+class VehicleFactoryConfig {}
+````
+
+## 4 @ConfigurationԼ
+
+@Configurationãעϣspring(Ӧ)
+
+springbeanʹõxmlļһbeanspringbootУΪãspringṩ@Configurationһע
+
+൱ڰѸΪspringxmlļе
+
+@ConfigurationעУʹ@BeanעעķصͶֱעΪbean
+
+@ConfigureעĶ£
+````
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Component
+public @interface Configuration {
+String value() default "";
+}
+````
+ӶײǺ@Component @Configuration к @Component ácontext:component-scan/@ComponentScanܴ@Configurationעࡣ
+
+ͨDZдԶԶʱϣ Spring ʹǡ ǿͨеעʵһ㡣
+
+ǿԽ˲еעͷ@Configuration @Bean ϡ
+
+ڽIJУǽֻÿĻ ˽Ϣƪ¡
+
+### 4.1 @ConditionalOnClass and @ConditionalOnMissingClass
+һжϵע⣬Ҫ֪ܶʱǰbeanģǸⲿjarǷмغжϵġ
+
+ʱҪⲿǷǷǷظbean
+
+ʹЩעͲе/ڣSpring ʹñǵԶ bean
+
+````
+@Configuration
+@ConditionalOnClass(DataSource.class)
+class MySQLAutoconfiguration {
+//...
+}
+````
+
+### 4.2 @ConditionalOnBean and @ConditionalOnMissingBean
+
+Ҫض bean ĴڻʱǿʹЩעͣ
+
+һעЩͬΪǵжbean
+
+````
+@Bean
+@ConditionalOnBean(name = "dataSource")
+LocalContainerEntityManagerFactoryBean entityManagerFactory() {
+// ...
+}
+````
+### 4.3 @ConditionalOnProperty
+ͨע⣬ǿԶԵֵ
+
+Ҫע⣬ֵԴapplication.propertiesļе
+
+````
+@Bean
+@ConditionalOnProperty(
+name = "usemysql",
+havingValue = "local"
+)
+DataSource dataSource() {
+// ...
+}
+````
+
+### 4.4 @ConditionalOnResource
+
+ǿ Spring ڴضԴʱʹö壺
+˼壬ҪclasspathԴļʱŽмأҲǺܳõһע⡣
+
+````
+
+@ConditionalOnResource(resources = "classpath:mysql.properties")
+Properties ditionalProperties() {
+// ...
+}
+````
+
+### 4.5 @ConditionalOnWebApplication and @ConditionalOnNotWebApplication
+עͨںwebǿȫ
+
+ʹЩעͣǿԸݵǰӦóǷ Web Ӧó
+````
+
+@ConditionalOnWebApplication
+HealthCheckController healthCheckController() {
+// ...
+}
+````
+
+### 4.6 @ConditionalExpression
+springbootΪ뵽עҪôɴԼдӦûɣ
+
+ǿڸӵʹע⡣ SpEL ʽΪʱSpring ʹñǵĶ壺
+
+````
+@Bean
+@ConditionalOnExpression("${usemysql} && ${mysqlserver == 'local'}")
+DataSource dataSource() {
+// ...
+}
+````
+
+### 4.7 @Conditional
+ʲô⣿
+springbootҲṩʲôʽˣֱûдһжtruefalse
+
+ڸӵǿԴһԶࡣ Ǹ Spring Զ @Conditional һʹã
+
+````
+@Conditional(HibernateCondition.class)
+Properties ditionalProperties() {
+//...
+}
+````
+
+## 5 ܽ
+ڱУǸԶù̲ΪԶԶ bean ṩ
\ No newline at end of file
diff --git "a/docs/spring/SpringBoot/SpringBoot\347\232\204\345\237\272\346\234\254\344\275\277\347\224\250.md" "b/docs/spring/SpringBoot/SpringBoot\347\232\204\345\237\272\346\234\254\344\275\277\347\224\250.md"
new file mode 100644
index 0000000..36a2500
--- /dev/null
+++ "b/docs/spring/SpringBoot/SpringBoot\347\232\204\345\237\272\346\234\254\344\275\277\347\224\250.md"
@@ -0,0 +1,152 @@
+# ٹSpringBootӦ
+
+̳springboot㹻ȨҲ㹻
+
+## һ hello world
+
+һġHello WorldκӵĶ˵㡣Ը֣ԸѺõķʽӦ
+
+## Ҫ
+
+1һֵIDE,ѡ IntelliJ IDEASpring ToolsVisual Studio Code Eclipse ȵȡ
+
+2JDKڰ汾Ļ8-17Dzѡ
+
+3ȻﻹҪmavenpomҲҪmavenmavenideaԴˡǻڽIJֽнܣҪЩ
+
+## һһµSpring BootĿ
+
+ʹ[start.spring.io](http://start.spring.io/)һwebĿڡdependenciesԻӡwebĻͼʾ
+
+ɡť zip ļѹϵһļС
+
+
+
+[start.spring.io](http://start.spring.io/)Ŀ[Spring Boot](https://spring.io/projects/spring-boot)һSpringӦóڲҪ̫á Spring Boot Spring Ŀеķʽ
+
+ѡʹmavenΪߣĿpomļpomļӵ
+
+````
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.0.5
+
+
+ com.example
+ demo
+ 0.0.1-SNAPSHOT
+ demo
+ Demo project for Spring Boot
+
+ 17
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+````
+
+
+## ڶĴ
+
+ IDE дĿ `src/main/java/com/example/demo` ļҵ `DemoApplication.java` ļ
+
+ͨʾĶⷽעļݡԸƲճֱӼ롣
+```
+package com.example.demo;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+@SpringBootApplication
+@RestController
+public class DemoApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(DemoApplication.class, args);
+ }
+ @GetMapping("/hello")
+ public String hello(@RequestParam(value = "name", defaultValue = "World") String name) {
+ return String.format("Hello %s!", name);
+ }
+}
+
+```
+
+ Spring Boot дһġHello World Web д롣
+
+ӵ`hello()`ּڻȡһΪnameStringȻ˲еĵ`"Hello"`
+
+ζнΪAmyӦǡHello Amy
+
+`@RestController` ע Spring˴һ˵㣬ö˵Ӧ Web Ͽá
+
+@GetMapping(/hello) Spring ʹǵ hello() Ӧ͵ http://localhost:8080/hello ַ
+
+@RequestParam Spring һֵڣĬʹõʡWorld
+
+##
+
+ǹгУնˣӵĿļļС
+
+ǿͨӦó
+
+**MacOS/Linux:**
+
+```
+COPY./gradlew bootRun
+
+```
+
+**Windows:**
+
+```
+COPY.\gradlew.bat bootRun
+
+```
+
+ӦûῴһЩ˷dzƵ
+
+
+иǣSpringӦѾʼˡ
+Spring Boot Ƕʽ Apache Tomcat 䵱ڼlocalhost˿ڡ8080ϵ
+
+ڶĵַ`http://localhost:8080/hello`
+
+ӦõõһѺõĻӦ
+
+
+# ܽ
+˼һSpringBootӦþôˣ㲻ҪļǶķ
+ֻҪһ࣬ͿʵһSpringBootӦá
+
+ҲΪʲôspringbootٹһΪʵ̫ˡ
+ȻʵʿҪõspringbootĹܺԣǽڽ½չܡ
+
+# ο
+https://spring.io/quickstart
\ No newline at end of file
diff --git "a/docs/spring/SpringBoot/Spring\345\270\270\350\247\201\346\263\250\350\247\243\344\275\277\347\224\250\346\214\207\345\215\227(\345\214\205\345\220\253Spring+SpringMVC+SpringBoot).md" "b/docs/spring/SpringBoot/Spring\345\270\270\350\247\201\346\263\250\350\247\243\344\275\277\347\224\250\346\214\207\345\215\227(\345\214\205\345\220\253Spring+SpringMVC+SpringBoot).md"
new file mode 100644
index 0000000..813fabe
--- /dev/null
+++ "b/docs/spring/SpringBoot/Spring\345\270\270\350\247\201\346\263\250\350\247\243\344\275\277\347\224\250\346\214\207\345\215\227(\345\214\205\345\220\253Spring+SpringMVC+SpringBoot).md"
@@ -0,0 +1,1112 @@
+# Springע
+## 1
+
+Ƕ֪SpringĵԾIOC+AOPIOCԭʵһSpringSpring Beanʵ
+DIҲע룬ΪҪĵĺĻ⣬עעĸҪȷ֪ġ
+ǰϰxmlļһbeanڣǸʹעʹDIĹ
+
+
+ǿʹ org.springframework.beans.factory.annotation org.springframework.context.annotation еע Spring DI Ĺܡ
+
+ͨЩΪSpring ע͡ǽڱ̳жлعˡ
+
+
+## 2 DIע
+
+### 2.1 @Autowired
+
+ǿʹ @Autowired Spring Ҫע
+ǿԽע빹캯setter ֶעһʹá
+Constructor injection:
+
+**ע**
+
+````
+class Car {
+ Engine engine;
+
+ @Autowired
+ Car(Engine engine) {
+ this.engine = engine;
+ }
+}
+````
+
+**Setterע**
+````
+class Car {
+ Engine engine;
+
+ @Autowired
+ void setEngine(Engine engine) {
+ this.engine = engine;
+ }
+}
+````
+**ע**
+````
+class Car {
+ @Autowired
+ Engine engine;
+}
+````
+
+@Autowired һΪ required IJĬֵΪ true
+
+Ҳʵ bean ʱ Spring Ϊ Ϊ true ʱ׳쳣κݡ
+
+ע⣬ʹù캯ע룬й캯ǿԵġ
+
+ 4.3 汾ʼDzҪʽʹ @Autowired ע캯캯
+
+### 2.2 @Bean
+
+@Bean ʵ Spring bean Ĺ
+
+```
+@Bean
+Engine engine() {
+ return new Engine();
+}
+````
+
+Ҫ͵ʵʱSpring Щ
+
+ɵ bean 빤ͬ Բͬķʽǿʹôע͵ƻֵֵDzƵı
+
+````
+@Bean("engine")
+Engine getEngine() {
+ return new Engine();
+}
+````
+һַdzbeanʽΪܶbeanһʼڴﶨõģҪʱа蹹
+
+ǿɵͶBeanҲԸԶbeanơ
+
+ע⣬@Bean ע͵ķ@Configuration С
+
+### 2.3 @Qualifier
+
+ʹ@Qualifier @Autowired ṩҪڲȷʹõbean id bean ơ
+
+磬 bean ʵͬĽӿڣ
+````
+class Bike implements Vehicle {}
+
+class Car implements Vehicle {}
+
+````
+
+ Spring Ҫעһ Vehicle beanԶƥ䶨 £ǿʹ @Qualifier עʽṩ bean ơ
+
+**ע**
+````
+@Autowired
+Biker(@Qualifier("bike") Vehicle vehicle) {
+this.vehicle = vehicle;
+}
+````
+
+**Setterע**
+
+````
+@Autowired
+void setVehicle(@Qualifier("bike") Vehicle vehicle) {
+this.vehicle = vehicle;
+}
+````
+:
+
+````
+@Autowired
+@Qualifier("bike")
+void setVehicle(Vehicle vehicle) {
+this.vehicle = vehicle;
+````
+**ע**
+
+````
+@Autowired
+@Qualifier("bike")
+Vehicle vehicle;
+````
+עǿƽõIJ࣬ǵһӿжʵʱͻᾭó
+
+### 2.4 @Required
+
+@Required setter ϱҪͨ XML
+````
+@Required
+void setColor(String color) {
+this.color = color;
+}
+````
+xml
+````
+
+
+
+````
+׳ BeanInitializationException
+dzټ÷֪һ¾
+
+### 2.5 @Value
+ǿʹ @Value ֵע bean 빹캯setter ֶעݡ
+
+ҲǷdzõһע⣬ΪǺܶʱҪapplication.propertiesļȡֵ
+
+**ע**
+````
+Engine(@Value("8") int cylinderCount) {
+this.cylinderCount = cylinderCount;
+}
+````
+
+**setterע**
+
+````
+@Autowired
+void setCylinderCount(@Value("8") int cylinderCount) {
+this.cylinderCount = cylinderCount;
+}
+````
+
+:
+````
+
+@Value("8")
+void setCylinderCount(int cylinderCount) {
+this.cylinderCount = cylinderCount;
+}
+````
+
+**ע**
+````
+@Value("8")
+int cylinderCount;
+````
+
+Ȼע뾲ֵ̬ûõġ ˣǿ @Value ʹռλַⲿԴжֵ .properties .yaml ļС
+````
+
+engine.fuelType=petrol
+````
+
+ǿͨ·ʽע engine.fuelType ֵ
+
+````
+@Value("${engine.fuelType}")
+String fuelType;
+````
+
+ʹ SpEL ʹ@Value ʾǹ@Value ҵ
+
+### 2.6 @DependsOn
+ǿʹôע Spring ע bean ֮ǰʼ bean ͨΪԶģ bean ֮ʽϵ
+
+ֻʽʱҪע⣬JDBCػ߾̬ʼ
+
+ǿָ bean Ƶʹ @DependsOn ע͵ֵҪһ bean Ƶ飺
+
+````
+@DependsOn("engine")
+class Car implements Vehicle {}
+````
+Alternatively, if we define a bean with the @Bean annotation, the factory method should be annotated with @DependsOn:
+````
+@Bean
+@DependsOn("fuel")
+Engine engine() {
+return new Engine();
+}
+````
+### 2.7 @Lazy
+سʼǵ bean ʱʹ @Lazy Ĭ£Spring Ӧóĵ/ʱеشе bean
+
+ǣЩҪʱ beanӦóʱ
+
+עΪǷȷλöͬ ǿڣ
+
+һ @Bean ע͵ bean ӳٷã˴ bean
+@Configuration а@Bean ܵӰ
+
+һ @Component ࣬ @Configuration ࣬ bean ӳٳʼ
+
+@Autowired 캯setter ֶΣӳټͨ
+
+````
+@Configuration
+@Lazy
+class VehicleFactoryConfig {
+
+ @Bean
+ @Lazy(false)
+ Engine engine() {
+ return new Engine();
+ }
+}
+````
+ͬһõע⡣
+
+άһдbeanĿʱᷢкܶbeanܶǰʹõģһҪʼʱͽгʼǽʡܶʱܡ
+
+
+### 2.8 @Lookup
+ͬһȽõע
+
+@Lookup Spring ǵʱط͵ʵ
+
+ϣSpring Ǵע͵ķʹǷķͺͲΪ BeanFactory#getBean IJ
+
+@Lookup ڣ
+
+ԭ bean עԼbean Provider
+
+ɾӵһԭ Spring beanôǼ⣺
+
+ǵĵ Spring bean ηЩԭ Spring bean
+
+ڣProvider ϶һַʽ @Lookup ijЩͨá
+
+ҪעǣspringĬʹõĵbeanҪעԭbeanDzҪĶ
+
+ȣǴһԭ beanԺǽע뵽 bean У
+````
+@Component
+@Scope("prototype")
+public class SchoolNotification {
+// ... prototype-scoped state
+}
+````
+ʹ@Lookupǿͨ bean ȡ SchoolNotification ʵ
+
+````
+@Component
+public class StudentServices {
+
+ // ... member variables, etc.
+
+ @Lookup
+ public SchoolNotification getNotification() {
+ return null;
+ }
+
+ // ... getters and setters
+}
+````
+Using @Lookup, we can get an instance of SchoolNotification through our singleton bean:
+````
+@Test
+public void whenLookupMethodCalled_thenNewInstanceReturned() {
+// ... initialize context
+StudentServices first = this.context.getBean(StudentServices.class);
+StudentServices second = this.context.getBean(StudentServices.class);
+
+ assertEquals(first, second);
+ assertNotEquals(first.getNotification(), second.getNotification());
+}
+````
+ע⣬ StudentServices Уǽ getNotification Ϊ
+
+Ϊ Spring ͨ beanFactory.getBean(StudentNotification.class) ˸÷ǿԽա
+
+
+### 2.9 @Primary
+ʱҪͬ͵bean Щ£ע뽫ɹΪ Spring ֪Ҫĸ bean
+
+Ѿ˴ѡ@Qualifier нߵ㲢ָ bean ơ
+
+ȻʱҪһض beanҪ bean
+
+ǿʹ@Primary @Primary õbeanunqualifiedעϱѡ
+
+````
+@Component
+@Primary
+class Car implements Vehicle {}
+
+@Component
+class Bike implements Vehicle {}
+
+@Component
+class Driver {
+@Autowired
+Vehicle vehicle;
+}
+
+@Component
+class Biker {
+@Autowired
+@Qualifier("bike")
+Vehicle vehicle;
+}
+````
+ǰʾУҪ ˣ Driver УSpring עһ Car bean Ȼ Biker bean Уֶ vehicle ֵһ Bike Ϊqualifiedġ
+
+### 2.10 @Scope
+
+ͨӦ˵beanscopeĬ϶ǵģʵspring beanֶֶ֧÷ΧŲͬڡ
+
+ʹ@Scope @Component @Bean ķΧ ǵԭ͡ỰglobalSession һЩԶ巶Χ
+
+ӦöֵΪ
+````
+singleton
+prototype
+request
+session
+application
+websocket
+````
+
+
+````
+@Component
+@Scope("prototype")
+class Engine {}
+````
+ǿһЩrequestsessionwebsocketbeanͨӦǺصģô洢ûϢsession֮bean
+
+ôʹãҪľ峡ѡˣһܴĻ⣬ȲչˣԺڵܡ
+
+## 3 ע
+ǿʹñעӦóġ
+
+
+### 3.1 @Profile
+
+ϣ Spring ضļڻ״̬ʱʹ@Component @Bean ǿʹ@Profile бǡ
+
+ǿʹע͵ֵļƣ
+
+ͨעòͬá
+
+
+````
+public interface DatasourceConfig {
+public void setup();
+}
+````
+
+ǿã
+
+````
+@Component
+@Profile("dev")
+public class DevDatasourceConfig implements DatasourceConfig {
+@Override
+public void setup() {
+System.out.println("Setting up datasource for DEV environment. ");
+}
+}
+````
+ã
+
+````
+@Component
+@Profile("production")
+public class ProductionDatasourceConfig implements DatasourceConfig {
+@Override
+public void setup() {
+System.out.println("Setting up datasource for PRODUCTION environment. ");
+}
+}
+````
+ȻҲʹxml͵ļbean
+
+xml
+````
+
+
+
+````
+### 3.2 @Import
+
+ǿʹض @Configuration ࣬ʹôעɨ衣 ǿΪЩṩ@Import ֵ
+
+˵Ҫõ@ConfigurationעbeanôspringӦñҪɨ赽Ŀ¼ǡûжԸ·ɨ裬ֻʹ·µĵ࣬ôǾͿʹ@Importˡ
+
+עǷdzõģһ
+
+````
+@Import(VehiclePartSupplier.class)
+class VehicleFactoryConfig {}
+
+@Configuration
+class VehiclePartSupplier{
+}
+````
+
+### 3.3 @ImportResource
+
+˵һ bean.xml ļҪ beans.xml ж bean 뵽 Spring Boot Уβأ
+
+1.Spring ʽļ bean.xml ˴ٸʾ˵ xml һ helloServiceʾ
+````
+
+
+
+
+
+
+````
+2.ʹ@ImportResourceע⣬ xml
+````
+/**
+ * Spring BootûSpringļԼдļҲԶʶ
+ * SpringļЧصSpring
+ * ʹ@ImportResourceע⣬עһ(˴)
+ */
+@SpringBootApplication
+@ImportResource(locations = {"classpath:beans.xml"})
+public class BootApplication {
+
+ public static void main(String[] args) {
+ // SpringӦ
+ SpringApplication.run(BootApplication.class,args);
+
+ }
+}
+
+````
+### 3.4 @PropertySource
+ͨע⣬ǿΪӦóöļ
+
+@PropertySource עṩһַԻƣڽ PropertySource ӵ Spring Environment У @Configuration һʹá
+
+ʹ @Value ȥöԣ磺@Value("testbean.name")ҲָĬֵ磺@Value("testbean.name:defaultValue")
+
+÷ʾ
+
+һļapp.properties
+````
+testbean.name=myTestBean
+````
+ @Configuration ʹ @PropertySource app.properties ø Environment PropertySources ϡ
+````
+@Configuration
+@PropertySource("classpath:/com/myco/app.properties")
+public class AppConfig {
+
+ @Autowired
+ Environment env;
+
+ @Bean
+ public TestBean testBean() {
+ TestBean testBean = new TestBean();
+ testBean.setName(env.getProperty("testbean.name"));
+ return testBean;
+ }
+}
+````
+
+ע⣺ʹ @Autowired Environment ע뵽УȻ testBean() ʹá
+У testBean.getName() ءmyTestBeanַ
+
+@PropertySource Java 8 ظעԣζǿαһࣺ
+
+````
+@Configuration
+@PropertySource("classpath:/annotations.properties")
+@PropertySource("classpath:/vehicle-factory.properties")
+class VehicleFactoryConfig {}
+````
+
+### 3.5 @PropertySources
+÷ͬϣֻһǿʹעָ@PropertySource ã
+````
+@Configuration
+@PropertySources({
+@PropertySource("classpath:/annotations.properties"),
+@PropertySource("classpath:/vehicle-factory.properties")
+})
+class VehicleFactoryConfig {}
+````
+ע⣬ Java 8 ǿͨظעʵͬĹܡ
+
+## 4.
+
+ڱУǿ Spring ע͵ĸ ǿ bean ӺӦģԼΪɨࡣ
+
+springϵеijעкܶ࣬һƪ²ȫǣ©ӭ䡣
+
+# Spring Beanע
+
+## 1
+ڱ̳Уǽڶ岻ͬ bean Spring bean ע͡
+
+мַ Spring bean ȣǿʹ XML ǡ ǻʹ@Bean ע bean
+
+ǿʹ org.springframework.stereotype еע֮һǸ࣬ಿɨ衣
+
+## 2 @ComponentScan
+Ǿʹõһע⣬ǵӦУʱһɨеİرǵҪɨⲿjarеbeanʱdzá
+
+ԼSpringBootApplicationϣҲԼ@configurationעϵ
+
+ɨ裬Spring Զɨе bean
+
+@ComponentScan ʹעɨЩࡣ
+
+ǿֱʹ basePackages value ֮һָƣvalue basePackages ı
+
+````
+@Configuration
+@ComponentScan(basePackages = "com.baeldung.annotations")
+class VehicleFactoryConfig {}
+````
+⣬ǿʹ basePackageClasses ָеࣺ
+
+````
+@Configuration
+@ComponentScan(basePackageClasses = VehicleFactoryConfig.class)
+class VehicleFactoryConfig {}
+````
+
+飬ǿΪÿṩ
+
+δָɨ跢ڴ @ComponentScan עͬһС
+
+@ComponentScan Java 8 ظעԣζǿαһࣺ
+
+````
+@Configuration
+@ComponentScan(basePackages = "com.baeldung.annotations")
+@ComponentScan(basePackageClasses = VehicleFactoryConfig.class)
+class VehicleFactoryConfig {}
+````
+
+ߣǿʹ @ComponentScans ָ @ComponentScan ã
+
+````
+@Configuration
+@ComponentScans({
+@ComponentScan(basePackages = "com.baeldung.annotations"),
+@ComponentScan(basePackageClasses = VehicleFactoryConfig.class)
+})
+````
+````
+class VehicleFactoryConfig {
+}
+````
+ʹ XML ʱɨͬ
+
+````
+
+````
+
+### 3 @Component
+
+@Component ༶ע⡣ ɨڼ䣬Spring Framework Զʹ@Component עࣺ
+````
+@Component
+class CarUtility {
+// ...
+}
+````
+
+Ĭ£ bean ʵͬĸСд ⣬ǿʹôע͵Ŀѡֵָͬơ
+
+@Repository@Service@Configuration @Controller Ǵ@Component ע⣬ǹͬbean Ϊ
+
+Spring ɨԶǡ
+
+ͨ˵ǻmvcӦǻõע⣬ڷwebӦиؿʹ@componentעbean
+
+### 4 @Repository
+
+DAO or Repository classes usually represent the database access layer in an application, and should be annotated with @Repository:
+````
+@Repository
+class VehicleRepository {
+// ...
+}
+````
+ʹôע͵һŵԶ־쳣ת ʹó־Կܣ Hibernateʱʹ @Repository ע͵׳ı쳣ԶתΪ Spring DataAccessExeption ࡣ
+
+Ҫ쳣תҪԼ PersistenceExceptionTranslationPostProcessor bean
+````
+@Bean
+public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
+return new PersistenceExceptionTranslationPostProcessor();
+}
+````
+ע⣬ڴ£Spring Զִ衣
+
+ͨ XML ã
+````
+
+````
+
+### 5 @Service
+ӦóҵͨפڷУǽʹ@Service עָʾһڸò㣺
+
+````
+@Service
+public class VehicleService {
+// ...
+}
+````
+### 6 @Controller
+@Controller һ༶ע⣬ Spring Framework Ϊ Spring MVC еĿ
+
+spring@Controller עbeanܶ飬ǻSpringMVCص
+
+````
+@Controller
+public class VehicleController {
+// ...
+}
+
+````
+## 7 @Configuration
+
+@Bean ע͵ bean 巽
+````
+@Configuration
+class VehicleFactoryConfig {
+
+ @Bean
+ Engine engine() {
+ return new Engine();
+ }
+
+}
+````
+## 8 AOPע
+ʹ Spring עʱ״һ㣬оض͵ΪĿꡣ
+
+磬 DAO 㷽ִʱ䡣 ǽ·棨ʹ AspectJ עͣ @Repository ͣ
+
+```
+@Aspect
+@Component
+public class PerformanceAspect {
+@Pointcut("within(@org.springframework.stereotype.Repository *)")
+public void repositoryClassMethods() {};
+
+ @Around("repositoryClassMethods()")
+ public Object measureMethodExecutionTime(ProceedingJoinPoint joinPoint)
+ throws Throwable {
+ long start = System.nanoTime();
+ Object returnValue = joinPoint.proceed();
+ long end = System.nanoTime();
+ String methodName = joinPoint.getSignature().getName();
+ System.out.println(
+ "Execution of " + methodName + " took " +
+ TimeUnit.NANOSECONDS.toMillis(end - start) + " ms");
+ return returnValue;
+ }
+}
+````
+
+ڴʾУǴһ㣬ƥʹ@Repository ע͵ез Ȼʹ@Around ֪ͨλǸ㣬ȷطõִʱ䡣
+
+⣬ʹַǿΪÿӦó־¼ܹƺΪ
+
+ȻˣaspectJעܶ࣬棬δҲᵥдĽܡ
+
+## 9
+
+ڱУǼ Spring עͲǸԴ͡
+
+ǻѧϰʹɨҵע͵ࡣ
+
+˽Щעε¸ɾֲԼӦóע֮ķ롣 ǻʹøСΪDzҪֶʽ bean
+# SpringMVCע
+## 1.
+ڱ̳Уǽ̽ org.springframework.web.bind.annotation е Spring Web ע͡
+
+## 2. @RequestMapping
+
+˵@RequestMapping @Controller ڲ ʹã
+
+·ƺֵӳ䵽ĸ URL
+ݵ HTTP
+params HTTP Ĵڡڻֵ
+headers HTTP ͷĴڡڻֵ
+ģ÷ HTTP Щý
+produces÷ HTTP ӦЩý
+һʾ
+
+````
+@Controller
+class VehicleController {
+
+ @RequestMapping(value = "/vehicles/home", method = RequestMethod.GET)
+ String home() {
+ return "home";
+ }
+}
+````
+༶ӦôעͣǿΪ @Controller едṩĬá Ψһ Spring ʹ÷øǵḽ·ֵ URL
+
+磬úЧһģ
+
+````
+@Controller
+@RequestMapping(value = "/vehicles", method = RequestMethod.GET)
+class VehicleController {
+
+ @RequestMapping("/home")
+ String home() {
+ return "home";
+ }
+}
+````
+
+⣬@GetMapping@PostMapping@PutMapping@DeleteMapping @PatchMapping @RequestMapping IJͬ壬HTTP ѷֱΪGETPOSTPUTDELETE PATCH
+
+Щ Spring 4.3 汾ʼá
+
+## 3 @RequestBody
+
+Ǽ@RequestBody HTTP ӳ䵽һ
+
+````
+@PostMapping("/save")
+void saveVehicle(@RequestBody Vehicle vehicle) {
+// ...
+}
+````
+лԶģȡ͡
+
+## 4 @PathVariable
+˵˵@PathVariable
+
+עָʾ URI ģ ǿʹ @RequestMapping עָ URI ģ壬ʹ @PathVariable ģ岿֮һ
+
+ǿʹƻֵʵһ㣺
+
+````
+@RequestMapping("/{id}")
+Vehicle getVehicle(@PathVariable("id") long id) {
+// ...
+}
+````
+ģвֵ뷽ƥ䣬ǾͲעָ
+
+````
+@RequestMapping("/{id}")
+Vehicle getVehicle(@PathVariable long id) {
+// ...
+}
+````
+⣬ǿͨIJΪ false ·Ϊѡ
+
+````
+@RequestMapping("/{id}")
+Vehicle getVehicle(@PathVariable(required = false) long id) {
+// ...
+}
+````
+## 5. @RequestParam
+We use @RequestParam for accessing HTTP request parameters:
+````
+@RequestMapping
+Vehicle getVehicleByParam(@RequestParam("id") long id) {
+// ...
+}
+````
+ @PathVariable עͬѡ
+
+Щ֮⣬ Spring зûֵΪֵʱǿʹ @RequestParam ָעֵ ΪˣDZ defaultValue
+
+ṩĬֵʽ required Ϊ false
+````
+@RequestMapping("/buy")
+Car buyCar(@RequestParam(defaultValue = "5") int seatCount) {
+// ...
+}
+````
+˲֮⣬ǻԷ HTTP ֣cookie ͱͷ
+
+ǿԷֱʹע@CookieValue @RequestHeader ǡ
+
+
+## 6. Response Handling Annotations
+ڽIJУǽ Spring MVC в HTTP Ӧע͡
+
+### 6.1 @ResponseBody
+@ResponseBody Spring ὫĽΪӦ
+
+````
+@ResponseBody
+@RequestMapping("/hello")
+String hello() {
+return "Hello World!";
+}
+````
+עע @Controller ࣬ʹ
+
+### 6.2 @ExceptionHandler
+
+ʹôעͣǿһԶ ׳κָ쳣ʱSpring ô˷
+
+쳣Ϊݸ
+````
+@ExceptionHandler(IllegalArgumentException.class)
+void onIllegalArgumentException(IllegalArgumentException exception) {
+// ...
+}
+````
+
+### 6.3 @ResponseStatus
+ʹôעͶעָͣӦ HTTP ״̬ ǿʹ code value ״̬롣
+
+⣬ǿʹ reason ṩԭ
+
+ҲԽ@ExceptionHandler һʹã
+
+@ExceptionHandler(IllegalArgumentException.class)
+@ResponseStatus(HttpStatus.BAD_REQUEST)
+void onIllegalArgumentException(IllegalArgumentException exception) {
+// ...
+}
+
+й HTTP Ӧ״̬ĸϢʱġ
+
+## 7 Webע
+һЩעͲֱӹ HTTP Ӧ ڽIJУǽġ
+
+### 7.1 @Controller
+ǿʹ@Controller һSpring MVC йظϢǹ Spring Bean Annotations ¡
+
+### 7.2 @RestController
+@RestController @Controller @ResponseBody
+
+ˣǵЧģ
+
+````
+@Controller
+@ResponseBody
+class VehicleRestController {
+// ...
+}
+````
+
+````
+@RestController
+class VehicleRestController {
+// ...
+}
+````
+### 7.3 @ModelAttribute
+ͨע⣬ǿͨṩģͼѾ MVC @Controller ģеԪأ
+
+````
+@PostMapping("/assemble")
+void assembleVehicle(@ModelAttribute("vehicle") Vehicle vehicleInModel) {
+// ...
+}
+````
+@PathVariable @RequestParam һͬƣDzָģͼ
+
+````
+@PostMapping("/assemble")
+void assembleVehicle(@ModelAttribute Vehicle vehicle) {
+// ...
+}
+````
+⣬@ModelAttributeһ;עһSpringԶķֵӵģУ
+
+````
+@ModelAttribute("vehicle")
+Vehicle getVehicle() {
+// ...
+}
+````
+ǰһDzָģͼSpring Ĭʹ÷ƣ
+````
+@ModelAttribute
+Vehicle vehicle() {
+// ...
+}
+````
+ Spring ֮ǰ @ModelAttribute ע͵ķ
+
+й @ModelAttribute ĸϢıġ
+
+### 7.4 @CrossOrigin
+@CrossOrigin Ϊע͵ÿͨţ
+
+````
+@CrossOrigin
+@RequestMapping("/hello")
+String hello() {
+return "Hello World!";
+}
+````
+һ࣬е
+
+ǿʹôע͵IJ CORS Ϊ
+
+йϸϢʱġ
+
+# SpringBootע
+## 1
+Spring Boot ͨԶùʹ Spring øס
+
+ڱٽ̳Уǽ̽ org.springframework.boot.autoconfigure org.springframework.boot.autoconfigure.condition еע⡣
+
+## 2 @SpringBootApplication
+ʹע Spring Boot Ӧóࣺ
+
+@SpringBootApplication
+ʹע Spring Boot Ӧóࣺ
+````
+@SpringBootApplication
+class VehicleFactoryApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(VehicleFactoryApplication.class, args);
+ }
+}
+````
+@SpringBootApplication װ@Configuration@EnableAutoConfiguration @ComponentScan ע⼰Ĭԡ
+
+## 3 @EnableAutoConfiguration
+
+@EnableAutoConfiguration˼壬Զá ζ Spring Boot ·вԶ bean ԶӦǡ
+
+ע⣬DZ뽫ע@Configuration һʹã
+
+````
+@Configuration
+@EnableAutoConfiguration
+class VehicleFactoryConfig {}
+````
+
+## 4 @ConfigurationԼ
+
+@Configurationãעϣspring(Ӧ)
+
+springbeanʹõxmlļһbeanspringbootУΪãspringṩ@Configurationһע
+
+൱ڰѸΪspringxmlļе
+
+@ConfigurationעУʹ@BeanעעķصͶֱעΪbean
+
+@ConfigureעĶ£
+````
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Component
+public @interface Configuration {
+String value() default "";
+}
+````
+ӶײǺ@Component @Configuration к @Component ácontext:component-scan/@ComponentScanܴ@Configurationעࡣ
+
+ͨDZдԶԶʱϣ Spring ʹǡ ǿͨеעʵһ㡣
+
+ǿԽ˲еעͷ@Configuration @Bean ϡ
+
+ڽIJУǽֻÿĻ ˽Ϣƪ¡
+
+### 4.1 @ConditionalOnClass and @ConditionalOnMissingClass
+һжϵע⣬Ҫ֪ܶʱǰbeanģǸⲿjarǷмغжϵġ
+
+ʱҪⲿǷǷǷظbean
+
+ʹЩעͲе/ڣSpring ʹñǵԶ bean
+
+````
+@Configuration
+@ConditionalOnClass(DataSource.class)
+class MySQLAutoconfiguration {
+//...
+}
+````
+
+### 4.2 @ConditionalOnBean and @ConditionalOnMissingBean
+
+Ҫض bean ĴڻʱǿʹЩעͣ
+
+һעЩͬΪǵжbean
+
+````
+@Bean
+@ConditionalOnBean(name = "dataSource")
+LocalContainerEntityManagerFactoryBean entityManagerFactory() {
+// ...
+}
+````
+### 4.3 @ConditionalOnProperty
+ͨע⣬ǿԶԵֵ
+
+Ҫע⣬ֵԴapplication.propertiesļе
+
+````
+@Bean
+@ConditionalOnProperty(
+name = "usemysql",
+havingValue = "local"
+)
+DataSource dataSource() {
+// ...
+}
+````
+
+### 4.4 @ConditionalOnResource
+
+ǿ Spring ڴضԴʱʹö壺
+˼壬ҪclasspathԴļʱŽмأҲǺܳõһע⡣
+
+````
+
+@ConditionalOnResource(resources = "classpath:mysql.properties")
+Properties ditionalProperties() {
+// ...
+}
+````
+
+### 4.5 @ConditionalOnWebApplication and @ConditionalOnNotWebApplication
+עͨںwebǿȫ
+
+ʹЩעͣǿԸݵǰӦóǷ Web Ӧó
+````
+
+@ConditionalOnWebApplication
+HealthCheckController healthCheckController() {
+// ...
+}
+````
+
+### 4.6 @ConditionalExpression
+springbootΪ뵽עҪôɴԼдӦûɣ
+
+ǿڸӵʹע⡣ SpEL ʽΪʱSpring ʹñǵĶ壺
+
+````
+@Bean
+@ConditionalOnExpression("${usemysql} && ${mysqlserver == 'local'}")
+DataSource dataSource() {
+// ...
+}
+````
+
+### 4.7 @Conditional
+ʲô⣿
+springbootҲṩʲôʽˣֱûдһжtruefalse
+
+ڸӵǿԴһԶࡣ Ǹ Spring Զ @Conditional һʹã
+
+````
+@Conditional(HibernateCondition.class)
+Properties ditionalProperties() {
+//...
+}
+````
+
+## 5 ܽ
+ڱУǸԶù̲ΪԶԶ bean ṩ
+
+# ο
+https://www.baeldung.com/spring-annotations
diff --git "a/docs/spring/Spring\344\270\255\345\257\271\344\272\216\346\225\260\346\215\256\345\272\223\347\232\204\350\256\277\351\227\256.md" "b/docs/spring/Spring\344\270\255\345\257\271\344\272\216\346\225\260\346\215\256\345\272\223\347\232\204\350\256\277\351\227\256.md"
new file mode 100644
index 0000000..69bfc96
--- /dev/null
+++ "b/docs/spring/Spring\344\270\255\345\257\271\344\272\216\346\225\260\346\215\256\345\272\223\347\232\204\350\256\277\351\227\256.md"
@@ -0,0 +1,1183 @@
+
+## Դ
+
+### Spring Դ
+
+Spring Դжַʽһһо٣
+
+#### [#](https://dunwu.github.io/spring-tutorial/pages/1b774c/#%E4%BD%BF%E7%94%A8-jndi-%E6%95%B0%E6%8D%AE%E6%BA%90)ʹ JNDI Դ
+
+ Spring Ӧò֧ JNDI WEB ϣ WebSphereJBossTomcat ȣͿʹ JNDI ȡԴ
+
+
+
+```
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+
+
+#### [#](https://dunwu.github.io/spring-tutorial/pages/1b774c/#%E4%BD%BF%E7%94%A8%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5%E6%B1%A0)ʹݿӳ
+
+Spring ûṩݿӳصʵ֣Ҫѡʵݿӳءһʹ [Druid (opens new window)](https://github.com/alibaba/druid)Ϊݿӳصʾ
+
+
+
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+
+
+#### [#](https://dunwu.github.io/spring-tutorial/pages/1b774c/#%E5%9F%BA%E4%BA%8E-jdbc-%E9%A9%B1%E5%8A%A8%E7%9A%84%E6%95%B0%E6%8D%AE%E6%BA%90) JDBC Դ
+
+
+
+```
+
+
+
+
+
+
+```
+
+
+#### ʹJDBC
+
+: 2022/11/16 20:10 / Ķ: 946668
+
+* * *
+
+
+
+ǰ[JDBC](https://www.liaoxuefeng.com/wiki/1252599548343744/1255943820274272)ʱѾJavaʹJDBCӿڷʹϵݿʱҪ¼
+
+* ȫ`DataSource`ʵʾݿӳأ
+* Ҫдݿķڲ²ݿ⣺
+ * ȫ`DataSource`ʵȡ`Connection`ʵ
+ * ͨ`Connection`ʵ`PreparedStatement`ʵ
+ * ִSQL䣬Dzѯͨ`ResultSet`ȡģ`int`
+
+ȷдJDBCĹؼʹ`try ... finally`ͷԴ漰ĴҪȷύع
+
+SpringʹJDBCͨIoCһ`DataSource`ʵȻSpringṩһ`JdbcTemplate`ԷDzJDBCˣͨ£ǻʵһ`JdbcTemplate`˼壬Ҫʹ[Templateģʽ](https://www.liaoxuefeng.com/wiki/1252599548343744/1281319636041762)
+
+дʾ߲ԴʱǿƼʹ[HSQLDB](http://hsqldb.org/)ݿ⣬һJavaдĹϵݿ⣬ڴģʽļģʽУֻһjardzʺʾ߲Դ롣
+
+ʵʹΪȴMaven`spring-data-jdbc`Ȼ
+
+* org.springframework:spring-context:6.0.0
+* org.springframework:spring-jdbc:6.0.0
+* jakarta.annotation:jakarta.annotation-api:2.1.1
+* com.zaxxer:HikariCP:5.0.1
+* org.hsqldb:hsqldb:2.7.1
+
+`AppConfig`УҪ¼Bean
+
+```
+@Configuration
+@ComponentScan
+@PropertySource("jdbc.properties")
+public class AppConfig {
+
+ @Value("${jdbc.url}")
+ String jdbcUrl;
+
+ @Value("${jdbc.username}")
+ String jdbcUsername;
+
+ @Value("${jdbc.password}")
+ String jdbcPassword;
+
+ @Bean
+ DataSource createDataSource() {
+ HikariConfig config = new HikariConfig();
+ config.setJdbcUrl(jdbcUrl);
+ config.setUsername(jdbcUsername);
+ config.setPassword(jdbcPassword);
+ config.addDataSourceProperty("autoCommit", "true");
+ config.addDataSourceProperty("connectionTimeout", "5");
+ config.addDataSourceProperty("idleTimeout", "60");
+ return new HikariDataSource(config);
+ }
+
+ @Bean
+ JdbcTemplate createJdbcTemplate(@Autowired DataSource dataSource) {
+ return new JdbcTemplate(dataSource);
+ }
+}
+
+```
+
+У
+
+1. ͨ`@PropertySource("jdbc.properties")`ȡݿļ
+2. ͨ`@Value("${jdbc.url}")`עļã
+3. һDataSourceʵʵ`HikariDataSource`ʱҪõעã
+4. һJdbcTemplateʵҪע`DataSource`ͨעġ
+
+HSQLDBдһļ`jdbc.properties`
+
+```
+# ݿļΪtestdb:
+jdbc.url=jdbc:hsqldb:file:testdb
+
+# HsqldbĬϵûsaǿַ:
+jdbc.username=sa
+jdbc.password=
+
+```
+
+ͨHSQLDBԴĹʼݿдһBeanSpringʱԶһ`users`
+
+```
+@Component
+public class DatabaseInitializer {
+ @Autowired
+ JdbcTemplate jdbcTemplate;
+
+ @PostConstruct
+ public void init() {
+ jdbcTemplate.update("CREATE TABLE IF NOT EXISTS users (" //
+ + "id BIGINT IDENTITY NOT NULL PRIMARY KEY, " //
+ + "email VARCHAR(100) NOT NULL, " //
+ + "password VARCHAR(100) NOT NULL, " //
+ + "name VARCHAR(100) NOT NULL, " //
+ + "UNIQUE (email))");
+ }
+}
+
+```
+
+ڣϡֻҪҪݿBeanУע`JdbcTemplate`ɣ
+
+```
+@Component
+public class UserService {
+ @Autowired
+ JdbcTemplate jdbcTemplate;
+ ...
+}
+
+```
+
+### JdbcTemplate÷
+
+Springṩ`JdbcTemplate`TemplateģʽṩһϵԻصΪصĹ߷ĿDZⷱ`try...catch`䡣
+
+Ծʾ˵JdbcTemplate÷
+
+ǿ`T execute(ConnectionCallback action)`ṩJdbc`Connection`ʹã
+
+```
+public User getUserById(long id) {
+ // עConnectionCallback:
+ return jdbcTemplate.execute((Connection conn) -> {
+ // ֱʹconnʵҪͷصJdbcTemplateԶͷ:
+ // ڲֶPreparedStatementResultSettry(...)ͷ:
+ try (var ps = conn.prepareStatement("SELECT * FROM users WHERE id = ?")) {
+ ps.setObject(1, id);
+ try (var rs = ps.executeQuery()) {
+ if (rs.next()) {
+ return new User( // new User object:
+ rs.getLong("id"), // id
+ rs.getString("email"), // email
+ rs.getString("password"), // password
+ rs.getString("name")); // name
+ }
+ throw new RuntimeException("user not found by id.");
+ }
+ }
+ });
+}
+
+```
+
+Ҳ˵صȡConnectionȻκλConnectionIJ
+
+ٿ`T execute(String sql, PreparedStatementCallback action)`÷
+
+```
+public User getUserByName(String name) {
+ // ҪSQL䣬ԼPreparedStatementCallback:
+ return jdbcTemplate.execute("SELECT * FROM users WHERE name = ?", (PreparedStatement ps) -> {
+ // PreparedStatementʵѾJdbcTemplateڻصԶͷ:
+ ps.setObject(1, name);
+ try (var rs = ps.executeQuery()) {
+ if (rs.next()) {
+ return new User( // new User object:
+ rs.getLong("id"), // id
+ rs.getString("email"), // email
+ rs.getString("password"), // password
+ rs.getString("name")); // name
+ }
+ throw new RuntimeException("user not found by id.");
+ }
+ });
+}
+
+```
+
+ǿ`T queryForObject(String sql, RowMapper rowMapper, Object... args)`
+
+```
+public User getUserByEmail(String email) {
+ // SQLRowMapperʵ:
+ return jdbcTemplate.queryForObject("SELECT * FROM users WHERE email = ?",
+ (ResultSet rs, int rowNum) -> {
+ // ResultSetĵǰӳΪһJavaBean:
+ return new User( // new User object:
+ rs.getLong("id"), // id
+ rs.getString("email"), // email
+ rs.getString("password"), // password
+ rs.getString("name")); // name
+ },
+ email);
+}
+
+```
+
+`queryForObject()`УSQLԼSQL`JdbcTemplate`Զ`PreparedStatement`Զִвѯ`ResultSet`ṩ`RowMapper`Ҫǰ`ResultSet`ĵǰӳһJavaBeanءУʹ`Connection``PreparedStatement``ResultSet`Ҫֶ
+
+`RowMapper`һJavaBeanʵԷκJava磬ʹ`SELECT COUNT(*)`ѯʱԷ`Long`
+
+```
+public long getUsers() {
+ return jdbcTemplate.queryForObject("SELECT COUNT(*) FROM users", (ResultSet rs, int rowNum) -> {
+ // SELECT COUNT(*)ѯֻһУȡһ:
+ return rs.getLong(1);
+ });
+}
+
+```
+
+ضм¼һУ`query()`
+
+```
+public List getUsers(int pageIndex) {
+ int limit = 100;
+ int offset = limit * (pageIndex - 1);
+ return jdbcTemplate.query("SELECT * FROM users LIMIT ? OFFSET ?",
+ new BeanPropertyRowMapper<>(User.class),
+ limit, offset);
+}
+
+```
+
+`query()`IJȻSQLSQLԼ`RowMapper`ʵֱʹSpringṩ`BeanPropertyRowMapper`ݿĽṹǡúJavaBeanһ£ô`BeanPropertyRowMapper`ͿֱӰһм¼תΪJavaBean
+
+ִеIJDzѯDz롢ºɾôҪʹ`update()`
+
+```
+public void updateUser(User user) {
+ // SQLSQLظµ:
+ if (1 != jdbcTemplate.update("UPDATE users SET name = ? WHERE id = ?", user.getName(), user.getId())) {
+ throw new RuntimeException("User not found by id");
+ }
+}
+
+```
+
+ֻһ`INSERT`Ƚ⣬ǾijһУͨҪȡֵ`JdbcTemplate`ṩһ`KeyHolder`һ
+
+```
+public User register(String email, String password, String name) {
+ // һKeyHolder:
+ KeyHolder holder = new GeneratedKeyHolder();
+ if (1 != jdbcTemplate.update(
+ // 1:PreparedStatementCreator
+ (conn) -> {
+ // PreparedStatementʱָRETURN_GENERATED_KEYS:
+ var ps = conn.prepareStatement("INSERT INTO users(email, password, name) VALUES(?, ?, ?)",
+ Statement.RETURN_GENERATED_KEYS);
+ ps.setObject(1, email);
+ ps.setObject(2, password);
+ ps.setObject(3, name);
+ return ps;
+ },
+ // 2:KeyHolder
+ holder)
+ ) {
+ throw new RuntimeException("Insert failed.");
+ }
+ // KeyHolderлȡصֵ:
+ return new User(holder.getKey().longValue(), email, password, name);
+}
+
+```
+
+`JdbcTemplate`طDzһһܡҪǿǣ`JdbcTemplate`ֻǶJDBCһװĿǾֶд`try(resource) {...}`Ĵ룬ڲѯҪͨ`RowMapper`ʵJDBCJavaת
+
+ܽһ`JdbcTemplate`÷Ǿǣ
+
+* Լѯѡ`query()``queryForObject()`ΪֻṩSQL䡢`RowMapper`
+* Ը²ѡ`update()`ΪֻṩSQLͲ
+* κθӵIJҲͨ`execute(ConnectionCallback)`ʵ֣Ϊõ`Connection`ͿκJDBC
+
+ʵʹȻǸֲѯƱṹʱܹJavaBeanһһӦôֱʹ`BeanPropertyRowMapper`ͺܷ㡣ṹJavaBeanһô죿ǾҪдһ²ѯʹĽṹJavaBeanһ¡
+
+磬`office_address`JavaBean`workAddress`Ҫָдѯ£
+
+```
+SELECT id, email, office_address AS workAddress, name FROM users WHERE email = ?
+```
+
+ʹ`JdbcTemplate`ʱõķ`List query(String, RowMapper, Object...)``RowMapper`þǰ`ResultSet`һм¼ӳΪJava Bean
+
+ְѹϵݿı¼ӳΪJavaĹ̾ORMObject-Relational MappingORMȿѼ¼תJavaҲJavaתΪм¼
+
+ʹ`JdbcTemplate``RowMapper`ԿԭʼORMҪʵָԶORMѡORMܣ[Hibernate](https://hibernate.org/)
+
+SpringмHibernate
+
+HibernateΪORMܣ`JdbcTemplate`HibernateȻҪJDBCԣҪJDBCӳأԼHibernateMavenУǼ
+
+* org.springframework:spring-context:6.0.0
+* org.springframework:spring-orm:6.0.0
+* jakarta.annotation:jakarta.annotation-api:2.1.1
+* jakarta.persistence:jakarta.persistence-api:3.1.0
+* org.hibernate:hibernate-core:6.1.4.Final
+* com.zaxxer:HikariCP:5.0.1
+* org.hsqldb:hsqldb:2.7.1
+
+`AppConfig`УȻҪ`DataSource`JDBCļԼʽ
+
+```
+@Configuration
+@ComponentScan
+@EnableTransactionManagement
+@PropertySource("jdbc.properties")
+public class AppConfig {
+ @Bean
+ DataSource createDataSource() {
+ ...
+ }
+}
+
+```
+
+ΪHibernateҪһ`LocalSessionFactoryBean`
+
+```
+public class AppConfig {
+ @Bean
+ LocalSessionFactoryBean createSessionFactory(@Autowired DataSource dataSource) {
+ var props = new Properties();
+ props.setProperty("hibernate.hbm2ddl.auto", "update"); // Ҫʹ
+ props.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
+ props.setProperty("hibernate.show_sql", "true");
+ var sessionFactoryBean = new LocalSessionFactoryBean();
+ sessionFactoryBean.setDataSource(dataSource);
+ // ɨָpackageȡentity class:
+ sessionFactoryBean.setPackagesToScan("com.itranswarp.learnjava.entity");
+ sessionFactoryBean.setHibernateProperties(props);
+ return sessionFactoryBean;
+ }
+}
+
+```
+
+ע[Bean](https://www.liaoxuefeng.com/wiki/1252599548343744/1308043627200545)н`FactoryBean``LocalSessionFactoryBean`һ`FactoryBean`Զһ`SessionFactory`HibernateУ`Session`ǷװһJDBC `Connection`ʵ`SessionFactory`ǷװJDBC `DataSource`ʵ`SessionFactory`ӳأÿҪݿʱ`SessionFactory`һµ`Session`൱ڴӳػȡһµ`Connection``SessionFactory`Hibernateṩĵһ`LocalSessionFactoryBean`SpringṩΪǷ㴴`SessionFactory`ࡣ
+
+ע洴`LocalSessionFactoryBean`Ĵ룬`Properties`Hibernateʼ`SessionFactory`ʱõãõο[Hibernateĵ](https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#configurations)ֻ3ã
+
+* `hibernate.hbm2ddl.auto=update`ʾԶݿıṹעⲻҪã
+* `hibernate.dialect=org.hibernate.dialect.HSQLDialect`ָʾHibernateʹõݿHSQLDBHibernateʹһHQLIJѯ䣬SQLƣڡ롱SQLʱ趨ݿ⡰ԡݿŻSQL
+* `hibernate.show_sql=true`HibernateӡִеSQLڵԷdzãǿԷؿHibernateɵSQLǷǵԤڡ
+
+`DataSource``Properties`֮⣬ע`setPackagesToScan()`Ǵһ`package`ƣָʾHibernateɨJava࣬ԶҳӳΪݿ¼JavaBeanǻϸαдHibernateҪJavaBean
+
+ţǻҪ`HibernateTransactionManager`
+
+```
+public class AppConfig {
+ @Bean
+ PlatformTransactionManager createTxManager(@Autowired SessionFactory sessionFactory) {
+ return new HibernateTransactionManager(sessionFactory);
+ }
+}
+
+```
+
+`HibernateTransactionManager`HibernateʹʽġΪֹеöϣνݿṹӳΪJava
+
+µݿ
+
+```
+CREATE TABLE user
+ id BIGINT NOT NULL AUTO_INCREMENT,
+ email VARCHAR(100) NOT NULL,
+ password VARCHAR(100) NOT NULL,
+ name VARCHAR(100) NOT NULL,
+ createdAt BIGINT NOT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `email` (`email`)
+);
+
+```
+
+У`id``email``password``name``VARCHAR`ͣ`email`ΨһȷΨһԣ`createdAt`洢͵ʱJavaBeanʾ£
+
+```
+public class User {
+ private Long id;
+ private String email;
+ private String password;
+ private String name;
+ private Long createdAt;
+
+ // getters and setters
+ ...
+}
+
+```
+
+ӳϵʮҪһЩעHibernateΰ`User`ӳ䵽¼
+
+```
+@Entity
+public class User {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(nullable = false, updatable = false)
+ public Long getId() { ... }
+
+ @Column(nullable = false, unique = true, length = 100)
+ public String getEmail() { ... }
+
+ @Column(nullable = false, length = 100)
+ public String getPassword() { ... }
+
+ @Column(nullable = false, length = 100)
+ public String getName() { ... }
+
+ @Column(nullable = false, updatable = false)
+ public Long getCreatedAt() { ... }
+}
+
+```
+
+һJavaBeanӳ䣬Ǿͱһ`@Entity`Ĭ£ӳı`user`ʵʵıͬʵʱ`users`һ`@Table(name="users")`ʾ
+
+```
+@Entity
+@Table(name="users)
+public class User {
+ ...
+}
+
+```
+
+ÿԵݿеӳ`@Column()`ʶ`nullable`ָʾǷΪ`NULL``updatable`ָʾǷ`UPDATE`䣬`length`ָʾ`String`͵еijȣûָĬ`255`
+
+Ҫ`@Id`ʶһ`@GeneratedValue`ԱHibernateܶȡֵ
+
+ϸĵͯЬܻע`id`Ͳ`long``Long`ΪHibernateΪ`null`Ͳ`INSERT`ֵָǷݿɵֵHibernateΪǵijֵָ`INSERT`ֱг`long`ֶǾĬֵ`0`ˣÿβֵ0³һ붼ʧܡ
+
+`createdAt`ȻͣDzûʹ`long``Long`ΪʹûͻᵼfindByExampleѯֻμǣΪӳʹõJavaBeanԶʹðװͶǻ͡
+
+ʹHibernateʱҪʹû͵ԣʹðװͣLongInteger
+
+Ƶģٶһ`Book`ࣺ
+
+```
+@Entity
+public class Book {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(nullable = false, updatable = false)
+ public Long getId() { ... }
+
+ @Column(nullable = false, length = 100)
+ public String getTitle() { ... }
+
+ @Column(nullable = false, updatable = false)
+ public Long getCreatedAt() { ... }
+}
+
+```
+
+ϸ۲`User``Book`ᷢǶ`id``createdAt`һģݿṹкܳÿͨǻͳһʹһɻƣ`createdAt`ʾʱ䣬`updatedAt`ʾʱֶͨΡ
+
+`User``Book`ظЩֶͨΣǿᵽһУ
+
+```
+@MappedSuperclass
+public abstract class AbstractEntity {
+
+ private Long id;
+ private Long createdAt;
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(nullable = false, updatable = false)
+ public Long getId() { ... }
+
+ @Column(nullable = false, updatable = false)
+ public Long getCreatedAt() { ... }
+
+ @Transient
+ public ZonedDateTime getCreatedDateTime() {
+ return Instant.ofEpochMilli(this.createdAt).atZone(ZoneId.systemDefault());
+ }
+
+ @PrePersist
+ public void preInsert() {
+ setCreatedAt(System.currentTimeMillis());
+ }
+}
+
+```
+
+`AbstractEntity`˵Ҫעһ`@MappedSuperclass`ʾڼ̳С⣬עǶһ`@Transient`һ⡱ԡΪ`getCreatedDateTime()`ǼóԣǴݿֵ˱Ҫע`@Transient`Hibernate᳢ԴݿȡΪ`createdDateTime`ڵֶδӶ
+
+ע`@PrePersist`ʶķʾǽһJavaBean־ûݿ֮ǰִINSERT䣩Hibernateִи÷ǾͿԶú`createdAt`ԡ
+
+`AbstractEntity`ǾͿԴ`User``Book`
+
+```
+@Entity
+public class User extends AbstractEntity {
+
+ @Column(nullable = false, unique = true, length = 100)
+ public String getEmail() { ... }
+
+ @Column(nullable = false, length = 100)
+ public String getPassword() { ... }
+
+ @Column(nullable = false, length = 100)
+ public String getName() { ... }
+}
+
+```
+
+עʹõע`jakarta.persistence`JPA淶һֻ֡ʹעķʽHibernateӳϵٽܴͳıȽϷXMLáͨSpringHibernateʱҲҪ`hibernate.cfg.xml`ļһ仰ܽ
+
+ʹSpringHibernateJPAע⣬κζXMLá
+
+`User``Book`ORMJava Bean֮ͨΪEntity Bean
+
+`user`ɾIJ顣ΪʹHibernateˣҪģʵǶ`User`JavaBeanСɾIJ顱DZдһ`UserService`ע`SessionFactory`
+
+```
+@Component
+@Transactional
+public class UserService {
+ @Autowired
+ SessionFactory sessionFactory;
+}
+
+```
+
+### Insert
+
+Ҫ־ûһ`User`ʵֻ`persist()``register()`Ϊ£
+
+```
+public User register(String email, String password, String name) {
+ // һUser:
+ User user = new User();
+ // úø:
+ user.setEmail(email);
+ user.setPassword(password);
+ user.setName(name);
+ // ҪidΪʹ
+ // 浽ݿ:
+ sessionFactory.getCurrentSession().persist(user);
+ // ѾԶid:
+ System.out.println(user.getId());
+ return user;
+}
+
+```
+
+### Delete
+
+ɾһ`User`൱ڴӱɾӦļ¼עHibernate`id`ɾ¼ˣҪȷ`User``id`Բɾ¼
+
+```
+public boolean deleteUser(Long id) {
+ User user = sessionFactory.getCurrentSession().byId(User.class).load(id);
+ if (user != null) {
+ sessionFactory.getCurrentSession().remove(user);
+ return true;
+ }
+ return false;
+}
+
+```
+
+ͨɾ¼ʱһ÷ȸظü¼ɾע¼ʱ`load()``null`
+
+### Update
+
+¼¼൱ȸ`User`ָԣȻ`merge()`
+
+```
+public void updateUser(Long id, String name) {
+ User user = sessionFactory.getCurrentSession().byId(User.class).load(id);
+ user.setName(name);
+ sessionFactory.getCurrentSession().merge(user);
+}
+
+```
+
+ǰڶ`User`ʱеԱע`@Column(updatable=false)`Hibernateڸ¼¼ʱֻ`@Column(updatable=true)`Լ뵽`UPDATE`УṩһİȫԣС`User``email``createdAt`ԣִ`update()`ʱ¶ӦݿСҲμǣHibernateṩģƹHibernateֱͨJDBCִ`UPDATE`ȻԸݿеֵ
+
+DZдĴַǸָIJѯ`id`ѯǿֱӵ`load()`Ҫʹѯ磬ִ²ѯ
+
+```
+SELECT * FROM user WHERE email = ? AND password = ?
+
+```
+
+ʹʲôѯ
+
+### ʹHQLѯ
+
+һֳõIJѯֱӱдHibernateõHQLѯ
+
+```
+List list = sessionFactory.getCurrentSession()
+ .createQuery("from User u where u.email = ?1 and u.password = ?2", User.class)
+ .setParameter(1, email).setParameter(2, password)
+ .list();
+
+```
+
+SQLȣHQLʹHibernateԶתΪʵʵıϸHQLԲο[Hibernateĵ](https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#query-language)
+
+˿ֱӴHQLַ⣬Hibernateʹһ`NamedQuery`ѯ֣ȻעСʹ`NamedQuery`ʱҪ`User`ע
+
+```
+@NamedQueries(
+ @NamedQuery(
+ // ѯ:
+ name = "login",
+ // ѯ:
+ query = "SELECT u FROM User u WHERE u.email = :e AND u.password = :pwd"
+ )
+)
+@Entity
+public class User extends AbstractEntity {
+ ...
+}
+
+```
+
+ע`NamedQuery``jakarta.persistence.NamedQuery`ֱӴHQLе㲻ͬǣռλʹ`:e``:pwd`
+
+ʹ`NamedQuery`ֻҪѯͲ
+
+```
+public User login(String email, String password) {
+ List list = sessionFactory.getCurrentSession()
+ .createNamedQuery("login", User.class) // NamedQuery
+ .setParameter("e", email) // e
+ .setParameter("pwd", password) // pwd
+ .list();
+ return list.isEmpty() ? null : list.get(0);
+}
+
+```
+
+ֱдHQLʹ`NamedQuery`ӡǰ߿ڴֱ۵ؿѯ䣬߿`User`ͳһزѯ
+
+һǽSpringмHibernateHibernateǵһ㷺ʹõORMܣǺܶС黹˵JPAJava Persistence APIɶ
+
+JPA֮ǰҪעJavaEE1999ͷˣServletJMSƽ̨ͬJavaڷdzڱУҸѽӿڶˣȻԻؼҸɻȥʵֽӿڣûͿڲͬijṩIJƷѡлΪûдʱֻҪýӿڣҪþĵײʵ֣JDBC
+
+JPAJavaEEһORMʵʵHibernateûɶ𣬵ûʹJPAôõľ`jakarta.persistence``org.hibernate`ĵΪJPAֻǽӿڣԣҪѡһʵֲƷJDBCӿںMySQLһ
+
+ʹJPAʱҲȫѡHibernateΪײʵ֣ҲѡJPAṩ[EclipseLink](https://www.eclipse.org/eclipselink/)SpringJPAļɣ֧ѡHibernateEclipseLinkΪʵ֡ȻHibernateΪJPAʵΪӣʾJPAĻ÷
+
+ʹHibernateһֻҪ
+
+* org.springframework:spring-context:6.0.0
+* org.springframework:spring-orm:6.0.0
+* jakarta.annotation:jakarta.annotation-api:2.1.1
+* jakarta.persistence:jakarta.persistence-api:3.1.0
+* org.hibernate:hibernate-core:6.1.4.Final
+* com.zaxxer:HikariCP:5.0.1
+* org.hsqldb:hsqldb:2.7.1
+
+ʵһڼHibernateȫһΪHibernateṩԼĽӿڣҲṩJPAӿڣJPAӿھ൱ͨJPAHibernate
+
+Ȼ`AppConfig`ʽ`DataSource`
+
+```
+@Configuration
+@ComponentScan
+@EnableTransactionManagement
+@PropertySource("jdbc.properties")
+public class AppConfig {
+ @Bean
+ DataSource createDataSource() { ... }
+}
+
+```
+
+ʹHibernateʱҪһ`LocalSessionFactoryBean`Զһ`SessionFactory`ʹJPAҲƵģҲһ`LocalContainerEntityManagerFactoryBean`Զһ`EntityManagerFactory`
+
+```
+@Bean
+public LocalContainerEntityManagerFactoryBean createEntityManagerFactory(@Autowired DataSource dataSource) {
+ var emFactory = new LocalContainerEntityManagerFactoryBean();
+ // עDataSource:
+ emFactory.setDataSource(dataSource);
+ // ɨָpackageȡentity class:
+ emFactory.setPackagesToScan(AbstractEntity.class.getPackageName());
+ // ʹHibernateΪJPAʵ:
+ emFactory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
+ // :
+ var props = new Properties();
+ props.setProperty("hibernate.hbm2ddl.auto", "update"); // Ҫʹ
+ props.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
+ props.setProperty("hibernate.show_sql", "true");
+ emFactory.setJpaProperties(props);
+ return emFactory;
+}
+
+```
+
+۲룬Ҫע`DataSource`趨Զɨ`package`⣬ҪָJPAṩ̣ʹSpringṩһ`HibernateJpaVendorAdapter`HibernateԼҪã`Properties`ʽע롣
+
+ǻҪʵһ`JpaTransactionManager`ʵʽ
+
+```
+@Bean
+PlatformTransactionManager createTxManager(@Autowired EntityManagerFactory entityManagerFactory) {
+ return new JpaTransactionManager(entityManagerFactory);
+}
+
+```
+
+ǾJPAȫʼЩͯЬܴ֪JPAҪ`persistence.xml`ļԼӵ`orm.xml`ļǸظߴңʹSpring+HibernateΪJPAʵ֣κļ
+
+Entity BeanúһȫͬȫAnnotationעֻľҵͨJPAӿڲݿ⡣
+
+`UserService`Ϊ˱ע`@Component``@Transactional`⣬Ҫעһ`EntityManager`DzҪʹ`Autowired``@PersistenceContext`
+
+```
+@Component
+@Transactional
+public class UserService {
+ @PersistenceContext
+ EntityManager em;
+}
+
+```
+
+ǻعһJDBCHibernateJPAṩĽӿڣʵϣǵĹϵ£
+
+| JDBC | Hibernate | JPA |
+| --- | --- | --- |
+| DataSource | SessionFactory | EntityManagerFactory |
+| Connection | Session | EntityManager |
+
+`SessionFactory``EntityManagerFactory`൱`DataSource``Session``EntityManager`൱`Connection`ÿҪݿʱҪȡµ`Session``EntityManager`ٹرա
+
+ǣע`UserService`עIJ`EntityManagerFactory``EntityManager`ұע`@PersistenceContext`ѵʹJPA̲߳ͬһ`EntityManager`
+
+ʵעIJ`EntityManager`һ`EntityManager`Ĵ࣬൱ڣ
+
+```
+public class EntityManagerProxy implements EntityManager {
+ private EntityManagerFactory emf;
+}
+
+```
+
+Springע`@PersistenceContext``EntityManager`ԶעôڱҪʱԶ`EntityManager`仰˵߳õ`EntityManager`Ȼͬһ࣬ôڲԲ̻ͬ߳ᴴͬ`EntityManager`ʵ
+
+ܽһ£ע`@PersistenceContext``EntityManager`Ա̰߳ȫع
+
+ˣ`UserService`ÿҵֱʹ`EntityManager`ͺܷ㡣ѯΪ
+
+```
+public User getUserById(long id) {
+ User user = this.em.find(User.class, id);
+ if (user == null) {
+ throw new RuntimeException("User not found by id: " + id);
+ }
+ return user;
+}
+
+```
+
+HQLѯƣJPAʹJPQLѯHQLࣺ
+
+```
+public User fetchUserByEmail(String email) {
+ // JPQLѯ:
+ TypedQuery query = em.createQuery("SELECT u FROM User u WHERE u.email = :e", User.class);
+ query.setParameter("e", email);
+ List list = query.getResultList();
+ if (list.isEmpty()) {
+ return null;
+ }
+ return list.get(0);
+}
+
+```
+
+ͬģJPAҲ֧`NamedQuery`ȸѯִٰ֣ѯ
+
+```
+public User login(String email, String password) {
+ TypedQuery query = em.createNamedQuery("login", User.class);
+ query.setParameter("e", email);
+ query.setParameter("pwd", password);
+ List list = query.getResultList();
+ return list.isEmpty() ? null : list.get(0);
+}
+
+```
+
+`NamedQuery`ͨעע`User`ϣĶһڵ`User`һ
+
+```
+@NamedQueries(
+ @NamedQuery(
+ name = "login",
+ query = "SELECT u FROM User u WHERE u.email=:e AND u.password=:pwd"
+ )
+)
+@Entity
+public class User {
+ ...
+}
+
+```
+
+ݿɾĵIJԷֱʹ`persist()``remove()``merge()`ΪEntity Beanʹ÷dzﲻٶ
+
+#### MyBatis
+
+: 2022/11/16 21:07 / Ķ: 601258
+
+* * *
+
+
+
+ʹHibernateJPAݿʱORMɵҪǰResultSetÿһбJava Bean߰Java BeanԶתINSERTUPDATEIJУӶʵORM
+
+ORM֪֮ΰӳ䵽Java BeanΪJava Beanϸ㹻עΪԪݣORMܻȡJava Beanע֪ν˫ӳ䡣
+
+ôORMθJava BeanģԱ`update()`и±Ҫԣ
+
+ʹ[Proxyģʽ](https://www.liaoxuefeng.com/wiki/1252599548343744/1281319432618017)ORMܶȡUserʵʵϲUser࣬Ǵ̳࣬User࣬ÿsetter˸д
+
+```
+public class UserProxy extends User {
+ boolean _isNameChanged;
+
+ public void setName(String name) {
+ super.setName(name);
+ _isNameChanged = true;
+ }
+}
+
+```
+
+ԸٵÿԵı仯
+
+һԶһϵʱֱͨgetterѯݿ⣺
+
+```
+public class UserProxy extends User {
+ Session _session;
+ boolean _isNameChanged;
+
+ public void setName(String name) {
+ super.setName(name);
+ _isNameChanged = true;
+ }
+
+ /**
+ * ȡUserAddress:
+ */
+ public Address getAddress() {
+ Query q = _session.createQuery("from Address where userId = :userId");
+ q.setParameter("userId", this.getId());
+ List list = query.list();
+ return list.isEmpty() ? null : list(0);
+ }
+}
+
+```
+
+ΪʵIJѯUserProxy뱣HibernateĵǰSessionǣύSessionԶرգʱٻȡ`getAddress()`ݿ⣬ȡIJһµݡˣORMAttached/Detached״̬ʾǰJava BeanSessionķΧڣSessionһ롱ܶѧȷ״̬仯߽磬ͻɴ`PersistentObjectException`쳣ʽ״̬ʹͨJava Beanڱøӡ
+
+⣬HibernateJPAΪʵּݶݿ⣬ʹHQLJPQLѯһתضݿSQLлݿ⣬һԶתܿ⣬SQLŻ鷳
+
+ORMͨṩ˻棬һΪһͶ档һָһSessionΧڵĻ棬龰ǸѯʱβѯԷͬһʵ
+
+```
+User user1 = session.load(User.class, 123);
+User user2 = session.load(User.class, 123);
+
+```
+
+ָSessionĻ棬һĬϹرգҪֶá漫ݵIJһԣԭSQLdzᵼĸ¡磺
+
+```
+// ߳1ȡ:
+User user1 = session1.load(User.class, 123);
+...
+// һʱ߳2ȡ:
+User user2 = session2.load(User.class, 123);
+
+```
+
+Чʱ̶߳ȡUserʵһģǣݿӦм¼ȫܱģ磺
+
+```
+-- û100:
+UPDATE users SET bonus = bonus + 100 WHERE createdAt <= ?
+
+```
+
+ORMж`id=123`ûǷܸ`UPDATE`Ӱ졣ǵݿֶ֧ͨӦóUPDATEִУORMܾ֪ˡ
+
+ǰORM֮ܳΪȫԶORMܡ
+
+ԱSpringṩJdbcTemplateORMȣҪм
+
+1. ѯҪֶṩMapperʵԱResultSetÿһбΪJava
+2. ɾIJIJбҪֶ룬UserʵΪ[user.id, user.name, user.email]бȽ鷳
+
+JdbcTemplateȷԣÿζȡһݿǻ棬ִеSQLȫȷģȱǴȽϷ`INSERT INTO users VALUES (?,?,?)`Ǹӡ
+
+ԣȫԶORMHibernateдȫJdbcTemplate֮䣬һְԶORMֻResultSetԶӳ䵽Java BeanԶJava BeanԼдSQL[MyBatis](https://mybatis.org/)һְԶORMܡ
+
+SpringмMyBatis
+
+ȣҪMyBatisΣSpringûHibernateöMyBatisļɣԣҪMyBatisٷԼһSpringɵĿ⣺
+
+* org.mybatis:mybatis:3.5.11
+* org.mybatis:mybatis-spring:3.0.0
+
+ǰһȴ`DataSource`DZزٵģ
+
+```
+@Configuration
+@ComponentScan
+@EnableTransactionManagement
+@PropertySource("jdbc.properties")
+public class AppConfig {
+ @Bean
+ DataSource createDataSource() { ... }
+}
+
+```
+
+ٻعһHibernateJPA`SessionFactory``EntityManagerFactory`MyBatis֮Ӧ`SqlSessionFactory``SqlSession`
+
+| JDBC | Hibernate | JPA | MyBatis |
+| --- | --- | --- | --- |
+| DataSource | SessionFactory | EntityManagerFactory | SqlSessionFactory |
+| Connection | Session | EntityManager | SqlSession |
+
+ɼORM·ƵġʹMyBatisĺľǴ`SqlSessionFactory`Ҫ`SqlSessionFactoryBean`
+
+```
+@Bean
+SqlSessionFactoryBean createSqlSessionFactoryBean(@Autowired DataSource dataSource) {
+ var sqlSessionFactoryBean = new SqlSessionFactoryBean();
+ sqlSessionFactoryBean.setDataSource(dataSource);
+ return sqlSessionFactoryBean;
+}
+
+```
+
+ΪMyBatisֱʹSpringʽˣʹJDBCһģ
+
+```
+@Bean
+PlatformTransactionManager createTxManager(@Autowired DataSource dataSource) {
+ return new DataSourceTransactionManager(dataSource);
+}
+
+```
+
+HibernateͬǣMyBatisʹMapperʵӳ䣬Mapperǽӿڡ`User`Ϊ`User``users`֮ӳ`UserMapper`д£
+
+```
+public interface UserMapper {
+ @Select("SELECT * FROM users WHERE id = #{id}")
+ User getById(@Param("id") long id);
+}
+
+```
+
+ע⣺Mapper`JdbcTemplate``RowMapper`ĸǶ`users`ĽӿڷǶһ`User getById(long)`ѯҪӿڷҪȷдѯSQLע`@Select`ǡSQLκβ뷽ƶӦ磬idͨע`@Param()`Ϊ`id`SQLォ滻ռλ`#{id}`
+
+жôÿֱSQLдӦռλɣ
+
+```
+@Select("SELECT * FROM users LIMIT #{offset}, #{maxResults}")
+List getAll(@Param("offset") int offset, @Param("maxResults") int maxResults);
+
+```
+
+ע⣺MyBatisִвѯݷķԶResultSetÿһתΪUserʵתȻǰӦͬķʽDZдSELECTı
+
+```
+-- created_timecreatedAt:
+SELECT id, name, email, created_time AS createdAt FROM users
+
+```
+
+ִINSERT鷳㣬ΪϣUserʵˣķӿ`@Insert`ע£
+
+```
+@Insert("INSERT INTO users (email, password, name, createdAt) VALUES (#{user.email}, #{user.password}, #{user.name}, #{user.createdAt})")
+void insert(@Param("user") User user);
+
+```
+
+IJ`user`User࣬SQLõʱ`#{obj.property}`ķʽдռλHibernateȫԶORMȣMyBatisдINSERT䡣
+
+`users``id`ôSQLв`id`ϣȡҪټһ`@Options`ע⣺
+
+```
+@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
+@Insert("INSERT INTO users (email, password, name, createdAt) VALUES (#{user.email}, #{user.password}, #{user.name}, #{user.createdAt})")
+void insert(@Param("user") User user);
+
+```
+
+`keyProperty``keyColumn`ֱָJavaBeanԺݿ
+
+ִ`UPDATE``DELETE`ԱȽϼǶ巽£
+
+```
+@Update("UPDATE users SET name = #{user.name}, createdAt = #{user.createdAt} WHERE id = #{user.id}")
+void update(@Param("user") User user);
+
+@Delete("DELETE FROM users WHERE id = #{id}")
+void deleteById(@Param("id") long id);
+
+```
+
+`UserMapper`ӿڣҪӦʵִЩݿķȻԼдʵ࣬dz˱д`UserMapper`ӿ⣬`BookMapper``BonusMapper`һһд̫鷳ˣMyBatisṩһ`MapperFactoryBean`ԶMapperʵࡣһע
+
+```
+@MapperScan("com.itranswarp.learnjava.mapper")
+...ע...
+public class AppConfig {
+ ...
+}
+
+```
+
+`@MapperScan`ͿMyBatisԶɨָMapperʵࡣҵУǿֱע룺
+
+```
+@Component
+@Transactional
+public class UserService {
+ // עUserMapper:
+ @Autowired
+ UserMapper userMapper;
+
+ public User getUserById(long id) {
+ // Mapper:
+ User user = userMapper.getById(id);
+ if (user == null) {
+ throw new RuntimeException("User not found by id.");
+ }
+ return user;
+ }
+}
+
+```
+
+ɼҵҪͨ`XxxMapper`ݿⷽݿ⡣
+
+### XML
+
+SpringмMyBatisķʽֻҪõע⣬ûκXMLļMyBatisҲʹXMLӳϵSQL䣬磬`User`ʱֵ춯̬SQL
+
+```
+
+ UPDATE users SET
+
+ name = #{user.name}
+ hobby = #{user.hobby}
+ summary = #{user.summary}
+
+ WHERE id = #{user.id}
+
+
+```
+
+дXMLõŵǿװ̬SQLҰSQLһȱ̫÷ʱ鿴SQLҪλXMLСDzXML÷ʽҪ˽ͯЬĶ[ٷĵ](https://mybatis.org/mybatis-3/zh/configuration.html)
+
+ʹMyBatisSQLҪȫдŵִеSQLԼдSQLSQLŻdzҲԱд⸴ӵSQLʹݿضлݿܾͲ̫סϢǴĿûлݿȫijݿдŻSQL
+
+# ο
+https://www.w3cschool.cn/wkspring
+https://www.runoob.com/w3cnote/basic-knowledge-summary-of-spring.html
+http://codepub.cn/2015/06/21/Basic-knowledge-summary-of-Spring
+https://dunwu.github.io/spring-tutorial
+https://mszlu.com/java/spring
+http://c.biancheng.net/spring/aop-module.html
\ No newline at end of file
diff --git "a/docs/spring/Spring\344\270\255\345\257\271\344\272\216\346\240\241\351\252\214\345\212\237\350\203\275\347\232\204\346\224\257\346\214\201.md" "b/docs/spring/Spring\344\270\255\345\257\271\344\272\216\346\240\241\351\252\214\345\212\237\350\203\275\347\232\204\346\224\257\346\214\201.md"
new file mode 100644
index 0000000..a77e4a0
--- /dev/null
+++ "b/docs/spring/Spring\344\270\255\345\257\271\344\272\216\346\240\241\351\252\214\345\212\237\350\203\275\347\232\204\346\224\257\346\214\201.md"
@@ -0,0 +1,715 @@
+# Spring У
+
+
+
+Java API 淶(`JSR303`)`Bean`Уı`validation-api`ûṩʵ֡`hibernate validation`Ƕ淶ʵ֣Уע`@Email``@Length`ȡ`Spring Validation`Ƕ`hibernate validation`Ķηװ֧`spring mvc`ԶУ顣
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/fe6aad/#%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8)
+
+### [#](https://dunwu.github.io/spring-tutorial/pages/fe6aad/#%E5%BC%95%E5%85%A5%E4%BE%9D%E8%B5%96)
+
+ spring-boot 汾С 2.3.xspring-boot-starter-web Զ hibernate-validator spring-boot 汾 2.3.xҪֶ
+
+
+
+```
+
+ org.hibernate.validator
+ hibernate-validator-parent
+ 6.2.5.Final
+
+
+```
+
+
+
+ web ˵ΪֹǷҵӰ죬 Controller һҪУģ£Ϊʽ
+
+* POSTPUT ʹ requestBody ݲ
+* GET ʹ requestParam/PathVariable ݲ
+
+ʵϣ requestBody У黹ǷУ飬նǵ Hibernate Validator ִУ飬Spring Validation ֻһװ
+
+### [#](https://dunwu.github.io/spring-tutorial/pages/fe6aad/#%E6%A0%A1%E9%AA%8C%E7%A4%BA%E4%BE%8B)Уʾ
+
+1ʵϱУע
+
+
+
+```
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class User implements Serializable {
+
+ @NotNull
+ private Long id;
+
+ @NotBlank
+ @Size(min = 2, max = 10)
+ private String name;
+
+ @Min(value = 1)
+ @Max(value = 100)
+ private Integer age;
+
+}
+
+```
+
+
+
+2ڷУע
+
+
+
+```
+@Slf4j
+@Validated
+@RestController
+@RequestMapping("validate1")
+public class ValidatorController {
+
+ /**
+ * {@link RequestBody} У
+ */
+ @PostMapping(value = "save")
+ public DataResult save(@Valid @RequestBody User entity) {
+ log.info("һ¼{}", JSONUtil.toJsonStr(entity));
+ return DataResult.ok(true);
+ }
+
+ /**
+ * {@link RequestParam} У
+ */
+ @GetMapping(value = "queryByName")
+ public DataResult queryByName(
+ @RequestParam("username")
+ @NotBlank
+ @Size(min = 2, max = 10)
+ String name
+ ) {
+ User user = new User(1L, name, 18);
+ return DataResult.ok(user);
+ }
+
+ /**
+ * {@link PathVariable} У
+ */
+ @GetMapping(value = "detail/{id}")
+ public DataResult detail(@PathVariable("id") @Min(1L) Long id) {
+ User user = new User(id, "", 18);
+ return DataResult.ok(user);
+ }
+
+}
+
+```
+
+
+
+3У׳?`ConstraintViolationException`??`MethodArgumentNotValidException`?쳣
+
+### [#](https://dunwu.github.io/spring-tutorial/pages/fe6aad/#%E7%BB%9F%E4%B8%80%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86)ͳһ쳣
+
+ʵĿУͨͳһ쳣һѺõʾ
+
+
+
+```
+@Slf4j
+@ControllerAdvice
+public class GlobalExceptionHandler {
+
+ /**
+ * в֪쳣
+ */
+ @ResponseBody
+ @ResponseStatus(HttpStatus.OK)
+ @ExceptionHandler(Throwable.class)
+ public Result handleException(Throwable e) {
+ log.error("δ֪쳣", e);
+ return new Result(ResultStatus.HTTP_SERVER_ERROR.getCode(), e.getMessage());
+ }
+
+ /**
+ * ͳһУ쳣(ͨ)
+ *
+ * @param e ConstraintViolationException
+ * @return {@link DataResult}
+ */
+ @ResponseBody
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ExceptionHandler({ ConstraintViolationException.class })
+ public Result handleConstraintViolationException(final ConstraintViolationException e) {
+ log.error("ConstraintViolationException", e);
+ List errors = new ArrayList<>();
+ for (ConstraintViolation> violation : e.getConstraintViolations()) {
+ Path path = violation.getPropertyPath();
+ List pathArr = StrUtil.split(path.toString(), ',');
+ errors.add(pathArr.get(0) + " " + violation.getMessage());
+ }
+ return new Result(ResultStatus.REQUEST_ERROR.getCode(), CollectionUtil.join(errors, ","));
+ }
+
+ /**
+ * У쳣
+ *
+ * @param e MethodArgumentNotValidException
+ * @return {@link DataResult}
+ */
+ @ResponseBody
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ExceptionHandler({ MethodArgumentNotValidException.class })
+ private Result handleMethodArgumentNotValidException(final MethodArgumentNotValidException e) {
+ log.error("MethodArgumentNotValidException", e);
+ List errors = new ArrayList<>();
+ for (ObjectError error : e.getBindingResult().getAllErrors()) {
+ errors.add(((FieldError) error).getField() + " " + error.getDefaultMessage());
+ }
+ return new Result(ResultStatus.REQUEST_ERROR.getCode(), CollectionUtil.join(errors, ","));
+ }
+
+}
+
+```
+
+
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/fe6aad/#%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8)ʹ
+
+### [#](https://dunwu.github.io/spring-tutorial/pages/fe6aad/#%E5%88%86%E7%BB%84%E6%A0%A1%E9%AA%8C)У
+
+ʵĿУܶҪʹͬһ DTO ղͬУܿDzһġʱ DTO ֶϼԼע⡣ˣspring-validation ֧˷УĹܣר⡣
+
+1
+
+
+
+```
+@Target({ ElementType.FIELD, ElementType.PARAMETER })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface AddCheck { }
+
+@Target({ ElementType.FIELD, ElementType.PARAMETER })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface EditCheck { }
+
+```
+
+
+
+2ʵϱУע
+
+
+
+```
+@Data
+public class User2 {
+
+ @NotNull(groups = EditCheck.class)
+ private Long id;
+
+ @NotNull(groups = { AddCheck.class, EditCheck.class })
+ @Size(min = 2, max = 10, groups = { AddCheck.class, EditCheck.class })
+ private String name;
+
+ @IsMobile(message = "Чֻ", groups = { AddCheck.class, EditCheck.class })
+ private String mobile;
+
+}
+
+```
+
+
+
+3ڷϸݲͬУ
+
+
+
+```
+@Slf4j
+@Validated
+@RestController
+@RequestMapping("validate2")
+public class ValidatorController2 {
+
+ /**
+ * {@link RequestBody} У
+ */
+ @PostMapping(value = "add")
+ public DataResult add(@Validated(AddCheck.class) @RequestBody User2 entity) {
+ log.info("һ¼{}", JSONUtil.toJsonStr(entity));
+ return DataResult.ok(true);
+ }
+
+ /**
+ * {@link RequestBody} У
+ */
+ @PostMapping(value = "edit")
+ public DataResult edit(@Validated(EditCheck.class) @RequestBody User2 entity) {
+ log.info("༭һ¼{}", JSONUtil.toJsonStr(entity));
+ return DataResult.ok(true);
+ }
+
+}
+
+```
+
+
+
+### [#](https://dunwu.github.io/spring-tutorial/pages/fe6aad/#%E5%B5%8C%E5%A5%97%E6%A0%A1%E9%AA%8C)ǶУ
+
+ǰʾУDTO ֶζǻͺ String ͡ʵʳУпijֶҲһȣʹǶУ顣 post 磬汣 User Ϣʱͬʱ Job ϢҪעǣʱ DTO ĶӦֶα@Valid ע⡣
+
+
+
+```
+@Data
+public class UserDTO {
+
+ @Min(value = 10000000000000000L, groups = Update.class)
+ private Long userId;
+
+ @NotNull(groups = {Save.class, Update.class})
+ @Length(min = 2, max = 10, groups = {Save.class, Update.class})
+ private String userName;
+
+ @NotNull(groups = {Save.class, Update.class})
+ @Length(min = 6, max = 20, groups = {Save.class, Update.class})
+ private String account;
+
+ @NotNull(groups = {Save.class, Update.class})
+ @Length(min = 6, max = 20, groups = {Save.class, Update.class})
+ private String password;
+
+ @NotNull(groups = {Save.class, Update.class})
+ @Valid
+ private Job job;
+
+ @Data
+ public static class Job {
+
+ @Min(value = 1, groups = Update.class)
+ private Long jobId;
+
+ @NotNull(groups = {Save.class, Update.class})
+ @Length(min = 2, max = 10, groups = {Save.class, Update.class})
+ private String jobName;
+
+ @NotNull(groups = {Save.class, Update.class})
+ @Length(min = 2, max = 10, groups = {Save.class, Update.class})
+ private String position;
+ }
+
+ /**
+ * ʱУ
+ */
+ public interface Save {
+ }
+
+ /**
+ * µʱУ
+ */
+ public interface Update {
+ }
+}
+ƴ
+
+```
+
+
+
+ǶУԽϷУһʹáоǶУԼÿһУ飬`List`ֶλ list ÿһ Job У
+
+### [#](https://dunwu.github.io/spring-tutorial/pages/fe6aad/#%E8%87%AA%E5%AE%9A%E4%B9%89%E6%A0%A1%E9%AA%8C%E6%B3%A8%E8%A7%A3)ԶУע
+
+1ԶУע?`@IsMobile`
+
+
+
+```
+@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
+@Retention(RUNTIME)
+@Constraint(validatedBy = MobileValidator.class)
+public @interface IsMobile {
+
+ String message();
+
+ Class>[] groups() default {};
+
+ Class extends Payload>[] payload() default {};
+
+}
+
+```
+
+
+
+2ʵ?`ConstraintValidator`?ӿڣд?`@IsMobile`?УעĽ
+
+
+
+```
+import cn.hutool.core.util.StrUtil;
+import io.github.dunwu.spring.core.validation.annotation.IsMobile;
+import io.github.dunwu.tool.util.ValidatorUtil;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+
+public class MobileValidator implements ConstraintValidator {
+
+ @Override
+ public void initialize(IsMobile isMobile) { }
+
+ @Override
+ public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
+ if (StrUtil.isBlank(s)) {
+ return false;
+ } else {
+ return ValidatorUtil.isMobile(s);
+ }
+ }
+
+}
+
+```
+
+
+
+### [#](https://dunwu.github.io/spring-tutorial/pages/fe6aad/#%E8%87%AA%E5%AE%9A%E4%B9%89%E6%A0%A1%E9%AA%8C)ԶУ
+
+ͨʵ?`org.springframework.validation.Validator`?ӿԶУ顣
+
+Ҫ
+
+* ʵ?`supports`?
+* ʵ?`validate`?
+ * ͨ?`Errors`?ռ
+ * `ObjectError`Bean
+ * `FieldError`BeanԣProperty
+ * ͨ?`ObjectError`??`FieldError`??`MessageSource`?ʵֻȡյĴİ
+
+
+
+```
+package io.github.dunwu.spring.core.validation;
+
+import io.github.dunwu.spring.core.validation.annotation.Valid;
+import io.github.dunwu.spring.core.validation.config.CustomValidatorConfig;
+import io.github.dunwu.spring.core.validation.entity.Person;
+import org.springframework.stereotype.Component;
+import org.springframework.validation.Errors;
+import org.springframework.validation.ValidationUtils;
+import org.springframework.validation.Validator;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+@Component
+public class CustomValidator implements Validator {
+
+ private final CustomValidatorConfig validatorConfig;
+
+ public CustomValidator(CustomValidatorConfig validatorConfig) {
+ this.validatorConfig = validatorConfig;
+ }
+
+ /**
+ * Уֻ Person У
+ */
+ @Override
+ public boolean supports(Class> clazz) {
+ return Person.class.equals(clazz);
+ }
+
+ @Override
+ public void validate(Object target, Errors errors) {
+ ValidationUtils.rejectIfEmpty(errors, "name", "name.empty");
+
+ List fields = getFields(target.getClass());
+ for (Field field : fields) {
+ Annotation[] annotations = field.getAnnotations();
+ for (Annotation annotation : annotations) {
+ if (annotation.annotationType().getAnnotation(Valid.class) != null) {
+ try {
+ ValidatorRule validatorRule = validatorConfig.findRule(annotation);
+ if (validatorRule != null) {
+ validatorRule.valid(annotation, target, field, errors);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+
+ private List getFields(Class> clazz) {
+ // Field
+ List fields = new ArrayList<>();
+ // classͲΪ
+ while (clazz != null) {
+ // Ե
+ Collections.addAll(fields, clazz.getDeclaredFields());
+ clazz = clazz.getSuperclass();
+ }
+ return fields;
+ }
+
+}
+
+```
+
+
+
+### [#](https://dunwu.github.io/spring-tutorial/pages/fe6aad/#%E5%BF%AB%E9%80%9F%E5%A4%B1%E8%B4%A5-fail-fast)ʧ(Fail Fast)
+
+Spring Validation ĬϻУֶΣȻ׳쳣ͨһЩã Fali Fast ģʽһУʧܾء
+
+
+
+```
+@Bean
+public Validator validator() {
+ ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
+ .configure()
+ // ʧģʽ
+ .failFast(true)
+ .buildValidatorFactory();
+ return validatorFactory.getValidator();
+}
+
+```
+
+
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/fe6aad/#spring-%E6%A0%A1%E9%AA%8C%E5%8E%9F%E7%90%86)Spring Уԭ
+
+### [#](https://dunwu.github.io/spring-tutorial/pages/fe6aad/#spring-%E6%A0%A1%E9%AA%8C%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF)Spring Уʹó
+
+* Spring У飨Validator
+* Spring ݰDataBinder
+* Spring Web WebDataBinder
+* Spring WebMVC/WebFlux У
+
+### [#](https://dunwu.github.io/spring-tutorial/pages/fe6aad/#validator-%E6%8E%A5%E5%8F%A3%E8%AE%BE%E8%AE%A1)Validator ӿ
+
+* ӿְ
+ * Spring ڲУӿڣ̵ͨķʽУĿ
+* ķ
+ * `supports(Class)`УĿܷУ
+ * `validate(Object,Errors)`УĿУʧܵ Errors
+*
+ * ռ`org.springframework.validation.Errors`
+ * Validator ࣺ`org.springframework.validation.ValidationUtils`
+
+### [#](https://dunwu.github.io/spring-tutorial/pages/fe6aad/#errors-%E6%8E%A5%E5%8F%A3%E8%AE%BE%E8%AE%A1)Errors ӿ
+
+* ӿְ
+ * ݰУռӿڣ Java Bean ǿ
+* ķ
+ * `reject`?أռİ
+ * `rejectValue`?أռֶеĴİ
+*
+ * Java Bean `org.springframework.validation.ObjectError`
+ * Java Bean Դ`org.springframework.validation.FieldError`
+
+### [#](https://dunwu.github.io/spring-tutorial/pages/fe6aad/#errors-%E6%96%87%E6%A1%88%E6%9D%A5%E6%BA%90)Errors İԴ
+
+Errors İɲ
+
+* ѡ Errors ʵ֣磺`org.springframework.validation.BeanPropertyBindingResult`
+* reject rejectValue
+* ȡ Errors ObjectError FieldError
+* ObjectError FieldError е code args MessageSource ʵ֣磺`ResourceBundleMessageSource`
+
+### [#](https://dunwu.github.io/spring-tutorial/pages/fe6aad/#spring-web-%E6%A0%A1%E9%AA%8C%E5%8E%9F%E7%90%86)spring web Уԭ
+
+#### [#](https://dunwu.github.io/spring-tutorial/pages/fe6aad/#requestbody-%E5%8F%82%E6%95%B0%E6%A0%A1%E9%AA%8C%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86)RequestBody Уʵԭ
+
+ spring-mvc У`RequestResponseBodyMethodProcessor`?ڽ?`@RequestBody`?עIJԼ`@ResponseBody`?עķֵġУִвУ϶ڽķ?`resolveArgument()`?У
+
+
+
+```
+@Override
+public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
+ NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
+
+ parameter = parameter.nestedIfOptional();
+ Object arg = readWithMessageConverters(webRequest, parameter, parameter.getNestedGenericParameterType());
+ String name = Conventions.getVariableNameForParameter(parameter);
+
+ if (binderFactory != null) {
+ WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name);
+ if (arg != null) {
+ // ԽвУ
+ validateIfApplicable(binder, parameter);
+ if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
+ // У׳ MethodArgumentNotValidException
+ throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());
+ }
+ }
+ if (mavContainer != null) {
+ mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());
+ }
+ }
+
+ return adaptArgumentIfNecessary(arg, parameter);
+}
+
+```
+
+
+
+ԿresolveArgument() validateIfApplicable()вУ顣
+
+
+
+```
+protected void validateIfApplicable(WebDataBinder binder, MethodParameter parameter) {
+ // ȡע⣬ @RequestBody@Valid@Validated
+ Annotation[] annotations = parameter.getParameterAnnotations();
+ for (Annotation ann : annotations) {
+ // ȳԻȡ @Validated ע
+ Validated validatedAnn = AnnotationUtils.getAnnotation(ann, Validated.class);
+ // ע @ValidatedֱӿʼУ顣
+ // ûУôжϲǰǷ Valid ͷע⡣
+ if (validatedAnn != null || ann.annotationType().getSimpleName().startsWith("Valid")) {
+ Object hints = (validatedAnn != null ? validatedAnn.value() : AnnotationUtils.getValue(ann));
+ Object[] validationHints = (hints instanceof Object[] ? (Object[]) hints : new Object[] {hints});
+ // ִУ
+ binder.validate(validationHints);
+ break;
+ }
+ }
+}
+
+```
+
+
+
+ϴ룬ͽ Spring Ϊʲôͬʱ֧?`@Validated``@Valid`?ע⡣
+
+һ WebDataBinder.validate() ʵ֣
+
+
+
+```
+@Override
+public void validate(Object target, Errors errors, Object... validationHints) {
+ if (this.targetValidator != null) {
+ processConstraintViolations(
+ // ˴ Hibernate Validator ִУ
+ this.targetValidator.validate(target, asValidationGroups(validationHints)), errors);
+ }
+}
+
+```
+
+
+
+ͨ룬Կ Spring Уʵǻ Hibernate Validator ķװ
+
+#### [#](https://dunwu.github.io/spring-tutorial/pages/fe6aad/#%E6%96%B9%E6%B3%95%E7%BA%A7%E5%88%AB%E7%9A%84%E5%8F%82%E6%95%B0%E6%A0%A1%E9%AA%8C%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86)IJУʵԭ
+
+Spring ָ֧ݷȥءУ飬ԭӦ AOP ˵ͨ?`MethodValidationPostProcessor`?̬ע AOP 棬Ȼʹ?`MethodValidationInterceptor`?е㷽֯ǿ
+
+
+
+```
+public class MethodValidationPostProcessor extends AbstractBeanFactoryAwareAdvisingPostProcessorimplements InitializingBean {
+ @Override
+ public void afterPropertiesSet() {
+ // Ϊ @Validated ע Bean
+ Pointcut pointcut = new AnnotationMatchingPointcut(this.validatedAnnotationType, true);
+ // Advisor ǿ
+ this.advisor = new DefaultPointcutAdvisor(pointcut, createMethodValidationAdvice(this.validator));
+ }
+
+ // Adviceʾһ
+ protected Advice createMethodValidationAdvice(@Nullable Validator validator) {
+ return (validator != null ? new MethodValidationInterceptor(validator) : new MethodValidationInterceptor());
+ }
+}
+
+```
+
+
+
+ſһ?`MethodValidationInterceptor`
+
+
+
+```
+public class MethodValidationInterceptor implements MethodInterceptor {
+ @Override
+ public Object invoke(MethodInvocation invocation) throws Throwable {
+ // ǿķֱ
+ if (isFactoryBeanMetadataMethod(invocation.getMethod())) {
+ return invocation.proceed();
+ }
+ // ȡϢ
+ Class>[] groups = determineValidationGroups(invocation);
+ ExecutableValidator execVal = this.validator.forExecutables();
+ Method methodToValidate = invocation.getMethod();
+ Set> result;
+ try {
+ // У飬ջίи Hibernate Validator У
+ result = execVal.validateParameters(
+ invocation.getThis(), methodToValidate, invocation.getArguments(), groups);
+ }
+ catch (IllegalArgumentException ex) {
+ ...
+ }
+ // 쳣ֱ׳
+ if (!result.isEmpty()) {
+ throw new ConstraintViolationException(result);
+ }
+ // ķ
+ Object returnValue = invocation.proceed();
+ // ԷֵУ飬ջίиHibernate ValidatorУ
+ result = execVal.validateReturnValue(invocation.getThis(), methodToValidate, returnValue, groups);
+ // 쳣ֱ׳
+ if (!result.isEmpty()) {
+ throw new ConstraintViolationException(result);
+ }
+ return returnValue;
+ }
+}
+
+```
+
+
+
+ʵϣ requestBody У黹ǷУ飬նǵ Hibernate Validator ִУ飬Spring Validation ֻһװ
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/fe6aad/#%E9%97%AE%E9%A2%98)
+
+**Spring ЩУ**
+
+* `org.springframework.validation.Validator`
+* ռ`org.springframework.validation.Errors`
+* Java Bean `org.springframework.validation.ObjectError`
+* Java Bean Դ`org.springframework.validation.FieldError`
+* Bean Validation 䣺`org.springframework.validation.beanvalidation.LocalValidatorFactoryBean`
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/fe6aad/#%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99)ο
+
+* [Spring ٷĵ֮ Core Technologies(opens new window)](https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans)
+* [С署 Spring ı˼롷(opens new window)](https://time.geekbang.org/course/intro/265)
+* https://juejin.cn/post/6856541106626363399
+
+
+# ο
+https://www.w3cschool.cn/wkspring
+https://www.runoob.com/w3cnote/basic-knowledge-summary-of-spring.html
+http://codepub.cn/2015/06/21/Basic-knowledge-summary-of-Spring
+https://dunwu.github.io/spring-tutorial
+https://mszlu.com/java/spring
+http://c.biancheng.net/spring/aop-module.html
\ No newline at end of file
diff --git "a/docs/spring/Spring\344\270\255\347\232\204Environment\347\216\257\345\242\203\345\217\230\351\207\217.md" "b/docs/spring/Spring\344\270\255\347\232\204Environment\347\216\257\345\242\203\345\217\230\351\207\217.md"
new file mode 100644
index 0000000..2c2f21a
--- /dev/null
+++ "b/docs/spring/Spring\344\270\255\347\232\204Environment\347\216\257\345\242\203\345\217\230\351\207\217.md"
@@ -0,0 +1,852 @@
+
+
+
+
+ڰøٵĴ롢дϵͳ Spring Boot ȻΪ Java Ӧÿʵ Spring Boot ṩڶУ**Զ**ǶһԣSpring Boot һΪԱԶɿ伴á߱ijһܵ Bean£Զõ Bean պҵijЩ£òظǣʱֻҪ͵ Bean ɣΪԶõ Bean `@ConditionalOnMissingBean`עΡ˵ǣֻһЩϸڣĸĶ˿ں (server.port) Դ URL (spring.datasource.url) ѹûҪ`ServerProperties``DataSourceProperties` Bean Զõ Bean Spring Boot ΪԶõ Bean ṩ1000ԣҪʱֻҪڻвļ (application.properties/application.yml) нָɣ Spring Boot `Externalized Configuration` (⻯) ԡ
+
+ȻⲿԴڻвļ֣ȤĶ߿Ķ Spring Boot ٷĵ Spring У`BeanFactory` Bean Ľɫ`Environment`ͬλΪһⲿԴеԶᱻӵ _Environment_ С**Ľ죬ⲿԴ_Disconf__Apollo_ _Nacos_ ȷֲʽģ Spring ĵ̣ҪףжȡȻᱻӵ _Environment_ **
+
+֮дƪ£`jasypt`һνӴ2018꣬ʱͺܺʵֶԼӽܵģҪʵôһҪϤ Bean ڡIoC չ (IoC Container Extension Points) Spring Boot ̵֪ʶҪ _Environment_
+
+> jasypt ʮּͨ`jasypt-maven-plugin`һ maven ΪֵģȻ`ENC()`滻ֵɡ£
+>
+> ```
+> jasypt.encryptor.password=crimson_typhoon
+>
+> spring.datasource.url=jdbc:mysql://HOST:PORT/db_sql_boy?characterEncoding=UTF-8
+> spring.datasource.hikari.driver-class-name=com.mysql.cj.jdbc.Driver
+> spring.datasource.hikari.username=root
+> spring.datasource.hikari.password=ENC(qS8+DEIlHxvhPHgn1VaW3oHkn2twrmwNOHewWLIfquAXiCDBrKwvIhDoqalKyhIF)
+> ƴ
+> ```
+
+## 1 ʶ Environmnent
+
+ʵʹУ _Environment_ ĻᲢࣻҵ Bean ȷʵҪȡⲿԴеijһֵֶ _Environment_ ע뵽ҵ Bean УҲֱʵ`EnvironmentAware`ӿڣõ _Environment_ ͵ Bean ʵ֮ͨ`getProperty()`ȡֵ_Environment_ ӿʾ
+
+```
+public interface Environment extends PropertyResolver {
+ String[] getActiveProfiles();
+ String[] getDefaultProfiles();
+ boolean acceptsProfiles(Profiles profiles);
+}
+
+public interface PropertyResolver {
+ boolean containsProperty(String key);
+ String getProperty(String key);
+ String getProperty(String key, String defaultValue);
+ T getProperty(String key, Class targetType);
+ T getProperty(String key, Class targetType, T defaultValue);
+ String resolvePlaceholders(String text);
+}
+ƴ
+```
+
+**ҲҪ _Environment_ _getProperty()_ ⲿԴеԲԵΪάȱӵ _Environment_ еģ`PropertySource`Ϊά**_PropertySource_ ǶԴƺԴһԵij`MapPropertySource`һʵ֣ͨ _Map_ صԡ_PropertySource_ £
+
+```
+public abstract class PropertySource {
+ protected final String name;
+ protected final T source;
+
+ public PropertySource(String name, T source) {
+ this.name = name;
+ this.source = source;
+ }
+
+ public String getName() { return this.name; }
+ public T getSource() { return this.source; }
+ public abstract Object getProperty(String name);
+}
+ƴ
+```
+
+ _PropertySource_ _PropertySource_ Ǿ߱ȡֵһġ
+
+#### ****getProperty()ڲִ****
+
+
+
+һ㣬_Environment_ ʵлһ`PropertyResolver`͵ijԱ _PropertyResolver_ ִ _getProperty()_ _PropertyResolver_ ʵֻԱֱǣ`ConversionService``PropertySources`ȣ_PropertyResolver_ `PropertySources` е _PropertySource_ȡԭֵȻί _ConversionService_ ԭֵת (бҪĻ)**Ȼ PropertySource Ǿ߱ȡֵһģ߱ռλתм߱ PropertyResolver Ҳӡ֤һӣڼѧУûʲôмһ˵ģУǾټһ**
+
+#### ****PropertySourceڲ****
+
+
+
+_Environment_ ʵг˳`PropertyResolver`͵ijԱ⣬һ`MutablePropertySources`͵ijԱṩֱӲ _MutablePropertySources_ ķֻͨ`getPropertySources()`ȡ _MutablePropertySources_ ʵȻ _MutablePropertySources_ е`addFirst()``addLast()``replace()`ȷȥ _PropertySource__MutablePropertySources_ _PropertySources_ Ψһһʵ࣬ͼʾ
+
+
+
+ܵ˵_Environment_ Ƕ _PropertySource_ _Profile_ Ķ _Profile_ ĸӦóҪͬлʱһЩͨͬ磬Դ URL ڿͲԻͻһSpring 3.1汾ʼֻ֧ _Profile_ á
+
+**Profile in Spring 3.1**
+
+ Spring 3.1汾ʱSpring Boot δ˵ʱ _Profile_ ԻЩ**覴**ģ覲褡Ҫڣͬһ͵ BeanΡһС覴ã
+
+```
+@Configuration(proxyBeanMethods = false)
+public class DataSourceConfig {
+ @Bean
+ @Profile("dev")
+ public DataSource devDataSource () {
+ return DataSourceBuilder.create()
+ .driverClassName("com.mysql.jdbc.Driver")
+ .url("jdbc:mysql://DEV_HOST:PORT/db_sql_boy?characterEncoding=UTF-8")
+ .username("dev")
+ .password("dev")
+ .build();
+ }
+
+ @Bean
+ @Profile("test")
+ public DataSource testDataSource () {
+ return DataSourceBuilder.create()
+ .driverClassName("com.mysql.jdbc.Driver")
+ .url("jdbc:mysql://TEST_HOST:PORT/db_sql_boy?characterEncoding=UTF-8")
+ .username("test")
+ .password("test")
+ .build();
+ }
+}
+ƴ
+```
+
+**Profile in Spring Boot**
+
+Spring Boot `@Profile`עӵˡٷп϶Ҳʶ _Profile in Spring 3.1_ 覴ã Spring Boot ĵһ汾 _(1.0.0.RELEASE)_ оȲ֧Ϊ _application.properties_ _application.yml_ _Profile_ ˡζһţ
+
+```
+@Configuration(proxyBeanMethods = false)
+public class DataSourceConfig {
+ @Bean
+ public DataSource devDataSource (DataSourceProperties dataSourceProperties) {
+ return DataSourceBuilder.create()
+ .driverClassName(dataSourceProperties.getDriverClassName())
+ .url(dataSourceProperties.getUrl())
+ .username(dataSourceProperties.getUsername())
+ .password(dataSourceProperties.getPassword())
+ .build();
+ }
+}
+ƴ
+```
+
+_application-dev.properties_ £
+
+```
+spring.datasource.url=jdbc:mysql://DEV_HOST:PORT/db_sql_boy?characterEncoding=UTF-8
+spring.datasource.hikari.driver-class-name=com.mysql.jdbc.Driver
+spring.datasource.hikari.password=dev
+spring.datasource.hikari.username=dev
+ƴ
+```
+
+_application-test.properties_ £
+
+```
+spring.datasource.url=jdbc:mysql://TEST_HOST:PORT/db_sql_boy?characterEncoding=UTF-8
+spring.datasource.hikari.driver-class-name=com.mysql.jdbc.Driver
+spring.datasource.hikari.password=test
+spring.datasource.hikari.username=test
+ƴ
+```
+
+ԭ Spring 3.1 Spring Boot Уͨ`spring.profiles.active`Ϊ _Environment_ ָ _Profile__Environment_ Ĭϼ _Profile_ Ϊ`default`дԺһ⣺һ㣬`@Profile` עҪ _@Configuration_ ע _@Bean_ עʹã _spring.profiles.active_ ֵΪ _dev_ ʱôЩ _@Configuration_ _@Bean_ ע (û`@Profile`עӰ) Bean ᱻΪ`BeanDefinition`ʵ𣿴ǻġ`ConfigurationClassPostProcessor` _@Configuration_ Ϊ _BeanDefinition_ڴ˹лִ`ConditionEvaluator``shouldSkip()`Ҫ£
+
+```
+public class ConditionEvaluator {
+ public boolean shouldSkip(AnnotatedTypeMetadata metadata, ConfigurationCondition.ConfigurationPhase phase) {
+ if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
+ return false;
+ }
+
+ if (phase == null) {
+ if (metadata instanceof AnnotationMetadata &&
+ ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
+ return shouldSkip(metadata, ConfigurationCondition.ConfigurationPhase.PARSE_CONFIGURATION);
+ }
+ return shouldSkip(metadata, ConfigurationCondition.ConfigurationPhase.REGISTER_BEAN);
+ }
+
+ List conditions = new ArrayList<>();
+ for (String[] conditionClasses : getConditionClasses(metadata)) {
+ for (String conditionClass : conditionClasses) {
+ Condition condition = getCondition(conditionClass, this.context.getClassLoader());
+ conditions.add(condition);
+ }
+ }
+
+ AnnotationAwareOrderComparator.sort(conditions);
+
+ for (Condition condition : conditions) {
+ ConfigurationCondition.ConfigurationPhase requiredPhase = null;
+ if (condition instanceof ConfigurationCondition) {
+ requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
+ }
+ if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
+ƴ
+```
+
+`shouldSkip()`һ _if_ Ǵ𰸣`@Profile`ע`@Conditional(ProfileCondition.class)`Σһͷû`Condition`Ӱֱӷ`false`ˣǾDz˼ඣ
+
+_Environment_ еЩ _PropertySource_ ɶðȻΪ _Bean_ ඣϻ˵ͼ
+
+
+
+> ǰ visio processOn ͼһ draw.ioû뵽㣬ǿҰһ
+
+## 2 Environmnent ʼ
+
+Ҫ Spring Boot _Environmnt_ оעЩ _PropertySource_λ`SpringApplication`е`run(String... args)`£
+
+```
+public class SpringApplication {
+ public ConfigurableApplicationContext run(String... args) {
+ StopWatch stopWatch = new StopWatch();
+ stopWatch.start();
+ DefaultBootstrapContext bootstrapContext = createBootstrapContext();
+ ConfigurableApplicationContext context = null;
+ configureHeadlessProperty();
+ SpringApplicationRunListeners listeners = getRunListeners(args);
+ listeners.starting(bootstrapContext, this.mainApplicationClass);
+ try {
+ ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
+ ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
+ configureIgnoreBeanInfo(environment);
+ Banner printedBanner = printBanner(environment);
+ context = createApplicationContext();
+ context.setApplicationStartup(this.applicationStartup);
+ prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
+ refreshContext(context);
+ afterRefresh(context, applicationArguments);
+ stopWatch.stop();
+ if (this.logStartupInfo) {
+ new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
+ }
+ listeners.started(context);
+ callRunners(context, applicationArguments);
+ } catch (Throwable ex) {
+ handleRunFailure(context, ex, listeners);
+ throw new IllegalStateException(ex);
+ }
+
+ try {
+ listeners.running(context);
+ } catch (Throwable ex) {
+ handleRunFailure(context, ex, null);
+ throw new IllegalStateException(ex);
+ }
+ return context;
+ }
+}
+ƴ
+```
+
+Կ_Environmnt_ ijʼ`refreshContext(context)`֮ǰɵģǺʵġ_run()_ ܸӣ뱾ϵֻ**һ**
+
+```
+prepareEnvironment(listeners, bootstrapContext, applicationArguments);
+ƴ
+```
+
+ֱ
+
+### 2.1 prepareEnvironment()
+
+Ȼݶ`prepareEnvironment()`ڣСһ
+
+```
+public class SpringApplication {
+ private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
+ DefaultBootstrapContext bootstrapContext,
+ ApplicationArguments applicationArguments) {
+ // 2.1.1
+ ConfigurableEnvironment environment = getOrCreateEnvironment();
+ // 2.1.2
+ configureEnvironment(environment, applicationArguments.getSourceArgs());
+ // 2.1.3
+ ConfigurationPropertySources.attach(environment);
+ // 2.1.4
+ listeners.environmentPrepared(bootstrapContext, environment);
+ DefaultPropertiesPropertySource.moveToEnd(environment);
+ bindToSpringApplication(environment);
+ ConfigurationPropertySources.attach(environment);
+ return environment;
+ }
+}
+ƴ
+```
+
+#### 2.1.1 getOrCreateEnvironment()
+
+`getOrCreateEnvironment()`Ҫ _Environment_ ʵǰӦǻ`ͬI/O`ģ͵ģ _Environment_ ѡ`ApplicationServletEnvironment`෴أǰӦǻ`첽I/O`ģ͵ģ _Environment_ ѡ`ApplicationReactiveWebEnvironment`ǹлǻ Spring MVC ӦãSpring MVC һ`Servlet API`֮ϡͬ I/O ģ͵ Java Web ܣ I/O ģζһ HTTP Ӧһ̣߳ÿһ HTTP ڸ߳ɴġ_ApplicationServletEnvironment_ ̳йϵͼʾ
+
+
+
+ͼԿ _ApplicationServletEnvironment_ ൱Ӵִ _ApplicationServletEnvironment_ 췽ʱȻᴥ췽е**Ϊ**
+
+```
+public abstract class AbstractEnvironment implements ConfigurableEnvironment {
+ public AbstractEnvironment() {
+ this(new MutablePropertySources());
+ }
+
+ protected AbstractEnvironment(MutablePropertySources propertySources) {
+ this.propertySources = propertySources;
+ // createPropertyResolver(propertySources)
+ // |___ ConfigurationPropertySources.createPropertyResolver(propertySources)
+ // |___ new ConfigurationPropertySourcesPropertyResolver(propertySources)
+ this.propertyResolver = createPropertyResolver(propertySources);
+ customizePropertySources(propertySources);
+ }
+}
+ƴ
+```
+
+```
+public class StandardServletEnvironment extends StandardEnvironment implements ConfigurableWebEnvironment {
+ @Override
+ protected void customizePropertySources(MutablePropertySources propertySources) {
+ propertySources.addLast(new StubPropertySource("servletConfigInitParams"));
+ propertySources.addLast(new StubPropertySource("servletContextInitParams"));
+ super.customizePropertySources(propertySources);
+ }
+}
+ƴ
+```
+
+```
+public class StandardEnvironment extends AbstractEnvironment {
+ @Override
+ protected void customizePropertySources(MutablePropertySources propertySources) {
+ propertySources.addLast(
+ new PropertiesPropertySource("systemProperties", (Map) System.getProperties()));
+ propertySources.addLast(
+ new SystemEnvironmentPropertySource("systemEnvironment", (Map) System.getenv()));
+ }
+}
+ƴ
+```
+
+ _ApplicationServletEnvironment_ 췽ִУʱ _Environment_ _MutablePropertySources_ ͵ijԱ`propertySources`Ѿ**** _PropertySource_ ˣǣ`servletConfigInitParams``servletContextInitParams``systemProperties``systemEnvironment`⣬ҲҪס _ApplicationServletEnvironment_ еҪԱ`MutablePropertySources``ConfigurationPropertySourcesPropertyResolver`
+
+#### 2.1.2 configureEnvironment()
+
+`configureEnvironment()`еҲܼȣΪ _Environment_ е _PropertySourcesPropertyResolver_ 趨 _ConversionService_Ȼ _Environment_ е _MutablePropertySources_ һΪ`commandLineArgs` _PropertySource_ ʵעʹõ`addFirst()`ŶζΪ`commandLineArgs` _PropertySource_ ȼߵġҪ£
+
+```
+public class SpringApplication {
+ protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
+ if (this.addConversionService) {
+ environment.getPropertyResolver().setConversionService(new ApplicationConversionService());
+ }
+ if (this.addCommandLineProperties && args.length > 0) {
+ MutablePropertySources sources = environment.getPropertySources();
+ sources.addFirst(new SimpleCommandLinePropertySource(args));
+ }
+ }
+}
+ƴ
+```
+
+`SimpleCommandLinePropertySource`
+
+```
+public class SimpleCommandLinePropertySource extends CommandLinePropertySource {
+ public SimpleCommandLinePropertySource(String... args) {
+ // 丸췽Ϊsuper("commandLineArgs", source)
+ super(new SimpleCommandLineArgsParser().parse(args));
+ }
+}
+ƴ
+```
+
+вDZȽϳõģ Spring Boot Ӧʱв`java -jar app.jar --server.port=8088`
+
+#### 2.1.3 ConfigurationPropertySources.attach()
+
+`attach()`Ҫ _Environment_ _MutablePropertySources_ ͷλòһΪ`configurationProperties` _PropertySource_ ʵҪ£
+
+```
+public final class ConfigurationPropertySources {
+ public static void attach(org.springframework.core.env.Environment environment) {
+ MutablePropertySources sources = ((ConfigurableEnvironment) environment).getPropertySources();
+ PropertySource> attached = getAttached(sources);
+ if (attached != null && attached.getSource() != sources) {
+ sources.remove(ATTACHED_PROPERTY_SOURCE_NAME);
+ attached = null;
+ }
+ if (attached == null) {
+ sources.addFirst(new ConfigurationPropertySourcesPropertySource("configurationProperties", new SpringConfigurationPropertySources(sources)));
+ }
+ }
+
+ static PropertySource> getAttached(MutablePropertySources sources) {
+ return (sources != null) ? sources.get("configurationProperties") : null;
+ }
+}
+ƴ
+```
+
+߶˺þãѹûΪ`configurationProperties` _PropertySource_ ɶáڹٷĵй`Relaxed Binding` (ɰ) в³ЩߡͨȽֱӡȣ _application.properties_ һ`a.b.my-first-key=hello spring environment`Ȼͨ _Environment_ ȡֵ£
+
+```
+@SpringBootApplication
+public class DemoApplication {
+ public static void main(String[] args) {
+ ConfigurableApplicationContext configurableApplicationContext = SpringApplication.run(DemoApplication.class, args);
+ ConfigurableWebEnvironment environment = (ConfigurableWebEnvironment)
+ configurableApplicationContext.getBean(Environment.class);
+ System.out.println(environment.getProperty("a.b.my-first-key"));
+ }
+}
+ƴ
+```
+
+Ӧų́ӡ _hello spring environment_ Ԥġɵͨ`environment.getProperty("a.b.myfirstkey")``environment.getProperty("a.b.my-firstkey")`Ȼܹȡݡ`a.b.myfirstkey``a.b.my-firstkey`ļеƣֻƶѣȷ****ȤĶ߿ DEBUG еԭ
+
+#### 2.1.4 listeners.environmentPrepared()
+
+úڰ壬λУҪ `environmentPrepared()`㲥һ`ApplicationEnvironmentPreparedEvent`¼`EnvironmentPostProcessorApplicationListener`Ӧ¼Ӧǵ͵**۲ģʽ**Ҫ£
+
+```
+public class SpringApplicationRunListeners {
+ private final List listeners;
+
+ void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
+ doWithListeners("spring.boot.application.environment-prepared",
+ (listener) -> listener.environmentPrepared(bootstrapContext, environment));
+ }
+
+ private void doWithListeners(String stepName, Consumer listenerAction) {
+ StartupStep step = this.applicationStartup.start(stepName);
+ this.listeners.forEach(listenerAction);
+ step.end();
+ }
+}
+
+public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
+ @Override
+ public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext,
+ ConfigurableEnvironment environment) {
+ this.initialMulticaster.multicastEvent(
+ new ApplicationEnvironmentPreparedEvent(bootstrapContext, this.application, this.args, environment));
+ }
+}
+
+public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
+ @Override
+ public void multicastEvent(ApplicationEvent event) {
+ multicastEvent(event, resolveDefaultEventType(event));
+ }
+
+ @Override
+ public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
+ ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
+ Executor executor = getTaskExecutor();
+ for (ApplicationListener> listener : getApplicationListeners(event, type)) {
+ if (executor != null) {
+ executor.execute(() -> invokeListener(listener, event));
+ } else {
+ invokeListener(listener, event);
+ }
+ }
+ }
+}
+ƴ
+```
+
+һ`EnvironmentPostProcessorApplicationListener`®ɽĿ
+
+```
+public class EnvironmentPostProcessorApplicationListener implements SmartApplicationListener, Ordered {
+ @Override
+ public void onApplicationEvent(ApplicationEvent event) {
+ if (event instanceof ApplicationEnvironmentPreparedEvent) {
+ onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);
+ }
+ if (event instanceof ApplicationPreparedEvent) {
+ onApplicationPreparedEvent();
+ }
+ if (event instanceof ApplicationFailedEvent) {
+ onApplicationFailedEvent();
+ }
+ }
+ private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {
+ ConfigurableEnvironment environment = event.getEnvironment();
+ SpringApplication application = event.getSpringApplication();
+ for (EnvironmentPostProcessor postProcessor : getEnvironmentPostProcessors(application.getResourceLoader(), event.getBootstrapContext())) {
+ postProcessor.postProcessEnvironment(environment, application);
+ }
+ }
+}
+ƴ
+```
+
+`EnvironmentPostProcessor` Spring Boot Ϊ _Environment_ չ㡣ùٷĵбȽϾһ仰_Allows for customization of the application's Environment prior to the application context being refreshed__EnvironmentPostProcessor_ һԽӿڣ£
+
+```
+public interface EnvironmentPostProcessor {
+ void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application);
+}
+ƴ
+```
+
+ _EnvironmentPostProcessorApplicationListener_ ¼У`getEnvironmentPostProcessors`سе _EnvironmentPostProcessor_ һڲ
+
+```
+public interface EnvironmentPostProcessorsFactory {
+ static EnvironmentPostProcessorsFactory fromSpringFactories(ClassLoader classLoader) {
+ return new ReflectionEnvironmentPostProcessorsFactory(
+ classLoader,
+ SpringFactoriesLoader.loadFactoryNames(EnvironmentPostProcessor.class, classLoader)
+ );
+ }
+}
+ƴ
+```
+
+`SpringFactoriesLoader`һ̽
+
+```
+public final class SpringFactoriesLoader {
+
+ public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
+
+ public static List loadFactoryNames(Class> factoryType, ClassLoader classLoader) {
+ ClassLoader classLoaderToUse = classLoader;
+ if (classLoaderToUse == null) {
+ classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
+ }
+ String factoryTypeName = factoryType.getName();
+ return loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
+ }
+
+ private static Map> loadSpringFactories(ClassLoader classLoader) {
+ Map> result = cache.get(classLoader);
+ if (result != null) {
+ return result;
+ }
+
+ result = new HashMap<>();
+ try {
+ Enumeration urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
+ while (urls.hasMoreElements()) {
+ URL url = urls.nextElement();
+ UrlResource resource = new UrlResource(url);
+ Properties properties = PropertiesLoaderUtils.loadProperties(resource);
+ for (Map.Entry, ?> entry : properties.entrySet()) {
+ String factoryTypeName = ((String) entry.getKey()).trim();
+ String[] factoryImplementationNames = StringUtils.commaDelimitedListToStringArray((String) entry.getValue());
+ for (String factoryImplementationName : factoryImplementationNames) {
+ result.computeIfAbsent(factoryTypeName, key -> new ArrayList<>())
+ .add(factoryImplementationName.trim());
+ }
+ }
+ }
+ result.replaceAll((factoryType, implementations) -> implementations.stream().distinct()
+ .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList)));
+ cache.put(classLoader, result);
+ } catch (IOException ex) {
+ throw new IllegalArgumentException("Unable to load factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);
+ }
+ return result;
+ }
+}
+ƴ
+```
+
+> **Spring SPI**
+>
+> > _SpringFactoriesLoader_ һ Spring е`SPI`ƣֱ˵Ǵ`classpath`µ`META-INF/spring.factories` ļм _EnvironmentPostProcessor_ ͽԼʵֵ _EnvironmentPostProcessor_ ŵļоˡʵ`JDK`е`SPI`ƺƹ
+
+ڵǰ汾Spring Boot 7 _EnvironmentPostProcessor_ ʵࡣȽϵ͵ķ¡
+
+**RandomValuePropertySourceEnvironmentPostProcessor**
+
+`RandomValuePropertySourceEnvironmentPostProcessor` _Environment_ һΪ`random` _PropertySource_`RandomValuePropertySource`£
+
+```
+public class RandomValuePropertySourceEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
+ public static final int ORDER = Ordered.HIGHEST_PRECEDENCE + 1;
+ private final Log logger;
+
+ public RandomValuePropertySourceEnvironmentPostProcessor(Log logger) {
+ this.logger = logger;
+ }
+
+ @Override
+ public int getOrder() {
+ return ORDER;
+ }
+
+ @Override
+ public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
+ RandomValuePropertySource.addToEnvironment(environment, this.logger);
+ }
+}
+ƴ
+```
+
+ô _RandomValuePropertySource_ ɶأҪ磺`environment.getProperty("random.int(5,10)")`Իȡһ`random.int`ΪԻȡһ _int_ ͵`random.long`ΪԻȡһ _long_ ͵`random.int(5,10)`ΪԻȡһ _[5, 10}_ _int_ ͵淨̽
+
+_SystemEnvironmentPropertySourceEnvironmentPostProcessor_
+
+ǰ_Environment_ ѾһΪ`systemEnvironment` _PropertySource_`SystemEnvironmentPropertySource``SystemEnvironmentPropertySourceEnvironmentPostProcessor`ڽ _SystemEnvironmentPropertySource_ 滻Ϊ`OriginAwareSystemEnvironmentPropertySource`զе㡰ѿӷƨһ١ĸоأ
+
+```
+public class SystemEnvironmentPropertySourceEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
+ public static final int DEFAULT_ORDER = SpringApplicationJsonEnvironmentPostProcessor.DEFAULT_ORDER - 1;
+ private int order = DEFAULT_ORDER;
+
+ @Override
+ public int getOrder() {
+ return this.order;
+ }
+
+ @Override
+ public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
+ String sourceName = "systemEnvironment";
+ PropertySource> propertySource = environment.getPropertySources().get(sourceName);
+ if (propertySource != null) {
+ replacePropertySource(environment, sourceName, propertySource, application.getEnvironmentPrefix());
+ }
+ }
+ private void replacePropertySource(ConfigurableEnvironment environment, String sourceName,
+ PropertySource> propertySource, String environmentPrefix) {
+ Map originalSource = (Map) propertySource.getSource();
+ SystemEnvironmentPropertySource source = new OriginAwareSystemEnvironmentPropertySource(sourceName, originalSource, environmentPrefix);
+ environment.getPropertySources().replace(sourceName, source);
+ }
+}
+ƴ
+```
+
+**SpringApplicationJsonEnvironmentPostProcessor**
+
+ͨ`java -jar -Dspring.application.json={"name":"duxiaotou"} app.jar` Spring Boot ӦõʱԻᱻԶӵ JVM ϵͳ (ʵ _-Dkey=value_ ʽԾ)Ч`System.setProperty(key, value)``SPRING_APPLICATION_JSON`һϵͳʱȻҲ`System.getenv()`г֡ǰᵽ`System.getProperties()``systemProperties`һ _PropertySource_`System.getenv()``systemEnvironment`һ _PropertySource_`SpringApplicationJsonEnvironmentPostProcessor`ڴ _PropertySource_ гȡ _spring.application.json_ _SPRING_APPLICATION_JSON_ _JSON_ _Environment_ һΪ`spring.application.json` _PropertySource_`JsonPropertySource`
+
+**ConfigDataEnvironmentPostProcessor**
+
+`ConfigDataEnvironmentPostProcessor``optional:classpath:/``optional:classpath:/config/``optional:file:./``optional:file:./config/``optional:file:./config/*/`ЩĿ¼µ _application.properties_ ļسָ _spring.profiles.active_ĻͬʱҲὫЩĿ¼µ _application-{profile}.properties_ ļسգ_ConfigDataEnvironmentPostProcessor_ _Environment_ `OriginTrackedMapPropertySource` _PropertySource_ λ _Environment_ β _application-{profile}.properties_ _OriginTrackedMapPropertySource_ _application.properties_ _OriginTrackedMapPropertySource_ ǰģһͦҪ
+
+## 3 jasypt ԭ
+
+> `jasypt``jasypt-spring-boot-starter`DzͬдģֻΪ jasypt Spring Boot ѡʵ
+
+_application.properties_ ļйԴһܺģ£
+
+```
+spring.datasource.hikari.password=ENC(4+t9a5QG8NkNdWVS6UjIX3dj18UtYRMqU6eb3wUKjivOiDHFLZC/RTK7HuWWkUtV)
+ƴ
+```
+
+`HikariDataSource` Bean _password_ ֶεֵզͱΪܺ _qwe@1234_ һأȻSpring Boot Ϊ _Environment_ ṩ`EnvironmentPostProcessor`һչʵ͵컻գûʹ Spring еһ _IoC չ_`BeanFactoryPostProcessor`ҲȫԵģΪִе _BeanFactoryPostProcessor_ е`postProcessBeanFactory()`ʱֻ`BeanDefinition`ļأûʵ _BeanDefinition_ Ӧ Bean
+
+濴һ`EnableEncryptablePropertiesBeanFactoryPostProcessor`еݣ
+
+```
+public class EnableEncryptablePropertiesBeanFactoryPostProcessor implements BeanFactoryPostProcessor, Ordered {
+
+ private final ConfigurableEnvironment environment;
+ private final EncryptablePropertySourceConverter converter;
+
+ public EnableEncryptablePropertiesBeanFactoryPostProcessor(ConfigurableEnvironment environment, EncryptablePropertySourceConverter converter) {
+ this.environment = environment;
+ this.converter = converter;
+ }
+
+ @Override
+ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
+ MutablePropertySources propSources = environment.getPropertySources();
+ converter.convertPropertySources(propSources);
+ }
+
+ @Override
+ public int getOrder() {
+ return Ordered.LOWEST_PRECEDENCE - 100;
+ }
+}
+ƴ
+```
+
+Դ _BeanFactoryPostProcessor_ `EncryptablePropertySourceConverter` _MutablePropertySources_ һתôתɶأ
+
+ţ _EncryptablePropertySourceConverter_£
+
+```
+public class EncryptablePropertySourceConverter {
+
+ public void convertPropertySources(MutablePropertySources propSources) {
+ propSources.stream()
+ .filter(ps -> !(ps instanceof EncryptablePropertySource))
+ .map(this::makeEncryptable)
+ .collect(toList())
+ .forEach(ps -> propSources.replace(ps.getName(), ps));
+ }
+
+ public PropertySource makeEncryptable(PropertySource propertySource) {
+ if (propertySource instanceof EncryptablePropertySource
+ || skipPropertySourceClasses.stream().anyMatch(skipClass -> skipClass.equals(propertySource.getClass()))) {
+ return propertySource;
+ }
+ PropertySource encryptablePropertySource = convertPropertySource(propertySource);
+ return encryptablePropertySource;
+ }
+
+ private PropertySource convertPropertySource(PropertySource propertySource) {
+ PropertySource encryptablePropertySource;
+ if (propertySource instanceof SystemEnvironmentPropertySource) {
+ encryptablePropertySource = (PropertySource) new EncryptableSystemEnvironmentPropertySourceWrapper((SystemEnvironmentPropertySource) propertySource, propertyResolver, propertyFilter);
+ } else if (propertySource instanceof MapPropertySource) {
+ encryptablePropertySource = (PropertySource) new EncryptableMapPropertySourceWrapper((MapPropertySource) propertySource, propertyResolver, propertyFilter);
+ } else if (propertySource instanceof EnumerablePropertySource) {
+ encryptablePropertySource = new EncryptableEnumerablePropertySourceWrapper<>((EnumerablePropertySource) propertySource, propertyResolver, propertyFilter);
+ } else {
+ encryptablePropertySource = new EncryptablePropertySourceWrapper<>(propertySource, propertyResolver, propertyFilter);
+ }
+ return encryptablePropertySource;
+ }
+}
+ƴ
+```
+
+Ȼԭ _PropertySource_ תΪһ`EncryptablePropertySourceWrapper`϶ʵĽܣģ
+
+`EncryptablePropertySourceWrapper`£
+
+```
+public class EncryptablePropertySourceWrapper extends PropertySource implements EncryptablePropertySource {
+ private final CachingDelegateEncryptablePropertySource encryptableDelegate;
+
+ public EncryptablePropertySourceWrapper(PropertySource delegate, EncryptablePropertyResolver resolver, EncryptablePropertyFilter filter) {
+ super(delegate.getName(), delegate.getSource());
+ encryptableDelegate = new CachingDelegateEncryptablePropertySource<>(delegate, resolver, filter);
+ }
+
+ @Override
+ public Object getProperty(String name) {
+ return encryptableDelegate.getProperty(name);
+ }
+
+ @Override
+ public PropertySource getDelegate() {
+ return encryptableDelegate;
+ }
+}
+ƴ
+```
+
+ʧûɶ _getProperty_ ίɸ`CachingDelegateEncryptablePropertySource`
+
+û취ֻܵ _CachingDelegateEncryptablePropertySource_ һ̽ˣ
+
+```
+public class CachingDelegateEncryptablePropertySource extends PropertySource implements EncryptablePropertySource {
+ private final PropertySource delegate;
+ private final EncryptablePropertyResolver resolver;
+ private final EncryptablePropertyFilter filter;
+ private final Map cache;
+
+ public CachingDelegateEncryptablePropertySource(PropertySource delegate, EncryptablePropertyResolver resolver, EncryptablePropertyFilter filter) {
+ super(delegate.getName(), delegate.getSource());
+ this.delegate = delegate;
+ this.resolver = resolver;
+ this.filter = filter;
+ this.cache = new HashMap<>();
+ }
+
+ @Override
+ public PropertySource getDelegate() {
+ return delegate;
+ }
+
+ @Override
+ public Object getProperty(String name) {
+ if (cache.containsKey(name)) {
+ return cache.get(name);
+ }
+ synchronized (name.intern()) {
+ if (!cache.containsKey(name)) {
+ Object resolved = getProperty(resolver, filter, delegate, name);
+ if (resolved != null) {
+ cache.put(name, resolved);
+ }
+ }
+ return cache.get(name);
+ }
+ }
+}
+ƴ
+```
+
+ڣ`EncryptablePropertySource`п˽ܵУ`EncryptablePropertyDetector`̽ǷҪܣҪͨжϸֵǷ`ENC()`
+
+```
+public interface EncryptablePropertySource extends OriginLookup {
+ default Object getProperty(EncryptablePropertyResolver resolver, EncryptablePropertyFilter filter, PropertySource source, String name) {
+ Object value = source.getProperty(name);
+ if (value != null && filter.shouldInclude(source, name) && value instanceof String) {
+ String stringValue = String.valueOf(value);
+ return resolver.resolvePropertyValue(stringValue);
+ }
+ return value;
+ }
+}
+
+public class DefaultPropertyResolver implements EncryptablePropertyResolver {
+
+ private final Environment environment;
+ private StringEncryptor encryptor;
+ private EncryptablePropertyDetector detector;
+
+ @Override
+ public String resolvePropertyValue(String value) {
+ return Optional.ofNullable(value)
+ .map(environment::resolvePlaceholders)
+ .filter(detector::isEncrypted)
+ .map(resolvedValue -> {
+ try {
+ String unwrappedProperty = detector.unwrapEncryptedValue(resolvedValue.trim());
+ String resolvedProperty = environment.resolvePlaceholders(unwrappedProperty);
+ return encryptor.decrypt(resolvedProperty);
+ } catch (EncryptionOperationNotPossibleException e) {
+ throw new DecryptionException("Unable to decrypt property: " + value + " resolved to: " + resolvedValue + ". Decryption of Properties failed, make sure encryption/decryption " +
+ "passwords match", e);
+ }
+ })
+ .orElse(value);
+ }
+}
+ƴ
+```
+
+## 4 ܽ
+
+ܽԵ־Ͳ˵ˣ˼Ȫӿˮ300֡ϣҼסڵǰ Spring Boot 汾У`ApplicationServletEnvironment` _Environment_սί`ConfigurationPropertySourcesPropertyResolver`ȥȡֵ
+
+## 5 οĵ
+
+1. [docs.spring.io/spring-boot](https://link.juejin.cn?target=https%3A%2F%2Fdocs.spring.io%2Fspring-boot%2Fdocs%2F2.5.7%2Freference%2Fhtml%2Ffeatures.html "https://docs.spring.io/spring-boot/docs/2.5.7/reference/html/features.html")
+
+
+
+ߣԳСͷ
+ӣhttps://juejin.cn/post/7098299623759937543
+Դϡ
+ȨСҵתϵȨҵתע
+
+# ο
+https://www.w3cschool.cn/wkspring
+https://www.runoob.com/w3cnote/basic-knowledge-summary-of-spring.html
+http://codepub.cn/2015/06/21/Basic-knowledge-summary-of-Spring
+https://dunwu.github.io/spring-tutorial
+https://mszlu.com/java/spring
+http://c.biancheng.net/spring/aop-module.html
\ No newline at end of file
diff --git "a/docs/spring/Spring\344\270\255\347\232\204\344\272\213\344\273\266\345\244\204\347\220\206\346\234\272\345\210\266.md" "b/docs/spring/Spring\344\270\255\347\232\204\344\272\213\344\273\266\345\244\204\347\220\206\346\234\272\345\210\266.md"
new file mode 100644
index 0000000..6acb8a1
--- /dev/null
+++ "b/docs/spring/Spring\344\270\255\347\232\204\344\272\213\344\273\266\345\244\204\347\220\206\346\234\272\345\210\266.md"
@@ -0,0 +1,270 @@
+
+
+
+
+# Spring е¼
+
+
+
+2022-05-16 15:29
+
+
+
+
+
+
+
+
+
+## Spring е¼
+
+Ѿ½ Spring ĺ?**ApplicationContext** beans ڡ beans ʱApplicationContext ijЩ͵¼磬ʱContextStartedEvent ֹͣʱContextStoppedEvent
+
+ͨ ApplicationEvent ApplicationListener ӿṩ ApplicationContext д¼һ bean ʵ ApplicationListenerôÿ ApplicationEvent ApplicationContext ϣǸ bean ᱻ֪ͨ
+
+Spring ṩµı¼
+
+| | Spring ¼ & |
+| --- | --- |
+| 1 | **ContextRefreshedEvent**ApplicationContext ʼˢʱ¼Ҳ ConfigurableApplicationContext ӿʹ refresh() |
+| 2 | **ContextStartedEvent**ʹ ConfigurableApplicationContext ӿе start() ApplicationContext ʱ¼Եݿ⣬ڽܵ¼κֹͣӦó |
+| 3 | **ContextStoppedEvent**ʹ ConfigurableApplicationContext ӿе stop() ֹͣ ApplicationContext ʱ¼ڽܵ¼ҪĹ |
+| 4 | **ContextClosedEvent**ʹ ConfigurableApplicationContext ӿе close() ر ApplicationContext ʱ¼һѹرյĵĩˣܱˢ» |
+| 5 | **RequestHandledEvent**һ web-specific ¼ bean HTTP Ѿ |
+
+ Spring ¼ǵ̵߳ģһ¼ֱҳеĽߵõĸϢý̱̽ˣ¼ʹãӦóʱӦע⡣
+
+## ¼
+
+Ϊ˼¼һ bean Ӧʵֻһ?**onApplicationEvent()**? ApplicationListener ӿڡˣдһ¼δģԼοôִлijЩ¼
+
+ǡλʹ Eclipse IDEȻIJһ Spring Ӧó
+
+| | |
+| --- | --- |
+| 1 | һΪ SpringExample ĿڴĿ?**src**?ļдһ com.tutorialspoint |
+| 2 | ʹ Add External JARs ѡ Spring ⣬ͼ Spring Hello World Example ½ڡ |
+| 3 | com.tutorialspoint д Java HelloWorldCStartEventHandlerCStopEventHandler MainApp |
+| 4 | ?**src**?ļд Bean ļ Beans.xml |
+| 5 | һǴ Java ļ Bean ļݣӦóʾ |
+
+?**HelloWorld.java**?ļݣ
+
+```
+package com.tutorialspoint;
+public class HelloWorld {
+ private String message;
+ public void setMessage(String message){
+ this.message = message;
+ }
+ public void getMessage(){
+ System.out.println("Your Message : " + message);
+ }
+}
+```
+
+?**CStartEventHandler.java**?ļݣ
+
+```
+package com.tutorialspoint;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.event.ContextStartedEvent;
+public class CStartEventHandler
+ implements ApplicationListener{
+ public void onApplicationEvent(ContextStartedEvent event) {
+ System.out.println("ContextStartedEvent Received");
+ }
+}
+```
+
+?**CStopEventHandler.java**?ļݣ
+
+```
+package com.tutorialspoint;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.event.ContextStoppedEvent;
+public class CStopEventHandler
+ implements ApplicationListener{
+ public void onApplicationEvent(ContextStoppedEvent event) {
+ System.out.println("ContextStoppedEvent Received");
+ }
+}
+```
+
+?**MainApp.java**?ļݣ
+
+```
+package com.tutorialspoint;
+
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class MainApp {
+ public static void main(String[] args) {
+ ConfigurableApplicationContext context =
+ new ClassPathXmlApplicationContext("Beans.xml");
+
+ // Let us raise a start event.
+ context.start();
+
+ HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
+
+ obj.getMessage();
+
+ // Let us raise a stop event.
+ context.stop();
+ }
+}
+```
+
+ļ?**Beans.xml**?ļ
+
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+һ˴Դ bean ļǾͿиӦóӦóһжϢ
+
+```
+ContextStartedEvent Received
+Your Message : Hello World!
+ContextStoppedEvent Received
+```
+
+
+
+
+
+
+
+## Spring еԶ¼
+
+дͷԼԶ¼ಽ衣һ¸˵дʹԶ Spring ¼
+
+| | |
+| --- | --- |
+| 1 | һΪ SpringExample ĿڴĿ?**src**?ļдһ com.tutorialspoint |
+| 2 | ʹ Add External JARs ѡ Spring ⣬ͼ Spring Hello World Example ½ڡ |
+| 3 | ͨչ?**ApplicationEvent**,һ¼ CustomEvent붨һĬϵĹ캯Ӧô ApplicationEvent м̳еĹ캯 |
+| 4 | һ¼࣬Դκзٶ EventClassPublisher ʵ ApplicationEventPublisherAware㻹Ҫ XML ļΪһ bean֮ʶ bean Ϊ¼ߣΪʵ ApplicationEventPublisherAware ӿڡ |
+| 5 | ¼һбٶ EventClassHandler ʵ ApplicationListener ӿڣʵԶ¼ onApplicationEvent |
+| 6 | ?**src**?ļд bean ļ Beans.xml MainApp ࣬Ϊһ Spring ӦóС |
+| 7 | һǴ Java ļ Bean ļݣӦóʾ |
+
+?**CustomEvent.java**?ļݣ
+
+```
+package com.tutorialspoint;
+import org.springframework.context.ApplicationEvent;
+public class CustomEvent extends ApplicationEvent{
+ public CustomEvent(Object source) {
+ super(source);
+ }
+ public String toString(){
+ return "My Custom Event";
+ }
+}
+
+```
+
+?**CustomEventPublisher.java**?ļݣ
+
+```
+package com.tutorialspoint;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.context.ApplicationEventPublisherAware;
+public class CustomEventPublisher
+ implements ApplicationEventPublisherAware {
+ private ApplicationEventPublisher publisher;
+ public void setApplicationEventPublisher
+ (ApplicationEventPublisher publisher){
+ this.publisher = publisher;
+ }
+ public void publish() {
+ CustomEvent ce = new CustomEvent(this);
+ publisher.publishEvent(ce);
+ }
+}
+```
+
+?**CustomEventHandler.java**?ļݣ
+
+```
+package com.tutorialspoint;
+import org.springframework.context.ApplicationListener;
+public class CustomEventHandler
+ implements ApplicationListener{
+ public void onApplicationEvent(CustomEvent event) {
+ System.out.println(event.toString());
+ }
+}
+```
+
+?**MainApp.java**?ļݣ
+
+```
+package com.tutorialspoint;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+public class MainApp {
+ public static void main(String[] args) {
+ ConfigurableApplicationContext context =
+ new ClassPathXmlApplicationContext("Beans.xml");
+ CustomEventPublisher cvp =
+ (CustomEventPublisher) context.getBean("customEventPublisher");
+ cvp.publish();
+ cvp.publish();
+ }
+}
+```
+
+ļ?**Beans.xml**
+
+```
+
+
+
+
+
+
+
+
+
+```
+
+һ˴Դ bean ļǾͿиӦóӦóһжϢ
+
+```
+My Custom Event
+My Custom Event
+```
+
+# ο
+https://www.w3cschool.cn/wkspring
+https://www.runoob.com/w3cnote/basic-knowledge-summary-of-spring.html
+http://codepub.cn/2015/06/21/Basic-knowledge-summary-of-Spring
+https://dunwu.github.io/spring-tutorial
+https://mszlu.com/java/spring
+http://c.biancheng.net/spring/aop-module.html
\ No newline at end of file
diff --git "a/docs/spring/Spring\344\270\255\347\232\204\350\265\204\346\272\220\347\256\241\347\220\206.md" "b/docs/spring/Spring\344\270\255\347\232\204\350\265\204\346\272\220\347\256\241\347\220\206.md"
new file mode 100644
index 0000000..09874af
--- /dev/null
+++ "b/docs/spring/Spring\344\270\255\347\232\204\350\265\204\346\272\220\347\256\241\347\220\206.md"
@@ -0,0 +1,309 @@
+## Resource ӿ
+
+Ա URL ʻƣSpring `org.springframework.core.io.Resource` ӿڳ˶ԵײԴķʽӿڣṩһõķʷʽ
+
+
+
+```
+public interface Resource extends InputStreamSource {
+
+ boolean exists();
+
+ boolean isReadable();
+
+ boolean isOpen();
+
+ boolean isFile();
+
+ URL getURL() throws IOException;
+
+ URI getURI() throws IOException;
+
+ File getFile() throws IOException;
+
+ ReadableByteChannel readableChannel() throws IOException;
+
+ long contentLength() throws IOException;
+
+ long lastModified() throws IOException;
+
+ Resource createRelative(String relativePath) throws IOException;
+
+ String getFilename();
+
+ String getDescription();
+}
+
+```
+
+
+
+ `Resource` ӿڵĶʾչ `InputStreamSource` ӿڡ`Resource` ĵķ£
+
+* `getInputStream()` - λҴǰԴصǰԴ `InputStream`ÿεö᷵һµ `InputStream`Ҫر
+* `exists()` - жϵǰԴǷĴڡ
+* `isOpen()` - жϵǰԴǷһѴ `InputStream`Ϊ true `InputStream` ܱζȡֻȡһȻرԱԴй©гԴʵַ false`InputStreamResource` ⡣
+* `getDescription()` - صǰԴԴʱԴڴϢһ˵ԴһȫļƣǵǰԴʵ URL
+
+ Spring Դӿڣ
+
+| | ӿ |
+| --- | --- |
+| | `org.springframework.core.io.InputStreamSource` |
+| ֻԴ | `org.springframework.core.io.Resource` |
+| дԴ | `org.springframework.core.io.WritableResource` |
+| Դ | `org.springframework.core.io.support.EncodedResource` |
+| Դ | `org.springframework.core.io.ContextResource` |
+
+
+
+
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/a1549f/#%E5%86%85%E7%BD%AE%E7%9A%84-resource-%E5%AE%9E%E7%8E%B0)õ Resource ʵ
+
+Spring õ Resource ʵ֣
+
+| ԴԴ | ǰ | ˵ |
+| --- | --- | --- |
+| [`UrlResource`(opens new window)](https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#resources-implementations-urlresource) | `file:``https:``ftp:` | `UrlResource` װһ `java.net.URL` **ڷʿͨ URL ʵκζ**ļHTTPS ĿꡢFTP Ŀȡ URL ַͨʽʾ˿ʹʵıǰָʾһ URL һ URL ͵ `file`ڷļϵͳ·`https`ͨ HTTPS ЭԴ`ftp`ͨ FTP Դȵȡ |
+| [`ClassPathResource`(opens new window)](https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#resources-implementations-classpathresource) | `classpath:` | `ClassPathResource` **·ϼԴ**ʹ߳ļָ class еһԴ |
+| [`FileSystemResource`(opens new window)](https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#resources-implementations-filesystemresource) | `file:` | `FileSystemResource` ** `java.io.File` Դʵ**֧ `java.nio.file.Path` Ӧ Spring ıַ·ת`FileSystemResource` ֽ֧Ϊļ URL |
+| [`PathResource`(opens new window)](https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#resources-implementations-pathresource) | | `PathResource` `java.nio.file.Path` Դʵ֡ |
+| [`ServletContextResource`(opens new window)](https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#resources-implementations-servletcontextresource) | | `ServletContextResource` ** `ServletContext` Դʵ**ʾӦ Web ӦóĿ¼е· |
+| [`InputStreamResource`(opens new window)](https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#resources-implementations-inputstreamresource) | | `InputStreamResource` **ָ `InputStream` Դʵ**ע⣺ `InputStream` ѱԶζȡ |
+| [`ByteArrayResource`(opens new window)](https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#resources-implementations-bytearrayresource) | | `ByteArrayResource` ָĶԴʵ֡Ϊֽ鴴һ `ByteArrayInputStream` |
+
+
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/a1549f/#resourceloader-%E6%8E%A5%E5%8F%A3)ResourceLoader ӿ
+
+`ResourceLoader` ӿڼ `Resource` 䶨£
+
+
+
+```
+public interface ResourceLoader {
+
+ Resource getResource(String location);
+
+ ClassLoader getClassLoader();
+}
+
+```
+
+
+
+Spring Ҫ ResourceLoader ʵ֣
+
+
+
+Spring Уе `ApplicationContext` ʵ `ResourceLoader` ӿڡˣ `ApplicationContext` ͨ `getResource()` ȡ `Resource` ʵ
+
+ʾ
+
+
+
+```
+// ûָԴǰSpring ᳢ԷغʵԴ
+Resource template = ctx.getResource("some/resource/path/myTemplate.txt");
+// ָ classpath: ǰSpring ǿʹ ClassPathResource
+Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt");
+// ָ file:http URL ǰSpring ǿʹ UrlResource
+Resource template = ctx.getResource("file:///some/resource/path/myTemplate.txt");
+Resource template = ctx.getResource("http://myhost.com/resource/path/myTemplate.txt");
+
+```
+
+
+
+±о Spring ݸλ·ԴIJԣ
+
+| ǰ | | ˵ |
+| --- | --- | --- |
+| `classpath:` | `classpath:com/myapp/config.xml` | · |
+| `file:` | `file:///data/config.xml` | URL ʽļϵͳ |
+| `http:` | `http://myserver/logo.png` | URL ʽ |
+| | `/data/config.xml` | ɵײ ApplicationContext ʵ־ |
+
+
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/a1549f/#resourcepatternresolver-%E6%8E%A5%E5%8F%A3)ResourcePatternResolver ӿ
+
+`ResourcePatternResolver` ӿ `ResourceLoader` ӿڵչǶԣλģʽ `Resource`
+
+
+
+```
+public interface ResourcePatternResolver extends ResourceLoader {
+
+ String CLASSPATH_ALL_URL_PREFIX = "classpath*:";
+
+ Resource[] getResources(String locationPattern) throws IOException;
+}
+
+```
+
+
+
+`PathMatchingResourcePatternResolver` һʵ֣ `ApplicationContext` ֮ʹãҲԱ `ResourceArrayPropertyEditor` `Resource[]` bean ԡ`PathMatchingResourcePatternResolver` ָܹԴλ·Ϊһƥ `Resource`
+
+> ע⣺κα `ApplicationContext` еĬ `ResourceLoader` ʵ `PathMatchingResourcePatternResolver` һʵʵ `ResourcePatternResolver` ӿڡ
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/a1549f/#resourceloaderaware-%E6%8E%A5%E5%8F%A3)ResourceLoaderAware ӿ
+
+`ResourceLoaderAware` ӿһĻصӿڣṩ `ResourceLoader` õĶ`ResourceLoaderAware` ӿڶ£
+
+
+
+```
+public interface ResourceLoaderAware {
+ void setResourceLoader(ResourceLoader resourceLoader);
+}
+
+```
+
+
+
+һʵ `ResourceLoaderAware` ӦóУΪ Spring beanʱᱻӦóʶΪ `ResourceLoaderAware`ȻӦóĻ `setResourceLoader(ResourceLoader)`ΪṩסSpring еӦóĶʵ `ResourceLoader` ӿڣ
+
+ `ApplicationContext` һ `ResourceLoader` bean ʵ `ApplicationContextAware` ӿڲֱʹṩӦóԴ ǣһ˵ֻҪЩʹרŵ `ResourceLoader` ӿڡ ô뽫ϵԴؽӿڣԱΪʵóӿڣϵ Spring `ApplicationContext` ӿڡ
+
+ӦóУʹ `ResourceLoader` ԶװΪʵ `ResourceLoaderAware` ӿڵͳĹ캯 `byType` ԶװģʽֱܹΪ캯 setter ṩ `ResourceLoader` Ϊ˻øԣԶװֶκͶ뿼ʹûעԶװ书ܡ £`ResourceLoader` ԶӵҪ `ResourceLoader` ͵ֶΡ캯УֻҪֶΡ캯 `@Autowired` ע⼴ɡ
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/a1549f/#%E8%B5%84%E6%BA%90%E4%BE%9D%E8%B5%96)Դ
+
+ bean Ҫͨijֶ̬ȷṩԴ·ô bean ʹ `ResourceLoader` `ResourcePatternResolver` ӿԴ 磬Ǽijģ壬ضԴȡûĽɫ ԴǾ̬ģȫ `ResourceLoader` ӿڣ `ResourcePatternResolver` ӿڣʹã bean Ҫ `Resource` ԣעġ
+
+ʹעЩԱüԭӦóĶעᲢʹһ JavaBeans `PropertyEditor`Խ `String` ·תΪ `Resource` 磬 MyBean һ `Resource` ͵ģԡ
+
+ʾ
+
+
+
+```
+
+
+
+
+```
+
+
+
+ע⣬õģԴ·ûǰΪӦóı `ResourceLoader`ԴҪͨ `ClassPathResource``FileSystemResource` ServletContextResource أȡĵȷ͡
+
+ҪǿʹضԴͣʹǰ ʾʾǿʹ `ClassPathResource` `UrlResource`ڷļϵͳļ
+
+
+
+```
+
+
+
+```
+
+
+
+ͨ `@Value` עԴļ `myTemplate.txt`ʾ£
+
+
+
+```
+@Component
+public class MyBean {
+
+ private final Resource template;
+
+ public MyBean(@Value("${template.path}") Resource template) {
+ this.template = template;
+ }
+
+ // ...
+}
+
+```
+
+
+
+Spring `PropertyEditor` Դļ·ַ `Resource` ע뵽 MyBean Ĺ췽
+
+ҪضԴļʹ `classpath*:` ǰ磺`classpath*:/config/templates/*.txt`
+
+
+
+```
+@Component
+public class MyBean {
+
+ private final Resource[] templates;
+
+ public MyBean(@Value("${templates.path}") Resource[] templates) {
+ this.templates = templates;
+ }
+
+ // ...
+}
+
+```
+
+
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/a1549f/#%E5%BA%94%E7%94%A8%E4%B8%8A%E4%B8%8B%E6%96%87%E5%92%8C%E8%B5%84%E6%BA%90%E8%B7%AF%E5%BE%84)ӦĺԴ·
+
+### [#](https://dunwu.github.io/spring-tutorial/pages/a1549f/#%E6%9E%84%E9%80%A0%E5%BA%94%E7%94%A8%E4%B8%8A%E4%B8%8B%E6%96%87)Ӧ
+
+ӦĹ캯ضӦַַͣͨΪԴλ·繹Ķ XML ļ
+
+ʾ
+
+
+
+```
+ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml");
+ApplicationContext ctx = new FileSystemXmlApplicationContext("conf/appContext.xml");
+ApplicationContext ctx = new FileSystemXmlApplicationContext("classpath:conf/appContext.xml");
+ApplicationContext ctx = new ClassPathXmlApplicationContext(
+ new String[] {"services.xml", "daos.xml"}, MessengerService.class);
+
+```
+
+
+
+### [#](https://dunwu.github.io/spring-tutorial/pages/a1549f/#%E4%BD%BF%E7%94%A8%E9%80%9A%E9%85%8D%E7%AC%A6%E6%9E%84%E9%80%A0%E5%BA%94%E7%94%A8%E4%B8%8A%E4%B8%8B%E6%96%87)ʹͨӦ
+
+ApplicationContext еԴ·ǵһ·һһӳ䵽ĿԴҲͨʽɰ classpath*Ҳǰ ant ʽʹ spring PathMatcher ƥ䣩
+
+ʾ
+
+
+
+```
+ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml");
+
+```
+
+
+
+ʹ `classpath*` ʾ·ƥļƵԴᱻȡ(Ͼǵ ClassLoader.getResources() ŽȡԴװյӦġ
+
+λ·ಿ֣`classpath*:` ǰ PathMatcher ʹã磺`classpath*:META-INF/*-beans.xml`
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/a1549f/#%E9%97%AE%E9%A2%98)
+
+Spring ԴЩͣ
+
+* XML Դ
+* Properties Դ
+* YAML Դ
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/a1549f/#%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99)ο
+
+* [Spring ٷĵ֮ Core Technologies(opens new window)](https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans)
+* [С署 Spring ı˼롷](https://time.geekbang.org/course/intro/265)
+
+# ο
+https://www.w3cschool.cn/wkspring
+https://www.runoob.com/w3cnote/basic-knowledge-summary-of-spring.html
+http://codepub.cn/2015/06/21/Basic-knowledge-summary-of-Spring
+https://dunwu.github.io/spring-tutorial
+https://mszlu.com/java/spring
+http://c.biancheng.net/spring/aop-module.html
\ No newline at end of file
diff --git "a/docs/spring/Spring\344\270\255\347\232\204\351\205\215\347\275\256\345\205\203\346\225\260\346\215\256\357\274\210\347\256\241\347\220\206\351\205\215\347\275\256\347\232\204\345\237\272\346\234\254\346\225\260\346\215\256\357\274\211.md" "b/docs/spring/Spring\344\270\255\347\232\204\351\205\215\347\275\256\345\205\203\346\225\260\346\215\256\357\274\210\347\256\241\347\220\206\351\205\215\347\275\256\347\232\204\345\237\272\346\234\254\346\225\260\346\215\256\357\274\211.md"
new file mode 100644
index 0000000..8589b50
--- /dev/null
+++ "b/docs/spring/Spring\344\270\255\347\232\204\351\205\215\347\275\256\345\205\203\346\225\260\346\215\256\357\274\210\347\256\241\347\220\206\351\205\215\347\275\256\347\232\204\345\237\272\346\234\254\346\225\260\346\215\256\357\274\211.md"
@@ -0,0 +1,298 @@
+
+
+# Spring Ԫ
+
+
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/55f315/#spring-%E9%85%8D%E7%BD%AE%E5%85%83%E4%BF%A1%E6%81%AF)Spring ԪϢ
+
+* Spring Bean ԪϢ - BeanDefinition
+* Spring Bean ԪϢ - PropertyValues
+* Spring ԪϢ
+* Spring ⲿԪϢ - PropertySource
+* Spring Profile ԪϢ - @Profile
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/55f315/#spring-bean-%E9%85%8D%E7%BD%AE%E5%85%83%E4%BF%A1%E6%81%AF)Spring Bean ԪϢ
+
+Bean ԪϢ - BeanDefinition
+
+* GenericBeanDefinitionͨ BeanDefinition
+* RootBeanDefinition Parent BeanDefinition ߺϲ BeanDefinition
+* AnnotatedBeanDefinitionעע BeanDefinition
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/55f315/#spring-bean-%E5%B1%9E%E6%80%A7%E5%85%83%E4%BF%A1%E6%81%AF)Spring Bean ԪϢ
+
+* Bean ԪϢ - PropertyValues
+ * ʵ - MutablePropertyValues
+ * ԪسԱ - PropertyValue
+* Bean Ĵ洢 - AttributeAccessor
+* Bean ԪϢԪ - BeanMetadataElement
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/55f315/#spring-%E5%AE%B9%E5%99%A8%E9%85%8D%E7%BD%AE%E5%85%83%E4%BF%A1%E6%81%AF)Spring ԪϢ
+
+Spring XML ԪϢ - beans Ԫ
+
+| beans Ԫ | Ĭֵ | ʹó |
+| --- | --- | --- |
+| profile | nullգ | Spring Profiles ֵ |
+| default-lazy-init | default | outter beans default-lazy-init Դʱ̳иֵΪfalse |
+| default-merge | default | outter beans default-merge Դʱ̳иֵΪfalse |
+| default-autowire | default | outter beans default-autowire Դʱ̳иֵΪno |
+| default-autowire-candidates | nullգ | Ĭ Spring Beans pattern |
+| default-init-method | nullգ | Ĭ Spring Beans Զʼ |
+| default-destroy-method | nullգ | Ĭ Spring Beans Զٷ |
+
+Spring XML ԪϢ - Ӧ
+
+| XML Ԫ | ʹó |
+| --- | --- |
+| ` ` | Spring ע |
+| ` ` | Spring @Component ԼԶעɨ |
+| ` ` | Spring LoadTimeWeaver |
+| ` ` | ¶ Spring Beans Ϊ JMX Beans |
+| ` ` | ǰƽ̨Ϊ MBeanServer |
+| ` ` | ⲿԴΪ Spring |
+| ` ` | ⲿԴ Spring |
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/55f315/#%E5%9F%BA%E4%BA%8E-xml-%E6%96%87%E4%BB%B6%E8%A3%85%E8%BD%BD-spring-bean-%E9%85%8D%E7%BD%AE%E5%85%83%E4%BF%A1%E6%81%AF) XML ļװ Spring Bean ԪϢ
+
+ײʵ - XmlBeanDefinitionReader
+
+| XML Ԫ | ʹó |
+| --- | --- |
+| ` ` | XML ԴµĶ Spring Beans |
+| ` ` | Spring Bean 壨BeanDefinition |
+| ` ` | Ϊ Spring Bean 壨BeanDefinitionӳ |
+| ` ` | ⲿ Spring XML Դ |
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/55f315/#%E5%9F%BA%E4%BA%8E-properties-%E6%96%87%E4%BB%B6%E8%A3%85%E8%BD%BD-spring-bean-%E9%85%8D%E7%BD%AE%E5%85%83%E4%BF%A1%E6%81%AF) Properties ļװ Spring Bean ԪϢ
+
+ײʵ - PropertiesBeanDefinitionReader
+
+| Properties | ʹó |
+| --- | --- |
+| `class` | Bean ȫ |
+| `abstract` | ǷΪ BeanDefinition |
+| `parent` | ָ parent BeanDefinition |
+| `lazy-init` | ǷΪӳٳʼ |
+| `ref` | Bean |
+| `scope` | Bean scope |
+| ${n} | n ʾ n+1 |
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/55f315/#%E5%9F%BA%E4%BA%8E-java-%E6%B3%A8%E8%A7%A3%E8%A3%85%E8%BD%BD-spring-bean-%E9%85%8D%E7%BD%AE%E5%85%83%E4%BF%A1%E6%81%AF) Java עװ Spring Bean ԪϢ
+
+Spring ģʽע
+
+| Spring ע | ˵ | ʼ汾 |
+| --- | --- | --- |
+| `@Repository` | ݲִģʽע | 2.0 |
+| `@Component` | ͨģʽע | 2.5 |
+| `@Service` | ģʽע | 2.5 |
+| `@Controller` | Web ģʽע | 2.5 |
+| `@Configuration` | ģʽע | 3.0 |
+
+Spring Bean ע
+
+| Spring ע | ˵ | ʼ汾 |
+| --- | --- | --- |
+| `@Bean` | 滻 XML Ԫ?`` | 3.0 |
+| `@DependsOn` | XML ?` ` | 3.0 |
+| `@Lazy` | XML ?` ` | 3.0 |
+| `@Primary` | 滻 XML Ԫ?` ` | 3.0 |
+| `@Role` | 滻 XML Ԫ?` ` | 3.1 |
+| `@Lookup` | XML ?`` | 4.1 |
+
+Spring Bean עע
+
+| Spring ע | ˵ | ʼ汾 |
+| --- | --- | --- |
+| `@Autowired` | Bean ע룬ֶ֧ҷʽ | 2.5 |
+| `@Qualifier` | ϸȵ @Autowired | 2.5 |
+
+?
+
+| Java ע | ˵ | ʼ汾 |
+| --- | --- | --- |
+| @Resource | @Autowired | 2.5 |
+| @Inject | @Autowired | 2.5 |
+
+Spring Bean װע
+
+| Spring ע | ˵ | ʼ汾 |
+| --- | --- | --- |
+| @Profile | ûװ | 3.1 |
+| @Conditional | װ | 4.0 |
+
+Spring Bean ڻصע
+
+| Spring ע | ˵ | ʼ汾 |
+| --- | --- | --- |
+| @PostConstruct | 滻 XML Ԫ? InitializingBean | 2.5 |
+| @PreDestroy | 滻 XML Ԫ? DisposableBean | 2.5 |
+
+Spring BeanDefinition ע
+
+| Spring ע | ˵ | ʼ汾 |
+| --- | --- | --- |
+| XML Դ | XmlBeanDefinitionReader | 1.0 |
+| Properties Դ | PropertiesBeanDefinitionReader | 1.0 |
+| Java ע | AnnotatedBeanDefinitionReader | 3.0 |
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/55f315/#spring-bean-%E9%85%8D%E7%BD%AE%E5%85%83%E4%BF%A1%E6%81%AF%E5%BA%95%E5%B1%82%E5%AE%9E%E7%8E%B0)Spring Bean ԪϢײʵ
+
+### [#](https://dunwu.github.io/spring-tutorial/pages/55f315/#spring-xml-%E8%B5%84%E6%BA%90-beandefinition-%E8%A7%A3%E6%9E%90%E4%B8%8E%E6%B3%A8%E5%86%8C)Spring XML Դ BeanDefinition ע
+
+ API - XmlBeanDefinitionReader
+
+* Դ - Resource
+* ײ - BeanDefinitionDocumentReader
+ * XML - Java DOM Level 3 API
+ * BeanDefinition - BeanDefinitionParserDelegate
+ * BeanDefinition ע - BeanDefinitionRegistry
+
+### [#](https://dunwu.github.io/spring-tutorial/pages/55f315/#spring-properties-%E8%B5%84%E6%BA%90-beandefinition-%E8%A7%A3%E6%9E%90%E4%B8%8E%E6%B3%A8%E5%86%8C)Spring Properties Դ BeanDefinition ע
+
+ API - PropertiesBeanDefinitionReader
+
+* Դ
+ * ֽ - Resource
+ * ַ - EncodedResouce
+* ײ
+ * 洢 - java.util.Properties
+ * BeanDefinition - API ڲʵ
+ * BeanDefinition ע - BeanDefinitionRegistry
+
+### [#](https://dunwu.github.io/spring-tutorial/pages/55f315/#spring-java-%E6%B3%A8%E5%86%8C-beandefinition-%E8%A7%A3%E6%9E%90%E4%B8%8E%E6%B3%A8%E5%86%8C)Spring Java ע BeanDefinition ע
+
+ API - AnnotatedBeanDefinitionReader
+
+* Դ
+ * - java.lang.Class
+* ײ
+ * - ConditionEvaluator
+ * Bean Χ - ScopeMetadataResolver
+ * BeanDefinition - ڲ API ʵ
+ * BeanDefinition - AnnotationConfigUtils.processCommonDefinitionAnnotations
+ * BeanDefinition ע - BeanDefinitionRegistry
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/55f315/#%E5%9F%BA%E4%BA%8E-xml-%E6%96%87%E4%BB%B6%E8%A3%85%E8%BD%BD-spring-ioc-%E5%AE%B9%E5%99%A8%E9%85%8D%E7%BD%AE%E5%85%83%E4%BF%A1%E6%81%AF) XML ļװ Spring IoC ԪϢ
+
+Spring IoC XML
+
+| ռ | ģ | Schema Դ URL |
+| --- | --- | --- |
+| beans | spring-beans | https://www.springframework.org/schema/beans/spring-beans.xsd |
+| context | spring-context | https://www.springframework.org/schema/context/spring-context.xsd |
+| aop | spring-aop | https://www.springframework.org/schema/aop/spring-aop.xsd |
+| tx | spring-tx | https://www.springframework.org/schema/tx/spring-tx.xsd |
+| util | spring-beans | beans https://www.springframework.org/schema/util/spring-util.xsd |
+| tool | spring-beans | https://www.springframework.org/schema/tool/spring-tool.xsd |
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/55f315/#%E5%9F%BA%E4%BA%8E-java-%E6%B3%A8%E8%A7%A3%E8%A3%85%E8%BD%BD-spring-ioc-%E5%AE%B9%E5%99%A8%E9%85%8D%E7%BD%AE%E5%85%83%E4%BF%A1%E6%81%AF) Java עװ Spring IoC ԪϢ
+
+Spring IoC װע
+
+| Spring ע | ˵ | ʼ汾 |
+| --- | --- | --- |
+| @ImportResource | 滻 XML Ԫ?`` | 3.0 |
+| @Import | Configuration Class | 3.0 |
+| @ComponentScan | ɨָ package ±ע Spring ģʽע | 3.1 |
+
+Spring IoC ע
+
+| Spring ע | ˵ | ʼ汾 |
+| --- | --- | --- |
+| @PropertySource | Գ PropertySource ע | 3.1 |
+| @PropertySources | @PropertySource ע | 4.0 |
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/55f315/#%E5%9F%BA%E4%BA%8E-extensible-xml-authoring-%E6%89%A9%E5%B1%95-springxml-%E5%85%83%E7%B4%A0) Extensible XML authoring չ SpringXML Ԫ
+
+Spring XML չ
+
+* д XML Schema ļ XML ṹ
+* Զ NamespaceHandler ʵ֣ռ
+* Զ BeanDefinitionParser ʵ֣XML Ԫ BeanDefinition
+* ע XML չռ XML Schema ӳ
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/55f315/#extensible-xml-authoring-%E6%89%A9%E5%B1%95%E5%8E%9F%E7%90%86)Extensible XML authoring չԭ
+
+### [#](https://dunwu.github.io/spring-tutorial/pages/55f315/#%E8%A7%A6%E5%8F%91%E6%97%B6%E6%9C%BA)ʱ
+
+* AbstractApplicationContext#obtainFreshBeanFactory
+ * AbstractRefreshableApplicationContext#refreshBeanFactory
+ * AbstractXmlApplicationContext#loadBeanDefinitions
+ * ...
+ * XmlBeanDefinitionReader#doLoadBeanDefinitions
+ * ...
+ * BeanDefinitionParserDelegate#parseCustomElement
+
+### [#](https://dunwu.github.io/spring-tutorial/pages/55f315/#%E6%A0%B8%E5%BF%83%E6%B5%81%E7%A8%8B)
+
+BeanDefinitionParserDelegate#parseCustomElement(org.w3c.dom.Element, BeanDefinition)
+
+* ȡ namespace
+* ͨ namespace NamespaceHandler
+* ParserContext
+* Ԫأȡ BeanDefinintion
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/55f315/#%E5%9F%BA%E4%BA%8E-properties-%E6%96%87%E4%BB%B6%E8%A3%85%E8%BD%BD%E5%A4%96%E9%83%A8%E5%8C%96%E9%85%8D%E7%BD%AE) Properties ļװⲿ
+
+ע
+
+* @org.springframework.context.annotation.PropertySource
+* @org.springframework.context.annotation.PropertySources
+
+API
+
+* org.springframework.core.env.PropertySource
+* org.springframework.core.env.PropertySources
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/55f315/#%E5%9F%BA%E4%BA%8E-yaml-%E6%96%87%E4%BB%B6%E8%A3%85%E8%BD%BD%E5%A4%96%E9%83%A8%E5%8C%96%E9%85%8D%E7%BD%AE) YAML ļװⲿ
+
+API
+
+* org.springframework.beans.factory.config.YamlProcessor
+ * org.springframework.beans.factory.config.YamlMapFactoryBean
+ * org.springframework.beans.factory.config.YamlPropertiesFactoryBean
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/55f315/#%E9%97%AE%E9%A2%98)
+
+**Spring Ƚ XML Schema Щ**
+
+| ռ | ģ | Schema Դ URL |
+| --- | --- | --- |
+| beans | spring-beans | https://www.springframework.org/schema/beans/spring-beans.xsd |
+| context | spring-context | https://www.springframework.org/schema/context/spring-context.xsd |
+| aop | spring-aop | https://www.springframework.org/schema/aop/spring-aop.xsd |
+| tx | spring-tx | https://www.springframework.org/schema/tx/spring-tx.xsd |
+| util | spring-beans | beans https://www.springframework.org/schema/util/spring-util.xsd |
+| tool | spring-beans | https://www.springframework.org/schema/tool/spring-tool.xsd |
+
+**Spring ԪϢЩ**
+
+* Bean ԪϢͨý飨 XMLProeprties ȣ BeanDefinition
+* IoC ԪϢͨý飨 XMLProeprties ȣ IoC ΪעAOP
+* ⲿãͨԴ ProeprtiesYAML ȣ PropertySource
+* Spring Profileͨⲿãṩ֧
+
+**Extensible XML authoring ȱ**
+
+* ߸ӶȣԱҪϤ XML Schemaspring.handlersspring.schemas Լ Spring API
+* ǶԪֽ֧ͨҪʹ÷ݹǶķʽǶףӣԪ
+* XML ܽϲSpring XML DOM Level 3 API ʵ֣ API ⣬Ȼܽϲ
+* XML ֲԲܺͱԵ XML ܣ JAXB
+
+## [#](https://dunwu.github.io/spring-tutorial/pages/55f315/#%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99)ο
+
+* [Spring ٷĵ֮ Core Technologies(opens new window)](https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans)
+* [С署 Spring ı˼롷(opens new window)](https://time.geekbang.org/course/intro/265)
+
+
+
+# ο
+https://www.w3cschool.cn/wkspring
+https://www.runoob.com/w3cnote/basic-knowledge-summary-of-spring.html
+http://codepub.cn/2015/06/21/Basic-knowledge-summary-of-Spring
+https://dunwu.github.io/spring-tutorial
+https://mszlu.com/java/spring
+http://c.biancheng.net/spring/aop-module.html
\ No newline at end of file
diff --git "a/docs/spring/Spring\344\272\213\345\212\241\345\237\272\346\234\254\347\224\250\346\263\225.md" "b/docs/spring/Spring\344\272\213\345\212\241\345\237\272\346\234\254\347\224\250\346\263\225.md"
new file mode 100644
index 0000000..85723ac
--- /dev/null
+++ "b/docs/spring/Spring\344\272\213\345\212\241\345\237\272\346\234\254\347\224\250\346\263\225.md"
@@ -0,0 +1,430 @@
+# SpringĽӿ
+
+[Spring](http://www.voidme.com/spring) ǻ AOP ʵֵģ AOP ԷΪλġSpring ԷֱΪΪ뼶ֻͳʱԣЩṩӦõķԡ
+
+ [Java](http://www.voidme.com/java) EE õķֲģʽУSpring λҵ㣬ṩĽ
+
+ Spring ѹ libs Ŀ¼УһΪ spring-tx-3.2.13.RELEASE.jar ļļ Spring ṩ JAR аĽӿڣPlatformTransactionManagerTransactionDefinition TransactionStatus
+
+ JAR ĺ jar ij zip ʽѹѹѹļе \org\springframework\transaction Ŀ¼Ŀ¼еļͼ 1 ʾ
+
+
+ͼ 1 Ľӿ
+
+ͼ 1 УעļDZڽҪĺĽӿڡĽӿڵüṩķ¡
+
+#### 1\. PlatformTransactionManager
+
+PlatformTransactionManager ӿ Spring ṩƽ̨ڹýӿṩ¡
+
+* TransactionStatus getTransactionTransactionDefinition definitionڻȡ״̬Ϣ
+* void commitTransactionStatus statusύ
+* void rollbackTransactionStatus statusڻع
+
+ĿУSpring xml õϸϢװ TransactionDefinition УȻͨ getTransaction() ״̬TransactionStatusһIJ
+
+#### 2\. TransactionDefinition
+
+TransactionDefinition ӿ壨ĶṩϢȡķа¡
+
+* String getName()ȡơ
+* int getIsolationLevel()ȡĸ뼶
+* int getPropagationBehavior()ȡĴΪ
+* int getTimeout()ȡijʱʱ䡣
+* boolean isReadOnly()ȡǷֻ
+
+УĴΪָͬһУͬǰʹõΪ 1 ʾ
+
+ 1 Ϊ
+| | ֵ | |
+| --- | --- | --- |
+| PROPAGATION_REQUIRED | required | ֵ֧ǰ A ѾУ B ֱʹá |
+| PROPAGATION_SUPPORTS | supports | ֵ֧ǰ A ѾУ B ֱʹáԷ״ִ̬ |
+| PROPAGATION_MANDATORY | mandatory | ֵ֧ǰ A û׳쳣 |
+| PROPAGATION_REQUIRES_NEW | requires_new | µ A ѾУ A |
+| PROPAGATION_NOT_SUPPORTED | not_supported | ֵ֧ǰԷ״ִ̬С A ѾУ |
+| PROPAGATION_NEVER | never | ֵ֧ǰ A У׳쳣 |
+| PROPAGATION.NESTED | nested | Ƕײ㽫ʹ Savepoint γǶ |
+
+УΪԿǷҪԼδ
+
+ͨ£ݵIJѯıԭݣԲҪݵӡĺɾȲûָĴΪ Spring3 ĬϵĴΪ required
+
+#### 3\. TransactionStatus
+
+TransactionStatus ӿ״̬ijһʱ״̬Ϣа 2 ʾ
+
+ 2 IJ
+| | ˵ |
+| --- | --- |
+| void flush() | ˢ |
+| boolean hasSavepoint() | ȡǷڱ |
+| boolean isCompleted() | ȡǷ |
+| boolean isNewTransaction() | ȡǷ |
+| boolean isRollbackOnly() | ȡǷع |
+| void setRollbackOnly() | ع |
+
+# SpringʽXMLʽʵ֣
+
+[Spring](http://www.voidme.com/spring) ַʽһǴͳıʽͨдʵֵһǻ AOP ʵֵʽʵʿУʽʹãֻ Spring ʽϸ⡣
+
+Spring ʽڵײ AOP ŵ̵ͨķʽֻҪļнصĹͿԽӦõҵС
+
+Spring ʵʽҪַʽ
+
+* XML ʽʽ
+* ͨ Annotation עⷽʽ
+
+ͨת˵İʹ XML ķʽʵ Spring ʽ
+
+#### 1\. Ŀ
+
+ MyEclipse дһΪ springDemo03 Web Ŀ Spring ֺ֧ JAR Ƶ Web Ŀ lib Ŀ¼Уӵ·¡ӵ JAR ͼ 1 ʾ
+
+
+ͼ 1 ҪJAR
+
+ͼ 1 пԿӵ spring-tx-3.2.13.RELEASE.jarԼ [MySQL](http://www.voidme.com/mysql) JDBC C3P0 JAR
+
+#### 2\. ݿ⡢Լ
+
+ MySQL дһΪ spring ݿ⣬Ȼڸݿдһ account вݣ SQL ִʾ
+
+ CREATE DATABASE spring;
+USE spring;
+CREATE TABLE account (
+ id INT (11) PRIMARY KEY AUTO_INCREMENT,
+ username VARCHAR(20) NOT NULL,
+ money INT DEFAULT NULL
+);
+INSERT INTO account VALUES (1,'zhangsan',1000);
+INSERT INTO account VALUES (2,'lisi',1000);
+
+ִк account еͼ 2 ʾ
+
+
+ͼ 2 ִн
+
+#### 3\. c3p0-db.properties
+
+Ŀ src ´һΪ c3p0-db.properties ļʹ C3P0 ԴҪڸļã
+
+jdbc.driverClass = com.mysql.jdbc.Driver
+jdbc.jdbcUrl = jdbc:mysql://localhost:3306/spring
+jdbc.user = root
+jdbc.password = root
+
+#### 4\. ʵ DAO
+
+#### 1 AccountDao ӿ
+
+Ŀ src Ŀ¼´һΪ com.mengma.dao İڸð´һӿ AccountDaoڽӿдտķʾ
+
+ package com.mengma.dao;
+
+public interface AccountDao {
+ //
+ public void out(String outUser, int money);
+
+ // տ
+ public void in(String inUser, int money);
+}
+
+У out() in() ֱڱʾտ
+
+#### 2DAOӿʵ
+
+Ŀ src Ŀ¼´һΪ com.mengma.dao.impl İڸð´ʵ AccountDaoImplʾ
+
+ package com.mengma.dao.impl;
+
+import org.springframework.jdbc.core.JdbcTemplate;
+import com.mengma.dao.AccountDao;
+
+public class AccountDaoImpl implements AccountDao {
+ private JdbcTemplate jdbcTemplate;
+
+ public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
+ this.jdbcTemplate = jdbcTemplate;
+ }
+
+ // ʵַ
+ public void out(String outUser, int money) {
+ this.jdbcTemplate.update("update account set money =money-?"
+ + "where username =?", money, outUser);
+ }
+
+ // տʵַ
+ public void in(String inUser, int money) {
+ this.jdbcTemplate.update("update account set money =money+?"
+ + "where username =?", money, inUser);
+ }
+}
+
+Уʹ JdbcTemplate update() ʵ˸²
+
+#### 5\. ʵ Service
+
+#### 1 Service ӿ
+
+Ŀ src Ŀ¼´һΪ com.mengma.service İڸð´ӿ AccountServiceʾ
+
+ package com.mengma.service;
+
+public interface AccountService {
+ // ת
+ public void transfer(String outUser, String inUser, int money);
+}
+
+#### 2 Service ӿʵ
+
+Ŀ src Ŀ¼´һΪ com.mengma.service.impl İڸð´ʵ AccountServiceImplʾ
+
+ package com.mengma.service.impl;
+
+import com.mengma.dao.AccountDao;
+
+public class AccountServiceImpl {
+ private AccountDao accountDao;
+
+ public void setAccountDao(AccountDao accountDao) {
+ this.accountDao = accountDao;
+ }
+
+ public void transfer(String outUser, String inUser, int money) {
+ this.accountDao.out(outUser, money);
+ this.accountDao.in(inUser, money);
+ }
+}
+
+пԿʵ AccountService ӿڣת˵ķʵ֣ݲIJͬ DAO Ӧķ
+
+#### 6\. Spring ļ
+
+Ŀ src Ŀ¼´ Spirng ļ applicationContext.xml༭ʾ
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+У ǵĵ 613 14 дֱ AOP ռ 4250 дʹ ֪ͨݡ
+
+ 5258 дʹ Ƕ棬е 54 дӦ AspectJ ʽ com.mengma.service зӦ 57 дʹ ǽ֪ͨϣ AOP ʽɡ
+
+#### 7\.
+
+Ŀ src Ŀ¼´ com.mengma.test İڸð´ AccountTestʾ
+
+ package com.mengma.test;
+import org.junit.Test;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import com.mengma.service.AccountService;
+public class AccountTest {
+ @Test
+ public void test() {
+ // Spring
+ String xmlPath = "applicationContext.xml";
+ ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
+ xmlPath);
+ AccountService accountService = (AccountService) applicationContext
+ .getBean("accountService");
+ accountService.transfer("zhangsan", "lisi", 100);
+ }
+}
+
+ģתҵ zhangsan ˻ lisi ˻ת 100 Ԫʹ JUnit test() гɹѯ account ͼ 3 ʾ
+
+ͼ 3 IJѯпԿzhangsan ɹ lisi ת 100 Ԫ
+
+
+ͼ 3 ѯ
+
+ͨİģתʧܵڵ transfer() һд롰int i=1/0ģϵͳϵʾ
+
+ public void transfer(String outUser, String inUser, int money) {
+ this.accountDao.out(outUser, money);
+ //ģϵ
+ int i = 1/0;
+ this.accountDao.in(inUser, money);
+}
+
+² test() JUnit ̨Ϣͼ 4 ʾ
+
+
+ͼ 4 ̨
+
+ͼ 4 пԿִвԷʱ˳ 0 쳣Ϣʱٴβѯ account ѯͼ 5 ʾ
+
+ͼ 5 IJѯпԿеݲûз仯ڳִй׳쳣ύתʧܡɴ˿֪Spring Чˡ
+
+
+ͼ 5 ѯ
+
+# SpringʽAnnotationעⷽʽʵ֣
+
+ [Spring](http://www.voidme.com/spring) Уʹû XML ķʽʵʽ⣬ͨ Annotation עķʽʵʽ
+
+ʹ Annotation ķʽdzֻҪĿ£¡
+
+#### 1 Spring עʾ
+
+
+
+#### 2Ҫʹҵ߷ע @Transactional @Transactional IJ @Transactional IJͼ 1 ʾ
+
+
+ͼ 1 @Transactionalб
+
+ͨġ [SpringXMLʵ](http://www.voidme.com/spring/spring-transaction-management-by-xml)̳ת˵İʹ Annotation עķʽʵ Spring ʽ
+
+#### 1\. ע
+
+ Spring ļ applicationContext.xmlĺʾ
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+пԿԭļȣֻ֣Ӳע
+
+Ҫעǣѧϰ AOP עⷽʽʱҪļпעָɨЩµע⣬ûпעΪڵ 3335 ֶ AccountServiceImpl @Transactional עڸУԻֱЧ
+
+#### 2\. @Transactional ע
+
+ AccountServiceImplļ @Transactional ע⼰Ӻʾ
+
+ package com.mengma.service.impl;
+
+import org.springframework.transaction.annotation.Isolation;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.mengma.dao.AccountDao;
+
+@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false)
+public class AccountServiceImpl {
+ private AccountDao accountDao;
+
+ public void setAccountDao(AccountDao accountDao) {
+ this.accountDao = accountDao;
+ }
+
+ public void transfer(String outUser, String inUser, int money) {
+ this.accountDao.out(outUser, money);
+ // ģϵ
+ int i = 1 / 0;
+ this.accountDao.in(inUser, money);
+ }
+}
+
+Ҫעǣʹ @Transactional עʱ֮áзָ
+
+ʹ JUnit ٴ test() ʱ̨ͬͼ 2 ʾ쳣Ϣ˵ʹû Annotation עķʽͬʵ Spring ʽע͵ģϵĴвԣת˲ɡ
+
+
+ͼ 2 н
+
+# ο
+https://www.w3cschool.cn/wkspring
+https://www.runoob.com/w3cnote/basic-knowledge-summary-of-spring.html
+http://codepub.cn/2015/06/21/Basic-knowledge-summary-of-Spring
+https://dunwu.github.io/spring-tutorial
+https://mszlu.com/java/spring
+http://c.biancheng.net/spring/aop-module.html
\ No newline at end of file
diff --git "a/docs/spring/Spring\345\220\210\351\233\206.md" "b/docs/spring/Spring\345\220\210\351\233\206.md"
new file mode 100644
index 0000000..931264e
--- /dev/null
+++ "b/docs/spring/Spring\345\220\210\351\233\206.md"
@@ -0,0 +1,22 @@
+# Spring
+
+
+# SpringԴ
+
+# SpringMVC
+
+# SpringMVC Դ
+
+# SpringBoot
+## springbootǰ
+## springbootĻʹ
+## springbootijע
+## springbootĺ
+## springbootĻԭ
+## springbootԴ
+
+# SpringBoot Դ
+
+# SpringCloud
+# SpringCloud Դ
+
diff --git "a/docs/spring/Spring\345\256\271\345\231\250\344\270\216IOC.md" "b/docs/spring/Spring\345\256\271\345\231\250\344\270\216IOC.md"
new file mode 100644
index 0000000..35623db
--- /dev/null
+++ "b/docs/spring/Spring\345\256\271\345\231\250\344\270\216IOC.md"
@@ -0,0 +1,157 @@
+IoC Inversion of Control ļдΪƷתһżһ˼룬һҪ̷ָܹƳϡij
+
+Spring ͨ IoC Java ʵͳʼƶ֮ϵǽ IoC Java Ϊ Spring Beanʹùؼ new Java ûκ
+
+IoC Spring Ҫĺ֮һᴩ Spring ӵɳ̡
+
+## ƷתIoC
+
+ڴͳ Java ӦУһҪһеԻͨͨ new Object() ķʽߵĶȻʵԻĵáΪ˷ǿԽǰ߳Ϊߡ߳ΪߡҲ˵ű߶ĿȨ
+
+ Spring ӦУJava ĿȨ IoC 첡
+
+Աͨ XML ļע⡢Java ȷʽ Java ж壬 XML ļʹ ǩ Java ʹ @Component עȡ
+Spring ʱIoC Զݶ壬ЩЩ IoC ĶΪ Spring Bean
+Ҫʹij Bean ʱֱӴ IoC лȡͨ ApplicationContext getBean() Ҫֶͨ루 new Obejct() ķʽ
+
+IoC ı䲻ǴģǴ˼Ϸˡӻλĸı䡣ԭһҪʹʲôԴͻԼ Spring ӦУIoC Ȩ˱һĵȴ IoC ҪĶBean
+
+ְ淢˿ȨķתԭͨʵֵĶĴת IoC æʵ֣ǽ̳Ϊ Spring ġƷת
+
+## ע루DI
+
+˽ IoC ֮ǻҪ˽һdzҪĸע롣
+
+ע루Denpendency InjectionдΪ DI Martin Fowler 2004 ڶԡƷתнʱġMartin Fowler ΪƷתһʺܻɬ˺ֱӵ⡰ﷴתˡʹáע롱桰Ʒת
+
+УͶ֮ǴһֽĹϵ˵ϵһҪõһдһԣһĶ
+
+磬һΪ B Java ࣬Ĵ¡
+
+
+
+
+
+
+
+public class B {
+String bid;
+A a;
+}
+
+
+
+
+
+
+
+ӴԿB дһ A ͵Ķ aʱǾͿ˵ B Ķڶ aעǾǻ֡ϵġ
+
+֪Ʒת˼ Spring ĴڶУSpring ԶϵĶע뵽ǰУνġע롱
+
+ע뱾 [Spring Bean ע](http://c.biancheng.net/spring/attr-injection.html)һֻ֣һԶѡ
+
+## IoC Ĺԭ
+
+ Java Уϵͳеĸ֮䡢ģ֮䡢ϵͳӲϵͳ֮䣬ٶһϹϵ
+
+һϵͳ϶ȹߣôͻά⣬ȫûϵĴ뼸κιڼеĹܶҪ֮Эɡڳʱе˼һ㶼ڲӰϵͳܵǰ£ȵĽ϶ȡ
+
+IoC ײͨģʽJava ķơXML ȼ϶Ƚ͵ȣҪ¡
+
+ļ Bean.xmlУԸԼ֮ϵã
+ǿ IoC һIJƷ Spring Bean
+ʱزЩļõĻϢԼ֮ϵ
+IoC Java ķƣӦĶ Spring Beanϵע뵽ĶС
+
+ڶĻϢ֮ϵļжģûڴнϣ˼ʹı䣬ҲֻҪļнļɣ Java ģ Spring IoC ʵֽԭ
+
+## IoC ʵ
+
+IoC ˼ IoC ʵֵģIoC ײʵһ Bean Spring Ϊṩֲͬ IoC Ƿֱ BeanFactory ApplicationContext
+
+### BeanFactory
+
+BeanFactory IoC Ļʵ֣Ҳ Spring ṩ IoC ṩ IoC Ĺܣ org.springframework.beans.factory.BeanFactory ӿڶ塣
+
+BeanFactory أlazy-loadƣڼļʱ̴ Java ֻглȡʹãԶʱŻᴴ
+
+#### ʾ 1
+
+ͨһʵʾʾ BeanFactory ʹá
+
+1\. HelloSpring ĿУ MainApp ĴΪʹ BeanFactory ȡ HelloWorld Ķ¡
+
+
+
+
+
+
+
+public static void main(String[] args) {
+BeanFactory context = new ClassPathXmlApplicationContext("Beans.xml");
+HelloWorld obj = context.getBean("helloWorld", HelloWorld.class);
+obj.getMessage();
+}
+
+
+
+
+
+
+
+2. MainApp.javą¡
+
+ message : Hello World!
+
+> ע⣺BeanFactory Spring ڲʹýӿڣͨ²ṩԱʹá
+
+### ApplicationContext
+
+ApplicationContext BeanFactory ӿڵӽӿڣǶ BeanFactory չApplicationContext BeanFactory ĻҵĹܣ AOP̣ʻֵ֧ȡ
+
+ApplicationContext ӿõʵ࣬±
+
+| ʵ | | ʾ |
+| --- | --- | --- |
+| ClassPathXmlApplicationContext | · ClassPath ָ XML ļ ApplicationContext ʵ | ApplicationContext applicationContext = new ClassPathXmlApplicationContext(String configLocation); |
+| FileSystemXmlApplicationContext | ָļϵͳ·ָ XML ļ ApplicationContext ʵ | ApplicationContext applicationContext = new FileSystemXmlApplicationContext(String configLocation); |
+
+> ϱʾУ configLocation ָ Spring ļƺλã Beans.xml
+
+#### ʾ 2
+
+Ǿͨһʵʾ ApplicationContext ʹá
+
+1. HelloSpring Ŀ MainApp main() Ĵ룬¡
+
+
+
+
+
+
+````
+public static void main(String[] args) {
+//ʹ FileSystemXmlApplicationContext ָ·µļ Bean.xml
+BeanFactory context = new FileSystemXmlApplicationContext("D:\\eclipe workspace\\spring workspace\\HelloSpring\\src\\Beans.xml");
+HelloWorld obj = context.getBean("helloWorld", HelloWorld.class);
+obj.getMessage();
+}
+````
+
+
+
+
+
+
+2. MainApp.javą¡
+
+ message : Hello World!
+
+# ο
+https://www.w3cschool.cn/wkspring
+https://www.runoob.com/w3cnote/basic-knowledge-summary-of-spring.html
+http://codepub.cn/2015/06/21/Basic-knowledge-summary-of-Spring
+https://dunwu.github.io/spring-tutorial
+https://mszlu.com/java/spring
+http://c.biancheng.net/spring/aop-module.html
\ No newline at end of file
diff --git "a/docs/spring/Spring\345\270\270\350\247\201\346\263\250\350\247\243.md" "b/docs/spring/Spring\345\270\270\350\247\201\346\263\250\350\247\243.md"
new file mode 100644
index 0000000..c5b2238
--- /dev/null
+++ "b/docs/spring/Spring\345\270\270\350\247\201\346\263\250\350\247\243.md"
@@ -0,0 +1,724 @@
+# Springע
+## 1
+
+Ƕ֪SpringĵԾIOC+AOPIOCԭʵһSpringSpring Beanʵ
+DIҲע룬ΪҪĵĺĻ⣬עעĸҪȷ֪ġ
+ǰϰxmlļһbeanڣǸʹעʹDIĹ
+
+
+ǿʹ org.springframework.beans.factory.annotation org.springframework.context.annotation еע Spring DI Ĺܡ
+
+ͨЩΪSpring ע͡ǽڱ̳жлعˡ
+
+
+## 2 DIע
+
+### 2.1 @Autowired
+
+ǿʹ @Autowired Spring Ҫע
+ǿԽע빹캯setter ֶעһʹá
+Constructor injection:
+
+**ע**
+
+````
+class Car {
+ Engine engine;
+
+ @Autowired
+ Car(Engine engine) {
+ this.engine = engine;
+ }
+}
+````
+
+**Setterע**
+````
+class Car {
+ Engine engine;
+
+ @Autowired
+ void setEngine(Engine engine) {
+ this.engine = engine;
+ }
+}
+````
+**ע**
+````
+class Car {
+ @Autowired
+ Engine engine;
+}
+````
+
+@Autowired һΪ required IJĬֵΪ true
+
+Ҳʵ bean ʱ Spring Ϊ Ϊ true ʱ׳쳣κݡ
+
+ע⣬ʹù캯ע룬й캯ǿԵġ
+
+ 4.3 汾ʼDzҪʽʹ @Autowired ע캯캯
+
+### 2.2 @Bean
+
+@Bean ʵ Spring bean Ĺ
+
+```
+@Bean
+Engine engine() {
+ return new Engine();
+}
+````
+
+Ҫ͵ʵʱSpring Щ
+
+ɵ bean 빤ͬ Բͬķʽǿʹôע͵ƻֵֵDzƵı
+
+````
+@Bean("engine")
+Engine getEngine() {
+ return new Engine();
+}
+````
+һַdzbeanʽΪܶbeanһʼڴﶨõģҪʱа蹹
+
+ǿɵͶBeanҲԸԶbeanơ
+
+ע⣬@Bean ע͵ķ@Configuration С
+
+### 2.3 @Qualifier
+
+ʹ@Qualifier @Autowired ṩҪڲȷʹõbean id bean ơ
+
+磬 bean ʵͬĽӿڣ
+````
+class Bike implements Vehicle {}
+
+class Car implements Vehicle {}
+
+````
+
+ Spring Ҫעһ Vehicle beanԶƥ䶨 £ǿʹ @Qualifier עʽṩ bean ơ
+
+**ע**
+````
+@Autowired
+Biker(@Qualifier("bike") Vehicle vehicle) {
+this.vehicle = vehicle;
+}
+````
+
+**Setterע**
+
+````
+@Autowired
+void setVehicle(@Qualifier("bike") Vehicle vehicle) {
+this.vehicle = vehicle;
+}
+````
+:
+
+````
+@Autowired
+@Qualifier("bike")
+void setVehicle(Vehicle vehicle) {
+this.vehicle = vehicle;
+````
+**ע**
+
+````
+@Autowired
+@Qualifier("bike")
+Vehicle vehicle;
+````
+עǿƽõIJ࣬ǵһӿжʵʱͻᾭó
+
+### 2.4 @Required
+
+@Required setter ϱҪͨ XML
+````
+@Required
+void setColor(String color) {
+this.color = color;
+}
+````
+xml
+````
+
+
+
+````
+׳ BeanInitializationException
+dzټ÷֪һ¾
+
+### 2.5 @Value
+ǿʹ @Value ֵע bean 빹캯setter ֶעݡ
+
+ҲǷdzõһע⣬ΪǺܶʱҪapplication.propertiesļȡֵ
+
+**ע**
+````
+Engine(@Value("8") int cylinderCount) {
+this.cylinderCount = cylinderCount;
+}
+````
+
+**setterע**
+
+````
+@Autowired
+void setCylinderCount(@Value("8") int cylinderCount) {
+this.cylinderCount = cylinderCount;
+}
+````
+
+:
+````
+
+@Value("8")
+void setCylinderCount(int cylinderCount) {
+this.cylinderCount = cylinderCount;
+}
+````
+
+**ע**
+````
+@Value("8")
+int cylinderCount;
+````
+
+Ȼע뾲ֵ̬ûõġ ˣǿ @Value ʹռλַⲿԴжֵ .properties .yaml ļС
+````
+
+engine.fuelType=petrol
+````
+
+ǿͨ·ʽע engine.fuelType ֵ
+
+````
+@Value("${engine.fuelType}")
+String fuelType;
+````
+
+ʹ SpEL ʹ@Value ʾǹ@Value ҵ
+
+### 2.6 @DependsOn
+ǿʹôע Spring ע bean ֮ǰʼ bean ͨΪԶģ bean ֮ʽϵ
+
+ֻʽʱҪע⣬JDBCػ߾̬ʼ
+
+ǿָ bean Ƶʹ @DependsOn ע͵ֵҪһ bean Ƶ飺
+
+````
+@DependsOn("engine")
+class Car implements Vehicle {}
+````
+Alternatively, if we define a bean with the @Bean annotation, the factory method should be annotated with @DependsOn:
+````
+@Bean
+@DependsOn("fuel")
+Engine engine() {
+return new Engine();
+}
+````
+### 2.7 @Lazy
+سʼǵ bean ʱʹ @Lazy Ĭ£Spring Ӧóĵ/ʱеشе bean
+
+ǣЩҪʱ beanӦóʱ
+
+עΪǷȷλöͬ ǿڣ
+
+һ @Bean ע͵ bean ӳٷã˴ bean
+@Configuration а@Bean ܵӰ
+
+һ @Component ࣬ @Configuration ࣬ bean ӳٳʼ
+
+@Autowired 캯setter ֶΣӳټͨ
+
+````
+@Configuration
+@Lazy
+class VehicleFactoryConfig {
+
+ @Bean
+ @Lazy(false)
+ Engine engine() {
+ return new Engine();
+ }
+}
+````
+ͬһõע⡣
+
+άһдbeanĿʱᷢкܶbeanܶǰʹõģһҪʼʱͽгʼǽʡܶʱܡ
+
+
+### 2.8 @Lookup
+ͬһȽõע
+
+@Lookup Spring ǵʱط͵ʵ
+
+ϣSpring Ǵע͵ķʹǷķͺͲΪ BeanFactory#getBean IJ
+
+@Lookup ڣ
+
+ԭ bean עԼbean Provider
+
+ɾӵһԭ Spring beanôǼ⣺
+
+ǵĵ Spring bean ηЩԭ Spring bean
+
+ڣProvider ϶һַʽ @Lookup ijЩͨá
+
+ҪעǣspringĬʹõĵbeanҪעԭbeanDzҪĶ
+
+ȣǴһԭ beanԺǽע뵽 bean У
+````
+@Component
+@Scope("prototype")
+public class SchoolNotification {
+// ... prototype-scoped state
+}
+````
+ʹ@Lookupǿͨ bean ȡ SchoolNotification ʵ
+
+````
+@Component
+public class StudentServices {
+
+ // ... member variables, etc.
+
+ @Lookup
+ public SchoolNotification getNotification() {
+ return null;
+ }
+
+ // ... getters and setters
+}
+````
+Using @Lookup, we can get an instance of SchoolNotification through our singleton bean:
+````
+@Test
+public void whenLookupMethodCalled_thenNewInstanceReturned() {
+// ... initialize context
+StudentServices first = this.context.getBean(StudentServices.class);
+StudentServices second = this.context.getBean(StudentServices.class);
+
+ assertEquals(first, second);
+ assertNotEquals(first.getNotification(), second.getNotification());
+}
+````
+ע⣬ StudentServices Уǽ getNotification Ϊ
+
+Ϊ Spring ͨ beanFactory.getBean(StudentNotification.class) ˸÷ǿԽա
+
+
+### 2.9 @Primary
+ʱҪͬ͵bean Щ£ע뽫ɹΪ Spring ֪Ҫĸ bean
+
+Ѿ˴ѡ@Qualifier нߵ㲢ָ bean ơ
+
+ȻʱҪһض beanҪ bean
+
+ǿʹ@Primary @Primary õbeanunqualifiedעϱѡ
+
+````
+@Component
+@Primary
+class Car implements Vehicle {}
+
+@Component
+class Bike implements Vehicle {}
+
+@Component
+class Driver {
+@Autowired
+Vehicle vehicle;
+}
+
+@Component
+class Biker {
+@Autowired
+@Qualifier("bike")
+Vehicle vehicle;
+}
+````
+ǰʾУҪ ˣ Driver УSpring עһ Car bean Ȼ Biker bean Уֶ vehicle ֵһ Bike Ϊqualifiedġ
+
+### 2.10 @Scope
+
+ͨӦ˵beanscopeĬ϶ǵģʵspring beanֶֶ֧÷ΧŲͬڡ
+
+ʹ@Scope @Component @Bean ķΧ ǵԭ͡ỰglobalSession һЩԶ巶Χ
+
+ӦöֵΪ
+````
+singleton
+prototype
+request
+session
+application
+websocket
+````
+
+
+````
+@Component
+@Scope("prototype")
+class Engine {}
+````
+ǿһЩrequestsessionwebsocketbeanͨӦǺصģô洢ûϢsession֮bean
+
+ôʹãҪľ峡ѡˣһܴĻ⣬ȲչˣԺڵܡ
+
+## 3 ע
+ǿʹñעӦóġ
+
+
+### 3.1 @Profile
+
+ϣ Spring ضļڻ״̬ʱʹ@Component @Bean ǿʹ@Profile бǡ
+
+ǿʹע͵ֵļƣ
+
+ͨעòͬá
+
+
+````
+public interface DatasourceConfig {
+public void setup();
+}
+````
+
+ǿã
+
+````
+@Component
+@Profile("dev")
+public class DevDatasourceConfig implements DatasourceConfig {
+@Override
+public void setup() {
+System.out.println("Setting up datasource for DEV environment. ");
+}
+}
+````
+ã
+
+````
+@Component
+@Profile("production")
+public class ProductionDatasourceConfig implements DatasourceConfig {
+@Override
+public void setup() {
+System.out.println("Setting up datasource for PRODUCTION environment. ");
+}
+}
+````
+ȻҲʹxml͵ļbean
+
+xml
+````
+
+
+
+````
+### 3.2 @Import
+
+ǿʹض @Configuration ࣬ʹôעɨ衣 ǿΪЩṩ@Import ֵ
+
+˵Ҫõ@ConfigurationעbeanôspringӦñҪɨ赽Ŀ¼ǡûжԸ·ɨ裬ֻʹ·µĵ࣬ôǾͿʹ@Importˡ
+
+עǷdzõģһ
+
+````
+@Import(VehiclePartSupplier.class)
+class VehicleFactoryConfig {}
+
+@Configuration
+class VehiclePartSupplier{
+}
+````
+
+### 3.3 @ImportResource
+
+˵һ bean.xml ļҪ beans.xml ж bean 뵽 Spring Boot Уβأ
+
+1.Spring ʽļ bean.xml ˴ٸʾ˵ xml һ helloServiceʾ
+````
+
+
+
+
+
+
+````
+2.ʹ@ImportResourceע⣬ xml
+````
+/**
+ * Spring BootûSpringļԼдļҲԶʶ
+ * SpringļЧصSpring
+ * ʹ@ImportResourceע⣬עһ(˴)
+ */
+@SpringBootApplication
+@ImportResource(locations = {"classpath:beans.xml"})
+public class BootApplication {
+
+ public static void main(String[] args) {
+ // SpringӦ
+ SpringApplication.run(BootApplication.class,args);
+
+ }
+}
+
+````
+### 3.4 @PropertySource
+ͨע⣬ǿΪӦóöļ
+
+@PropertySource עṩһַԻƣڽ PropertySource ӵ Spring Environment У @Configuration һʹá
+
+ʹ @Value ȥöԣ磺@Value("testbean.name")ҲָĬֵ磺@Value("testbean.name:defaultValue")
+
+÷ʾ
+
+һļapp.properties
+````
+testbean.name=myTestBean
+````
+ @Configuration ʹ @PropertySource app.properties ø Environment PropertySources ϡ
+````
+@Configuration
+@PropertySource("classpath:/com/myco/app.properties")
+public class AppConfig {
+
+ @Autowired
+ Environment env;
+
+ @Bean
+ public TestBean testBean() {
+ TestBean testBean = new TestBean();
+ testBean.setName(env.getProperty("testbean.name"));
+ return testBean;
+ }
+}
+````
+
+ע⣺ʹ @Autowired Environment ע뵽УȻ testBean() ʹá
+У testBean.getName() ءmyTestBeanַ
+
+@PropertySource Java 8 ظעԣζǿαһࣺ
+
+````
+@Configuration
+@PropertySource("classpath:/annotations.properties")
+@PropertySource("classpath:/vehicle-factory.properties")
+class VehicleFactoryConfig {}
+````
+
+### 3.5 @PropertySources
+÷ͬϣֻһǿʹעָ@PropertySource ã
+````
+@Configuration
+@PropertySources({
+@PropertySource("classpath:/annotations.properties"),
+@PropertySource("classpath:/vehicle-factory.properties")
+})
+class VehicleFactoryConfig {}
+````
+ע⣬ Java 8 ǿͨظעʵͬĹܡ
+
+## 4.
+
+ڱУǿ Spring ע͵ĸ ǿ bean ӺӦģԼΪɨࡣ
+
+springϵеijעкܶ࣬һƪ²ȫǣ©ӭ䡣
+
+# Spring Beanע
+
+## 1
+ڱ̳Уǽڶ岻ͬ bean Spring bean ע͡
+
+мַ Spring bean ȣǿʹ XML ǡ ǻʹ@Bean ע bean
+
+ǿʹ org.springframework.stereotype еע֮һǸ࣬ಿɨ衣
+
+## 2 @ComponentScan
+Ǿʹõһע⣬ǵӦУʱһɨеİرǵҪɨⲿjarеbeanʱdzá
+
+ԼSpringBootApplicationϣҲԼ@configurationעϵ
+
+ɨ裬Spring Զɨе bean
+
+@ComponentScan ʹעɨЩࡣ
+
+ǿֱʹ basePackages value ֮һָƣvalue basePackages ı
+
+````
+@Configuration
+@ComponentScan(basePackages = "com.baeldung.annotations")
+class VehicleFactoryConfig {}
+````
+⣬ǿʹ basePackageClasses ָеࣺ
+
+````
+@Configuration
+@ComponentScan(basePackageClasses = VehicleFactoryConfig.class)
+class VehicleFactoryConfig {}
+````
+
+飬ǿΪÿṩ
+
+δָɨ跢ڴ @ComponentScan עͬһС
+
+@ComponentScan Java 8 ظעԣζǿαһࣺ
+
+````
+@Configuration
+@ComponentScan(basePackages = "com.baeldung.annotations")
+@ComponentScan(basePackageClasses = VehicleFactoryConfig.class)
+class VehicleFactoryConfig {}
+````
+
+ߣǿʹ @ComponentScans ָ @ComponentScan ã
+
+````
+@Configuration
+@ComponentScans({
+@ComponentScan(basePackages = "com.baeldung.annotations"),
+@ComponentScan(basePackageClasses = VehicleFactoryConfig.class)
+})
+````
+````
+class VehicleFactoryConfig {
+}
+````
+ʹ XML ʱɨͬ
+
+````
+
+````
+
+### 3 @Component
+
+@Component ༶ע⡣ ɨڼ䣬Spring Framework Զʹ@Component עࣺ
+````
+@Component
+class CarUtility {
+// ...
+}
+````
+
+Ĭ£ bean ʵͬĸСд ⣬ǿʹôע͵Ŀѡֵָͬơ
+
+@Repository@Service@Configuration @Controller Ǵ@Component ע⣬ǹͬbean Ϊ
+
+Spring ɨԶǡ
+
+ͨ˵ǻmvcӦǻõע⣬ڷwebӦиؿʹ@componentעbean
+
+### 4 @Repository
+
+DAO or Repository classes usually represent the database access layer in an application, and should be annotated with @Repository:
+````
+@Repository
+class VehicleRepository {
+// ...
+}
+````
+ʹôע͵һŵԶ־쳣ת ʹó־Կܣ Hibernateʱʹ @Repository ע͵׳ı쳣ԶתΪ Spring DataAccessExeption ࡣ
+
+Ҫ쳣תҪԼ PersistenceExceptionTranslationPostProcessor bean
+````
+@Bean
+public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
+return new PersistenceExceptionTranslationPostProcessor();
+}
+````
+ע⣬ڴ£Spring Զִ衣
+
+ͨ XML ã
+````
+
+````
+
+### 5 @Service
+ӦóҵͨפڷУǽʹ@Service עָʾһڸò㣺
+
+````
+@Service
+public class VehicleService {
+// ...
+}
+````
+### 6 @Controller
+@Controller һ༶ע⣬ Spring Framework Ϊ Spring MVC еĿ
+
+spring@Controller עbeanܶ飬ǻSpringMVCص
+
+````
+@Controller
+public class VehicleController {
+// ...
+}
+
+````
+## 7 @Configuration
+
+@Bean ע͵ bean 巽
+````
+@Configuration
+class VehicleFactoryConfig {
+
+ @Bean
+ Engine engine() {
+ return new Engine();
+ }
+
+}
+````
+## 8 AOPע
+ʹ Spring עʱ״һ㣬оض͵ΪĿꡣ
+
+磬 DAO 㷽ִʱ䡣 ǽ·棨ʹ AspectJ עͣ @Repository ͣ
+
+```
+@Aspect
+@Component
+public class PerformanceAspect {
+@Pointcut("within(@org.springframework.stereotype.Repository *)")
+public void repositoryClassMethods() {};
+
+ @Around("repositoryClassMethods()")
+ public Object measureMethodExecutionTime(ProceedingJoinPoint joinPoint)
+ throws Throwable {
+ long start = System.nanoTime();
+ Object returnValue = joinPoint.proceed();
+ long end = System.nanoTime();
+ String methodName = joinPoint.getSignature().getName();
+ System.out.println(
+ "Execution of " + methodName + " took " +
+ TimeUnit.NANOSECONDS.toMillis(end - start) + " ms");
+ return returnValue;
+ }
+}
+````
+
+ڴʾУǴһ㣬ƥʹ@Repository ע͵ез Ȼʹ@Around ֪ͨλǸ㣬ȷطõִʱ䡣
+
+⣬ʹַǿΪÿӦó־¼ܹƺΪ
+
+ȻˣaspectJעܶ࣬棬δҲᵥдĽܡ
+
+## 9
+
+ڱУǼ Spring עͲǸԴ͡
+
+ǻѧϰʹɨҵע͵ࡣ
+
+˽Щעε¸ɾֲԼӦóע֮ķ롣 ǻʹøСΪDzҪֶʽ bean
+
+# ο
+https://www.baeldung.com/spring-annotations
+
diff --git "a/docs/spring/Spring\346\246\202\350\277\260.md" "b/docs/spring/Spring\346\246\202\350\277\260.md"
new file mode 100644
index 0000000..1152df8
--- /dev/null
+++ "b/docs/spring/Spring\346\246\202\350\277\260.md"
@@ -0,0 +1,145 @@
+Spring Java EE һĿԴܣɱΪSpring ֮ Rod Johnson 2002 ĿҪ Java ҵӦóĿѶȺڡ
+
+Spring ԵһֱԱΪ Java ҵӦóѡʱգSpring ٲȻΪ Java EE ʣΪ˹ Java EE Ӧõʵ
+
+## Spring ĵ뷢չ
+
+ڵ J2EEJava EE ƽ̨Ƴ EJB ΪĵĿʽֿʽʵʵĿдֱˣʹøӡӷסǿڳֲѶȴȡ
+
+Rod Johnson 2004 ij顶Expert One-on-One J2EE Development without EJBУ EJB ӷĽṹһķͷֱԸӼķʽ滻
+
+ⱾУRod Johnson ͨһ 3 дĸչʾڲʹ EJB ¹һչ Java ӦóУRod Johnson длṹ룬аõ Java ӿں࣬ ApplicationContextBeanFactory ȡЩĸΪ com.interface21Ϊṩ 21 ͵һο
+
+ⱾӰԶ Rod Johnson com.interface21 Ĵ뿪Դ¿ܲΪSpringΪSpring һƴһɨƽͳ J2EE ĺ
+
+2003 2 £Spring 0.9 汾 Apache 2.0 ԴЭ飻2004 4 £Spring 1.0 汾ʽĿǰΪֹSpring Ѿ뵽˵ 5 汾Ҳdz˵ Spring 5
+
+## Spring
+
+ڲͬᄈУSpring ĺDzͬġǾͷֱӡ塱͡塱Ƕȣ Spring нܡ
+
+### SpringSpring ջ
+
+ϵ Spring ָ Spring Framework Ϊĵ Spring ջ
+
+ʮķչSpring ѾһӦÿܣչΪһɶͬĿģ飩ɵij켼 Spring FrameworkSpring MVCSpringBootSpring CloudSpring DataSpring Security ȣ Spring Framework ĿĻ
+
+ЩĿ˴ҵӦÿƼȸݣܹԱչвϲĸʵ⣬Ա˸õĿ顣
+
+| Ŀ | |
+| --- | --- |
+| Spring Data | Spring ṩݷģ飬 JDBC ORM ṩ˺ܺõ֧֡ͨԱʹһͳһķʽλڲͬݿеݡ |
+| Spring Batch | һרҵϵͳеճܣܹԱĿ׳ЧӦó |
+| Spring Security | ǰΪ Acegi Spring нϳģ֮һһԶƻ֤ͷʿƿܡ |
+| Spring Mobile | Ƕ Spring MVC չƶ Web ӦõĿ |
+| Spring Boot | Spring Ŷṩȫ¿ܣΪ Spring ԼһЩ伴õãԼ Spring ӦõĴ̡ |
+| Spring Cloud | һ Spring Boot ʵֵܡijһżһϵܵϡϳġ֤ͨ Spring Boot ˼ٷװεиӵúʵԭΪԱṩһײάķֲʽϵͳ߰ |
+
+### SpringSpring Framework
+
+ Spring ָ Spring FrameworkͨǽΪ Spring ܡ
+
+Spring һֲġ Java Ӧóһվʽ Spring ջĺĺͻΪ˽ҵӦÿĸԶġ
+
+Spring IJ֣ IoC AOP
+
+| | |
+| --- | --- |
+| IOC | Inverse of Control ļдΪƷתָѴ̽ Spring й |
+| AOP | Aspect Oriented Programming ļдΪ̡AOP װĹΪЩҵأȴΪҵģͬõװϵͳظ룬ģ϶ȡ⣬AOP һЩϵͳϵ⣬־Ȩȡ |
+
+Spring һֻ Bean ı̵̼ظı Java 硣Spring ʹü Java Bean ǰֻ EJB ɵĹʹúܶิӵĴźͼ࣬ EJB ӷסЧĿģʽķĿĺάչ
+
+ʵʿУӦóͨϵֱܹΪֲ㣨webҵ㣨service־ò㣨dao
+
+Spring Java EE ӦøĽÿһ㶼ṩ˼֧֡
+
+* ڱֲṩ˶ Spring MVCStruts2 ȿܵϣ
+* ҵṩ˹ͼ¼־Ĺܣ
+* ڳ־ò㻹 MyBatisHibernate JdbcTemplate ȼݿзʡ
+
+ֵ Spring һȫĽЩѾнϺýSpring ظ顣
+
+ϿSpring ܸ Java ԱߵɶȣҵijҲṩõĽڿԴܵ˹㷺Ļӭұֹ˾Ϊ Java Ŀѡܡ
+
+## Spring Framework ص
+
+Spring ܾ¼ص㡣
+
+### ****
+
+Spring һԽжĴϵά Spring
+
+### **㼯ɸ**
+
+Spring ųĿԴܣڲṩ˶Ըܣ Struts2HibernateMyBatis ȣֱ֧֡
+
+### ** Java EE API ʹѶ**
+
+Spring Java EE зdzõһЩ APIJDBCJavaMailԶ̵õȣṩ˷װʹЩ API ӦõѶȴ͡
+
+### **IJ**
+
+Spring ֧ JUnit4ͨעⷽز Spring
+
+### **AOP ̵֧**
+
+Spring ṩ̣ԷʵֶԳȨغмصȹܡ
+
+### **ʽ֧**
+
+ֻҪͨþͿɶĹֶ̡
+
+Spring ܻҵӦÿĸ棬 20 ͬģ顣
+
+spring-aop spring-context-indexer spring-instrument spring-orm spring-web
+spring-aspects spring-context-support spring-jcl spring-oxm spring-webflux
+spring-beans spring-core spring-jdbc spring-r2dbc spring-webmvc
+spring-context spring-expression spring-jms spring-test spring-websocket
+spring-messaging spring-tx
+
+
+ͼ1Springܹͼ
+
+ͼа Spring ܵģ飬ЩģһҵӦÿڿпԸѡԵʹҪģ顣ֱЩģýмܡ
+
+## 1\. Data Access/Integrationݷʣɣ
+
+ݷʣɲ JDBCORMOXMJMS Transactions ģ飬¡
+
+* JDBC ģ飺ṩһ JBDC ģ壬ʹЩģͳ߳ JDBC 뻹бƣܵ Spring ĺô
+* ORM ģ飺ṩеġ-ϵӳ켯ɵ API JPAJDOHibernate MyBatis ȡһʹ Spring
+* OXM ģ飺ṩһ֧ Object /XML ӳijʵ֣ JAXBCastorXMLBeansJiBX XStream Java ӳ XML ݣ߽XML ӳ Java
+* JMS ģ飺ָ Java Ϣṩһ ϢߡϢߡģڸӼʹ JMSJMS Ӧó֮䣬ֲʽϵͳзϢ첽ͨš
+* Transactions ģ飺ֱ֧̺ʽ
+
+## 2\. Web ģ
+
+Spring Web WebServletWebSocket Portlet ¡
+
+* Web ģ飺ṩ˻ Web ԣļϴܡʹõ Servlet IOC ʼԼ Web Ӧġ
+* Servlet ģ飺ṩһ Spring MVC Web ʵ֡Spring MVC ṩ˻עԴע롢ݰ֤ȼһdzõ JSP ǩȫ Spring Э
+* WebSocket ģ飺ṩ˼ĽӿڣûֻҪʵӦĽӿھͿԿٵĴ WebSocket ServerӶʵ˫ͨѶ
+* Portlet ģ飺ṩ Portlet ʹ MVC ʵ֣ Web-Servlet ģĹܡ
+
+## 3\. Core ContainerSpring ĺ
+
+Spring ĺģ齨Ļ Beans ģ顢Core ģ顢Context ģ SpEL ʽģɣûЩҲ AOPWeb ϲĹܡ¡
+
+* Beans ģ飺ṩ˿ܵĻ֣Ʒתע롣
+* Core ģ飺װ Spring ܵĵײ㲿֣ԴʡתһЩùࡣ
+* Context ģ飺 Core Beans ģĻ֮ϣ Beans ģ鹦ܲԴ֤ʻJava EE ֧֡ڡ¼ȡApplicationContext ӿģĽ㡣
+* SpEL ģ飺ṩǿıʽַ֧֣֧ʺֵãַ֧ʼ顢֧㣬ִ֧ Spring ȡ BeanҲ֧бͶӰѡһбۺϵȡ
+
+## 4\. AOPAspectsInstrumentation Messaging
+
+ Core Container ֮ AOPAspects ģ飬£
+
+* AOP ģ飺ṩʵ֣ṩ־¼ȨơͳƵͨùܺҵļ̬ܶİЩӵҪĴУ˾ְҵͨùܵϡ
+* Aspects ģ飺ṩ AspectJ ļɣһǿҳ̣AOPܡ
+* Instrumentation ģ飺ṩߵֺ֧ʵ֣ضӦ÷ʹá
+* messaging ģ飺Spring 4.0 ԺϢSpring-messagingģ飬ģṩ˶ϢϵṹЭ֧֡
+
+## 5\. Test ģ
+
+Test ģ飺Spring ֧ Junit TestNG ԿܣһṩһЩ Spring IJԹܣڲ Web ʱģ Http Ĺܡ
\ No newline at end of file
diff --git "a/docs/spring/springMVC/SpringMVC\345\270\270\350\247\201\346\263\250\350\247\243.md" "b/docs/spring/springMVC/SpringMVC\345\270\270\350\247\201\346\263\250\350\247\243.md"
new file mode 100644
index 0000000..6bd5272
--- /dev/null
+++ "b/docs/spring/springMVC/SpringMVC\345\270\270\350\247\201\346\263\250\350\247\243.md"
@@ -0,0 +1,232 @@
+## 1.
+ ڱ̳Уǽ̽ org.springframework.web.bind.annotation е Spring Web ע͡
+
+## 2. @RequestMapping
+
+˵@RequestMapping @Controller ڲ ʹã
+
+·ƺֵӳ䵽ĸ URL
+ݵ HTTP
+params HTTP Ĵڡڻֵ
+headers HTTP ͷĴڡڻֵ
+ģ÷ HTTP Щý
+produces÷ HTTP ӦЩý
+һʾ
+
+````
+@Controller
+class VehicleController {
+
+ @RequestMapping(value = "/vehicles/home", method = RequestMethod.GET)
+ String home() {
+ return "home";
+ }
+}
+````
+༶ӦôעͣǿΪ @Controller едṩĬá Ψһ Spring ʹ÷øǵḽ·ֵ URL
+
+磬úЧһģ
+
+````
+@Controller
+@RequestMapping(value = "/vehicles", method = RequestMethod.GET)
+class VehicleController {
+
+ @RequestMapping("/home")
+ String home() {
+ return "home";
+ }
+}
+````
+
+⣬@GetMapping@PostMapping@PutMapping@DeleteMapping @PatchMapping @RequestMapping IJͬ壬HTTP ѷֱΪGETPOSTPUTDELETE PATCH
+
+Щ Spring 4.3 汾ʼá
+
+## 3 @RequestBody
+
+Ǽ@RequestBody HTTP ӳ䵽һ
+
+````
+@PostMapping("/save")
+void saveVehicle(@RequestBody Vehicle vehicle) {
+// ...
+}
+````
+лԶģȡ͡
+
+## 4 @PathVariable
+˵˵@PathVariable
+
+עָʾ URI ģ ǿʹ @RequestMapping עָ URI ģ壬ʹ @PathVariable ģ岿֮һ
+
+ǿʹƻֵʵһ㣺
+
+````
+@RequestMapping("/{id}")
+Vehicle getVehicle(@PathVariable("id") long id) {
+// ...
+}
+````
+ģвֵ뷽ƥ䣬ǾͲעָ
+
+````
+@RequestMapping("/{id}")
+Vehicle getVehicle(@PathVariable long id) {
+// ...
+}
+````
+⣬ǿͨIJΪ false ·Ϊѡ
+
+````
+@RequestMapping("/{id}")
+Vehicle getVehicle(@PathVariable(required = false) long id) {
+// ...
+}
+````
+## 5. @RequestParam
+ We use @RequestParam for accessing HTTP request parameters:
+````
+@RequestMapping
+Vehicle getVehicleByParam(@RequestParam("id") long id) {
+// ...
+}
+````
+ @PathVariable עͬѡ
+
+Щ֮⣬ Spring зûֵΪֵʱǿʹ @RequestParam ָעֵ ΪˣDZ defaultValue
+
+ṩĬֵʽ required Ϊ false
+````
+@RequestMapping("/buy")
+Car buyCar(@RequestParam(defaultValue = "5") int seatCount) {
+// ...
+}
+````
+˲֮⣬ǻԷ HTTP ֣cookie ͱͷ
+
+ǿԷֱʹע@CookieValue @RequestHeader ǡ
+
+
+## 6. Response Handling Annotations
+ڽIJУǽ Spring MVC в HTTP Ӧע͡
+
+### 6.1 @ResponseBody
+@ResponseBody Spring ὫĽΪӦ
+
+````
+@ResponseBody
+@RequestMapping("/hello")
+String hello() {
+return "Hello World!";
+}
+````
+עע @Controller ࣬ʹ
+
+### 6.2 @ExceptionHandler
+
+ʹôעͣǿһԶ ׳κָ쳣ʱSpring ô˷
+
+쳣Ϊݸ
+````
+@ExceptionHandler(IllegalArgumentException.class)
+void onIllegalArgumentException(IllegalArgumentException exception) {
+// ...
+}
+````
+
+### 6.3 @ResponseStatus
+ʹôעͶעָͣӦ HTTP ״̬ ǿʹ code value ״̬롣
+
+⣬ǿʹ reason ṩԭ
+
+ҲԽ@ExceptionHandler һʹã
+
+@ExceptionHandler(IllegalArgumentException.class)
+@ResponseStatus(HttpStatus.BAD_REQUEST)
+void onIllegalArgumentException(IllegalArgumentException exception) {
+// ...
+}
+
+й HTTP Ӧ״̬ĸϢʱġ
+
+## 7 Webע
+һЩעͲֱӹ HTTP Ӧ ڽIJУǽġ
+
+### 7.1 @Controller
+ǿʹ@Controller һSpring MVC йظϢǹ Spring Bean Annotations ¡
+
+### 7.2 @RestController
+@RestController @Controller @ResponseBody
+
+ˣǵЧģ
+
+````
+@Controller
+@ResponseBody
+class VehicleRestController {
+// ...
+}
+````
+
+````
+@RestController
+class VehicleRestController {
+// ...
+}
+````
+### 7.3 @ModelAttribute
+ͨע⣬ǿͨṩģͼѾ MVC @Controller ģеԪأ
+
+````
+@PostMapping("/assemble")
+void assembleVehicle(@ModelAttribute("vehicle") Vehicle vehicleInModel) {
+// ...
+}
+````
+@PathVariable @RequestParam һͬƣDzָģͼ
+
+````
+@PostMapping("/assemble")
+void assembleVehicle(@ModelAttribute Vehicle vehicle) {
+// ...
+}
+````
+⣬@ModelAttributeһ;עһSpringԶķֵӵģУ
+
+````
+@ModelAttribute("vehicle")
+Vehicle getVehicle() {
+// ...
+}
+````
+ǰһDzָģͼSpring Ĭʹ÷ƣ
+````
+@ModelAttribute
+Vehicle vehicle() {
+// ...
+}
+````
+ Spring ֮ǰ @ModelAttribute ע͵ķ
+
+й @ModelAttribute ĸϢıġ
+
+### 7.4 @CrossOrigin
+@CrossOrigin Ϊע͵ÿͨţ
+
+````
+@CrossOrigin
+@RequestMapping("/hello")
+String hello() {
+return "Hello World!";
+}
+````
+һ࣬е
+
+ǿʹôע͵IJ CORS Ϊ
+
+йϸϢʱġ
+
+
+# ο
+https://www.baeldung.com/spring-annotations
diff --git "a/docs/spring/\347\254\254\344\270\200\344\270\252Spring\345\272\224\347\224\250.md" "b/docs/spring/\347\254\254\344\270\200\344\270\252Spring\345\272\224\347\224\250.md"
new file mode 100644
index 0000000..b40a369
--- /dev/null
+++ "b/docs/spring/\347\254\254\344\270\200\344\270\252Spring\345\272\224\347\224\250.md"
@@ -0,0 +1,70 @@
+##
+ǿȰ Spring Jar Լ Commons-loggin 뵽ĿУӣҪٵ Spring Jar
+
+````
+org.springframework.core-5.3.13.jar
+org.springframework.beans-5.3.13.jar
+spring-context-5.3.13.jar
+spring-expression-5.3.13.jar
+commons.logging-1.2.jar
+````
+ȻƼʹmaven
+
+## Java
+ HelloSpring д net.biancheng.c Ȼ´ HelloWorld.java MainApp.java ࡣ
+
+HelloWorld.java Ĵ
+````
+package net.biancheng.c;
+public class HelloWorld {
+ private String message;
+ public void setMessage(String message) {
+ this.message = message;
+ }
+ public void getMessage() {
+ System.out.println("message : " + message);
+ }
+}
+````
+MainApp.java Ĵ
+````
+package net.biancheng.c;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+ public class MainApp {
+ public static void main(String[] args) {
+ ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
+ HelloWorld obj = context.getBean("helloWorld",HelloWorld.class);
+ obj.getMessage();
+ }
+ }
+````
+ϴ룬Ҫע㣺
+
+ ApplicationContext ʱʹ ClassPathXmlApplicationContext ࣬ڼ Spring ļͳʼжBean
+ApplicationContext.getBean() ȡ Bean÷ֵΪ ObjectͨǿתΪ HelloWorld ʵе getMessage()
+
+## ļ
+
+ src Ŀ¼£һ Spring ļ Beans.xml¡
+````
+
+
+
+
+
+
+````
+ҲԽļΪЧƣҪעǣļ MainApp.java жȡļһ¡
+
+Beans.xml ڸͬ Bean Ψһ IDӦ Bean Ըֵ磬ϴУǿڲӰ£ message ֵ
+## г
+
+ MainApp.javaEclipse IDE ̨ʾϢ¡
+ message : Hello World!
+
+ˣǾͳɹ˵һ Spring Ӧó
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index de1628d..a91c75e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,8 +7,28 @@
groupId
JavaTutorial
1.0-SNAPSHOT
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.0.5
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
com.github.houbb
markdown-toc
@@ -51,5 +71,13 @@
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
\ No newline at end of file
diff --git a/src/main/java/Test.java b/src/main/java/Test.java
new file mode 100644
index 0000000..269694c
--- /dev/null
+++ b/src/main/java/Test.java
@@ -0,0 +1,22 @@
+import org.springframework.beans.factory.annotation.Lookup;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author hpl
+ * @date 2023/4/15 14:40
+ */
+@Service
+public class Test {
+
+
+
+
+ public static void main(String[] args) {
+
+ }
+
+
+ public void test(){
+
+ }
+}
From 84e1254e8691ae7e4dad0803dc17c2c8ef33b29a Mon Sep 17 00:00:00 2001
From: h2pl <362294931@qq.com>
Date: Thu, 20 Apr 2023 21:35:59 +0800
Subject: [PATCH 10/39] done
---
ReadMe.md | 69 +-
...10\346\240\270\345\277\203\357\274\211.md" | 7 +-
...\260\203\345\272\246\344\270\216@Async.md" | 240 +
...45\345\277\227\347\256\241\347\220\206.md" | 806 +++
...\210\260\345\244\226\351\203\250Tomcat.md" | 302 +
...42\203\345\267\245\345\205\267Actuator.md" | 5832 +++++++++++++++++
...232\204Starter\346\234\272\345\210\266.md" | 262 +
...72\346\234\254\344\275\277\347\224\250.md" | 122 +-
...07\344\273\266\347\256\241\347\220\206.md" | 2989 +++++++++
...50\347\275\262\345\267\245\345\205\267.md" | 345 +
...52\345\212\250\347\224\237\346\210\220.md" | 625 ++
...345\267\245\345\205\267SpringBootAdmin.md" | 294 +
...45\350\257\206\346\270\205\345\215\225.md" | 0
...05\345\214\226\345\212\237\350\203\275.md" | 179 +
...70\347\224\250\345\212\237\350\203\275.md" | 594 ++
...70\345\244\204\347\220\206\345\231\250.md" | 235 +
...04\346\213\246\346\210\252\345\231\250.md" | 88 +
...76\350\247\243\346\236\220\345\231\250.md" | 181 +
...\277\207\346\273\244\345\231\250Filter.md" | 151 +
...53\351\200\237\345\205\245\351\227\250.md" | 1153 ++++
...07\344\273\266\344\270\212\344\274\240.md" | 237 +
...70\350\247\201\346\263\250\350\247\243.md" | 0
...\243\347\241\256\347\232\204Controller.md" | 0
...67\346\261\202\350\275\254\345\217\221.md" | 0
...4\232SpringMVC\346\246\202\350\277\260.md" | 0
...43\346\236\220\345\216\237\347\220\206.md" | 0
...5\277\265\344\270\216DispatcherServlet.md" | 0
...6@ResponseBody\346\263\250\350\247\243.md" | 0
...75\347\232\204\346\224\257\346\214\201.md" | 32 +-
...57\345\242\203\345\217\230\351\207\217.md" | 15 +-
...04\347\220\206\346\234\272\345\210\266.md" | 34 +-
...54\346\225\260\346\215\256\357\274\211.md" | 20 +-
...72\346\234\254\347\224\250\346\263\225.md" | 488 +-
.../spring/Spring\346\246\202\350\277\260.md" | 36 +-
...37\347\220\206\350\257\246\350\247\243.md" | 0
...37\347\220\206\350\257\246\350\247\243.md" | 0
...4\232SpringAOP\346\246\202\350\277\260.md" | 0
...40\350\275\275\350\277\207\347\250\213.md" | 0
...13\345\212\241\346\246\202\350\277\260.md" | 0
...20\347\240\201\345\211\226\346\236\220.md" | 0
...\274\232Spring\346\246\202\350\277\260.md" | 0
...70\345\277\203\346\265\201\347\250\213.md" | 0
...07\347\250\213\345\210\206\346\236\220.md" | 0
43 files changed, 14849 insertions(+), 487 deletions(-)
create mode 100644 "docs/spring/SpringBoot/SpringBoot\344\270\255\347\232\204\344\273\273\345\212\241\350\260\203\345\272\246\344\270\216@Async.md"
create mode 100644 "docs/spring/SpringBoot/SpringBoot\344\270\255\347\232\204\346\227\245\345\277\227\347\256\241\347\220\206.md"
create mode 100644 "docs/spring/SpringBoot/SpringBoot\345\272\224\347\224\250\344\271\237\345\217\257\344\273\245\351\203\250\347\275\262\345\210\260\345\244\226\351\203\250Tomcat.md"
create mode 100644 "docs/spring/SpringBoot/SpringBoot\347\224\237\344\272\247\347\216\257\345\242\203\345\267\245\345\205\267Actuator.md"
create mode 100644 "docs/spring/SpringBoot/SpringBoot\347\232\204Starter\346\234\272\345\210\266.md"
create mode 100644 "docs/spring/SpringBoot/SpringBoot\347\232\204\351\205\215\347\275\256\346\226\207\344\273\266\347\256\241\347\220\206.md"
create mode 100644 "docs/spring/SpringBoot/SpringBoot\350\207\252\345\270\246\347\232\204\347\203\255\351\203\250\347\275\262\345\267\245\345\205\267.md"
create mode 100644 "docs/spring/SpringBoot/SpringBoot\351\233\206\346\210\220Swagger\345\256\236\347\216\260API\346\226\207\346\241\243\350\207\252\345\212\250\347\224\237\346\210\220.md"
create mode 100644 "docs/spring/SpringBoot/\345\237\272\344\272\216SpringBoot\344\270\255\347\232\204\345\274\200\346\272\220\347\233\221\346\216\247\345\267\245\345\205\267SpringBootAdmin.md"
rename "docs/spring/\347\273\231\344\275\240\344\270\200\344\273\275SpringBoot\347\237\245\350\257\206\346\270\205\345\215\225.md" => "docs/spring/SpringBoot/\347\273\231\344\275\240\344\270\200\344\273\275SpringBoot\347\237\245\350\257\206\346\270\205\345\215\225.md" (100%)
create mode 100644 "docs/spring/SpringMVC/SpringMVC\344\270\255\347\232\204\345\233\275\351\231\205\345\214\226\345\212\237\350\203\275.md"
create mode 100644 "docs/spring/SpringMVC/SpringMVC\344\270\255\347\232\204\345\270\270\347\224\250\345\212\237\350\203\275.md"
create mode 100644 "docs/spring/SpringMVC/SpringMVC\344\270\255\347\232\204\345\274\202\345\270\270\345\244\204\347\220\206\345\231\250.md"
create mode 100644 "docs/spring/SpringMVC/SpringMVC\344\270\255\347\232\204\346\213\246\346\210\252\345\231\250.md"
create mode 100644 "docs/spring/SpringMVC/SpringMVC\344\270\255\347\232\204\350\247\206\345\233\276\350\247\243\346\236\220\345\231\250.md"
create mode 100644 "docs/spring/SpringMVC/SpringMVC\344\270\255\347\232\204\350\277\207\346\273\244\345\231\250Filter.md"
create mode 100644 "docs/spring/SpringMVC/SpringMVC\345\237\272\346\234\254\344\273\213\347\273\215\344\270\216\345\277\253\351\200\237\345\205\245\351\227\250.md"
create mode 100644 "docs/spring/SpringMVC/SpringMVC\345\246\202\344\275\225\345\256\236\347\216\260\346\226\207\344\273\266\344\270\212\344\274\240.md"
rename "docs/spring/springMVC/SpringMVC\345\270\270\350\247\201\346\263\250\350\247\243.md" => "docs/spring/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220/SpringMVC\345\270\270\350\247\201\346\263\250\350\247\243.md" (100%)
rename "docs/spring/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232DispatcherServlet\345\246\202\344\275\225\346\211\276\345\210\260\346\255\243\347\241\256\347\232\204Controller.md" => "docs/spring/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232DispatcherServlet\345\246\202\344\275\225\346\211\276\345\210\260\346\255\243\347\241\256\347\232\204Controller.md" (100%)
rename "docs/spring/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232DispatcherServlet\347\232\204\345\210\235\345\247\213\345\214\226\344\270\216\350\257\267\346\261\202\350\275\254\345\217\221.md" => "docs/spring/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232DispatcherServlet\347\232\204\345\210\235\345\247\213\345\214\226\344\270\216\350\257\267\346\261\202\350\275\254\345\217\221.md" (100%)
rename "docs/spring/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\346\246\202\350\277\260.md" => "docs/spring/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\346\246\202\350\277\260.md" (100%)
rename "docs/spring/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\347\232\204\350\247\206\345\233\276\350\247\243\346\236\220\345\216\237\347\220\206.md" => "docs/spring/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\347\232\204\350\247\206\345\233\276\350\247\243\346\236\220\345\216\237\347\220\206.md" (100%)
rename "docs/spring/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\350\256\276\350\256\241\347\220\206\345\277\265\344\270\216DispatcherServlet.md" => "docs/spring/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232SpringMVC\350\256\276\350\256\241\347\220\206\345\277\265\344\270\216DispatcherServlet.md" (100%)
rename "docs/spring/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232\346\266\210\346\201\257\350\275\254\346\215\242\345\231\250HttpMessageConverter\344\270\216@ResponseBody\346\263\250\350\247\243.md" => "docs/spring/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\220\357\274\232\346\266\210\346\201\257\350\275\254\346\215\242\345\231\250HttpMessageConverter\344\270\216@ResponseBody\346\263\250\350\247\243.md" (100%)
rename "docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232AOP\345\256\236\347\216\260\345\216\237\347\220\206\350\257\246\350\247\243.md" => "docs/spring/Spring\346\272\220\347\240\201\345\210\206\346\236\220/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232AOP\345\256\236\347\216\260\345\216\237\347\220\206\350\257\246\350\247\243.md" (100%)
rename "docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232JDK\345\222\214cglib\345\212\250\346\200\201\344\273\243\347\220\206\345\216\237\347\220\206\350\257\246\350\247\243.md" => "docs/spring/Spring\346\272\220\347\240\201\345\210\206\346\236\220/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232JDK\345\222\214cglib\345\212\250\346\200\201\344\273\243\347\220\206\345\216\237\347\220\206\350\257\246\350\247\243.md" (100%)
rename "docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232SpringAOP\346\246\202\350\277\260.md" => "docs/spring/Spring\346\272\220\347\240\201\345\210\206\346\236\220/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232SpringAOP\346\246\202\350\277\260.md" (100%)
rename "docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232SpringIOC\345\256\271\345\231\250\347\232\204\345\212\240\350\275\275\350\277\207\347\250\213.md" => "docs/spring/Spring\346\272\220\347\240\201\345\210\206\346\236\220/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232SpringIOC\345\256\271\345\231\250\347\232\204\345\212\240\350\275\275\350\277\207\347\250\213.md" (100%)
rename "docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232Spring\344\272\213\345\212\241\346\246\202\350\277\260.md" => "docs/spring/Spring\346\272\220\347\240\201\345\210\206\346\236\220/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232Spring\344\272\213\345\212\241\346\246\202\350\277\260.md" (100%)
rename "docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232Spring\344\272\213\345\212\241\346\272\220\347\240\201\345\211\226\346\236\220.md" => "docs/spring/Spring\346\272\220\347\240\201\345\210\206\346\236\220/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232Spring\344\272\213\345\212\241\346\272\220\347\240\201\345\211\226\346\236\220.md" (100%)
rename "docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232Spring\346\246\202\350\277\260.md" => "docs/spring/Spring\346\272\220\347\240\201\345\210\206\346\236\220/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232Spring\346\246\202\350\277\260.md" (100%)
rename "docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232\345\210\235\346\216\242SpringIOC\346\240\270\345\277\203\346\265\201\347\250\213.md" => "docs/spring/Spring\346\272\220\347\240\201\345\210\206\346\236\220/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232\345\210\235\346\216\242SpringIOC\346\240\270\345\277\203\346\265\201\347\250\213.md" (100%)
rename "docs/spring/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232\346\207\222\345\212\240\350\275\275\347\232\204\345\215\225\344\276\213Bean\350\216\267\345\217\226\350\277\207\347\250\213\345\210\206\346\236\220.md" => "docs/spring/Spring\346\272\220\347\240\201\345\210\206\346\236\220/Spring\346\272\220\347\240\201\345\211\226\346\236\220\357\274\232\346\207\222\345\212\240\350\275\275\347\232\204\345\215\225\344\276\213Bean\350\216\267\345\217\226\350\277\207\347\250\213\345\210\206\346\236\220.md" (100%)
diff --git a/ReadMe.md b/ReadMe.md
index c8ec78e..c73d49b 100644
--- a/ReadMe.md
+++ b/ReadMe.md
@@ -144,32 +144,67 @@
### Spring
-* [Spring常见注解.md](docs/spring/Spring常见注解.md)
+* [SpringAOP的概念与作用](docs/spring/Spring常见注解.md)
+* [SpringBean的定义与管理(核心)](docs/spring/Spring常见注解.md)
+* [Spring中对于数据库的访问](docs/spring/Spring常见注解.md)
+* [Spring中对于校验功能的支持](docs/spring/Spring常见注解.md)
+* [Spring中的Environment环境变量](docs/spring/Spring常见注解.md)
+* [Spring中的事件处理机制](docs/spring/Spring常见注解.md)
+* [Spring中的资源管理](docs/spring/Spring常见注解.md)
+* [Spring中的配置元数据(管理配置的基本数据)](docs/spring/Spring常见注解.md)
+* [Spring事务基本用法](docs/spring/Spring常见注解.md)
+* [Spring合集](docs/spring/Spring常见注解.md)
+* [Spring容器与IOC](docs/spring/Spring常见注解.md)
+* [Spring常见注解](docs/spring/Spring常见注解.md)
+* [Spring概述](docs/spring/Spring常见注解.md)
+* [第一个Spring应用](docs/spring/Spring常见注解.md)
+
+* [Spring源码剖析:Spring概述](docs/spring/Spring源码分析/Spring源码剖析:Spring概述.md)
+* [Spring源码剖析:初探SpringIOC核心流程](docs/spring/Spring源码分析/Spring源码剖析:初探SpringIOC核心流程.md)
+* [Spring源码剖析:SpringIOC容器的加载过程 ](docs/spring/Spring源码分析/Spring源码剖析:SpringIOC容器的加载过程.md)
+* [Spring源码剖析:懒加载的单例Bean获取过程分析](docs/spring/Spring源码分析/Spring源码剖析:懒加载的单例Bean获取过程分析.md)
+* [Spring源码剖析:JDK和cglib动态代理原理详解 ](docs/spring/Spring源码分析/Spring源码剖析:JDK和cglib动态代理原理详解.md)
+* [Spring源码剖析:SpringAOP概述](docs/spring/Spring源码分析/Spring源码剖析:SpringAOP概述.md)
+* [Spring源码剖析:AOP实现原理详解 ](docs/spring/Spring源码分析/Spring源码剖析:AOP实现原理详解.md)
+* [Spring源码剖析:Spring事务概述](docs/spring/Spring源码分析/Spring源码剖析:Spring事务概述.md)
+* [Spring源码剖析:Spring事务源码剖析](docs/spring/Spring源码分析/Spring源码剖析:Spring事务源码剖析.md)
+### SpringMVC
-* [Spring源码剖析:Spring概述](docs/spring/Spring源码剖析:Spring概述.md)
-* [Spring源码剖析:初探SpringIOC核心流程](docs/spring/Spring源码剖析:初探SpringIOC核心流程.md)
-* [Spring源码剖析:SpringIOC容器的加载过程 ](docs/spring/Spring源码剖析:SpringIOC容器的加载过程.md)
-* [Spring源码剖析:懒加载的单例Bean获取过程分析](docs/spring/Spring源码剖析:懒加载的单例Bean获取过程分析.md)
-* [Spring源码剖析:JDK和cglib动态代理原理详解 ](docs/spring/Spring源码剖析:JDK和cglib动态代理原理详解.md)
-* [Spring源码剖析:SpringAOP概述](docs/spring/Spring源码剖析:SpringAOP概述.md)
-* [Spring源码剖析:AOP实现原理详解 ](docs/spring/Spring源码剖析:AOP实现原理详解.md)
-* [Spring源码剖析:Spring事务概述](docs/spring/Spring源码剖析:Spring事务概述.md)
-* [Spring源码剖析:Spring事务源码剖析](docs/spring/Spring源码剖析:Spring事务源码剖析.md)
+* [SpringMVC中的国际化功能](docs/spring/SpringMVC/SpringMVC中的国际化功能.md)
+* [SpringMVC中的异常处理器](docs/spring/SpringMVC/SpringMVC中的异常处理器.md)
+* [SpringMVC中的拦截器](docs/spring/SpringMVC/SpringMVC中的拦截器.md)
+* [SpringMVC中的视图解析器](docs/spring/SpringMVC/SpringMVC中的视图解析器.md)
+* [SpringMVC中的过滤器Filter](docs/spring/SpringMVC/SpringMVC中的过滤器Filter.md)
+* [SpringMVC基本介绍与快速入门](docs/spring/SpringMVC/SpringMVC基本介绍与快速入门.md)
+* [SpringMVC如何实现文件上传](docs/spring/SpringMVC/SpringMVC如何实现文件上传.md)
+* [SpringMVC中的常用功能](docs/spring/SpringMVC/SpringMVC中的常用功能.md)
-### SpringMVC
-* [SpringMVC源码分析:SpringMVC概述](docs/spring/springMVC/SpringMVC源码分析:SpringMVC概述.md)
-* [SpringMVC源码分析:SpringMVC设计理念与DispatcherServlet](docs/spring/springMVC/SpringMVC源码分析:SpringMVC设计理念与DispatcherServlet.md)
-* [SpringMVC源码分析:DispatcherServlet的初始化与请求转发 ](docs/spring/springMVC/SpringMVC源码分析:DispatcherServlet的初始化与请求转发.md)
-* [SpringMVC源码分析:DispatcherServlet如何找到正确的Controller ](docs/spring/springMVC/SpringMVC源码分析:DispatcherServlet如何找到正确的Controller.md)
-* [SpringMVC源码剖析:消息转换器HttpMessageConverter与@ResponseBody注解](docs/spring/springMVC/SpringMVC源码剖析:消息转换器HttpMessageConverter与@ResponseBody注解.md)
-* [SpringMVC源码分析:SpringMVC的视图解析原理 ](docs/spring/springMVC/SpringMVC源码分析:SpringMVC的视图解析原理.md)
+* [SpringMVC源码分析:SpringMVC概述](docs/spring/SpringMVC源码分析/SpringMVC源码分析:SpringMVC概述.md)
+* [SpringMVC源码分析:SpringMVC设计理念与DispatcherServlet](docs/spring/SpringMVC源码分析/SpringMVC源码分析:SpringMVC设计理念与DispatcherServlet.md)
+* [SpringMVC源码分析:DispatcherServlet的初始化与请求转发 ](docs/spring/SpringMVC源码分析/SpringMVC源码分析:DispatcherServlet的初始化与请求转发.md)
+* [SpringMVC源码分析:DispatcherServlet如何找到正确的Controller ](docs/spring/SpringMVC源码分析/SpringMVC源码分析:DispatcherServlet如何找到正确的Controller.md)
+* [SpringMVC源码剖析:消息转换器HttpMessageConverter与@ResponseBody注解](docs/spring/SpringMVC/SpringMVC源码剖析:消息转换器HttpMessageConverter与@ResponseBody注解.md)
+* [SpringMVC源码分析:SpringMVC的视图解析原理 ](docs/spring/SpringMVC源码分析/SpringMVC源码分析:SpringMVC的视图解析原理.md)
### SpringBoot
* [SpringBoot系列:SpringBoot的前世今生](docs/spring/SpringBoot/SpringBoot的前世今生.md)
+* [给你一份SpringBoot知识清单.md](docs/spring/SpringBoot/给你一份SpringBoot知识清单.md)
+* [Spring常见注解使用指南(包含Spring+SpringMVC+SpringBoot)](docs/spring/SpringBoot/Spring常见注解使用指南(包含Spring+SpringMVC+SpringBoot).md)
+* [SpringBoot中的日志管理](docs/spring/SpringBoot/SpringBoot中的日志管理.md)
+* [SpringBoot常见注解](docs/spring/SpringBoot/SpringBoot常见注解.md)
+* [SpringBoot应用也可以部署到外部Tomcat](docs/spring/SpringBoot/SpringBoot应用也可以部署到外部Tomcat.md)
+* [SpringBoot生产环境工具Actuator](docs/spring/SpringBoot/SpringBoot生产环境工具Actuator.md)
+* [SpringBoot的Starter机制](docs/spring/SpringBoot/SpringBoot的Starter机制.md)
+* [SpringBoot的前世今生](docs/spring/SpringBoot/SpringBoot的前世今生.md)
+* [SpringBoot的基本使用](docs/spring/SpringBoot/SpringBoot的基本使用.md)
+* [SpringBoot的配置文件管理](docs/spring/SpringBoot/SpringBoot的配置文件管理.md)
+* [SpringBoot自带的热部署工具](docs/spring/SpringBoot/SpringBoot自带的热部署工具.md)
+* [SpringBoot中的任务调度与@Async](docs/spring/SpringBoot/SpringBoot中的任务调度与@Async.md)
+* [基于SpringBoot中的开源监控工具SpringBootAdmin](docs/spring/SpringBoot/基于SpringBoot中的开源监控工具SpringBootAdmin.md)
### SpringCloud
diff --git "a/docs/spring/SpringBean\347\232\204\345\256\232\344\271\211\344\270\216\347\256\241\347\220\206\357\274\210\346\240\270\345\277\203\357\274\211.md" "b/docs/spring/SpringBean\347\232\204\345\256\232\344\271\211\344\270\216\347\256\241\347\220\206\357\274\210\346\240\270\345\277\203\357\274\211.md"
index a684554..c4de431 100644
--- "a/docs/spring/SpringBean\347\232\204\345\256\232\344\271\211\344\270\216\347\256\241\347\220\206\357\274\210\346\240\270\345\277\203\357\274\211.md"
+++ "b/docs/spring/SpringBean\347\232\204\345\256\232\344\271\211\344\270\216\347\256\241\347\220\206\357\274\210\346\240\270\345\277\203\357\274\211.md"
@@ -133,11 +133,11 @@ Bean
һעBeanBeanͻԶÿBeanʱԶBeanĻصʱͼ
-
+
עһ㣬ʹ`BeanFactory`ΪSpringֶעBeanȡBeanʵȻֶעᡣ
- BeanPostProcessor bp = (BeanPostProcessor)beanFactory.getBean("bp"); beanFactory.addBeanPostProcessor(bp); Person p = (Person)beanFactory.getBean("person");
+BeanPostProcessor bp = (BeanPostProcessor)beanFactory.getBean("bp"); beanFactory.addBeanPostProcessor(bp); Person p = (Person)beanFactory.getBean("person");
###
@@ -158,7 +158,7 @@ Spring
SpringļãָԶɨİ
-
+
### ʹ@Resource
@@ -174,6 +174,7 @@ Spring
Springṩ`@Autowired`עָԶװ䣬`@Autowired`setterͨʵȡʹ`@Autowired`עsetterʱĬϲbyTypeԶװԡֲ£Զװ͵ĺѡBeanʵжʱͿ쳣Ϊʵ־ȷԶװ䣬Springṩ`@Qualifier`ע⣬ͨʹ`@Qualifier`BeanidִԶװ䡣
# ο
+
https://www.w3cschool.cn/wkspring
https://www.runoob.com/w3cnote/basic-knowledge-summary-of-spring.html
http://codepub.cn/2015/06/21/Basic-knowledge-summary-of-Spring
diff --git "a/docs/spring/SpringBoot/SpringBoot\344\270\255\347\232\204\344\273\273\345\212\241\350\260\203\345\272\246\344\270\216@Async.md" "b/docs/spring/SpringBoot/SpringBoot\344\270\255\347\232\204\344\273\273\345\212\241\350\260\203\345\272\246\344\270\216@Async.md"
new file mode 100644
index 0000000..c3bce06
--- /dev/null
+++ "b/docs/spring/SpringBoot/SpringBoot\344\270\255\347\232\204\344\273\273\345\212\241\350\260\203\345\272\246\344\270\216@Async.md"
@@ -0,0 +1,240 @@
+
+
+
+
+# Spring Boot
+
+ݽվѸѧϰʼǡܽоղء֤ȷԣʹöķ뱾վأ
+
+
+
+
+
+
+
+
+
+ִضʱεĹ̡Spring BootΪSpringӦóϱдȳṩ˺ܺõ֧֡
+
+## Java Cronʽ
+
+Java CronʽCronTriggerʵ`org.quartz.Trigger`ࡣ йJava cronʽĸϢĴ -
+
+* [https://docs.oracle.com/cd/E12058_01/doc/doc.1014/e12030/cron_expressions.html](https://docs.oracle.com/cd/E12058_01/doc/doc.1014/e12030/cron_expressions.html)
+
+`[@EnableScheduling](https://github.com/EnableScheduling "@EnableScheduling")`עΪӦóõȳעӵSpring BootӦóļС
+
+```
+@SpringBootApplication
+@EnableScheduling
+
+public class DemoApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(DemoApplication.class, args);
+ }
+}
+
+```
+
+`[@Scheduled](https://github.com/Scheduled "@Scheduled")`עضʱڴȳ
+
+```
+@Scheduled(cron = "0 * 9 * * ?")
+public void cronJobSch() throws Exception {
+}
+
+```
+
+һʾ룬ʾÿ9:00ʼÿ9:59ִ
+
+```
+package com.yiibai.demo.scheduler;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+@Component
+public class Scheduler {
+ @Scheduled(cron = "0 * 9 * * ?")
+ public void cronJobSch() {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+ Date now = new Date();
+ String strDate = sdf.format(now);
+ System.out.println("Java cron job expression:: " + strDate);
+ }
+}
+
+```
+
+ĻͼʾӦó`09:03:23`Ҵʱÿһִһcronҵȳ
+
+
+
+## ̶
+
+̶ʵȳضʱִȴǰһɡ ֵԺΪλ ʾʾڴ˴ -
+
+```
+@Scheduled(fixedRate = 1000)
+public void fixedRateSch() {
+}
+
+```
+
+˴ʾӦóʱÿִʾ -
+
+```
+package com.yiibai.demo.scheduler;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+@Component
+public class Scheduler {
+ @Scheduled(fixedRate = 1000)
+ public void fixedRateSch() {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+
+ Date now = new Date();
+ String strDate = sdf.format(now);
+ System.out.println("Fixed Rate scheduler:: " + strDate);
+ }
+}
+
+```
+
+עĻͼʾ`09:12:00`Ӧó֮ÿһ̶ʵȳִ
+
+
+
+## ̶ӳ
+
+̶ӳٵȳضʱִ Ӧõȴһɡ ֵӦԺΪλ ˴ʾʾ -
+
+```
+@Scheduled(fixedDelay = 1000, initialDelay = 1000)
+public void fixedDelaySch() {
+}
+
+```
+
+`initialDelay`ڳʼӳֵ֮һִʱ䡣
+
+Ӧó`3`ÿִһʾʾ -
+
+```
+package com.yiibai.demo.scheduler;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+@Component
+public class Scheduler {
+ @Scheduled(fixedDelay = 1000, initialDelay = 3000)
+ public void fixedDelaySch() {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+ Date now = new Date();
+ String strDate = sdf.format(now);
+ System.out.println("Fixed Delay scheduler:: " + strDate);
+ }
+}
+
+```
+
+ִʾ`09:18:39`ʼӦóÿ`3`̶ӳټƻ(ÿִһ)
+
+
+
+
+
+//Ķhttps://www.yiibai.com/spring-boot/spring_boot_scheduling.html
+
+@EnableAsync ע
+Ҫʹ @AsyncҪʹ @EnableAsync ע Spring Boot е첽ԡ
+
+@Configuration
+@EnableAsync
+public class AppConfig {
+}
+ϸ˵ԲοAsyncConfigurer(opens new window)
+
+#@Async ע
+#ֵ֧÷
+1ֵ
+
+ @Async עη첽ʽá仰˵ڵô˷ʱأʵִзύ Spring TaskExecutor С£ԽעӦڷ void ķʾʾ
+
+@Async
+void doSomething() {
+// this will be executed asynchronously
+}
+2ֵ
+
+ʹ @Scheduled עע͵ķͬЩָΪʱɵԡʽãĵá磬´ @Async עĺϷӦã
+
+@Async
+void doSomething(String s) {
+// this will be executed asynchronously
+}
+3зֵ
+
+첽÷ֵķǣЩҪ Future ͵ķֵȻṩ첽ִеĺôԱ߿ڵ Future ϵ get() ֮ǰִʾʾڷֵķʹ@Async
+
+@Async
+Future returnSomething(int i) {
+// this will be executed asynchronously
+}
+#ֵ֧÷
+@Async ڻصһʹã @PostConstruct
+
+Ҫ첽ʼ Spring beanʹõijʼ Spring beanȻĿϵ @Async ע͵ķʾʾ
+
+public class SampleBeanImpl implements SampleBean {
+
+ @Async
+ void doSomething() {
+ // ...
+ }
+
+}
+
+public class SampleBeanInitializer {
+
+ private final SampleBean bean;
+
+ public SampleBeanInitializer(SampleBean bean) {
+ this.bean = bean;
+ }
+
+ @PostConstruct
+ public void initialize() {
+ bean.doSomething();
+ }
+
+}
+#ȷִָ
+Ĭ£ڷָ @Async ʱʹõִ첽֧ʱõִʹ XML AsyncConfigurer ʵ֣УΪ annotation-driven ԪءǣҪָʾִиʱӦʹĬִֵʹ @Async ע value ԡʾʾִд˲
+
+@Async("otherExecutor")
+void doSomething(String s) {
+// this will be executed asynchronously by "otherExecutor"
+}
+£otherExecutor Spring κ Executor bean ƣҲκ Executor ƣ磬ʹ Ԫػ Spring @Qualifier עָ
+
+# @Async 쳣
+ @Async ķֵΪ Future ʱڷִڼ׳쳣Ϊڵ get ʱ׳쳣ǣڷֵΪ void ͵ķ쳣ᱻ䡣ṩ AsyncUncaughtExceptionHandler 쳣ʾʾִд˲
+
+public class MyAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler {
+
+ @Override
+ public void handleUncaughtException(Throwable ex, Method method, Object... params) {
+ // handle exception
+ }
+}
+Ĭ£¼쳣ʹ AsyncConfigurer XML ԪضԶ AsyncUncaughtExceptionHandler
\ No newline at end of file
diff --git "a/docs/spring/SpringBoot/SpringBoot\344\270\255\347\232\204\346\227\245\345\277\227\347\256\241\347\220\206.md" "b/docs/spring/SpringBoot/SpringBoot\344\270\255\347\232\204\346\227\245\345\277\227\347\256\241\347\220\206.md"
new file mode 100644
index 0000000..009576d
--- /dev/null
+++ "b/docs/spring/SpringBoot/SpringBoot\344\270\255\347\232\204\346\227\245\345\277\227\347\256\241\347\220\206.md"
@@ -0,0 +1,806 @@
+## 4\. ־
+
+
+
+
+
+Spring Bootڲ־ʹ [Commons Logging](https://commons.apache.org/logging) Եײ־ʵֱֿš Ϊ [Java Util Logging](https://docs.oracle.com/javase/17/docs/api/java/util/logging/package-summary.html) [Log4j2](https://logging.apache.org/log4j/2.x/) [Logback](https://logback.qos.ch/) ṩĬá ÿһ£¼loggerԤΪʹÿ̨Ҳѡļ
+
+
+
+
+
+Ĭ£ʹ StarterĬʹLogback ʵLogback·ҲڣȷʹJava Util LoggingCommons LoggingLog4JSLF4Jⶼȷ
+
+
+
+
+
+| | кܶJava־ܡ бܻң벻Ҫġ һ˵㲻Ҫı־Spring BootĬֵͺܺá |
+| --- | --- |
+
+
+
+
+
+| | ӦóһservletӦ÷ʱJava Util Logging APIִе־ᱻ͵Ӧó־С ԷֹѾӦóִе־Ӧó־С |
+| --- | --- |
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/features.html#features.logging.log-format)4.1\. ־ʽ
+
+
+
+Spring BootĬϵ־ʽӡ
+
+
+
+
+
+
+
+ 2023-03-03T21:18:18.827+08:00 INFO 19388 --- [ main] o.s.b.d.f.s.MyApplication : Starting MyApplication using Java 17 with PID 19388 (/opt/apps/myapp.jar started by myuser in /opt/apps/)
+2023-03-03T21:18:18.834+08:00 INFO 19388 --- [ main] o.s.b.d.f.s.MyApplication : No active profile set, falling back to 1 default profile: "default"
+2023-03-03T21:18:20.439+08:00 INFO 19388 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
+2023-03-03T21:18:20.461+08:00 INFO 19388 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
+2023-03-03T21:18:20.461+08:00 INFO 19388 --- [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.5]
+2023-03-03T21:18:20.600+08:00 INFO 19388 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
+2023-03-03T21:18:20.602+08:00 INFO 19388 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1685 ms
+2023-03-03T21:18:21.078+08:00 INFO 19388 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
+2023-03-03T21:18:21.093+08:00 INFO 19388 --- [ main] o.s.b.d.f.s.MyApplication : Started MyApplication in 2.998 seconds (process running for 3.601)
+
+
+
+
+
+
+
+Ŀ¡
+
+
+
+
+
+* DateʱTimeȷ룬
+
+* ־: `ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`.
+
+* ID
+
+* һ `---` ָʵ־ϢĿʼ
+
+* ߳ƣڷУڿ̨ܻᱻضϣ
+
+* ¼ƣͨԴƣͨд
+
+* ־Ϣ
+
+
+
+
+
+| | Logbackû `FATAL` ӳ䵽 `ERROR` |
+| --- | --- |
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/features.html#features.logging.console-output)4.2\. ̨
+
+
+
+Ĭ£־ `ERROR``WARN` `INFO` Ϣ̨ Ҳͨ `--debug` ־Ӧó `debug` ģʽ
+
+
+
+
+
+
+
+```
+$ java -jar myapp.jar --debug
+```
+
+
+
+
+
+
+
+| | Ҳ `application.properties` ָ `debug=true` |
+| --- | --- |
+
+
+
+
+
+debugģʽʱһЩļ¼ǶʽHibernateSpring BootΪϢ debugģʽζŽӦóΪ `DEBUG` ¼Ϣ
+
+
+
+
+
+⣬ͨӦóʱʹ `--trace` ־ `application.properties` ʹ `trace=true` trace ģʽ ԶһЩļ¼ǶʽHibernate schemaɺSpringϣиټ¼
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/features.html#features.logging.console-output.color-coded)4.2.1\. ɫ
+
+
+
+ն֧ANSIͻʹòɫĶ Խ `spring.output.ansi.enabled` Ϊ [ֵֵ֧](https://docs.spring.io/spring-boot/docs/3.1.0-SNAPSHOT/api/org/springframework/boot/ansi/AnsiOutput.Enabled.html)ԸԶ⡣
+
+
+
+
+
+ɫͨʹ `%clr` תؼõġ ʽУת־ɫʾ
+
+
+
+
+
+
+
+```
+%clr(%5p)
+```
+
+
+
+
+
+
+
+±־ɫӳϵ
+
+
+
+
+| ־ | ɫ |
+| --- | --- |
+| `FATAL` | |
+| `ERROR` | |
+| `WARN` | |
+| `INFO` | |
+| `DEBUG` | |
+| `TRACE` | |
+
+
+
+⣬ҲͨΪתṩһѡָӦʹõɫʽ 磬ҪʹıΪɫʹá
+
+
+
+
+
+
+
+```
+%clr(%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}){yellow}
+```
+
+
+
+
+
+
+
+֧ɫʽ
+
+
+
+
+
+* `blue`
+
+* `cyan`
+
+* `faint`
+
+* `green`
+
+* `magenta`
+
+* `red`
+
+* `yellow`
+
+
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/features.html#features.logging.file-output)4.3\. ļ
+
+
+
+Ĭ£Spring Bootֻ̨¼־д־ļ ڿ̨֮д־ļҪ `logging.file.name` `logging.file.path` ԣ磬 `application.properties` У
+
+
+
+
+
+±ʾ `logging.*` αһʹá
+
+
+
+Table 5\. Logging properties
+| `logging.file.name` | `logging.file.path` | Example | Description |
+| --- | --- | --- | --- |
+| _(none)_ | _(none)_ | | ֻڿ̨м¼ |
+| ָļ | _(none)_ | `my.log` | дָ־ļ ƿһȷеλãҲ뵱ǰĿ¼λá |
+| _(none)_ | ָĿ¼ | `/var/log` | `spring.log` дָĿ¼ ƿһȷеλãҲ뵱ǰĿ¼λá |
+
+
+
+־ļڴﵽ10MBʱͻֻ̨һĬ»¼ `ERROR` `WARN` `INFO` Ϣ
+
+
+
+
+
+| | ־Զʵʵ־ʩ ˣضԣLogback `logback.configurationFile` spring Boot |
+| --- | --- |
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/features.html#features.logging.file-rotation)4.4\. ļֻ־
+
+
+
+ʹLogbackʹ `application.properties` `application.yaml` ļ־ֻá ־ϵͳ㽫ҪԼֱֻã磬ʹLog4J2ôһ `log4j2.xml` `log4j2-spring.xml` ļ
+
+
+
+
+
+ֻ֧ԡ
+
+
+
+
+| | ˵ |
+| --- | --- |
+| `logging.logback.rollingpolicy.file-name-pattern` | ڴ־鵵ļģʽ |
+| `logging.logback.rollingpolicy.clean-history-on-start` | ӦóʱǷ־鵵 |
+| `logging.logback.rollingpolicy.max-file-size` | ־ļ鵵ǰߴ磨ļﵽͻ鵵 |
+| `logging.logback.rollingpolicy.total-size-cap` | ־ڱɾǰߴ磨鵵ļռôССᱻɾ |
+| `logging.logback.rollingpolicy.max-history` | ҪĹ鵵־ļĬΪ7 |
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/features.html#features.logging.log-levels)4.5\. ־
+
+
+
+ֵ֧־ϵͳͨʹ `logging.level.=` Spring `Environment`磬 `application.properties`־ `level` `TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, `FATAL`, `OFF` ֮һ `root` ¼loggerļͨ `logging.level.root` á
+
+
+
+
+
+ʾ `application.properties` DZڵ־á
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+logging.level.root=warn
+logging.level.org.springframework.web=debug
+logging.level.org.hibernate=error
+```
+
+
+
+
+
+
+
+Ҳʹû־ 磬`LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_WEB=DEBUG` `org.springframework.web` Ϊ `DEBUG`
+
+
+
+
+
+| | ֻڰ־ ڿɰǽתΪСдĸԲַʽΪ־ ҪΪһ־ʹ[`SPRING_APPLICATION_JSON`](https://springdoc.cn/spring-boot/features.html#features.external-config.application-json) |
+| --- | --- |
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/features.html#features.logging.log-groups)4.6\. ־飨Log Groups
+
+
+
+ܹص־¼飬Աͬʱǽãͨá 磬ܾı __ Tomcatصļ¼ļ¼𣬵㲻סİ
+
+
+
+
+
+Ϊ˰⣬Spring BootSpring `Environment` ж־顣 磬ͨ `application.properties` м tomcat group
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+logging.group.tomcat=org.apache.catalina,org.apache.coyote,org.apache.tomcat
+
+```
+
+
+
+
+
+
+
+һúͿһдıloggerļ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+logging.level.tomcat=trace
+
+```
+
+
+
+
+
+
+
+Spring BootԤ־飬Կ伴á
+
+
+
+
+| | еlogger |
+| --- | --- |
+| web | `org.springframework.core.codec`, `org.springframework.http`, `org.springframework.web`, `org.springframework.boot.actuate.endpoint.web`, `org.springframework.boot.web.servlet.ServletContextInitializerBeans` |
+| sql | `org.springframework.jdbc.core`, `org.hibernate.SQL`, `org.jooq.tools.LoggerListener` |
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/features.html#features.logging.shutdown-hook)4.7\. ʹ־ Shutdown Hook
+
+
+
+ΪӦóֹʱͷ־ԴṩһShutdown HookJVM˳ʱ־ϵͳ ӦówarļʽģShutdown HookԶעᡣ ӦóиӵIJνṹShutdown Hook ܣùػӣоײ־ϵͳֱṩѡ 磬Logbackṩ [context selectors](https://logback.qos.ch/manual/loggingSeparation.html)ÿ¼Լб ʹ `logging.register-shutdown-hook` Shutdown Hook Ϊ `false` עᡣ `application.properties` `application.yaml` ļøԡ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+logging.register-shutdown-hook=false
+
+```
+
+
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/features.html#features.logging.custom-log-configuration)4.8\. Զ־
+
+
+
+־ϵͳͨclasspathϰʵĿҿͨclasspathĸĿ¼» Spring `Environment` ָλṩһʵļһƣ `logging.config`
+
+
+
+
+
+ͨʹ `org.springframework.boot.logging.LoggingSystem` ϵͳԣǿSpring Bootʹض־ϵͳ ֵӦ `LoggingSystem` ʵֵȫ Ҳͨʹ `none` ֵȫSpring Boot־á
+
+
+
+
+
+| | S־ڴ `ApplicationContext` ֮ǰʼģԲܴSpring `@Configuration` ļе `@PropertySources` ־ ı־ϵͳȫͣΨһͨSystem properties |
+| --- | --- |
+
+
+
+
+
+־ϵͳļ
+
+
+
+
+| ־ϵͳ | ļ |
+| --- | --- |
+| Logback | `logback-spring.xml`, `logback-spring.groovy`, `logback.xml` `logback.groovy` |
+| Log4j2 | `log4j2-spring.xml` `log4j2.xml` |
+| JDK (Java Util Logging) | `logging.properties` |
+
+
+
+| | ڿܵ£ǽʹ `-spring` ־ã磬 `logback-spring.xml` `logback.xml` ʹñλãSpringȫ־ʼ |
+| --- | --- |
+
+
+
+
+
+| | "ִеjar "ʱJava Util LoggingһЩ֪⣬ᵼ⡣ ܵĻǽڴ "ִеjar" ʱʹ |
+| --- | --- |
+
+
+
+
+
+Ϊ˰ƣһЩԴSpring `Environment` תƵSystem properties±ʾ
+
+
+
+| Spring Environment | System Property | ע |
+| --- | --- | --- |
+| `logging.exception-conversion-word` | `LOG_EXCEPTION_CONVERSION_WORD` | ¼쳣ʱʹõתʡ |
+| `logging.file.name` | `LOG_FILE` | ˣĬϵ־С |
+| `logging.file.path` | `LOG_PATH` | ˣĬϵ־С |
+| `logging.pattern.console` | `CONSOLE_LOG_PATTERN` | ڿ̨stdoutʹõ־ģʽ |
+| `logging.pattern.dateformat` | `LOG_DATEFORMAT_PATTERN` | date ʽ. |
+| `logging.charset.console` | `CONSOLE_LOG_CHARSET` | ̨־ַ롣 |
+| `logging.threshold.console` | `CONSOLE_LOG_THRESHOLD` | ڿ̨־¼־ |
+| `logging.pattern.file` | `FILE_LOG_PATTERN` | Ҫļʹõ־ģʽ `LOG_FILE` ã |
+| `logging.charset.file` | `FILE_LOG_CHARSET` | ļ־ַ루 `LOG_FILE` ã |
+| `logging.threshold.file` | `FILE_LOG_THRESHOLD` | ļ־¼־ |
+| `logging.pattern.level` | `LOG_LEVEL_PATTERN` | Ⱦ־ʱʹõĸʽĬΪ `%5p` |
+| `PID` | `PID` | ǰĽID |
+
+
+
+ʹLogbackҲᱻתơ
+
+
+
+| Spring Environment | System Property | ע |
+| --- | --- | --- |
+| `logging.logback.rollingpolicy.file-name-pattern` | `LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN` | ־ļģʽĬΪ `${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz` |
+| `logging.logback.rollingpolicy.clean-history-on-start` | `LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START` | Ƿʱ鵵־ļ |
+| `logging.logback.rollingpolicy.max-file-size` | `LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE` | ־ļС |
+| `logging.logback.rollingpolicy.total-size-cap` | `LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP` | Ҫ־ݵܴС |
+| `logging.logback.rollingpolicy.max-history` | `LOGBACK_ROLLINGPOLICY_MAX_HISTORY` | Ҫ鵵־ļ |
+
+
+
+ֵ֧־ϵͳڽļʱԴ System properties лȡԡ Ӽ `spring-boot.jar` еĬá
+
+
+
+
+
+* [Logback](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot/src/main/resources/org/springframework/boot/logging/logback/defaults.xml)
+
+* [Log4j 2](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot/src/main/resources/org/springframework/boot/logging/log4j2/log4j2.xml)
+
+* [Java Util logging](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot/src/main/resources/org/springframework/boot/logging/java/logging-file.properties)
+
+
+
+
+
+| | ־ʹռλӦʹ[Spring Boot](https://springdoc.cn/spring-boot/features.html#features.external-config.files.property-placeholders)ǵײܵ ֵעǣʹLogbackӦʹ `:` ΪĬֵ֮ķָʹ `:-` |
+| --- | --- |
+
+
+
+
+
+| | ֻͨ `LOG_LEVEL_PATTERN` ʹLogback `logging.pattern.level` ־MDCʱݡ 磬ʹ `logging.pattern.level=user:%X{user} %5p` ôĬϵ־ʽһ "user" MDCĿڵĻʾ 2019-08-30 12:30:04.031 user:someone INFO 22174 --- [ nio-8080-exec-0] demo.ControllerHandling authenticated request |
+| --- | --- |
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/features.html#features.logging.logback-extensions)4.9\. Logback չ
+
+
+
+Spring BootһЩLogbackչиá `logback-spring.xml` ļʹЩչ
+
+
+
+
+
+| | Ϊ `logback.xml` ļأ㲻ʹչ Ҫʹ `logback-spring.xml` ߶һ `logging.config` ԡ |
+| --- | --- |
+
+
+
+
+
+| | չ [Logbackɨ](https://logback.qos.ch/manual/configuration.html#autoScan) һʹá ͼļĻᵼµĴ¼ |
+| --- | --- |
+
+
+
+
+
+
+
+ ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:71 - no applicable action for [springProperty], current ElementPath is [[configuration][springProperty]]
+ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:71 - no applicable action for [springProfile], current ElementPath is [[configuration][springProfile]]
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/features.html#features.logging.logback-extensions.profile-specific)4.9.1\. ضļ
+
+
+
+`` ǩԸݻSpringļѡԵذųõIJ֣ ֧ `` Ԫصκεط ʹ `name` ָõļ `` ǩһļƣ `staging` һļʽ ļʽӵļ `production & (eu-central | eu-west)` 鿴 [Spring ܲοָ](https://docs.spring.io/spring-framework/docs/6.0.5/reference/html/core.html#beans-definition-profiles-java) ˽ϸڡ бʾļ
+
+
+
+
+
+
+
+```
+
+
+
+
+
+
+
+
+
+
+
+```
+
+
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/features.html#features.logging.logback-extensions.environment-properties)4.9.2\. ԣEnvironment Properties
+
+
+
+`` ǩԷ Spring `Environment` еԣԱLogbackʹá Logbackз `application.properties` ļеֵá ñǩĹʽLogbackı `` ǩơ Ȼ㲻ֱָһ `value` ָԵ `source` `Environment` Ҫ `local` Χĵط洢ԣʹ `scope` ԡ ҪһֵĬֵһû `Environment` ãʹ `defaultValue` ԡ ʾιԱLogbackʹá
+
+
+
+
+
+
+
+```
+
+
+ ${fluentHost}
+ ...
+
+```
+
+
+
+
+
+
+
+| | `source` kebabָ `my.property-name` ȻԿͨʹÿɵĹӵ `Environment` С |
+| --- | --- |
+
+
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/features.html#features.logging.log4j2-extensions)4.10\. Log4j2 չ
+
+
+
+Spring BootһЩLog4j2չиáκ `log4j2-spring.xml` ļʹЩչ
+
+
+
+
+
+| | Ϊ `log4j2.xml` ļأ㲻ʹչҪʹ `log4j2-spring.xml` ߶һ ``logging.config`` ԡ |
+| --- | --- |
+
+
+
+
+
+| | ЩչȡLog4Jṩ [Spring Boot֧](https://logging.apache.org/log4j/2.x/log4j-spring-boot/index.html) ӦȷĹв `org.apache.logging.log4j:log4j-spring-boot` ģ顣 |
+| --- | --- |
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/features.html#features.logging.log4j2-extensions.profile-specific)4.10.1\. ضļ
+
+
+
+`` ǩԸݻSpringļѡԵذųõIJ֡ļֱ֧ `` Ԫصκεطʹ `name` ָĸļá `` ǩһļƣ `staging`һļʽ ļʽӵļ `production & (eu-central | eu-west)`鿴 [Springܲοָ](https://docs.spring.io/spring-framework/docs/6.0.5/reference/html/core.html#beans-definition-profiles-java) ˽ϸڡ бʾļ
+
+
+
+
+
+
+
+```
+
+
+
+
+
+
+
+
+
+
+
+```
+
+
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/features.html#features.logging.log4j2-extensions.environment-properties-lookup)4.10.2\. EnvironmentԲ
+
+
+
+Log4j2Spring `Environment` еԣʹ `spring:` ǰ [](https://logging.apache.org/log4j/2.x/manual/lookups.html)Log4j2з `application.properties` ļеֵá
+
+
+
+
+
+ʾһΪ `applicationName` Log4j2ԣSpring `Environment` жȡ `spring.application.name`
+
+
+
+
+
+
+
+```
+
+ ${spring:spring.application.name}
+
+```
+
+
+
+
+
+
+
+| | ѯkeyӦkebabfָ `my.property-name` |
+| --- | --- |
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/features.html#features.logging.log4j2-extensions.environment-property-source)4.10.3\. Log4j2 ϵͳԣSystem Properties
+
+
+
+Log4j2֧һЩ [System Properties](https://logging.apache.org/log4j/2.x/manual/configuration.html#SystemProperties)øĿ磬`log4j2.skipJansi` ϵͳԿ `ConsoleAppender` ǷWindowsϳʹ [Jansi](https://github.com/fusesource/jansi)
+
+
+
+
+
+Log4j2 ʼصϵͳԶԴSpring `Environment` лá磬 `application.properties` ļ `log4j2.skipJansi=false` `ConsoleAppender` WindowsʹJansi
+
+
+
+
+
+| | ֻеϵͳԣsystem propertiesͲϵͳڼصֵʱŻῼSpring `Environment` |
+| --- | --- |
+
+
+
+
+
+| | Log4j2ʼڼصϵͳԲSpring `Environment`磬Log4j2ѡĬLog4j2ʵֵ Spring Environment ֮ǰʹõġ |
+| --- | --- |
+
+
+
+
+
+
+
diff --git "a/docs/spring/SpringBoot/SpringBoot\345\272\224\347\224\250\344\271\237\345\217\257\344\273\245\351\203\250\347\275\262\345\210\260\345\244\226\351\203\250Tomcat.md" "b/docs/spring/SpringBoot/SpringBoot\345\272\224\347\224\250\344\271\237\345\217\257\344\273\245\351\203\250\347\275\262\345\210\260\345\244\226\351\203\250Tomcat.md"
new file mode 100644
index 0000000..e22fa00
--- /dev/null
+++ "b/docs/spring/SpringBoot/SpringBoot\345\272\224\347\224\250\344\271\237\345\217\257\344\273\245\351\203\250\347\275\262\345\210\260\345\244\226\351\203\250Tomcat.md"
@@ -0,0 +1,302 @@
+
+
+
+
+# Spring Boot Tomcat
+
+ݽվѸѧϰʼǡܽоղء֤ȷԣʹöķ뱾վأ
+
+
+
+
+
+
+
+
+
+ͨʹSpring BootӦóԴһwarļԲWebСڱУѧϰδWARļTomcat WebвSpring BootӦó
+
+## Spring Boot Servletʼ
+
+ͳIJʽʹSpring BootӦó`[@SpringBootApplication](https://github.com/SpringBootApplication "@SpringBootApplication")`չ`SpringBootServletInitializer`ࡣ `SpringBootServletInitializer`ļʹServletʱӦó
+
+JARļSpring BootӦóļĴ -
+
+```
+package com.yiibai.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class DemoApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(DemoApplication.class, args);
+ }
+}
+
+```
+
+Ҫչ`SpringBootServletInitializer`֧WARļ Spring BootӦóļĴ -
+
+```
+package com.yiibai.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.support.SpringBootServletInitializer;
+
+@SpringBootApplication
+public class DemoApplication extends SpringBootServletInitializer {
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+ return application.sources(DemoApplication.class);
+ }
+ public static void main(String[] args) {
+ SpringApplication.run(DemoApplication.class, args);
+ }
+}
+
+```
+
+## Main
+
+Spring BootУҪڹļָࡣ
+Maven`pom.xml``start`࣬ʾ -
+
+```
+com.yiibai.demo.DemoApplication
+
+```
+
+Gradle`build.gradle`ʾ -
+
+```
+mainClassName="com.yiibai.demo.DemoApplication"
+
+```
+
+## JARΪWAR
+
+ʹ´뽫װJARΪWAR
+
+Maven_pom.xml_ нװΪWARʾ -
+
+```
+war
+
+```
+
+Gradle_build.gradle_ Ӧówarʾ -
+
+```
+apply plugin: 'war'
+apply plugin: 'application'
+
+```
+
+GradlNowдһRest˵ַ:`"Hello World from Tomcat"` ҪдRest˵㣬ҪSpring Boot Web starterӵļС
+
+MavenʹʾĴ_pom.xml_ Spring Boot -
+
+```
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+```
+
+GradleʹʾĴ_build.gradle_ Spring Boot starter -
+
+```
+dependencies {
+ compile('org.springframework.boot:spring-boot-starter-web')
+}
+
+```
+
+ڣʹʾĴSpring Boot ApplicationļбдһRest˵ -
+
+```
+package com.yiibai.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.support.SpringBootServletInitializer;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@SpringBootApplication
+@RestController
+public class DemoApplication extends SpringBootServletInitializer {
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+ return application.sources(DemoApplication.class);
+ }
+ public static void main(String[] args) {
+ SpringApplication.run(DemoApplication.class, args);
+ }
+
+ @RequestMapping(value = "/")
+ public String hello() {
+ return "Hello World from Tomcat";
+ }
+}
+
+```
+
+## Ӧó
+
+ڣʹMavenGradleһWARļԲTomcatУԴӦóʾ
+
+Mavenʹ`mvn package`Ӧó ȻWARļĿĿ¼ҵĻͼʾ -
+
+
+
+Gradleʹ`gradle clean build`Ӧó ȻWARļ`build/libs`Ŀ¼ҵ۲˴ĻͼԱõ -
+
+
+
+## Tomcat
+
+ڣTomcatwebappsĿ¼²WARļ۲˴ʾĻͼԱõ -
+
+
+
+ɹҳеURL => `http://localhost:8080/demo-0.0.1-SNAPSHOT/`۲ͼʾ -
+
+
+
+£
+
+ļ_pom.xml_ -
+
+```
+
+
+4.0.0
+
+ com.yiibai
+ demo
+ 0.0.1-SNAPSHOT
+ war
+ demo
+ Demo project for Spring Boot
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 1.5.8.RELEASE
+
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+ com.yiibai.demo.DemoApplication
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
+```
+
+ļ_build.gradle_
+
+```
+buildscript {
+ ext {
+ springBootVersion = '1.5.8.RELEASE'
+ }
+ repositories {
+ mavenCentral()
+ }
+dependencies {
+ classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
+ }
+}
+
+apply plugin: 'java'
+apply plugin: 'eclipse'
+apply plugin: 'org.springframework.boot'
+apply plugin: 'war'
+apply plugin: 'application'
+
+group = 'com.yiibai'
+version = '0.0.1-SNAPSHOT'
+sourceCompatibility = 1.8
+mainClassName = "com.yiibai.demo.DemoApplication"
+
+repositories {
+ mavenCentral()
+}
+dependencies {
+ compile('org.springframework.boot:spring-boot-starter-web')
+ testCompile('org.springframework.boot:spring-boot-starter-test')
+}
+
+```
+
+Spring BootӦóļĴ -
+
+```
+package com.yiibai.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.support.SpringBootServletInitializer;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@SpringBootApplication
+@RestController
+public class DemoApplication extends SpringBootServletInitializer {
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+ return application.sources(DemoApplication.class);
+ }
+ public static void main(String[] args) {
+ SpringApplication.run(DemoApplication.class, args);
+ }
+
+ @RequestMapping(value = "/")
+ public String hello() {
+ return "Hello World from Tomcat";
+ }
+}
+```
+
+
+
+
+
+//Ķhttps://www.yiibai.com/spring-boot/spring_boot_tomcat_deployment.html
+
diff --git "a/docs/spring/SpringBoot/SpringBoot\347\224\237\344\272\247\347\216\257\345\242\203\345\267\245\345\205\267Actuator.md" "b/docs/spring/SpringBoot/SpringBoot\347\224\237\344\272\247\347\216\257\345\242\203\345\267\245\345\205\267Actuator.md"
new file mode 100644
index 0000000..e0eeb3e
--- /dev/null
+++ "b/docs/spring/SpringBoot/SpringBoot\347\224\237\344\272\247\347\216\257\345\242\203\345\267\245\345\205\267Actuator.md"
@@ -0,0 +1,5832 @@
+
+
+#
+
+[Back to index](https://springdoc.cn/spring-boot/index.html)
+
+* [1\. Ĺ](https://springdoc.cn/spring-boot/actuator.html#actuator.enabling)
+* [2\. ˵㣨Endpoint](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints)
+* [3\. ͨHTTPмغ](https://springdoc.cn/spring-boot/actuator.html#actuator.monitoring)
+* [4\. ͨJMXмغ](https://springdoc.cn/spring-boot/actuator.html#actuator.jmx)
+* [5\. ɹ۲ԣObservability](https://springdoc.cn/spring-boot/actuator.html#actuator.observability)
+* [6\. ־¼Logger](https://springdoc.cn/spring-boot/actuator.html#actuator.loggers)
+* [7\. ָ꣨Metrics](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics)
+* [8\. ٣Tracing](https://springdoc.cn/spring-boot/actuator.html#actuator.micrometer-tracing)
+* [9\. ](https://springdoc.cn/spring-boot/actuator.html#actuator.auditing)
+* [10\. ¼ HTTP Exchange](https://springdoc.cn/spring-boot/actuator.html#actuator.http-exchanges)
+* [11\. ̼](https://springdoc.cn/spring-boot/actuator.html#actuator.process-monitoring)
+* [12\. Cloud Foundry ֧](https://springdoc.cn/spring-boot/actuator.html#actuator.cloud-foundry)
+* [13\. ʲô](https://springdoc.cn/spring-boot/actuator.html#actuator.whats-next)
+
+
+
+
+
+
+
+
+
+
+
+
+
+| | վ([springdoc.cn](https://springdoc.cn/))еԴ [spring.io](https://spring.io/) ԭʼȨ [spring.io](https://spring.io/) [springboot.io - Spring Boot](https://springboot.io/) з룬ɹѧϰоδɣýκתءû֮صΪ ̱Spring Pivotal Software, Inc. Լҵ̱ꡣ |
+| --- | --- |
+
+
+
+
+
+Spring BootһЩĹܣڽӦóʱغӦó ѡͨʹHTTP˵ʹJMXͼӦó ơָռҲԶӦӦó
+
+
+
+
+
+
+
+
+
+## [](https://springdoc.cn/spring-boot/actuator.html#actuator.enabling)1\. Ĺ
+
+
+
+
+
+[`spring-boot-actuator`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator) ģṩSpring Bootܡ ЩܵƼӶ `spring-boot-starter-actuator` Starter
+
+
+
+
+
+
+
+ActuatorĶ
+
+
+
+actuatorִ һָƶijĻеװáactuator ԴһСı仯в˶
+
+
+
+
+
+
+
+
+
+ҪڻMavenĿactuator Starter
+
+
+
+
+
+
+
+```
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+```
+
+
+
+
+
+
+
+Gradleʹ
+
+
+
+
+
+
+
+```
+dependencies {
+ implementation 'org.springframework.boot:spring-boot-starter-actuator'
+}
+```
+
+
+
+
+
+
+
+
+
+
+
+## [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints)2\. ˵㣨Endpoint
+
+
+
+
+
+Actuator ˵㣨endpointԼزӦó Spring BootһЩõĶ˵㣬ԼĶ˵㡣 磬`health` ˵ṩӦóϢ
+
+
+
+
+
+[û](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.enabling)ÿĶ˵㣬[ͨHTTPJMXǣʹǿԶ̷ʣ](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.exposing)һ˵㱻úͱ¶ʱΪǿõġõĶ˵ֻǿʱŻᱻԶáӦóѡͨHTTP¶ж˵ID `/actuator` ǰӳ䵽һURL磬Ĭ£`health` ˵㱻ӳ䵽 `/actuator/health`
+
+
+
+
+
+| | Ҫ˽actuatorĶ˵ԼǵӦʽ뿴APIĵ [HTML](https://docs.spring.io/spring-boot/docs/3.1.0-SNAPSHOT/actuator-api/htmlsingle) [PDF](https://docs.spring.io/spring-boot/docs/3.1.0-SNAPSHOT/actuator-api/pdf/spring-boot-actuator-web-api.pdf) |
+| --- | --- |
+
+
+
+
+
+Ǽصնˡ
+
+
+
+
+| ID | ˵ |
+| --- | --- |
+| `auditevents` | ǰӦó¼Ϣ Ҫһ `AuditEventRepository` bean |
+| `beans` | ʾӦóSpring Beanб |
+| `caches` | ʾõĻ档 |
+| `conditions` | ʾúԶԼǷϻϵԭ |
+| `configprops` | ʾ `@ConfigurationProperties` б |
+| `env` | ¶Spring `ConfigurableEnvironment` еԡ |
+| `flyway` | ʾκѾӦõFlywayݿǨơ Ҫһ `Flyway` bean |
+| `health` | ʾӦóĽϢ |
+| `httpexchanges` | ʾ HTTP exchange ϢĬ£ 100 HTTP request/response exchange Ҫһ `HttpExchangeRepository` bean |
+| `info` | ʾӦóϢ |
+| `integrationgraph` | ʾSpringͼ Ҫ `spring-integration-core` |
+| `loggers` | ʾӦóloggerá |
+| `liquibase` | ʾκѾӦõLiquibaseݿǨơ Ҫһ `Liquibase` Bean |
+| `metrics` | ʾǰӦó metrics Ϣ |
+| `mappings` | ʾ `@RequestMapping` ·б |
+| `quartz` | ʾйQuartz Scheduler JobϢ |
+| `scheduledtasks` | ʾӦóеļƻ |
+| `sessions` | Spring Sessionֵ֧ĻỰ洢мɾûỰ ҪһʹSpring SessionĻServletWebӦó |
+| `shutdown` | ӦóŵعرաֻʹjarʱЧĬǽõġ |
+| `startup` | ʾ `ApplicationStartup` ռ[](https://springdoc.cn/spring-boot/features.html#features.spring-application.startup-tracking)Ҫ `SpringApplication` Ϊ `BufferingApplicationStartup` |
+| `threaddump` | Performs a thread dump. |
+
+
+
+ӦóһWebӦóSpring MVCSpring WebFluxJerseyʹ¶Ķ˵㡣
+
+
+
+
+| ID | ˵ |
+| --- | --- |
+| `heapdump` | һdumpļ HotSpot JVMϣһ `HPROF` ʽļ OpenJ9 JVMϣһ `PHD` ʽļ |
+| `logfile` | ־ļݣ `logging.file.name` `logging.file.path` ѱã ֧ʹHTTP `Range` ͷ־ļIJݡ |
+| `prometheus` | Կɱ Prometheus ץȡĸʽչʾmetric `micrometer-registry-prometheus` |
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.enabling)2.1\. ö˵
+
+
+
+Ĭ£ `shutdown` ж˵㶼á Ҫһ˵ãʹ `management.endpoint..enabled` ԡ `shutdown` ˵㡣
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.endpoint.shutdown.enabled=true
+
+```
+
+
+
+
+
+
+
+ϣ˵ǡѡáǡѡá뽫 `management.endpoints.enabled-by-default` Ϊ `false`ʹõ˵ `enabled` ѡá `info` ˵㣬˵㡣
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.endpoints.enabled-by-default=false
+management.endpoint.info.enabled=true
+
+```
+
+
+
+
+
+
+
+| | õĶ˵Ӧóȫɾֻı䱩¶˵ļʹ [`include` `exclude` ](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.exposing)档 |
+| --- | --- |
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.exposing)2.2\. ¶˵
+
+
+
+Ĭ£ֻhealth˵ͨHTTPJMX¶ġ ڶ˵ܰϢӦϸǺʱ¶ǡ
+
+
+
+
+
+ҪıЩ˵㱻¶ʹض `include` `exclude` ԡ
+
+
+
+
+| | Ĭ |
+| --- | --- |
+| `management.endpoints.jmx.exposure.exclude` | |
+| `management.endpoints.jmx.exposure.include` | `health` |
+| `management.endpoints.web.exposure.exclude` | |
+| `management.endpoints.web.exposure.include` | `health` |
+
+
+
+`include` г˱¶Ķ˵ID `exclude` г˲ӦñĶ˵ID `exclude` `include` ԡ һ˵IDб `include` `exclude` ԡ
+
+
+
+
+
+磬ҪͨJMXֻ `health` `info` ˵㣬ʹԡ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.endpoints.jmx.exposure.include=health,info
+
+```
+
+
+
+
+
+
+
+`*` ѡж˵㡣 磬ҪͨHTTPеĶ `env` `beans` ˵㣬ʹԡ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.endpoints.web.exposure.include=*
+management.endpoints.web.exposure.exclude=env,beans
+
+```
+
+
+
+
+
+
+
+| | `*` YAMLо⺬壬ųеĶ˵㣬һҪš |
+| --- | --- |
+
+
+
+
+
+| | Ӧóǹ¶ģǿҽҲ[Ķ˵](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.security) |
+| --- | --- |
+
+
+
+
+
+| | ڶ˵㱩¶ʱʵʩԼIJԣעһ `EndpointFilter` bean |
+| --- | --- |
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.security)2.3\. ȫSecurity
+
+
+
+Ϊ˰ȫĬֻ `/health` ˵ͨHTTP ʹ `management.endpoints.web.exposure.include` ñ¶Ķ˵㡣
+
+
+
+
+
+| | `management.endpoints.web.exposure.include` ֮ǰȷ¶ִϢڷǽ֮Spring Security֮Ķ֤ȫ |
+| --- | --- |
+
+
+
+
+
+Spring Securityclasspathϣû `SecurityFilterChain` beanô `/health` ִ֮actuatorSpring BootԶ֤ȫ 㶨һԶ `SecurityFilterChain` beanSpring BootԶþͻȫִķʹ
+
+
+
+
+
+ΪHTTP˵Զ尲ȫ磬ֻijֽɫûʣSpring BootṩһЩ `RequestMatcher` Spring Securityʹá
+
+
+
+
+
+һ͵Spring Securityÿܿӡ
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@Configuration(proxyBeanMethods = false)
+public class MySecurityConfiguration {
+
+ @Bean
+ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
+ http.securityMatcher(EndpointRequest.toAnyEndpoint());
+ http.authorizeHttpRequests((requests) -> requests.anyRequest().hasRole("ENDPOINT_ADMIN"));
+ http.httpBasic(withDefaults());
+ return http.build();
+ }
+
+}
+
+```
+
+
+
+
+
+
+
+ǰʹ `EndpointRequest.toAnyEndpoint()` ƥһκζ˵㣬ȻȷеĶ˵㶼 `ENDPOINT_ADMIN` Ľɫ `EndpointRequest` ϻƥ APIĵ [HTML](https://docs.spring.io/spring-boot/docs/3.1.0-SNAPSHOT/actuator-api/htmlsingle) [PDF](https://docs.spring.io/spring-boot/docs/3.1.0-SNAPSHOT/actuator-api/pdf/spring-boot-actuator-web-api.pdf)
+
+
+
+
+
+ڷǽ沿Ӧóϣִ˵㶼ܱʣҪ֤ ͨı `management.endpoints.web.exposure.include` һ㣬ʾ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.endpoints.web.exposure.include=*
+
+```
+
+
+
+
+
+
+
+⣬Spring SecurityҪԶ尲ȫãδ֤ķʶ˵㣬ʾ
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@Configuration(proxyBeanMethods = false)
+public class MySecurityConfiguration {
+
+ @Bean
+ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
+ http.securityMatcher(EndpointRequest.toAnyEndpoint());
+ http.authorizeHttpRequests((requests) -> requests.anyRequest().permitAll());
+ return http.build();
+ }
+
+}
+
+```
+
+
+
+
+
+
+
+| | ǰУֻactuator˵㡣 Spring Bootİȫκ `SecurityFilterChain` bean¶ȫ˳Ҫһ `SecurityFilterChain` beanӦó֡ |
+| --- | --- |
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.security.csrf)2.3.1\. վα챣CSRF
+
+
+
+Spring BootSpring SecurityĬֵCSRFĬ± ζʹĬϰȫʱҪ `POST`shutdownloggers˵㣩`PUT` `DELETE` actuator˵403ֹĴ
+
+
+
+
+
+| | ǽֻ㴴ķͻʹʱȫCSRF |
+| --- | --- |
+
+
+
+
+
+ [Springȫοָ](https://docs.spring.io/spring-security/reference/6.1.0-M1/features/exploits/csrf.html) ҵCSRFϢ
+
+
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.caching)2.4\. ö˵
+
+
+
+˵Զ治ҪκβĶȡӦ Ҫö˵㻺Ӧʱ䣬ʹ `cache.time-to-live` ԡ ӽ `beans` ˵ĻʱΪ10롣
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.endpoint.beans.cache.time-to-live=10s
+
+```
+
+
+
+
+
+
+
+| | `management.endpoint.` ǰΨһرʶõĶ˵㡣 |
+| --- | --- |
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.hypermedia)2.5\. Actuator Web ˵ijý壨Hypermedia
+
+
+
+һ discovery page ӵж˵С Ĭ£discovery page `/actuator` ǿõġ
+
+
+
+
+
+Ҫ discovery pageӦóԡ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.endpoints.web.discovery.enabled=false
+
+```
+
+
+
+
+
+
+
+һԶĹ·ʱdiscovery page Զ `/actuator` Ƶĵĸ 磬· `/management`discovery pageԴ `/management` á ·Ϊ `/` ʱҳãԷֹmappingͻĿԡ
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.cors)2.6\. CORS֧
+
+
+
+[ԴԴ](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing)CORS [W3Cһ淶](https://www.w3.org/TR/cors/)ķʽָֿȨʹSpring MVCSpring WebFluxActuatorWeb˵֧
+
+
+
+
+
+CORS֧Ĭǽõģֻ `management.endpoints.web.cors.allowed-origins` ԺŻá `example.com` е `GET` `POST`
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.endpoints.web.cors.allowed-origins=https://example.com
+management.endpoints.web.cors.allowed-methods=GET,POST
+
+```
+
+
+
+
+
+
+
+| | μ [`CorsEndpointProperties`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/CorsEndpointProperties.java) Իѡб |
+| --- | --- |
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.implementing-custom)2.7\. ʵԶ˵
+
+
+
+һ `@Endpoint` ע `@Bean`κδ `@ReadOperation``@WriteOperation` `@DeleteOperation` ע͵ķԶͨJMXWebӦóҲͨHTTP ͨʹJerseySpring MVCSpring WebFlux˵ͨHTTP¶ JerseySpring MVCãʹSpring MVC
+
+
+
+
+
+ӱ¶һһԶ
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@ReadOperation
+public CustomData getData() {
+ return new CustomData("test", 5);
+}
+
+```
+
+
+
+
+
+
+
+Ҳͨʹ `@JmxEndpoint` `@WebEndpoint` дضĶ˵㡣 Щ˵㱻ǸԵļϡ 磬`@WebEndpoint` ֻͨHTTP¶ͨJMX
+
+
+
+
+
+ͨʹ `@EndpointWebExtension` `@EndpointJmxExtension` дضļչ ЩעṩضIJǿеĶ˵㡣
+
+
+
+
+
+ҪWebܵضܣʵservletSpring `@Controller` `@RestController` ˵㣬DzͨJMXʹòͬWebʱá
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.implementing-custom.input)2.7.1\.
+
+
+
+˵ϵIJͨ롣 ͨwebʱЩֵURLIJѯJSON塣 ͨJMXʱӳ䵽MBeanIJС Ĭ£DZġ ǿͨʹ `@javax.annotation.Nullable` `@org.springframework.lang.Nullable` עΪѡ
+
+
+
+
+
+ԽJSONеÿӳ䵽˵һ һJSON塣
+
+
+
+
+
+
+
+```
+{
+ "name": "test",
+ "counter": 42
+}
+```
+
+
+
+
+
+
+
+һдòҪ `String name` `int counter` ʾ
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@WriteOperation
+public void updateData(String name, int counter) {
+ // injects "test" and 42
+}
+
+```
+
+
+
+
+
+
+
+| | Ϊ˵Ǽ֪ģڷǩָֻ͡ رǣ֧ `CustomData` һ `name` `counter` Եĵһ |
+| --- | --- |
+
+
+
+
+
+| | Ϊӳ䵽IJʵֶ˵JavaӦ `-parameters` 룬ʵֶ˵KotlinӦ `-java-parameters` 롣 ʹSpring BootGradleʹMaven `spring-boot-starter-parent`⽫Զ |
+| --- | --- |
+
+
+
+
+
+##### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.implementing-custom.input.conversion)ת
+
+
+
+бҪݸ˵IJԶתΪ͡ ڵò֮ǰͨJMXHTTPյ뱻תΪͣʹ `ApplicationConversionService` ʵԼκ `Converter` `GenericConverter` Bean `@EndpointConverter`
+
+
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.implementing-custom.web)2.7.2\. ԶWEB˵
+
+
+
+ `@Endpoint``@WebEndpoint` `@EndpointWebExtension` ԶʹJerseySpring MVCSpring WebFluxͨHTTP JerseySpring MVCãʹSpring MVC
+
+
+
+
+
+##### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.implementing-custom.web.request-predicates)WEB˵νʣPredicates
+
+
+
+һνʻΪweb¶Ķ˵ϵÿoperationԶɡ
+
+
+
+
+
+
+
+##### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.implementing-custom.web.path-predicates)Path
+
+
+
+pathνɶ˵ID籩¶Ķ˵Ļ· ĬϵĻ· `/actuator` 磬һIDΪ `sessions` Ķ˵νʹ `/actuator/sessions` Ϊ·
+
+
+
+
+
+ͨ `@Selector` עһһ· IJΪһ·ӵ·νС ڵö˵ʱñֵᱻ 벶ʣ·Ԫأһ `@Selector(Match=ALL_REMAINING)`ʹΪһ `String[]` תݵ͡
+
+
+
+
+
+
+
+##### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.implementing-custom.web.method-predicates)HTTP method
+
+
+
+HTTP methodνɲ;ģ±ʾ
+
+
+
+
+| Operation | HTTP method |
+| --- | --- |
+| `@ReadOperation` | `GET` |
+| `@WriteOperation` | `POST` |
+| `@DeleteOperation` | `DELETE` |
+
+
+
+
+
+##### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.implementing-custom.web.consumes-predicates)Consumes
+
+
+
+ʹrequest body `@WriteOperation`HTTP `POST`νʵ `consumes` Ӿ `application/vnd.spring-boot.actuator.v2+json, application/json` `consumes` Ӿǿյġ
+
+
+
+
+
+
+
+##### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.implementing-custom.web.produces-predicates)Produces
+
+
+
+νʵ `produces` Ӿ `@DeleteOperation``@ReadOperation` `@WriteOperation` ע͵ `produces` Ծ ǿѡġ ʹ`produces` ӾԶȷ
+
+
+
+
+
+ `void` `Void` `produces` ӾΪա `org.springframework.core.io.Resource``produces` Ӿ `application/octet-stream` `produces` Ӿ `application/vnd.spring-boot.actuator.v2+json, application/json`
+
+
+
+
+
+
+
+##### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.implementing-custom.web.response-status)WEB˵Ӧ״̬
+
+
+
+˵ĬӦ״̬ȡڲͣдɾͲصݣеĻ
+
+
+
+
+
+ `@ReadOperation` һֵӦ״̬200(Ok) ûзһֵӦ״̬404(Not Found)
+
+
+
+
+
+ `@WriteOperation` `@DeleteOperation` һֵӦ״̬200OK ûзһֵӦ״̬204No Content
+
+
+
+
+
+һڵʱûIJ߲ܱתΪͣͲᱻãӦ״̬400Bad Request
+
+
+
+
+
+
+
+##### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.implementing-custom.web.range-requests)WEB˵ Range
+
+
+
+ʹHTTP rangeһHTTPԴһ֡ ʹSpring MVCSpring Web Fluxʱ `org.springframework.core.io.Resource` IJԶַ֧Χ
+
+
+
+
+
+| | ʹJerseyʱ֧ Range |
+| --- | --- |
+
+
+
+
+
+
+
+##### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.implementing-custom.web.security)Web˵İȫ
+
+
+
+web˵webض˵չϵIJԽյǰ `java.security.Principal` `org.springframework.boot.actuate.endpoint.SecurityContext` Ϊ ǰͨ `@Nullable` һʹãΪ֤δ֤ûṩͬΪ ͨͨʹ `isUserInRole(String)` ִȨ顣
+
+
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.implementing-custom.servlet)2.7.3\. Servlet ˵
+
+
+
+һServletΪһ˵㱩¶ʵһ `@ServletEndpoint` ע࣬ͬʱʵ `Supplier` Servlet˵ṩservletĸεϣȴ˿ֲԡ ǵĿеServletΪһ˵ µĶ˵㣬Ӧѡ `@Endpoint` `@WebEndpoint` ע⡣
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.implementing-custom.controller)2.7.4\. Controller ˵
+
+
+
+ʹ `@ControllerEndpoint` `@RestControllerEndpoint` ʵһSpring MVCSpring WebFluxĶ˵㡣 ͨʹSpring MVCSpring WebFluxıעӳ䣬 `@RequestMapping` `@GetMapping`˵ID·ǰ ˵ṩSpringWebܸļɣȴ˿ֲԡ Ӧѡ `@Endpoint` `@WebEndpoint` ע⡣
+
+
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.health)2.8\. Ϣ
+
+
+
+ʹýϢеӦó״̬ ϵͳʱѱˡ `health` ˵㱩¶Ϣȡ `management.endpoint.health.show-details` `management.endpoint.health.show-components` ԣǿΪֵ֮һ
+
+
+
+
+| ֵ | ˵ |
+| --- | --- |
+| `never` | ϸڴӲʾ |
+| `when-authorized` | ϸֻʾȨû ȨĽɫͨʹ `management.endpoint.health.roles` á |
+| `always` | ʾû |
+
+
+
+Ĭֵ `never` ûڶ˵һɫʱDZΪDZȨġ ˵ûýɫĬֵ֤ûΪȨġ ͨʹ `management.endpoint.health.roles` ýɫ
+
+
+
+
+
+| | ѾӦóϣʹ `always`İȫãsecurity configuration֤ͷ֤ûhealth˵㡣 |
+| --- | --- |
+
+
+
+
+
+ϢǴ [`HealthContributorRegistry`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthContributorRegistry.java) ռģĬ£ [`HealthContributor`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthContributor.java) ʵ `ApplicationContext` У Spring BootһЩԶõ `HealthContributor`ҲԱдԼġ
+
+
+
+
+
+һ `HealthContributor` һ `HealthIndicator` һ `CompositeHealthContributor` һ `HealthIndicator` ṩʵʵĽϢ `Status` һ `CompositeHealthContributor` ṩ `HealthContributors` ϡ ۺcontributorγһ״ṹʾϵͳĽ״
+
+
+
+
+
+Ĭ£յϵͳ״һ `StatusAggregator` óģһ״̬бÿ `HealthIndicator` ״̬ беĵһ״̬彡״̬ û `HealthIndicator` ص״̬ `StatusAggregator` ֪ģͻʹ `UNKNOWN` ״̬
+
+
+
+
+
+| | ʹ `HealthContributorRegistry` ʱעȡעὡָꡣ |
+| --- | --- |
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.health.auto-configured-health-indicators)2.8.1\. ԶõHealthIndicators
+
+
+
+ʵʱSpring BootԶ±г `HealthIndicators` Ҳͨ `management.health.key.enabled` ûͣѡָꡣ ±г `key`
+
+
+
+
+| Key | Name | ˵ |
+| --- | --- | --- |
+| `cassandra` | [`CassandraDriverHealthIndicator`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cassandra/CassandraDriverHealthIndicator.java) | CassandraݿǷѾ |
+| `couchbase` | [`CouchbaseHealthIndicator`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/couchbase/CouchbaseHealthIndicator.java) | CouchbaseȺǷѾ |
+| `db` | [`DataSourceHealthIndicator`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/jdbc/DataSourceHealthIndicator.java) | ǷԻ`DataSource`ӡ |
+| `diskspace` | [`DiskSpaceHealthIndicator`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicator.java) | ̿ռǷ㡣 |
+| `elasticsearch` | [`ElasticsearchRestHealthIndicator`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/elasticsearch/ElasticsearchRestHealthIndicator.java) | ElasticsearchȺǷѾ |
+| `hazelcast` | [`HazelcastHealthIndicator`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/hazelcast/HazelcastHealthIndicator.java) | HazelcastǷѾ |
+| `influxdb` | [`InfluxDbHealthIndicator`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/influx/InfluxDbHealthIndicator.java) | InfluxDBǷѾ |
+| `jms` | [`JmsHealthIndicator`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/jms/JmsHealthIndicator.java) | һJMSǷѾ |
+| `ldap` | [`LdapHealthIndicator`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/ldap/LdapHealthIndicator.java) | һLDAPǷ |
+| `mail` | [`MailHealthIndicator`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/mail/MailHealthIndicator.java) | һʼǷ |
+| `mongo` | [`MongoHealthIndicator`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/data/mongo/MongoHealthIndicator.java) | MongoݿǷѾ |
+| `neo4j` | [`Neo4jHealthIndicator`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/neo4j/Neo4jHealthIndicator.java) | Neo4jݿǷѾ |
+| `ping` | [`PingHealthIndicator`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/PingHealthIndicator.java) | Ӧ `UP` |
+| `rabbit` | [`RabbitHealthIndicator`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/amqp/RabbitHealthIndicator.java) | һRabbitǷѾ |
+| `redis` | [`RedisHealthIndicator`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/data/redis/RedisHealthIndicator.java) | RedisǷѾ |
+
+
+
+| | ͨ `management.health.defaults.enabled` ǡ |
+| --- | --- |
+
+
+
+
+
+ `HealthIndicators` ǿõģĬ²á
+
+
+
+
+| Key | Name | ˵ |
+| --- | --- | --- |
+| `livenessstate` | [`LivenessStateHealthIndicator`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/availability/LivenessStateHealthIndicator.java) | ʾ Liveness ӦóĿ״̬ |
+| `readinessstate` | [`ReadinessStateHealthIndicator`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/availability/ReadinessStateHealthIndicator.java) | ¶ Readiness ӦóĿ״̬ |
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.health.writing-custom-health-indicators)2.8.2\. дԶHealthIndicators
+
+
+
+ΪṩԶĽϢעʵ [`HealthIndicator`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthIndicator.java) ӿڵSpring Bean Ҫṩһ `health()` ʵ֣һ `Health` Ӧ `Health` ӦӦðһstatusѡҪʾϸڡ Ĵʾһ `HealthIndicator` ʵ
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@Component
+public class MyHealthIndicator implements HealthIndicator {
+
+ @Override
+ public Health health() {
+ int errorCode = check();
+ if (errorCode != 0) {
+ return Health.down().withDetail("Error Code", errorCode).build();
+ }
+ return Health.up().build();
+ }
+
+ private int check() {
+ // perform some specific health check
+ return ...
+ }
+
+}
+
+```
+
+
+
+
+
+
+
+| | һ `HealthIndicator` ıʶIDû `HealthIndicator` Bean֣ڵĻ ǰУϢһΪ `my` Ŀҵ |
+| --- | --- |
+
+
+
+
+
+| | ָͨͨHTTPõģҪκӳʱ֮ǰӦ κνָӦʱ䳬10룬Spring Boot¼һϢ ֵʹ `management.endpoint.health.logging.slow-indicator-threshold` ԡ |
+| --- | --- |
+
+
+
+
+
+Spring BootԤ [`Status`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/Status.java) ⣬`Health` Էشϵͳ״̬Զ `Status` £㻹Ҫṩ `StatusAggregator` ӿڵԶʵ֣ͨʹ `management.endpoint.health.status.order` Ĭʵ֡
+
+
+
+
+
+磬һ `HealthIndicator` ʵʹһΪ `FATAL` `Status` Ϊ˳Ӧóԡ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.endpoint.health.status.order=fatal,down,out-of-service,unknown,up
+
+```
+
+
+
+
+
+
+
+ӦеHTTP״̬뷴ӳ彡״̬ Ĭ£`OUT_OF_SERVICE` `DOWN` ӳ䵽503 κδӳĽ״̬ `UP`ӳΪ200 ͨHTTPʽ˵㣬ܻעԶ״̬ӳ䡣 Զӳ `DOWN` `OUT_OF_SERVICE` Ĭӳ䡣 뱣Ĭӳ䣬ȷǣԼκԶӳ䡣 磬Խ `FATAL` ӳΪ503ã `DOWN` `OUT_OF_SERVICE` Ĭӳ䡣
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.endpoint.health.status.http-mapping.down=503
+management.endpoint.health.status.http-mapping.fatal=503
+management.endpoint.health.status.http-mapping.out-of-service=503
+
+```
+
+
+
+
+
+
+
+| | ҪĿƣԶԼ `HttpCodeStatusMapper` bean |
+| --- | --- |
+
+
+
+
+
+±ʾ״̬Ĭ״̬ӳ䡣
+
+
+
+
+| Status | Mapping |
+| --- | --- |
+| `DOWN` | `SERVICE_UNAVAILABLE` (`503`) |
+| `OUT_OF_SERVICE` | `SERVICE_UNAVAILABLE` (`503`) |
+| `UP` | Ĭûӳ䣬HTTP״̬Ϊ `200` |
+| `UNKNOWN` | Ĭûӳ䣬HTTP״̬Ϊ `200` |
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.health.reactive-health-indicators)2.8.3\. Ӧʽָ
+
+
+
+ӦʽӦóЩʹSpring WebFluxӦó`ReactiveHealthContributor` ṩһԼȡӦóĽ״ 봫ͳ `HealthContributor` ƣϢ [`ReactiveHealthContributorRegistry`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ReactiveHealthContributorRegistry.java) ռĬ£ [`HealthContributor`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthContributor.java) [`ReactiveHealthContributor`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ReactiveHealthContributor.java) ʵ `ApplicationContext`
+
+
+
+
+
+ӦʽAPIмij `HealthContributors` ڵԵִС
+
+
+
+
+
+| | һӦʽӦóУӦʹ `ReactiveHealthContributorRegistry` ʱעȡעὡָꡣ Ҫעһͨ `HealthContributor`Ӧ `ReactiveHealthContributor#adapt` װ |
+| --- | --- |
+
+
+
+
+
+Ϊ˴ӦʽAPIṩԶĽϢעʵ [`ReactiveHealthIndicator`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ReactiveHealthIndicator.java) ӿڵSpring Bean Ĵʾһ `ReactiveHealthIndicator` ʾʵ֡
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@Component
+public class MyReactiveHealthIndicator implements ReactiveHealthIndicator {
+
+ @Override
+ public Mono health() {
+ return doHealthCheck().onErrorResume((exception) ->
+ Mono.just(new Health.Builder().down(exception).build()));
+ }
+
+ private Mono doHealthCheck() {
+ // perform some specific health check
+ return ...
+ }
+
+}
+
+```
+
+
+
+
+
+
+
+| | ΪԶԿǴ `AbstractReactiveHealthIndicator` չ |
+| --- | --- |
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.health.auto-configured-reactive-health-indicators)2.8.4\. Զõ ReactiveHealthIndicators
+
+
+
+ʵʱSpring BootԶµ `ReactiveHealthIndicators`
+
+
+
+
+| Key | Name | ˵ |
+| --- | --- | --- |
+| `cassandra` | [`CassandraDriverReactiveHealthIndicator`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cassandra/CassandraDriverReactiveHealthIndicator.java) | CassandraݿǷѾ |
+| `couchbase` | [`CouchbaseReactiveHealthIndicator`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/couchbase/CouchbaseReactiveHealthIndicator.java) | CouchbaseȺǷѾ |
+| `elasticsearch` | [`ElasticsearchReactiveHealthIndicator`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/data/elasticsearch/ElasticsearchReactiveHealthIndicator.java) | ElasticsearchȺǷѾ |
+| `mongo` | [`MongoReactiveHealthIndicator`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/data/mongo/MongoReactiveHealthIndicator.java) | MongoݿǷѾ |
+| `neo4j` | [`Neo4jReactiveHealthIndicator`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/neo4j/Neo4jReactiveHealthIndicator.java) | Neo4jݿǷѾ |
+| `redis` | [`RedisReactiveHealthIndicator`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/data/redis/RedisReactiveHealthIndicator.java) | RedisǷѾ |
+
+
+
+| | бҪӦʽָȡָꡣ ⣬κûбȷ `HealthIndicator` ᱻԶװ |
+| --- | --- |
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.health.groups)2.8.5\. Health飨Health Groups
+
+
+
+ʱָ֯ɿڲͬĿĵǺõġ
+
+
+
+
+
+Ҫһָ飬ʹ `management.endpoint.health.group.` ԣָһָIDб `include` `exclude` 磬Ҫһֻݿָ飬Զ¡
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.endpoint.health.group.custom.include=db
+
+```
+
+
+
+
+
+
+
+Ȼͨ `[localhost:8080/actuator/health/custom](http://localhost:8080/actuator/health/custom)`
+
+
+
+
+
+ͬҪһ飬ݿָųڸ֮⣬ָ꣬Զ¡
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.endpoint.health.group.custom.exclude=db
+
+```
+
+
+
+
+
+
+
+Ĭ£̳ϵͳͬ `StatusAggregator` `HttpCodeStatusMapper` á ȻҲÿĻ϶Щ ҪҲԸ `show-details` `roles` ԡ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.endpoint.health.group.custom.show-details=when-authorized
+management.endpoint.health.group.custom.roles=admin
+management.endpoint.health.group.custom.status.order=fatal,up
+management.endpoint.health.group.custom.status.http-mapping.fatal=500
+management.endpoint.health.group.custom.status.http-mapping.out-of-service=500
+
+```
+
+
+
+
+
+
+
+| | ҪעԶ `StatusAggregator` `HttpCodeStatusMapper` Bean飬ʹ `@Qualifier("groupname")` |
+| --- | --- |
+
+
+
+
+
+һҲ/ųһ `CompositeHealthContributor` Ҳֻ/ųһ `CompositeHealthContributor` ij ʹȫɣʾ
+
+
+
+
+
+
+
+```
+management.endpoint.health.group.custom.include="test/primary"
+management.endpoint.health.group.custom.exclude="test/primary/b"
+```
+
+
+
+
+
+
+
+У`custom` 齫Ϊ `primary` `HealthContributor`Ǹ `test` һɲ֡ `primary` һ壬Ϊ `b` `HealthContributor` ų `custom` ֮⡣
+
+
+
+
+
+˿ڻ˿ڵĶ·ṩ KubernetesƻкãЩУڰȫǣΪִ˵ʹһĹ˿Ǻܳġ һĶ˿ڿܵ²ɿĽ飬ΪʹɹӦóҲ һ·ãʾ
+
+
+
+
+
+
+
+```
+management.endpoint.health.group.live.additional-path="server:/healthz"
+```
+
+
+
+
+
+
+
+⽫ʹ `live` ˿ `/healthz` Ͽá ǰǿԵģ `server:`˿ڣ `management:`˿ڣã ·һһ·Ρ
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.health.datasource)2.8.6\. Դ
+
+
+
+`DataSource` ָʾԴ·ԴBeanĽ״ ·ԴĽ״ÿĿԴĽ״ ڽ˵ӦУ·ԴÿĿ궼ͨʹ·ɼġ 㲻ϣָа·Դ뽫 `management.health.db.ignore-routing-data-sources` Ϊ `true`
+
+
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.kubernetes-probes)2.9\. Kubernetes ̽
+
+
+
+KubernetesϵӦóͨ [̽](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes) ṩйڲ״̬Ϣ [Kubernetes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/)kubeletЩ̽벢ԽӦ
+
+
+
+
+
+Ĭ£Spring Boot[Ӧÿ״̬](https://springdoc.cn/spring-boot/features.html#features.spring-application.application-availability) KubernetesУactuator `ApplicationAvailability` ӿռ Liveness Readiness Ϣר[ָ](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.health.auto-configured-health-indicators)ʹЩϢ`LivenessStateHealthIndicator` `ReadinessStateHealthIndicator` Щָʾȫֽ˵㣨`"/actuator/health"` Ҳͨʹ[](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.health.groups)ΪHTTP̽룺`"/actuator/health/liveness"` `"/actuator/health/readiness"`
+
+
+
+
+
+Ȼ¶˵ϢKubernetesʩ
+
+
+
+
+
+
+
+```
+livenessProbe:
+ httpGet:
+ path: "/actuator/health/liveness"
+ port:
+ failureThreshold: ...
+ periodSeconds: ...
+
+readinessProbe:
+ httpGet:
+ path: "/actuator/health/readiness"
+ port:
+ failureThreshold: ...
+ periodSeconds: ...
+```
+
+
+
+
+
+
+
+| | `` ӦñΪִ˵õĶ˿ڡ WebĶ˿ڣҲһĹ˿ڣ `"management.server.port"` Ѿá |
+| --- | --- |
+
+
+
+
+
+ֻеӦó[Kubernetesʱ](https://springdoc.cn/spring-boot/deployment.html#deployment.cloud.kubernetes)ЩŻԶá ͨʹ `management.endpoint.health.probes.enabled` κλǡ
+
+
+
+
+
+| | һӦóʱ䳬õЧڣKubernetes ᵽ `"startupProbe"` ΪһܵĽһ˵ﲻһҪ `"startupProbe"`Ϊ `"readinessProbe"` ֮ǰʧЧζӦó֮ǰյȻӦóҪܳʱԿʹ `"startupProbe"` ȷKubernetesӦóɱ[̽ӦóеΪ](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.kubernetes-probes.lifecycle)IJ֡ |
+| --- | --- |
+
+
+
+
+
+Actuator˵㱻һĹУôЩ˵Ͳʹͬʩ˿ڡӳء £ʹ磬ܽµӣ̽Ҳܳɹ ԭ˿ `liveness` `readiness` Ǹ⡣ ͨʵ֡
+
+
+
+
+
+
+
+```
+management.endpoint.health.probes.add-additional-paths=true
+```
+
+
+
+
+
+
+
+⽫ʹ `liveness` `/livez` ã`readiness` `readyz` ˿ڿá
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.kubernetes-probes.external-state)2.9.1\. Kubernetes̽ⲿ״̬
+
+
+
+ִ liveness readiness ̽Ϊ顣ζе[Ĺ](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.health.groups)Ƕǿõġ磬öĽָꡣ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.endpoint.health.group.readiness.include=readinessState,customCheck
+
+```
+
+
+
+
+
+
+
+Ĭ£Spring BootЩָꡣ
+
+
+
+
+
+liveness ̽벻ӦⲿϵͳĽ顣[ӦóЧ״̬](https://springdoc.cn/spring-boot/features.html#features.spring-application.application-availability.liveness)ƻKubernetes᳢ͨӦóʵ⡣ζţһⲿϵͳݿ⡢Web APIⲿ棩ֹϣKubernetesܻӦóʵϡ
+
+
+
+
+
+ readiness ̽⣬ⲿϵͳѡӦóԱԭSpring Boot״̬̽вκζĽ顣[Ӧóʵreadiness stateunready](https://springdoc.cn/spring-boot/features.html#features.spring-application.application-availability.readiness)KubernetesͲὫ·ɵʵһЩⲿϵͳܲӦʵ£ǿԱ״̬̽СⲿϵͳܲӦóĹؼӦóж·ͻˣ£ǾԲӦñڡҵǣһӦʵⲿϵͳܳжϡ̽УⲿʱӦóᱻֹ߲ͣջи߲εĹϣҲͨڵʹö·
+
+
+
+
+
+| | һӦóʵûã`type=ClusterIP` `NodePort` KubernetesκδӡûHTTPӦ503ȣΪûӡ`type=LoadBalancer` ķܽҲܲӣȡṩߡһȷ [ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) ķҲһȡʵֵķʽӦ?ڷδε connection refusedڸؾڵ£HTTP 503Ǻпܵġ |
+| --- | --- |
+
+
+
+
+
+⣬һӦóʹ Kubernetes [autoscaling](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/)ܻӦóӸƽȡͬķӦȡautoscalerá
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.kubernetes-probes.lifecycle)2.9.2\. Ӧóں̽״̬
+
+
+
+Kubernetes Probesֵ֧һҪӦóڵһԡ `AvailabilityState`Ӧóڴڲ״̬ʵʵ̽루¶״̬֮ ʵʵ̽루¶˸״̬֮кܴ ӦóڵIJͬΣ̽ʹá
+
+
+
+
+
+Spring Boot[رڼ䷢application event](https://springdoc.cn/spring-boot/features.html#features.spring-application.application-events-and-listeners)̽ԼЩ¼¶ `AvailabilityState` Ϣ
+
+
+
+
+
+±ʾ˲ͬε `AvailabilityState` HTTP connector״̬
+
+
+
+
+
+һSpring BootӦóʱ
+
+
+
+
+| | LivenessState | ReadinessState | HTTP server | ע |
+| --- | --- | --- | --- | --- |
+| Starting | `BROKEN` | `REFUSING_TRAFFIC` | δ | Kubernetes "liveness" ̽룬ʱӦó |
+| Started | `CORRECT` | `REFUSING_TRAFFIC` | ܾ | Ӧóıˢ¡Ӧóִûյ |
+| Ready | `CORRECT` | `ACCEPTING_TRAFFIC` | | ѾɡӦóڽ |
+
+
+
+һSpring BootӦóرʱ
+
+
+
+
+| ͣ | Liveness State | Readiness State | HTTP server | ע |
+| --- | --- | --- | --- | --- |
+| Running | `CORRECT` | `ACCEPTING_TRAFFIC` | | Ҫرա |
+| Graceful shutdown | `CORRECT` | `REFUSING_TRAFFIC` | µܾ | ã [ŹػᴦС](https://springdoc.cn/spring-boot/web.html#web.graceful-shutdown) |
+| Shutdown complete | N/A | N/A | ر | ӦóıرգӦóرա |
+
+
+
+| | KubernetesĸϢμ[Kubernetes](https://springdoc.cn/spring-boot/deployment.html#deployment.cloud.kubernetes.container-lifecycle)֡ |
+| --- | --- |
+
+
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.info)2.10\. ӦϢ
+
+
+
+ӦóϢ˴ `ApplicationContext` ж [`InfoContributor`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/info/InfoContributor.java) BeanռĸϢ Spring BootһЩԶõ `InfoContributor` BeanҲԱдԼġ
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.info.auto-configured-info-contributors)2.10.1\. Զõ InfoContributor
+
+
+
+ʵʱSpringԶ `InfoContributor` Bean
+
+
+
+
+| ID | Name | ˵ | ǰ |
+| --- | --- | --- | --- |
+| `build` | [`BuildInfoContributor`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/info/BuildInfoContributor.java) | ¶˹Ϣ | һ `META-INF/build-info.properties` Դ |
+| `env` | [`EnvironmentInfoContributor`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/info/EnvironmentInfoContributor.java) | ¶ `Environment` `info.` ͷκԡ | None. |
+| `git` | [`GitInfoContributor`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/info/GitInfoContributor.java) | ¶gitϢ | һ `git.properties` Դ |
+| `java` | [`JavaInfoContributor`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/info/JavaInfoContributor.java) | ¶JavaʱRuntimeϢ | None. |
+| `os` | [`OsInfoContributor`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/info/OsInfoContributor.java) | ¶ϵͳϢ | None. |
+
+
+
+˹ߣcontributorǷ `management.info..enabled` Կơ ͬcontributorвͬĬֵȡǵȾ¶Ϣʡ
+
+
+
+
+
+ûȾӦñã`env``java` `os` contributor Ĭǽõġ ͨ `management.info..enabled` Ϊ `true` ǡ
+
+
+
+
+
+`build` `git` ϢcontributorĬõġ ͨ `management.info..enabled` Ϊ `false` á ⣬ҪÿһĬõcontributor뽫 `management.info.defaults.enabled` Ϊ `false`
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.info.custom-application-information)2.10.2\. ԶӦϢApplication Information
+
+
+
+ `env` contributor ʱͨ `info.*` Spring `info` ˵¶ݡ `info` keyµ `Environment` ԶԶ¶ 磬 `application.properties` ļá
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+info.app.encoding=UTF-8
+info.app.java.source=17
+info.app.java.target=17
+
+```
+
+
+
+
+
+
+
+| | ӲЩֵ㻹 [ڹʱչϢ](https://springdoc.cn/spring-boot/howto.html#howto.properties-and-configuration.expand-properties)ʹMavenԽǰӸд¡PropertiesYaml```info.app.encoding=@project.build.sourceEncoding@info.app.java.source=@java.version@info.app.java.target=@java.version@``` |
+| --- | --- |
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.info.git-commit-information)2.10.3\. Git Commit Ϣ
+
+
+
+`info` ˵һõĹܹ `git` ԴĿʱ״̬Ϣ һ `GitProperties` beanʹ `info` ˵Щԡ
+
+
+
+
+
+| | classpathĸ `git.properties` ļ`GitProperties` BeanͻᱻԶáϸڼ "[gitϢ](https://springdoc.cn/spring-boot/howto.html#howto.build.generate-git-info)" |
+| --- | --- |
+
+
+
+
+
+Ĭ£˵ᱩ¶ `git.branch``git.commit.id` `git.commit.time` ԣڣ 㲻ЩԳڶ˵ӦУҪ `git.properties` ļųǡ ʾgitϢ `git.properties` ȫݣʹ `management.info.git.mode` ԣʾ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.info.git.mode=full
+
+```
+
+
+
+
+
+
+
+Ҫ `info` ˵ȫgitύϢ `management.info.git.enabled` Ϊ `false`ʾ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.info.git.enabled=false
+
+```
+
+
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.info.build-information)2.10.4\. Ϣ
+
+
+
+ `BuildProperties` Beanǿõģ`info` ˵ҲԷĹϢclasspathе `META-INF/build-info.properties` ļãͻᷢ
+
+
+
+
+
+| | MavenGradleɸļ "[ɹϢ](https://springdoc.cn/spring-boot/howto.html#howto.build.generate-info)" |
+| --- | --- |
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.info.java-information)2.10.5\. JavaϢ
+
+
+
+`info` ˵㷢˹JavaлϢϸڼ [`JavaInfo`](https://docs.spring.io/spring-boot/docs/3.1.0-SNAPSHOT/api/org/springframework/boot/info/JavaInfo.html)
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.info.os-information)2.10.6\. ϵͳOSϢ
+
+
+
+`info` ˵㷢IJϵͳϢϸڼ [`OsInfo`](https://docs.spring.io/spring-boot/docs/3.1.0-SNAPSHOT/api/org/springframework/boot/info/OsInfo.html)`
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.info.writing-custom-info-contributors)2.10.7\. дԶ InfoContributor
+
+
+
+ΪṩԶӦóϢעʵ [`InfoContributor`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/info/InfoContributor.java) ӿڵSpring Bean
+
+
+
+
+
+ӹһֻһֵ `example` Ŀ
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@Component
+public class MyInfoContributor implements InfoContributor {
+
+ @Override
+ public void contribute(Info.Builder builder) {
+ builder.withDetail("example", Collections.singletonMap("key", "value"));
+ }
+
+}
+
+```
+
+
+
+
+
+
+
+ `info` ˵㣬Ӧÿһ¶ĿӦ
+
+
+
+
+
+
+
+```
+{
+ "example": {
+ "key" : "value"
+ }
+}
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## [](https://springdoc.cn/spring-boot/actuator.html#actuator.monitoring)3\. ͨHTTPмغ
+
+
+
+
+
+ڿһWebӦóSpring Boot ActuatorԶõĶ˵㣬ʹͨHTTP ĬϵĹʹö˵ `id` `/actuator` ǰΪURL· 磬`health` `/actuator/health` ʽ
+
+
+
+
+
+| | Actuator ֧ Spring MVCSpring WebFluxJersey JerseySpring MVCãʹSpring MVC |
+| --- | --- |
+
+
+
+
+
+| | Ϊ˻APIĵ [HTML](https://docs.spring.io/spring-boot/docs/3.1.0-SNAPSHOT/actuator-api/htmlsingle) [PDF](https://docs.spring.io/spring-boot/docs/3.1.0-SNAPSHOT/actuator-api/pdf/spring-boot-actuator-web-api.pdf) мصȷJSONӦJacksonһҪ |
+| --- | --- |
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.monitoring.customizing-management-server-context-path)3.1\. ƹ˵·
+
+
+
+ʱΪ˵㶨ǰǺõġ 磬ӦóѾ `/actuator` Ŀġ ʹ `management.endpoints.web.base-path` ı˵ǰʾ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.endpoints.web.base-path=/manage
+
+```
+
+
+
+
+
+
+
+ǰ `application.properties` ӽ˵ `/actuator/{id}` Ϊ `/manage/{id}` 磬`/manage/info`
+
+
+
+
+
+| | ǹ˿ڱΪ[ʹòͬHTTP˿](https://springdoc.cn/spring-boot/actuator.html#actuator.monitoring.customizing-management-server-port)¶˵㣬 `management.endpoints.web.base-path` `server.servlet.context-path` Servlet WebӦã `spring.webflux.base-path` reactive WebӦã `management.server.port` `management.endpoints.web.base-path` `management.server.base-path` ġ |
+| --- | --- |
+
+
+
+
+
+Ѷ˵ӳ䵽ͬ·ʹ `management.endpoints.web.path-mapping` ԡ
+
+
+
+
+
+ӽ `/actuator/health` ӳΪ `/healthcheck`
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.endpoints.web.base-path=/
+management.endpoints.web.path-mapping.health=healthcheck
+
+```
+
+
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.monitoring.customizing-management-server-port)3.2\. ƹ˿
+
+
+
+ڻƵIJ˵ͨʹĬϵHTTP˿¶˵һǵѡ ȻӦóԼУܸϲʹòͬHTTP˿¶˵㡣
+
+
+
+
+
+ `management.server.port` ıHTTP˿ڣʾ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.server.port=8081
+
+```
+
+
+
+
+
+
+
+| | Cloud Foundry ϣĬ£Ӧóڶ˿ 8080 Ͻ HTTP TCP ·ɵ Cloud Foundry ʹԶ˿ڣҪȷӦó·ԽתԶ˿ڡ |
+| --- | --- |
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.monitoring.management-specific-ssl)3.3\. ManagementSSL
+
+
+
+ΪʹԶ˿ʱҲͨʹø `management.server.ssl.*` ùSSL 磬ùͨHTTPṩӦóʹHTTPSʾ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+server.port=8443
+server.ssl.enabled=true
+server.ssl.key-store=classpath:store.jks
+server.ssl.key-password=secret
+management.server.port=8080
+management.server.ssl.enabled=false
+
+```
+
+
+
+
+
+
+
+ߣʹSSLʹòͬԿ洢ʾ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+server.port=8443
+server.ssl.enabled=true
+server.ssl.key-store=classpath:main.jks
+server.ssl.key-password=secret
+management.server.port=8080
+management.server.ssl.enabled=true
+management.server.ssl.key-store=classpath:management.jks
+management.server.ssl.key-password=secret
+
+```
+
+
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.monitoring.customizing-management-server-address)3.4\. Managementַ
+
+
+
+ͨ `management.server.address` ƹ˵Ŀõַ ֻڲάϼֻ `localhost` ӣá
+
+
+
+
+
+| | ֻе˿˿ڲͬʱڲͬĵַϽм |
+| --- | --- |
+
+
+
+
+
+ `application.properties` Զ̹ӡ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.server.port=8081
+management.server.address=127.0.0.1
+
+```
+
+
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.monitoring.disabling-http-endpoints)3.5\. HTTP˵
+
+
+
+㲻ͨHTTP¶˵㣬ѹ˿Ϊ `-1`ʾ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.server.port=-1
+
+```
+
+
+
+
+
+
+
+Ҳͨʹ `management.endpoints.web.exposure.exclude` ʵ֣ʾ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.endpoints.web.exposure.exclude=*
+
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+## [](https://springdoc.cn/spring-boot/actuator.html#actuator.jmx)4\. ͨJMXмغ
+
+
+
+
+
+JavaչJMXṩһĻغӦó Ĭ£ùδá ͨ `spring.jmx.enabled` Ϊ `true` Spring Bootʵ `MBeanServer` ΪIDΪ `mbeanServer` Bean κδSpring JMXעBean`@ManagedResource``@ManagedAttribute` `@ManagedOperation`ᱩ¶
+
+
+
+
+
+ƽ̨ṩһ `MBeanServer` Spring BootʹڱҪʱĬΪVM `MBeanServer` Щʧˣͻᴴһµ `MBeanServer`
+
+
+
+
+
+ϸڼ [`JmxAutoConfiguration`](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jmx/JmxAutoConfiguration.java) ࡣ
+
+
+
+
+
+Ĭ£Spring BootҲ˵ΪJMX MBeans `org.springframework.boot` ¹ ҪȫJMXеĶ˵עᣬԿעԼ `EndpointObjectNameFactory` ʵ֡
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.jmx.custom-mbean-names)4.1\. ԶMBean
+
+
+
+MBeanͨɶ˵ `id` ɡ 磬 `health` ˵㱻¶Ϊ `org.springframework.boot:type=Endpoint,name=Health`
+
+
+
+
+
+ӦóһϵSpring `ApplicationContext`ַܻᷢͻ Ϊ˽⣬Խ `spring.jmx.unique-names` Ϊ `true`MBean־Ψһġ
+
+
+
+
+
+㻹Զ屩¶˵JMX ʾ `application.properties` һӡ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+spring.jmx.unique-names=true
+management.endpoints.jmx.domain=com.example.myapp
+
+```
+
+
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.jmx.disable-jmx-endpoints)4.2\. JMX˵
+
+
+
+㲻ͨJMX¶˵㣬 `management.endpoints.jmx.exposure.exclude` Ϊ `*`ʾ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.endpoints.jmx.exposure.exclude=*
+
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+## [](https://springdoc.cn/spring-boot/actuator.html#actuator.observability)5\. ɹ۲ԣObservability
+
+
+
+
+
+ɹ۲ָⲿ۲һеϵͳڲ״̬֧ɣ־١
+
+
+
+
+
+ڶ٣Spring Bootʹ [Micrometer Observation](https://micrometer.io/docs/observation)ҪԼĹ۲죨⽫¶٣עһ `ObservationRegistry`
+
+
+
+
+
+
+
+```
+@Component
+public class MyCustomObservation {
+
+ private final ObservationRegistry observationRegistry;
+
+ public MyCustomObservation(ObservationRegistry observationRegistry) {
+ this.observationRegistry = observationRegistry;
+ }
+
+ public void doSomething() {
+ Observation.createNotStarted("doSomething", this.observationRegistry)
+ .lowCardinalityKeyValue("locale", "en-US")
+ .highCardinalityKeyValue("userId", "42")
+ .observe(() -> {
+ // Execute business logic here
+ });
+ }
+
+}
+
+```
+
+
+
+
+
+
+
+| | ͿȵıǩӵָУ߿ȵıǩֻӵС |
+| --- | --- |
+
+
+
+
+
+`ObservationPredicate``GlobalObservationConvention` `ObservationHandler` ͵ Bean Զעᵽ `ObservationRegistry` ϡע `ObservationRegistryCustomizer` Beanһע
+
+
+
+
+
+ϸ [Micrometer Observation ĵ](https://micrometer.io/docs/observation)
+
+
+
+
+
+| | JDBCR2DBCĿɹ۲ԣObservabilityʹõĿá JDBC [Datasource Micrometer Ŀ](https://github.com/jdbc-observations/datasource-micrometer) ṩһ Spring Boot StarterڵJDBCʱԶ۲졣 [οĵ](https://jdbc-observations.github.io/datasource-micrometer/docs/current/docs/html/)ĶϢR2DBC [R2DBC۲Spring BootԶ](https://github.com/spring-projects-experimental/r2dbc-micrometer-spring-boot) ΪR2DBCѯô۲졣 |
+| --- | --- |
+
+
+
+
+
+½ڽṩ־ָٵĸϸڡ
+
+
+
+
+
+
+
+
+
+## [](https://springdoc.cn/spring-boot/actuator.html#actuator.loggers)6\. ־¼Logger
+
+
+
+
+
+Spring Boot Actuatorʱ鿴Ӧó־Ĺܡ Բ鿴б־¼ãȷõ־Լ־ܸЧ־ɡ Щ֮һ
+
+
+
+
+
+* `TRACE`
+
+* `DEBUG`
+
+* `INFO`
+
+* `WARN`
+
+* `ERROR`
+
+* `FATAL`
+
+* `OFF`
+
+* `null`
+
+
+
+
+
+`null` ʾûȷá
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.loggers.configure)6.1\. һ Logger
+
+
+
+Ҫһļ¼`POST` һʵ嵽ԴURIʾ
+
+
+
+
+
+
+
+```
+{
+ "configuredLevel": "DEBUG"
+}
+```
+
+
+
+
+
+
+
+| | Ҫ reset ã¼ض𣨲ʹĬãԴһ `null` ֵΪ `configuredLevel` |
+| --- | --- |
+
+
+
+
+
+
+
+
+
+
+
+## [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics)7\. ָ꣨Metrics
+
+
+
+
+
+Spring Boot ActuatorΪ [Micrometer](https://micrometer.io/) ṩԶãMicrometerһ֧ [ڶϵͳ](https://micrometer.io/docs) Ӧóָӿڣ
+
+
+
+
+
+* [AppOptics](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.appoptics)
+
+* [Atlas](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.atlas)
+
+* [Datadog](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.datadog)
+
+* [Dynatrace](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.dynatrace)
+
+* [Elastic](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.elastic)
+
+* [Ganglia](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.ganglia)
+
+* [Graphite](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.graphite)
+
+* [Humio](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.humio)
+
+* [Influx](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.influx)
+
+* [JMX](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.jmx)
+
+* [KairosDB](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.kairos)
+
+* [New Relic](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.newrelic)
+
+* [OpenTelemetry](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.otlp)
+
+* [Prometheus](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.prometheus)
+
+* [SignalFx](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.signalfx)
+
+* [Simple (in-memory)](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.simple)
+
+* [Stackdriver](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.stackdriver)
+
+* [StatsD](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.statsd)
+
+* [Wavefront](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.wavefront)
+
+
+
+
+
+| | Ҫ˽MicrometerĹܣμ [οĵ](https://micrometer.io/docs)ر [](https://micrometer.io/docs/concepts) |
+| --- | --- |
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.getting-started)7.1\.
+
+
+
+Spring BootԶһϵ `MeterRegistry`ΪclasspathϷֵÿֵ֧ʵһע ʱclasspathж `micrometer-registry-{system}` Spring Bootעˡ
+
+
+
+
+
+עйͬص㡣 磬ʹ Micrometer עʵclasspathϣҲԽһضע ӽDatadog
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.datadog.metrics.export.enabled=false
+
+```
+
+
+
+
+
+
+
+ҲԽеעעض˵ʾ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.defaults.metrics.export.enabled=false
+
+```
+
+
+
+
+
+
+
+Spring BootκԶõעӵ `Metrics` ϵȫ־̬עȷҪ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.metrics.use-global-registry=false
+
+```
+
+
+
+
+
+
+
+ע `MeterRegistryCustomizer` Beanһעκαע֮ǰӦͨǩ
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@Configuration(proxyBeanMethods = false)
+public class MyMeterRegistryConfiguration {
+
+ @Bean
+ public MeterRegistryCustomizer metricsCommonTags() {
+ return (registry) -> registry.config().commonTags("region", "us-east-1");
+ }
+
+}
+
+```
+
+
+
+
+
+
+
+ͨķͽӦضעʵ֡
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@Configuration(proxyBeanMethods = false)
+public class MyMeterRegistryConfiguration {
+
+ @Bean
+ public MeterRegistryCustomizer graphiteMetricsNamingConvention() {
+ return (registry) -> registry.config().namingConvention(this::name);
+ }
+
+ private String name(String name, Meter.Type type, String baseUnit) {
+ return ...
+ }
+
+}
+
+```
+
+
+
+
+
+
+
+Spring Boot [ instrumentation](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.supported)ͨûרעơ
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export)7.2\. ֵ֧ļϵͳ
+
+
+
+ڼҪÿֵ֧ļϵͳ
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.appoptics)7.2.1\. AppOptics
+
+
+
+Ĭ£AppOpticsעĻᶨڽָ͵ `[api.appoptics.com/v1/measurements](https://api.appoptics.com/v1/measurements)`Ҫָ굼 SaaS [AppOptics](https://micrometer.io/docs/registry/appOptics)ṩAPIơ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.appoptics.metrics.export.api-token=YOUR_TOKEN
+
+```
+
+
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.atlas)7.2.2\. Atlas
+
+
+
+Ĭ£ָᱻ㱾ػϵ [Atlas](https://micrometer.io/docs/registry/atlas)ṩ [Atlas server](https://github.com/Netflix/atlas) λá
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.atlas.metrics.export.uri=https://atlas.example.com:7101/api/v1/publish
+
+```
+
+
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.datadog)7.2.3\. Datadog
+
+
+
+һDatadogעĻᶨڽָ͵ [datadoghq](https://www.datadoghq.com/) Ҫָ굽 [Datadog](https://micrometer.io/docs/registry/datadog)ṩAPIԿ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.datadog.metrics.export.api-key=YOUR_KEY
+
+```
+
+
+
+
+
+
+
+ṩһӦԿѡôԪݣDZͺͻλҲ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.datadog.metrics.export.api-key=YOUR_API_KEY
+management.datadog.metrics.export.application-key=YOUR_APPLICATION_KEY
+
+```
+
+
+
+
+
+
+
+Ĭ£ָ걻͵Datadog [site](https://docs.datadoghq.com/getting_started/site) `[api.datadoghq.com](https://api.datadoghq.com/)` DatadogĿйվϣҪָͨ꣬ӦURI
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.datadog.metrics.export.uri=https://api.datadoghq.eu
+
+```
+
+
+
+
+
+
+
+㻹ԸıDatadogָʱ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.datadog.metrics.export.step=30s
+
+```
+
+
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.dynatrace)7.2.4\. Dynatrace
+
+
+
+DynatraceṩָȡAPIΪ [Micrometer](https://micrometer.io/docs/registry/dynatrace) ʵֵġ [](https://www.dynatrace.com/support/help/how-to-use-dynatrace/metrics/metric-ingestion/ingestion-methods/micrometer) ҵDynatraceMicrometerָĵ`v1` ռеֻڵ [Timeseries v1 API](https://www.dynatrace.com/support/help/dynatrace-api/environment-api/metric-v1/) ʱ`v2` ռеֻڵ [Metrics v2 API](https://www.dynatrace.com/support/help/dynatrace-api/environment-api/metric-v2/post-ingest-metrics/) ʱע⣬üÿֻܵAPI `v1` `v2` 汾`v2` 汾ѡ `device-id`v1Ҫv2вʹã `v1` ռбãômetric `v1` ˵㡣ͼٶ `v2` 汾
+
+
+
+
+
+##### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.dynatrace.v2-api)v2 API
+
+
+
+ַͨʽʹv2 API
+
+
+
+
+
+###### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.dynatrace.v2-api.auto-config)Զ
+
+
+
+DynatraceԶOneAgentDynatrace Operator for Kubernetesص
+
+
+
+
+
+**OneAgent**OneAgentָԶ [local OneAgent ingest endpoint](https://www.dynatrace.com/support/help/how-to-use-dynatrace/metrics/metric-ingestion/ingestion-methods/local-api/) ȡ˵㽫ָתDynatraceˡ
+
+
+
+
+
+**Dynatrace Kubernetes Operator**ڰװDynatrace OperatorKubernetesʱעԶӲԱȡĶ˵URIAPIơ
+
+
+
+
+
+ĬΪ `io.micrometer:micrometer-registry-dynatrace` ֮⣬Ҫرá
+
+
+
+
+
+
+
+###### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.dynatrace.v2-api.manual-config)ֶ
+
+
+
+ûԶãҪ [Metrics v2 API](https://www.dynatrace.com/support/help/dynatrace-api/environment-api/metric-v2/post-ingest-metrics/) Ķ˵һ API ơAPIƱ Ingest metrics `metrics.ingest`Ȩáǽ齫ƵķΧһȨϡȷ˵URI·磬`/api/v2/metrics/ingest`
+
+
+
+
+
+Metrics API v2ȡ˵URLIJѡͬ
+
+
+
+
+
+* SaaS: `https://{your-environment-id}.live.dynatrace.com/api/v2/metrics/ingest`
+
+* Managed deployments: `https://{your-domain}/e/{your-environment-id}/api/v2/metrics/ingest`
+
+
+
+
+
+ `example` environment id öֵ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.dynatrace.metrics.export.uri=https://example.live.dynatrace.com/api/v2/metrics/ingest
+management.dynatrace.metrics.export.api-token=YOUR_TOKEN
+
+```
+
+
+
+
+
+
+
+ʹDynatrace v2 APIʱʹ¿ѡܣϸڿ [Dynatraceĵ](https://www.dynatrace.com/support/help/how-to-use-dynatrace/metrics/metric-ingestion/ingestion-methods/micrometer#dt-configuration-properties) ҵ
+
+
+
+
+
+* Metric key ǰһǰǰӵеmetric keyС
+
+* DynatraceԪʵOneAgentDynatraceԱУöԪݣ磬̻Podḻָꡣ
+
+* Ĭάȡָӵеļֵԡ Micrometerָ˾ͬıǩǽĬdimension
+
+* ʹDynatrace Summary instrumentijЩ£Micrometer Dynatraceעָ걻ܾ Micrometer 1.9.xУͨDynatraceضժҪ⡣ Ϊ `false` ʹMicrometerص1.9.x֮ǰĬΪ ֻڴMicrometer 1.8.xǨƵ1.9.xʱʱſʹá
+
+
+
+
+
+ԲָURIAPIƣʾ £ʹԶõĶ˵㡣
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.dynatrace.metrics.export.v2.metric-key-prefix=your.key.prefix
+management.dynatrace.metrics.export.v2.enrich-with-dynatrace-metadata=true
+management.dynatrace.metrics.export.v2.default-dimensions.key1=value1
+management.dynatrace.metrics.export.v2.default-dimensions.key2=value2
+management.dynatrace.metrics.export.v2.use-dynatrace-summary-instruments=true
+
+```
+
+
+
+
+
+
+
+
+
+
+
+##### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.dynatrace.v1-api)v1 API (Legacy)
+
+
+
+Dynatrace v1 APIָעͨʹ [Timeseries v1 API](https://www.dynatrace.com/support/help/dynatrace-api/environment-api/metric-v1/) ڽָ͵õURI Ϊеã `device-id` ʱv1Ҫv2вʹãָ걻Timeseries v1˵㡣 Ҫ [Dynatrace](https://micrometer.io/docs/registry/dynatrace) ָ꣬ṩAPIơ豸IDURI
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.dynatrace.metrics.export.uri=https://{your-environment-id}.live.dynatrace.com
+management.dynatrace.metrics.export.api-token=YOUR_TOKEN
+management.dynatrace.metrics.export.v1.device-id=YOUR_DEVICE_ID
+
+```
+
+
+
+
+
+
+
+v1APIָURIָ·Ϊv1Ķ˵·Զӡ
+
+
+
+
+
+
+
+##### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.dynatrace.version-independent-settings)汾ص
+
+
+
+API˵⣬㻹ԸıDynatraceָļʱ䡣 Ĭϵĵʱ `60s` ӽʱΪ30롣
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.dynatrace.metrics.export.step=30s
+
+```
+
+
+
+
+
+
+
+ [Micrometerĵ](https://micrometer.io/docs/registry/dynatrace) [Dynatraceĵ](https://www.dynatrace.com/support/help/how-to-use-dynatrace/metrics/metric-ingestion/ingestion-methods/micrometer) ҵΪMicrometerDynatrace exporterĸϢ
+
+
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.elastic)7.2.5\. Elastic
+
+
+
+Ĭ£ָ걻㱾ػϵ [Elastic](https://micrometer.io/docs/registry/elastic) ͨʹṩҪʹõElasticλá
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.elastic.metrics.export.host=https://elastic.example.com:8086
+
+```
+
+
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.ganglia)7.2.6\. Ganglia
+
+
+
+Ĭ£ָ걻㱾ػϵ [Ganglia](https://micrometer.io/docs/registry/ganglia) ṩ [Ganglia server](http://ganglia.sourceforge.net/) Ͷ˿ڣʾ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.ganglia.metrics.export.host=ganglia.example.com
+management.ganglia.metrics.export.port=9649
+
+```
+
+
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.graphite)7.2.7\. Graphite
+
+
+
+Ĭ£ָᱻ㱾ػϵ [Graphite](https://micrometer.io/docs/registry/graphite) ṩ [Graphite server](https://graphiteapp.org/) Ͷ˿ڣʾ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.graphite.metrics.export.host=graphite.example.com
+management.graphite.metrics.export.port=9004
+
+```
+
+
+
+
+
+
+
+MicrometerṩһĬϵ `HierarchicalNameMapper`dimensional meter IDhttps://micrometer.io/docs/registry/graphite#_hierarchical_name_mapping[ӳ䵽 flat hierarchical name]
+
+
+
+
+
+| | ҪΪ붨 `GraphiteMeterRegistry` ṩԼ `HierarchicalNameMapper` Լ壬ṩһԶõ `GraphiteConfig` `Clock` BeanJavaKotlin```@Configuration(proxyBeanMethods = false)public class MyGraphiteConfiguration { @Bean public GraphiteMeterRegistry graphiteMeterRegistry(GraphiteConfig config, Clock clock) { return new GraphiteMeterRegistry(config, clock, this::toHierarchicalName); } private String toHierarchicalName(Meter.Id id, NamingConvention convention) { return ... }}``` |
+| --- | --- |
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.humio)7.2.8\. Humio
+
+
+
+Ĭ£HumioעĻᶨڽָ͵ [cloud.humio.com](https://cloud.humio.com/) Ҫָ굼SaaS [Humio](https://micrometer.io/docs/registry/humio)ṩAPIơ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.humio.metrics.export.api-token=YOUR_TOKEN
+
+```
+
+
+
+
+
+
+
+㻹ӦһǩȷָԴ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.humio.metrics.export.tags.alpha=a
+management.humio.metrics.export.tags.bravo=b
+
+```
+
+
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.influx)7.2.9\. Influx
+
+
+
+Ĭ£ָᱻڱػϵ [Influx](https://micrometer.io/docs/registry/influx) v1ʵĬáҪָ굽InfluxDB v2 `org``bucket` дָauthentication `token`ͨ·ʽṩҪʹõ [Influx server](https://www.influxdata.com/) λá
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.influx.metrics.export.uri=https://influx.example.com:8086
+
+```
+
+
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.jmx)7.2.10\. JMX
+
+
+
+Micrometerṩ˶ [JMX](https://micrometer.io/docs/registry/jmx) ķֲӳ䣬ҪΪһۺͿֲķʽ鿴صĶ Ĭ£ָ걻 `metrics` JMX ͨ·ʽṩҪʹõ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.jmx.metrics.export.domain=com.example.app.metrics
+
+```
+
+
+
+
+
+
+
+MicrometerṩһĬϵ `HierarchicalNameMapper`dimensional meter ID [ӳ䵽 flat hierarchical name](https://micrometer.io/docs/registry/jmx#_hierarchical_name_mapping)
+
+
+
+
+
+| | ҪΪ붨 `JmxMeterRegistry` ṩԼ `HierarchicalNameMapper` Լ壬ṩһԶõ `JmxConfig` `Clock` BeanJavaKotlin```@Configuration(proxyBeanMethods = false)public class MyJmxConfiguration { @Bean public JmxMeterRegistry jmxMeterRegistry(JmxConfig config, Clock clock) { return new JmxMeterRegistry(config, clock, this::toHierarchicalName); } private String toHierarchicalName(Meter.Id id, NamingConvention convention) { return ... }}``` |
+| --- | --- |
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.kairos)7.2.11\. KairosDB
+
+
+
+Ĭ£ָ걻㱾ػϵ [KairosDB](https://micrometer.io/docs/registry/kairos) ͨ·ʽṩҪʹõ [KairosDB server](https://kairosdb.github.io/) λá
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.kairos.metrics.export.uri=https://kairosdb.example.com:8080/api/v1/datapoints
+
+```
+
+
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.newrelic)7.2.12\. New Relic
+
+
+
+New RelicעĻᶨڽָ͵ [New Relic](https://micrometer.io/docs/registry/new-relic)Ҫָ굽 [New Relic](https://newrelic.com/)ṩAPIԿ˻ID
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.newrelic.metrics.export.api-key=YOUR_KEY
+management.newrelic.metrics.export.account-id=YOUR_ACCOUNT_ID
+
+```
+
+
+
+
+
+
+
+㻹ԸıNew Relicָʱ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.newrelic.metrics.export.step=30s
+
+```
+
+
+
+
+
+
+
+Ĭ£ָͨREST÷ģclasspathJava Agent APIҲʹ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.newrelic.metrics.export.client-provider-type=insights-agent
+
+```
+
+
+
+
+
+
+
+ͨԼ `NewRelicClientProvider` ȫơ
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.otlp)7.2.13\. OpenTelemetry
+
+
+
+Ĭ£ָ걻㱾ػϵ [OpenTelemetry](https://micrometer.io/docs/registry/otlp) ͨ·ʽṩҪʹõ [OpenTelemtry metric endpoint](https://opentelemetry.io/) λá
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.otlp.metrics.export.url=https://otlp.example.com:4318/v1/metrics
+
+```
+
+
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.prometheus)7.2.14\. Prometheus
+
+
+
+[Prometheus](https://micrometer.io/docs/registry/prometheus) ϣscrapeѯӦóʵָꡣSpring Boot `/actuator/prometheus` ṩһactuator˵㣬Աʵĸʽ [Prometheus scrape](https://prometheus.io/)
+
+
+
+
+
+| | Ĭ£ö˵Dzõģ뱻¶ϸμ[¶˵](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.exposing) |
+| --- | --- |
+
+
+
+
+
+ `scrape_config` ӵ `prometheus.yml`
+
+
+
+
+
+
+
+```
+scrape_configs:
+ - job_name: "spring"
+ metrics_path: "/actuator/prometheus"
+ static_configs:
+ - targets: ["HOST:PORT"]
+```
+
+
+
+
+
+
+
+Ҳ֧ [Prometheus Exemplars](https://prometheus.io/docs/prometheus/latest/feature_flags/#exemplars-storage)ҪܣӦһ `SpanContextSupplier` Beanʹ [Micrometer Tracing](https://micrometer.io/docs/tracing)⽫ΪԶã룬ǿԴԼġ鿴 [Prometheus ĵ](https://prometheus.io/docs/prometheus/latest/feature_flags/#exemplars-storage) ΪҪPrometheusȷãֻ֧ʹ [OpenMetrics](https://github.com/OpenObservability/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#exemplars) ʽ
+
+
+
+
+
+ڶݵĻҵܴڵʱ䲻ȡʹ [Prometheus Pushgateway](https://github.com/prometheus/pushgateway) ָ֧֣걩¶PrometheusҪPrometheus Pushgateway֧֣Ŀ
+
+
+
+
+
+
+
+```
+
+ io.prometheus
+ simpleclient_pushgateway
+
+```
+
+
+
+
+
+
+
+Prometheus Pushgatewayclasspathϣ `management.prometheus.metrics.export.pushgateway.enabled` ԱΪ `true` ʱһ `PrometheusPushGatewayManager` beanͱԶˡ Prometheus PushgatewayָĹ
+
+
+
+
+
+ͨʹ `management.prometheus.metrics.export.pushgateway` µ `PrometheusPushGatewayManager` ڸãҲṩԼ `PrometheusPushGatewayManager` bean
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.signalfx)7.2.15\. SignalFx
+
+
+
+SignalFxעĻᶨڽָ͵ [SignalFx](https://micrometer.io/docs/registry/signalFx)Ҫָ굽 [SignalFx](https://www.signalfx.com/)ṩaccess token
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.signalfx.metrics.export.access-token=YOUR_ACCESS_TOKEN
+
+```
+
+
+
+
+
+
+
+ҲԸıSignalFxָʱ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.signalfx.metrics.export.step=30s
+
+```
+
+
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.simple)7.2.16\. Simple
+
+
+
+Micrometerṩһġڴеĺˣûעú˻ԶΪá㿴 [metrics endpoint](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.endpoint) ռЩ
+
+
+
+
+
+һʹκõĺˣڴеĺ˾ͻԶرաҲȷؽ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.simple.metrics.export.enabled=false
+
+```
+
+
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.stackdriver)7.2.17\. Stackdriver
+
+
+
+StackdriverעĻᶨ [Stackdriver](https://cloud.google.com/stackdriver/) ָꡣҪָ굽SaaS [Stackdriver](https://micrometer.io/docs/registry/stackdriver)ṩGoogle Cloud project ID
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.stackdriver.metrics.export.project-id=my-project
+
+```
+
+
+
+
+
+
+
+㻹ԸıStackdriverָʱ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.stackdriver.metrics.export.step=30s
+
+```
+
+
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.statsd)7.2.18\. StatsD
+
+
+
+StatsDעеؽָͨUDPStatsD agentĬ£ָ걻㱾ػϵ [StatsD](https://micrometer.io/docs/registry/statsD) agentͨ·ʽṩStatsD˿ںЭ飬Աʹá
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.statsd.metrics.export.host=statsd.example.com
+management.statsd.metrics.export.port=9125
+management.statsd.metrics.export.protocol=udp
+
+```
+
+
+
+
+
+
+
+㻹ԸıҪʹõStatsD·Э飨ĬΪDatadog
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.statsd.metrics.export.flavor=etsy
+
+```
+
+
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.export.wavefront)7.2.19\. Wavefront
+
+
+
+Wavefrontעڽָ͵ [Wavefront](https://micrometer.io/docs/registry/wavefront)ֱӽָ굼 [Wavefront](https://www.wavefront.com/)ṩAPI token
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.wavefront.api-token=YOUR_API_TOKEN
+
+```
+
+
+
+
+
+
+
+⣬ĻʹWavefront sidecarڲתָݵWavefront API
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.wavefront.uri=proxy://localhost:2878
+
+```
+
+
+
+
+
+
+
+ָ귢Wavefront [Wavefrontĵ](https://docs.wavefront.com/proxies_installing.html) `proxy://HOST:PORT` ʽ
+
+
+
+
+
+ҲԸıWavefrontָʱ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.wavefront.metrics.export.step=30s
+
+```
+
+
+
+
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.supported)7.3\. ֵָ֧ MetricͶMeter
+
+
+
+Spring BootΪָļṩԶעᡣ ڴ£Ĭֵṩ˺ָ꣬Էκֵ֧ļϵͳС
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.supported.jvm)7.3.1\. JVMָ
+
+
+
+Զͨʹú Micrometer JVM JVMָ `jvm.` meter name ·
+
+
+
+
+
+ṩJVMָꡣ
+
+
+
+
+
+* ڴͻϸ
+
+* ռйصͳ
+
+* ߳
+
+* غжص
+
+* JVMİ汾Ϣ
+
+* JIT ʱ
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.supported.system)7.3.2\. ϵͳָ
+
+
+
+ԶͨʹúMicrometerʵϵͳ ϵͳָ `system.``process.` `disk.` meter ·
+
+
+
+
+
+ṩϵͳָꡣ
+
+
+
+
+
+* CPUָ
+
+* ļָ
+
+* ʱָ꣨ӦóѾеʱ;ʱĹ̶
+
+* õĴ̿ռ
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.supported.application-startup)7.3.3\. Ӧóָ
+
+
+
+Զñ¶Ӧóʱָꡣ
+
+
+
+
+
+* `application.started.time`: Ӧóʱ䡣
+
+* `application.ready.time`ӦóΪṩʱ䡣
+
+
+
+
+
+ָӦȫǵġ
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.supported.logger)7.3.4\. ־¼ָ
+
+
+
+ԶLogbackLog4J2¼ ϸ `log4j2.events.` `logback.events.` meter¹
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.supported.tasks)7.3.5\. ִк͵ָ
+
+
+
+Զʹпõ `ThreadPoolTaskExecutor` `ThreadPoolTaskScheduler` BeanֻܱҪײ `ThreadPoolExecutor` á ָexecutorǣexecutorBeanơ
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.supported.spring-mvc)7.3.6\. Spring MVC ָ
+
+
+
+Զܹ Spring MVC Controllerͱʽhandlerж Ĭ£ָ `http.server.requests` Ϊɵġ ͨ `management.observations.http.server.requests.name` Ƹơ
+
+
+
+
+
+ڲĹ۲observationĸϢμ [Spring Framework οĵ](https://docs.spring.io/spring-framework/docs/6.0.5/reference/html/integration.html#integration.observability.http-server.servlet)
+
+
+
+
+
+ҪӵĬϱǩУṩһ̳ `org.springframework.http.server.observation` е `DefaultServerRequestObservationConvention` `@Bean`Ҫ滻Ĭϱǩṩһʵ `ServerRequestObservationConvention` `@Bean`
+
+
+
+
+
+| | ijЩ£Webд쳣ᱻ¼ΪǩӦóѡ벢ͨ[handled exception Ϊ request attribute](https://springdoc.cn/spring-boot/web.html#web.servlet.spring-mvc.error-handling)¼쳣 |
+| --- | --- |
+
+
+
+
+
+Ĭ£ ҪԶṩһʵ `FilterRegistrationBean` `@Bean`
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.supported.spring-webflux)7.3.7\. Spring WebFlux ָ
+
+
+
+ԶܹSpring WebFlux controllerͱʽhandlerж Ĭ£ָ `http.server.requests` Ϊɵġ ͨ `management.observations.http.server.requests.name` Ƹơ
+
+
+
+
+
+ڲĹ۲observationĸϢμ [Spring Framework οĵ](https://docs.spring.io/spring-framework/docs/6.0.5/reference/html/integration.html#integration.observability.http-server.reactive)
+
+
+
+
+
+ҪӵĬϱǩУṩ̳ `org.springframework.http.server.reactive.observation` е `DefaultServerRequestObservationConvention` `@Bean`Ҫ滻Ĭϱǩṩһʵ `ServerRequestObservationConvention` `@Bean`
+
+
+
+
+
+| | ijЩ£ʹд쳣ᱻ¼ΪǩӦóѡ벢ͨ[handled exceptionΪrequest attribute](https://springdoc.cn/spring-boot/web.html#web.reactive.webflux.error-handling)¼쳣 |
+| --- | --- |
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.supported.jersey)7.3.8\. Jersey Server ָ
+
+
+
+ԶʹJersey JAX-RSʵܱ Ĭ£ָ `http.server.requests` Ϊɵġ ͨ `management.observations.http.server.requests.name` ơ
+
+
+
+
+
+Ĭ£Jerseyָ걻ΪϢ
+
+
+
+
+| Tag | ˵ |
+| --- | --- |
+| `exception` | ʱ׳κ쳣ļ |
+| `method` | ķ磬`GET` `POST` |
+| `outcome` | ĽӦ״̬롣 1xx `INFORMATIONAL`2xx `SUCCESS`3xx `REDIRECTION`4xx `CLIENT_ERROR`5xx `SERVER_ERROR` |
+| `status` | ӦHTTP״̬루磬`200` `500` |
+| `uri` | ܵĻڽб滻֮ǰURIģ壨磺`/api/person/{id}` |
+
+
+
+ҪƱǩṩһʵ `JerseyTagsProvider` `@Bean`
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.supported.http-clients)7.3.9\. HTTP Client ָ
+
+
+
+Spring Boot Actuator `RestTemplate` `WebClient` ĹߡΪˣעԶõĹʹʵ
+
+
+
+
+
+* `RestTemplateBuilder` `RestTemplate`
+
+* `WebClient.Builder` `WebClient`
+
+
+
+
+
+ҲֶӦøߵcustomizer `ObservationRestTemplateCustomizer` `ObservationWebClientCustomizer`
+
+
+
+
+
+Ĭ£ָ `http.client.requests` ɵġ
+
+
+
+
+
+ͨ `management.observations.http.client.requests.name` ֡
+
+
+
+
+
+ڲĹ۲observationĸϢμ [Spring Framework οĵ](https://docs.spring.io/spring-framework/docs/6.0.5/reference/html/integration.html#integration.observability.http-client)
+
+
+
+
+
+Ҫʹ `RestTemplate` ʱƱǩṩһʵ `org.springframework.http.client.observation` `ClientRequestObservationConvention` `@Bean`Ҫʹ `WebClient` ʱԶǩṩһʵ `org.springframework.web.reactive.function.client` `ClientRequestObservationConvention` `@Bean`
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.supported.tomcat)7.3.10\. Tomcat ָ
+
+
+
+Զý `MBeanRegistry` ʱŻTomcat Ĭ£`MBeanRegistry` ǽõģͨ `server.tomcat.mbeanregistry.enabled` Ϊ `true`
+
+
+
+
+
+Tomcatָ `tomcat.` meter ·
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.supported.cache)7.3.11\. Cache ָ
+
+
+
+Զÿʱпõ `Cache` ʵм⣬ָ `cache` Ϊǰ
+
+
+
+
+
+DZDZĻָ꼯
+
+
+
+
+
+ҲʹöġԻָꡣ
+
+
+
+
+
+֧»⡣
+
+
+
+
+
+* Cache2k
+
+* Caffeine
+
+* Hazelcast
+
+* κμݵJCacheJSR-107ʵ
+
+* Redis
+
+
+
+
+
+ָɻƺ `CacheManager` ǣ`CacheManager` Beanġ
+
+
+
+
+
+| | ֻʱõĻ汻ע ûڻжĻ棬κʱĻԱ̷ʽĻ棬Ҫȷעᡣ һ `CacheMetricsRegistrar` Beanʹ̸ס |
+| --- | --- |
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.supported.spring-graphql)7.3.12\. Spring GraphQL ָ
+
+
+
+μ [Spring GraphQL οĵ](https://docs.spring.io/spring-graphql/docs/1.1.2/reference/html/)
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.supported.jdbc)7.3.13\. DataSource ָ
+
+
+
+Զʹпõ `DataSource` ָǰΪ `jdbc.connections` ԴĽDZʾеǰġеġĺСDZ
+
+
+
+
+
+ҲɻbeanƼ `DataSource` ǡ
+
+
+
+
+
+| | Ĭ£Spring BootΪֵ֧ԴṩԪݡ ϲԴ֧֣Ӷ `DataSourcePoolMetadataProvider` Bean `DataSourcePoolMetadataProvidersConfiguration` ˽ʵ |
+| --- | --- |
+
+
+
+
+
+⣬Hikariضָ `hikaricp` ǰ¶ ÿָ궼poolǣ `spring.datasource.name` ƣ
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.supported.hibernate)7.3.14\. Hibernate ָ
+
+
+
+ `org.hibernate.orm:hibernate-micrometer` classpathϣͳƹܵHibernate `EntityManagerFactory` ʵᱻһΪ `hibernate` ָ⡣
+
+
+
+
+
+Ҳ `EntityManagerFactory` ǣBeanġ
+
+
+
+
+
+ҪͳƣJPA `hibernate.generate_statistics` Ϊ `true` Զõ `EntityManagerFactory` á
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+spring.jpa.properties[hibernate.generate_statistics]=true
+
+```
+
+
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.supported.spring-data-repository)7.3.15\. Spring Data Repository ָ
+
+
+
+ԶܹSpring Data `Repository` ĵýж Ĭ£ָ `spring.data.repository.invocations` Ϊɡ ͨ `management.metrics.data.repository.metric-name` Զơ
+
+
+
+
+
+`io.micrometer.core.annotation` е `@Timed` ע֧ `Repository` ӿںͷ㲻¼ `Repository` õĶmetricԽ `management.metrics.data.repository.autotime.enabled` Ϊ `false`רʹ `@Timed` ע⡣
+
+
+
+
+
+| | һ `longTask = true` `@Timed` עΪ÷һʱʱҪһ metric nameҿʱtask timerӡ |
+| --- | --- |
+
+
+
+
+
+Ĭ£repositoryصĶΪϢ
+
+
+
+
+| Tag | ˵ |
+| --- | --- |
+| `repository` | Դ `Repository` ļ |
+| `method` | õ `Repository` ơ |
+| `state` | ״̬`SUCCESS`, `ERROR`, `CANCELED`, `RUNNING` |
+| `exception` | ׳κ쳣ļ |
+
+
+
+Ҫ滻ĬϱǩҪṩһʵ `RepositoryTagsProvider` `@Bean`
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.supported.rabbitmq)7.3.16\. RabbitMQ ָ
+
+
+
+Զʹпõ RabbitMQ ӹָΪ `rabbitmq`
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.supported.spring-integration)7.3.17\. Spring Integration ָ
+
+
+
+ֻҪ `MeterRegistry` beanSpring IntegrationͻԶṩ [Micrometer support](https://docs.spring.io/spring-integration/docs/6.1.0-M1/reference/html/system-management.html#micrometer-integration) `spring.integration.` meter ·
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.supported.kafka)7.3.18\. Kafka ָ
+
+
+
+ԶΪԶõ߹߹ֱעһ `MicrometerConsumerListener` `MicrometerProducerListener` Ϊ `StreamsBuilderFactoryBean` עһ `KafkaStreamsMicrometerListener` ϸڣSpring Kafkaĵе [Micrometer Native Metrics](https://docs.spring.io/spring-kafka/docs/3.0.3/reference/html/#micrometer-native) ֡
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.supported.mongodb)7.3.19\. MongoDB ָ
+
+
+
+ڼҪMongoDBĿö
+
+
+
+
+
+##### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.supported.mongodb.command)MongoDBָ
+
+
+
+Զý `MongoMetricsCommandListener` Զõ `MongoClient` עᡣ
+
+
+
+
+
+һΪ `mongodb.driver.commands` timerָ걻ײMongoDB driverÿ Ĭ£ÿָ궼ΪϢ
+
+
+
+
+| Tag | ˵ |
+| --- | --- |
+| `command` | ơ |
+| `cluster.id` | ļȺıʶ |
+| `server.address` | ķĵַ |
+| `status` | Ľ`SUCCESS` `FAILED |
+
+
+
+Ϊ滻ĬϵĶǩһ `MongoCommandTagsProvider` beanʾ
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@Configuration(proxyBeanMethods = false)
+public class MyCommandTagsProviderConfiguration {
+
+ @Bean
+ public MongoCommandTagsProvider customCommandTagsProvider() {
+ return new CustomCommandTagsProvider();
+ }
+
+}
+
+```
+
+
+
+
+
+
+
+ҪԶõԡ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.metrics.mongo.command.enabled=false
+
+```
+
+
+
+
+
+
+
+
+
+##### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.supported.mongodb.connection-pool)MongoDB ӳָ
+
+
+
+Զý `MongoMetricsConnectionPoolListener` Զõ `MongoClient` עᡣ
+
+
+
+
+
+ΪӳشIJָꡣ
+
+
+
+
+
+* `mongodb.driver.pool.size` ӳصĵǰСкʹõijԱ
+
+* `mongodb.driver.pool.checkedout` 浱ǰʹе
+
+* `mongodb.driver.pool.waitqueuesize` ӵĵȴеĵǰС
+
+
+
+
+
+Ĭ£ÿָ궼ΪϢ
+
+
+
+
+| Tag | ˵ |
+| --- | --- |
+| `cluster.id` | ӳӦļȺıʶ |
+| `server.address` | ӳӦķĵַ |
+
+
+
+ҪȡĬϵĶǩ붨һ `MongoConnectionPoolTagsProvider` bean
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@Configuration(proxyBeanMethods = false)
+public class MyConnectionPoolTagsProviderConfiguration {
+
+ @Bean
+ public MongoConnectionPoolTagsProvider customConnectionPoolTagsProvider() {
+ return new CustomConnectionPoolTagsProvider();
+ }
+
+}
+
+```
+
+
+
+
+
+
+
+ҪԶõӳضԡ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.metrics.mongo.connectionpool.enabled=false
+
+```
+
+
+
+
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.supported.jetty)7.3.20\. Jetty ָ
+
+
+
+ԶͨʹMicrometer `JettyServerThreadPoolMetrics` ΪJetty `ThreadPool` ָꡣ Jetty `Connector` ʵָͨʹMicrometer `JettyConnectionMetrics` `server.ssl.enabled` Ϊ `true` ʱMicrometer `JettySslHandshakeMetrics`
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.supported.timed-annotation)7.3.21\. @Timed ע֧
+
+
+
+ҪSpring Bootֱֵ֧ĵطʹ `@Timed`ο [Micrometer ĵ](https://micrometer.io/docs/concepts#_the_timed_annotation)
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.supported.redis)7.3.22\. Redis ָ
+
+
+
+ԶΪԶõ `LettuceConnectionFactory` עһ `MicrometerCommandLatencyRecorder` ϸڣLettuceĵ [Micrometer Metrics](https://lettuce.io/core/6.2.3.RELEASE/reference/index.html#command.latency.metrics.micrometer)
+
+
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.registering-custom)7.4\. עԶָ
+
+
+
+ҪעԶ뽫 `MeterRegistry` עС
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@Component
+public class MyBean {
+
+ private final Dictionary dictionary;
+
+ public MyBean(MeterRegistry registry) {
+ this.dictionary = Dictionary.load();
+ registry.gauge("dictionary.size", Tags.empty(), this.dictionary.getWords().size());
+ }
+
+}
+
+```
+
+
+
+
+
+
+
+ĶBeanǽʹ `MeterBinder` עǡ
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+public class MyMeterBinderConfiguration {
+
+ @Bean
+ public MeterBinder queueSize(Queue queue) {
+ return (registry) -> Gauge.builder("queueSize", queue::size).register(registry);
+ }
+
+}
+
+```
+
+
+
+
+
+
+
+ʹ `MeterBinder` ȷȷϵڼֵʱBeanǿõġ 㷢Ӧóظһָ꣬ô `MeterBinder` ʵҲá
+
+
+
+
+
+| | Ĭ£ `MeterBinder` Beanָ궼ԶSpring `MeterRegistry` |
+| --- | --- |
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.customizing)7.5\. Ƹָ
+
+
+
+Ҫض `Meter` ʵԶ壬ʹ `io.micrometer.core.instrument.config.MeterFilter` ӿڡ
+
+
+
+
+
+磬 `com.example` ͷDZID `mytag.region` ǩΪ `mytag.area`¹
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@Configuration(proxyBeanMethods = false)
+public class MyMetricsFilterConfiguration {
+
+ @Bean
+ public MeterFilter renameRegionTagMeterFilter() {
+ return MeterFilter.renameTag("com.example", "mytag.region", "mytag.area");
+ }
+
+}
+
+```
+
+
+
+
+
+
+
+| | Ĭ£е `MeterFilter` BeanԶSpring `MeterRegistry` ȷʹSpring `MeterRegistry` עָ꣬ʹ `Metrics` κξ̬ ЩʹõDzSpringȫע |
+| --- | --- |
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.customizing.common-tags)7.5.1\. ǩTag
+
+
+
+ͨñǩһڶлά꣬ʵջȡ ñǩDZԽãʾ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.metrics.tags.region=us-east-1
+management.metrics.tags.stack=prod
+
+```
+
+
+
+
+
+
+
+ǰΪֵΪ `us-east-1` `prod` DZ `region` `stack` ǩ
+
+
+
+
+
+| | ʹGraphiteͨǩ˳ǺҪġ ʹַܱ֤ǩ˳GraphiteûһԶ `MeterFilter` 档 |
+| --- | --- |
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.customizing.per-meter-properties)7.5.2\. Per-meter Properties
+
+
+
+ `MeterFilter` Bean㻹ʹÿĻӦһԶ幦ܡ ʹSpring Boot `PropertiesMeterFilter`ÿĶƱӦԸƿͷκαID ӹ˵κID `example.remote` ͷDZ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.metrics.enable.example.remote=false
+
+```
+
+
+
+
+
+
+
+per-meterĶơ
+
+
+
+Table 1\. Per-meter customizations
+| Property | ˵ |
+| --- | --- |
+| `management.metrics.enable` | ǷܾضIDMeter ܵMeter `MeterRegistry` й˵ |
+| `management.metrics.distribution.percentiles-histogram` | Ƿʺϼɾۼάȣİٷλֱֵͼ |
+| `management.metrics.distribution.minimum-expected-value`, `management.metrics.distribution.maximum-expected-value` | ͨǯԤֵķΧٵֱͼͰ |
+| `management.metrics.distribution.percentiles` | Ӧóмİٷλֵ |
+| `management.metrics.distribution.expiry`, `management.metrics.distribution.buffer-length` | ͨڻλлǸȨأλڿõĹںתΪ õĻȡ |
+| `management.metrics.distribution.slo` | һۻֱͼеͰķˮƽĿ궨塣 |
+
+
+
+ `percentiles-histogram` ٷ-ֱͼ`percentiles`ٷ `slo` ĸĸϸڣμMicrometerĵе [Histograms and percentiles ֱͼͰٷ](https://micrometer.io/docs/concepts#_histograms_and_percentiles)
+
+
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.endpoint)7.6\. ָ˵
+
+
+
+Spring Bootṩһ `metrics` ˵㣬ԵʹӦóռָꡣö˵ĬDzõģ빫ϸμ [¶˵](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints.exposing)
+
+
+
+
+
+ `/actuator/metrics` ʾһõDZб ͨṩΪѡ鿴ijضDZϢ磬`/actuator/metrics/jvm.memory.max`
+
+
+
+
+
+| | ʹõӦʹõһ£ļϵͳо淶֡ 仰˵ `jvm.memory.max` PrometheusʾΪ `jvm_memory_max`ΪȻӦʹ `jvm.memory.max` Ϊѡ `metrics` ˵мDZ |
+| --- | --- |
+
+
+
+
+
+ҲURLĩβ `tag=KEY:VALUE` ѯԶDZά??磬`/actuator/metrics/jvm.memory.max?tag=area:nonheap`
+
+
+
+
+
+| | IJֵDZƥDZκӦõıǩͳ _ܺ_ ǰУص `Value` ͳǶѵ Code CacheCompressed Class Space Metaspace ڴ桰㼣֮͡ ֻ Metaspace ߴ磬һ `tag=id:Metaspace` -- `/actuator/metrics/jvm.memory.max?tag=area:nonheap&tag=id:Metaspace` |
+| --- | --- |
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.metrics.micrometer-observation)7.7\. Micrometer Observation
+
+
+
+һ `DefaultMeterObservationHandler` Զע `ObservationRegistry` ϣΪÿɵĹ۲죨completed observationmetric
+
+
+
+
+
+
+
+
+
+
+
+## [](https://springdoc.cn/spring-boot/actuator.html#actuator.micrometer-tracing)8\. ٣Tracing
+
+
+
+
+
+Spring Boot Actuator Ϊ Micrometer Tracing ṩԹԶã [Micrometer Tracing](https://micrometer.io/docs/tracing) еtracerһӿڣfacade
+
+
+
+
+
+| | Ҫ˽ Micrometer Tracing ܵϢ [οĵ](https://micrometer.io/docs/tracing) |
+| --- | --- |
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.micrometer-tracing.tracers)8.1\. ֵ֧
+
+
+
+Spring BootΪṩԶá
+
+
+
+
+
+* ʹ [Zipkin](https://zipkin.io/) [Wavefront](https://docs.wavefront.com/) [OpenTelemetry](https://opentelemetry.io/)
+
+* ʹ [Zipkin](https://zipkin.io/) [Wavefront](https://docs.wavefront.com/) [OpenZipkin Brave](https://github.com/openzipkin/brave)
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.micrometer-tracing.getting-started)8.2\.
+
+
+
+ҪһʼٵʾӦóǵĿĶԣ[getting-started.html](https://springdoc.cn/spring-boot/getting-started.html#getting-started.first-application) 漰ļ Hello World! web㹻ˡǽʹ `OpenTelemetry` `Zipkin` Ϊٺˡ
+
+
+
+
+
+عһ£ǵҪӦô뿴ġ
+
+
+
+
+
+
+
+```
+@RestController
+@SpringBootApplication
+public class MyApplication {
+
+ private static final Log logger = LogFactory.getLog(MyApplication.class);
+
+ @RequestMapping("/")
+ String home() {
+ logger.info("home() has been called");
+ return "Hello World!";
+ }
+
+ public static void main(String[] args) {
+ SpringApplication.run(MyApplication.class, args);
+ }
+
+}
+
+```
+
+
+
+
+
+
+
+| | `home()` Уһӵlogger䣬ںҪ |
+| --- | --- |
+
+
+
+
+
+ڣDZ
+
+
+
+
+
+* `org.springframework.boot:spring-boot-starter-actuator`
+
+* `io.micrometer:micrometer-tracing-bridge-otel` - Micrometer Observation API OpenTelemetry ıҪ
+
+* `io.opentelemetry:opentelemetry-exporter-zipkin` - Zipkin [traces](https://micrometer.io/docs/tracing#_glossary) Ҫġ
+
+
+
+
+
+µ application properties:
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.tracing.sampling.probability=1.0
+
+```
+
+
+
+
+
+
+
+Ĭ£Spring Bootֻ10%вԷֹٺ˲ظԽлΪ100%ÿᱻ͵ٺˡ
+
+
+
+
+
+ΪռͿӻ٣ҪһиٵĺˡʹZipkinΪǵĸٺˡ [Zipkinָ](https://zipkin.io/pages/quickstart) ṩڱZipkin˵
+
+
+
+
+
+ZipkinкӦó
+
+
+
+
+
+web `[localhost:8080](http://localhost:8080/)`Ӧÿ
+
+
+
+
+
+
+
+ Hello World!
+
+
+
+
+
+
+
+ĻѾΪHTTPһ observationŽӵ `OpenTelemetry`Zipkinһµĸ٣trace
+
+
+
+
+
+ڣ `[localhost:9411](http://localhost:9411/)` Zipkinû棬 "Run Query" ťгռĸϢӦÿһ١ "Show" ť鿴ٵϸڡ
+
+
+
+
+
+| | ͨ `logging.pattern.level` Ϊ `%5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}]`־аǰĸ٣trace span id |
+| --- | --- |
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.micrometer-tracing.tracer-implementations)8.3\. Tracerʵ
+
+
+
+Micrometer Tracerֶ֧ʾʵ֣Spring Bootжϡ
+
+
+
+
+
+ʵֶҪ `org.springframework.boot:spring-boot-starter-actuator`
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.micrometer-tracing.tracer-implementations.otel-zipkin)8.3.1\. ʹ Zipkin OpenTelemetry
+
+
+
+* `io.micrometer:micrometer-tracing-bridge-otel` - Micrometer Observation API OpenTelemetry ıҪ
+
+* `io.opentelemetry:opentelemetry-exporter-zipkin` - ZipkintraceҪġ
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.micrometer-tracing.tracer-implementations.otel-wavefront)8.3.2\. ʹ Wavefront OpenTelemetry
+
+
+
+* `io.micrometer:micrometer-tracing-bridge-otel` - Micrometer Observation API OpenTelemetry ıҪ
+
+* `io.micrometer:micrometer-tracing-reporter-wavefront` - WavefronttraceҪġ
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.micrometer-tracing.tracer-implementations.brave-zipkin)8.3.3\. ʹ Zipkin OpenZipkin Brave
+
+
+
+* `io.micrometer:micrometer-tracing-bridge-brave` - Micrometer Observation API Brave ıҪ
+
+* `io.zipkin.reporter2:zipkin-reporter-brave` - Zipkin trace Ҫġ
+
+
+
+
+
+| | ĿûʹSpring MVCSpring WebFluxҲҪʹ `io.zipkin.reporter2:zipkin-sender-urlconnection` |
+| --- | --- |
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/actuator.html#actuator.micrometer-tracing.tracer-implementations.brave-wavefront)8.3.4\. ʹWavefrontOpenZipkin Brave
+
+
+
+* `io.micrometer:micrometer-tracing-bridge-brave` - ӲMicrometer Observation APIBraveıҪ
+
+* `io.micrometer:micrometer-tracing-reporter-wavefront` - WavefronttraceҪġ
+
+
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.micrometer-tracing.creating-spans)8.4\. Զȣspan
+
+
+
+ͨһ observation ԼspanΪˣ `ObservationRegistry` ע뵽С
+
+
+
+
+
+
+
+```
+@Component
+class CustomObservation {
+
+ private final ObservationRegistry observationRegistry;
+
+ CustomObservation(ObservationRegistry observationRegistry) {
+ this.observationRegistry = observationRegistry;
+ }
+
+ void someOperation() {
+ Observation observation = Observation.createNotStarted("some-operation", this.observationRegistry);
+ observation.lowCardinalityKeyValue("some-tag", "some-value");
+ observation.observe(() -> {
+ // Business logic ...
+ });
+ }
+
+}
+
+```
+
+
+
+
+
+
+
+⽫һΪ "some-operation" observationǩΪǩΪ "some-tag=some-value"
+
+
+
+
+
+| | ڲmetric´һspanҪʹ Micrometer [ͼTracer API](https://micrometer.io/docs/tracing#_using_micrometer_tracing_directly) |
+| --- | --- |
+
+
+
+
+
+
+
+
+
+
+
+## [](https://springdoc.cn/spring-boot/actuator.html#actuator.auditing)9\.
+
+
+
+
+
+һSpring SecurityãSpring Boot ActuatorһƿܣԷ¼ĬΪ authentication success, failure access denied 쳣 һܶڱʵʩ֤ʧܵԷdzá
+
+
+
+
+
+ͨӦóṩһ `AuditEventRepository` ͵beanơ Ϊ˷㣬Spring Bootṩһ `InMemoryAuditEventRepository` `InMemoryAuditEventRepository` Ĺޣǽֻڿʹ 뿼ǴԼ `AuditEventRepository` ʵ֡
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.auditing.custom)9.1\.
+
+
+
+Ϊ˶Ʒİȫ¼ṩԼ `AbstractAuthenticationAuditListener` `AbstractAuthorizationAuditListener` ʵ֡
+
+
+
+
+
+ҲΪԼҵ¼ʹƷ Ҫһ㣬Ҫô `AuditEventRepository` beanעԼֱʹҪôSpring `ApplicationEventPublisher` `AuditApplicationEvent`ͨʵ `ApplicationEventPublisherAware`
+
+
+
+
+
+
+
+
+
+
+
+## [](https://springdoc.cn/spring-boot/actuator.html#actuator.http-exchanges)10\. ¼ HTTP Exchange
+
+
+
+
+
+ͨӦóṩһ `HttpExchangeRepository` ͵ bean HTTP exchange ļ¼Ϊ˷Spring Boot ṩ `InMemoryHttpExchangeRepository`Ĭ£洢100 request/response exchangeٽtracing solutionsȣ`InMemoryHttpExchangeRepository` ģǽֻڿʹǽʹһĸٻ۲ `Zipkin` `OpenTelemetry`⣬ҲԴԼ `HttpExchangeRepository`
+
+
+
+
+
+ʹ `httpexchanges` ˵ȡ洢 `HttpExchangeRepository` е request/response exchange Ϣ
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.http-exchanges.custom)10.1\. Զ HTTP Exchange ¼
+
+
+
+ҪԶÿ¼ exchange Ŀʹ `management.httpexchanges.recording.include` ԡ
+
+
+
+
+
+Ҫȫֹ±룬뽫 `management.httpexchanges.recording.enabled` Ϊ `false`
+
+
+
+
+
+
+
+
+
+
+
+## [](https://springdoc.cn/spring-boot/actuator.html#actuator.process-monitoring)11\. ̼
+
+
+
+
+
+ `spring-boot` ģУҵļ࣬Щļڽ̼ͨá
+
+
+
+
+
+* `ApplicationPidFileWriter` һӦóPIDļĬ£ӦóĿ¼£ļΪ `application.pid`
+
+* `WebServerPortFileWriter` һļеWebĶ˿ڣĬ£ӦóĿ¼£ļΪ `application.port`
+
+
+
+
+
+Ĭ£Щдûбǡ
+
+
+
+
+
+* [ͨչ](https://springdoc.cn/spring-boot/actuator.html#actuator.process-monitoring.configuration)
+
+* [Ա̷ʽʵֽ̼](https://springdoc.cn/spring-boot/actuator.html#actuator.process-monitoring.programmatically)
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.process-monitoring.configuration)11.1\. չ
+
+
+
+ `META-INF/spring.factories` ļУԼдPIDļlistenerһ߶
+
+
+
+
+
+
+
+ org.springframework.context.ApplicationListener=\
+org.springframework.boot.context.ApplicationPidFileWriter,\
+org.springframework.boot.web.context.WebServerPortFileWriter
+
+
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.process-monitoring.programmatically)11.2\. Ա̷ʽʵֽ̼
+
+
+
+Ҳͨ `SpringApplication.addListeners(?)` ʵ `Writer` һ `Writer` 캯Զļ·
+
+
+
+
+
+
+
+
+
+
+
+## [](https://springdoc.cn/spring-boot/actuator.html#actuator.cloud-foundry)12\. Cloud Foundry ֧
+
+
+
+
+
+Spring Boot actuatorģ֧֣ݵ Cloud Foundry ʵʱֽ֧ `/cloudfoundryapplication` ·Ϊ `@Endpoint` Beanṩһȫ·ߡ
+
+
+
+
+
+չ֧ʹ Cloud Foundry UI鿴ѲӦó Web Ӧóõ Spring Boot ִϢǿ 磬Ӧó״̬ҳĽϢǵ͵ running stopped ״̬
+
+
+
+
+
+| | ͨûֱӷ `/cloudfoundryapplication` · Ҫʹøö˵㣬дһЧ UAA ơ |
+| --- | --- |
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.cloud-foundry.disable)12.1\. չ Cloud Foundry Actuator ֧
+
+
+
+ȫ `/cloudfoundryapplication` ˵㣬 `application.properties` ļá
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.cloudfoundry.enabled=false
+
+```
+
+
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.cloud-foundry.ssl)12.2\. Cloud Foundryǩ֤
+
+
+
+Ĭ£`/cloudfoundryapplication` ˵İȫ֤Ը Cloud Foundry SSL á Cloud Foundry UAA Cloud Controller ʹǩ֤飬Ҫԡ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+management.cloudfoundry.skip-ssl-validation=true
+
+```
+
+
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/actuator.html#actuator.cloud-foundry.custom-context-path)12.3\. Զ Context Path
+
+
+
+ context-path Ϊ `/` κݣ Cloud Foundry ˵Ӧóĸá 磬 `server.servlet.context-path=/app` Cloud Foundry ˵ `/app/cloudfoundryapplication/*` á
+
+
+
+
+
+ϣ Cloud Foundry ˵ʼ `/cloudfoundryapplication/*` ã۷·ΣҪӦóȷá ʹõ Web ͬͬ Tomcatá
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@Configuration(proxyBeanMethods = false)
+public class MyCloudFoundryConfiguration {
+
+ @Bean
+ public TomcatServletWebServerFactory servletWebServerFactory() {
+ return new TomcatServletWebServerFactory() {
+
+ @Override
+ protected void prepareContext(Host host, ServletContextInitializer[] initializers) {
+ super.prepareContext(host, initializers);
+ StandardContext child = new StandardContext();
+ child.addLifecycleListener(new Tomcat.FixContextListener());
+ child.setPath("/cloudfoundryapplication");
+ ServletContainerInitializer initializer = getServletContextInitializer(getContextPath());
+ child.addServletContainerInitializer(initializer, Collections.emptySet());
+ child.setCrossContext(true);
+ host.addChild(child);
+ }
+
+ };
+ }
+
+ private ServletContainerInitializer getServletContextInitializer(String contextPath) {
+ return (classes, context) -> {
+ Servlet servlet = new GenericServlet() {
+
+ @Override
+ public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
+ ServletContext context = req.getServletContext().getContext(contextPath);
+ context.getRequestDispatcher("/cloudfoundryapplication").forward(req, res);
+ }
+
+ };
+ context.addServlet("cloudfoundry", servlet).addMapping("/*");
+ };
+ }
+
+}
+
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+## [](https://springdoc.cn/spring-boot/actuator.html#actuator.whats-next)13\. ʲô
+
+
+
+
+
+һ [Graphite](https://graphiteapp.org/) ͼιߡ
+
+
+
+
+
+ԼĶ [ѡ](https://springdoc.cn/spring-boot/deployment.html#deployment) ǰȥ˽йSpring Boot [߲](https://springdoc.cn/spring-boot/build-tool-plugins.html#build-tool-plugins)һЩϢ
+
+
+
+
+
+
+
diff --git "a/docs/spring/SpringBoot/SpringBoot\347\232\204Starter\346\234\272\345\210\266.md" "b/docs/spring/SpringBoot/SpringBoot\347\232\204Starter\346\234\272\345\210\266.md"
new file mode 100644
index 0000000..0318193
--- /dev/null
+++ "b/docs/spring/SpringBoot/SpringBoot\347\232\204Starter\346\234\272\345\210\266.md"
@@ -0,0 +1,262 @@
+starterSpringBootеһ·ЧĽĿ̵ĸӳ̶ȣڼŷdzõЧתһƬ£ϸspring boot staterʲôʲô
+
+Spring Boot StarterSpringBootбһָstackoverflowѾ˸starterʲô뿴Ļش[](https://stackoverflow.com/a/28273660)https://stackoverflow.com/questions/28273543/what-are-spring-boot-starter-jars/28273660#28273660
+
+
+
+˼˵starterһֶsynthesizeϳɣʲô˼أҿԾٸ˵
+
+### ? ͳ
+
+ûstarter֮ǰҪSpringʹjpaҿҪ²
+
+1. MavenʹõݿJDBCjar
+2. jpa
+3. xxx.xmlһЩϢ
+4. ĵֱ
+
+Ҫעǣ**_ÿ½һҪõjpaĿʱҪظһ_**ҲڵһԼĿʱGoogleԼһ˰ʱ˸ֵ֮jpaˡЩо˻OneNoteνĿĹ̸¼IJԼҪõļݣһٴjpaĿʱͲҪٴȥGoogleˣֻҪűʼٰ֮еļcopy&pasteͿˡ
+
+IJҲ㲻Уʵûstarter֮ǰôɵģм⣺
+
+1. ̱ȽϷһӳĿ
+2. ͣcopy&paste[Dont repeat yourself](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)
+3. ڵһõʱ߱ȽСףҪѵʱ
+
+### ʹSpring Boot StarterЧ
+
+starterҪĿľΪ˽Щ⡣
+
+starterstarterõ˿Լȥ鷳ҪעDzͬstarterΪ˽ͬڲʵֿܻкܴIJ죬jpastarterRedisstarterʵ־ͲһΪstarterısynthesizeһijҲеDockerΪǶһװIJ֪DockerΪ˽ʲôģҲDockerstarterһȡ
+
+starterʵ֣Ȼͬstarterʵв죬ǻ϶ʹõͬݣConfigurationPropertiesAutoConfigurationΪSpring BootšԼáһʹConfigurationPropertiesǵãЩöһĬֵûдԭʼõ£ĬֵͻЧںܶǷdzõġ֮⣬starterConfigurationPropertiesʹеԱۼһļУһresourcesĿ¼µapplication.propertiesǾSpringĿXML
+
+starter
+
+
+
+starterjarԼֶõʱjarûʲôͬǿΪstarterʵǰһЩòԼѼû˰ûȥ˷ĹڡԼá£ConfigurationPropertiesûνòΪ?`application.properties`?ļĴڣʹҪԶãеҲֻҪһļнУʹdz㡣
+
+˽starterʵǰûõIJ֮Ҫstarterͱstarter֮䲢ǾϵǸϵǿԸһһstarterûʹʱӵļ㡣ǿԸһеһstarterñʹʱӵļ㣬ʵSpring BootŶѾдֵеǵstarter[](https://github.com/spring-projects/spring-boot/tree/v1.5.7.RELEASE/spring-boot-starters)鿴Щstarterб
+
+springboot ô˾ȻûԶstarter붼Խһ¡
+
+
+
+# SpringBoot starter
+
+SpringBootеstarterһַdzҪĻƣܹǰӵãͳһɽstarterӦֻҪmavenstarterSpringBootԶɨ赽ҪصϢӦĬástarterǰ˸ĴҪøϢšSpringBootԶͨclasspath·µҪBeanעIOCSpringBootṩճҵӦзֳspring-boot-starterģ顣Щģ鶼ѭԼĬãǵЩãѭԼá
+
+# Զstarter
+
+ճʱһЩҵ֮Ĺܻģ飬ĿãһĿҲҪãÿζ¼ɵĻͻ鷳ʱֻҪЩܻģװһstarterĻʹõʱȥͺܷˡ
+
+## Զstarter
+
+ʵԶstarterܼҪ5
+
+1. ½ģ飬淶 springbootԴstarter淶Ϊspring-boot-starter-xxx Զstarter淶Ϊxxx-spring-boot-starter
+
+ xxx-spring-boot-autoconfigureԶúĴ
+ xxx-spring-boot-starter
+ҪԶô뿪ԽϵһģСֻspringbootٷ齫ģֿ
+2\. spring-boot-autoconfigure
+3\. ԶXXXProperties : ԸҪҪļеġ
+4\. ԶXXXAutoConfigurationࣺҪԶʱһЩͬʱҲҪXXXProperties Ч
+5\. Զspring.factoriesļresources/META-INFһspring.factoriesļspring-configuration-metadata.jsonspring-configuration-metadata.jsonļдļʱʾҪɲҪеĻʾѺáspring.factoriesڵԶ࣬Ҫ
+
+## ʵ
+
+Ϊ˷ֻһģˣ
+
+1. һģ飬Ϊspring-boot-starter-my-starterӦpomļ
+
+```
+ com.example
+ spring-boot-starter-my-starter
+ 1.0
+ my-starter
+ƴ
+```
+
+1. spring-boot-autoconfigure ʹõspring-boot-autoconfigure汾2.6.2
+
+```
+
+
+ org.springframework.boot
+ spring-boot-autoconfigure
+ 2.6.2
+
+
+ƴ
+```
+
+1. ԶXXXProperties
+
+```
+@ConfigurationProperties(prefix = "com.arron")
+public class MyStarterProperties {
+
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
+ƴ
+```
+
+ٴһMyStarterConfigڶȡMyStarterProperties
+
+```
+public class MyStarterConfig {
+
+ private MyStarterProperties myStarterProperties;
+
+ private String name;
+
+ public MyStarterConfig(MyStarterProperties myStarterProperties) {
+ this.myStarterProperties = myStarterProperties;
+ }
+
+ public String getName() {
+ return myStarterProperties.getName();
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
+ƴ
+```
+
+1. ԶXXXAutoConfiguration
+
+```
+@Configuration
+// EnableConfigurationProperties valueе
+@EnableConfigurationProperties(value = {MyStarterProperties.class})
+public class MyStarterAutoConfiguration {
+
+ @Autowired
+ private MyStarterProperties myStarterProperties;
+
+ @Bean
+ @ConditionalOnMissingBean(MyStarterConfig.class)
+ public MyStarterConfig myStarterConfig(){
+ return new MyStarterConfig(myStarterProperties);
+ }
+
+}
+ƴ
+```
+
+1. resources/META-INFһspring.factoriesļ
+
+spring.factories
+
+```
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.example.myStarter.MyStarterAutoConfiguration
+ƴ
+```
+
+spring-configuration-metadata.json
+
+```
+{
+ "group": [
+ {
+ "name": "com.arron",
+ "type": "com.example.myStarter.MyStarterProperties",
+ "sourceType": "com.example.myStarter.MyStarterProperties"
+ }
+ ],
+ "properties": [
+ {
+ "name": "com.arron.name",
+ "type": "java.lang.String",
+ "description": "my start name",
+ "sourceType": "com.example.myStarter.MyStarterProperties",
+ "defaultValue": "MyStarterProperties name"
+ }
+ ]
+}
+ƴ
+```
+
+##
+
+ҵͼmaveninstallװ 
+
+Ȼ½һĿвԣĿ̾Ͳˡ
+
+1.
+
+```
+
+ com.example
+ spring-boot-starter-my-starter
+ 1.0
+
+ƴ
+```
+
+1. ļԣ
+
+```
+com:
+ arron:
+ name: myname
+ƴ
+```
+
+1. Ԫԣ
+
+```
+@RunWith(SpringRunner.class)
+@SpringBootTest
+class RabbitmqApplicationTests {
+ @Autowired
+ private MyStarterConfig myStarterConfig;
+
+ @Test
+ public void testMyStarter(){
+ String name = myStarterConfig.getName();
+ System.out.println(name);
+ }
+}
+ƴ
+```
+
+̨
+
+```
+myname
+ƴ
+```
+
+ˣһԶspringboot starterˡ
+
+# ע
+
+ЩעԶstarterǿܻõ
+
+* @Conditionalһжϣעbean
+* @ConditionalOnMissingBeanbeanʱ,ʵǰBean
+* @ConditionalOnPropertyļ㶨bean
+* @ConditionalOnBeanbeanʱ,ʵǰBean
+* @ConditionalOnClass ·ϴڣʵǰBean
+* @ConditionalOnMissingClass ·ϲڣʵǰBean
+
+
+
+ߣ
+ӣhttps://juejin.cn/post/7127468724046528525
+Դϡ
+ȨСҵתϵȨҵתע
+
diff --git "a/docs/spring/SpringBoot/SpringBoot\347\232\204\345\237\272\346\234\254\344\275\277\347\224\250.md" "b/docs/spring/SpringBoot/SpringBoot\347\232\204\345\237\272\346\234\254\344\275\277\347\224\250.md"
index 36a2500..247e419 100644
--- "a/docs/spring/SpringBoot/SpringBoot\347\232\204\345\237\272\346\234\254\344\275\277\347\224\250.md"
+++ "b/docs/spring/SpringBoot/SpringBoot\347\232\204\345\237\272\346\234\254\344\275\277\347\224\250.md"
@@ -20,55 +20,20 @@
ɡť zip ļѹϵһļС
-
+
[start.spring.io](http://start.spring.io/)Ŀ[Spring Boot](https://spring.io/projects/spring-boot)һSpringӦóڲҪ̫á Spring Boot Spring Ŀеķʽ
ѡʹmavenΪߣĿpomļpomļӵ
-````
-
-
- 4.0.0
-
- org.springframework.boot
- spring-boot-starter-parent
- 3.0.5
-
-
- com.example
- demo
- 0.0.1-SNAPSHOT
- demo
- Demo project for Spring Boot
-
- 17
-
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
-
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
-
-
-````
+````
+
+ 4.0.0 org.springframework.boot spring-boot-starter-parent 3.0.5 com.example demo 0.0.1-SNAPSHOT demo Demo project for Spring Boot 17 org.springframework.boot spring-boot-starter-web
+ org.springframework.boot spring-boot-starter-test test
+ org.springframework.boot spring-boot-maven-plugin
+
+````
## ڶĴ
@@ -76,27 +41,20 @@
IDE дĿ `src/main/java/com/example/demo` ļҵ `DemoApplication.java` ļ
ͨʾĶⷽעļݡԸƲճֱӼ롣
-```
-package com.example.demo;
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
-
-@SpringBootApplication
-@RestController
-public class DemoApplication {
- public static void main(String[] args) {
- SpringApplication.run(DemoApplication.class, args);
- }
- @GetMapping("/hello")
- public String hello(@RequestParam(value = "name", defaultValue = "World") String name) {
- return String.format("Hello %s!", name);
- }
-}
-
-```
+```
+package com.example.demo;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+@SpringBootApplication
+@RestController
+public class DemoApplication {
+ public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } @GetMapping("/hello") public String hello(@RequestParam(value = "name", defaultValue = "World") String name) { return String.format("Hello %s!", name); }}
+
+```
Spring Boot дһġHello World Web д롣
@@ -104,8 +62,7 @@ public class DemoApplication {
ζнΪAmyӦǡHello Amy
-`@RestController` ע Spring˴һ˵㣬ö˵Ӧ Web Ͽá
-
+`@RestController` ע Spring˴һ˵㣬ö˵Ӧ Web Ͽá
@GetMapping(/hello) Spring ʹǵ hello() Ӧ͵ http://localhost:8080/hello ַ
@RequestParam Spring һֵڣĬʹõʡWorld
@@ -118,34 +75,33 @@ public class DemoApplication {
**MacOS/Linux:**
-```
-COPY./gradlew bootRun
-
-```
+```
+COPY./gradlew bootRun
+
+```
**Windows:**
-```
-COPY.\gradlew.bat bootRun
-
-```
+```
+COPY.\gradlew.bat bootRun
+
+```
-ӦûῴһЩ˷dzƵ
-
+ӦûῴһЩ˷dzƵ
+
-иǣSpringӦѾʼˡ
-Spring Boot Ƕʽ Apache Tomcat 䵱ڼlocalhost˿ڡ8080ϵ
+иǣSpringӦѾʼˡ Spring Boot Ƕʽ Apache Tomcat 䵱ڼlocalhost˿ڡ8080ϵ
ڶĵַ`http://localhost:8080/hello`
-ӦõõһѺõĻӦ
-
+ӦõõһѺõĻӦ
+
# ܽ
-˼һSpringBootӦþôˣ㲻ҪļǶķ
+˼һSpringBootӦþôˣ㲻ҪļǶķ
ֻҪһ࣬ͿʵһSpringBootӦá
-ҲΪʲôspringbootٹһΪʵ̫ˡ
+ҲΪʲôspringbootٹһΪʵ̫ˡ
ȻʵʿҪõspringbootĹܺԣǽڽ½չܡ
# ο
diff --git "a/docs/spring/SpringBoot/SpringBoot\347\232\204\351\205\215\347\275\256\346\226\207\344\273\266\347\256\241\347\220\206.md" "b/docs/spring/SpringBoot/SpringBoot\347\232\204\351\205\215\347\275\256\346\226\207\344\273\266\347\256\241\347\220\206.md"
new file mode 100644
index 0000000..46c6771
--- /dev/null
+++ "b/docs/spring/SpringBoot/SpringBoot\347\232\204\351\205\215\347\275\256\346\226\207\344\273\266\347\256\241\347\220\206.md"
@@ -0,0 +1,2989 @@
+## 1.SpringBootùı
+
+ΪʵֿٴͿĿSpringbootܴspringbootĿԽĿֱӴjarУԼװTomcatһַݵIJʽ
+
+Ŀķʽһjar𣬼ļ͵jarͻ
+
+һĿйУҪĶļĻҪ´
+
+ĿҪͬһ̨ʱԵjarͬĵĿjar100Mܾռ99M˷Դ˷ԼĿЧʡ
+
+ĿļȡjarͳһĿЧֽԼ˷ĴģͬʱĿάҲǷdzģĶļ·Ϳˣ¹
+
+Ǿʵַ
+
+### 1.1 **ļͳһ**
+
+```
+ - springbootļ
+ - Springbootȡļapplication.propertiesȼΪ
+ - JarͬĿ¼configĿ¼
+ - JarͬĿ¼
+ - classPath(resourcesĿ¼)configĿ¼
+ - classpathĿ¼
+
+```
+
+springbootĬȥԼĺļȼһȼķʽĿʱͨķʽָĿغļ
+java Cjar -Dspring.config.location=xxx/xxx/xxxx.properties xxxx.jar
+
+Spring Bootȼߵλҵãôȼ͵
+
+### 1.2 **Դļ**
+
+SpringbootļѾܹȡjarйˣǻһЩҵϵļԴļԴļFTPϢȣquartzʱ־ļȥȡȷڴõ
+
+֪SpringbootĿͨעⷽʽȡļҲͨעⷽʽĿܹõjarⲿļģͼ
+
+
+@PropertySourcevalueֵһclasspathconfigĿ¼µԴļڶǸspring.profiles.path̬ȡĿ¼spring.profiles.pathںļԶһֵļͳһļ·ignoreResourceNotFound=true趨ǰһ·ûҵļݵڶ·ȥҡ
+
+ǻֱӸ·FileSystemResourceȥһļʵͼ
+
+
+ԭƣںļԶͳһĿ¼·ļ
+
+logback־ļطʽ£
+
+
+һʵַ˼·
+
+```
+ - springbootļﶨһspring.profiles.pathֵָļͳһõĿ¼ļҲǷ
+
+ - ļļĵطҲӦûȡspring.profiles.path̬ظ·µļ
+
+ - Pom.xmlļĴģ飬ļųǴjarDzļģοĵڵ3
+
+ - jarʱָͨصĺļΪspring.profiles.pathµĺļ
+
+```
+**ͳһ**
+
+ͨjarԴjarҲԷĿjarͬĿ¼µlibĿ¼ǿԸpom.xmlʵ֣οĵڵ3
+
+****
+
+```
+
+
+
+ src/main/java
+
+ **/*.properties
+ **/*.xml
+
+ true
+
+
+ src/main/resources
+
+
+ **/*.properties
+ **/*.xml
+ **/*.yml
+
+ false
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 1.8
+ 1.8
+ true
+ true
+
+ C:/Program Files/Java/jdk1.8.0_161/bin/javac.exe
+
+
+
+
+ maven-jar-plugin
+
+
+
+ true
+ lib/
+ false
+ com.xrq.demo.Application
+
+
+ ./
+
+
+
+ *.properties
+ *.yml
+ *.xml
+ config/**
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+ copy
+ package
+
+ copy-dependencies
+
+
+
+ ${project.build.directory}/lib
+
+
+
+
+
+
+
+
+```
+
+ĺpom.xmlbuildģͿͨmvn package mvn installǵjar
+
+1. **Ŀshellűд**
+ ԶshellűʵĿֹͣ״̬
+
+```
+#!/bin/bash
+#滻ΪԼִг,
+APP_NAME=demo1-0.0.1-SNAPSHOT.jar
+JVM="-server -Xms512m -Xmx512m -XX:PermSize=64M -XX:MaxNewSize=128m -XX:MaxPermSize=128m -Djava.awt.headless=true -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled"
+APPFILE_PATH="-Dspring.config.location=/usr/local/demo/config/application-demo1.properties"
+#ʹ˵,ʾ
+usage() {
+echo "Usage: sh ִнű.sh [start|stop|restart|status]"
+exit 1
+}
+#Ƿ
+is_exist(){
+pid=`ps -ef|grep $APP_NAME|grep -v grep|awk '{print $2}' `
+#ڷ1,ڷ0
+if [ -z "${pid}" ]; then
+return 1
+else
+return 0
+fi
+}
+#
+start(){
+is_exist
+if [ $? -eq "0" ]; then
+echo "${APP_NAME} is already running. pid=${pid} ."
+else
+nohup java $JVM -jar $APPFILE_PATH $APP_NAME > /dev/null 2>&1
+fi
+}
+#ֹͣ
+stop(){
+is_exist
+if [ $? -eq "0" ]; then
+kill -9 $pid
+else
+echo "${APP_NAME} is not running"
+fi
+}
+#״̬
+status(){
+is_exist
+if [ $? -eq "0" ]; then
+echo "${APP_NAME} is running. Pid is ${pid}"
+else
+echo "${APP_NAME} is NOT running."
+fi
+}
+#
+restart(){
+stop
+start
+}
+#,ѡִжӦ,ִʹ˵
+case "$1" in
+"start")
+start
+;;
+"stop")
+stop
+;;
+"status")
+status
+;;
+"restart")
+restart
+;;
+*)
+usage
+;;
+esac
+
+```
+
+****
+
+linux½ļУǴõĿjarȥjarͬĿ¼½configlibļУֱļ͵ȥṹͼ*.shΪԼдĿshellű
+
+
+
+configڵspringbootļapplication-demo1.propertiesļ
+
+spring.profiles.pathijɵǰļڵĿ¼Ϊ/usr/local/demo/config
+
+*.shűAPPFILE_PATHֵ
+
+APPFILE_PATH="-Dspring.config.location=/usr/local/demo/config/application-demo1.properties"
+
+**Ŀ**
+
+jarĿ¼ִ
+
+sh [demo1.sh](http://demo1.sh/) start Ŀ
+
+sh [demo1.sh](http://demo1.sh/) stop ֹͣĿ
+
+sh [demo1.sh](http://demo1.sh/) restartĿ
+
+sh [demo1.sh](http://demo1.sh/) statusĿ״̬
+
+## 2\. ⲿ
+
+
+
+
+
+Spring Boot㽫ⲿͿڲͬĻʹͬӦó롣 ʹøⲿԴJava properties ļYAMLļв
+
+
+
+
+
+ֵͨʹ `@Value` עֱעBeanҲͨSpring `Environment` ʣͨ `@ConfigurationProperties` [](https://springdoc.cn/spring-boot/features.html#features.external-config.typesafe-configuration-properties)
+
+
+
+
+
+Spring Boot ʹһdzر `PropertySource` ˳ּдֵ property source ԸǰԴжֵ ˳ǡ
+
+
+
+
+
+1. Ĭԣͨ `SpringApplication.setDefaultProperties` ָ
+
+2. @Configuration ϵ [`@PropertySource`](https://docs.spring.io/spring-framework/docs/6.0.5/javadoc-api/org/springframework/context/annotation/PropertySource.html) ע⡣ע⣬Դֱapplication contextˢʱŻᱻӵСijЩ˵Ѿ̫ˣ `logging.*` `spring.main.*` ˢ¿ʼǰѾȡˡ
+
+3. ݣ `application.properties` ļ
+
+4. `RandomValuePropertySource`ֻ `random.*` ԡ
+
+5. ϵͳ
+
+6. Java System properties (`System.getProperties()`).
+
+7. `java:comp/env` е JNDI ԡ
+
+8. `ServletContext` init parameters.
+
+9. `ServletConfig` init parameters.
+
+10. `SPRING_APPLICATION_JSON` ԣǶ뻷ϵͳеJSON
+
+11. в
+
+12. ڲе `properties` ԡ [`@SpringBootTest`](https://docs.spring.io/spring-boot/docs/3.1.0-SNAPSHOT/api/org/springframework/boot/test/context/SpringBootTest.html) Ͳעпã[ڲӦóһضƬ](https://springdoc.cn/spring-boot/features.html#features.testing.spring-boot-applications.autoconfigured-tests)
+
+13. еhttps://docs.spring.io/spring-framework/docs/6.0.5/javadoc-api/org/springframework/test/context/TestPropertySource.html[`@TestPropertySource`] ע.
+
+14. devtoolsڻ״̬ʱ`$HOME/.config/spring-boot` Ŀ¼µ[Devtoolsȫ](https://springdoc.cn/spring-boot/using.html#using.devtools.globalsettings)
+
+
+
+
+
+ļ˳ǡ
+
+
+
+
+
+1. jarд[Application properties](https://springdoc.cn/spring-boot/features.html#features.external-config.files)application.properties YAML
+
+2. jarд [ض Profile application properties](https://springdoc.cn/spring-boot/features.html#features.external-config.files.profile-specific)`application-{profile}.properties` YAML
+
+3. jar֮[Application properties](https://springdoc.cn/spring-boot/features.html#features.external-config.files)ԣapplication.propertiesYAML
+
+4. jar֮[ض Profile application properties](https://springdoc.cn/spring-boot/features.html#features.external-config.files.profile-specific) `application-{profile}.properties` YAML
+
+
+
+
+
+| | Ӧóмʹһָʽ ͬһط `.properties` `.yml` ʽļ`.properties` ȡ |
+| --- | --- |
+
+
+
+
+
+Ϊṩһӣ㿪һ `@Component`ʹһ `name` ԣʾ
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@Component
+public class MyBean {
+
+ @Value("${name}")
+ private String name;
+
+ // ...
+
+}
+
+```
+
+
+
+
+
+
+
+Ӧóclasspath磬jarУһ `application.properties` ļΪ `name` ṩһĬֵһµĻʱjar֮ṩһ `application.properties` ļ `name` һԵIJԣһضв磬`java -jar app.jar --name="Spring"`
+
+
+
+
+
+| | `env` `configprops` ˵ȷһΪʲôһضֵʱdzáʹ˵ֵ "[](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints)" ֡ |
+| --- | --- |
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/features.html#features.external-config.command-line-args)2.1\.
+
+
+
+Ĭ£`SpringApplication` Ὣκѡ `--` ͷIJ `--server.port=9000` תΪ `property` ӵSpring `Environment` С ǰڻļԴ
+
+
+
+
+
+㲻ϣԱӵ `Environment` Уͨ `SpringApplication.setAddCommandLineProperties(false)` ǡ
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/features.html#features.external-config.application-json)2.2\. JSON Application Properties
+
+
+
+ϵͳƣζЩƲʹá Ϊ˰⣬Spring Boot㽫һԿΪһһJSONṹ
+
+
+
+
+
+Ӧóʱκ `spring.application.json` `SPRING_APPLICATION_JSON` Խӵ `Environment` С
+
+
+
+
+
+磬`SPRING_APPLICATION_JSON` Կ UN*X shell Ϊṩ
+
+
+
+
+
+
+
+```
+$ SPRING_APPLICATION_JSON='{"my":{"name":"test"}}' java -jar myapp.jar
+```
+
+
+
+
+
+
+
+ǰУSpring `Environment` յõ `my.name=test`
+
+
+
+
+
+ͬJSONҲΪһϵͳṩ
+
+
+
+
+
+
+
+```
+$ java -Dspring.application.json='{"my":{"name":"test"}}' -jar myapp.jar
+```
+
+
+
+
+
+
+
+ͨʹһвṩJSON
+
+
+
+
+
+
+
+```
+$ java -jar myapp.jar --spring.application.json='{"my":{"name":"test"}}'
+```
+
+
+
+
+
+
+
+ҪһӦ÷УҲʹһΪ `java:comp/env/spring.application.json` JNDI
+
+
+
+
+
+| | JSONе `null` ֵӵɵԴУ `PropertySourcesPropertyResolver` `null` Ϊȱʧֵ ζJSON `null` ֵԵͽԴԡ |
+| --- | --- |
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/features.html#features.external-config.files)2.3\. ⲿ Application Properties
+
+
+
+ӦóʱSpring BootԶλҵ `application.properties` `application.yaml` ļ
+
+
+
+
+
+1. classpath
+
+
+
+ 1. classpath ·
+
+ 2. classpath µ `/config`
+
+
+
+2. ǰĿ¼
+
+
+
+ 1. ǰĿ¼
+
+ 2. ǰĿ¼µ `config/` Ŀ¼
+
+ 3. `config/` Ŀ¼ֱĿ¼
+
+
+
+
+
+
+
+бȼϵĿֵǽĿֵ صļΪ `PropertySources` ӵSpring `Environment` С
+
+
+
+
+
+㲻ϲ `application` Ϊļƣָͨ `spring.config.name` лһļơ 磬ΪѰ `myproject.properties` `myproject.yaml` ļ·ʽӦó
+
+
+
+
+
+
+
+```
+$ java -jar myproject.jar --spring.config.name=myproject
+```
+
+
+
+
+
+
+
+Ҳͨʹ `spring.config.location` һȷλá ԽһŷָбаһҪλá
+
+
+
+
+
+ʾָͬļ
+
+
+
+
+
+
+
+```
+$ java -jar myproject.jar --spring.config.location=\
+ optional:classpath:/default.properties,\
+ optional:classpath:/override.properties
+```
+
+
+
+
+
+
+
+| | [ļǿѡ](https://springdoc.cn/spring-boot/features.html#features.external-config.files.optional-prefix)ҿDzڵģôʹ `optional:` ǰ |
+| --- | --- |
+
+
+
+
+
+| | `spring.config.name`, `spring.config.location`, `spring.config.extra-location` ȷЩļ뱻ء DZ뱻ΪԣͨDzϵͳϵͳԣв |
+| --- | --- |
+
+
+
+
+
+ `spring.config.location` Ŀ¼ļӦ `/` β ʱǽ `spring.config.name` ɵƣȻء `spring.config.location` ָļֱӵ롣
+
+
+
+
+
+| | Ŀ¼ļλֵҲչԼ[ضļ](https://springdoc.cn/spring-boot/features.html#features.external-config.files.profile-specific)磬 `spring.config.location` `classpath:myconfig.properties`Ҳᷢʵ `classpath:myconfig-.properties` ļء |
+| --- | --- |
+
+
+
+
+
+ڴ£ӵÿ `spring.config.location` һļĿ¼ λǰDZ˳ģλÿԸǰλõֵ
+
+
+
+
+
+һӵλãʹضļҪṩһʾԱSpring Boot֪Ӧη顣һλһλõļϣЩλöΪͬһ磬classpathλ÷飬ȻⲿλáһλڵĿӦ `;` ָϸڼ [ָ profile](https://springdoc.cn/spring-boot/features.html#features.external-config.files.profile-specific) ֵӡ
+
+
+
+
+
+ͨʹ `spring.config.location` õλȡĬλá 磬 `spring.config.location` Ϊ `optional:classpath:/custom-config/,optional:file:./custom-config/` ǵλü¡
+
+
+
+
+
+1. `optional:classpath:custom-config/`
+
+2. `optional:file:./custom-config/`
+
+
+
+
+
+ϲӶλã滻ǣʹ `spring.config.extra-location` ӸλüصԿԸĬλõԡ 磬 `spring.config.extra-location` Ϊ `optional:classpath:/custom-config/,optional:file:./custom-config/` ǵλü¡
+
+
+
+
+
+1. `optional:classpath:/;optional:classpath:/config/`
+
+2. `optional:file:./;optional:file:./config/;optional:file:./config/*/`
+
+3. `optional:classpath:custom-config/`
+
+4. `optional:file:./custom-config/`
+
+
+
+
+
+һļָĬֵȻһļѡԵظЩֵ һĬλõ `application.properties` `spring.config.name` ѡbasenameΪӦóṩĬֵ ȻЩĬֵʱλһԶλõIJͬļǡ
+
+
+
+
+
+| | ʹûϵͳԣϵͳʹþָļʹ»ߴ棨磬 `SPRING_CONFIG_NAME` `spring.config.name` μ[ӻ](https://springdoc.cn/spring-boot/features.html#features.external-config.typesafe-configuration-properties.relaxed-binding.environment-variables) ˽顣 |
+| --- | --- |
+
+
+
+
+
+| | ӦóservletӦ÷УôJNDIԣ `java:comp/env` УservletijʼԴ滷ϵͳԣ֮һ |
+| --- | --- |
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/features.html#features.external-config.files.optional-prefix)2.3.1\. ѡλ(Optional Locations)
+
+
+
+Ĭ£ָλòʱSpring Boot׳һ `ConfigDataLocationNotFoundException` Ӧó
+
+
+
+
+
+ָһλã㲻Ǵڣʹ `optional:` ǰ `spring.config.locationspring.config.extra-location` ʹǰҲ [`spring.config.import`](https://springdoc.cn/spring-boot/features.html#features.external-config.files.importing) ʹá
+
+
+
+
+
+磬`spring.config.import` ֵΪ `optional:file:./myconfig.properties` Ӧóʹ `myconfig.properties` ļʧ
+
+
+
+
+
+е `ConfigDataLocationNotFoundExceptions` ʼռӦóʹ `spring.config.on-not-found` ԡ ʹ `SpringApplication.setDefaultProperties(..)` ʹϵͳ/ֵΪ `ignore`
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/features.html#features.external-config.files.wildcard-locations)2.3.2\. ַͨ
+
+
+
+һļλһ·а `*` ַͱΪһͨλá ͨڼʱչˣֱӵĿ¼Ҳ顣 ͨλKubernetesжԵԴĻرá
+
+
+
+
+
+磬һЩRedisúһЩMySQLã÷ֿͬʱҪֶһ `application.properties` ļС
+
+
+
+
+
+ܻᵼ `application.properties` ļڲͬλã `/config/redis/application.properties` `/config/mysql/application.properties` £һͨλ `config/*/` ļ
+
+
+
+
+
+Ĭ£Spring Boot `config/*/` Ĭλá ζjar֮ `/config` Ŀ¼Ŀ¼ᱻ
+
+
+
+
+
+ `spring.config.location` `spring.config.extra-location` ʹͨλá
+
+
+
+
+
+| | ͨλñֻһ `*` `*/` βĿ¼λã `*/` ļλá ͨλýļľ·ĸ˳ |
+| --- | --- |
+
+
+
+
+
+| | ͨλֻⲿĿ¼á 㲻 `classpath:` λʹͨ |
+| --- | --- |
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/features.html#features.external-config.files.profile-specific)2.3.3\. ضļProfile Specific Files
+
+
+
+ `application` ļSpring Bootʹ `application-{profile}` profileضļ 磬ӦóΪ `prod` ļ`spring.profiles.active=prod`ʹYAMLļô `application.yml` `application-prod.yml` ǡ
+
+
+
+
+
+ضļ(`profiles`) `application.properties` λͬضļڷضļ ָ˼ļʤIJԡ 磬ļ `prod,live` `spring.profiles.active` ָģ`application-prod.properties` еֵԱ `application-live.properties` еֵǡ
+
+
+
+
+
+| | ʤIJ[location group](https://springdoc.cn/spring-boot/features.html#features.external-config.files.location-groups) `spring.config.location` `classpath:/cfg/,classpath:/ext/` `classpath:/cfg/;classpath:/ext/` ͬĸǹ磬 `prod,live` ˵ǿļ /cfg application-live.properties/ext application-live.properties application-prod.properties һ `spring.config.location` Ϊ `classpath:/cfg/,classpath:/ext/` ʱǻ `/ext` ļ֮ǰ `/cfg` ļ1. `/cfg/application-live.properties` 2. `/ext/application-prod.properties` 3. `/ext/application-live.properties` `classpath:/cfg/;classpath:/ext/` ʱ `;` ָͬһ `/cfg` `/ext` 1. `/ext/application-prod.properties` 2. `/cfg/application-live.properties` 3. `/ext/application-live.properties` |
+| --- | --- |
+
+
+
+
+
+`Environment` һĬϵļĬΪ `[default]` ûûļͻʹЩļ 仰˵ûȷļôͻῼ `application-default` ԡ
+
+
+
+
+
+| | ļֻһΡ Ѿֱ[](https://springdoc.cn/spring-boot/features.html#features.external-config.files.importing)һļضļôᱻڶε롣 |
+| --- | --- |
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/features.html#features.external-config.files.importing)2.3.4\.
+
+
+
+application properties пʹ `spring.config.import` Դطݡ ڱʱΪļĶļ
+
+
+
+
+
+磬 classpath `application.properties` ļݡ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+spring.application.name=myapp
+spring.config.import=optional:file:./dev.properties
+
+```
+
+
+
+
+
+
+
+⽫뵱ǰĿ¼µ `dev.properties` ļļ `dev.properties` еֵڴļ У`dev.properties` Խ `spring.application.name` ¶Ϊһֵͬ
+
+
+
+
+
+һֻᱻһΣٴΡ һproperties/yamlļڵĵļб˳Ҫ 磬ӲͬĽ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+spring.config.import=my.properties
+my.property=value
+
+```
+
+
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+my.property=value
+spring.config.import=my.properties
+
+```
+
+
+
+
+
+
+
+У`my.properties` ļֵڴ䵼ļ
+
+
+
+
+
+һһ `spring.config.import` ¿ָλá λýDZ˳ĵ뽫ȴ
+
+
+
+
+
+| | ʵʱ[ضļı](https://springdoc.cn/spring-boot/features.html#features.external-config.files.profile-specific)Ҳǵ롣 ӽ `my.properties` Լκ `my-.properties` 塣 |
+| --- | --- |
+
+
+
+
+
+| | Spring Boot ṩ˿ɲεAPIֲָ֧ͬλõַ Ĭ£ԵJava PropertiesYAML [](https://springdoc.cn/spring-boot/features.html#features.external-config.files.configtree) jarṩ֧֣ҪDZļ 磬ⲿ洢ConsulApache ZooKeeperNetflix ArchaiusNacos֧ԼλãʵԼüأ `org.springframework.boot.context.config` е `ConfigDataLocationResolver` `ConfigDataLoader` ࡣ |
+| --- | --- |
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/features.html#features.external-config.files.importing-extensionless)2.3.5\. չļ
+
+
+
+Щƽ̨Ϊװļvolume mounted filesļչ ҪЩչļҪSpring BootһʾԱ֪μǡ ͨչʾڷһ㡣
+
+
+
+
+
+磬һ `/etc/config/myconfig` ļϣyamlʽ롣 ķ `application.properties` е
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+spring.config.import=file:/etc/config/myconfig[.yaml]
+
+```
+
+
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/features.html#features.external-config.files.configtree)2.3.6\. ʹConfiguration Trees
+
+
+
+ƽ̨KubernetesӦóʱ㾭Ҫȡƽ̨ṩֵ ڴĿIJټȱ㣬رֵ secret ġ
+
+
+
+
+
+Ϊƽ̨㽫ӳ䵽صݾ 磬Kubernetes Ծ [`ConfigMaps`](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#populate-a-volume-with-data-stored-in-a-configmap) [`Secrets`](https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets-as-files-from-a-pod)
+
+
+
+
+
+ʹֳ volume ģʽ
+
+
+
+
+
+1. һļһԣͨдYAML
+
+2. ļдһĿ¼УļΪ keyݳΪ value
+
+
+
+
+
+ڵһʹ `spring.config.import` ֱӵYAMLļ[](https://springdoc.cn/spring-boot/features.html#features.external-config.files.importing) ڵڶҪʹ `configtree:` ǰԱSpring Boot֪ҪļΪԹ
+
+
+
+
+
+ٸӣһ£KubernetesѾvolume
+
+
+
+
+
+
+
+ etc/
+ config/
+ myapp/
+ username
+ password
+
+
+
+
+
+
+
+`username` ļݽһֵ `password` ݽһ secret
+
+
+
+
+
+ҪЩԣ `application.properties` `application.yaml` ļݡ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+spring.config.import=optional:configtree:/etc/config/
+
+```
+
+
+
+
+
+
+
+ȻԴ `Environment` Գ淽ʽʻע `myapp.username` `myapp.password` ԡ
+
+
+
+
+
+| | µļйơ УΪ˷Ϊ `username` `password`Խ `spring.config.import` Ϊ `optional:configtree:/etc/config/myapp` |
+| --- | --- |
+
+
+
+
+
+| | еŵļҲᱻȷӳ䡣 磬У`/etc/config` Ϊ `myapp.username` ļ `Environment` е `myapp.username` |
+| --- | --- |
+
+
+
+
+
+| | ֵԱַ `String` `byte[]` ͣȡԤڵݡ |
+| --- | --- |
+
+
+
+
+
+жҪͬһļе룬ʹͨݷʽ κ `/*/` β `configtree:` λýֱӵļΪ
+
+
+
+
+
+磬volume
+
+
+
+
+
+
+
+ etc/
+ config/
+ dbconfig/
+ db/
+ username
+ password
+ mqconfig/
+ mq/
+ username
+ password
+
+
+
+
+
+
+
+ʹ `configtree:/etc/config/*/` Ϊλá
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+spring.config.import=optional:configtree:/etc/config/*/
+
+```
+
+
+
+
+
+
+
+⽫ `db.username``db.password``mq.username` `mq.password` ԡ
+
+
+
+
+
+| | ʹͨصĿ¼ǰĸ˳еġ Ҫһͬ˳ôӦðÿλΪһĵг |
+| --- | --- |
+
+
+
+
+
+ҲDocker secret Docker swarmsecretķȨʱsecretᱻװصС 磬һΪ `db.password` secret `/run/secrets/` λã· `db.password` Springá
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+spring.config.import=optional:configtree:/run/secrets/
+
+```
+
+
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/features.html#features.external-config.files.property-placeholders)2.3.7\. ռλ
+
+
+
+`application.properties` `application.yml` еֵʹʱͨе `Environment` ˣԲοǰֵ磬ϵͳԻ `${name}` ռλһֵκεط ռλҲָһĬֵʹ `:` ָĬֵƣ `${name:default}`
+
+
+
+
+
+ʾ˴ĬֵͲĬֵռλʹ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+app.name=MyApp
+app.description=${app.name} is a Spring Boot application written by ${username:Unknown}
+
+```
+
+
+
+
+
+
+
+ `username` ûطã`app.description` ֵ `MyApp is a Spring Boot application written by Unknown`
+
+
+
+
+
+| | ӦʼʹռλеƵĹ淶ʽʹСдĸkebab-caseǡ ⽫Spring Bootʹ[ɰ](https://springdoc.cn/spring-boot/features.html#features.external-config.typesafe-configuration-properties.relaxed-binding) `@ConfigurationProperties` ʱͬ磬`${demo.item-price}` `application.properties` ļлȡ `demo.item-price` `demo.itemPrice` ʽԣԼϵͳлȡ `DEMO_ITEMPRICE` `${demo.itemPrice}` Ļ `demo.item-price` `DEMO_ITEMPRICE` Ͳᱻǡ |
+| --- | --- |
+
+
+
+
+
+| | ҲʹּSpring BootԵ short 塣 μ_[howto.html](https://springdoc.cn/spring-boot/howto.html#howto.properties-and-configuration.short-command-line-arguments)_ķ |
+| --- | --- |
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/features.html#features.external-config.files.multi-document)2.3.8\. ʹöĵļWorking with Multi-Document Files
+
+
+
+Spring Boot㽫һļֳɶļÿļǶӵġ ļǰ˳ģϵ¡ ļԸǰļжԡ
+
+
+
+
+
+ `application.yml` ļʹñYAMLĵ ַ`---`һļĽһļĿʼ
+
+
+
+
+
+磬ļĵ
+
+
+
+
+
+
+
+```
+spring:
+ application:
+ name: "MyApp"
+---
+spring:
+ application:
+ name: "MyCloudApp"
+ config:
+ activate:
+ on-cloud-platform: "kubernetes"
+```
+
+
+
+
+
+
+
+ `application.properties` ļһ `#---` `!---` עͱļķָ
+
+
+
+
+
+
+
+```
+spring.application.name=MyApp
+#---
+spring.application.name=MyCloudApp
+spring.config.activate.on-cloud-platform=kubernetes
+```
+
+
+
+
+
+
+
+| | properties ļķָκǰհףұַ ָǰвͬעǰ |
+| --- | --- |
+
+
+
+
+
+| | ĵļͨ뼤һʹã `spring.config.activated.on-profile` [һ](https://springdoc.cn/spring-boot/features.html#features.external-config.files.activation-properties) |
+| --- | --- |
+
+
+
+
+
+| | ĵļͨʹ `@PropertySource` `@TestPropertySource` עء |
+| --- | --- |
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/features.html#features.external-config.files.activation-properties)2.3.9\. ԣActivation Properties
+
+
+
+ʱֻijЩʱһضǺõġ 磬һЩֻضļʱء
+
+
+
+
+
+ʹ `spring.config.activation.*` ؼһļ
+
+
+
+
+
+¡
+
+
+
+Table 2\. activation properties
+| | ˵ |
+| --- | --- |
+| `on-profile` | һ֮ƥļʽʹļڻ״ָ̬ļʱЧ |
+| `on-cloud-platform` | `CloudPlatform`ʹļڻ״̬ƽ̨״̬Ч |
+
+
+
+磬ָڶļֻKubernetesʱЧֻ prod staging ļڻ״̬ʱЧ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+myprop=always-set
+#---
+spring.config.activate.on-cloud-platform=kubernetes
+spring.config.activate.on-profile=prod | staging
+myotherprop=sometimes-set
+
+```
+
+
+
+
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/features.html#features.external-config.encrypting)2.4\. ԣEncrypting Properties
+
+
+
+Spring BootûΪֵṩκ֧֣ṩHookmSpring `Environment` аֵ `EnvironmentPostProcessor` ӿӦóǰ `Environment` μ[howto.html](https://springdoc.cn/spring-boot/howto.html#howto.application.customize-the-environment-or-application-context)˽顣
+
+
+
+
+
+Ҫһְȫķʽ洢ƾ֤룬 [Spring Cloud Vault](https://cloud.spring.io/spring-cloud-vault/) Ŀṩ˶ [HashiCorp Vault](https://www.vaultproject.io/)д洢ⲿõ֧֡
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/features.html#features.external-config.yaml)2.5\. ʹ YAML
+
+
+
+[YAML](https://yaml.org/) JSONijֲָݵķʽ ֻҪclasspath [SnakeYAML](https://github.com/snakeyaml/snakeyaml) ⣬`SpringApplication` ͻԶ֧YAMLΪpropertiesƷ
+
+
+
+
+
+| | ʹ StarterSnakeYAML `spring-boot-starter` Զṩ |
+| --- | --- |
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/features.html#features.external-config.yaml.mapping-to-properties)2.5.1\. YAMLӳ䵽Properties
+
+
+
+YAML ĵҪֲʽתΪ Spring `Environment` һʹõıƽṹ 磬YAMLĵ
+
+
+
+
+
+
+
+```
+environments:
+ dev:
+ url: "https://dev.example.com"
+ name: "Developer Setup"
+ prod:
+ url: "https://another.example.com"
+ name: "My Cool App"
+```
+
+
+
+
+
+
+
+Ϊ˴ `Environment` зЩԣǽƽʾ
+
+
+
+
+
+
+
+```
+environments.dev.url=https://dev.example.com
+environments.dev.name=Developer Setup
+environments.prod.url=https://another.example.com
+environments.prod.name=My Cool App
+```
+
+
+
+
+
+
+
+ͬأYAMLебҲҪбƽ DZʾΪ `[index]` key 磬YAML
+
+
+
+
+
+
+
+```
+my:
+ servers:
+ - "dev.example.com"
+ - "another.example.com"
+```
+
+
+
+
+
+
+
+ǰӽתΪԡ
+
+
+
+
+
+
+
+```
+my.servers[0]=dev.example.com
+my.servers[1]=another.example.com
+```
+
+
+
+
+
+
+
+| | ʹ `[index]` ŵԿʹSpring Boot `Binder` Java `List` `Set` ϸڼ [Ͱȫ](https://springdoc.cn/spring-boot/features.html#features.external-config.typesafe-configuration-properties) ֡ |
+| --- | --- |
+
+
+
+
+
+| | YAMLļͨʹ `@PropertySource` `@TestPropertySource` עء ԣҪַʽֵ£Ҫʹһ properties ļ |
+| --- | --- |
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/features.html#features.external-config.yaml.directly-loading)2.5.2\. ֱӼYAML
+
+
+
+Spring Frameworkṩ࣬YAMLĵ `YamlPropertiesFactoryBean` YAMLΪ `Properties` أ`YamlMapFactoryBean` YAMLΪ `Map` ء
+
+
+
+
+
+YAMLΪSpring `PropertySource` Ҳʹ `YamlPropertySourceLoader` ࡣ
+
+
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/features.html#features.external-config.random-values)2.6\. ֵ
+
+
+
+The `RandomValuePropertySource` is useful for injecting random values (for example, into secrets or test cases). It can produce integers, longs, uuids, or strings, as shown in the following example:
+
+
+
+
+
+`RandomValuePropertySource` עֵã磬ע ԲIntegerLongUUIDStringʾ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+my.secret=${random.value}
+my.number=${random.int}
+my.bignumber=${random.long}
+my.uuid=${random.uuid}
+my.number-less-than-ten=${random.int(10)}
+my.number-in-range=${random.int[1024,65536]}
+
+```
+
+
+
+
+
+
+
+`random.int*` `OPEN value (,max) CLOSE` `OPEN,CLOSE` κַ `value,max` ṩ `max`ô `value` Сֵ `max` ֵռ
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/features.html#features.external-config.system-environment)2.7\. ϵͳ
+
+
+
+Spring Boot֧Ϊһǰ ϵͳвͬҪSpring BootӦóͺá ϵͳԵǰֱ `SpringApplication` á
+
+
+
+
+
+磬㽫ǰΪ `input` `remote.timeout` ϵͳҲΪ `input.remote.timeout`
+
+
+
+
+
+
+
+### [](https://springdoc.cn/spring-boot/features.html#features.external-config.typesafe-configuration-properties)2.8\. Ͱȫ
+
+
+
+ʹ `@Value("${property}")` עעʱ鷳رǵҪԻǷֲġ Spring BootṩһִԵǿ͵Bean֤Ӧóá
+
+
+
+
+
+| | μ[`@Value` Ͱȫ֮](https://springdoc.cn/spring-boot/features.html#features.external-config.typesafe-configuration-properties.vs-value-annotation) |
+| --- | --- |
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/features.html#features.external-config.typesafe-configuration-properties.java-bean-binding)2.8.1\. JavaBean
+
+
+
+ʾһ˱JavaBeanԵbean
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@ConfigurationProperties("my.service")
+public class MyProperties {
+
+ private boolean enabled;
+
+ private InetAddress remoteAddress;
+
+ private final Security security = new Security();
+
+ // getters / setters...
+
+ public static class Security {
+
+ private String username;
+
+ private String password;
+
+ private List roles = new ArrayList<>(Collections.singleton("USER"));
+
+ // getters / setters...
+
+ }
+
+}
+
+```
+
+
+
+
+
+
+
+ǰPOJOԡ
+
+
+
+
+
+* `my.service.enabled`ĬֵΪ`false`
+
+* `my.service.remote-address`Ϳ`String`ǿṩ
+
+* `my.service.security.username`һǶ `security` ɸԵƾ رǣȫûʹͣ `SecurityProperties`
+
+* `my.service.security.password`.
+
+* `my.service.security.role`һ `String` ļϣĬΪ `USER`
+
+
+
+
+
+| | ӳ䵽Spring Bootпõ `@ConfigurationProperties` ԣͨpropertiesļYAMLļƽãЩǹAPI౾ getters/setters ζſֱʹãһ仰SpringҲͨgetter/setterЩpublicֵģã |
+| --- | --- |
+
+
+
+
+
+| | һĬϵι캯gettersetterͨDZģΪͨJava Beans property descriptorJavaʡʵֵģSpring MVCһ £ʡsetter* Map, ֻҪDZʼҪһgetterһҪһsetterΪǿԱͻ䡣 * Collectionarray ͨͨYAMLʹõŷֵָԣʡ ںһ£һsetterDZġ ǽΪһsetter ʼһϣȷDzɱģǰӣ * ǶPOJOԱʼǰе `Security` ֶΣͲҪsetter ðͨʹĬϹ캯ʱʵҪһsetter ЩʹProject LombokԶgettersetter ȷLombokΪκضĹ캯ΪԶʵֻDZJava Beanԣֶ֧Ծ̬Եİ |
+| --- | --- |
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/features.html#features.external-config.typesafe-configuration-properties.constructor-binding)2.8.2\. 캯
+
+
+
+һڵӿòɱķʽдʾ
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@ConfigurationProperties("my.service")
+public class MyProperties {
+
+ // fields...
+
+ public MyProperties(boolean enabled, InetAddress remoteAddress, Security security) {
+ this.enabled = enabled;
+ this.remoteAddress = remoteAddress;
+ this.security = security;
+ }
+
+ // getters...
+
+ public static class Security {
+
+ // fields...
+
+ public Security(String username, String password, @DefaultValue("USER") List roles) {
+ this.username = username;
+ this.password = password;
+ this.roles = roles;
+ }
+
+ // getters...
+
+ }
+
+}
+
+```
+
+
+
+
+
+
+
+УΨһġ캯ĴζӦʹøù캯а ζŰҵһϣIJĹ캯 ж캯ʹ `@ConstructorBinding` עָʹĸ캯й캯 ҪΪһֻһ캯ѡ캯ù캯 `@Autowired` ע⡣ 캯 `Record` һʹá ļ¼ж캯ûбҪʹ `@ConstructorBinding`
+
+
+
+
+
+캯Ƕ׳Աе `Security`Ҳͨ乹캯
+
+
+
+
+
+Ĭֵڹ캯Recordʹ `@DefaultValue` ָ תӦڽע `String` ֵǿתΪȱʧԵĿ͡
+
+
+
+
+
+οǰӣû `Security` `MyProperties` ʵһ `security` ͵ `null` ֵ Ϊʹһ null `Security` ʵʹû֮ʹKotlinʱ⽫Ҫ `Security` `username` `password` Ϊ nullableΪûĬֵʹһյ `@DefaultValue` ע⡣
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+public MyProperties(boolean enabled, InetAddress remoteAddress, @DefaultValue Security security) {
+ this.enabled = enabled;
+ this.remoteAddress = remoteAddress;
+ this.security = security;
+}
+
+```
+
+
+
+
+
+
+
+| | Ҫʹù캯ʹ `@EnableConfigurationProperties` ɨá 㲻ܶͨSpringƴBeanʹù캯 `@Component` Beanͨʹ `@Bean` Beanͨʹ `@Import` صBean |
+| --- | --- |
+
+
+
+
+
+| | Ҫԭʹù캯 `-parameters` ࡣʹ Spring Boot Gradle ʹ Maven `spring-boot-starter-parent`⽫Զá |
+| --- | --- |
+
+
+
+
+
+| | 齫 `java.util.Optional` `@ConfigurationProperties` һʹãΪҪΪһʹá ˣʺע롣 Ϊ͵Աһ£ȷʵһ `Optional` ԣûֵ`null` һյ `Optional` |
+| --- | --- |
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/features.html#features.external-config.typesafe-configuration-properties.enabling-annotated-types)2.8.3\. @ConfigurationProperties
+
+
+
+Spring Bootṩ˰ `@ConfigurationProperties` ͲעΪBeanĻʩ Ļԣɨ裬乤ʽɨơ
+
+
+
+
+
+ʱ `@ConfigurationProperties` עܲʺɨ裬磬ڿԼԶûǡ Щ£ʹ `@EnableConfigurationProperties` עָҪб עκ `@Configuration` ϣʾ
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@Configuration(proxyBeanMethods = false)
+@EnableConfigurationProperties(SomeProperties.class)
+public class MyConfiguration {
+
+}
+
+```
+
+
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@ConfigurationProperties("some.properties")
+public class SomeProperties {
+
+}
+
+```
+
+
+
+
+
+
+
+Ҫʹɨ裬application `@ConfigurationPropertiesScan` ע⡣ ͨӵ `@SpringBootApplication` עmainУҲԱӵκ `@Configuration` ϡ Ĭ£ɨעڵİʼԶɨԲο¡
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@SpringBootApplication
+@ConfigurationPropertiesScan({ "com.example.app", "com.example.another" })
+public class MyApplication {
+
+}
+
+```
+
+
+
+
+
+
+
+| | `@ConfigurationProperties` Beanʹɨͨ `@EnableConfigurationProperties` עʱBeanһƣ`-` `` `@ConfigurationProperties` עָĻǰ `` Beanȫơ עûṩκǰֻʹBeanȫơ `com.example.app` У `SomeProperties` ӵ bean `some.properties-com.example.app.SomeProperties` |
+| --- | --- |
+
+
+
+
+
+ǽ `@ConfigurationProperties` ֻ environmentرDzעBean ڱ߽ǰʹ setter עṩκ `*Aware` ӿڣ `EnvironmentAware` Ҫ `Environment` ȻʹùעBeanBean `@Component` ע⣬ʹûJavaBean
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/features.html#features.external-config.typesafe-configuration-properties.using-annotated-types)2.8.4\. ʹ @ConfigurationProperties
+
+
+
+÷ʽ `SpringApplication` ⲿYAMLϵرãʾ
+
+
+
+
+
+
+
+```
+my:
+ service:
+ remote-address: 192.168.1.1
+ security:
+ username: "admin"
+ roles:
+ - "USER"
+ - "ADMIN"
+```
+
+
+
+
+
+
+
+Ҫʹ `@ConfigurationProperties` BeanBeanͬķʽעǣʾ
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@Service
+public class MyService {
+
+ private final MyProperties properties;
+
+ public MyService(MyProperties properties) {
+ this.properties = properties;
+ }
+
+ public void openConnection() {
+ Server server = new Server(this.properties.getRemoteAddress());
+ server.start();
+ // ...
+ }
+
+ // ...
+
+}
+
+```
+
+
+
+
+
+
+
+| | ʹ `@ConfigurationProperties` ԪļЩļԱIDEԵġԶȫܡ [¼](https://springdoc.cn/spring-boot/configuration-metadata.html#appendix.configuration-metadata) |
+| --- | --- |
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/features.html#features.external-config.typesafe-configuration-properties.third-party-configuration)2.8.5\.
+
+
+
+ʹ `@ConfigurationProperties` עһ֮⣬㻹ڹ `@Bean` ʹ ֮ĵʱرá
+
+
+
+
+
+Ҫ `Environment` һBeanBeanע `@ConfigurationProperties` ʾ
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@Configuration(proxyBeanMethods = false)
+public class ThirdPartyConfiguration {
+
+ @Bean
+ @ConfigurationProperties(prefix = "another")
+ public AnotherComponent anotherComponent() {
+ return new AnotherComponent();
+ }
+
+}
+
+```
+
+
+
+
+
+
+
+κ `another` ǰJavaBeanԶᱻӳ䵽 `AnotherComponent` Beanϣ䷽ʽǰ `SomeProperties` ӡ
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/features.html#features.external-config.typesafe-configuration-properties.relaxed-binding)2.8.6\. ɵİ
+
+
+
+Spring Bootڽ `Environment` `@ConfigurationProperties` beanʱʹһЩɵĹ `Environment` ƺbean֮䲻Ҫȫƥ䡣 ãӰۺŷָƣ磬 `context-path` `contextPath` ʹдƣ磬`PORT` `port`
+
+
+
+
+
+ʾһӣ `@ConfigurationProperties` ࡣ
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@ConfigurationProperties(prefix = "my.main-project.person")
+public class MyPersonProperties {
+
+ private String firstName;
+
+ public String getFirstName() {
+ return this.firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+}
+
+```
+
+
+
+
+
+
+
+ϵĴ˵µƶʹá
+
+
+
+Table 3\. relaxed binding
+| Property | Note |
+| --- | --- |
+| `my.main-project.person.first-name` | Kebab ̺߸ `.properties` `.yml` ļʹá |
+| `my.main-project.person.firstName` | շ |
+| `my.main-project.person.first_name` | »ߣһ `.properties` `.yml` ļʽ |
+| `MY_MAINPROJECT_PERSON_FIRSTNAME` | дʽʹϵͳʱʹôдʽ |
+
+
+
+| | ע `prefix` ֵ __ kebabСд `-` ָ `my.main-project.person` |
+| --- | --- |
+
+
+
+Table 4\. ÿԴĿɰ
+| Դ | | б |
+| --- | --- | --- |
+| Properties ļ | շ, kebab , » | ʹ `[ ]` ŷֵָıб |
+| YAML ļ | շ, kebab , » | YAMLбŷֵָ |
+| | д»Ϊָ( [ӻ](https://springdoc.cn/spring-boot/features.html#features.external-config.typesafe-configuration-properties.relaxed-binding.environment-variables)). | Numeric values surrounded by underscores (see [ӻ](https://springdoc.cn/spring-boot/features.html#features.external-config.typesafe-configuration-properties.relaxed-binding.environment-variables)) |
+| ϵͳԣSystem properties | շ, kebab , » | ʹ `[ ]` ŷֵָıб |
+
+
+
+| | ǽ飬ڿܵ£ӦСдkebabʽ洢 `my.person.first-name=Rod` |
+| --- | --- |
+
+
+
+
+
+##### [](https://springdoc.cn/spring-boot/features.html#features.external-config.typesafe-configuration-properties.relaxed-binding.maps)Map
+
+
+
+ `Map` ʱҪʹһŷţԱ㱣ԭʼ `key` ֵ keyûб `[ ]` κηĸ֡`-` `.` ַɾ
+
+
+
+
+
+磬ǽһ `Map`
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+my.map.[/key1]=value1
+my.map.[/key2]=value2
+my.map./key3=value3
+```
+
+
+
+
+
+
+
+| | YAMLļҪŰʹkeyȷ |
+| --- | --- |
+
+
+
+
+
+Խһ `Map` `/key1``/key2` `key3` Ϊmapkey бѾ `key3` ɾΪûбŰ
+
+
+
+
+
+ֵʱ `.` ļҪ `[]` ֵöٺ `java.lang` еͣ `Object` `a.b=c` `Map` е `.` һ `{"a.b"="c"}` EntryMap κͣ `key` `.` Ҫʹŷš 磬 `a.b=c` `Map` һ `{"a"={"b"="c"}` entryMap `[a.b]=c` һ `{"a.b"="c"}` entry Map
+
+
+
+
+
+
+
+##### [](https://springdoc.cn/spring-boot/features.html#features.external-config.typesafe-configuration-properties.relaxed-binding.environment-variables)ӻ
+
+
+
+磬Linux shellֻܰĸ`a` `z` `A` `Z` ֣ `0` `9` »ַ `_` չUnix shellҲôдĸ
+
+
+
+
+
+Spring BootɵİΪܵЩƼݡ
+
+
+
+
+
+Ҫ淶ʽתΪƣѭЩ
+
+
+
+
+
+* »ߣ`_`滻㣨`.`
+
+* ɾκۺţ`-`
+
+* תΪдĸ
+
+
+
+
+
+磬 `spring.main.log-startup-info` һΪ `SPRING_MAIN_LOGSTARTUPINFO` Ļ
+
+
+
+
+
+ҲڰбListʱʹá Ҫһ `List`ڱУԪرţӦ»߰
+
+
+
+
+
+磬 `my.service[0].other` ʹһΪ `MY_SERVICE_0_OTHER` Ļ
+
+
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/features.html#features.external-config.typesafe-configuration-properties.merging-complex-types)2.8.7\. ϲӵ
+
+
+
+Listڶطʱǵ滻list
+
+
+
+
+
+磬һ `MyPojo` `name` `description` ĬΪ `null` Ӵ `MyProperties` б¶һ `MyPojo` б
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@ConfigurationProperties("my")
+public class MyProperties {
+
+ private final List list = new ArrayList<>();
+
+ public List getList() {
+ return this.list;
+ }
+
+}
+
+```
+
+
+
+
+
+
+
+á
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+my.list[0].name=my name
+my.list[0].description=my description
+#---
+spring.config.activate.on-profile=dev
+my.list[0].name=my another name
+
+```
+
+
+
+
+
+
+
+ `dev` ļδ`MyProperties.list` һ `MyPojo` Ŀ֮ǰ Ȼ `dev` ļ`list` ȻֻһĿname Ϊ `my another name`descriptionΪ `null` òбӵڶ `MyPojo` ʵҲϲĿ
+
+
+
+
+
+һ `List` ڶļбָʱʹþȼǸֻǸ ӡ
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+my.list[0].name=my name
+my.list[0].description=my description
+my.list[1].name=another name
+my.list[1].description=another description
+#---
+spring.config.activate.on-profile=dev
+my.list[0].name=my another name
+
+```
+
+
+
+
+
+
+
+ǰУ `dev` ļǼģ`MyProperties.list` _һ_ `MyPojo` Ŀname `my another name`description `null` YAMLŷָбYAMLбȫбݡ
+
+
+
+
+
+ `Map` ԣôӶԴȡֵа ȻڶԴеͬһԣʹþȼǸ Ӵ `MyProperties` ¶һ `Map`
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@ConfigurationProperties("my")
+public class MyProperties {
+
+ private final Map map = new LinkedHashMap<>();
+
+ public Map getMap() {
+ return this.map;
+ }
+
+}
+
+```
+
+
+
+
+
+
+
+á
+
+
+
+
+
+
+
+Properties
+
+Yaml
+
+
+
+
+
+```
+my.map.key1.name=my name 1
+my.map.key1.description=my description 1
+#---
+spring.config.activate.on-profile=dev
+my.map.key1.name=dev name 1
+my.map.key2.name=dev name 2
+my.map.key2.description=dev description 2
+
+```
+
+
+
+
+
+
+
+ `dev` ļûм`MyProperties.map` һkeyΪ `key1` ĿnameΪ `my name 1` descriptionΪ `my description 1` Ȼ `dev` ļ`map` ĿkeyΪ `key1` nameΪ `dev name 1`descriptionΪ `my description 1` `key2`nameΪ `dev name 2`descriptionΪ `dev description 2`
+
+
+
+
+
+| | ǰĺϲԴԣļ |
+| --- | --- |
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/features.html#features.external-config.typesafe-configuration-properties.conversion)2.8.8\. ԣPropertiesת
+
+
+
+Spring Boot `@ConfigurationProperties` Beanʱͼⲿapplication propertiesǿƸΪȷ͡ ҪԶתṩһ `ConversionService` beanBeanΪ `conversionService` ԶԱ༭ͨ `CustomEditorConfigurer` beanԶ `Converters` Beanʹ `@ConfigurationPropertiesBinding` ע⣩
+
+
+
+
+
+| | BeanӦóڵڱģȷ `ConversionService` ʹõϵ ͨ£Ҫκϵڴʱûȫʼ Զ `ConversionService` Ҫkeys coercionֻ `@ConfigurationPropertiesBinding` Զת |
+| --- | --- |
+
+
+
+
+
+##### [](https://springdoc.cn/spring-boot/features.html#features.external-config.typesafe-configuration-properties.conversion.durations)תΪ Duration
+
+
+
+Spring BootԱʱרŵ֧֡ 㹫һ `java.time.Duration` ԣapplication propertiesе¸ʽͿá
+
+
+
+
+
+* ͨ `long` ʹúΪĬϵλָ `@DurationUnit`
+
+* ISO-8601ʽ [ `java.time.Duration` ʹ](https://docs.oracle.com/javase/17/docs/api/java/time/Duration.html#parse-java.lang.CharSequence-)
+
+* һĸʽֵ͵λϵģ`10s` ʾ10룩
+
+
+
+
+
+뿼ӡ
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@ConfigurationProperties("my")
+public class MyProperties {
+
+ @DurationUnit(ChronoUnit.SECONDS)
+ private Duration sessionTimeout = Duration.ofSeconds(30);
+
+ private Duration readTimeout = Duration.ofMillis(1000);
+
+ // getters / setters...
+
+}
+
+```
+
+
+
+
+
+
+
+Ҫָһ30ĻỰʱ `30` `PT30S` `30s` ǵȼ۵ġ ȡʱΪ500msκһʽָ `500`, `PT0.5S` `500ms`.
+
+
+
+
+
+Ҳʹֵ֧ʱ䵥λ
+
+
+
+
+
+* `ns`
+
+* `us`
+
+* `ms`
+
+* `s`
+
+* `m`
+
+* `h` Сʱ
+
+* `d`
+
+
+
+
+
+ĬϵλǺ룬ʹ `@DurationUnit` дʾ
+
+
+
+
+
+ϲʹù캯ͬԿԱ¶ʾ
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@ConfigurationProperties("my")
+public class MyProperties {
+
+ // fields...
+
+ public MyProperties(@DurationUnit(ChronoUnit.SECONDS) @DefaultValue("30s") Duration sessionTimeout,
+ @DefaultValue("1000ms") Duration readTimeout) {
+ this.sessionTimeout = sessionTimeout;
+ this.readTimeout = readTimeout;
+ }
+
+ // getters...
+
+}
+
+```
+
+
+
+
+
+
+
+| | Ҫһ `Long` ԣǺ룬ȷ嵥λʹ `@DurationUnit` ṩһ·ͬʱָ֧ḻĸʽ |
+| --- | --- |
+
+
+
+
+
+
+
+##### [](https://springdoc.cn/spring-boot/features.html#features.external-config.typesafe-configuration-properties.conversion.periods)תΪڼ䣨Period
+
+
+
+durationSpring Bootʹ `java.time.Period` ͡ ¸ʽapplication propertiesʹá
+
+
+
+
+
+* һ `int` ʾʹΪĬϵλָ `@PeriodUnit`
+
+* ISO-8601ʽ [ `java.time.Period` ʹ](https://docs.oracle.com/javase/17/docs/api/java/time/Period.html#parse-java.lang.CharSequence-)
+
+* һĸʽֵ͵λϵģ `1y3d` ʾ13죩
+
+
+
+
+
+֧мĵλʽ
+
+
+
+
+
+* `y`
+
+* `m`
+
+* `w`
+
+* `d`
+
+
+
+
+
+| | `java.time.Period` ʵϴδ洢һݷʽζ 7족 |
+| --- | --- |
+
+
+
+
+
+
+
+##### [](https://springdoc.cn/spring-boot/features.html#features.external-config.typesafe-configuration-properties.conversion.data-sizes)תΪݴСData Sizes
+
+
+
+Spring Frameworkһ `DataSize` ֵֽͣΪλС 㹫һ `DataSize` ԣapplication propertiesе¸ʽͿá
+
+
+
+
+
+* һ `long` ʾʹֽΪĬϵλָ `@DataSizeUnit`
+
+* һĸʽֵ͵λϵģ`10MB` ζ10ֽڣ
+
+
+
+
+
+ӡ
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@ConfigurationProperties("my")
+public class MyProperties {
+
+ @DataSizeUnit(DataUnit.MEGABYTES)
+ private DataSize bufferSize = DataSize.ofMegabytes(2);
+
+ private DataSize sizeThreshold = DataSize.ofBytes(512);
+
+ // getters/setters...
+
+}
+
+```
+
+
+
+
+
+
+
+Ҫָһ10ֽڣMbĻС `10` `10MB` ǵȼ۵ġ 256ֽڵĴСֵָΪ `256` `256B`
+
+
+
+
+
+ҲʹЩֵ֧ĵλ
+
+
+
+
+
+* `B` ֽ
+
+* `KB` KB
+
+* `MB` MB
+
+* `GB` GB
+
+* `TB` TB
+
+
+
+
+
+Ĭϵλֽڣʹ `@DataSizeUnit` дʾ
+
+
+
+
+
+ϲʹù캯ͬԿԱ¶ʾ
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@ConfigurationProperties("my")
+public class MyProperties {
+
+ // fields...
+
+ public MyProperties(@DataSizeUnit(DataUnit.MEGABYTES) @DefaultValue("2MB") DataSize bufferSize,
+ @DefaultValue("512B") DataSize sizeThreshold) {
+ this.bufferSize = bufferSize;
+ this.sizeThreshold = sizeThreshold;
+ }
+
+ // getters...
+
+}
+
+```
+
+
+
+
+
+
+
+| | һ `Long` ԣȷ嵥λʹ `@DataSizeUnit`ֽڡ ṩһ·ͬʱָ֧ḻĸʽ |
+| --- | --- |
+
+
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/features.html#features.external-config.typesafe-configuration-properties.validation)2.8.9\. @ConfigurationProperties У
+
+
+
+ֻҪʹSpring `@Validated` ע⣬Spring Bootͻ᳢֤ `@ConfigurationProperties` ࡣ ֱʹJSR-303 `jakarta.validation` Լע⡣ Ҫһ㣬ȷclasspathһݵJSR-303ʵ֣ȻԼעӵֶУʾ
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@ConfigurationProperties("my.service")
+@Validated
+public class MyProperties {
+
+ @NotNull
+ private InetAddress remoteAddress;
+
+ // getters/setters...
+
+}
+
+```
+
+
+
+
+
+
+
+| | Ҳͨ configuration properties `@Bean` ע `@Validated` ֤ |
+| --- | --- |
+
+
+
+
+
+ΪȷΪǶԴ֤ʹûҵԣصֶα `@Valid` ע͡ ӽǰ `MyProperties` Ļϡ
+
+
+
+
+
+
+
+Java
+
+Kotlin
+
+
+
+
+
+```
+@ConfigurationProperties("my.service")
+@Validated
+public class MyProperties {
+
+ @NotNull
+ private InetAddress remoteAddress;
+
+ @Valid
+ private final Security security = new Security();
+
+ // getters/setters...
+
+ public static class Security {
+
+ @NotEmpty
+ private String username;
+
+ // getters/setters...
+
+ }
+
+}
+
+```
+
+
+
+
+
+
+
+ҲͨһΪ `configurationPropertiesValidator` beanһԶSpring `Validator` `@Bean` ӦñΪ `static` ֤Ӧóڵڴģ `@Bean` Ϊ̬BeanĴҪʵ `@Configuration` ࡣ Աʵκ⡣
+
+
+
+
+
+| | `spring-boot-actuator` ģһ¶ `@ConfigurationProperties` Bean Ķ˵㡣 ͨ `/actuator/configprops` ʹӦJMX˵㡣 "[](https://springdoc.cn/spring-boot/actuator.html#actuator.endpoints)"֡ |
+| --- | --- |
+
+
+
+
+
+
+
+#### [](https://springdoc.cn/spring-boot/features.html#features.external-config.typesafe-configuration-properties.vs-value-annotation)2.8.10\. @ConfigurationProperties vs. @Value
+
+
+
+`@Value` עһĵܣṩͰȫͬĹܡ ±ܽ `@ConfigurationProperties` `@Value` ֵ֧Ĺܡ
+
+
+
+
+| | `@ConfigurationProperties` | `@Value` |
+| --- | --- | --- |
+| [ɰ](https://springdoc.cn/spring-boot/features.html#features.external-config.typesafe-configuration-properties.relaxed-binding) | Yes | ( [ע](https://springdoc.cn/spring-boot/features.html#features.external-config.typesafe-configuration-properties.vs-value-annotation.note)) |
+| [֧ Meta-data](https://springdoc.cn/spring-boot/configuration-metadata.html#appendix.configuration-metadata) | Yes | No |
+| `SpEL` ʽ | No | Yes |
+
+
+
+| | ȷʵʹ `@Value`ǽʹƵĹ淶ʽʹСдĸkebab-caseơ ⽫Spring Bootʹ [ɰ](https://springdoc.cn/spring-boot/features.html#features.external-config.typesafe-configuration-properties.relaxed-binding) `@ConfigurationProperties` ʱͬ磬`@Value("${demo.item-price}")` `application.properties` ļлȡ `demo.item-price` `demo.itemPrice` ʽԼϵͳлȡ `DEMO_ITEMPRICE` `@Value("${demo.itemPrice}")` 棬`demo.item-price` `DEMO_ITEMPRICE` ᱻǡ |
+| --- | --- |
+
+
+
+
+
+ΪԼһüǽ㽫Ƿһ `@ConfigurationProperties` עPOJOС ΪṩṹġͰȫĶԽע뵽ԼbeanС
+
+
+
+
+
+Ӧ[application property](https://springdoc.cn/spring-boot/features.html#features.external-config.files) ļ `SpEL` ʽڽЩļenvironmentʱᱻ Ȼ `@Value` дһ `SpEL` ʽ Ӧóļֵһ `SpEL` ʽڱ `@Value` ʱ
+
+
+
+
+
+
+
+
+
+
+
+
+
+## [](https://springdoc.cn/spring-boot/features.html#features.profiles)
+
diff --git "a/docs/spring/SpringBoot/SpringBoot\350\207\252\345\270\246\347\232\204\347\203\255\351\203\250\347\275\262\345\267\245\345\205\267.md" "b/docs/spring/SpringBoot/SpringBoot\350\207\252\345\270\246\347\232\204\347\203\255\351\203\250\347\275\262\345\267\245\345\205\267.md"
new file mode 100644
index 0000000..477370a
--- /dev/null
+++ "b/docs/spring/SpringBoot/SpringBoot\350\207\252\345\270\246\347\232\204\347\203\255\351\203\250\347\275\262\345\267\245\345\205\267.md"
@@ -0,0 +1,345 @@
+# SpringBoot - Ȳdevtools
+
+> SpringBootУÿдĶҪٵԣܱȽϷʱ䣻SpringBootŶԴṩspring-boot-devtoolsdevtoolsͼԵЧʡ@pdai
+
+* [SpringBoot - Ȳdevtools](#springboot%E5%85%A5%E9%97%A8---%E9%85%8D%E7%BD%AE%E7%83%AD%E9%83%A8%E7%BD%B2devtools%E5%B7%A5%E5%85%B7)
+ * [֪ʶ](#%E5%87%86%E5%A4%87%E7%9F%A5%E8%AF%86%E7%82%B9)
+ * [ʲôȲȼأ](#%E4%BB%80%E4%B9%88%E6%98%AF%E7%83%AD%E9%83%A8%E7%BD%B2%E5%92%8C%E7%83%AD%E5%8A%A0%E8%BD%BD)
+ * [ʲôLiveLoad](#%E4%BB%80%E4%B9%88%E6%98%AFliveload)
+ * [devtoolsʵȲ](#%E9%85%8D%E7%BD%AEdevtools%E5%AE%9E%E7%8E%B0%E7%83%AD%E9%83%A8%E7%BD%B2)
+ * [POM](#pom%E9%85%8D%E7%BD%AE)
+ * [IDEA](#idea%E9%85%8D%E7%BD%AE)
+ * [application.yml](#applicationyml%E9%85%8D%E7%BD%AE)
+ * [ʹLiveLoad](#%E4%BD%BF%E7%94%A8liveload)
+ * [һ](#%E8%BF%9B%E4%B8%80%E6%AD%A5%E7%90%86%E8%A7%A3)
+ * [devtoolԭΪλԶ](#devtool%E7%9A%84%E5%8E%9F%E7%90%86%E4%B8%BA%E4%BD%95%E4%BC%9A%E8%87%AA%E5%8A%A8%E9%87%8D%E5%90%AF)
+ * [devtoolǷᱻJar](#devtool%E6%98%AF%E5%90%A6%E4%BC%9A%E8%A2%AB%E6%89%93%E5%8C%85%E8%BF%9Bjar)
+ * [devtoolΪλĬϽûѡ](#devtool%E4%B8%BA%E4%BD%95%E4%BC%9A%E9%BB%98%E8%AE%A4%E7%A6%81%E7%94%A8%E7%BC%93%E5%AD%98%E9%80%89%E9%A1%B9)
+ * [devtoolǷԸSpringbootӦȫֵã](#devtool%E6%98%AF%E5%90%A6%E5%8F%AF%E4%BB%A5%E7%BB%99%E6%89%80%E6%9C%89springboot%E5%BA%94%E7%94%A8%E5%81%9A%E5%85%A8%E5%B1%80%E7%9A%84%E9%85%8D%E7%BD%AE)
+ * [Ҳdevtoolʲôѡ](#%E5%A6%82%E6%9E%9C%E6%88%91%E4%B8%8D%E7%94%A8devtool%E8%BF%98%E6%9C%89%E4%BB%80%E4%B9%88%E9%80%89%E6%8B%A9)
+ * [ʾԴ](#%E7%A4%BA%E4%BE%8B%E6%BA%90%E7%A0%81)
+ * [ο](#%E5%8F%82%E8%80%83%E6%96%87%E7%AB%A0)
+
+## [#](#֪ʶ) ֪ʶ
+
+### [#](#ʲôȲȼ) ʲôȲȼأ
+
+> ȲȼӦеʱԶ£¼ػ滻classȣӦõһPSspring-boot-devtoolsṩķҲҪģֶֻʵԶضѡ
+
+ϸϣҪȲȼ, JavaĿԣ
+
+* **Ȳ**
+
+ * ڷʱ²Ŀ
+ * ֱ¼Ӧãַʽͷڴ棬ȼظӸɾףͬʱҲʱ䡣
+* **ȼ**
+
+ * ʱ¼classӶӦá
+ * ȼصʵԭҪ[javaػ](/md/java/jvm/java-jvm-classload.html)ʵַʽԸΪʱһ̨̣߳ʱļļʱ仯ʱˣ롣
+ * ԱȷƣʱȡϢ̬ͨĵıΪ ȼʱͨ¼ظıϢֱӸıΪ
+
+### [#](#ʲôliveload) ʲôLiveLoad
+
+LiveLoadṩͻԶظµĹߣΪLiveLoadLiveload֣ devtoolsѾLiveLoadǿwebӦãԶˢ£ ʱԿLiveLoad.
+
+
+
+ͬһʱֻһLiveReload ʼӦó֮ǰȷûLiveReloadСIDEӦóֻеһӦó֧LiveReload
+
+## [#](#devtoolsʵȲ) devtoolsʵȲ
+
+> ͨʵԶʽȲ
+
+### [#](#pom) POM
+
+spring-boot-devtools
+
+
+
+```
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ true
+
+
+
+```
+
+
+
+### [#](#idea) IDEA
+
+> ʹIDEAߣַͨʽ
+
+* ʽһ **κʱֶ£Ctrl+F9**
+
+
+Ҳ`mvn compile`봥£
+
+* ʽ **IDEA迪ʱ룬Զ**
+
+**1**
+
+File->Setting->Build,Execution,Deployment->Compile
+
+ѡMake project automatically
+
+
+
+**2**
+
+ݼctrl+alt+shift+/
+
+ѡRegistry
+
+ѡcompiler.automake.allow.when.app.running
+
+°汾IDEAFile->setting->Advanced Setttingsĵһã
+
+
+### [#](#application-yml) application.yml
+
+
+
+```
+spring:
+ devtools:
+ restart:
+ enabled: true #ÿȲ
+ additional-paths: src/main/java #Ŀ¼
+ exclude: WEB-INF/**
+ thymeleaf:
+ cache: false #ʹThymeleafģ棬رջ
+
+```
+
+
+
+### [#](#ʹliveload) ʹLiveLoad
+
+spring-boot-devtoolsģ**ǶʽLiveReload**Դʱڴˢ¡ LiveReloadչ֧ChromeFirefoxSafariԴlivereload.comء
+
+
+ߴأfirefox:
+
+
+
+װ֮ͨͼ
+
+
+
+㲻ӦóʱLiveReloadԽspring.devtools.livereload.enabledΪfalse
+
+ͬһʱֻһLiveReload ʼӦó֮ǰȷûLiveReloadСIDEӦóֻеһӦó֧LiveReload
+
+## [#](#һ) һ
+
+> ȻһЩʹdevtoolߣǺܹģ¼⣬һ⡣@pdai
+
+### [#](#devtoolԭ-ΪλԶ) devtoolԭΪλԶ
+
+> ΪʲôͬӦãΪʲôֶǽʹspring-boot-devtoolsȲ
+
+spring-boot-devtoolsʹClassLoaderһClassLoaderزᷢĵࣨjarһClassLoaderrestart ClassLoaderػĵࣨԶࣩ
+
+̨һ**ļ̣߳File Watcher****Ŀ¼еļ䶯ʱ ԭrestart ClassLoader¼µrestart ClassLoader**
+
+Ϊļ䶯jar¼أֻԶ࣬صȽ٣ȽϿ졣
+
+ҲΪʲôͬӦãΪʲôֶʹspring-boot-devtoolsȲ
+
+ԶмҪע:
+
+* **Զ¼־**
+
+¼ʲô־
+
+ͨ¹ر
+
+
+
+```
+spring:
+ devtools:
+ restart:
+ log-condition-evaluation-delta: false
+
+```
+
+
+
+* **ųһЩҪԶԴ**
+
+ijЩԴڸʱһҪĬ£ıԴ/META-INF/maven/META-INF/resources/resources/static/public/templatesȷᴥֳװҪԶЩųʹøspring.devtools.restart.excludeԡ磬Ҫų/static/public㽫ԣ
+
+
+
+```
+spring:
+ devtools:
+ restart:
+ exclude: "static/**,public/**"
+
+```
+
+
+
+ҪЩĬֵųøspring.devtools.restart.additional-excludeԡ
+
+* **Զ**
+
+ͨʹʵֵġڴӦóַЧܺáǣʱᵼ⡣
+
+Ĭ£IDE еκδĿʹáأκγ.jarļʹáء㴦һģĿҲÿģ鶼뵽 IDE УҪԶһЩΪˣԴһMETA-INF/spring-devtools.propertiesļ
+
+spring-devtools.propertiesļrestart.excludeΪǰrestart.includeincludeԪӦñߵĿԼexcludeҪӦ롰BaseĿԵֵӦ·ʽģʽʾʾ
+
+
+
+```
+restart:
+ exclude:
+ companycommonlibs: "/mycorp-common-[\\w\\d-\\.]+\\.jar"
+ include:
+ projectcommon: "/mycorp-myproj-[\\w\\d-\\.]+\\.jar"
+
+```
+
+
+
+صϢ[´ڴ](https://docs.spring.io/spring-boot/docs/current/reference/html/using.html#using.devtools)鿴
+
+### [#](#devtoolǷᱻjar) devtoolǷᱻJar
+
+> devtoolԭ˵ӦֻڿԵʱʹãjarʱDzҪģSpringJAR
+
+* **Ĭ£ᱻJAR**
+
+дӦóʱԱ**Զ**ͨ java -jarʱᱻΪǡӦá
+
+* **Զ̵Ӧ**
+
+_ãֻεлʹ SSL бʱӦ_
+
+£devtoolҲ߱Զ̵ԵԶ̿ͻӦóּڴ IDE СҪorg.springframework.boot.devtools.RemoteSpringApplicationʹӵԶĿͬ·СӦóΨһӵԶ URL
+
+磬ʹ Eclipse Spring Toolsһmy-appѲ Cloud Foundry ΪĿִ²
+
+1. ѡRun Configurations?Run˵
+2. һµJava Applicationá
+3. my-appĿ
+4. ʹorg.springframework.boot.devtools.RemoteSpringApplicationΪࡣ
+5. https://myapp.cfapps.ioProgram argumentsκԶ URL
+
+еԶ̿ͻ˿б
+
+
+
+```
+ . ____ _ __ _ _
+ /\\ / ___'_ __ _ _(_)_ __ __ _ ___ _ \ \ \ \
+( ( )\___ | '_ | '_| | '_ \/ _` | | _ \___ _ __ ___| |_ ___ \ \ \ \
+ \\/ ___)| |_)| | | | | || (_| []::::::[] / -_) ' \/ _ \ _/ -_) ) ) ) )
+ ' |____| .__|_| |_|_| |_\__, | |_|_\___|_|_|_\___/\__\___|/ / / /
+ =========|_|==============|___/===================================/_/_/_/
+ :: Spring Boot Remote :: 2.5.4
+
+2015-06-10 18:25:06.632 INFO 14938 --- [ main] o.s.b.devtools.RemoteSpringApplication : Starting RemoteSpringApplication on pwmbp with PID 14938 (/Users/pwebb/projects/spring-boot/code/spring-boot-project/spring-boot-devtools/target/classes started by pwebb in /Users/pwebb/projects/spring-boot/code)
+2015-06-10 18:25:06.671 INFO 14938 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2a17b7b6: startup date [Wed Jun 10 18:25:06 PDT 2015]; root of context hierarchy
+2015-06-10 18:25:07.043 WARN 14938 --- [ main] o.s.b.d.r.c.RemoteClientConfiguration : The connection to http://localhost:8080 is insecure. You should use a URL starting with 'https://'.
+2015-06-10 18:25:07.074 INFO 14938 --- [ main] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
+2015-06-10 18:25:07.130 INFO 14938 --- [ main] o.s.b.devtools.RemoteSpringApplication : Started RemoteSpringApplication in 0.74 seconds (JVM running for 1.105)
+
+```
+
+
+
+### [#](#devtoolΪλĬϽûѡ) devtoolΪλĬϽûѡ
+
+> Spring Boot ֵ֧һЩ**ʹû**磬ģ滺ѱģԱظģļ⣬Spring MVC ṩ̬ԴʱӦ HTTP ͷ
+
+Ȼ**зdz棬ڿпܻʵ䷴**ʹոӦóĸġԭ spring-boot-devtools ĬϽûѡ
+
+Thymeleaf ṩspring.thymeleaf.cacheģĻ棬ʹspring-boot-devtoolsģʱDzҪֶЩԵģΪspring-boot-devtoolsԶá
+
+ôԶЩأDevToolsPropertyDefaultsPostProcessorҵӦĬá
+
+
+
+```
+public class DevToolsPropertyDefaultsPostProcessor implements EnvironmentPostProcessor {
+
+ static {
+ Map properties = new HashMap<>();
+ properties.put("spring.thymeleaf.cache", "false");
+ properties.put("spring.freemarker.cache", "false");
+ properties.put("spring.groovy.template.cache", "false");
+ properties.put("spring.mustache.cache", "false");
+ properties.put("server.servlet.session.persistent", "true");
+ properties.put("spring.h2.console.enabled", "true");
+ properties.put("spring.web.resources.cache.period", "0");
+ properties.put("spring.web.resources.chain.cache", "false");
+ properties.put("spring.template.provider.cache", "false");
+ properties.put("spring.mvc.log-resolved-exception", "true");
+ properties.put("server.error.include-binding-errors", "ALWAYS");
+ properties.put("server.error.include-message", "ALWAYS");
+ properties.put("server.error.include-stacktrace", "ALWAYS");
+ properties.put("server.servlet.jsp.init-parameters.development", "true");
+ properties.put("spring.reactor.debug", "true");
+ PROPERTIES = Collections.unmodifiableMap(properties);
+ }
+
+```
+
+
+
+Ȼ㲻뱻ӦԱspring-boot-devtoolsĬã ͨspring.devtools.add-propertiesfalseapplication.ymlС
+
+### [#](#devtoolǷԸspringbootӦȫֵ) devtoolǷԸSpringbootӦȫֵã
+
+> ͨspring-boot-devtools.ymlļӵ$HOME/.config/spring-bootĿ¼**ȫ devtools **
+
+ӵЩļκԶʹ devtools Spring Boot Ӧó磬ҪΪʼʹôļҪӵspring-boot-devtoolsļУ
+
+
+
+```
+spring:
+ devtools:
+ restart:
+ trigger-file: ".reloadtrigger"
+
+```
+
+
+
+### [#](#Ҳdevtool-ʲôѡ) Ҳdevtoolʲôѡ
+
+> Ҳdevtoolʲôѡ
+
+**ʵʵĿУҲȥʹdevtool**, Ϊ
+
+* devtoolʽȻ滻JRebelǣշѵģ
+* ҪĻһȨ
+ * ԶĿֶûʲô̫ôֶ
+ * £**ڲĻ߾̬Դ**IDEAǿͨRebuildCtrl + Shift + F9ȸ
+
+
+
+* һspring loaded ʵļȲ𣬾ɿ[githubַ´ڴ](https://github.com/spring-projects/spring-loaded)ϵ˵
+
+## [#](#ʾԴ) ʾԴ
+
+https://github.com/realpdai/tech-pdai-spring-demos
+
+## [#](#ο) ο
+
+https://docs.spring.io/spring-boot/docs/current/reference/html/using.html#using.devtools
+
+https://liayun.blog.csdn.net/article/details/116541775
+
+* * *
+
+Ȩ@pdai ԭӣhttps://pdai.tech/md/spring/springboot/springboot-x-hello-devtool.html
\ No newline at end of file
diff --git "a/docs/spring/SpringBoot/SpringBoot\351\233\206\346\210\220Swagger\345\256\236\347\216\260API\346\226\207\346\241\243\350\207\252\345\212\250\347\224\237\346\210\220.md" "b/docs/spring/SpringBoot/SpringBoot\351\233\206\346\210\220Swagger\345\256\236\347\216\260API\346\226\207\346\241\243\350\207\252\345\212\250\347\224\237\346\210\220.md"
new file mode 100644
index 0000000..e225d74
--- /dev/null
+++ "b/docs/spring/SpringBoot/SpringBoot\351\233\206\346\210\220Swagger\345\256\236\347\216\260API\346\226\207\346\241\243\350\207\252\345\212\250\347\224\237\346\210\220.md"
@@ -0,0 +1,625 @@
+
+
+Ŀ¼
+
+* [SwaggerĽ](https://www.cnblogs.com/progor/p/13297904.html#swagger%E7%9A%84%E4%BB%8B%E7%BB%8D)
+ * [ŵȱ](https://www.cnblogs.com/progor/p/13297904.html#%E4%BC%98%E7%82%B9%E4%B8%8E%E7%BC%BA%E7%82%B9)
+* [swagger](https://www.cnblogs.com/progor/p/13297904.html#%E6%B7%BB%E5%8A%A0swagger)
+ * [1.](https://www.cnblogs.com/progor/p/13297904.html#1%E6%B7%BB%E5%8A%A0%E4%BE%9D%E8%B5%96%E5%8C%85)
+ * [2.Swagger:](https://www.cnblogs.com/progor/p/13297904.html#2%E9%85%8D%E7%BD%AEswagger)
+ * [3.](https://www.cnblogs.com/progor/p/13297904.html#3%E6%B5%8B%E8%AF%95)
+* [](https://www.cnblogs.com/progor/p/13297904.html#%E5%9C%BA%E6%99%AF)
+ * [ӿ](https://www.cnblogs.com/progor/p/13297904.html#%E5%AE%9A%E4%B9%89%E6%8E%A5%E5%8F%A3%E7%BB%84)
+ * [ӿ](https://www.cnblogs.com/progor/p/13297904.html#%E5%AE%9A%E4%B9%89%E6%8E%A5%E5%8F%A3)
+ * [ӿ](https://www.cnblogs.com/progor/p/13297904.html#%E5%AE%9A%E4%B9%89%E6%8E%A5%E5%8F%A3%E8%AF%B7%E6%B1%82%E5%8F%82%E6%95%B0)
+ * [һʵࡣ](https://www.cnblogs.com/progor/p/13297904.html#%E5%9C%BA%E6%99%AF%E4%B8%80%E8%AF%B7%E6%B1%82%E5%8F%82%E6%95%B0%E6%98%AF%E5%AE%9E%E4%BD%93%E7%B1%BB)
+ * [Ƿʵࡣ](https://www.cnblogs.com/progor/p/13297904.html#%E5%9C%BA%E6%99%AF%E4%BA%8C%E8%AF%B7%E6%B1%82%E5%8F%82%E6%95%B0%E6%98%AF%E9%9D%9E%E5%AE%9E%E4%BD%93%E7%B1%BB)
+ * [ӿӦ](https://www.cnblogs.com/progor/p/13297904.html#%E5%AE%9A%E4%B9%89%E6%8E%A5%E5%8F%A3%E5%93%8D%E5%BA%94)
+ * [Ӧʵࣺ](https://www.cnblogs.com/progor/p/13297904.html#%E5%93%8D%E5%BA%94%E6%98%AF%E5%AE%9E%E4%BD%93%E7%B1%BB)
+ * [ӦǷʵࣺ](https://www.cnblogs.com/progor/p/13297904.html#%E5%93%8D%E5%BA%94%E6%98%AF%E9%9D%9E%E5%AE%9E%E4%BD%93%E7%B1%BB)
+* [Swagger UIǿ](https://www.cnblogs.com/progor/p/13297904.html#swagger-ui%E5%A2%9E%E5%BC%BA)
+ * [UIԱȣ](https://www.cnblogs.com/progor/p/13297904.html#ui%E5%AF%B9%E6%AF%94)
+ * [ʹ](https://www.cnblogs.com/progor/p/13297904.html#%E4%BD%BF%E7%94%A8)
+ * [ŵ](https://www.cnblogs.com/progor/p/13297904.html#%E4%BC%98%E7%82%B9)
+* [Spring Securityע](https://www.cnblogs.com/progor/p/13297904.html#%E6%95%B4%E5%90%88spring-security%E6%B3%A8%E6%84%8F)
+* [tokenĴ](https://www.cnblogs.com/progor/p/13297904.html#%E5%AF%B9%E4%BA%8Etoken%E7%9A%84%E5%A4%84%E7%90%86)
+* [Swaggerİȫ](https://www.cnblogs.com/progor/p/13297904.html#swagger%E7%9A%84%E5%AE%89%E5%85%A8%E7%AE%A1%E7%90%86)
+
+
+
+* * *
+
+# SwaggerĽ
+
+?ܳԹдһӿںԼȥӿĵĽӿںĽӿĵ֮϶ᷢһǾĵߴĵǹ˾ѽӿĵдӿҪúܽ?дĵͿ۹ʣĹп©ģswaggerһдӿڵʱԶɽӿĵĶֻҪѭĹ淶дһЩӿڵ˵ע⼴ɡ
+
+## ŵȱ
+
+?ŵ㣺
+
+* ԶĵֻҪڽӿʹעбעɶӦĽӿĵ
+* ԶĵǶ̬ɵģ˽ӿڣĵҲԶӦģҲעĻͲᷢ˽ӿڣȴǸ½ӿĵ
+* ֧ߵԣswaggerṩߵýӿڵĹܡ
+
+?ȱ㣺
+
+* ܴʱܰ㴦е顣ֻṩһߵԣ洢IJʹPostmanYAPIִ֧ûĹܡ
+* ҪѭһЩ淶淶ġ˵ܻ᷵һjsonݣݿһMapʽģôǴʱܱעMapʽķݵÿֶε˵һʵĻǿͨעֶμ˵Ҳ˵swaggerƼʹGETʽύݵʱʹBodyƼʹqueryheader·Ȼֻߵԡ
+* ûнӿĵ¹Ȼһӿڸ֮ܲľɰĽӿϢ㡰ܡ뿴ɰĽӿϢЩҶȸ·ʱܻľɰĽӿڡôʱֻɺȥûעˣԿԿǽӿĵµʱע;ɰģȻд°ġȻͨӿĵԱȡ
+* ȻJavaʵвģͣpo,dto,voȣģ͵ΪһЩһû¼ʱֻҪusername,passwordȨʱҪȨޱϢʹUserʵĻĵоͻԶ˶ϢҪģʵ࣬¼ʱһLoginFormҪû-ȨϢʱʹUserࡣȻˣswagger֮ʹžͻôˡ
+
+?ȱдеܻ࣬swaggerеʵҪǹ淶⣬淶ʱֻĴ淶ԣͼʼˣǰʲôӿڵIJʹһ࣬swaggerҪֿijֲĴ淶ԡ
+
+?ע´ʾSpring BootԲο[swagger-demo](https://github.com/alprogor/swagger-demo)
+
+* * *
+
+# swagger
+
+?ȽswaggerҲϽôʹãġٽ⡣
+
+## 1.
+
+?ע⣬ǰѾspring bootweb
+
+ƴ
+
+```
+
+ io.springfox
+ springfox-swagger2
+ 2.9.2
+
+
+ io.springfox
+ springfox-swagger-ui
+ 2.9.2
+
+
+```
+
+## 2.Swagger:
+
+ҪʹswaggerDZswaggerãҪһswagger࣬ΪSwaggerConfig.java
+
+ƴ
+
+```
+package com.example.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+@Configuration //
+@EnableSwagger2 //swagger
+public class SwaggerConfig {
+ @Bean
+ public Docket createRestApi() {
+ return new Docket(DocumentationType.SWAGGER_2) // DocumentationType.SWAGGER_2 ̶ģswagger2
+// .groupName("ֲʽϵͳ") // öĵʱôҪgroupNameʶ
+ .apiInfo(apiInfo()) // APIϢ
+ .select() // select()һApiSelectorBuilderʵ,ƽӿڱswaggerĵ
+ .apis(RequestHandlerSelectors.basePackage("com.example.controller")) // ָɨĸµĽӿ
+ .paths(PathSelectors.any())// ѡеAPI,ֻΪAPIĵ
+ .build();
+ }
+
+ /**
+ * ڶAPIϢеAPIܱ⡢汾
+ * @return
+ */
+ private ApiInfo apiInfo() {
+ return new ApiInfoBuilder()
+ .title("XXĿAPI") // ԶAPI
+ .description("XXĿSwaggerAPI") // API
+ .termsOfServiceUrl("") // ڶ
+ .version("1.0") // 汾
+ .build(); //
+ }
+}
+
+```
+
+## 3.
+
+ǵSpring BootĿĬ8080˿ڣ㲻һעĺurl`http://localhost:8080/swagger-ui.html`
+ȻͿԿһµĽ棬ʱûýӿݣʾ`No operations defined in spec!`
+
+
+
+?ǽζӿڣԼswagger UIеݡ
+
+* * *
+
+#
+
+## ӿ
+
+ӿʱӦǷģҴֶһcontrollerеģûصĽӿӦöUserControllerУôͬҵʱӦö/ֲͬĽӿ顣ӿʹ`@Api`֡
+磺
+
+ƴ
+
+```
+@Api(tags = "ɫ") // tagsԵ֡
+@RestController
+public class RoleController {
+}
+
+```
+
+
+
+ƴ
+
+```
+@Api(tags = "û") // tagsԵ֡
+@RestController
+public class UserController {
+}
+
+```
+
+?Ҳɻtags飬ͺһЩıǩһʹñǩࡣ
+?Controller£ӿ飩ûнӿڣôswagger uiDzʾģеĻͻʾ
+
+
+## ӿ
+
+ʹ`@Api`עһController֮нӿڣôͻĬĵûԶ˵
+
+ƴ
+
+```
+@Api(tags = "û")
+@RestController
+public class UserController {
+ // ע⣬swaggerҪʹ@RequestMapping
+ // Ϊ@RequestMapping֧ʽswaggerΪӿ7ʽĽӿĵ
+ @GetMapping("/info")
+ public String info(String id){
+ return "aaa";
+ }
+}
+
+```
+
+
+
+
+
+ǿʹ`@ApiOperation`ӿڣ磺
+
+ƴ
+
+```
+ @ApiOperation(value = "û",notes = "ûnotes")
+ @GetMapping("/test")
+ public String test(String id){
+ return "test";
+ }
+
+```
+
+
+
+
+* valueԵǽӿڵļ
+* notesӿڵ
+* tagsԶⶨӿ飬ӿѾ`@Api(tags = "û")`ӿڻֵˡûУԶʹtags`tags = "ɫ"`ýɫҲӿĵ
+
+## ӿ
+
+ʹ`@ApiOperation`ӿڣʵȱٽӿ˵Ƿֳ
+?עһ£**GETʽswaggerƼʹbodyʽ**ҲDzϣGETʽʱʹjsonform-dataȷʽݣʱʹ·url(?ȻPOSTMANֵ֧)ӿڴݵjsonform-dataʽģʹPOSTʽá
+
+### һʵࡣ
+
+ʱҪʹ`@ApiModel`עʵ࣬ȻڽӿжΪʵ༴ɣ
+
+* @ApiModel
+ *
+ * valueʵ
+ * descriptionʵ˵
+* @ApiModelPropertyֶε塣
+ *
+ * valueֶ˵
+ * exampleʾExample ValueĬֵãֶΪstringʱʱʾĬֵΪ"".
+ * nameµֶɵֶ
+ * allowableValuesֵ÷Χ`{1,2,3}`ֻȡֵ`[1,5]`ȡ15ֵ`(1,5)`15ֵ15ʹinfinity-infinityֵ`[1, infinity]`СֵΪ1ֵ
+ * requiredֶǷĬfalse,
+ * hiddenֶΣĬfalseҪҪʹtrueΪֶĬ϶ʾû`@ApiModelProperty`
+
+ƴ
+
+```
+// ʹ@ApiModelע
+@ApiModel(value="û¼",description="û¼")
+public class LoginForm {
+ // ʹApiModelPropertyעֶԡ
+ @ApiModelProperty(value = "û",required = true,example = "root")
+ private String username;
+ @ApiModelProperty(value = "",required = true,example = "123456")
+ private String password;
+
+ // ˴ʡθֵʱҪgetter,setter,swaggerҲҪ
+}
+
+```
+
+Σ
+
+ƴ
+
+```
+ @ApiOperation(value = "¼ӿ",notes = "¼ӿڵ˵")
+ @PostMapping("/login")
+ public LoginForm login(@RequestBody LoginForm loginForm){
+ return loginForm;
+ }
+
+```
+
+Ч
+
+
+
+### Ƿʵࡣ
+
+**˵һΣGETʽswaggerƼʹbodyʽݣȻSpring MVCԶװGETDzҪʹform-datajsonȷʽݲʹPostmanԽӿڣswagger߲Dz֧**
+ڷʵʹ`@ApiImplicitParams``@ApiImplicitParam`
+`@ApiImplicitParams`ڷͷϣ`@ApiImplicitParam``@ApiImplicitParams`棬һ`@ApiImplicitParam`Ӧһ
+`@ApiImplicitParam`
+
+* name֣Ҳֶε,ӿڵӦ**ӦҲɣԿ**
+* value
+* requiredעǷ
+* paramTypepath,query,body,form,headerȷʽڶڷʵʱõֻpath,query,headerbodyformDzõġbodyڶɢֻjsonĽӿ`form-data`,`x-www-form-urlencoded`ʱܲʹswaggerҳAPIԣں潲BootstrapUIswaggerǿеԣBootstrapUIswaggerָ֧`form-data``x-www-form-urlencoded`
+
+ʾһURL
+
+ƴ
+
+```
+ // ʹURL query
+ @ApiOperation(value = "¼ӿ2",notes = "¼ӿڵ˵2")
+ @ApiImplicitParams({
+ @ApiImplicitParam(name = "username",//
+ value = "û",//
+ required = true,//Ƿ봫
+ //paramTypeͣpath,query,body,form,header
+ paramType = "query"
+ )
+ ,
+ @ApiImplicitParam(name = "password",//
+ value = "",//
+ required = true,//Ƿ봫
+ paramType = "query"
+ )
+ })
+ @PostMapping(value = "/login2")
+ public LoginForm login2(String username,String password){
+ System.out.println(username+":"+password);
+ LoginForm loginForm = new LoginForm();
+ loginForm.setUsername(username);
+ loginForm.setPassword(password);
+ return loginForm;
+ }
+
+```
+
+ʾURL·
+
+ƴ
+
+```
+ // ʹ·
+ @PostMapping("/login3/{id1}/{id2}")
+ @ApiOperation(value = "¼ӿ3",notes = "¼ӿڵ˵3")
+ @ApiImplicitParams({
+ @ApiImplicitParam(name = "id1",//
+ value = "û",//
+ required = true,//Ƿ봫
+ //paramTypeͣpath,query,body,form,header
+ paramType = "path"
+ )
+ ,
+ @ApiImplicitParam(name = "id2",//
+ value = "",//
+ required = true,//Ƿ봫
+ paramType = "path"
+ )
+ })
+ public String login3(@PathVariable Integer id1,@PathVariable Integer id2){
+ return id1+":"+id2;
+ }
+
+```
+
+ʾheader
+
+ƴ
+
+```
+ // headerݲ
+ @PostMapping("/login4")
+ @ApiOperation(value = "¼ӿ4",notes = "¼ӿڵ˵4")
+ @ApiImplicitParams({
+ @ApiImplicitParam(name = "username",//
+ value = "û",//
+ required = true,//Ƿ봫
+ //paramTypeͣpath,query,body,form,header
+ paramType = "header"
+ )
+ ,
+ @ApiImplicitParam(name = "password",//
+ value = "",//
+ required = true,//Ƿ봫
+ paramType = "header"
+ )
+ })
+ public String login4( @RequestHeader String username,
+ @RequestHeader String password){
+ return username+":"+password;
+ }
+
+```
+
+ʾģļϴ
+
+ƴ
+
+```
+ // ļϴʱҪ@ApiParam÷@ApiImplicitParamһ@ApiParamڲ
+ // ҲԲע⣬swaggerԶ˵
+ @ApiOperation(value = "ϴļ",notes = "ϴļ")
+ @PostMapping(value = "/upload")
+ public String upload(@ApiParam(value = "ͼƬļ", required = true)MultipartFile uploadFile){
+ String originalFilename = uploadFile.getOriginalFilename();
+
+ return originalFilename;
+ }
+
+ // ļϴʱ**swaggerֻܲԵļϴ**
+ @ApiOperation(value = "ϴļ",notes = "ϴļ")
+ @PostMapping(value = "/upload2",consumes = "multipart/*", headers = "content-type=multipart/form-data")
+ public String upload2(@ApiParam(value = "ͼƬļ", required = true,allowMultiple = true)MultipartFile[] uploadFile){
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < uploadFile.length; i++) {
+ System.out.println(uploadFile[i].getOriginalFilename());
+ sb.append(uploadFile[i].getOriginalFilename());
+ sb.append(",");
+ }
+ return sb.toString();
+ }
+
+ // ļв
+ @ApiOperation(value = "ļв",notes = "ļв")
+ @PostMapping(value = "/upload3")
+ @ApiImplicitParams({
+ @ApiImplicitParam(name = "name",
+ value = "ͼƬ",
+ required = true
+ )
+ })
+ public String upload3(@ApiParam(value = "ͼƬļ", required = true)MultipartFile uploadFile,
+ String name){
+ String originalFilename = uploadFile.getOriginalFilename();
+
+ return originalFilename+":"+name;
+ }
+
+```
+
+## ӿӦ
+
+ӿӦǷ鿴ӿĵܹ֪ӿڷصݵ塣
+
+### Ӧʵࣺ
+
+ǰڶӿʱᵽʹ`@ApiModel`ע࣬ӿڷ࣬ôϵ˵ҲΪӦ˵
+
+ƴ
+
+```
+ // ر@ApiModelע
+ @ApiOperation(value = "ʵӦ",notes = "ΪʵĽӿ")
+ @PostMapping("/role1")
+ public LoginForm role1(@RequestBody LoginForm loginForm){
+ return loginForm;
+ }
+
+```
+
+
+
+### ӦǷʵࣺ
+
+swaggerԷʵӦϸ˵ֻܱעӦϢͨ`@ApiResponses``@ApiResponse`ʵֵġ
+`@ApiResponses``@ApiResponse``@ApiModel`һʹá
+
+ƴ
+
+```
+ // ͵,ʱֶעͣʵswaggerƼʹʵ
+ @ApiOperation(value = "ʵ",notes = "ʵ")
+ @ApiResponses({
+ @ApiResponse(code=200,message = "óɹ"),
+ @ApiResponse(code=401,message = "Ȩ" )
+ }
+ )
+ @PostMapping("/role2")
+ public String role2(){
+ return " {\n" +
+ " name:\"㶫\",\n" +
+ " citys:{\n" +
+ " city:[\"\",\"\",\"麣\"]\n" +
+ " }\n" +
+ " }";
+ }
+
+```
+
+
+
+* * *
+
+# Swagger UIǿ
+
+ܻUIǺܺÿһЩṩһЩSwagger UIǿȽе`swagger-bootstrap-ui``swagger-bootstrap-ui`Ϊ
+
+## UIԱȣ
+
+
+
+
+
+## ʹ
+
+1.
+
+ƴ
+
+```
+
+
+ io.springfox
+ springfox-swagger2
+ 2.9.2
+
+
+ io.springfox
+ springfox-swagger-ui
+ 2.9.2
+
+
+
+ com.github.xiaoymin
+ swagger-bootstrap-ui
+ 1.8.7
+
+
+```
+
+2.swaggerע`@EnableSwaggerBootstrapUI`:
+
+ƴ
+
+```
+@Configuration //
+@EnableSwagger2 //swagger
+@EnableSwaggerBootstrapUI // SwaggerBootstrapUI
+public class SwaggerConfig {
+ // ʡ
+}
+
+```
+
+3.API`http://localhost:8080/doc.html`ԤbootstarpSwagger UI档
+
+## ŵ
+
+1.?ÿһ
+
+2.˵ˣBootstrapUIswaggerָ֧`form-data``x-www-form-urlencoded`
+
+
+3.ָ֧ƵAPIĵ͵ȫAPIĵ
+
+
+
+
+* * *
+
+# Spring Securityע
+
+Spring BootSpring SecuritySwaggerʱҪص·ͷе·עǷ¼·
+
+ƴ
+
+```
+.antMatchers("/swagger**/**").permitAll()
+.antMatchers("/webjars/**").permitAll()
+.antMatchers("/v2/**").permitAll()
+.antMatchers("/doc.html").permitAll() // bootstarpSwagger UI棬һ
+
+```
+
+* * *
+
+# tokenĴ
+
+swaggerֻ֧˼ĵԣһЩӿڣDzԵʱҪtokenϢдheaderУĿǰûԶͷĵط
+?һ
+ʹSwagger BootstrapUIôڡĵȫֲheader
+
+?swaggerȫֲã
+
+ƴ
+
+```
+ //жȫֲ˵ͷ
+ ParameterBuilder parameterBuilder = new ParameterBuilder();
+ List parameters = new ArrayList();
+ parameterBuilder.name("authorization").description("")
+ .modelRef(new ModelRef("string")).parameterType("header").required(false).build();
+ parameters.add(parameterBuilder.build());
+ return new Docket(DocumentationType.SWAGGER_2) // DocumentationType.SWAGGER_2 ̶ģswagger2
+ .apiInfo(apiInfo()) // APIϢ
+ .select() // select()һApiSelectorBuilderʵ,ƽӿڱswaggerĵ
+ .apis(RequestHandlerSelectors.basePackage("com.example.controller")) // ָɨĸµĽӿ
+ .paths(PathSelectors.any())// ѡеAPI,ֻΪAPIĵ
+ .build().globalOperationParameters(parameters);
+
+```
+
+?ʹ`@ApiImplicitParams`עһͷ磺
+
+ƴ
+
+```
+ // ҪIJDZõҪ,Ȩtoken
+ @PostMapping("/login6")
+ @ApiOperation(value = "tokenĽӿ",notes = "tokenĽӿ")
+ @ApiImplicitParams({
+ @ApiImplicitParam(name = "authorization",//
+ value = "Ȩtoken",//
+ required = true,//Ƿ봫
+ paramType = "header"
+ )
+ ,
+ @ApiImplicitParam(name = "username",//
+ value = "û",//
+ required = true,//Ƿ봫
+ paramType = "query"
+ )
+ })
+ public String login6(String username){
+ return username;
+ }
+
+```
+
+* * *
+
+# Swaggerİȫ
+
+1.ȨԸswaggerȨҪswaggerҳû룬Щspring securityshiroˣﲻ
+
+2.DzʽпԷʣʽйرSwaggerԶãͲswaggerҳˡʹ`@Profile({"dev","test"})`עֻdevtestSwaggerԶá
+ȻSpring Bootļĵǰprofile`spring.profiles.active=release`֮ʱ`http://localhost:8080/swagger-ui.html`
+
+* * *
+
+
+
+ߣ[progor](https://www.cnblogs.com/progor/)
+Ϊԭתע
+
diff --git "a/docs/spring/SpringBoot/\345\237\272\344\272\216SpringBoot\344\270\255\347\232\204\345\274\200\346\272\220\347\233\221\346\216\247\345\267\245\345\205\267SpringBootAdmin.md" "b/docs/spring/SpringBoot/\345\237\272\344\272\216SpringBoot\344\270\255\347\232\204\345\274\200\346\272\220\347\233\221\346\216\247\345\267\245\345\205\267SpringBootAdmin.md"
new file mode 100644
index 0000000..fc25a2c
--- /dev/null
+++ "b/docs/spring/SpringBoot/\345\237\272\344\272\216SpringBoot\344\270\255\347\232\204\345\274\200\346\272\220\347\233\221\346\216\247\345\267\245\345\205\267SpringBootAdmin.md"
@@ -0,0 +1,294 @@
+Spring Boot Admin(SBA)һԴĿڹͼ Spring Boot ӦóӦóͨ http ķʽ Spring Cloud ֻעᵽ SBA УȻͿʵֶ Spring Boot ĿĿӻͲ鿴ˡ
+
+Spring Boot Admin Լ Spring Boot ȺĿṩϸĽ (Health)ϢڴϢJVM ϵͳͻԡϢ־úͲ鿴ʱ鿴Spring Boot 鿴ȹܡһʹðɡ
+
+յչʾЧ£
+
+[](https://s5.51cto.com/oss/202201/14/5d142e8c6b544f7b981b3eff8099b3d8.png)
+
+## 1.SBAض
+
+Ҫһ Spring Boot Admin Ŀغǵ Spring Boot Ŀķʽʹͨ Spring Boot Ŀƣ岽¡ʹ Idea һ Spring Boot Ŀ
+
+[](https://s5.51cto.com/oss/202201/14/d97c492785db6ff2ded49175184ceda9.png)
+
+[](https://s3.51cto.com/oss/202201/14/8bb1f0389b95e174b56ac01ba313ec7b.png)
+
+Ҫע⣬Ҫ Spring Boot Admin(Server)˿֧֣ܵͼʾ
+
+[](https://s4.51cto.com/oss/202201/14/122e9f0726fde8ac0c8936c79ef12f5f.png)
+
+ҲǴ Spring Boot ĿҪҪĿ֧֣
+
+
+
+
+
+```
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ de.codecentric
+ spring-boot-admin-starter-server
+
+
+```
+
+
+
+
+
+
+
+### 1.1 SBA
+
+Ŀ֮ҪϿ SBA
+
+
+
+
+
+```
+import de.codecentric.boot.admin.server.config.EnableAdminServer;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@EnableAdminServer // Ӵд
+@SpringBootApplication
+public class SbaserverApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(SbaserverApplication.class, args);
+ }
+}
+
+```
+
+
+
+
+
+### 1.2 SBA˿ں
+
+ application.properties һĿĶ˿ںžͿֱˣõĶ˿ں 9001
+
+
+
+
+
+```
+server.port=9001
+
+```
+
+
+
+
+
+PSö˿ںŵҪĿΪ˲ Spring Boot Ŀͻ SBA ǵ˲Ժԡ
+
+Ŀ֮ͿԿ SBA ҳˣͼʾ
+
+[](https://s5.51cto.com/oss/202201/14/20418ce88230b20b234f9e9c15e07f47.png)
+
+ʱ SBA лûκҪصĿٴһ Spring Boot Ŀ뵽 SBA мغɡ
+
+## 2.һͨSpringBootĿ
+
+ȣҪһͨ Spring Boot ĿĴͲʾˡ Spring Boot Ŀ֮Ҫ Spring Boot ĿҪ SBA ͻ˿֧֣ܵҲ pom.xml ݣ
+
+
+
+
+
+
+
+```
+
+ de.codecentric
+ spring-boot-admin-starter-client
+
+
+```
+
+
+
+
+
+Ȼ application.properties ļ SBA ˵ַҲǵһ SBA Ŀĵַ£
+
+
+
+
+
+```
+# ǰĿ˿ں
+server.port=8080
+# Spring Boot Admin ط˵ַ
+spring.boot.admin.client.url=http://localhost:9001
+
+```
+
+
+
+
+
+Сspring.boot.admin.client.urlΪ SBA صַ
+
+## 3.SpringBootAdmin
+
+Ϣ֮ʱ鿴 Spring Boot Admin ҳобص Spring Boot Ŀˣͼʾ
+
+[](https://s5.51cto.com/oss/202201/14/c010770a5cdfe5fad0ad1e8f0c3b07dc.png)
+
+ҲԵӦǽ鿴 Spring Boot Admin бص Spring Boot Ŀͼʾ
+
+[](https://s4.51cto.com/oss/202201/14/d88e33f87e116000f9717e8c19c43cc4.png)
+
+Ӧýҳ棬ͼʾ
+
+[](https://s2.51cto.com/oss/202201/14/4c3609840ea5cb45779eafbc2b260324.png)
+
+[](https://s4.51cto.com/oss/202201/14/2912ed434d97f8dd49c27ce73252d34c.png)
+
+¼־а Spring Boot ״̬չʾ(UP ΪOFFLINE Ϊ쳣)ͷʱ䣬ͼʾ
+
+[](https://s5.51cto.com/oss/202201/14/5792a62fbcafe6978bfe3bd26cf1e3ab.png)
+
+## 4.SpringBoot쳣
+
+ֶѱص Spring Boot Ŀֹ֮ͣ Spring Boot Admin оͿԲ鿴һӦѾͣˣͼʾ
+
+[](https://s5.51cto.com/oss/202201/14/47569a3fe09e62b2364c26bdbd7da4bc.png)
+
+Ҳͨ¼־鿴 Spring Boot 崻ľʱ䣬ͼʾ
+
+[](https://s2.51cto.com/oss/202201/14/b63f631561fa646f85ccf3e1e4321939.png)
+
+## 5.ò鿴
+
+ͨǿԿص Spring Boot ѡDZȽٵģôܲ鿴ļ?Ҫ⣬Ҫڱص Spring Boot Ŀ spring-boot-starter-actuator ֧֣ܵ鿴мòУչʾЧ£
+
+[](https://s4.51cto.com/oss/202201/14/03938ac0bded4487b6720fc4657f9e99.png)
+
+һЩ
+
+### 5.1 actuator֧
+
+ڱص Spring Boot Ŀ actuator ֧֣Ҳ pom.xml ã
+
+
+
+
+
+
+
+```
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+```
+
+
+
+
+
+ֶ Maven (Զ룬˲ɺ)
+
+### 5.2 ÿм
+
+ڱص Spring Boot Ŀã
+
+
+
+
+
+```
+#
+management.endpoints.web.exposure.include=*
+
+```
+
+
+
+
+
+ϵǿżѡ֮ Spring Boot ĿȻˢ Spring Boot Admin ļչʾˣͼʾ
+
+[](https://s6.51cto.com/oss/202201/14/2cc24e05bc6185ba1869872db5a864a5.png)
+
+### 5.3 ĿԤ
+
+ Spring Boot м֮ͨ SBA ͿԲ鿴ˣ
+
+* ʱ䡢ۼʱ;
+* ̺߳ռõ CPU Դ;
+* Ϣմͻʱ;
+* JVM ߳תڴתͶӦļ;
+* Բ鿴 Spring Boot Ŀе־;
+* 鿴 Spring Boot Ŀܼ;
+* 鿴 Spring Boot лϢ;
+* 鿴 Spring Boot Ϣ;
+* 鿴 Spring Boot еĶʱ;
+* 鿴 Spring Boot Ŀел档
+
+ǼҪҳĽͼһ
+
+### 5.3.1 鿴л
+
+[](https://s5.51cto.com/oss/202201/14/a9db77b1b0e378450086edd1ab438df5.png)
+
+[](https://s2.51cto.com/oss/202201/14/17604f4f5eb388a2a6c08f55e1e050ac.png)
+
+### 5.3.2 鿴ʱ
+
+[](https://s5.51cto.com/oss/202201/14/113d94b9bd488e239967915aededc89c.png)
+
+### 5.3.3 Ŀ־
+
+[](https://s3.51cto.com/oss/202201/14/8da60846eecbdbd9472ae6dbf17d951f.png)
+
+ǿͨ Spring Boot Admin ̬Ŀе־
+
+### 5.3.4 JVM̺߳ڴ鿴
+
+[](https://s2.51cto.com/oss/202201/14/d3f98228a8b19675475c863457821034.png)
+
+### 5.3.5 鿴SpringBootл
+
+[](https://s5.51cto.com/oss/202201/14/ae811102080c26b11135be50cd889710.png)
+
+ȻǻԶЩɾ
+
+## 6.鿴Ŀʵʱ־
+
+Ҫ鿴Ŀе־Ϣһǰǰ㱻ص Spring Boot Ŀ־ı·־ļֻеһ Spring Boot ĿŻὫ־浽ϣͨ SBA 鿴õ־· Spring Boot application.properties ļã
+
+
+
+
+
+```
+# ־·
+logging.file.path=C:\\work\\log
+
+```
+
+
+
+
+
+֮ Spring Boot ĿȻˢ SBA ҳ棬չʾЧ£
+
+[](https://s6.51cto.com/oss/202201/14/3f03c6402cc8a2532ed45ab43be156ac.png)
+
+ʱǾͿԲ鿴ʵʱ־ϢˣȻҲʱ־ҪĻ
+
+## ܽ
+
+Spring Boot Admin(SBA)һԴĿڹͼ Spring Boot ӦóṩϸĽ (Health)ϢڴϢJVM ϵͳͻԡϢ־úͲ鿴ʱ鿴Spring Boot 鿴ȹܡ
+
+Ҫһ SBA һ Spring Boot Ŀص Spring Boot ĿҪ SBA Client ֧֣ܵ actuator ܺӦãͿʵֶ Spring Boot Ŀˡ
\ No newline at end of file
diff --git "a/docs/spring/\347\273\231\344\275\240\344\270\200\344\273\275SpringBoot\347\237\245\350\257\206\346\270\205\345\215\225.md" "b/docs/spring/SpringBoot/\347\273\231\344\275\240\344\270\200\344\273\275SpringBoot\347\237\245\350\257\206\346\270\205\345\215\225.md"
similarity index 100%
rename from "docs/spring/\347\273\231\344\275\240\344\270\200\344\273\275SpringBoot\347\237\245\350\257\206\346\270\205\345\215\225.md"
rename to "docs/spring/SpringBoot/\347\273\231\344\275\240\344\270\200\344\273\275SpringBoot\347\237\245\350\257\206\346\270\205\345\215\225.md"
diff --git "a/docs/spring/SpringMVC/SpringMVC\344\270\255\347\232\204\345\233\275\351\231\205\345\214\226\345\212\237\350\203\275.md" "b/docs/spring/SpringMVC/SpringMVC\344\270\255\347\232\204\345\233\275\351\231\205\345\214\226\345\212\237\350\203\275.md"
new file mode 100644
index 0000000..374388b
--- /dev/null
+++ "b/docs/spring/SpringMVC/SpringMVC\344\270\255\347\232\204\345\233\275\351\231\205\345\214\226\345\212\237\350\203\275.md"
@@ -0,0 +1,179 @@
+#### ʻ
+
+* * *
+
+ڿӦóʱֶ֧Եֶ֧ԵĹ֮ܳΪʻӢinternationalizationдΪi18nΪĸiĩĸnм18ĸ
+
+ضıػܣӢlocalizationдΪL10nػָݵڵʾȡ
+
+ҲаߺϳΪȫӢglobalizationдΪg11n
+
+JavaУֶ֧Ժͱػͨ`MessageFormat``Locale`ʵֵģ
+
+
+WebӦóҪʵֹʻܣҪȾViewʱҪѸԵԴļͬûͬһҳʱʾԾDzͬġ
+
+Spring MVCӦóʵֹʻ
+
+### ȡLocale
+
+ʵֹʻĵһǻȡû`Locale`WebӦóУHTTP淶涨Я`Accept-Language`ͷָʾû趨˳磺
+
+```
+Accept-Language: zh-CN,zh;q=0.8,en;q=0.2
+
+```
+
+HTTPͷʾѡģѡģѡӢġ`q`ʾȨأǿɻһȼбתΪJava`Locale`û`Locale`ֻͨȨߵ`Locale`
+
+Spring MVCͨ`LocaleResolver`Զ`HttpServletRequest`лȡ`Locale`ж`LocaleResolver`ʵ࣬õ`CookieLocaleResolver`
+
+```
+@Primary
+@Bean
+LocaleResolver createLocaleResolver() {
+ var clr = new CookieLocaleResolver(); clr.setDefaultLocale(Locale.ENGLISH); clr.setDefaultTimeZone(TimeZone.getDefault()); return clr;}
+
+```
+
+`CookieLocaleResolver``HttpServletRequest`лȡ`Locale`ʱȸһضCookieжǷָ`Locale`ûУʹHTTPͷȡûУͷĬϵ`Locale`
+
+ûһηվʱ`CookieLocaleResolver`ֻܴHTTPͷȡ`Locale`ʹĬԡͨվҲûԼѡԣʱ`CookieLocaleResolver`ͻûѡԴŵCookieУһηʱͻ᷵ûϴѡԶĬԡ
+
+### ȡԴļ
+
+ڶǰдģеַԴļķʽ洢ⲿڶԣļΪ`messages`ôԴļ밴·ʽclasspathУ
+
+* ĬԣļΪ`messages.properties`
+* ģLocale`zh_CN`ļΪ`messages_zh_CN.properties`
+* ģLocale`ja_JP`ļΪ`messages_ja_JP.properties`
+* ԡ
+
+ÿԴļͬkey磬ĬӢģļ`messages.properties`£
+
+```
+language.select=Language
+home=Home
+signin=Sign In
+copyright=Copyright?{0,number,#}
+
+```
+
+ļ`messages_zh_CN.properties`£
+
+```
+language.select=
+home=ҳ
+signin=¼
+copyright=Ȩ?{0,number,#}
+
+```
+
+### MessageSource
+
+ǴһSpringṩ`MessageSource`ʵԶȡе`.properties`ļṩһͳһӿʵ֡롱
+
+```
+// code, arguments, locale:
+String text = messageSource.getMessage("signin", null, locale);
+
+```
+
+У`signin``.properties`ļжkeyڶ`Object[]`ΪʽʱIJһǻȡû`Locale`ʵ
+
+`MessageSource`£
+
+```
+@Bean("i18n")
+MessageSource createMessageSource() {
+ var messageSource = new ResourceBundleMessageSource(); // ָļUTF-8:
+ messageSource.setDefaultEncoding("UTF-8"); // ָļ:
+ messageSource.setBasename("messages"); return messageSource;}
+
+```
+
+ע`ResourceBundleMessageSource`ԶļԶԵԴļ
+
+עSpringᴴֻһ`MessageSource`ʵԼ`MessageSource`רŸҳʻʹõģΪ`i18n``MessageSource`ʵͻ
+
+### ʵֶ
+
+ҪViewʹ`MessageSource``Locale`ԣͨдһ`MvcInterceptor`Դע뵽`ModelAndView`У
+
+```
+@Component
+public class MvcInterceptor implements HandlerInterceptor {
+ @Autowired LocaleResolver localeResolver;
+ // עעMessageSourcei18n:
+ @Autowired @Qualifier("i18n") MessageSource messageSource;
+ public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { if (modelAndView != null) { // ûLocale:
+ Locale locale = localeResolver.resolveLocale(request); // Model:
+ modelAndView.addObject("__messageSource__", messageSource); modelAndView.addObject("__locale__", locale); } }}
+
+```
+
+Ҫ`WebMvcConfigurer`ע`MvcInterceptor`ڣͿViewе`MessageSource.getMessage()`ʵֶԣ
+
+```
+{{ __messageSource__.getMessage('signin', null, __locale__) }}
+
+```
+
+дȻУʽ̫ˡʹViewʱҪÿضView涨ƹʻPebbleУǿԷװһʻƾ»`_`һ´`ViewResolver`Ĵ룺
+
+```
+@Bean
+ViewResolver createViewResolver(@Autowired ServletContext servletContext, @Autowired @Qualifier("i18n") MessageSource messageSource) {
+ var engine = new PebbleEngine.Builder() .autoEscaping(true) .cacheActive(false) .loader(new Servlet5Loader(servletContext)) // չ:
+ .extension(createExtension(messageSource)) .build(); var viewResolver = new PebbleViewResolver(); viewResolver.setPrefix("/WEB-INF/templates/"); viewResolver.setSuffix(""); viewResolver.setPebbleEngine(engine); return viewResolver;}
+
+private Extension createExtension(MessageSource messageSource) {
+ return new AbstractExtension() { @Override public Map getFunctions() { return Map.of("_", new Function() { public Object execute(Map args, PebbleTemplate self, EvaluationContext context, int lineNumber) { String key = (String) args.get("0"); List