-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
454 lines (397 loc) · 53.2 KB
/
index.html
File metadata and controls
454 lines (397 loc) · 53.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0,viewport-fit=cover"><title>彬子的Blog</title><meta name="author" content="彬子"><meta name="copyright" content="彬子"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="biny">
<meta property="og:type" content="website">
<meta property="og:title" content="彬子的Blog">
<meta property="og:url" content="https://binzi.top/index.html">
<meta property="og:site_name" content="彬子的Blog">
<meta property="og:description" content="biny">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://binzi.top/img/qq.jpg">
<meta property="article:author" content="彬子">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://binzi.top/img/qq.jpg"><link rel="shortcut icon" href="/img/favicon.ico"><link rel="canonical" href="https://binzi.top/index.html"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox/fancybox.min.css" media="print" onload="this.media='all'"><script>
(() => {
const saveToLocal = {
set: (key, value, ttl) => {
if (!ttl) return
const expiry = Date.now() + ttl * 86400000
localStorage.setItem(key, JSON.stringify({ value, expiry }))
},
get: key => {
const itemStr = localStorage.getItem(key)
if (!itemStr) return undefined
const { value, expiry } = JSON.parse(itemStr)
if (Date.now() > expiry) {
localStorage.removeItem(key)
return undefined
}
return value
}
}
window.btf = {
saveToLocal,
getScript: (url, attr = {}) => new Promise((resolve, reject) => {
const script = document.createElement('script')
script.src = url
script.async = true
Object.entries(attr).forEach(([key, val]) => script.setAttribute(key, val))
script.onload = script.onreadystatechange = () => {
if (!script.readyState || /loaded|complete/.test(script.readyState)) resolve()
}
script.onerror = reject
document.head.appendChild(script)
}),
getCSS: (url, id) => new Promise((resolve, reject) => {
const link = document.createElement('link')
link.rel = 'stylesheet'
link.href = url
if (id) link.id = id
link.onload = link.onreadystatechange = () => {
if (!link.readyState || /loaded|complete/.test(link.readyState)) resolve()
}
link.onerror = reject
document.head.appendChild(link)
}),
addGlobalFn: (key, fn, name = false, parent = window) => {
if (!true && key.startsWith('pjax')) return
const globalFn = parent.globalFn || {}
globalFn[key] = globalFn[key] || {}
globalFn[key][name || Object.keys(globalFn[key]).length] = fn
parent.globalFn = globalFn
}
}
const activateDarkMode = () => {
document.documentElement.setAttribute('data-theme', 'dark')
if (document.querySelector('meta[name="theme-color"]') !== null) {
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
}
}
const activateLightMode = () => {
document.documentElement.setAttribute('data-theme', 'light')
if (document.querySelector('meta[name="theme-color"]') !== null) {
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
}
}
btf.activateDarkMode = activateDarkMode
btf.activateLightMode = activateLightMode
const theme = saveToLocal.get('theme')
const mediaQueryDark = window.matchMedia('(prefers-color-scheme: dark)')
const mediaQueryLight = window.matchMedia('(prefers-color-scheme: light)')
if (theme === undefined) {
if (mediaQueryLight.matches) activateLightMode()
else if (mediaQueryDark.matches) activateDarkMode()
else {
const hour = new Date().getHours()
const isNight = hour <= 6 || hour >= 18
isNight ? activateDarkMode() : activateLightMode()
}
mediaQueryDark.addEventListener('change', () => {
if (saveToLocal.get('theme') === undefined) {
e.matches ? activateDarkMode() : activateLightMode()
}
})
} else {
theme === 'light' ? activateLightMode() : activateDarkMode()
}
const asideStatus = saveToLocal.get('aside-status')
if (asideStatus !== undefined) {
document.documentElement.classList.toggle('hide-aside', asideStatus === 'hide')
}
const detectApple = () => {
if (/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)) {
document.documentElement.classList.add('apple')
}
}
detectApple()
})()
</script><script>const GLOBAL_CONFIG = {
root: '/',
algolia: undefined,
localSearch: {"path":"/search.xml","preload":false,"top_n_per_article":1,"unescape":false,"languages":{"hits_empty":"未找到符合您查询的内容:${query}","hits_stats":"共找到 ${hits} 篇文章"}},
translate: {"defaultEncoding":2,"translateDelay":0,"msgToTraditionalChinese":"繁","msgToSimplifiedChinese":"简"},
highlight: {"plugin":"highlight.js","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":400,"highlightFullpage":true,"highlightMacStyle":false},
copy: {
success: '复制成功',
error: '复制失败',
noSupport: '浏览器不支持'
},
relativeDate: {
homepage: true,
post: true
},
runtime: '天',
dateSuffix: {
just: '刚刚',
min: '分钟前',
hour: '小时前',
day: '天前',
month: '个月前'
},
copyright: {"limitCount":150,"languages":{"author":"作者: 彬子","link":"链接: ","source":"来源: 彬子的Blog","info":"著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。"}},
lightbox: 'fancybox',
Snackbar: undefined,
infinitegrid: {
js: 'https://cdn.jsdelivr.net/npm/@egjs/infinitegrid/dist/infinitegrid.min.js',
buttonText: '加载更多'
},
isPhotoFigcaption: false,
islazyload: false,
isAnchor: false,
percent: {
toc: true,
rightside: true,
},
autoDarkmode: true
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
title: '彬子的Blog',
isPost: false,
isHome: true,
isHighlightShrink: false,
isToc: false,
isShuoshuo: false
}</script><link href="/self/btf.css" rel="stylesheet"><meta name="generator" content="Hexo 7.3.0"></head><body><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img text-center"><img src="/img/qq.jpg" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="site-data text-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">100</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">32</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">5</div></a></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><span class="site-page group"><i class="fa-fw fas fa-compass"></i><span> 页面</span><i class="fas fa-chevron-down"></i></span><ul class="menus_item_child"><li><a class="site-page child" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 归档</span></a></li><li><a class="site-page child" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></li><li><a class="site-page child" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></li><li><a class="site-page child" href="/Gallery/"><i class="fa-fw fas fa-images"></i><span> 图库</span></a></li><li><a class="site-page child" href="/talking/"><i class="fa-fw fas fa-comment-dots"></i><span> 说说</span></a></li><li><a class="site-page child" href="/link/"><i class="fa-fw fas fa-thumbs-up"></i><span> 示例</span></a></li></ul></div><div class="menus_item"><span class="site-page group"><i class="fa-fw fas fa-book"></i><span> 文档</span><i class="fas fa-chevron-down"></i></span><ul class="menus_item_child"><li><a class="site-page child" href="/posts/21cfbf15/"><span> 🚀 快速开始</span></a></li><li><a class="site-page child" href="/posts/dc584b87/"><span> 📑 主题页面</span></a></li><li><a class="site-page child" href="/posts/4aa8abbe/"><span> 🛠 主题配置</span></a></li><li><a class="site-page child" href="/posts/ceeb73f/"><span> ⚔️ 标签外挂</span></a></li><li><a class="site-page child" href="/posts/98d20436/"><span> ❓ 主题问答</span></a></li><li><a class="site-page child" href="/posts/4073eda/"><span> ⚡️ 进阶教程</span></a></li><li><a class="site-page child" href="/posts/198a4240/"><span> ✨ 更新日志</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="/messageboard/"><i class="fa-fw fas fa-comment-dots"></i><span> 留言板</span></a></div><div class="menus_item"><span class="site-page group"><i class="fa-fw fas fa-language"></i><span> 语言</span><i class="fas fa-chevron-down"></i></span><ul class="menus_item_child"><li><a class="site-page child" href="/en/"><i class="fa-fw fas fa-e"></i><span> English</span></a></li><li><a class="site-page child" href="/"><i class="fa-fw fas fa-c"></i><span> 中文</span></a></li></ul></div></div></div></div><div class="page" id="body-wrap"><header class="full_page" id="page-header" style="background-image: url(https://oss.012700.xyz/butterfly/2024/10/index.jpg);"><nav id="nav"><span id="blog-info"><a class="nav-site-title" href="/"><span class="site-name">彬子的Blog</span></a></span><div id="menus"><div id="search-button"><span class="site-page social-icon search"><i class="fas fa-search fa-fw"></i><span> 搜索</span></span></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><span class="site-page group"><i class="fa-fw fas fa-compass"></i><span> 页面</span><i class="fas fa-chevron-down"></i></span><ul class="menus_item_child"><li><a class="site-page child" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 归档</span></a></li><li><a class="site-page child" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></li><li><a class="site-page child" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></li><li><a class="site-page child" href="/Gallery/"><i class="fa-fw fas fa-images"></i><span> 图库</span></a></li><li><a class="site-page child" href="/talking/"><i class="fa-fw fas fa-comment-dots"></i><span> 说说</span></a></li><li><a class="site-page child" href="/link/"><i class="fa-fw fas fa-thumbs-up"></i><span> 示例</span></a></li></ul></div><div class="menus_item"><span class="site-page group"><i class="fa-fw fas fa-book"></i><span> 文档</span><i class="fas fa-chevron-down"></i></span><ul class="menus_item_child"><li><a class="site-page child" href="/posts/21cfbf15/"><span> 🚀 快速开始</span></a></li><li><a class="site-page child" href="/posts/dc584b87/"><span> 📑 主题页面</span></a></li><li><a class="site-page child" href="/posts/4aa8abbe/"><span> 🛠 主题配置</span></a></li><li><a class="site-page child" href="/posts/ceeb73f/"><span> ⚔️ 标签外挂</span></a></li><li><a class="site-page child" href="/posts/98d20436/"><span> ❓ 主题问答</span></a></li><li><a class="site-page child" href="/posts/4073eda/"><span> ⚡️ 进阶教程</span></a></li><li><a class="site-page child" href="/posts/198a4240/"><span> ✨ 更新日志</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="/messageboard/"><i class="fa-fw fas fa-comment-dots"></i><span> 留言板</span></a></div><div class="menus_item"><span class="site-page group"><i class="fa-fw fas fa-language"></i><span> 语言</span><i class="fas fa-chevron-down"></i></span><ul class="menus_item_child"><li><a class="site-page child" href="/en/"><i class="fa-fw fas fa-e"></i><span> English</span></a></li><li><a class="site-page child" href="/"><i class="fa-fw fas fa-c"></i><span> 中文</span></a></li></ul></div></div><div id="toggle-menu"><span class="site-page"><i class="fas fa-bars fa-fw"></i></span></div></div></nav><div id="site-info"><h1 id="site-title">彬子的Blog</h1><div id="site-subtitle"><span id="subtitle"></span></div><div id="site_social_icons"><a class="social-icon" href="https://github.com/Thinkya1" target="_blank" title="Github"><i class="fab fa-github" style="color: #24292e;"></i></a></div></div><div id="scroll-down"><i class="fas fa-angle-down scroll-down-effects"></i></div></header><main class="layout" id="content-inner"><div class="recent-posts nc" id="recent-posts"><div class="recent-post-items"><div class="recent-post-item"><div class="recent-post-info no-cover"><a class="article-title" href="/2026/01/01/MySQL%E9%94%81/" title="MySQL的锁">MySQL的锁</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time datetime="2025-12-31T17:10:00.000Z" title="发表于 2026-01-01 01:10:00">2026-01-01</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/">数据库</a></span></div><div class="content"> MySQL锁 全局锁: flush tables with read lock,执行此条命令,整个数据库处于只读状态 unlock tables, 释放全局锁,会话断开时,也会自动释放全局锁 一般用来全库逻辑备份 表级锁:MySQL 里面表级别的锁有这几种: 表锁:通过lock tables 语句可以对表加表锁,表锁除了会限制别的线程的读写外,也会限制本线程接下来的读写操作。 元数据锁:当我们对数据库表进行操作时,会自动给这个表加上 MDL,对一张表进行 CRUD 操作时,加的是 MDL 读锁;对一张表做结构变更操作的时候,加的是 MDL 写锁;MDL 是为了保证当用户对表执行 CRUD 操作时,防止其他线程对这个表结构做了变更。 意向锁:当执行插入、更新、删除操作,需要先对表加上「意向独占锁」,然后对该记录加独占锁。意向锁的目的是为了快速判断表里是否有记录被加锁。 行级锁:InnoDB 引擎是支持行级锁的,而 MyISAM 引擎并不支持行级锁。 记录锁(Record Lock) 锁住某行记录,分为读写锁,事务提交后自动释放,例如select * from...</div></div></div><div class="recent-post-item"><div class="post_cover right"><a href="/2025/12/30/%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%E5%99%A8%E4%B8%8E%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E7%AE%97%E6%B3%95/" title="垃圾收集器(CMS-G1-ZGC)与垃圾回收算法"><img class="post-bg" src="/img/covers/1766223868563-25277577-8021-46f0-b6c0-eba574164d41.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="垃圾收集器(CMS-G1-ZGC)与垃圾回收算法"></a></div><div class="recent-post-info"><a class="article-title" href="/2025/12/30/%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%E5%99%A8%E4%B8%8E%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E7%AE%97%E6%B3%95/" title="垃圾收集器(CMS-G1-ZGC)与垃圾回收算法">垃圾收集器(CMS-G1-ZGC)与垃圾回收算法</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time datetime="2025-12-30T15:13:00.000Z" title="发表于 2025-12-30 23:13:00">2025-12-30</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Java/">Java</a></span></div><div class="content"> 垃圾收集器(CMS-G1-ZGC) CMS 垃圾收集器 JDK1.5时引入,JDK9被标记弃用,JDK14被移除 CMS(Concurrent Mark Sweep,并发标记清除)收集器是以获取最短回收停顿时间为目标的收集器(追求低停顿),它在垃圾收集时使得用户线程和 GC 线程并发执行,因此在垃圾收集过程中用户也不会感到明显的卡顿。 初始标记:Stop The World,仅使用一条初始标记线程对所有与 GC Roots 直接关联的对象进行标记。 并发标记:使用多条标记线程,与用户线程并发执行。此过程进行可达性分析,标记出所有废弃对象。速度很慢。 重新标记:Stop The World,使用多条标记线程并发执行,将刚才并发标记过程中新出现的废弃对象标记出来。 并发清除:只使用一条 GC 线程,与用户线程并发执行,清除刚才标记的对象。这个过程非常耗时。 并发标记与并发清除过程耗时最长,且可以与用户线程一起工作,因此,总体上说,CMS 收集器的内存回收过程是与用户线程一起并发执行的。 CMS...</div></div></div><div class="recent-post-item"><div class="post_cover left"><a href="/2025/12/28/%E7%B1%BB%E5%8A%A0%E8%BD%BD%E6%9C%BA%E5%88%B6%E4%B8%8E%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8/" title="类加载机制与类加载器"><img class="post-bg" src="/img/covers/image-20251228153154941.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="类加载机制与类加载器"></a></div><div class="recent-post-info"><a class="article-title" href="/2025/12/28/%E7%B1%BB%E5%8A%A0%E8%BD%BD%E6%9C%BA%E5%88%B6%E4%B8%8E%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8/" title="类加载机制与类加载器">类加载机制与类加载器</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time datetime="2025-12-28T11:13:00.000Z" title="发表于 2025-12-28 19:13:00">2025-12-28</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Java/">Java</a></span></div><div class="content"> 类加载机制/类加载器 类加载的完整流程(生命周期) 类从加载到卸载经历 5 个阶段,其中加载、验证、准备、初始化、卸载的顺序是固定的,解析阶段可能与初始化交叉进行: 1. 加载(Loading) 任务:通过类的全限定名(如com.example.User)获取其字节码数据,并生成Class对象。 来源:字节码可来自本地文件、网络、数据库、动态生成(如 CGLib)等。 关键组件:类加载器(ClassLoader)负责此阶段。 2. 验证(Verification) 任务:确保字节码符合 JVM 规范,避免恶意或无效字节码危害虚拟机安全。 验证内容 文件格式验证(魔数、版本号等) 元数据验证(类继承关系、字段方法合法性) 字节码验证(指令逻辑正确性) 符号引用验证(常量池引用有效性) 3. 准备(Preparation) 任务 :为类的静态变量分配内存并设置 初始默认值 (非显式赋值)。 例如:public static int a = 10;在准备阶段a的值为0(int...</div></div></div><div class="recent-post-item"><div class="post_cover right"><a href="/2025/12/27/MySQL%E7%9A%84MVCC/" title="MySQL的MVCC"><img class="post-bg" src="/img/covers/image-20251116012419555.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="MySQL的MVCC"></a></div><div class="recent-post-info"><a class="article-title" href="/2025/12/27/MySQL%E7%9A%84MVCC/" title="MySQL的MVCC">MySQL的MVCC</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time datetime="2025-12-26T17:10:00.000Z" title="发表于 2025-12-27 01:10:00">2025-12-27</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/">数据库</a></span></div><div class="content"> MVCC多版本并发控制 MVCC 的目标:让读操作尽量不阻塞写操作,写操作也尽量不阻塞读操作。 核心机制: MVCC主要依赖以下机制实现: 数据库行记录中的隐藏字段:最近修改本行数据的事务id、回滚指针指向本行数据的上个版本(其实是指向undo,通过undo计算上一个版本) •undo log:回滚日志,在insert、delete、update时产生,记载了与操作相反的操作,比如delete操作对应了一条insert日志 •readview:快照读SQL执行时产生的读视图,生成的一个快照,记录了以下字段,用于数据的可见性判断:◦ 当前活跃的事务id集合◦ 最小活跃事务id◦ 预分配事务id,即应该分配的下一个事务id◦ readview创建者id,即本事务id ...</div></div></div><div class="recent-post-item"><div class="recent-post-info no-cover"><a class="article-title" href="/2025/12/25/SpringMVC%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B/" title="SpringMVC执行流程">SpringMVC执行流程</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time datetime="2025-12-25T13:05:00.000Z" title="发表于 2025-12-25 21:05:00">2025-12-25</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Java/">Java</a></span></div><div class="content"> SpringMVC执行流程 请求先到 DispatcherServlet(前端控制器),它负责调度 HandlerMapping → HandlerAdapter → Controller → ViewResolver → View。 Spring MVC 采用前端控制器模式,所有请求先进入 DispatcherServlet。DispatcherServlet 通过 HandlerMapping 找到对应的 Controller,再通过 HandlerAdapter 调用方法执行。Controller 返回结果后,如果是视图名则交给 ViewResolver 解析并渲染视图;如果是 @ResponseBody,则通过 HttpMessageConverter 转换为 JSON 返回给客户端。 </div></div></div><div class="recent-post-item"><div class="post_cover right"><a href="/2025/12/24/MySqL%E4%BA%8B%E5%8A%A1%E7%89%B9%E6%80%A7%EF%BC%8C%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB/" title="MySqL事务特性,隔离级别"><img class="post-bg" src="/img/covers/image-20251224220314987.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="MySqL事务特性,隔离级别"></a></div><div class="recent-post-info"><a class="article-title" href="/2025/12/24/MySqL%E4%BA%8B%E5%8A%A1%E7%89%B9%E6%80%A7%EF%BC%8C%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB/" title="MySqL事务特性,隔离级别">MySqL事务特性,隔离级别</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time datetime="2025-12-24T14:34:00.000Z" title="发表于 2025-12-24 22:34:00">2025-12-24</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/">数据库</a></span></div><div class="content"> MySqL事务隔离级别 事务的特性: 原子性:事务要么全部提交成功要么全部失败 一致性:事务操作前和操作后具有完整性约束,数据库保持一致性状态 隔离性:事务执行时相互隔离互不影响,可以防止多个事务并发执行由于交叉执行导致的不一致 持久性:事务操作结束后修改是永久性的,即使关机故障也不会消失 MySQL InnoDB 引擎通过什么技术来保证事务的这四个特性的呢? 持久性是通过 redo log (重做日志)来保证的; 原子性是通过 undo log(回滚日志) 来保证的; 隔离性是通过 MVCC(多版本并发控制) 或锁机制来保证的; 一致性则是通过持久性+原子性+隔离性来保证; 事务的隔离级别有哪些? 读未提交 最低的隔离级别, 会导致脏读、幻读或不可重复读。 读已提交 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。这是大多数数据库(如 Oracle, SQL Server)的默认隔离级别。 ...</div></div></div><div class="recent-post-item"><div class="recent-post-info no-cover"><a class="article-title" href="/2025/12/21/Redis%E7%9A%84ziplist%E5%88%B0ListPack/" title="Redis的ziplist到ListPack">Redis的ziplist到ListPack</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time datetime="2025-12-21T14:24:00.000Z" title="发表于 2025-12-21 22:24:00">2025-12-21</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/">数据库</a></span></div><div class="content"> Redis的压缩列表ziplist到紧凑列表listpack ziplist 的结构(老版本用的) 大概长这样: 12345[zlbytes][zltail][zllen][entry1][entry2]...[entryN][0xFF]● *zlbytes*,记录整个压缩列表占用对内存字节数;● *zltail*,记录压缩列表「尾部」节点距离起始地址由多少字节,也就是列表尾的偏移量;● *zllen*,记录压缩列表包含的节点数量;● *0xFF*,标记压缩列表的结束点,固定值 0xFF(十进制255)。 每个 entry 里: 1[prevlen][encoding][data] prevlen:前一个 entry 的长度(1 或 5 字节) encoding:当前 entry 是字符串还是整数,长度是多少 data:真正的数据 listpack 的结构(新版本用的) 大概长这样: 1234[total_bytes][count][entry1][entry2]...[entryN][0xFF]total_bytes:整个 listpack...</div></div></div><div class="recent-post-item"><div class="post_cover right"><a href="/2025/12/19/HotSpot%20%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%E5%99%A8/" title="HotSpot 垃圾收集器"><img class="post-bg" src="https://cdn-doocs.oss-cn-shenzhen.aliyuncs.com/gh/doocs/jvm@main/images/serial.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="HotSpot 垃圾收集器"></a></div><div class="recent-post-info"><a class="article-title" href="/2025/12/19/HotSpot%20%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%E5%99%A8/" title="HotSpot 垃圾收集器">HotSpot 垃圾收集器</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time datetime="2025-12-19T12:43:00.000Z" title="发表于 2025-12-19 20:43:00">2025-12-19</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Java/">Java</a></span></div><div class="content"> HotSpot 垃圾收集器 HotSpot 虚拟机提供了多种垃圾收集器,每种收集器都有各自的特点,虽然我们要对各个收集器进行比较,但并非为了挑选出一个最好的收集器。我们选择的只是对具体应用最合适的收集器。 新生代垃圾收集器 Serial 垃圾收集器(单线程) 只开启一条 GC 线程进行垃圾回收,并且在垃圾收集过程中停止一切用户线程,即 Stop The World。 一般客户端应用所需内存较小,不会创建太多对象,而且堆内存不大,因此垃圾收集器回收时间短,即使在这段时间停止一切用户线程,也不会感觉明显卡顿。因此 Serial 垃圾收集器适合客户端使用。 由于 Serial 收集器只使用一条 GC 线程,避免了线程切换的开销,从而简单高效。 ParNew 垃圾收集器(多线程) ParNew 是 Serial 的多线程版本。由多条 GC 线程并行地进行垃圾清理。但清理过程依然需要 Stop The World。 ParNew 追求“低停顿时间”,与 Serial 唯一区别就是使用了多线程进行垃圾收集,在多 CPU 环境下性能比 Serial...</div></div></div><div class="recent-post-item"><div class="recent-post-info no-cover"><a class="article-title" href="/2025/12/17/AIO%20BIO%20NIO%E5%8C%BA%E5%88%AB%EF%BC%9F/" title="AIO BIO NIO区别?">AIO BIO NIO区别?</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time datetime="2025-12-17T13:46:00.000Z" title="发表于 2025-12-17 21:46:00">2025-12-17</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Java/">Java</a></span></div><div class="content"> AIO BIO NIO区别? BIO(同步阻塞 I/O) BIO 是传统的 I/O 模式,全称为 Block I/O,也叫同步阻塞 I/O。在 BIO 模式下,当我们执行 I/O 操作时,比如读取文件或者网络请求,程序会 阻塞,直到 I/O 操作完成后,才能继续执行后面的代码。也就是说,当一个线程在等待 I/O 完成时,它是处于阻塞状态的,不能做其他事情。 NIO(同步非阻塞 I/O) 一个线程管理多个连接 NIO 是对传统 BIO 的改进,它全称是 Non-blocking I/O(非阻塞 I/O)。在 NIO 模式下,I/O 操作不是阻塞的,可以同时处理多个 I/O 请求。与 BIO 不同的是,NIO 使用了 Channel(通道) 和 Buffer(缓冲区) 来进行数据读写,并且它支持 多路复用,这意味着多个 I/O 操作可以共享一个线程来处理,从而大大提高了并发性能。 AIO(异步非阻塞 I/O) AIO 是 NIO 的进一步升级,叫做 Asynchronous I/O(异步非阻塞 I/O)。在 AIO 模式下,I/O 操作是完全异步的,不需要线程阻塞等待...</div></div></div><div class="recent-post-item"><div class="recent-post-info no-cover"><a class="article-title" href="/2025/12/17/Redis%E7%BD%91%E7%BB%9C%E6%A8%A1%E5%9E%8B/" title="Redis网络模型">Redis网络模型</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time datetime="2025-12-17T13:43:00.000Z" title="发表于 2025-12-17 21:43:00">2025-12-17</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/">数据库</a></span></div><div class="content"> Redis网络模型(io多路复用) 阻塞IO(Blocking IO) 假设服务端只开启一个线程处理请求,第一个请求到来,开始调用内核read函数,然后就会发生阻塞,第二个请求到来时服务端将无法处理,只能等第一个请求读取完成。这种方式的缺点很明显,每次只能处理一个请求,无法发挥cpu多核优势,性能低下。 为了解决这个问题,我们可以引入多线程,这样就可以同时处理多个请求了,但服务端可能同时有成千上万的请求需要处理,随之而来的是线程数膨胀,频繁创建、销毁线程带来的性能影响,当然我们可以使用线程池,但服务能处理的总体数量就会受限于线程池线程数量。 非阻塞IO(NON-Blocking...</div></div></div></div><nav id="pagination"><div class="pagination"><span class="page-number current">1</span><a class="page-number" href="/page/2/#content-inner">2</a><span class="space">…</span><a class="page-number" href="/page/10/#content-inner">10</a><a class="extend next" rel="next" href="/page/2/#content-inner"><i class="fas fa-chevron-right fa-fw"></i></a></div></nav></div><div class="aside-content" id="aside-content"><div class="card-widget card-info text-center"><div class="avatar-img"><img src="/img/qq.jpg" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/></div><div class="author-info-name">彬子</div><div class="author-info-description">biny</div><div class="site-data"><a href="/archives/"><div class="headline">文章</div><div class="length-num">100</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">32</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">5</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/Thinkya1"><i class="fab fa-github"></i><span>Follow Me</span></a><div class="card-info-social-icons"><a class="social-icon" href="https://github.com/Thinkya1" target="_blank" title="Github"><i class="fab fa-github" style="color: #24292e;"></i></a></div></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content">This is my Blog</div></div><div class="sticky_layout"><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2026/01/01/MySQL%E9%94%81/" title="MySQL的锁">MySQL的锁</a><time datetime="2025-12-31T17:10:00.000Z" title="发表于 2026-01-01 01:10:00">2026-01-01</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2025/12/30/%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%E5%99%A8%E4%B8%8E%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E7%AE%97%E6%B3%95/" title="垃圾收集器(CMS-G1-ZGC)与垃圾回收算法"><img src="/img/covers/1766223868563-25277577-8021-46f0-b6c0-eba574164d41.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="垃圾收集器(CMS-G1-ZGC)与垃圾回收算法"/></a><div class="content"><a class="title" href="/2025/12/30/%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%E5%99%A8%E4%B8%8E%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E7%AE%97%E6%B3%95/" title="垃圾收集器(CMS-G1-ZGC)与垃圾回收算法">垃圾收集器(CMS-G1-ZGC)与垃圾回收算法</a><time datetime="2025-12-30T15:13:00.000Z" title="发表于 2025-12-30 23:13:00">2025-12-30</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2025/12/28/%E7%B1%BB%E5%8A%A0%E8%BD%BD%E6%9C%BA%E5%88%B6%E4%B8%8E%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8/" title="类加载机制与类加载器"><img src="/img/covers/image-20251228153154941.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="类加载机制与类加载器"/></a><div class="content"><a class="title" href="/2025/12/28/%E7%B1%BB%E5%8A%A0%E8%BD%BD%E6%9C%BA%E5%88%B6%E4%B8%8E%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8/" title="类加载机制与类加载器">类加载机制与类加载器</a><time datetime="2025-12-28T11:13:00.000Z" title="发表于 2025-12-28 19:13:00">2025-12-28</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2025/12/27/MySQL%E7%9A%84MVCC/" title="MySQL的MVCC"><img src="/img/covers/image-20251116012419555.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="MySQL的MVCC"/></a><div class="content"><a class="title" href="/2025/12/27/MySQL%E7%9A%84MVCC/" title="MySQL的MVCC">MySQL的MVCC</a><time datetime="2025-12-26T17:10:00.000Z" title="发表于 2025-12-27 01:10:00">2025-12-27</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2025/12/25/SpringMVC%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B/" title="SpringMVC执行流程">SpringMVC执行流程</a><time datetime="2025-12-25T13:05:00.000Z" title="发表于 2025-12-25 21:05:00">2025-12-25</time></div></div></div></div><div class="card-widget card-categories"><div class="item-headline">
<i class="fas fa-folder-open"></i>
<span>分类</span>
</div>
<ul class="card-category-list expandBtn" id="aside-cat-list">
<li class="card-category-list-item "><a class="card-category-list-link" href="/categories/Java/"><span class="card-category-list-name">Java</span><span class="card-category-list-count">10</span></a></li><li class="card-category-list-item "><a class="card-category-list-link" href="/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/"><span class="card-category-list-name">数据库</span><span class="card-category-list-count">10</span></a></li><li class="card-category-list-item parent"><a class="card-category-list-link" href="/categories/%E7%AE%97%E6%B3%95/"><span class="card-category-list-name">算法</span><span class="card-category-list-count">80</span><i class="fas fa-caret-left "></i></a><ul class="card-category-list child"><li class="card-category-list-item "><a class="card-category-list-link" href="/categories/%E7%AE%97%E6%B3%95/%E6%A8%A1%E6%9D%BF/"><span class="card-category-list-name">模板</span><span class="card-category-list-count">2</span></a></li><li class="card-category-list-item "><a class="card-category-list-link" href="/categories/%E7%AE%97%E6%B3%95/%E9%A2%98%E8%A7%A3/"><span class="card-category-list-name">题解</span><span class="card-category-list-count">75</span></a></li></ul></li>
</ul></div><div class="card-widget card-tags"><div class="item-headline"><i class="fas fa-tags"></i><span>标签</span></div><div class="card-tag-cloud"><a href="/tags/Java/" style="font-size: 1.45em; color: rgb(165, 151, 93);">Java</a><a href="/tags/IO/" style="font-size: 1.15em; color: rgb(152, 83, 195);">IO</a><a href="/tags/%E9%9B%86%E5%90%88/" style="font-size: 1.21em; color: rgb(81, 94, 64);">集合</a><a href="/tags/%E5%B9%B6%E5%8F%91/" style="font-size: 1.27em; color: rgb(127, 52, 50);">并发</a><a href="/tags/JVM/" style="font-size: 1.27em; color: rgb(80, 51, 50);">JVM</a><a href="/tags/%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86/" style="font-size: 1.15em; color: rgb(55, 195, 123);">垃圾收集</a><a href="/tags/MySQL/" style="font-size: 1.33em; color: rgb(176, 50, 53);">MySQL</a><a href="/tags/%E7%B4%A2%E5%BC%95/" style="font-size: 1.15em; color: rgb(50, 50, 66);">索引</a><a href="/tags/HashMap/" style="font-size: 1.15em; color: rgb(170, 50, 181);">HashMap</a><a href="/tags/%E4%BA%8B%E5%8A%A1/" style="font-size: 1.21em; color: rgb(50, 146, 143);">事务</a><a href="/tags/MVCC/" style="font-size: 1.15em; color: rgb(121, 111, 174);">MVCC</a><a href="/tags/%E9%94%81/" style="font-size: 1.21em; color: rgb(140, 50, 50);">锁</a><a href="/tags/Redis/" style="font-size: 1.39em; color: rgb(163, 183, 90);">Redis</a><a href="/tags/%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81/" style="font-size: 1.15em; color: rgb(50, 50, 184);">分布式锁</a><a href="/tags/Redisson/" style="font-size: 1.15em; color: rgb(50, 65, 50);">Redisson</a><a href="/tags/%E7%BD%91%E7%BB%9C%E6%A8%A1%E5%9E%8B/" style="font-size: 1.15em; color: rgb(50, 195, 169);">网络模型</a><a href="/tags/IO%E5%A4%9A%E8%B7%AF%E5%A4%8D%E7%94%A8/" style="font-size: 1.15em; color: rgb(173, 58, 55);">IO多路复用</a><a href="/tags/%E8%BF%87%E6%9C%9F%E7%AD%96%E7%95%A5/" style="font-size: 1.15em; color: rgb(132, 196, 90);">过期策略</a><a href="/tags/%E6%B7%98%E6%B1%B0%E7%AD%96%E7%95%A5/" style="font-size: 1.15em; color: rgb(50, 74, 120);">淘汰策略</a><a href="/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/" style="font-size: 1.15em; color: rgb(50, 166, 68);">数据结构</a><a href="/tags/Spring/" style="font-size: 1.21em; color: rgb(190, 54, 114);">Spring</a><a href="/tags/IOC/" style="font-size: 1.15em; color: rgb(152, 65, 50);">IOC</a><a href="/tags/DI/" style="font-size: 1.15em; color: rgb(66, 106, 160);">DI</a><a href="/tags/%E7%BC%93%E5%AD%98/" style="font-size: 1.21em; color: rgb(128, 50, 50);">缓存</a><a href="/tags/%E6%95%B0%E6%8D%AE%E5%90%8C%E6%AD%A5/" style="font-size: 1.15em; color: rgb(108, 59, 187);">数据同步</a><a href="/tags/%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%E5%99%A8/" style="font-size: 1.15em; color: rgb(101, 80, 50);">垃圾收集器</a><a href="/tags/%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E7%AE%97%E6%B3%95/" style="font-size: 1.15em; color: rgb(50, 61, 68);">垃圾回收算法</a><a href="/tags/Volatile/" style="font-size: 1.15em; color: rgb(143, 66, 170);">Volatile</a><a href="/tags/SpringMVC/" style="font-size: 1.15em; color: rgb(191, 50, 50);">SpringMVC</a><a href="/tags/%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B/" style="font-size: 1.15em; color: rgb(132, 184, 134);">执行流程</a><a href="/tags/%E7%B1%BB%E5%8A%A0%E8%BD%BD/" style="font-size: 1.15em; color: rgb(50, 50, 150);">类加载</a><a href="/tags/%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/" style="font-size: 1.15em; color: rgb(118, 99, 50);">性能优化</a></div></div><div class="card-widget card-archives">
<div class="item-headline">
<i class="fas fa-archive"></i>
<span>归档</span>
<a class="card-more-btn" href="/archives/" title="查看更多"><i class="fas fa-angle-right"></i></a>
</div>
<ul class="card-archive-list">
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2026/01/">
<span class="card-archive-list-date">2026年01月</span>
<span class="card-archive-list-count">1</span>
</a>
</li>
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2025/12/">
<span class="card-archive-list-date">2025年12月</span>
<span class="card-archive-list-count">9</span>
</a>
</li>
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2025/11/">
<span class="card-archive-list-date">2025年11月</span>
<span class="card-archive-list-count">8</span>
</a>
</li>
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2025/10/">
<span class="card-archive-list-date">2025年10月</span>
<span class="card-archive-list-count">2</span>
</a>
</li>
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2025/05/">
<span class="card-archive-list-date">2025年05月</span>
<span class="card-archive-list-count">1</span>
</a>
</li>
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2025/03/">
<span class="card-archive-list-date">2025年03月</span>
<span class="card-archive-list-count">21</span>
</a>
</li>
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2025/02/">
<span class="card-archive-list-date">2025年02月</span>
<span class="card-archive-list-count">15</span>
</a>
</li>
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2025/01/">
<span class="card-archive-list-date">2025年01月</span>
<span class="card-archive-list-count">13</span>
</a>
</li>
</ul></div><div class="card-widget card-webinfo"><div class="item-headline"><i class="fas fa-chart-line"></i><span>网站信息</span></div><div class="webinfo"><div class="webinfo-item"><div class="item-name">文章数目 :</div><div class="item-count">100</div></div><div class="webinfo-item"><div class="item-name">运行时间 :</div><div class="item-count" id="runtimeshow" data-publishDate="2024-11-06T13:58:31.000Z"><i class="fa-solid fa-spinner fa-spin"></i></div></div><div class="webinfo-item"><div class="item-name">本站总字数 :</div><div class="item-count">58.8k</div></div><div class="webinfo-item"><div class="item-name">最后更新时间 :</div><div class="item-count" id="last-push-date" data-lastPushDate="2026-01-24T20:56:06.403Z"><i class="fa-solid fa-spinner fa-spin"></i></div></div></div></div></div></div></main><footer id="footer" style="background-image: url(https://oss.012700.xyz/butterfly/2024/10/index.jpg);"><div id="footer-wrap"><div class="copyright">©2019 - 2026 By 彬子</div><div class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="darkmode" type="button" title="日间和夜间模式切换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside-config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button id="translateLink" type="button" title="简繁转换">繁</button><button id="go-up" type="button" title="回到顶部"><span class="scroll-percent"></span><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="/js/tw_cn.js"></script><script src="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox/fancybox.umd.min.js"></script><script src="https://cdn.jsdelivr.net/npm/instant.page/instantpage.min.js" type="module"></script><div class="js-pjax"><script>window.typedJSFn = {
init: str => {
window.typed = new Typed('#subtitle', Object.assign({
strings: str,
startDelay: 300,
typeSpeed: 150,
loop: true,
backSpeed: 50,
}, {"loop":true}))
},
run: subtitleType => {
if (true) {
if (typeof Typed === 'function') {
subtitleType()
} else {
btf.getScript('https://cdn.jsdelivr.net/npm/typed.js/dist/typed.umd.min.js').then(subtitleType)
}
} else {
subtitleType()
}
}
}
btf.addGlobalFn('pjaxSendOnce', () => { typed.destroy() }, 'typedDestroy')
</script><script>function subtitleType () {
fetch('https://v1.hitokoto.cn')
.then(response => response.json())
.then(data => {
if (true) {
const from = '出自 ' + data.from
const sub = ["今日事,今日毕","Never put off till tomorrow what you can do today"]
sub.unshift(data.hitokoto, from)
typedJSFn.init(sub)
} else {
document.getElementById('subtitle').textContent = data.hitokoto
}
})
}
typedJSFn.run(subtitleType)
</script><script>(() => {
const runMermaid = ele => {
window.loadMermaid = true
const theme = document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'default'
ele.forEach((item, index) => {
const mermaidSrc = item.firstElementChild
const mermaidThemeConfig = `%%{init:{ 'theme':'${theme}'}}%%\n`
const mermaidID = `mermaid-${index}`
const mermaidDefinition = mermaidThemeConfig + mermaidSrc.textContent
const renderFn = mermaid.render(mermaidID, mermaidDefinition)
const renderMermaid = svg => {
mermaidSrc.insertAdjacentHTML('afterend', svg)
}
// mermaid v9 and v10 compatibility
typeof renderFn === 'string' ? renderMermaid(renderFn) : renderFn.then(({ svg }) => renderMermaid(svg))
})
}
const codeToMermaid = () => {
const codeMermaidEle = document.querySelectorAll('pre > code.mermaid')
if (codeMermaidEle.length === 0) return
codeMermaidEle.forEach(ele => {
const preEle = document.createElement('pre')
preEle.className = 'mermaid-src'
preEle.hidden = true
preEle.textContent = ele.textContent
const newEle = document.createElement('div')
newEle.className = 'mermaid-wrap'
newEle.appendChild(preEle)
ele.parentNode.replaceWith(newEle)
})
}
const loadMermaid = () => {
if (true) codeToMermaid()
const $mermaid = document.querySelectorAll('#article-container .mermaid-wrap')
if ($mermaid.length === 0) return
const runMermaidFn = () => runMermaid($mermaid)
btf.addGlobalFn('themeChange', runMermaidFn, 'mermaid')
window.loadMermaid ? runMermaidFn() : btf.getScript('https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js').then(runMermaidFn)
}
btf.addGlobalFn('encrypt', loadMermaid, 'mermaid')
window.pjax ? loadMermaid() : document.addEventListener('DOMContentLoaded', loadMermaid)
})()</script><script>(() => {
const $chartjs = document.querySelectorAll('#article-container .chartjs-container')
if ($chartjs.length === 0) return
const applyThemeDefaultsConfig = theme => {
if (theme === 'dark-mode') {
Chart.defaults.color = "rgba(255, 255, 255, 0.8)"
Chart.defaults.borderColor = "rgba(255, 255, 255, 0.2)"
Chart.defaults.scale.ticks.backdropColor = "transparent"
} else {
Chart.defaults.color = "rgba(0, 0, 0, 0.8)"
Chart.defaults.borderColor = "rgba(0, 0, 0, 0.1)"
Chart.defaults.scale.ticks.backdropColor = "transparent"
}
}
// Recursively traverse the config object and automatically apply theme-specific color schemes
const applyThemeConfig = (obj, theme) => {
if (typeof obj !== 'object' || obj === null) return
Object.keys(obj).forEach(key => {
const value = obj[key]
// If the property is an object and has theme-specific options, apply them
if (typeof value === 'object' && value !== null) {
if (value[theme]) {
obj[key] = value[theme] // Apply the value for the current theme
} else {
// Recursively process child objects
applyThemeConfig(value, theme)
}
}
})
}
const runChartJS = () => {
window.loadChartJS = true
Array.from($chartjs).forEach((item, index) => {
const chartSrc = item.firstElementChild
const chartID = item.getAttribute('data-chartjs-id') || ('chartjs-' + index) // Use custom ID or default ID
const width = item.getAttribute('data-width')
const existingCanvas = document.getElementById(chartID)
// If a canvas already exists, remove it to avoid rendering duplicates
if (existingCanvas) {
existingCanvas.parentNode.remove()
}
const chartDefinition = chartSrc.textContent
const canvas = document.createElement('canvas')
canvas.id = chartID
const div = document.createElement('div')
div.className = 'chartjs-wrap'
if (width) {
div.style.width = width
}
div.appendChild(canvas)
chartSrc.insertAdjacentElement('afterend', div)
const ctx = document.getElementById(chartID).getContext('2d')
const config = JSON.parse(chartDefinition)
const theme = document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark-mode' : 'light-mode'
// Set default styles (initial setup)
applyThemeDefaultsConfig(theme)
// Automatically traverse the config and apply dual-mode color schemes
applyThemeConfig(config, theme)
new Chart(ctx, config)
})
}
const loadChartJS = () => {
window.loadChartJS ? runChartJS() : btf.getScript('https://cdn.jsdelivr.net/npm/chart.js/dist/chart.umd.min.js').then(runChartJS)
}
// Listen for theme change events
btf.addGlobalFn('themeChange', runChartJS, 'chartjs')
btf.addGlobalFn('encrypt', runChartJS, 'chartjs')
window.pjax ? loadChartJS() : document.addEventListener('DOMContentLoaded', loadChartJS)
})()</script></div><script data-pjax src="/self/btf.js"></script><script defer="defer" id="ribbon" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/dist/canvas-ribbon.min.js" size="150" alpha="0.6" zIndex="-1" mobile="false" data-click="false"></script><script src="https://cdn.jsdelivr.net/npm/pjax/pjax.min.js"></script><script>(() => {
const pjaxSelectors = ["head > title","#config-diff","#body-wrap","#rightside-config-hide","#rightside-config-show",".js-pjax"]
window.pjax = new Pjax({
elements: 'a:not([target="_blank"])',
selectors: pjaxSelectors,
cacheBust: false,
analytics: false,
scrollRestoration: false
})
const triggerPjaxFn = (val) => {
if (!val) return
Object.values(val).forEach(fn => fn())
}
document.addEventListener('pjax:send', () => {
// removeEventListener
btf.removeGlobalFnEvent('pjaxSendOnce')
btf.removeGlobalFnEvent('themeChange')
// reset readmode
const $bodyClassList = document.body.classList
if ($bodyClassList.contains('read-mode')) $bodyClassList.remove('read-mode')
triggerPjaxFn(window.globalFn.pjaxSend)
})
document.addEventListener('pjax:complete', () => {
btf.removeGlobalFnEvent('pjaxCompleteOnce')
document.querySelectorAll('script[data-pjax]').forEach(item => {
const newScript = document.createElement('script')
const content = item.text || item.textContent || item.innerHTML || ""
Array.from(item.attributes).forEach(attr => newScript.setAttribute(attr.name, attr.value))
newScript.appendChild(document.createTextNode(content))
item.parentNode.replaceChild(newScript, item)
})
triggerPjaxFn(window.globalFn.pjaxComplete)
})
document.addEventListener('pjax:error', e => {
if (e.request.status === 404) {
pjax.loadUrl('/404.html')
}
})
})()</script><div id="local-search"><div class="search-dialog"><nav class="search-nav"><span class="search-dialog-title">搜索</span><span id="loading-status"></span><button class="search-close-button"><i class="fas fa-times"></i></button></nav><div class="text-center" id="loading-database"><i class="fas fa-spinner fa-pulse"></i><span> 数据加载中</span></div><div class="search-wrap"><div id="local-search-input"><div class="local-search-box"><input class="local-search-box--input" placeholder="搜索文章" type="text"/></div></div><hr/><div id="local-search-results"></div><div id="local-search-stats-wrap"></div></div></div><div id="search-mask"></div><script src="/js/search/local-search.js"></script></div></div></body></html>