-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsearch.xml
790 lines (379 loc) · 781 KB
/
search.xml
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
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>MythicGuide</title>
<link href="/post/8f75096f.html"/>
<url>/post/8f75096f.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="MythicGuide"><a href="#MythicGuide" class="headerlink" title="MythicGuide"></a>MythicGuide</h1><p>”磨刀不误砍柴功“</p><p><a href="https://blog.luhuhu.cn/post/8f75096f.html">LINK</a></p><h2 id="大秘境"><a href="#大秘境" class="headerlink" title="大秘境"></a>大秘境</h2><p>WOW 11.0 S1 大秘境内容</p><ul><li><p><a href="https://ngabbs.com/read.php?&tid=41039556">debuff相关</a></p><p>带标签的debuff:<br>进攻驱散(魔法):萨满、牧师、法师(法术偷取)、牧师群体驱散(5目标)、术士的狗、猎人(宁神)、恶魔猎手<br>进攻驱散(激怒):猎人、德、唤魔师(压迫怒吼,群体,cd长)、武僧(分筋错骨+天赋,单体,cd长)、盗贼(毒刃,这版本还是不是循环里的我忘了)<br>防御驱散(魔法):小鬼(术士),所有治疗自带,牧师群体驱散(5目标)<br>防御驱散(诅咒):萨满、德、法师<br>防御驱散(中毒):德、唤魔师、武僧、骑士。清毒图腾(萨满)<br>防御驱散(疾病):牧师、武僧、骑士<br>防御驱散(流血):灼烧之焰(唤魔师,三系,能驱诅咒疾病中毒流血)、保护祝福(骑士,三系,天赋)<br>矮人和黑铁矮人种族技能可以驱魔法诅咒疾病中毒流血,<br>血精灵种族技能可以群体进攻驱散魔法。</p></li></ul><ol><li><p>回响之城</p><p>爬行者:1号boss前面的蜘蛛,会大量的<strong>中毒dot</strong>。<br>戳刺飞虫:可叠加的<strong>流血</strong>,不过只会打当前仇恨<br>网法师:恶臭齐射,群体<strong>中毒dot</strong>,可打断。<br>3号boss:全是<strong>中毒dot</strong>,而且伤害都不低</p></li><li><p>矶石宝库</p><p>入侵者:虚空感染,<strong>诅咒</strong>dot,他现在改成瞬发了,能驱就多驱点,很疼的。<br>引擎语者:对坦克<strong>减速</strong>,可叠加,<strong>魔法</strong>。</p></li><li><p>破晨号</p><p>影法师:诱捕暗影,dot+减速的<strong>诅咒</strong>,解移动限制的也能解掉。<br>威胁不大,读的也不多</p></li><li><p>千丝之城</p><p>剧毒之刃:<strong>中毒dot</strong>,只会给t上。<br>3号前的大虫子:<strong>中毒dot</strong>,5人份,无法规避。</p></li><li><p>仙林</p><p>恶爪者(门口的小爬爬):身上自带有<strong>魔法</strong>buff,这个buff会导致他死亡时出现地板圈,踩中会10%易伤,属于<strong>诅咒</strong>,敌我不分。<br>这个怪通常不需要起手大驱/奥术洪流,因为没有后续伤害,易伤能加快清怪速度。<br>塑型者:木棘外壳,敌方buff,如果没打断需要<strong>进攻驱散魔法</strong>,触发了以后是个带伤害带定身的<strong>魔法debuff</strong>,没有还魂/大驱基本全死。<br>追猎者(狐狸):<strong>流血</strong><br>蛾子:<strong>魔法debuff</strong>。<br>照看者:大回血,敌方buff,如果没打断需要<strong>进攻驱散魔法</strong>,也就血精灵和牧师好搞一些,换个单驱人他已经全队回满了。<br>掠夺者(蜻蜓):<strong>中毒</strong> </p></li><li><p>通灵战潮</p><p>凋零之袋:死亡时自爆,伤害+dot,<strong>疾病</strong><br>1号boss:喷吐除了高伤还会带一个<strong>疾病dot</strong>。<br>刻骨者:白骨剥离,高伤+dot+降血上限,<strong>流血</strong>。<br>采集者(2楼):淤液喷洒,群体<strong>疾病</strong>dot。</p></li><li><p>围攻伯拉勒斯</p><p>破浪者:闪现+正面锥形dot,可规避,<strong>流血</strong>。<br>塑浪者:防水甲壳,敌方buff,如果没打断需要<strong>进攻驱散,魔法</strong><br>咒刃:法术直伤+15%易伤可叠加,<strong>诅咒</strong>。<br>2号boss的所有dot均无法驱散。<br>劫掠者(2号后的鱼人):dot,<strong>疾病</strong>。<br>唤风者:虽然是魔法dot,但是他读出来你就死了,无所谓了。<strong>魔法</strong><br>杀手(楼梯前的一波,整个副本路上就两只):25%减治疗效果,<strong>疾病</strong>。<br>指挥官(骑马怪):会群体减伤buff,属于<strong>魔法</strong>。打断就行……<br>入侵者:平砍会给坦克上<strong>中毒dot</strong>,叠的飞快,伤害还不低,没啥好的处理办法。<br>4号的点名水dot。<strong>魔法</strong></p></li><li><p>格瑞姆巴托</p><p>暮光术士:点名2目标,吸奶盾+dot,钢条,<strong>诅咒</strong>,能解但是太多了解不过来,配合各类小怪combo都是要命的。<br>3号boss:3目标直伤+吸奶盾,<strong>诅咒</strong>。时间轴和击飞AOE重合,驱散需要卡轴(1秒内解掉且早于治疗出手,这样才能吃到奶)。</p></li></ol><hr><p><a href="https://bbs.nga.cn/read.php?tid=40888495">怪物说明</a></p><p><em><strong>TODO</strong></em> </p><ol><li>TANK细节部分后续添加</li></ol><h3 id="回响之城"><a href="#回响之城" class="headerlink" title="回响之城"></a>回响之城</h3><p><img src="https://oss.luhuhu.cn/202410111043598.png" alt="回响之城"></p><h4 id="NOTE"><a href="#NOTE" class="headerlink" title="NOTE"></a>NOTE</h4><ol><li>波次1颤声侍从(共振弹幕)远程打断、dk拉,充血爬行者(自爆)有点多,桥上位置不大注意躲避</li><li>波次2颤声侍从*2,需要安排远程断、拉,伊克辛恐惧安排盯断</li><li>波次3颤声侍从+充血爬行者*n</li><li>纳克特AOE安排减伤</li><li>5、6波次参考前面的处理</li><li>BOSS1,T注意蛋刷新位置,保持boss离蛋20码左右距离,方便近战转火,放水远程组、近战组集合统一顺时针或逆时针站位</li><li>波次7、8、9 哨兵优先击杀(钢条),血卫(减伤光环)主目标击杀,盯断沾血网法师恶臭齐射,可以看技能合并波次</li><li>BOSS2,面前的怪可以通过明月进战斗跳过,没什么注意点,放圈集中时T记得呆在圈右侧边沿,默认顺时针旋转,头前盯T位置</li><li>11 注意不要add旁边的虫子,蝙蝠无仇恨跳人,集中站位,12、13波次谨慎合并,存在地板晕combo情况,容易团灭</li><li>尾王,中毒点名之后,走好位置不要乱动,萨满的清毒图腾不要乱丢(团灭发动机),该踩黑水踩黑水,如果中场比较脏需要安排人清理,尽可能把中场空出来</li></ol><ul><li>这边1、2波次可以尝试合并,这边考虑到线路过长就拆了波次,如果要合波次就不要拉角上的颤声了(3个断不过来)</li><li>队伍配置建议:dk+冰法+奶萨+T+X,有冰法老一的小蜘蛛处理会轻松很多,如果都是近战层数高了容易被小蜘蛛咬死,dk在处理远程读条、哨兵的时候是不可或缺的,尾王死亡脚步可以卡时间可以无限续,无视机制</li></ul><h4 id="MDT"><a href="#MDT" class="headerlink" title="MDT"></a>MDT</h4><pre class=" language-bash"><code class="language-bash"><span class="token operator">!</span>TrvZsonpqWxPms<span class="token punctuation">(</span>3RFF7f4GzbNIJQQ8J8wbm2GJCy5gppCLd8grXJbAMwYwolvCsfjnt3t3ZiBiZEt75lDDxon37<span class="token punctuation">(</span>MPrzA<span class="token punctuation">)</span>Q1<span class="token punctuation">(</span>rtdzApC<span class="token punctuation">(</span>84W7TtxVmoyAYj<span class="token punctuation">)</span>zZxoBA<span class="token punctuation">)</span>YTxx<span class="token punctuation">)</span>2PJpSNENP90y<span class="token punctuation">)</span>40Jh6ToN9vdDJmGhMDJ<span class="token punctuation">)</span>pV<span class="token punctuation">)</span>LHNm<span class="token punctuation">)</span>3DXC<span class="token punctuation">(</span>zttMXzAD2N9<span class="token punctuation">)</span><span class="token punctuation">(</span>NF9ZF<span class="token punctuation">)</span>9FyAhp<span class="token punctuation">(</span>b7j3vF6<span class="token punctuation">(</span>nVDOF2YiDAEAYo4ECUVxkPW625J92BwS30Lo3B66UALSBibc3sSpmp8KDCq4LinZR9tCHD00E127jLLNKO<span class="token punctuation">)</span>XN3N9KTGu8NgDbBo8J2<span class="token punctuation">)</span>KZAOrx6TfzJcznwwjlR9z5dM2f<span class="token punctuation">(</span>s8wogaGhGRuYUIpqhoOKxK9pIsjCKjCKJJWzkUS9<span class="token punctuation">)</span>rSoXRnTDDABxxcHbvqqcbzStWtvlaQYaO5auPUAuvIuuLqgQIunOdgcH6RgMYUu1KlruelWftouMCrwBtsaHOaWQDaysaMQe4OsPmPAPmPTfufkOciVsiVcugipwqLaSkGI<span class="token punctuation">)</span>rNb5P1OtX9xP7XePbNehtEQ2Qs7uS7PGTPrLNb4ZL0KsUauNbQ131U02iERUtn3e95U6ClALPqbZrlogp07zlTBJPgebHHhwo5rLeXIGFZHOribdjh<span class="token punctuation">(</span>rry4nQCGRkv<span class="token punctuation">)</span>yWQompl5J2pdtHqrQC7oc5kstDNhI7ukDkLzBid9zQmrYVyUceuUXqeuik1pRIKBIxUd8T5QgADcFEb9scz68dYEdifncnfqXYWDkRbHGb96n<span class="token punctuation">(</span>Mc<span class="token punctuation">(</span>gEVcbBfTnsLkG6LRAB1pU<span class="token punctuation">(</span>xNmp5VRX2<span class="token punctuation">(</span>QcuBqBtHrfrlwmKQ48SB1c4qt9JQnOfF1vArfFNK4fXTpqsVILyIQOIa6zldaRZYQKMJousQncvycq6eBlf6SnMFzQ3Vl0WbMAZ<span class="token punctuation">(</span>7Fv1AzUEji<span class="token punctuation">(</span>X83p</code></pre><h3 id="矶石宝库-未完成"><a href="#矶石宝库-未完成" class="headerlink" title="矶石宝库(未完成)"></a>矶石宝库(未完成)</h3><p><img src="https://oss.luhuhu.cn/202409121320456.png" alt="矶石宝库"></p><h4 id="NOTE-1"><a href="#NOTE-1" class="headerlink" title="NOTE"></a>NOTE</h4><h4 id="MDT-1"><a href="#MDT-1" class="headerlink" title="MDT"></a>MDT</h4><pre class=" language-BASH"><code class="language-BASH">!vA1wpXTru4Fn9rqEU4XEEnnkQHirsLPvQVyfG1oL2T7wbEttFzfxsiCnqsAAcWcLKaP5guIsezz52pMUZ4DFQ)f6CX274DPpujJL3zoNVZ357CoZGpWFiFVcJfgo2Ovkg9R(dcS89(LGGFu8LV3WfkuU03gm(eJvUK)G2wU(EvgRGVh5Yx7R)oI3n(MV6799U9WfReiHz0kJpEqPOBuPyr)bHWSf8QmsXGBhuub5pl2DcH1dcmEjFGQhK6blcM6r8br(ej3m10iPng)a)FccwST3OLlwECFVWquqyyksPRkxJg0bDBtajMHcNaDKXI6DCmPh00hOjA2Drguq6UDidvsXmSYfsBdddddhr4(GahdDiss4HsEPIN0BvoikQdzOpkvdc7s2mOQkJaadWn1lnXDYXhj17eAxfKAuYv3YiIJYcSQqzB8brNiUkZa5ynkha6qqv(bCviaODruPwIZSpQd)OAzGO92r7TTo00C5fvRZPrfyNZtS2Z8Yvc4wkt0mZjl3YOGoTayDqvbOd1vDQDmfAIiaKlA6EKeURwnfMHbQsLuwmQaqR8Tm66djNsJtgHsQYD144EbTfjdxQMutWZnNKwYI6z6ZT3cDosNYIKrbGQOAN5KHfDKJEh1a2MUPBN6sIbMHgLigrDpGkDKyMzIsJHW0HdYoZHYXf9Cl1K6qBLnsR1zbs9BnDtXOBbpzouZJuqmvEx)EhptlhjzgSZXKAzgycswkMvy0aBoFKoKLzkQt5jx5mTXRNbl7l0rsw3M0rGFVZgGCv)mhZnnanpOpDAacYjurz3sD5kLUvq5sxTWDe7jVfmki4NgR0T8hX3BIGIbJgjVemjOYO6n(yHrxpmCIGOSl0sGmk4oI3Tp(zT2FhFVYJ8dcVv2OyubT1xb76GiicaIrowiXLRH9HvjWv6d7IWU2aSnfcaiStYwOKK8sYC0J)Sh38KDkemsLWWQ3KTYFXwzB2cB)pNSe)JVMF3vyFyA(toO6nB)YheV3MvhiE)9y78PMNUC8P7ZRnp7Z7g)6f)7jNk(p2VzJgXRFxG1xWU3RBnZPsefWWE108TQX29HSvNtaFZJ3T9KZZx8n85Fm)bZlt0scQePVVlnTYML6MUHH6MfrXTp5jMEf1o4brU9RQ4E9bPo9tukycyw6sj2u3ioe5dqinelXFg6Mdriwuc0XXHISWq5w2DtKwNVwRZokE2f4p7b8AjzgFHfAF)LAV5le6aFY3YxCE29BW3Cx2Jwcjt)JoS6aa2kF(sx3ZtlVXtFu1b4lU8qcpslcTFZh4p5Lnpz94JxJD)veLhPmU7HSxnxRxnvCTf5p9qETgAZQoq7nMTz99IF3AIIsY3VDk2Cn4)(rnp7C2b3nUX5863lE1zRoGHCB))vUDZj3qN(rjYTTB)osh9Gyy)Q7H96dzz1VLrn4kUcT2M4IHueesv9P2jNgqY1ptaeKRLnYgsSCTWsXNKuxqyBrFoaHWwcKOxy)mSx5Tz9DAw)TcPJT6ssPBVJf6zZ6llftHQvFpwTgz97yHP6UBXg8NUD8uVtuAy1oqiNgQNJjNTPwakLGOoowuasrmuYmiLsXqIdWYgGCfhWEr9sOlGZNTj)9pV1PVxeF2bRiAMK9aQpe8VzJNhpDDrJbB)pkxxLxQvwN9ITeJVq2KlR3MTXlINApfMIKOz9fAF8dJxDg2QZ0SXSAJJ3(tXBCMyILTWgc0U81Ip(84tFJULMDpfqRoJrY7AM8UwUySTf1smZqD0zyYGKlgafLtXXscna7aVWcgU3KV9MB368hkik)tBLmyD4CTxBNKtuAD(g69I)ZhX3CszP73oJvBoncsNp7iXkDiC6nE3y4IbrrbxTuyzzgmCLOYFPCD5b0xQlBKNGR))Q8)3p</code></pre><h3 id="破晨号"><a href="#破晨号" class="headerlink" title="破晨号"></a>破晨号</h3><p><img src="https://oss.luhuhu.cn/202409121517147.png" alt="破晨号"></p><h4 id="NOTE-2"><a href="#NOTE-2" class="headerlink" title="NOTE"></a>NOTE</h4><ol><li>BOSS1射线T安排减伤,远程集中站位 集中放圈</li><li>BOSS2注意站位(后面有个好战者 拉到就团灭)、放球方向</li><li>尾王注意波的方向、搬炸弹</li></ol><ul><li>比较简单的本,没什么特别需要注意的</li></ul><h4 id="MDT-2"><a href="#MDT-2" class="headerlink" title="MDT"></a>MDT</h4><pre class=" language-BASH"><code class="language-BASH">!LI12UXXXr0Vg)ix03V8yucmSfqOjWs4hhesXDnyYgYaYHokVqiRihsQBuooYw2sugsw2Xq2uYaorIM6c)z2zxUpLFH0Dv9mDnlvSaJiwqSZzNUQQR(CQQMPGxmFr3LwUF)Lp3gdk)lfZYzfD3y5Lk6QN7x9oZoyJ3)Dm)2IUlS0sRUY73BT1xE1vkMvZffD)WfgSrV4Qp3gRTwVvkNBJbdclx1a0DJfh07d7fbl6(Nc)66H7Ewo5FXpc4Jm(Pm(15jO8iKS5EldME1bRUwr3(9L963pGfnujzH4TQOMcSR6vyKOj89iUaVfn4Ad11IPCTShXM4TyHv5Oow1YxEiG1K4OS5seZ3Yl9xm4LM4wqUB4IYyioFR9s8(5t5aB8sttmwJWHuhKIbl7A27Hlcma8kdCh2P28ykZrnmxrTS0HhPEQLdgLAAHFQdIqYPmMcOKdwlp7HesJlTTSEA7wB)5BzDKRyauyjX7u2orXBZlP8Kf4yUTX1AQRDP1loPNRzPjp3K5X8QIrntMWNdoojejPUM78KezUQ1Xc1RA6MV2wsAOp70kmKMduQP5XCZuPpkzSM8YvT2a2wxPlqLBzt9IFZgR8b9wDL3DPZh37HAgL969hxELpOyXIUR3BqVZvgl(qyCDxB5(LVx)(R3RC9C2VSzxm3cd6vw27DxP)QXOBHnkx9xhXJ28mtDprNc2SS35d)FYZU1Xp6bB(7c15wDXFFW1noO7kX1UeE5BB4oU06SEU0jcFk6pJsgpGE7zmEgZ5vkLMj5Sqah(jnuPJhD1zIhjDNF2QT3A01U)KV(UhFVR(FE(vR(Xxo(6xP6BV4O7ENJp6RQ2(hh(8VS623F8hT)MNLxT7tpZ71T7OF67gDPDhFXFEZZo5zFYOBFNQpENr79vHLp57V1K7V3OD(05dxC83(rdp8bvp4FwT1UBE2WTxDJRvT1Hdp8WXV8bJ(hVS6oBhUln7TgEWLR27gtE4NmE)DoERho8O9kAkQwVvJ0eK4n1wOp8huTyghKbt5MzSELHlzsPskSARmKb0rAy3b4D01O1DGIfDNriKDmrt31R7OJwV7mExhggiYtBGyPbIX7DoUtXDsJYfoecXbNghCdVJcJdU21XcXHuP7iXaHBuDs6C1BuKOvERqy9cpxjnHIGHirqJePXh2ZygHX64Hir481rII7RZj6wrc)1hjoQJesW6rhPeQ0wM7vX8q0rsVOtRqFgJYha1(qw0Z0avxllYDI()ouIzxogksVmU9JHcNxhkkTPtlIvi)zSENwQ9gMt5jrI9xosw81KuczcrDsbOMXiXABskoEhr7KItBKgjZOfwfNrtk(3OqHRJ5FmP4SjIaNPIPhmP47OOHIZASmLLzeHcrsHJej8tw3kK1crTYeYJENrOtfNI1TCCbZkKbTPsXesB8Nuth3JVXFfRNm(7)IJF6JhEW(t(8)vSKZtFC1lV0Xp5YtU5rdF(dQE0pf((WxC9ICtss2w0rN2IHCmsbfcwSoaKTTWx1nGMmOncYJFZfbnqEX3aghITgLdUY3b1Rryo8DzgwrGJUtAI6no4pd4pUnd7iWrxQWTblbhjq8mSGahDPYgxOaDjyqHodBiW2mm4slAqFdSKLHLGl1qweZOWwtkZWkcmSl9Grax6uaB3MHDe4OlLIijubU0bguXZWccmKyJs2zvQeCS6LodBiWPtYi3YLdqLVbwZYWAEdzqJ7YuPHADMcLzD(ffA2i)5mf5rTMQNUZPCSybAj3AeqpDdQnSbXbxZT6qDyRnK6EvAd1j7sBgEWdhFXdQE(pF8l(H5ebHIyYTEYOh9VRc96V8TdTOh)Lx64hVx1UpE4Z(MQRDVHhCHHhCLX38lGVKwB12)THhSZOF4EHlh9S7fm1WdVkANnp7CcuqE8r3D8Hhn6k7m6Z2pm6qCLF83fgGinmWw7gKLb)ByV14N9PHHggT9Tg9zFEkzOARpbTuT(u0Opfz9jVrFkY6tEJ(KxRpLroA(mnPpbuuF66iQ1NABKKG6tewrGbMlqlr9zc2MHDeyqSWHoDGldD3D16tewqGbXIdAgH6tb0mwNHne4Ol1OrWnjm5aOpryuFIWG(uRIu(K(eLwYmSIaRrJOA0NCOVOnd7iWWUewysFkHow8mSGahDP0bvzvjrET(mbBiWwuKZQ1NyjbLVbg1NimQp1r3ORDzirOLzyfbw3qY0MellKQ05I7AhbotFmyjHOrEJ0(620DwdDpmxAA0lmQjSbDdiHlajjwUDeqB9nGCwgfO7syhXRjcQeDpbRiWa3dYwiD36BAhLGDeyG7XYTJWkYaDpbtkud0DnWGq6UZGJ8DQsOgAc18)Q(rW011pG5Aing0nGK2cafqgPuUmx03aYzzuEAWnFDcfP5y9dewrGtTHy1juNaGTzyhbgCPfK(Ol5qwKNHfe4ujlztcfZ56mSHadU0dp4b5meQFGWswgwMMzx3u)aKQq9JeSIadIzEU)UfhyWMHDe4Ky2wx)WAO93T11psWGlL5(7wyszS(Hm3FpbNkm7B6VtQFaWP(756hHXS4n93bdc1psWkcm4sOZuQ(bmmcu)ib7iWGlHJbt9GtHJBdpdliWGlHJbd6sqOy0zydbg0JWXGbDjdG9nWwwg2MA)eLo44HWWnwzgwrGHsaWXGfl5aTIS2mSJadUeQm4WQoan1XZWccCA8Wqq5QNinK2C6mSHadUeogCOlbTQZ3a7zzyp4s4yWJUefXYmSIaNhc2BsWStDXOwv3B)SGN4r1FvRM(8uco3Zn(WZf4LQajn98u5hv36BEPbyb14lnGXRhpsKkNwcLuEdcLzzu3QzY6QQCr8vLGEWFA9qRNO2O0cpNfE0EHp(OFNyZwp)t8KjvCk(4OU6A5Heu9MvWoXe1kh3OdKiLsyzHPRjtuR8HNxn(yO6qxvnZL(P2XDyg1X38BQE0tgD0fgDH)Ey81r7C7HhCTHVyxCI5jF91hVF9lTIFAtft9YImwBijBySWO(Ux9llk9sRiVSiVi)YIIfSXq518c0EDuqM1l5mTWz1wf3CskyG3vZfWMHWBlcKIG2kCa5lsVs0)CVE)H4Qklk(Vd</code></pre><h3 id="千丝之城-未完成"><a href="#千丝之城-未完成" class="headerlink" title="千丝之城(未完成)"></a>千丝之城(未完成)</h3><p><img src="https://oss.luhuhu.cn/202409121520190.png" alt="千丝之城"></p><h4 id="NOTE-3"><a href="#NOTE-3" class="headerlink" title="NOTE"></a>NOTE</h4><h4 id="MDT-3"><a href="#MDT-3" class="headerlink" title="MDT"></a>MDT</h4><pre class=" language-bash"><code class="language-bash"><span class="token operator">!</span>LI1spY1rv4FrtR69JLyqrkcrJL7iwELMXZTJgsZmOXDhm7mBWeLOebSadeweKrcfICwyuijoc<span class="token punctuation">)</span>NXZ4zwXFbQZ3PQBDU9msilK8JB<span class="token punctuation">)</span>9vv9DQtDEu37GE4DgwD8jRxFY93Tz7VCyPwnS6xmo<span class="token punctuation">(</span>ELNgwD4XhF2P<span class="token punctuation">)</span>KXZFWjND6WsVknSA3jhxW<span class="token punctuation">)</span>H675U3MD<span class="token punctuation">)</span>OV3dhw9<span class="token punctuation">(</span>hUz3iTm3F35NpE627UBZMHLg9eWQDhTz89h3GL8NxyFqz0l1I<span class="token punctuation">)</span>zPRmHHL2HT0<span class="token punctuation">)</span>FdiBfsx<span class="token punctuation">(</span>XQ7F2MZoFy1612X1RH9khVNg9Ya<span class="token punctuation">(</span>zSm82c2wcdHmnhnpjDaZshX00EHmKi5rHrWtmZZtTNbzhflUrHbvCeyXtSjY2Ool3xw2qDWj20npF7znS<span class="token punctuation">)</span>WIvZKXQzD8owHTS1t75L2YOlIzJWmTjSilDL<span class="token punctuation">)</span>Qj3eTTllKJSFAXcSBWX78L2m7pC2MjrQ7LMRNnxVWCxVE9ryZNfhvBjR6DM5kPX4NpK4SLH2380edjT3QqoMG8ankgpgTyY5zRFgMzq44NMmhAONp7Q<span class="token punctuation">)</span>xFBQzLQzMf0WXMHPqZT912OKgRrp7xKVPVohQzpM2a4T1N2pfW09OiGBAGsmkQXXbnCeyeXm0rD5jk6Kcu8YTupdKwq7Ehc05KzMVZm7mPBbSjOzBqZ2HU5tC7THO970gYnBHMNqrzs0cLX2X4W2XWPaflH2og7mZkmWviyH9d3s2MSsd5BAU9WWTeRhUf3UFMlWDlhcn<span class="token punctuation">)</span>zC4MPg5PilAWr2HjkTXBYeOY4bpEGsW1OiaV2PHBMtzK7TTdCQ6<span class="token punctuation">(</span>zvt2VDM9hHbWXoCDmp<span class="token punctuation">(</span>tvVAiDAMZtMtUx<span class="token punctuation">(</span>xlUF<span class="token punctuation">)</span>8fJrUcg3mdE7u<span class="token punctuation">)</span>KFWUtF3XZo9Tp<span class="token punctuation">(</span>HfUInUA744p7KtF3HJgw9GXnJ3Fl1UQEoa5p<span class="token punctuation">)</span>K1B<span class="token punctuation">)</span>XRx<span class="token punctuation">)</span>GXTtTEQl52Xhw<span class="token punctuation">(</span>3RFXtU6zpDy1zh9tlZEAmRoE25HEHUFIChYbqXc1Qrlpahl3Hw0n80w5ZMfiOB1bwLAbvuMa9lq17vhyYHf4mSbg6GXHvHYCmKdNaTlWrDdKAt3qljyfyljL2aynTcLG5jyNa2tWXfCYpbRwWn<span class="token punctuation">)</span>MGtcyssTEHdNYf4uMGPU7nyJaMKu7bmKmLaSVdheWKKgfCrqYuCb3BRbBvDyljPXdywYaT5T2oStatsA5tSqfwJMItWjbmjP1rY4uDyNUdBeWKKw4QCobSVdlK0rs6mlOEWcjD5jyVqspjPJdles6TDyHKEsspCv<span class="token punctuation">(</span>MKu59yhojGjj9y7eeo2GUdBeWKK<span class="token punctuation">(</span>efSfeNLbFhwCwgijdoY1hAHpfJnKNGJQoCKKmKOnF0udKPNTDyNaMKmQXI0YqksgJD4KaMKmAxuQzLyjZKKjDh2iGjjJEatsAviLk57WbbmKmsgvkbyCKKYtWzvhodjX2jJAaAfE22HDcyizgpcj1CkFSdNeWzgM6DRGM6ixxqlimscs2KIjGUM6p8cIGKikiG2gCsQv5obke1iqLOe2oAukYAI8OSccNKWZod8meVKDIFefejjr1ztfNqjjBjdL6bIAsncJKOEgtIJYswlVUgVGiijG4gSNqPjBjtf3Hj3jqXPgbQofqrqnkpzDoSuO<span class="token punctuation">(</span>uJWjjiXdEUsneVKFJLkkisscKmHeiTJfNDIOovJWijqomF24yXZyPqTQgrqsulDGLkvjiNiQxvj8kbbxXcb<span class="token punctuation">)</span>AuYY65ouCnRkHtsqI74gtOSfrqMlQB1isscuFoZ9Suvc8IkAbHrsGA0OGGoWIJUvAu<span class="token punctuation">)</span>QreKe9wd6qQsqIJAyvIOsqGQyMa0lAQe4hwbHtsqIBWLc0rwCo8b1YAejjb6<span class="token punctuation">)</span>YlvsvjiZf1ZAegjb6bZ7jUKwJWlicsIARFSujjrUtKLIJkBkhm3SuCuBRrifhv3uS4z5oh13AeYDovHJUweU5HQtyuAbHrsGBxX3NqjC7gLxqeKefX9Pip7KKi3j0kbbvHZNSmHPhmyOkCteojbjEmZZoijIcIKKGepg4lxP6HOgQc3eHrsqIxklrZ24KeEbrqsqIxklrV6KjjjYDcRuCQcNV0CMmxBx8PpXY<span class="token punctuation">)</span>3xwMlRYLVcKfBzlXWxwMQPL5llZGHoi2m<span class="token punctuation">(</span>2LLPAaoCz5kOw1r11TbkTdylIVTDyNaU7<span class="token punctuation">)</span>QNDEorUdNeW4GZZHtao28qwHh6TCLqRseA04DgBUKLT<span class="token punctuation">(</span>ah8AV1bHqPPxwftXItixsokuU9DKx<span class="token punctuation">)</span>zF7L<span class="token punctuation">)</span>HV66F3V5Yp4F<span class="token punctuation">)</span>F<span class="token punctuation">(</span>Up6Ip9VF1l<span class="token punctuation">)</span>Jx<span class="token punctuation">)</span>4p6Yx<span class="token punctuation">(</span>Ol<span class="token punctuation">)</span>NV4I<span class="token punctuation">)</span>2ZF9h<span class="token punctuation">)</span>HV6B<span class="token punctuation">(</span>Wx<span class="token punctuation">)</span>PFh5Gpf<span class="token punctuation">(</span>z<span class="token punctuation">(</span>Rl1SaFPbtU0pQy4opvONLHSaxWLlLLDQuPkrOuMPq533cE9x8fV6RF0Lp<span class="token punctuation">)</span>VEXl<span class="token punctuation">(</span>2RE2ZU6F98x91p9Ip5ZlwZvF5lU8V8zx<span class="token punctuation">(</span>Op<span class="token punctuation">)</span>Qx<span class="token punctuation">(</span>4lE6F6IN9nx<span class="token punctuation">(</span>KF<span class="token punctuation">)</span>1<span class="token punctuation">)</span>5F9R<span class="token punctuation">)</span>v<span class="token punctuation">)</span>JlE8NCXV9jcBY<span class="token punctuation">))</span>iU5OBe3eVrCtiIxubNLj<span class="token punctuation">(</span>TggWTiT14MOVg3ubdDWANwvnUjIPNNa54ggfxTjO5BxqWLHO54MgStaJ<span class="token punctuation">(</span>R4wG14gUhvSdNeWO3QbBdoUXXvf6WgbCTVk9boATvjyFhoiGrpv30lzzD4U74ImmC9EmagxJXH3fWAMYV6FkV3OZQBjhNFbtt1TM5CCnUvbFwblYpbg6Gukx5DiTTZQC9SQcwpRYTZkVg3VNpRs9C8kStatYzSCJFah5E9D4KaoZWP2zfEBP<span class="token punctuation">(</span>xY8nYdDZOzVbVKohHLN8qXf<span class="token punctuation">(</span>MhYsvX8tGHoi8qAYbWEOejEEcS6Hak8qL3sjm5HmTO5gStatYPm9Oz<span class="token punctuation">(</span>TpHhQcNeWKKkn3TDMhQ9HGU7HBg3UD8TpD9zKl7WDBp77t403W5o7ng6J8W1qh<span class="token punctuation">(</span>V</code></pre><pre class=" language-bash"><code class="language-bash"><span class="token operator">!</span>nA12UTnmm0VOgyrzDXV2nGHUb4wupGH9Iq8f5uV6yp4i3L<span class="token punctuation">(</span>s<span class="token punctuation">(</span>2NKVijNyVveafh6J45qsrgjqIVlsAZ<span class="token punctuation">(</span>LmxDs<span class="token punctuation">)</span>ymAxGXsJ4ErsXSHeeITJjIbZZ3fY47armw<span class="token punctuation">)</span>JH3ghQxUxetmV9P<span class="token punctuation">(</span>66l7RAuTx2312E8YEZtNuPDk9JViVS<span class="token punctuation">)</span>52A96t1PVVtOg<span class="token punctuation">(</span>KuuvwwL3xREFIJ<span class="token punctuation">)</span>iLVoYqYBP19sJKY776KnQp33Cq228qXzn7id1jNK1A5x12OHPSankzs<span class="token punctuation">(</span>kP8yvZbrCG5xDvLQhllpjhIy9g<span class="token punctuation">(</span>TgPxW7<span class="token punctuation">)</span>1GCgxW2fdPQrRFayypyOrtOapBH2TsSBLAFbByhj5T1TDIekNrtZVI8zhXTocHSEcb3QIjtHEMWRimKtziN0qoTHwkoaXzm<span class="token punctuation">(</span>vKn7SiNVcUvrRsVx8ezPhcC5mKnPbWcLeskra1lg95ICB0twHEWPyCGRW6kzyVAMROHTvTymzHOcGuAEQHhYen<span class="token punctuation">(</span>0HPo6yo64o6IS0fg4oJGS0fc2dbHyBkpC6u4qkC5XWzHvMX4rydi6igYMqdaGHigOSrm0nHYZ4HOHWLpIb4BIfhXXbdyJU1T<span class="token punctuation">)</span>Jwl2vECnSobScm1uVYwV1kqIKqr<span class="token punctuation">(</span>Nra0TT1qWMryuagIwYh8be<span class="token punctuation">)</span>yPFEEZ21fGMhLvo4Eyn3tCTsuxNmZ1jZxHILPakaaAmfGxJcx7c4AxaVjCZ57vMhUG2Wf0kjCcFyOcAUJnC7Xktb28ywYkJEPRoXmAbPfLHyAXcxqVACX42Cjt2vTuLzKqF<span class="token punctuation">(</span>I<span class="token punctuation">(</span>pvBBHE07eR3P2gCMvYCBOh5nrDMCwaJfn8NeOPgeaV5jhgPatg6Or8vcvSvLZZryRKt3UZUec45f<span class="token punctuation">(</span>dGay7Xa8mwjA8kbt<span class="token punctuation">)</span>jEsFwT8nzTfQsEwV<span class="token punctuation">(</span>CAvHSB3dpEz<span class="token punctuation">)</span>p0xvO<span class="token punctuation">(</span>DZ1k6v67vC3L9333OKnIKJfvM7nu2jLV0wx812QgzHiZzz62bzYd9v1d3pyIK<span class="token punctuation">(</span>QcDM5N0p9AYHZN<span class="token punctuation">)</span>2x02e<span class="token punctuation">)</span>fa</code></pre><h3 id="仙林"><a href="#仙林" class="headerlink" title="仙林"></a>仙林</h3><p><img src="https://oss.luhuhu.cn/202409101155220.png" alt="仙林"></p><h4 id="NOTE-4"><a href="#NOTE-4" class="headerlink" title="NOTE"></a>NOTE</h4><ol><li>波次1要等下110走过去,不然容易拉到左边的怪</li><li>波次2收割精魂注意风筝,一般直接去开第3波次,打完吃增益开BOSS1</li><li>BOSS1爆发留给虚弱阶段,正常情况下两个波次要打死</li><li>迷宫注意心能挥砍安排减伤,明月可以 拉门里的怪,在我的路线中迷宫走完需要到**62.4+%**进度</li><li>尾王前第一波怪可以选择跳过,隐遁、冰冻、禁锢、隐身可以,波次6注意要拉到最上面的两个苍蝇,不然会缺进度</li><li>尾王出小怪T脚下集合速度清理,马上就是拉线,AOE阶段不要贪伤害活下来优先</li></ol><h4 id="MDT-4"><a href="#MDT-4" class="headerlink" title="MDT"></a>MDT</h4><pre class=" language-bash"><code class="language-bash"><span class="token operator">!</span>TrvsVrnmu4FrLANeVXXsvf9sOiJ4OrzMXEiqiPAgN2cNgbcXfelxGkHaPk6b4q5cNaQG<span class="token punctuation">)</span>mmWmN4VaEjBUWmrr2p7VL3ZphbuCdbFsUsLpUUqFFrkei4hkL31msWZMmPQ8MYzZZRkfPiavWRZNi4Joa<span class="token punctuation">)</span>a11rBNOVQGFqwrT0sZ46zZKL69Qlk880eGxpQqEGSWr5SCL<span class="token punctuation">(</span>Ak1CPEUbtQvFT5F7E3UUCQSQC3jhjsJnBxlL3lVCQyKGpxwihRToXHZQGb3<span class="token punctuation">(</span>g16yQ9vkrKgjsPgoePyrAI7bzF02v8BkXojUzcYHWfkzW68XvfvZeCLkwQuDOJ79GfgBimQlezayluMSvTHuglTk7Xf35GgY6HZSABsKgrTBGmyIULK<span class="token punctuation">(</span>GwQISlaPUkCVOQrwrHmx4uioKhCap0<span class="token punctuation">(</span>SZXtFPf78l8cjzhZdnHDJdoaAosWbQh5vNeOEBbXoaf4HwEdpFydvV16oBcC0a9hZqV9jbgi2BaVa0<span class="token punctuation">)</span>TNOZuTPFyI7BnybNUmxHocgwGnEXmpceibzqJkZfK6M6AX79dmSE76i7Z4iFVyutLZx6I8L9ip9qwqstCwYD9tlpY8E93oE1NovWRgDhZvTURv8j<span class="token punctuation">(</span>r7GbaCucKy<span class="token punctuation">(</span>fdOeIqTrI7uANnWeeGqOmgehHGjULqnnjgJSL1g8F9QpU<span class="token punctuation">(</span>ShUAXJx<span class="token punctuation">(</span>LpNT8nVB1jl<span class="token punctuation">(</span>Z5pD97F2Vp7TRp5R<span class="token punctuation">)</span>87<span class="token punctuation">)</span>y55lw<span class="token punctuation">)</span>6pS8fpA1XVC1ZFI1ALgWn376mcfaGaeeqzjycfXSQL4ncngazgJeJiiumM<span class="token punctuation">(</span>FnYT169NF5n38WSPvxkVAtiE8o3crZq9c2wP3lRqQ1YDlvvwhKvRRUInU9RsBDH9y<span class="token punctuation">)</span>QL<span class="token punctuation">)</span>cS4Vd</code></pre><h3 id="通灵战潮"><a href="#通灵战潮" class="headerlink" title="通灵战潮"></a>通灵战潮</h3><p><img src="https://oss.luhuhu.cn/202410111234092.png" alt="通灵战潮"></p><h4 id="NOTE-5"><a href="#NOTE-5" class="headerlink" title="NOTE"></a>NOTE</h4><ol><li>第1波安排个人控一下门口收割者拿盾牌,在守门人第二次aoe时交,</li><li>第二个盾可以看压力情况交(2、3波次或者BOSS1)</li><li>BOSS1注意点,点名交个减不要朝人群,小怪及时控制转火</li><li>桥前的那波跳怪小心,进战斗死到外面</li><li>11波次有两个刻骨者两个读条一个恐惧尖鸣叫,安排打断、减伤</li><li>BOSS2,有dk可以拉读条怪、猎手,也可以选择控制,注意头前、地板</li><li>BOSS3注意第一个胖子不要打死,留个钩子再打死,矛不叠加,注意沟通顺序</li><li>尾王默认第一次点名在右边,注意提前拉怪</li></ol><ul><li>队伍配置建议 dk+法师+萨满+T+X</li><li>道具建议 波次1交盾,波次11交球,波次14交盾+球,矛交BOSS3,其他酌情处理</li></ul><h4 id="MDT-5"><a href="#MDT-5" class="headerlink" title="MDT"></a>MDT</h4><pre class=" language-bash"><code class="language-bash"><span class="token operator">!</span>1v1soYniq0RKbm2MTjzrMnEgjIYsK6pWipXXoYnEYKBsoazDUaZfk5weQcW8rzuB1DBCvV6vpELrruFsjVozmtx2NT<span class="token punctuation">)</span>qnsAuYVR1FX9pL801RRlFwVDBADrnYjuLCF6Qs<span class="token punctuation">(</span>KCASz7EZhBmk5ZNM31amx2320l2h2NNDzlowqUFEw<span class="token punctuation">)</span>SEgHCBYyV3yUPT3C5mc136<span class="token punctuation">(</span>eJ9d7lpQxxU76lQrgxjTA9xNwEuDwjVPN1xSatW8Gk4Y7BUQDGu8RrMAKM9Nw8IJxDQXE8I4E2G7hQdgxq<span class="token punctuation">(</span>ehW4fyIoPasJqW8CXLYTfJKJr2b5Zc5tXlgSuBKNPv9pGFeRfY2FtlkcRZRBkPXW0gtgTca177QbekHNCnEYrYjbhJRlNe5WdGl0zjeGV1dFNV55veIPtfWRs94ohwIe0cG5hYjjSraL3fFuqSjzGKTOd3SBCTw6UetmNbMikIKwO<span class="token punctuation">(</span>b8rL9GiD<span class="token punctuation">(</span>h1NAUJQrR0gaFsBrbyLuVpRLH4f6SyybEyJ1ihBqCoAmAb5pSQmqBSzAtalrHG1MCAK<span class="token punctuation">(</span>kRwU6XkupbQEh1SlFJetjrw0dMAR2efkk<span class="token punctuation">(</span>qbu8auEwouWRUSE0p9WWfBXrkoUyFEvs<span class="token punctuation">(</span>4iRorWTNOSvnWa7Yf7tKcdonipEjMIAmTPW6GnjTWtsPvIRFoo1e9znHO<span class="token punctuation">(</span>9cDz7cJu2B448tJrpxiMgVJvuqZYzbCQeYKxKPNMuwrMSIwRKbHH2Cx<span class="token punctuation">(</span>bZdMpuARNcPDfkvTnm<span class="token punctuation">(</span>gVOfTEiJo8gjmsfvBKyK0IHsk<span class="token punctuation">)</span>n0KGAkY1KbyPcRm<span class="token punctuation">))</span>1ShVfkUDenrbxPTEy2IFCht9I77<span class="token punctuation">)</span><span class="token punctuation">(</span>6p<span class="token punctuation">)</span>ZV<span class="token punctuation">)</span>LsUE<span class="token punctuation">(</span>j3jv3YI<span class="token punctuation">)</span>HtZARvF3Izf0Ht7213dRdhT9UQyGJ<span class="token punctuation">(</span>Aryv<span class="token punctuation">)</span>7</code></pre><h3 id="围攻伯拉勒斯"><a href="#围攻伯拉勒斯" class="headerlink" title="围攻伯拉勒斯"></a>围攻伯拉勒斯</h3><p><img src="https://oss.luhuhu.cn/202410111257199.png" alt="围攻伯拉勒斯"></p><h4 id="NOTE-6"><a href="#NOTE-6" class="headerlink" title="NOTE"></a>NOTE</h4><ol><li>2波次后的跳怪要注意110,可以找个潜行职业提前探路</li><li>BOSS1 T带小怪位置注意不要朝人群</li><li>火枪手注意躲避,可以明月开怪跳</li><li>BOSS2注意近战位站人,没人会狙击</li><li>猴子区注意香蕉</li><li>狙击手跳过注意地上香蕉(有一根在正中央)</li><li>BOSS3躲浪,尽量把水放在外围</li><li>尾王转台子注意等一下人,2台子转3台子T记得嘲一下章鱼,路上会咬人,点名驱散注意站位</li></ol><h4 id="MDT-6"><a href="#MDT-6" class="headerlink" title="MDT"></a>MDT</h4><pre class=" language-bash"><code class="language-bash"><span class="token operator">!</span>Tr1YUonmq0FP48oB5YgeIqLmILwkTD8vbcjqRZL7DhFpSLf8hH4ZapZ4mXUu1QOepEoNZCMX2OmFWOhoFEz<span class="token punctuation">(</span>JWLRJlZM<span class="token punctuation">(</span>kvUrFAzA5YHHjW5G3mBxOTT6wEaxFC<span class="token punctuation">(</span>rZRUzpNF20xACgTdE2<span class="token punctuation">)</span>8V<span class="token punctuation">)</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span>5h<span class="token punctuation">)</span>0Oxo<span class="token punctuation">(</span>j4K7QpD<span class="token punctuation">)</span>IRJNnAaSp8UHVDO6TJgTD4KJi1t5tdtRaYZP1lxGz3H1PjtFH8TE94e8e4xtz0xgTU3BTxbc7EfrGt27RxNFewMjvP6qrbFbv9rJ<span class="token punctuation">(</span>kmbmPuEEc8P9vpxcqBp8Ic<span class="token punctuation">)</span>xI7PVk6LAFk<span class="token punctuation">(</span>iXBcrX<span class="token punctuation">)</span>yBjxWD8vOTaS2Oe4TOQP0uneMQscDvvmk0hLHpqR1VsKKd4JO3br5fKqjRSkc<span class="token punctuation">)</span>8efRuXi3eJC1nkVa85xlAyRs3tpWwdZwlZwxI<span class="token punctuation">(</span>6W6VVoUq24UnM7Agy6ZArpiUI6DykCKoksBOL4dOY4Hmr92JO63OYh2HzXZjbcYIAyOxL2B4<span class="token punctuation">(</span>n3uYZ3dgWj2sOYoUyAVPfvqTOgkQmdSvpBKN69Db1JrleyjLLre2q83LuxK9S5rQcE7PL3<span class="token punctuation">(</span>OrQeXUK4w5XvzT4VBtFsW9rE5uGSroT8O0qpnQ2fjve8XGxwWN1QO<span class="token punctuation">(</span>FrDIV0DKTYalnX4PKoyySHDjmsRzF8BVOPJM4feXPrLUQ<span class="token punctuation">(</span><span class="token punctuation">)</span>wdxvLqAEcPSzxUpliKgAdsKnbmOObdwaXKgpwXx80qV0sfv4Gc5S3CnZoeDXtk8jEr3fj6Ukah1kfhmlPv2yU3noC3mp7gRQN7FLbIYlL5bmiFCsDhlplP6V3vrY0tWrtUvKks<span class="token punctuation">(</span>N<span class="token punctuation">(</span>8O1oEADY9cHR<span class="token punctuation">(</span>7a8zdnKy<span class="token punctuation">(</span>3d</code></pre><h3 id="格瑞姆巴托-未完成"><a href="#格瑞姆巴托-未完成" class="headerlink" title="格瑞姆巴托(未完成)"></a>格瑞姆巴托(未完成)</h3><p><img src="https://oss.luhuhu.cn/202409121520112.png" alt="格瑞姆巴托"></p><h4 id="NOTE-7"><a href="#NOTE-7" class="headerlink" title="NOTE"></a>NOTE</h4><h4 id="MDT-7"><a href="#MDT-7" class="headerlink" title="MDT"></a>MDT</h4><pre class=" language-bash"><code class="language-bash"><span class="token operator">!</span>TMzBVX5rvy4FrE1Z8<span class="token punctuation">(</span>mFnarQvGBrRfiXhEeXX7w5wJnkEDB5lroTanrH8cHckjnvqlPnusleOru386pg8U2<span class="token punctuation">(</span>t9VaZCFMxo7AlAbvj3M1xZZmNzoZzUFUN19I<span class="token punctuation">(</span>v6hU26JhV<span class="token punctuation">(</span>z3zJj<span class="token punctuation">)</span>I<span class="token punctuation">(</span>LfD9dFJrJET4N6hEM1wBRn<span class="token punctuation">)</span>rJo32RV1M9lB689d3z916h<span class="token punctuation">(</span>9wBNW3<span class="token punctuation">)</span>h<span class="token punctuation">)</span>g<span class="token punctuation">)</span>GFYp8v7h<span class="token punctuation">(</span>6NzJDgLgMZUZ5o3OnN8Y7SXgXERQGH7S6gJE9rBGH8NhBD74tVSG9<span class="token punctuation">)</span>wwIFu9ts<span class="token punctuation">)</span>BbnjrA<span class="token punctuation">)</span>YWZU1gBDU<span class="token punctuation">(</span>HJhRgnEm7rPhrZ7mgjD<span class="token punctuation">(</span>xeSoN6AyeBOPhXG4B5dHMpelgF1iwR0J4WqGyVSNpq0YZGgSZnvc51HHpobAC6WZlKPOSSGMIcmcllmiAI5wX5W7YXh9YJEfOo1rDsGwtJBGgWud0qPoPKNcJRgFWGpyXhCZLrgVkLrSOoOLQJ0uqA7dts9CL5YLXTd0V6MUzUIck0kQV<span class="token punctuation">(</span>fg<span class="token punctuation">)</span>y<span class="token punctuation">(</span>R2xfVVLn0uFDuFdZf3qAg32JmLNGVvIUfZpRGmuBrGqMdgF<span class="token punctuation">)</span>Suxke1UWRdS8y4rmcS<span class="token punctuation">(</span>FgbYxtWUZkT1LOmih7iagm2IMYzESOd5zps<span class="token punctuation">(</span>oE61px6vXwJZxNNpQ0g9o<span class="token punctuation">(</span>8h<span class="token punctuation">)</span>2KsIXpxAxp3Ks0FsNDeg<span class="token punctuation">(</span>et0MlLHYcKR<span class="token punctuation">)</span>yhyAJSKpHK55JLpFc5mcFnQ6pPkxHJ3pATw7YIkikEAHoHqhHcSyKga<span class="token punctuation">)</span>CdkTkfk6OD<span class="token punctuation">)</span>K26xVqoIKOe8s2s5E4<span class="token punctuation">)</span>sQMYzOyovZ01F8kEXCLvcZC<span class="token punctuation">)</span>MN9BPbqW3Jm8DhHSTQx4aqDgANBULpu5ZdnDQyr9<span class="token punctuation">)</span>0pA8Jb<span class="token punctuation">)</span>yXpo8JNuUs9wDcPT2XhPQFLJDuriNBLkAB0yArrxqXwy5cNcs4KKvR5w9cBnPtkI5E3vBXrXqskzPeHg5wiP7PkDjfKajmKlFKMfwikEq0SZV1qrzzjPbOYYNK0TKYNYacLstHYI1PQJsfQ8cwzY5KsLaQAKDZLdDN4PJaxzYH<span class="token punctuation">)</span>zcEaYmW3DNnFLrBT5lS2BMIKSF4KrJ<span class="token punctuation">(</span>zRV5R0VA<span class="token punctuation">)</span>WThTXOZoj51OE0k2XZT<span class="token punctuation">(</span>4jV04XBpAs13qEiNm6nJ<span class="token punctuation">))</span>JE8np8VD3<span class="token punctuation">(</span>HBT6Rg7D9zgUwEuYVqnFOlMqovkDKo6NF9XYlLkkhUb98d1s1aShoCjHPBa6iG41FrOtoal5juhoTtyLgL22j60sN33pEjtwnsYMiN2PLYGZ01fuANmMQhVKgBINEjNjiTgV12z0DDX9<span class="token punctuation">)</span>ytMfNXN6LgoC6x8bhT7J<span class="token punctuation">)</span>QN8Bo8HpC6d<span class="token punctuation">)</span>dhC<span class="token punctuation">)</span>BD<span class="token punctuation">(</span>xuo9AFrQTzF<span class="token punctuation">(</span>Fz2V8Ah8wFzS59F0Jo4z39O3<span class="token punctuation">)</span>pn9oxm<span class="token punctuation">(</span>qjYtU9r3<span class="token punctuation">(</span>AZUZJIpW0RFLz<span class="token punctuation">)</span>Jpy2F83n9opA6DEqS1d<span class="token punctuation">(</span>1V70<span class="token punctuation">)</span>5Nm7I38O39UhCVBSY5<span class="token punctuation">)</span>PhDNDp8JVWr<span class="token punctuation">)</span>5REWN9<span class="token punctuation">(</span>Pv7MXzr<span class="token punctuation">(</span>Oxn1sLGIbFnj3yzWPMldl0dKugwkedmugw4giPmSSZpa1SfOTbDP9cXGUu1Bc6gGT4cmzFTqfyZeHsizyvdRz4u4K2bjBriEIUb0X1k2ZWiKyYjrifO<span class="token punctuation">(</span>qkAyjdRAyesHDGhNiRyldNdPdhKJyjcPmuXQUgwLlz148Eclaw1WAggHSlfsLnpijXcxd7z4aTfetSAAvgsdIw0WsgwrBTjruAvAsdI20Wwg2vle0uIvIbjuXMUg2GqAsdIH2ldPnnJQH1mSPobnLANSWT<span class="token punctuation">(</span>BJ63ouRbfcVzaCzoufWwJodH37c02GUeuoWr1Vcp2XdviQFZ0u9RYJuRGILVu<span class="token punctuation">)</span>wWAgofUymm56xrOw<span class="token punctuation">)</span>wWEgofspo7H6xrqLwhsrdlz4uiDEuCIqgWbIu9BbBz4uiDwiIshs7aouXu9lHt1VkNcLB0oRUu<span class="token punctuation">)</span>wWAggHK0mA7SO<span class="token punctuation">(</span>TG9mCkK2ak3kftcQ<span class="token punctuation">(</span>TGLmCkKwFAbVy9BbVq9RY6a2ZoeeQyd7iJbH0cmDkvbSQH1mSHWQs9RKEexd7z4aHJLKwesfo8AfnSKHvnmcPYMsvwtdBzyxdJqQqAZ2cPRRHDTvPdHuRshKDTvPtZWgkvLu1ri1UuiDUg2ZWbABizdeH0OWPirdlzyu<span class="token punctuation">(</span>0L6OhH04tH0BAyldJYhjWiKwjWHko01WbuXQbgH0AsHmOAyndNpKKEnfczCYMWUg2ZWTZLIoeZ4Sf6ccwdsEdqoWqV8dX1HzPOZWAWYBascEQ3i2of1qO1a9I0CdfLi0Gm3GMeunFliOMMMUSHaRgQcjORiOMtoMkKLiD1PMVTgdT5BhBLNdLjlOkJ7wUIGkH1mmcNe5pld7AypdJAf82hYqGZuYqwUjqJk4cwNqhf8JV5YLC6PitGgPrOKkLo<span class="token variable"><span class="token punctuation">((</span>L4RU9NOjWPx8<span class="token punctuation">(</span>tV6JN9B37WNFR937U7V3FD6DV3bx8lp<span class="token punctuation">)</span>lQI2axDRT3UAdC2LV00l<span class="token punctuation">(</span>GdV3no86pnzX7c3p6k8WN<span class="token punctuation">(</span>PXpm7Qxkr<span class="token punctuation">(</span>WheFGdER9M<span class="token punctuation">(</span>EFiZINJpF1X5Q35m6qxi<span class="token punctuation">(</span>FE281QCoxSmtextrjuF2p78Z3JU<span class="token punctuation">)</span>nNE1l<span class="token punctuation">)</span>vp52ZU0No9kVZ<span class="token punctuation">)</span>E3lm757oB3Be<span class="token punctuation">)</span>q055S3<span class="token punctuation">)</span>5PpC99M<span class="token punctuation">(</span>r<span class="token punctuation">)</span>RdEVNXMeEEzv52MFJ9WBcc8wP4gHqzYomnwz1dp84Z8WVKtMSURernvFCzMCGBY7FbE<span class="token punctuation">(</span>WAnwN2eT8h9W3fFbtlF48Y0iy60bJYBvNy<span class="token punctuation">(</span>qFsM137kh<span class="token punctuation">(</span>2pnUBC49<span class="token punctuation">(</span>4J<span class="token punctuation">(</span>GO7<span class="token punctuation">(</span>lU2Rn9j7EWt<span class="token punctuation">)</span>KPF21NET<span class="token punctuation">)</span><span class="token punctuation">((</span>p<span class="token punctuation">(</span>JM<span class="token punctuation">(</span>RUYSB97<span class="token punctuation">)</span>QNK22MDPNT<span class="token punctuation">)</span>EF20N<span class="token punctuation">)</span>27V3LI7Ur797<span class="token punctuation">)</span>0RWsD4RTOvW516OOOZP9M4RakxTafC24wBORZg6SoP<span class="token punctuation">)</span>KNWh9SBXNRtFNhF0U7o9bxlg<span class="token punctuation">)</span>yv0<span class="token punctuation">(</span>7D5y5ip4IVg9Gv<span class="token punctuation">)</span>gOhK9Uvm6vUGqOQhiu1lieQ6be0rU71z9abErsOcj9aIkYU1Df9abILq1WAgofof8it6b4gh03ZJ8<span class="token punctuation">)</span>5fT74lAfztcrKS2xNhLfTGw0shFrlQlAzzrBR3kIUNtxJsl6o2I23w0DSfTVUOfE2IUR4Kw81DvWVr70rBDfR0rftjTOJ<span class="token punctuation">(</span>RL5dQrjvnTOjOTbHvA4nGSsRYl6mmBLwvw0QGIzLgUrGYFgRzyt79GfR0jm79MEgoqV<span class="token punctuation">(</span>qXSsRkwPjSKHv07XpjR0z8XSsdhKvR02IvAGRwPTfR0O0UALwuSstynddJjKFCYkTRCvWc2ZWiKWDt2kTOALoJLmmcPe<span class="token punctuation">(</span>KPQjD1kDgBz4S7Dv1knQ9GvAcNTsdSP5EpBLw2SstyndNnz6zwP7kwPjSNHx0kTej5JzLoJri1mR0YMvAnZkTSzLgl<span class="token punctuation">(</span>SvAlkOdvC2knWKvASeYwPHRvYknH1mSHW2QvADZknH9mmcjUzhzLwtUGfnSKHrirHC2knzu20WwgoFHbBXkTbPnFOIjR0eoKDVRkwPnHQv6mwZWTBIrwPbU9NHO5x4<span class="token punctuation">)</span>xXiFtmI<span class="token punctuation">(</span>Qtsq238Ng33QcTnieJcff4KwMnlgfQkWzkjgzAIroMyKPjg5AIrbY4pfppEpMRH9mmeJWRhiXiF3aDrmIWsggIrQMyKhRAsms1eJY4SyKplgLvllIr<span class="token punctuation">(</span>SyugtIr4sKks<span class="token punctuation">)</span>JENMQH1mmug0vXO8x8ajgPRIrfmczx9E9IOIFOig1vVxFb3QMiXO4Bsc9171RkIrzC7s2Kyuh2s0HkMeJimjgHVAI83lfPrPAynd3oMsIr0x8GPDm14zyes6s7K<span class="token punctuation">(</span>NPDVEclz4uiJhiSfXiY1ceJYyldNcPblEsmI<span class="token punctuation">((</span>THyeHjXicdXiJRjgjXxWbeJYyndJqIVclsmI<span class="token punctuation">(</span>IhGyug7z4aHRIrkOCcXOmwYWkcxfJu4iR30Wwg21WK<span class="token punctuation">(</span>NOEVEctIreo0cjjgPXnhcQgwZWgAX7lIr6296ZypdhQBd571BYxgxWAqYBaLqcQbseKUIkUxFPblVbugHJT571BYxYp0AGScMBqKFVgeLOBFNVOSI1GM3qtcwqgcTuWHEuPbpVH8z10NPBgBtVwP8xfk9Nn6LpZgJMmz0lS54TsQ4NzNjB9Ds80FwOtTWZK<span class="token punctuation">(</span>7gr3lR<span class="token punctuation">))</span></span>a</code></pre><pre class=" language-bash"><code class="language-bash"><span class="token operator">!</span>fB12UXjmq0pN<span class="token punctuation">(</span>uwHVGn8AALIAJeTsBE2IBMeAiWwUSDZl8TxJb8ywZgv1xQwjVg7JhFMzoESfiXtIJnP<span class="token punctuation">)</span>uM13P6gHo4nnsT4EXX81boI98pekIWt9VJWcpeiIiQp0Zgrvn3lI8NMDm<span class="token punctuation">(</span>XYQQX4<span class="token punctuation">(</span>xKDYX4ZLjJX5TjVk7gJllgJp101vMwjpmg<span class="token punctuation">)</span>5kzs9y8WPX4F<span class="token punctuation">)</span>ss<span class="token punctuation">)</span>y87ndJXzj1Fs1<span class="token punctuation">)</span>vTvAQ1wsbi5DvVMX4u16pi6v<span class="token punctuation">)</span>0SXLQmc2que7a5<span class="token punctuation">)</span>pr7v0RSOOmBOQ<span class="token punctuation">)</span>9fU9BP8vruWu3ZjvdYjhjBOTvw3<span class="token punctuation">)</span>LH6NLn1Fn<span class="token punctuation">)</span>II1in6ozLk<span class="token punctuation">)</span>u2uRG1Ba<span class="token punctuation">(</span>JHQQfNUxkFRS<span class="token punctuation">(</span>zrK30xTLf9FVOOtQtPQfCsH0k7A<span class="token punctuation">)</span>NMoZntXjtyfMCAdBQAAvEbLKLNDfMNSITxT6fdsCmOg86qOT7bRipeD1YwH6B4kB1<span class="token punctuation">(</span>WMhXnqcC5c1Sud1MXsxn3v0ARRZPuFk9kmgpacKimqmIX8iQz7q<span class="token punctuation">(</span>UClWS8qy1EWQbFhbo<span class="token punctuation">)</span>S55G51wbXnMbf4g<span class="token punctuation">(</span>bI676XeZK0BeIM<span class="token punctuation">)</span>KVjYqzzuKoY4VylYntUiojdLmHLnJXokSgz8VP4mIyj0yUQQWD90T0LllOz5tO57qbMlf2tZXDPaXLcBtRafssOH<span class="token punctuation">(</span>Kj0bZO93L3bMTl0D72gxXHsctAV<span class="token punctuation">)</span>0palnpJpHvlXEARaH6gaqqsabzHznh1K4w0NmqFYb9zaOp9M3a<span class="token punctuation">(</span>UU8oz6vHAG1cyBYTUNxWaFOUjU9ul3C3HdU<span class="token punctuation">(</span>glXSDK1G4FHNS1wqgjnnGX1ss0AvfFN03COD<span class="token punctuation">)</span>ukLYtrZgyvnJ<span class="token punctuation">(</span>hzLLhc5pi9fcvx8SATQcISkdISQdISkeI8TAz2h8q4pWjZsL6lgmfy24KCqLcNCqHqTFp40SLkcKrycCOLUdD2EHqahLKeQbr3HoyOSbgKFyoqNaGoHGi1du1qneI1DdwIDI1TdeRRhi7fm3wC3QyePGTuoyv0XDfFyVBMxsX0amE<span class="token punctuation">(</span>zolpm54G6DtNLvgO9YlQ2hAlFBm<span class="token punctuation">((</span>K<span class="token punctuation">(</span>g1dMUBm<span class="token punctuation">(</span>OmPB6DtiXX3YlNEburRu<span class="token punctuation">(</span>stv<span class="token punctuation">(</span>3AkRL5IuyKL35KkFEOSs<span class="token punctuation">)</span>sNftpuMlo<span class="token punctuation">(</span>RIMZ54txU84dQXe<span class="token punctuation">)</span>b</code></pre><h2 id="TANK"><a href="#TANK" class="headerlink" title="TANK"></a>TANK</h2><h3 id="德鲁伊"><a href="#德鲁伊" class="headerlink" title="德鲁伊"></a>德鲁伊</h3><p><strong>基础:</strong></p><ul><li><p><strong>绿字优先级:</strong>急速全能暴击精通</p></li><li><p><strong>常规:</strong>开树皮月火接怪,尽可能每个怪都上到月火,痛击铁鬃宏,高亮摧折裂伤,明月为站定聚怪标记</p></li><li><p><strong>优势:</strong>3min化身物免锁血,适合成熟车队大波次融怪</p></li><li><p><strong>劣势:</strong>仇恨能力略弱,不过没关系手快的dps(狂暴战)多死几次他就适应了,体感腿真的不长在接怪的时候吃减速定身也不敢变形解减速、定身,跟戒律牧沟通拉人方便卡视角聚怪</p></li><li><p><strong>天赋参考:</strong> </p><pre class=" language-bash"><code class="language-bash">**减伤向**CgGAqvgeoHLefPLb/Pa8nkKXDBAAAAAAAAAAAAmZGmhlhlZmZMzYhhZmFLAMGMzMT0MzMzMzYWgNGAAAAAAwwYGYZbmNMmlRgpAAQA2YmZA**伤害向**CgGAqvgeoHLefPLb/Pa8nkKXDBAAAAAAAAAAAAmxMzMjlxYGzYmxCDzMLWAYMYmZmoZmZmZmxsAbMAAAAAAghxMwy2MbYMLjATBAgAsxMzA</code></pre></li></ul><p><strong>TIP</strong></p><ul><li><p>可以卡化身</p></li><li><p>猫形态痛击可以减少明月CD,赶路来回切换释放痛击可以保证每波都有明月;</p></li><li><p>切忌不要用脸接怪,开树皮接怪</p></li></ul><p><strong>宏分享</strong></p><pre class=" language-bash"><code class="language-bash"><span class="token comment" spellcheck="true"># 光柱宏</span>/wm <span class="token punctuation">[</span>@cursor<span class="token punctuation">]</span>6<span class="token comment" spellcheck="true"># 取消光柱</span>/cwm 0<span class="token comment" spellcheck="true">#showtooltip</span>/cast <span class="token punctuation">[</span>known:102793,@cursor<span class="token punctuation">]</span> 乌索尔旋风<span class="token punctuation">;</span> 群体缠绕<span class="token comment" spellcheck="true">#showtooltip</span>/use <span class="token punctuation">[</span>mod:shift<span class="token punctuation">]</span>14<span class="token punctuation">;</span>13<span class="token comment" spellcheck="true">#showtooltip</span>/cast 复生/script SendChatMessage<span class="token punctuation">(</span><span class="token string">"正在战复你!"</span>,<span class="token string">"whisper"</span>,GetDefaultLanguage<span class="token punctuation">(</span><span class="token string">"target"</span><span class="token punctuation">)</span>,UnitName<span class="token punctuation">(</span><span class="token string">"target"</span><span class="token punctuation">))</span>/y 正在战复 <span class="token operator">==</span><span class="token operator">></span>%t<span class="token operator"><=</span><span class="token operator">=</span><span class="token comment" spellcheck="true">#showtooltip 甘霖</span>/castsequence reset<span class="token operator">=</span>90 甘霖,阿加治疗药水/use 治疗石<span class="token comment" spellcheck="true">#showtooltip</span>/cast <span class="token punctuation">[</span>@mouseover,exists,harm<span class="token punctuation">]</span> 安抚<span class="token punctuation">;</span> <span class="token punctuation">[</span>@mouseover,exists,help<span class="token punctuation">]</span> 清除腐蚀<span class="token punctuation">;</span> <span class="token punctuation">[</span>harm<span class="token punctuation">]</span> 安抚<span class="token punctuation">;</span> 清除腐蚀<span class="token comment" spellcheck="true">#showtooltips</span>/cast <span class="token punctuation">[</span>combat<span class="token punctuation">]</span> 影遁<span class="token punctuation">;</span> <span class="token punctuation">[</span>nocombat<span class="token punctuation">]</span> 潜行<span class="token comment" spellcheck="true">#showtooltip</span>/castsequence reset<span class="token operator">=</span>3 狂暴回复<span class="token comment" spellcheck="true">#showtooltip</span>/cast <span class="token punctuation">[</span>@mouseover,exists,help<span class="token punctuation">]</span>月火术<span class="token comment" spellcheck="true">#showtooltips 痛击</span>/cast 痛击/cast 铁鬃量(财)力而用<span class="token comment" spellcheck="true">#showtooltip</span>/cast 化身:乌索克的守护者<span class="token punctuation">(</span>变形<span class="token punctuation">)</span>/use 淬火药水</code></pre><h3 id="恶魔猎手"><a href="#恶魔猎手" class="headerlink" title="恶魔猎手"></a>恶魔猎手</h3><p><strong>基础:</strong></p><ul><li><strong>优先级:</strong>急速全能暴击精通</li><li><strong>常规:</strong></li></ul><h3 id="战士"><a href="#战士" class="headerlink" title="战士"></a>战士</h3><p><strong>基础:</strong></p><ul><li><strong>优先级:</strong>急速全能=暴击精通</li></ul><h3 id="死亡骑士"><a href="#死亡骑士" class="headerlink" title="死亡骑士"></a>死亡骑士</h3><p><strong>基础:</strong></p><ul><li><strong>优先级</strong>:全能暴击=精通急速(10%)</li></ul><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><p>素材来源:</p><ul><li><a href="https://space.bilibili.com/552125061">熊T-逆风</a></li><li><a href="https://space.bilibili.com/141341784">雨帆灬</a></li></ul>]]></content>
<categories>
<category> WOW </category>
</categories>
<tags>
<tag> Mythic </tag>
</tags>
</entry>
<entry>
<title>WowAddons&Cnf</title>
<link href="/post/8b5c58d3.html"/>
<url>/post/8b5c58d3.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="wow插件及配置"><a href="#wow插件及配置" class="headerlink" title="wow插件及配置"></a>wow插件及配置</h1><p>”磨刀不误砍柴功“</p><h2 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h2><ul><li>系统:Win11</li><li>机器:MECHREVO WUJIE 14pro & 台式机(R1700 + N1070 +48G)</li></ul><h2 id="插件"><a href="#插件" class="headerlink" title="插件"></a>插件</h2><ul><li><p>平台:CurseForge、NewBeeBox</p></li><li><p>参考站点</p><ul><li><a href="https://maxroll.gg/">maxroll</a></li><li><a href="https://wago.io/">wago</a></li><li><a href="https://www.curseforge.com/wow">curseforge</a></li><li><a href="https://www.lhfszs.com/">灵魂复苏前瞻</a></li><li><a href="https://www.mythictrap.com/cn">RaidGuides</a></li><li><a href="https://kuangbaozhan.flowus.cn/">狂暴战.cn</a></li><li><a href="https://keystone.guru/">mdtRoute</a></li></ul></li><li><p>插件清单</p><p>Normal</p><ul><li>WeakAuras</li><li>Bagnon</li><li>Bartender4</li><li>Details</li><li>Myslot</li><li>RangeDisplay</li><li>PlaterNameplates</li><li>Shadowed Unit Frames</li><li>idTip</li></ul><p>PVE</p><ul><li>DBM/BW</li><li>Mythic Dungeon Tools</li><li>Hekili Priority Helper</li></ul><p>PVP</p><ul><li>OmniBar</li><li>BattleGroundEnemies</li><li>BigDebuffs</li><li>Ominibar</li><li>GladiusEx</li><li>Diminish DR Tracker</li></ul></li></ul><h2 id="大秘境"><a href="#大秘境" class="headerlink" title="大秘境"></a>大秘境</h2><h3 id="回响之城"><a href="#回响之城" class="headerlink" title="回响之城"></a>回响之城</h3><p><img src="https://oss.luhuhu.cn/202409100957141.png" alt="回响之城"></p><p>mdt</p><blockquote><p>!1z53VTrrqC8)FsvRU9x3T3RLQkLG6rLUiECf2X7vzWyJSpxcVyLuiO200eKQAeIwXd0aTIc0GsRAcXK)zi3fNN6)cm7o3p2ZyuoBFzNDN5Z8DNzVtruRQI70njP7AJ7L(vQiINk(l16pdUtf3QtNb9)y9WrDh0xfj8KQ4XD7OIdU1n(WBfNU6YPTuX3TvVXAJBwB8WH6(P3ECVEWQPvdepUDp9D19SUCy3K0pkjzKoDeSMit8tH)kN7ng3)o6b9xUZ6GnctfNQ1FE3(3r1wfps3tVwQbf7cnHaw4xaHRYvLFfX8vru7fdUeQiU9o4gwGkY3EfyhvAhn06ot2hXmU24ckogdgdijIcZNalGcRGalHcUGycdCpbSrbBeWgfMlb8hneWdiabc5jWsHeXXZgzyAgJScReZIynwKWmeFo)KA(QqhS63GEdgQItsy6KeNaJtHIAb1ZgFkXcaaVdGM0JIzhdtodJO6WqbZiDbyskXCeUy8czJviBc3mq6YUrzOOqXqy4OBeOIwiOf6S0k7P2)zv7Vm7VLPQjrd1obRqnK2GqqPM0ytG43Wgwwql2hkex6CQjtBgVwPlZNkDJJjLatkMB2ZDZ(AWCZHqZ2fe)gbq0iHqvJWDHMHfZKgzhTXezO8IzhbZUqx6k7pCzehMG1jgh62H4RMRwlPnZUb4x3kBPPWJn3RmcjjOzIg0ON1kxeIZuGy3KvlwwQ4wQeonZbwuLyZSh(jeZjI1zWalUJbkJGzwAddwQn)BqlctvpLlFlw7rajiHK57ECjIoNyzkkkjs0GfkYIXyDke22QULEt2yf1hzuhrsLnxrU5rafThy)jT4iaVgGwEytH)KUBDKWfO2Ti2cHA8kR8WUicgzNDx8ea2)Zgxr0znC1)9O2IJy8StwSaFvFwI1lZ3)xfFwvXrPNMVtM61OMX(STu96W3xE63p7poqfpO9NcpgR6rwXDW7Ujxq99c9y(8aFVajxLCvUnE38Q(EEmpFrilGhYfq9eyIx3lCDt6fpA98J36kz7S)S)6vtwj)OxM)n7DX9o59t)HjRqU25t3oBVxp7SNMV53L)1Vi7W9V84Npzf61U8Noi75hE(zp68t3Dj6KpjBR)mFNxNn9KStEIb((G7lARRqveiesbHl9K(sgCYznQbEuFFzOqsyHs)qPXK)8OsY27DaxzhUx(g)6S)(3UyZx9(P7K9l3l)hFw2UpmB7NMDWlaCp)0FoBR7NV920)zJnzWho8raPz(UpawWfp7HJwhi(BFu20nApy0ihEzU8kz8qdpmMVNmekmbOeiVGQ75tc40qq9jWtHxK0o7nVz2zNm7ThImn7DhbCxrm8wstwj7XVmBR3Ue9k5h9KSJV)suCdi)bpoF)FVMRYsUB3QNonvVC)KbgqBnoDWhyg38QoxFU5yExiUDTQ)9p</p></blockquote><p><strong>高危技能</strong></p><table><thead><tr><th>类型</th><th>怪物名称</th><th>技能</th><th>应对</th></tr></thead><tbody><tr><td>小怪</td><td>颤声侍从</td><td>共振弹幕=高额AOE</td><td>点断</td></tr><tr><td>小怪</td><td>充血的爬行者</td><td>毒性喷涂=8s中毒</td><td>驱散</td></tr><tr><td>门神</td><td>伊克辛</td><td>恐惧尖鸣=6s恐惧</td><td>打断</td></tr><tr><td>门神</td><td>纳克特</td><td>巢穴的召唤=不可断高额AOE</td><td>减伤</td></tr><tr><td>门神</td><td>阿提克</td><td>毒云=地板绿圈</td><td></td></tr><tr><td>BOSS1</td><td>阿瓦诺克斯</td><td>蜘蛛蛋=定时出小怪盯非坦克</td><td>转火或风筝</td></tr><tr><td></td><td></td><td>贪得无厌=小蜘蛛靠近会背boss吃掉,增伤50%可叠加</td><td></td></tr><tr><td></td><td></td><td>警示尖鸣=3s尖刺AOE</td><td>减伤</td></tr><tr><td></td><td></td><td>蛛纱强袭=5sAOE,同时又地板圈</td><td>一起走位</td></tr><tr><td></td><td></td><td>贪食撕咬=高额打T</td><td>减伤</td></tr><tr><td>小怪</td><td>魁梧的血卫</td><td>野蛮猛击 AOE,伤害没特别高,主要是会晕1秒<br>烈度 鲁层增伤,每层10%</td><td></td></tr><tr><td>小怪</td><td>沾血的网法师</td><td>恶臭齐射 AOE,漏了会造成高额伤害还有一个吸收盾</td><td>打断</td></tr><tr><td>小怪</td><td>沾血的助手</td><td>深掘打击 打T技能,被打中会回血+增伤</td><td></td></tr><tr><td>小怪</td><td>哨兵鹿壳虫</td><td>预警尖鸣 读一个10秒的钢条控断后会继续读,<br>需要每10秒控断一次读出来的话会召唤附近的怪极易造成<strong>灭团</strong></td><td>控断</td></tr><tr><td>BOSS2</td><td>阿努布泽克特</td><td>感染=单体高伤害DOT</td><td>减伤</td></tr><tr><td></td><td></td><td>无休虫群=躲开场上的紫色圈圈中了会有中等伤害的2秒DOT</td><td></td></tr><tr><td></td><td></td><td>钻地冲击=冲向并击飞一个玩家,然后需要躲开地板圈</td><td></td></tr><tr><td></td><td></td><td>小怪=战斗中隔段时间会召唤小怪<br>小怪会读条控制玩家,读条很长,在<br>打断或者控断即可</td><td></td></tr><tr><td>小怪</td><td>鲜血监督者</td><td>毒液箭雨 高额伤害AOE+DOT</td><td>打断</td></tr><tr><td>小怪</td><td>飞翼运输者</td><td>冲刺打击 随机冲人<br>伤害高注意自保</td><td></td></tr><tr><td>小怪</td><td>蛛魔搬运者</td><td>野蛮猛击 AOE,伤害没特别高,会晕1秒<br>烈度 叠层增伤,每层10%</td><td></td></tr><tr><td>BOSS3</td><td>收割者吉卡塔尔</td><td>毒液箭雨=群体中毒DOT,伤害很高</td><td>驱散</td></tr><tr><td></td><td></td><td>培植毒药=群体中毒DOT,伤害一般,可以驱散<br>DOT结束后会向两个方向放出毒液波<br>中波就会被秒杀</td><td>驱散</td></tr><tr><td></td><td></td><td>小怪<br>血工 附近跑来跑去的小爬爬,死后会原地生成一滩黑水<br>玩家踩到黑水上后会生成一只“黑血“<br>小怪会一直对该玩家读定身的钢条,<br>钢条控断后结束定身效果</td><td></td></tr><tr><td></td><td></td><td>宇宙奇点=将玩家吸入BOSS脚下的地板圈<br>读条结束后如果没能离开圈会被秒杀<br>靠踩黑水被定身,或无敌/闪现类技能逃脱</td><td>无敌<br>闪现<br>踩黑水定身</td></tr></tbody></table><h3 id="矶石宝库"><a href="#矶石宝库" class="headerlink" title="矶石宝库"></a>矶石宝库</h3><p><img src="https://oss.luhuhu.cn/202409121320456.png" alt="矶石宝库"></p><p>mdt</p><blockquote><p>!vA1wpXTru4Fn9rqEU4XEEnnkQHirsLPvQVyfG1oL2T7wbEttFzfxsiCnqsAAcWcLKaP5guIsezz52pMUZ4DFQ)f6CX274DPpujJL3zoNVZ357CoZGpWFiFVcJfgo2Ovkg9R(dcS89(LGGFu8LV3WfkuU03gm(eJvUK)G2wU(EvgRGVh5Yx7R)oI3n(MV6799U9WfReiHz0kJpEqPOBuPyr)bHWSf8QmsXGBhuub5pl2DcH1dcmEjFGQhK6blcM6r8br(ej3m10iPng)a)FccwST3OLlwECFVWquqyyksPRkxJg0bDBtajMHcNaDKXI6DCmPh00hOjA2Drguq6UDidvsXmSYfsBdddddhr4(GahdDiss4HsEPIN0BvoikQdzOpkvdc7s2mOQkJaadWn1lnXDYXhj17eAxfKAuYv3YiIJYcSQqzB8brNiUkZa5ynkha6qqv(bCviaODruPwIZSpQd)OAzGO92r7TTo00C5fvRZPrfyNZtS2Z8Yvc4wkt0mZjl3YOGoTayDqvbOd1vDQDmfAIiaKlA6EKeURwnfMHbQsLuwmQaqR8Tm66djNsJtgHsQYD144EbTfjdxQMutWZnNKwYI6z6ZT3cDosNYIKrbGQOAN5KHfDKJEh1a2MUPBN6sIbMHgLigrDpGkDKyMzIsJHW0HdYoZHYXf9Cl1K6qBLnsR1zbs9BnDtXOBbpzouZJuqmvEx)EhptlhjzgSZXKAzgycswkMvy0aBoFKoKLzkQt5jx5mTXRNbl7l0rsw3M0rGFVZgGCv)mhZnnanpOpDAacYjurz3sD5kLUvq5sxTWDe7jVfmki4NgR0T8hX3BIGIbJgjVemjOYO6n(yHrxpmCIGOSl0sGmk4oI3Tp(zT2FhFVYJ8dcVv2OyubT1xb76GiicaIrowiXLRH9HvjWv6d7IWU2aSnfcaiStYwOKK8sYC0J)Sh38KDkemsLWWQ3KTYFXwzB2cB)pNSe)JVMF3vyFyA(toO6nB)YheV3MvhiE)9y78PMNUC8P7ZRnp7Z7g)6f)7jNk(p2VzJgXRFxG1xWU3RBnZPsefWWE108TQX29HSvNtaFZJ3T9KZZx8n85Fm)bZlt0scQePVVlnTYML6MUHH6MfrXTp5jMEf1o4brU9RQ4E9bPo9tukycyw6sj2u3ioe5dqinelXFg6Mdriwuc0XXHISWq5w2DtKwNVwRZokE2f4p7b8AjzgFHfAF)LAV5le6aFY3YxCE29BW3Cx2Jwcjt)JoS6aa2kF(sx3ZtlVXtFu1b4lU8qcpslcTFZh4p5Lnpz94JxJD)veLhPmU7HSxnxRxnvCTf5p9qETgAZQoq7nMTz99IF3AIIsY3VDk2Cn4)(rnp7C2b3nUX5863lE1zRoGHCB))vUDZj3qN(rjYTTB)osh9Gyy)Q7H96dzz1VLrn4kUcT2M4IHueesv9P2jNgqY1ptaeKRLnYgsSCTWsXNKuxqyBrFoaHWwcKOxy)mSx5Tz9DAw)TcPJT6ssPBVJf6zZ6llftHQvFpwTgz97yHP6UBXg8NUD8uVtuAy1oqiNgQNJjNTPwakLGOoowuasrmuYmiLsXqIdWYgGCfhWEr9sOlGZNTj)9pV1PVxeF2bRiAMK9aQpe8VzJNhpDDrJbB)pkxxLxQvwN9ITeJVq2KlR3MTXlINApfMIKOz9fAF8dJxDg2QZ0SXSAJJ3(tXBCMyILTWgc0U81Ip(84tFJULMDpfqRoJrY7AM8UwUySTf1smZqD0zyYGKlgafLtXXscna7aVWcgU3KV9MB368hkik)tBLmyD4CTxBNKtuAD(g69I)ZhX3CszP73oJvBoncsNp7iXkDiC6nE3y4IbrrbxTuyzzgmCLOYFPCD5b0xQlBKNGR))Q8)3p</p></blockquote><table><thead><tr><th>类型</th><th>怪物名称</th><th>技能</th><th>应对</th></tr></thead><tbody><tr><td>小怪</td><td>大地注能魔像</td><td>震地=30码AOE,多个同时压力大</td><td>减伤</td></tr><tr><td></td><td>阴森的虚空之魂</td><td>咆哮恐惧=4s<strong>恐惧</strong></td><td>打断</td></tr><tr><td></td><td>改造的载货机器人</td><td>地板圈</td><td></td></tr><tr><td></td><td>咒心入侵者</td><td>虚空感染=10s诅咒,可叠层</td><td>驱散</td></tr><tr><td>BOSS1</td><td>E.D.N.A</td><td>不稳定尖刺=点名三人形成石柱</td><td></td></tr><tr><td></td><td></td><td>折光涉嫌=激光,可以清石柱</td><td></td></tr><tr><td></td><td></td><td>大地破裂=AOE,摧毁所有石柱,根据石柱数量出伤</td><td>减伤</td></tr><tr><td></td><td></td><td>震地猛击=高额打T,并留下震地回响,驱散可获得减伤</td><td></td></tr><tr><td>小怪</td><td>虚缚抢劫者</td><td>虚空风暴=6s持续aoe</td><td>减伤</td></tr><tr><td></td><td>引擎语者</td><td>震荡跃击=减速</td><td></td></tr><tr><td></td><td>被转化的代言人</td><td>禁声齿轮=沉默3s</td><td>打断</td></tr><tr><td></td><td>虚缚嗥狼</td><td>穿透哀嚎=读条完成后AOE并施加<strong>易伤</strong></td><td>打断</td></tr></tbody></table><h3 id="破晨号"><a href="#破晨号" class="headerlink" title="破晨号"></a>破晨号</h3><p><img src="https://oss.luhuhu.cn/202409121517147.png" alt="破晨号"></p><p>mdt</p><blockquote><p>!LMv3oXXrw4NMCjJQ))5wNvrkCXeKAuUSLaZmzz3zHv4bNS3GiEDwa)hoBwNyhdoYoKSwobCKYU2eaBEzMUNzUAFf26CQQ7Q6b0YISnc1Z3uvDo158D(ov1KtZNnpBHf72DXRUAV()L82usE2N2PZF09uE2ClSWYl9XDw5AlU8s5TLetE2QlUqEMAHpD15fF81P)(PZZU(C9wTdSmxD1vwPZs9Nz1E9YBRQ)C2QZ3RZ170dxXvwSB)pQB3R1P)1CtPny((U)xn2F3Ql9jDwEPpCHpZ9Du3473PZFAXL(K85ZZUwNEDUAFWtWj6SGBE)zNXQxPQFb)WWF4Wp9HhNnbLcq86XcMF5ElVsEw3U8oD7cMo4xvt0pur6sHRR4CweyjSDsmHFis00QutZMW08ojRPFiACwMudlAyll6WYe)OF9h9y2gwP78oRu73SKrJFOp4IZ2yVaJNoHb0Whv1(yfcfdDyigxzt9E39bhZQkXbJqpXM3hYmPlmvKUYCJpLAtxz3IMU0m7ejcxWPpecsjhKgw2IbKAtQBS6HTB16pBJv3ZvuiABAkFcxa)mBYlt5jZr9X2AtltnTjmF2zTCflny56iVpUkiiThjkTBKfIK)O)st96yySEKNLutrUJonZwzaEJfHN6)TNSmZZ1rE1KKzQkVbzJMYiRyW4mHVu3yhiAmvuAPFNpZ97Xh)WrhSxE2YZ)hCQi1sgzl4F6duudLRnAlLByUFY7oLGdHHpykLLqmwHqijCkXf4CFLmgKVcefYMTDXMBuE3Nn(7FYONEN)Zj3P4xE7W7D7IF8gLpzNrN(DfB(ldo5BlE8Zg(57V200ITF9v(OSSYF95L3C7H343wB6Xh)LLpENIVyRYD)o30h)tpC8Z2TCRVAw3hg9JF(GJ2RyV)zXgBV20UHxC)7wSXrdo6OHVDVY)XBl2zt3OKK3BWH3Qy37p(fF5W93A0gVyWP7crGLC(yqaPA)cjgFoEI9rx8Fyr6uahmRNFczkPSfwbMnfJXBPGjMzLTKWCZMYAAH1v9dXZP0wHIYjCUGZ0sneqLsFcLFzDeDQJqv0wcVJqLMwA0r4czlU3tOkrltQROSwJHAeudxjmcf4jbQL4DYt4kRBt7djesll6jmJTYteuBZGIuy1mM2YSubxXmGNeuDLxwpPrYHjTTKEprqR9enRYtCjHw0jspuHstvsdJi0grIROEhDfkyFWv4CslSdCgLGjkmO44r2gPhHrZSgTurOmTcjk8862m1vOgHvXjcLs7YNkMiugcvOgkJOzChfviimUg(kXKE8W7)x9vod)Phn61VCWH7p(B(xqX1RFzXBV5OxDRXp40bNSxXb)Q75bV5EjvoM0iIWhqADb8eNZFLgXfgRkfX16aTLXiqLeMI04JYAqveudGu4jda6i4eOPwfiCMTkukAkBlFQdGrpLYJWIeyWCCfKLOO9uO9O6iSjbgmPWVnibyGEqJWSeyWKcnmrM3K4cYKryvcSocJMu7xqBnmNeH5OjLyu0hrXTgNhHfjW4U0IlcAsdOq0MRJWMeyWKCgqIfOjn4ckOrywcmgyvWefIamu0jJWQe4qMeynMOdkS1WssewsRjds)Uu1kCUaBJkdQvr0UcFH2fFmQKkdLIWmgUXOnkRrko3kdxPqXohvUZwTN59l2(Ldo(hko8GItFKR7d0KcAMTZZhD6JgVXDkozDaATPzNTdw4rxz23EtFrLBMU2DUMEL3A91MoPGcpKqS3RXimeqsKtDcayVxL3)1UsBQKQLoTuTMRox)xCwFrn4Wxm8ghwCYVn6n)8mmNJWg)WxvEW)UW1t(wp21kfCYxUBy7E3No4W1hC4Th(GhHpeMBXM)TbhUv5p)u3hlp(PULAWr3XVoRn9mmVCYOtFYWJoT82Bv(177AXdZ8lEUBphAAVX2orfN9vK3B4XFLR5E5MpS8R)M0Gb9cKxM))l5fukOsEHvlVWIYl0A5fwuEHwlVqRKx4qjwKsgKxquV8IPfRsErQboUxEXdlsGXcpSQYlVeG1rytcmwR77EGM01D3ujV4HzjWyTUbCWG8cdBglJWQeyWKHot(nj2qcLx8WE5fpmkVifyZlFe1RmWJWIeyPFre1YluWKCDe2KaJ7sCIb5fomeuEjaZsGbtYnytcrqJQsEjaRsG1EnksL8IxrtyRH9YlEyV8IemJSYKUaHKhHfjWYAsMufyzUqLm2BsAsGJ0hLxrJJD9RUsWLJURoh6oPMUJhOOD0RtydYAWeUagKiXUPiT1wdsjruKUZXDeTIiic09aSibg5Ey0Yt3126UPbytcmY9iXUP(gkiDpaN0NbP7sKb5P7gvlDE8QCxUa6)B9d3sxPFWQo2wObMSgmPRgsb4aLYe5I2AqkjI61peySiHM71p8WIe4qxusva1WqyDe2KaJMuJL(EtsXOincZsGdsw86aQpMlJWQey0Kw8Ihj5qu)WdZjryu)GJtmOFGLQO(rawKaJfZ04Xt0(Z7OJWMe4qXSUs)qRspEIUs)iaJMKhpEIgVfNx)GhpEsaoimBRpEsI(bchoEsu)WDkrA9XtWfe1pcWIey0KyNPG(bEwku)iaBsGrtIPbv15(CPBfncZsGrtIPbL3KyHIsgHvjWy9iMguEtsqyBnSMeH1H2pGgK)0T4zZ08iSibgLaW0G2l5GTI06iSjbgnjQmy8Qoin1qJWSe4WPBDoLP6a1UWMrgHvjWOjX0GXBsSw1yRHTKiSfnjMgSEt6lI5ryrcC8m8wvaMeeJUGRuFEArPxPwBRVCVx4dUCpHwDmgwq2R(2JggLAPkR7cnwUWrpJ3EKEb3P(cCfjHxPiszW75iA12vB2l4QYN1cnVQC4CkqemiImXvLjn3SkHKzPeQXnC46UPB2g3vwyC3S3reecMMyWB3xDIAHLzyWLOLUoJWR03)vnDz3zuh(GFO4GxvE66LR)3DhFTCRhp4W7o4nB7pX84V)Ed3p9Llrnx2qXzEPoH3UuYl1XYIVuhqyTXl1rP1UuKIqCxqW)(lQEFH23jxbAQvL39nTW3QdwYG1aUeuJxGHHOTCkrYmAP7wyQywP6vEoZC960VFNpCPUldU2CR2F53hWH)YgxzIXa)Ppe4CZ)V</p></blockquote><h3 id="千丝之城"><a href="#千丝之城" class="headerlink" title="千丝之城"></a>千丝之城</h3><p><img src="https://oss.luhuhu.cn/202409101028317.png" alt="千丝之城"></p><p>mdt</p><blockquote><p>!LI1spY1rv4FrtR69JLyqrkcrJL7iwELMXZTJgsZmOXDhm7mBWeLOebSadeweKrcfICwyuijoc)NXZ4zwXFbQZ3PQBDU9msilK8JB)9vv9DQtDEu37GE4DgwD8jRxFY93Tz7VCyPwnS6xmo(ELNgwD4XhF2P)KXZFWjND6WsVknSA3jhxW)H675U3MD)OV3dhw9(hUz3iTm3F35NpE627UBZMHLg9eWQDhTz89h3GL8NxyFqz0l1I)zPRmHHL2HT0)FdiBfsx(XQ7F2MZoFy1612X1RH9khVNg9Ya(zSm82c2wcdHmnhnpjDaZshX00EHmKi5rHrWtmZZtTNbzhflUrHbvCeyXtSjY2Ool3xw2qDWj20npF7znS)WIvZKXQzD8owHTS1t75L2YOlIzJWmTjSilDL)Qj3eTTllKJSFAXcSBWX78L2m7pC2MjrQ7LMRNnxVWCxVE9ryZNfhvBjR6DM5kPX4NpK4SLH2380edjT3QqoMG8ankgpgTyY5zRFgMzq44NMmhAONp7Q)xFBQzLQzMf0WXMHPqZT912OKgRrp7xKVPVohQzpM2a4T1N2pfW09OiGBAGsmkQXXbnCeyeXm0rD5jk6Kcu8YTupdKwq7Ehc05KzMVZm7mPBbSjOzBqZ2HU5tC7THO970gYnBHMNqrzs0cLX2X4W2XWPaflH2og7mZkmWviyH9d3s2MSsd5BAU9WWTeRhUf3UFMlWDlhcn)zC4MPg5PilAWr2HjkTXBYeOY4bpEGsW1OiaV2PHBMtzK7TTdCQ6(zvt2VDM9hHbWXoCDmp(tvVAiDAMZtMtUx(xlUF)8fJrUcg3mdE7u)KFWUtF3XZo9Tp(HfUInUA744p7KtF3HJgw9GXnJ3Fl1UQEoa5p)K1B)XRx)GXTtTEQl52Xhw(3RFXtU6zpDy1zh9tlZEAmRoE25HEHUFIChYbqXc1Qrlpahl3Hw0n80w5ZMfiOB1bwLAbvuMa9lq17vhyYHf4mSbg6GXHvHYCmKdNaTlWrDdKAt3qljyfyljL2aynTcLG5jyNa2tWXfCYpbRwWn)MGtcyssTEHdNYf4uMGPU7nyJaMKu7bmKmLaSVdheWKKgfCrqYuCb3BRbBvDyljPXdywYaT5T2oStatsA5tSqfwJMItWjbmjP1rY4uDyNUdBeWKKw4QCobSVdlK0rs6mlOEWcjD5jyVqspjPJdles6TDyHKEsspCv(MKu59yhojGjj9y7eeo2GUdBeWKK(efSfeNLbFhwCwgijdoY1hAHpfJnKNGJQoCKKmKOnF0udKPNTDyNaMKmQXI0YqksgJD4KaMKmAxuQzLyjZKKjDh2iGjjJEatsAviLk57WbbmKmsgvkbyCKKYtWzvhodjX2jJAaAfE22HDcyizgpcj1CkFSdNeWzgM6DRGM6ixxqlimscs2KIjGUM6p8cIGKikiG2gCsQv5obke1iqLOe2oAukYAI8OSccNKWZod8meVKDIFefejjr1ztfNqjjBjdL6bIAsncJKOEgtIJYswlVUgVGiijG4gSNqPjBjtf3Hj3jqXPgbQofqrqnkpzDoSuO(uJWjjiXdEUsneVKFJLkkisscKmHeiTJfNDIOovJWijqomF24yXZyPqTQgrqsulDGLkvjiNiQxvj8kbbxXcb)AuYY65ouCnRkHtsqI74gtOSfrqMlQB1isscuFoZ9Suvc8IkAbHrsGA0OGGoWIJUvAu)QreKe9wd6qQsqIJAyvIOsqGQyMa0lAQe4hwbHtsqIBWLc0rwCo8b1YAejjb6)YlvsvjiZf1ZAegjb6bZ7jUKwJWlicsIARFSujjrUtKLIJkBkhm3SuCuBRrifhv3uS4z5oh13AeYDovHJUweU5HQtyuAbHrsGBxX3NqjC7gLxqeKefX9Pip7KKi3j0kbbvHZNSmHPhmyOkCteojbjEmZZoijIcIKKGepg4lxP6HOgQc3eHrsqIxklrZ24KeEbrqsqIxklrV6KjjjYDcRuCQcNV0CMmxBx8PpXY)3xwMlRYLVcKfBzlXWxwMQPL5llZGHoi2m(2LLPAaoCz5kOw1r11TbkTdylIVTDyNaU7)QNDEorUdNeW4GZZHtao28qwHh6TCLqRseA04DgBUKLT(ah8AV1bHqPPxwftXItixsokuU9DKx)zF7L)HV66F3V5Yp4F)F(Up6Ip9VF1l)Jx)4p6Yx(Ol)NV4I)2ZF9h)HV6B(Wx)PFh5Gpf(z(Rl1SaFPbtU0pQy4opvONLHSaxWLlLLDQuPkrOuMPq533cE9x8fV6RF0Lp)VEXl(2RE2ZU6F98x91p9Ip5ZlwZvF5lU8V8zx(Op)Qx(4lE6F6IN9nx(KF)1)5F9R)v)JlE8NCXV9jcBY))iU5OBe3eVrCtiIxubNLj(TggWTiT14MOVg3ubdDWANwvnUjIPNNa54ggfxTjO5BxqWLHO54MgStaJ(R4wG14gUhvSdNeWO3QbBdoUXXvf6WgbCTVk9boATvjyFhoiGrpv30lzzD4U74ImmC9EmagxJXH3fWAMYV6FkV3OZQBjhNFbtt1TM5CCnUvbFwblYpbg6Gukx5DiTTZQC9SQcwpRYTZkVg3VNpRs9C8kStatYzSCJFah5E9D4KaoZWP2zfEBP(xY8nYdDZOzVbVKohHLN8qXf(MhYsvX8tGHoi8qAYbWEOejEEcS6Hak8qL3sjm5HmTO5gStatYPm9Oz(TpHhQcNeWKKkn3TDMhQ9HGU7HBg3UD8TpD9zKl7WDBp77t403W5o7ng6J8W1qh(V</p></blockquote><h3 id="仙林"><a href="#仙林" class="headerlink" title="仙林"></a>仙林</h3><p><img src="https://oss.luhuhu.cn/202409101155220.png" alt="仙林"></p><p>mdt</p><blockquote><p>!TrvsVrnmu4FrLANeVXXsvf9sOiJ4OrzMXEiqiPAgN2cNgbcXfelxGkHaPk6b4q5cNaQG)mmWmN4VaEjBUWmrr2p7VL3ZphbuCdbFsUsLpUUqFFrkei4hkL31msWZMmPQ8MYzZZRkfPiavWRZNi4Joa)a11rBNOVQGFqwrT0sZ46zZKL69Qlk880eGxpQqEGSWr5SCL(Ak1CPEUbtQvFT5F7E3UUCQSQC3jhjsJnBxlL3lVCQyKGpxwihRToXHZQGb3(g16yQ9vkrKgjsPgoePyrAI7bzF02v8BkXojUzcYHWfkzW68XvfvZeCLkwQuDOJ79GfgBimQlezayluMSvTHuglTk7Xf35GgY6HZSABsKgrTBGmyIULK(GwQISlaPUkCVOQrwrHmx4uioKhCap0(SZXtFPf78l8cjzhZdnHDJdoaAosWbQh5vNeOEBbXoaf4HwEdpFydvV16oBcC0a9hZqV9jbgi2BaVa0)TNOZuTPFyI7BnybNUmxHocgwGnEXmpceibzqJkZfK6M6AX79dmSE76i7Z4iFVyutLZx6I8L9ip9qwqstCwYD9tlpY8E93oE1NovWRgDhZvTURv8j(r7GbaCucKy(fdOeIqTrI7uANnWeeGqOmgehHGjULqnnjgJSL1g8F9QpU(ShUAXJx(LpNT8nVB1jl(Z5pD97F2Vp7TRp5R)87)y55lw)6pS8fpA1XVC1ZFI1ALgWn376mcfaGaeeqzjycfXSQL4ncngazgJeJiiumM(FnYT169NF5n38WSPvxkVAtiE8o3crZq9c2wP3lRqQ1YDlvvwhKvRRUInU9RsBDH9y)QL)cS4Vd</p></blockquote><h3 id="通灵战潮"><a href="#通灵战潮" class="headerlink" title="通灵战潮"></a>通灵战潮</h3><p><img src="https://oss.luhuhu.cn/202409101115396.png" alt="通灵战潮"></p><p>mdt</p><blockquote><p>!1rvZUrnpu03NkvPe787wavajKBLsb2zX8JD1aHe0moTfwGa29rLyhcOSfqiKOsSGfLsFB6WqxXRa2x7KCDMp0enJ9475CVNJV3Wd57YlQhFFXe1c9sgSFQD1wj0OWiAuEaniv)tcxUzueNr4BTzAqsAsEqQ(jkLKchfZzudowe)kCwmVy5RoA5lF)QxC6F(5XRE35x(LpV8)(4QpD2gKNEVlF2XRE(3xDYxnB(1XVz55F7Itp6IF86niCfVOstHYS4aH4bgslgnDAD1DeZxmRUsZEqgVOz2uEXT2F7BFdY8NCWDVoVysDz98DgvkukXnRK1g1mQrvFvZ)pRApnR(Xm9qt5QZJsCO(7lp7T)(KpODGzs5SjnLQhRZDaVy)rLncdztAMpxuP2PPSKZY62x0mUuSVOeQ05ZKQTLYfIElfKIl2R1uTNOUcsnn2KzXdnL2yEXcrP(IWiqaNobAypsNRoIA)Ib3dMfuyreSigEs4SColfQCnfSWqnn6GSaZH4ZS3vbasDagCHealXITnMC4pxpYudPuhPM7m952nq6IrNyTCEHusfsjQyCXNz1IhJ2cjgZBeIkdr5ceahvoBjXkVySWBpJIttMtV(fjvGYRdnbHofP0(kk3joR0dXUrgEJ2lX7iDoL9gvz8815xkLJT1vI50ovL0AE9ko7)X7ngMgUXfWjNI21jSq8TAi1R(OEky4TBUaji)otvBLHRiTH1NGiS0J6Zw2ATeDX1EukCuckNzqJk128cb0(NOKe7GHfrUZLDAmC96jS)63AkyhH655q)EVJK01TP6P282bgjW9RDFldJcD3A4ocgHW31XH3GeXvqb2EHC(AJEwO4A3ejfKxc4hPWIiyrg8KdpXDv5GEvsOFluO3ajX6BKy(AZU2(yNL1tn0fqWVyXqQ3SiXMEIpqQx1mSZ04IeC3Ex6BtHzSDWWSPUX(E0aPMGG4MpzKepid7vS(TQRpA48jj7FaGrYhK9mVSBh(OEV2HgmasoF95pkXli7h(F)</p></blockquote><h3 id="围攻伯拉勒斯"><a href="#围攻伯拉勒斯" class="headerlink" title="围攻伯拉勒斯"></a>围攻伯拉勒斯</h3><p><img src="https://oss.luhuhu.cn/202409111200515.png" alt="围攻伯拉勒斯"></p><p>mdt</p><blockquote><p>!LI1sVXXXr4FrCr)(XvLad4lBmWkKGKddcFm0H2R5gqn0X5sGSISPKPKPCeGnTGSbIHKHIeSEdljs5O)mCgU8u(lKUQAMPRznt4bliUO7VQ76RQQRQMPNczX5lMS8ARnBZFB5wxyJzBwm2kcftwD20zB9olpTSQQ8T3C9z4Y2UA2VcW3yZ3T4ClSM1(OIXMIQIjvLFu63toC)5p8oftMTY7vUA1fsBFms1A0O3Yj0ERtidkHp4S2I1xYOlgRkERLCYO0gJAtqBSoVbezkgRH9LO4CjlSyY5)B)XMNDVMlV3j)JV7KB(Xh9QDB(HRb0VzAbvGIYKnwkbay0qLSo(VIXUIXlfGnpL2Wex0psa7zYsAHzKc24eximYdBEYsQOzKeD2w3zjFmiKoT1z0szYJsgTvNwrfSvMFBnoBYJTsLqf8EhZVdwDYP9ETWAuwNgezx0KL179cYXp(sV6)86RL(T(gxF(BU9X3B35V8FD8LEz9Rb86V)snF7TB(M7E0lVE9EFw9JFY5B29Q1pEVMlE)MR8LZV4NmFN7x)INu)5hM2wAdNN0kTI67880(M)9FC9JE1rhCWX)77WcTMFrHwLiaXti0kdIrAm0kJIrwk0kvlgATPtdNo6SbN0R0q(GvrHw7GukRsMYDmEJYhDXyBEdeATgP1QeP)Cwtqyo1qRAHq7838fnxz)J(PRF8d(6uqifqo(Y)4rV(wZF0HhV7xxVZHSyIJBigVtymXeHoLYlmCdjy8kBmenXuYs40pJjJy(bpT52h08T3pzkjwB(boF(boEq5KUqQGse9EBN3H8LeKsiJYuANv7uNkFNCRBm)Ghm)fplDYNiR52xD1zFWkZy0f405TELsQKMGvfCkKoxxPRXemU0rv0y0EFROH0Pxio3C4)C(F)NozN9Q)0NMIQnp77swWrV8on7Epir(gxR5R(X6DoiLtwF1R38zxmT4JV1LN)OVP(HVQz)BwN24xSpeKWm25p)(mdpoiofdbFikeXussuIbJqBCsMY7CsR0O1rV()X5YvVz9lUBQqdi7np84l9WCb4NCJ5p)UqxOh)8MNE4XF5xDYd2V(ZHvMqozhiOEYtV3jp511x5bPAoMjkf86P4ILtRCgLtAd0uckNCoyuQAsfmqDfun59Ju8IjNtydwNnLrKQMCyTKKQLK8(ZJ1KDm6mSKuI45gyosrU6w324ujIJcTv3bjm02d6YGEc0aPBuZbdep6atXPEuPKGt9OLixEASodByWwQTtYKLiFPOcm2NHdm4yUjfsP3HJz9UumyKspy)kIsdo2MHDmypbdDdik144ypSwKH1sco5cAIsfowNHnmyKsh0hvtuka3r7ZWbgCKGHtwKsxeChJmdRyWiLw8XFiLo01m2mSJb7jyihePmLzcJJ9Wwrg2IuAgLY8TeL0yDg2WGTeCYDSeLACSpdhyWrco5ooIsfowMHvmyKsn4ooIsbo2MHDmypbNCbhsPnIJJ9WErg2JuQW8CKslgQ86mSHbBj4usGhP06WX(mCGbhj4KleikTqcrqMHvmyKsj4cbIsnKqeSzyhd2tWjxiquQGeIqShokYWrKsbCqfjkfG7e1zydd2sWqzosPbl0J(mCGbhjyOGwGCAc0ejtGIlaFZIiwulqEnoAILjWXf4jbqRpbXTLMeZcOgrTcGorYyaChj1kYOPjAMadxGLeGTXiYv0eptqGliscWUDe5ySuQKmbkUaKCQDg1wshH6bPYYe44c8KaWNOwt6aK5ivXSaQ5uRanso(mhj1Es3orZey4cSKa4bkulkTLM4zccCbrsa2qNixJoOrYeO4cqYTOdsTQ0k0bnwMahxGNeaoi1UsJp2tAIzbudRwbwKCSHUKAzPIOdA1mbgUalja8jQTLkqt8mbbUaKCYNOwxkhnrYeO4c0KaWNO2xklnXYe44c8mbHwbTxArEgxG6mETexW39EakTevA37Gmw0YG(xidXUx8rtpuP9kAX8v0CdUhHZl9wlCZsNlDRUa7EeYZ4on)CBXp0wcJSTEBS3wI0JrbW0tO1dSL0fa1ALlDBrRslsDW6TL0Q2EJ1kMS17VI4T)D)()079h2kX8YRwH3nprXhU80TlbZD1T3ARYnRENTNoLENKwGjBVY0YpSCkAA)5K0(BF39ZymWLEnlWbX4f82vvT3OhCuDj4OM2L3gLuCviDuqYtrjdPfBr7fEHLGt60HHPFq7Xs66BuyUITVwoX7FdV2fQ)aP)iZog74K54KHm76TE60CO)Pl73GQpQ0QpMMCCnPh4drigv17fTKzicPlpOCC7vk5A2pWGwFfnlGyPaIBGMPdnfDQPIlepHT7yX6EEcmBeDN2RpckS1UqJmWTsEKcoPuo(A1cmi1EXWXD7KU7cLqqNxw8)yqaVMtxYe3W5jAywiEPT8bxBYbEtUERkIHlvNB1LmA7sgzAbNOu5vwXmhj3TyrauBOX0ZHsoiHVpHe8qiz1HSGLwdZtgwlrjbkD)PtlvGsXVU04i36BZeidT3a10UudcSCwxwsze9SQ4kTlgqbfDFmOpIJ6kRzhB1DYmdsE6RKjlt3QfQRq6z9qqsBl(zTyQ64xlzPhq2npDRTMulyhPl0ljBsdYQL2bZcSzl0maYm60EFqOFAftzEULkZ9WGDzAhWj7u6AKjR78f)asl0nOFr821UCosVLOhWxN1ssZv(5It7G1Vy0ePoUqsrfZCKuRzz3hoavKsmiHyqHL80o46AT0Ni19Mhi19NBK6md8c0(v)FAO0lwjw4qLBBdlFgMDsny6TndzB4wxSYwRy(kSifBrDfIAnpGOhKwQnduqv)tY)1BV57woBt8BRdxcOQS8dGV9(kftUq50s6DcA9fmkS1gRx9BwF9luM)I7TACTnwF9nwD7Pv)v0LN8xklFFIWI)7d</p></blockquote><h3 id="格瑞姆巴托"><a href="#格瑞姆巴托" class="headerlink" title="格瑞姆巴托"></a>格瑞姆巴托</h3><p><img src="https://oss.luhuhu.cn/202409111434619.png" alt="格瑞姆巴托"></p><p>mdt</p><blockquote><p>!TMzBVX5rvy4FrE1Z8(mFnarQvGBrRfiXhEeXX7w5wJnkEDB5lroTanrH8cHckjnvqlPnusleOru386pg8U2(t9VaZCFMxo7AlAbvj3M1xZZmNzoZzUFUN19I(v6hU26JhV(z3zJj)I(LfD9dFJrJET4N6hEM1wBRn)rJo32RV1M9lB689d3z916h(9wBNW3)h)g)GFYp8v7h(6NzJDgLgMZUZ5o3OnN8Y7SXgXERQGH7S6gJE9rBGH8NhBD74tVSG9)wwIFu9ts)BbnjrA)YWZU1gBDU(HJhRgnEm7rPhrZ7mgjD(xeSoN6AyeBOPhXG4B5dHMpelgF1iwR0J4WqGyVSNpq0YZGgSZnvc51HHpobAC6WZlKPOSSGMIcmcllmiAI5wX5W7YXh9YJEfOo1rDsGwtJBGgWud0qPoPKNcJRgFWGpyXhCZLrgVkLrSOoOLQJ0uqA7dts9CL5YLXTd0V6MUzUIck0kQV(fg)y(R2xfVVLn0uFDuFdZf3qAg32JmLNGVvIUfZpRGmuBrGqMdgF)Suxke1UWRdS8y4rmcS(FgbYxtWUZkT1LOmih7iagm2IMYzESOd5zps(oE61px6vXwJZxNNpQ0g9o(8h)2KsIXpxAxp3Ks0FsNDeg(et0MlLHYcKR)yhyAJSKpHK55JLpFc5mcFnQ6pPkxHJ3pATw7YIkikEAHoHqhHcSyKga)CdkTkfk6OD)K26xVqoIKOe8s2s5E4)sQMYzOyovZ01F8kEXCLvcZC)MN9BPbqW3Jm8DhHSTQx4aqDgANBULpu5ZdnDQyr9)0pA8Jb)yXpo8JNuUs9wDcPT2XhPQFLJDuriNBLkAB0yArrxqXwy5cNcs4KKvR5w9cBnPtkI5E3vBXrXqskzPeHg5wiP7PkDjfKajmKlFKMfwikEq0SZV1qrzzjPbOYYNK0TKYNYacLstHYI1PQJsfQ8cwzY5KsLaQAKDZLdDN4PJaxzYH)zcEaYmW3DNnFLrBT5lS2BMIKSF4KrJ(zRV5R0VA)WThTXOZoj51OE0k2XZT(4jV04XBpAs13qEiNm6nJ))JE8np8VD3(HBT6Rg7D9zgUwEuYVqnFOlMqovkDKo6NF9XYlLkkhUb98d1s1aShoCjHPBa6iG41FrOtoal5juhoTtyLgL22j60sN33pEjtwnsYMiN2PLYGZ01fuANmMQhVKgBINEjNjiTgV12z0DDX9)ytMfNXN6LgoC6x8bhT7J)QN8Bo8HpC6d)dhC)BD(xuo9AFrQTzF(Fz2V8Ah8wFzS59F0Jo4z39O3)pn9oxm(qjYtU9r3(AZUZJIpW0RFLz)Jpy2F83n9opA6DEqS1d(1V70)5Nm7I38O39UhCVBSY5)PhDNDp8JVWr)5REWN9(Pv7MXzr(Oxn1sLGIbFnj3yzWPMldl0dKugwkedmugw4giPmSSZpa1SfOTbDP9cXGUu1Bc6gGT4cmzFTqfyZeHsizyvdRz4u4K2bjBriEIUb0X1k2ZWiKyYjrifO(qkAyjdRAyesHDGhNiRyldNdPdhKJyjcPmuXQUgwLlz148Eclaw1WAggHSlfsLnpijXcxd7z4aTfetSAAvgsdIw0WsgwrBTjruAvAsdI20Wwg2vle0uIvIbjuXMUg2GqAsdIH2ldPnnJQH1mSPobnLANSWT(BJ63ouRbfcVzaCzoufWwJodH37c02GUeuoWr1Vcp2XdviQFZ0u9RYJuRGILVu)wWAgofUymm56xrOw)wWEgofspo7H6xrqLwhsrdlz4uiDEuCIqgWbIu9BbBz4uiDwiIshs7aouXu9lHt1VkNcLB0oRUu)wWAggHK0mA7SO(TG9mCkK2ak3kftcQ(TGLmCkKwFAbVy9BbVq9RY6a2ZoeeQyd7iJbH0cmDkvbSQH1mSHWQs9RKEexd7z4aHJLKwesfo8AfnSKHvnmcPYMsvwtdBzyxdJqQqAZ2cPRRHDTvPdHuRshKDTvPtZWgkvLu1ri1UuiDUg2ZWbABizdeH0OWPirdlzyu(0L6OhH04tH0BAyldJYhjWiKwjWHko01WbuXQbgH0AsHmOAyndNpKKEnfczCYMWUg2ZWTZLIoeZ4Sf6ccwdsEdqoWqV8dX1HzPOZWAWYBascEQ3i2of1qO1a9I0CdfLi0Gm3GMeunFliOMMMUSHaRgQcjORiOMtoMkKLiD1PMVTgdT5BhBLNdLjlOkJ7wUIGkH1mmcNe5pld7AypdJAf82hYqGZuYqwUjqJk4cwNqhf8JV5YLC6PitGgPrOKkLo((L4RU9NOjWPx8(tV6JN9B37WNFR937U7V3FD6DV3bx8lp)lQI2axDRT3UAdC2LV00l(GdV3no86pnzX7c3p6k8WN(PXpm7Qxkr(WheFGdER9M(EFiZINJpF1X5Q35m6qxi(FE281QCoxSmtextrjuF2p78Z3JU)nNE1l)vp52ZU0No9kVZ)E3lm757oB3Be)q055S3)5PpC99M(r)RdEVNXMeEEzv52MFJ9WBcc8wP4gHqzYomnwz1dp84Z8WVKtMSURernvFCzMCGBY7FbE(WAnwN2eT8h9W3fFbtlF48Y0iy60bJYBvNy(qFsM137kh(2pnUBC49(4J(GO7(lU2Rn9j7EWt)KPF21NET)((p(JM(RUYSB97)QNK22MDPNT)EF20N)27V3LI7Ur797)0RWsD4RTOvW516OOOZP9M4RakxTafC24wBORZg6SoP)KNWh9SBXNRtFNhF0U7o9bxlg)yv0(7D5y5ip4IVg9Gv)gOhK9Uvm6vUGqOQhiu1lieQ6be0rU71z9abErsOcj9aIkYU1Df9abILq1WAgofof8it6b4gh03ZJ8)5fT74lAfztcrKS2xNhLfTGw0shFrlQlAzzrBR3kIUNtxJsl6o2I23w0DSfTVUOfE2IUR4Kw81DvWVr70rBDfR0rftjTOJ(RL5dQrjvnTOjOTbHvA4nGSsRYl6mmBLwvw0QGIzLgUrGYFgRzyt79GfR0jm79MEgoqV(qXSsRkwPjSKHv07XpjR0z8XSsdhKvR02IvAGRwPTfR0O0UALwuSstynddJjKFCYkTRCvWc2ZWiKWDt2kTOALoJLmmcPe(KPQjD1kDgBz4S7Dv1knQ9GvAcNTsdSP5EpBLw2SstyndNnz6zwP7kwPjSNHx0kTej5JzLoJri1mR0YMvAnZkTSzLgl(SvAlkOdvC2knWKvASeYwPHRvYknH1mSHW2QvADZknH9mmcjUzhzLwtUGfnSKHrirHC2knzu20WwgoFHbBXkTbPnFOIjR0eoKDVRkwPnHQv6mwZWTBIrwPbU9NHO5x4)xXiFtmI(Qtsq238Ng33QcTnieJcff4KwMnlgfQkWzkjgzAIroMyKPjg5AIrbY4pfppEpMRH9mmeJWRhiXiF3aDrmIWsggIrQMyKhRAsms1eJY4SyKplgLvllIr(SyugtIr4sKks)JENMQH1mmug0vXO8x8ajgPRIrfmczx9E9IOIFOig1vVxFb3QMiXO4Bsc9171RkIrzC7s2Kyuh2s0HkMeJimjgHVAI83lfPrPAynd3oMsIr0x8GPDm14zyes6s7K(NPDVEclz4uiJhiSfXiY1ceJYyldNcPblEsmI((THyeHjXicdXiJRjgjXxWbeJYyndJqIVclsmI(IhGyug7z4aHRIrkOCcXOmwYWkcxfJu4iR30Wwg21WK(NOEVEctIreo0cjjgPXnhcQgwZWgAX7lIr6296ZypdhQBd571BYxgxWAqYBaLqcQbseKUIkUxFPblVbugHJT571BYxYp0AGScMBqKFVgeLOBFNVOSI1GM3qtcwqgcTuWHEuPbpVH8z10NPBgBtVwP8xfk9Nn6LpZgJMmz0lS54TsQ4NzNjB9Ds80FwOtTWZK(7gr3lR))a</p></blockquote><h2 id="PVE"><a href="#PVE" class="headerlink" title="PVE"></a>PVE</h2><h3 id="TANK"><a href="#TANK" class="headerlink" title="TANK"></a>TANK</h3><h4 id="德鲁伊"><a href="#德鲁伊" class="headerlink" title="德鲁伊"></a>德鲁伊</h4><ul><li><strong>优先级</strong>:急速全能暴击精通</li></ul><p><strong>TIP:</strong> 猫形态痛击同样减少明月CD,赶路过程中可以来回切换释放痛击刷新明月CD</p><h4 id="恶魔猎手"><a href="#恶魔猎手" class="headerlink" title="恶魔猎手"></a>恶魔猎手</h4><ul><li><strong>优先级:</strong>急速全能暴击精通</li><li><strong>机制:</strong>魔化之后强化</li></ul><h4 id="战士"><a href="#战士" class="headerlink" title="战士"></a>战士</h4><ul><li><strong>优先级:</strong>急速全能=暴击精通</li><li><strong>机制:</strong>通过盾牌格挡+无视痛苦来减伤,消耗怒气减少天神和盾墙的CD</li></ul><h4 id="死亡骑士"><a href="#死亡骑士" class="headerlink" title="死亡骑士"></a>死亡骑士</h4><ul><li><strong>优先级</strong>:全能暴击=精通急速(10%)</li></ul><h3 id="DPS"><a href="#DPS" class="headerlink" title="DPS"></a>DPS</h3><h3 id="HEALER"><a href="#HEALER" class="headerlink" title="HEALER"></a>HEALER</h3><h2 id="PVP"><a href="#PVP" class="headerlink" title="PVP"></a>PVP</h2><h3 id="240910"><a href="#240910" class="headerlink" title="240910"></a>240910</h3><p>队伍:猎野牧</p><blockquote><p>起手方式1:野德起手4+2晕主目标, 猎人胁迫+冰冻对方治疗,33里面牧师要卖位置去恐惧量力而行 够不着就野德去吹 换技能或者压位置都可以,基本上一个冰冻一次进攻节奏</p><p>起手方式2:</p></blockquote><p>菜刀队伍:战惩、死惩、战死</p><p>猫咪视角:</p><blockquote><p>总的思路是早起手,不要让惩戒骑着马摸到我方牧师,德疾奔起惩戒第一时间乌索尔最好能乌索尔到战士(概率较低),流血挂完留意骑士上马就接蛮力猛击,基本上第一波牧师就不会被集火到。</p><p>关于第一波起手的伤害,要尽可能打出无敌,有无敌的骑士如果摸到牧师一波章两波必死,战士有盾反、风车、不吃恐 不好拆,骑士可以顶无敌进攻。<br>提供几个应对思路:</p><ol><li>冰+胁迫(先冰的容错会高很多) 拿来拆火,德的位置不要靠太近(可能要提供换血服务),相对战士,惩戒骑好拆很多,压力特别大就自己恐骑士dps转战士</li><li></li></ol><p>大多数情况下不会打野德,只有cjq被德黏着集火不到又开了爆发的时候可能会打一套野德,不吃同步控制的情况下单惩戒无死亡压力,如果吃同步控制战士又有转头的迹象德自己交技能顶,ms留章</p></blockquote><h2 id="专业"><a href="#专业" class="headerlink" title="专业"></a>专业</h2><h2 id="首周"><a href="#首周" class="headerlink" title="首周"></a>首周</h2><p><img src="https://oss.luhuhu.cn/202409120915733.png" alt="装等说明"></p>]]></content>
<categories>
<category> WOW </category>
</categories>
<tags>
<tag> Addons </tag>
<tag> Cnf </tag>
</tags>
</entry>
<entry>
<title>一次游戏开荒经历</title>
<link href="/post/16447623.html"/>
<url>/post/16447623.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="一次游戏开荒经历"><a href="#一次游戏开荒经历" class="headerlink" title="一次游戏开荒经历"></a>一次游戏开荒经历</h1><p><img src="https://oss.luhuhu.cn/202406171137694.jpeg" alt="DNF"></p><h2 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h2><ul><li>游戏:<code>毒奶粉</code>一款老的鹅厂端游的手游版本,几年前就有过造势发布,但是被版号摁住没发出来</li><li>伙伴:两个大学时玩的很好的同学和一个玩的很好的同事</li><li>时间:2024-06-17</li></ul><h2 id="经历"><a href="#经历" class="headerlink" title="经历"></a>经历</h2><p>我个人开始对它(玩这个游戏)的预期便没有多长久,所以也没有花多少精力钻研,日常的工作与学习几乎占据了空余的我。</p><p>开服之后,服务器一如预期地炸了,仿佛新游戏开服不炸一下就缺乏生命力,开始关服、修复、给玩家一些蚊子腿补偿。换以前,我一定会说这些大厂的技术不堪大用,现在有了不一样的角度——一件事情如果走的过于顺利就容易显得便宜,相比蠢,我跟愿意相信他们是聪明且”坏”。</p><p>马上玩儿法上有了很大的区分,pjj和h首当其“充”</p><blockquote><p>pjj : “疲劳刷完了,怎么办?干点什么?”</p><p>20s later</p><p>pjj : “妈的,合天空去了”</p><p>20min later</p><p>pjj : “操,充了两单648”</p><p>我 :”…”</p><p>h : “我看好像挺好合的,一单下去就差一件了”</p></blockquote><p>我觉得我应该是拿得出这一千块钱来的,只是我不愿意,即如我妻子所说的狗比,我的吝啬常常让我在三个人的小群里显得格格不入</p><p>lyc那边则完全是另外一个风格,他发给我各种文档、各种攻略,企图教会不太聪明的我如何聪明的去玩这个游戏,在跟我讲的时候我顺着网线都能感受到他的光芒——智慧的光芒。</p><hr><h2 id="话题"><a href="#话题" class="headerlink" title="话题"></a>话题</h2><h3 id="关于工作室存在的利弊分析(开放市场交易的利弊分析)"><a href="#关于工作室存在的利弊分析(开放市场交易的利弊分析)" class="headerlink" title="关于工作室存在的利弊分析(开放市场交易的利弊分析)"></a>关于工作室存在的利弊分析(开放市场交易的利弊分析)</h3><p>由于游戏限制了玩家之间的交易,所有的交易必须通过拍卖行且不能自主定价(系统有一个参考价),向卖家收取10%的费用,并且限制商品买卖次数,即你买来的东西即与你<code>灵魂绑定</code>,不能做二道贩子转手卖出去。</p><p>上述的规则引起了一个话题:工作室的存在是利大于弊还是弊大于利?</p><p><code>ybh</code>:<strong>去掉工作室,从某种程度上可以减小大部分个体玩家之间的强度差距</strong></p><p>以下是小伙伴的聊天记录原文</p><blockquote><p>能享受到工作室利好的是没什么时间,有点小钱的这部分人</p><p>但是游戏需要人数基础,绝大部分玩家只会充个月卡之类的,这部分人的游戏体验会被工作室影响,工作室的存在会把游戏节奏、进度加快,人民币的购买力会加强,大部分消费会从厂商转向工作室,而游戏厂商需要盈利(破坏游戏市场),工作室对玩家来说没什么好处,他们也是赚你的钱无非是从厂商那边抢;</p><p>一旦开放交易市场,马上<code>泰拉</code>(虚拟货币)就会变的不值钱,原本有部分不买的人会因为低价去买,这时候大部分人(新增的购买者)都变强了,我(不买的玩家)吭哧吭哧玩半天排名却越来越靠后了,那么玩家就会流失的越来越快,游戏最终就只剩下充钱的,而这部分钱的大部分还是被工作室赚走了</p><p>比如dnf手游由工作室,本来<code>碳</code>是200一个,现在只用100了,那么会出现一部分人迅速变强,团本开放之后要么选择充钱变强,要么就是在低保线上垂死挣扎,等过段时间不氪金的就跟不上大部队的进度,人员流失就加快了,只有绝大部分玩家的游戏进度接近,玩家才能玩的持久</p><p>手游和端游不一样,手游的大头不单单是礼包,充值换泰拉才是大头,资源限制逼你充钱</p><p>有工作室,我100rmb能购买的材料一定变多,然后则会部分人比之前更强了,本来大家可能战斗力在1.5w、1.6w上下,现在大部分人变成1.7w、1.8w,而低(不充钱)的人还是原地踏步,跟大米(WOW)组队一个道理,这部分不充钱的人就会组不了队,进不了团,然后这部分不充钱的会有一部分转化成充钱(找工作室),游戏厂商啥都没捞着,剩下1.3w战斗力就会慢慢流失</p><p>你可能没有感受过单人玩网游的组队体验,刚开服的时候所有人都是一个起跑线,差距不大 打副本啥的随便组,后面慢慢的 别人有好宠物了,但是还愿意带你,再到后面 大家已经有神兽了,装备也成套了,自己都秒秒了,带着你还要卡时间,慢慢就不可能会带你了</p></blockquote><p>谈利弊不能脱离立场,在这里有游戏厂商、工作室、玩家三个角色</p><ul><li><p>厂商视角</p><p>如果开放交易市场,工作室的存在会迅速让泰拉对人民币贬值,但是厂商掌握着交易规则的制定权,就现状而言,商品礼包只支持人民币结算,即泰拉的贬值并不一定产生商品礼包销量的降低,但是一定会降低泰拉礼包的销量(需求泰拉的重氪玩家会更多购买礼包,而需求礼包的白嫖玩家会更多的搬砖使泰拉产量上升,微氪玩家会通过工作室获得比厂商更好的人民币兑换泰拉的比例),厂商下场出售泰拉就好比国家队下场卖房,卖的房子性价比不一定更高,质量或许也不见得更好,但是最起码炸雷的概率小,即便炸雷了,某种程度上也保证了肉烂在锅里(存在个体背着肉跑国外的,但是大部头总还是能保障的)。综上,厂商直接出售泰拉,且禁止泰拉与人民币的直接兑换有种即当裁判,又当运动员(且禁止没有血统的人当运动员)的感觉,容易滋生腐败。</p></li><li><p>工作室视角</p><p>如果交易市场关闭,工作室几乎就没有生存的空间,只能变成劳力外包(劳务派遣现状),没有市场就不可能存在所谓的市场活力,就不会有孕育创新力的土壤,也就不会有对外部势力的核心竞争力。这种环境下,工作室的存活首先要保障的是自己的血统,而血统的获取除了娘胎里带来的那就只能去认干的,这部分会成为工作室运营成本的一大部分,对技术创新的投入会变少,干的好不如说的好,对于成绩可以通过丧事喜办来解决。并且对人的态度会变化,人变成人力资源,变成生产鹅肝的容器鹅、生产鱼子酱的容器鱼。</p></li><li><p>玩家视角<br>玩家的视角很复杂,因为玩家是每个真实的个体,他们中间的群体组成了厂商、工作室。</p><p>对玩家来说,其实无法真实感受到这背后的博弈,因为大多数玩家其实本身就是桌子上的菜。玩家能够直接感受到的是价格,我在厂商那边购买需要200,如果交易开放玩家可能只需要150,当然也可能需要250,对于部分精尖商品(如骨戒),工作室不会允许它以厂商指导价出现在市场上,如果交易市场开放即便烂在仓库里(把牛奶倒掉)也不会允许这部分商品被廉价出售,而没有交易市场工作室便没有这个牟利的空间,便没有了囤货居奇的必要。在对玩家进行分析相对前两者要更复杂,玩家视角的分层会更明显,大约可以分为重氪、中氪、白嫖三个层次。</p><ul><li><p>重氪</p><p>就重氪个体而言,他不是菜,他无所谓市场开不开放,他本身可能就是厂商的一员,是规则的制定者,rmb和泰拉都是数字而已,他担心的是不要有人把我的凳子踢掉。</p><p>对这个群体而言,他的考虑是很复杂的,首先他要保障自己被很好、更好的服务,但是他同时其实又承受了来自外部势力的压迫,他要维系的是你们(奴才们)要有能力去对抗外部的入侵,同时这个能力不能用来革我的命。但是他们又缺乏判断技术能力的基础,他们喜欢看好看的文章、精美的PPT,他们可以安慰自己,或许能力不一定强,但是最起码我保障了奴才们真实的服从力。</p></li><li><p>中氪</p><p>中氪玩家,或许是重氪滑落下来的,或许是白嫖玩家通过“努力”挤上来的,这个努力加上引号的原因是它(努力)是以结果为导向,以效率为第一追求的,即它不是非黑即白的,政策偏向群众它就讨好群众,政策偏向集权,它就讨好领导。</p><p>交易市场的关闭意味着高度集权,阶级的跃迁和跌落大部分取决于他的站队,在这部分人中对于技术能力强的,有能力在市场竞争中获取有利地位的会选择润,相对欠缺、甚至缺乏能力的则需要磨练舔的能力,要做到应舔尽舔,舔匀了不至于在上层斗争中被简单牺牲掉。</p></li><li><p>白嫖</p><p>白嫖或者微氪玩家,占据了玩家90%及以上的份额,是最广大玩家群众,他们的利益被重氪和中氪玩家所代表,很不幸我是其中之一,很幸运我意识到这点。</p><p>他们被教育吃苦(搬砖)就可以阶级跃迁,但是他们大多不知道实现跃迁的大多是通过吃人,你不吃人,上面的人也不放心把你放上去,单维度的聪明大多时候只会陷入困顿,即聪明是不够的,还需要坏。</p></li></ul></li></ul><hr><h2 id="2024年7月9日续"><a href="#2024年7月9日续" class="headerlink" title="2024年7月9日续"></a>2024年7月9日续</h2><p>前文已大致阐述了个人的一些看法(关于市场),总的概括来说是倾向于开放。至于所谓通过不同视角对事物所作的分析,是个体情绪、感受的味道多于客观描述,我想过删掉这篇文章,但是最后还是没有删掉,因为我觉得情绪化的表达并不一定完全没有价值,狗屁文章自有它狗屁的作用。</p><h2 id="2024年7月12日"><a href="#2024年7月12日" class="headerlink" title="2024年7月12日"></a>2024年7月12日</h2><p>游戏出“大事”了,国服版本在移植韩服的时候连带着bug也一同带了过来(是真的一点都不改么?就改了个文本 国际化?)。</p><p>游戏的拍卖行系统在玩家上架道具的时候,设备开启离线模式会提示上架失败,然后邮件退回道具,但是本地原先的道具并没有被消耗掉,看了视频我简单猜测下实现:<br>正常情况下,当客户端发起道具上架请求,在服务器收到上架请求后,上架道具,服务器扣除玩家道具,返回客户端上架成功通知,同步客户端道具数量,完成上架;<br>视频的情况是,当客户端发起道具上架请求的瞬间,客户端断网,即上架请求发出被中断回滚退回道具到邮箱,同时因为上架流程未走完所以客户端也不会更新道具数量,而回滚退回道具的步骤显然是在客户端侧处理并不是在服务器端处理(好像也没办法从服务器端处理,因为断网了服务器感知不到请求),从而实现了复制道具的效果。</p>]]></content>
<categories>
<category> 杂文 </category>
</categories>
<tags>
<tag> 手记 </tag>
</tags>
</entry>
<entry>
<title>麒麟操作系统内核,同其他操作系统内核的相似性分析</title>
<link href="/post/fc9a3f71.html"/>
<url>/post/fc9a3f71.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="麒麟操作系统内核,同其他操作系统内核的相似性分析"><a href="#麒麟操作系统内核,同其他操作系统内核的相似性分析" class="headerlink" title="麒麟操作系统内核,同其他操作系统内核的相似性分析"></a>麒麟操作系统内核,同其他操作系统内核的相似性分析</h1><blockquote><p>Copyright (c) 2006 Dancefire (dancefire#gmail).</p><p>Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled “GNU Free Documentation License”.</p></blockquote><p>作者:Dancefire (dancefire # gmail dot com) 2006/04/27</p><h2 id="一、引言"><a href="#一、引言" class="headerlink" title="一、引言"></a>一、引言</h2><p>麒麟操作系统是由国防科技大学、中软公司、联想公司、浪潮公司和民族恒星公司五家单位合作研制的服务器操作系统。按照麒麟官方的说法:</p><p>“Kylin 服务器操作系统是国家 863 计划的重大研究成果,拥有完全自主版权的内核,与 Linux 在应用上二进制兼容,并支持 64 位,是中国独立研发成功的、具有完全自主知识产权的服务器操作系统。”[1]</p><p>“银河麒麟操作系统是针对未来的主流网络服务和高性能计算服务的需求,参照国际主流标准,参考 Darwin、FreeBSD、Linux 和其它商用操作系统,借鉴 UNIX 操作系统和微内核操作系统的设计思想,设计并实现具有自主版权的、可支持多种 CPU 芯片和多种计算机体系结构的、具有高性能、高可用性与高安全性的、并与 Linux 应用和设备驱动二进制兼容的中文服务器操作系统,”</p><p><em>摘自麒麟操作系统 2.0.21 内自带的帮助文档</em></p><p>近日,有不少人对麒麟操作系统宣称的 “完全自主版权” 和“中国独立研发成功”这两个核心问题产生了质疑。随着麒麟 2.0.14 和 2.0.21 系统可以通过麒麟的官方网站下载后(<a href="http://www.kylin.org.cn/download.htm">http://www.kylin.org.cn/download.htm</a> ),这种质疑的声音越来越大。麒麟除内核以外的应用大部分都来自自由组织 GNU 的代码,这些代码并不属于 “中国独立研发”,而且他们的版权也不属于麒麟操作系统的开发者。更有甚者,有人开始通过反汇编麒麟操作系统内核发现和美国的 FreeBSD 开放源代码操作系统非常相似。随后又有人成功的用 FreeBSD 的内核启动了麒麟操作系统。按照麒麟官方的介绍,麒麟具有 Linux 的二进制兼容的能力,可是丝毫没有提及与 FreeBSD 的兼容性,使得麒麟内核与 FreeBSD 的关系变得比较引人注目。在官方介绍中的简简单单的“参考” 是无法解释这种相似程度的。</p><p>“课题组通过评测和分析,认为当时正在研发中的 FreeBSD 5.0 具有比 Unix SVR4.2 更好的发展势头,特别是 SMPng 项目的开展,为 FreeBSD 5.0 支持 SMP 对称多处理器系统奠定了良好的基础,因此银河麒麟操作系统的系统服务层从 SVR4.2 升级到当时正在研发中的 FreeBSD 5.0。”</p><p>声明发出后一定程度上得到了大家谅解,可是虽然提及和 FreeBSD 的关系,却又十分隐晦,既没有明确的对官方网站新闻中的报道失实承认错误,没有明确阐述麒麟的操作系统是否具有 “完全知识产权” 以及是否是“中国独立研发”,甚至也没有对官方页面上的事实报道进行修正。而且,既然说明使用了 FreeBSD 5.0 的代码,却又说仅限于系统服务层,而丝毫未提及所占比例。这依旧让人们对这个获得 863 计划软件重大专项的资助的操作系统到底有多少创新产生一个大大的疑问。</p><p>为了调查清楚麒麟操作系统内核自主创新的百分比,以及与其它操作系统之间的关系,我将麒麟操作系统内核与 FreeBSD、NetBSD、OpenBSD、Linux 和 Solaris 的内核进行了可执行代码的相似度分析。</p><p>在整个过程中,我将尽量保持客观的原则进行分析。由于麒麟操作系统属于封闭源代码系统,因此在无法获得内核源代码的情况下,我将只进行二进制可执行代码文件的相似度分析。由于可执行代码受编译环境、内存分布情况以及模块的变动的影响很大,因此,会产生即使采用同一套代码,却产生很低的相似度情况。但是,对操作系统内核这种大型软件系统来说,却不会因为不同的代码而产生很高的相似度的情况。因此,我们将这次对二进制可执行代码分析所得的相似度作为相似度的下限。<strong>换句话说,真实的相似度应该会高于此次分析结果,但是由于分析方法的局限性,无法取得上限。</strong></p><h2 id="二、可执行文件的相似度比较"><a href="#二、可执行文件的相似度比较" class="headerlink" title="二、可执行文件的相似度比较"></a>二、可执行文件的相似度比较</h2><p>二进制可执行文件的相似度分析一直是一个难题。大家都知道,即使是同一份源代码,使用同一个编译器,可用不同的编译参数进行编译后,代码也会产生极大的差异。</p><p>当发生有人因为盗用别人的源代码而产生的侵权后,如果不能够将二者的源代码拿出进行比较的话,判断是否抄袭非常困难。因此,一直以来或多或少,总会有人无所顾忌的将开放源代码的软件拿来加入到自己的软件中,或者干脆就是在那些源代码的基础上稍加修改和更换了版权信息就宣称是自己研发的。因为他们知道,只要不把自己的源代码公诸于众,那么抄袭就很难判定。</p><p>下面我就详细说一下我采用的分析方法。</p><p>2.1 ELF 可执行文件相似度分析方法</p><p>这次分析起始,我就碰到了一些难题。如果对二进制可执行文件进行基于字节的相似性分析,即使匹配上某些字节,也很难说明两段代码的相似性,另外匹配也很容易受到各种噪音的干扰而产生很低的相似度,可是噪音却无法被去除。</p><p>因此,使最小比较单元具有明确的语义和合理的过滤噪音是我首先要解决的问题。</p><p>2.1.1 反汇编</p><p>二进制文件的比较难以确定最小单元语义的根本问题在于二进制文件是以字节为单位,然而每个字节却没有特定的含义。你很难说 <strong>89</strong> e5 和 83 EC <strong>89</strong> 中的 89 相同说明什么,在这个例子中,前者的 89 e5 是 i386 的一条指令,而后者的 89 则是一个立即数,所以他们相同实际上什么都不说明。</p><p>针对这次分析,由于都是可执行代码,而且都采用了 ELF 的文件格式。由于这个特点,我首先将所有操作系统的内核通过 objdump 反汇编成汇编代码。这样做有一个直接的好处,就是每一行都是一条汇编语句,而每一条汇编语句又是一个程序不可分的最小逻辑单元。这样,接下来的分析就可以基于行来进行相似性的分析,因为每出现一行相同就说明有一个最小的逻辑单元相同,如果出现连续的行相似,那么就说明有连续的代码段相似。相同的行越多两个内核就越相似。</p><p>并且经过反汇编后,就避免了因文件内包含的其他无关信息,如字符串、资源文件、数据文件等,对分析结果产生的影响。</p><p>这个方法依旧无法避免因编译参数差异所造成的相似度下降的影响。虽然如此,但是我很幸运,从这次分析的结果看,依旧得到了不低的相似度。</p><p>2.1.2 过滤噪音</p><p>噪音的出现有很多原因,可能是内存分布不同、代码的增删导致的偏移地址的变化,对相同含义的常量而数值却不同等等。这些值的差异,可能会造成不同的执行结果,但是却对两段代码的相似性比较影响不大。请看下列两个代码段:</p><p>c043e9e8 <freebsd4_sigcode>: | c04431d8 <freebsd4_sigcode>:</freebsd4_sigcode></freebsd4_sigcode></p><p>freebsd4_sigcode(): freebsd4_sigcode():</p><p>c043e9e8: call *<strong>0x10</strong>(%esp) | c04431d8: call *<strong>0x10</strong>(%esp)</p><p>c043e9ec: lea <strong>0x14</strong>(%esp),%eax | c04431dc: lea <strong>0x14</strong>(%esp),%eax</p><p>c043e9f0: push %eax | c04431e0: push %eax</p><p>c043e9f1: testl $0x20000,<strong>0x54</strong>(%eax) | c04431e1: testl $0x20000,<strong>0x54</strong>(%eax)</p><p>c043e9f8: jne <strong>c043e9fd</strong> <freebsd4_sigcode+**0x15**> | c04431e8: jne <strong>c04431ed</strong> <freebsd4_sigcode+**0x15**></p><p>c043e9fa: movl <strong>0x14</strong>(%eax),%gs | c04431ea: movw <strong>0x14</strong>(%eax),%gs</p><p>c043e9fd: mov $0x158,%eax | c04431ed: mov $0x158,%eax</p><p>c043ea02: push %eax | c04431f2: push %eax</p><p>c043ea03: int $0x80 | c04431f3: int $0x80</p><p>c043ea05: jmp <strong>c043ea05</strong> <freebsd4_sigcode+**0x1d**> | c04431f5: jmp <strong>c04431f5</strong> <freebsd4_sigcode+**0x1d**></p><p>c043ea07: nop | c04431f7: nop</p><p>左边的代码是来自 FreeBSD 5.3 内核的,而右边的代码来自麒麟 2.0.21/18 的内核。通过人的分析,我们可以得出这两段代码实际上是相同的。可是对于计算机程序比较的时候,就不尽然。</p><p>请注意上述的有颜色的数字。用蓝色表示的代码地址 [4]、绿色表示的偏移地址、红色表示的立即数、深蓝色表示的函数偏移地址和粉色表示的函数地址,这些数字的不同,就造成了代码比较时候的失败。上述 13 行代码,如果就这样比较的话,只有函数名一行可以匹配。因此虽然是相同的代码,却只有 7.7% 的相似度。下面我们就来去除这些干扰。</p><p>首先,我们将代码行地址、函数跳转地址和函数偏移地址去除。代码行所在的地址,实际上是说明了代码所在内存的位置,内存的位置会随着代码的删改而很容易产生变动,这些对我们比较代码逻辑没有意义。其中有些绝对地址,我们将其替换为 “{Address}”,这样既不受地址变化的影响,又不至影响了代码的含义。</p><p>然后我们将绿色的偏移地址替换成特定字符串 “{Offset}”。产生偏移地址的原因一般有两种,一种是结构体,另一种是数组。即使不对结构体删改,而仅仅是对结构体的声明顺序的变动都可以造成偏移地址的不同,我们在这里只关心程序在这里用到了一个偏移地址,而不关心用的到底是偏移了多少。数组的用法虽然不常出现,但是即使出现其中的位置也是很容易发生变动的。因此在这里,我们也将偏移地址的数值替换成统一的字符串。</p><p>最后,我们来处理红色的立即数。当然立即数并不是只有上述的几种情况下出现,虽然在上述的例子中,两边的立即数都完全一样,单是在某些情况下还是会出现不同。</p><p>立即数在程序中一般是常量,而常量有可能是与系统相关的数值,或者仅仅是一个符号,而不在乎具体数值。无论是什么含义,常量虽然在执行过程中不会改变,在设计过程中却很容易发生变动。不过对我们分析代码逻辑没有太大的影响,因此,在分析的时候我们对数值进行模糊化,将其替换为 “{Number}” 这个特定字符串。</p><p>至此,上述代码将会变为:</p><p><freebsd4_sigcode>: | <freebsd4_sigcode>:</freebsd4_sigcode></freebsd4_sigcode></p><p>freebsd4_sigcode(): | freebsd4_sigcode():</p><p> call *{Offset}(%esp) | call *{Offset}(%esp)</p><p> lea {Offset}(%esp),%eax | lea {Offset}(%esp),%eax</p><p> push %eax | push %eax</p><p> testl {Number},{Offset}(%eax) | testl {Number},{Offset}(%eax)</p><p> jne <freebsd4_sigcode+{Offset}> | jne <freebsd4_sigcode+{Offset}></p><p> movl {Offset}(%eax),%gs | movw {Offset}(%eax),%gs</p><p> mov {Number},%eax | mov {Number},%eax</p><p> push %eax | push %eax</p><p> int {Number} | int {Number}</p><p> jmp <freebsd4_sigcode+{Offset}> | jmp <freebsd4_sigcode+{Offset}></p><p> nop | nop</p><p>现在这两段代码的相似度将变成真实的 100%。</p><p>2.1.3 代码段顺序调整</p><p>经过上面的噪音过滤后,代码已经能够在基本不影响代码逻辑的前提下去除了噪音的影响。可是,还有一种情况会对匹配结果带来较大的影响。就是代码块位置的前后变动,我们来看下面这两段代码的比对。</p><p>begin(): <</p><p> mov {Address},%eax <</p><p> lea {Offset}(%eax),%esp <</p><p> xor %ebp,%ebp <</p><p> mov {Address},%esi <</p><p> mov %esi,{Offset}(%eax) <</p><p> pushl {Address} <</p><p> call <init386> <</init386></p><p> add {Number},%esp <</p><p> call <mi_startup> <</mi_startup></p><p> add {Number},%esp <</p><p>sigcode(): sigcode():</p><p> call *{Offset}(%esp) call *{Offset}(%esp)</p><p> lea {Offset}(%esp),%eax lea {Offset}(%esp),%eax</p><p> push %eax push %eax</p><p> testl {Number},{Offset}(%eax) testl {Number},{Offset}(%eax)</p><p> jne <sigcode+{Offset}> jne <sigcode+{Offset}></p><p> movl {Offset}(%eax),%gs | movw {Offset}(%eax),%gs</p><p> mov {Number},%eax mov {Number},%eax</p><p> push %eax push %eax</p><p> int {Number} int {Number}</p><p> jmp <sigcode+{Offset}> jmp <sigcode+{Offset}></p><p> nop nop</p><p> > begin():</p><p> > mov {Address},%eax</p><p> > lea {Offset}(%eax),%esp</p><p> > xor %ebp,%ebp</p><p> > mov {Address},%esi</p><p> > mov %esi,{Offset}(%eax)</p><p> > pushl {Address}</p><p> > call <init386></init386></p><p> > add {Number},%esp</p><p> > call <mi_startup></mi_startup></p><p> > add {Number},%esp</p><p>和刚才一样。左边来自 FreeBSD 5.3 的代码,右边来自 Kylin 2.0 的代码 (但是为了举例,函数前后顺序稍作调整)。在两段代码实际上非常相似,但是由于代码前后的顺序不同,导致只有一个代码块 sigcode() 可以匹配的上,相似度仅为 47.6%。</p><p>针对这类情况,我的解决办法是将代码块按照标号 / 函数名进行排序。经过排序,上述代码段比对将变为:</p><p>begin(): begin():</p><p> mov {Address},%eax mov {Address},%eax</p><p> lea {Offset}(%eax),%esp lea {Offset}(%eax),%esp</p><p> xor %ebp,%ebp xor %ebp,%ebp</p><p> mov {Address},%esi mov {Address},%esi</p><p> mov %esi,{Offset}(%eax) mov %esi,{Offset}(%eax)</p><p> pushl {Address} pushl {Address}</p><p> call <init386> call <init386></init386></init386></p><p> add {Number},%esp add {Number},%esp</p><p> call <mi_startup> call <mi_startup></mi_startup></mi_startup></p><p> add {Number},%esp add {Number},%esp</p><p>sigcode(): sigcode():</p><p> call *{Offset}(%esp) call *{Offset}(%esp)</p><p> lea {Offset}(%esp),%eax lea {Offset}(%esp),%eax</p><p> push %eax push %eax</p><p> testl {Number},{Offset}(%eax) testl {Number},{Offset}(%eax)</p><p> jne <sigcode+{Offset}> jne <sigcode+{Offset}></p><p> movl {Offset}(%eax),%gs | movw {Offset}(%eax),%gs</p><p> mov {Number},%eax mov {Number},%eax</p><p> push %eax push %eax</p><p> int {Number} int {Number}</p><p> jmp <sigcode+{Offset}> jmp <sigcode+{Offset}></p><p> nop nop</p><p>现在,这两段代码只有一行不同,相似度也就变为了 95.2%。</p><p>但是这种依赖于标号 / 函数名排序的做法有效的程度实际上是有局限的。首先,并不是所有函数名都会保存于可执行代码中,至少 inline 函数就会在编译时扩展到调用的语句位置,还有一些函数在编译器优化时被优化掉。所以,不同的编译器,或者不同的编译参数都有可能导致某些函数名在执行体中消失,从而导致排序失败。另外,不是所有的可执行体都会保留函数名,对于 Windows 的 PE 文件来说,如果不用 debug 模式编译的话,除了导出函数外,其他的函数名一般不会保存在执行文件中,</p><p>在我用同样的方法分析 Windows 文件内核的时候出现了比较严重的问题,即使血亲关系很近的两个版本的 Windows 内核,无论排序或者不排序,相似度都非常的低,对于这类 PE 文件根本无法反映出相似度。所以,在最终的分析中,我剔出了原本列在比较目标中的 XP 内核。</p><p>因为 ELF 的这个特点,这次我的分析将只对使用 ELF 的文件格式的内核进行分析。</p><p>2.1.4 比较</p><p>在原本的计划中,我曾考虑采用常用于字符串相似度比较的编辑距离 (Levenshtein Distance) 算法 [5]。这个算法的含义,是计算两字符串之间的距离有多远。编辑距离是指,从原字符串变化到目的字符串最少需要进行多少次包括添加、修改、删除在内的操作。举例而言:</p><p>如果计算 kitten 和 sitting 之间的编辑距离,我们最少需要进行 3 次操作,</p><p>1、 kitten -> sitten (修改 s->k)</p><p>2、 sitten -> sittin (修改 i->e)</p><p>3、 sittin -> sitting (增加 g)</p><p>因此,kitten 和 sitting 之间的编辑距离是 3。这个算法是俄国的科学家 Vladimir Levenshtein 在 1965 年提出的。这个算法主要是应用在 DNA 分析、拼字检查、语音辨识和抄袭侦测上。[6]</p><p>但是这个算法的计算复杂度太高,是 O(nm) 的复杂度。对于平均大小在 100 万行的操作系统内核源代码来说,就是万亿次级别的比对。对于普通的计算机,平均每两个内核的比对就要花去数小时。而此次参与比对的内核将有 20 个左右,完成一个比较完整的比对过程将会出现几百次比对,那么就要花数个月的时间,不太现实。</p><p>因此,这次我采用的是简化的比对办法。通过 diff 命令来比较两个内核源文件的差异。Diff 使用的是一种更聪明的计算方法,虽然最坏情况差不太多,但是大多数情况下具有较高的性能 [7]。</p><p>通过 diff 给出的结果可以得知第一个文件增改多少行代码后,就可以变为第二个文件。diff 的算法和其实对于修改我们并不介意,我们只关心增加多少行代码就可以变为第二个文件。</p><p>假设内核 A 的代码有 a 行,内核 B 的代码有 b 行。而从内核 A 变化到内核 B 需要添加 c 行,由内核 B 变化到内核 A 需要 d 行。由此,我们可以得知,在内核 A 中,存在有 b-c 行代码和内核 B 是相同的。因此,我们将内核 A 中所存在的内核 B 的代码行数除以内核 A 自身的代码行数定义为两个内核的相似度,即</p><p>由公式可知,A->B 和 B->A 的计算结果将有可能不同。因为我们判断相似度的原因不单纯是看二者的差异,更重要的是看他们之间的血亲关系的远近,因此我们取双向转换中的最大值,作为 A<->B 之间的相似度。</p><p>A-B 间的相似度 = max((b-c) / a, (a-d) / b )</p><p>2.1.5 小结</p><p>分析方法还有待完善,可以看出,二进制可执行文件的分析依旧还有很大的难度,很容易受到各种外围环境的变化而导致相似度大幅下降,而无法反映真实的相似度。因此对于那些刻意隐瞒相关性的二进制可执行文件来说还是比较容易的逃过这种分析方法的检测。</p><p>但是,分析方法的缺陷却只会导致相似度的下降,而不会导致差异很大的代码产生很高的相似度。因此,我这次采用这次分析方法主要就是确定麒麟操作系统内核与其他操作系统之间的相似度的下限,并从数据中试图分析出他们的血亲关系。</p><p>2.2 多种操作系统内核相似度比较</p><p>为了比对尽量客观,这次参加比对的操作系统内核包括,FreeBSD, NetBSD, OpenBSD, Linux, Solaris 和银河麒麟操作系统,共 6 个操作系统,22 个内核。</p><p>原计划中,要将 Mac OS X 中的 Darwin 8.0.1, 7.0.1 拿来比对,可是由于其文件格式是 Mach-O 的,而我又没有支持 Mach-O 的 objdump,所以暂时无法参与比对。另外,原计划曾打算拿相关性更差的 Windows NT 系列的系统内核来进行比对,可是由于之前所说的 PE 格式问题而导致的相似度没有参考价值,所以,这次也没有将其列入最终的比对。</p><p>为了确认比对的有效性,我们将先对 FreeBSD, NetBSD 和 OpenBSD 之间的比对来审视其比对效果。</p><p>2.2.1 FreeBSD 间不同版本内核相似度分析</p><p>FreeBSD 是一种 Unix 衍生操作系统,由 BSD, 386BSD 和 4.4BSD 发展而来的 Unix 的一个重要分支。而 BSD 的全称是 “伯克利软件发布”,是美国加州大学伯克利分校计算机系统研究组所制作的一套包括内核在内完整的操作系统,起源于 AT&T 的 Unix V6,但是后来由于与 AT&T 的版权纠纷问题,彻底的删除了 AT&T 在 BSD 内核中的代码,大约占 10% 左右。也正是这场官司,而给了 Linux 得以飞速发展的机遇。在版权问题解决后,BSD 借助其高质量的代码,在开放源代码的世界里有了飞速的发展,分别产生了 3 个重要的分支,FreeBSD, OpenBSD, NetBSD。FreeBSD 发展至今,已经成为公认的相当可靠和健壮的操作系统。[9,10]</p><p>因为焦点集中在 FreeBSD 身上,而且特别是 5.x 和 6.x 的系统上,因此这回参与比较的 FreeBSD 的内核版本较多,分别有 FreeBSD 5.0, 5.1, 5.2, 5.2.1, 5.3, 5.4, 5.5 beta 4 和 6.0。</p><table><tbody><tr><td nowrap="nowrap"><p><strong>原始内核 \ 目标内核</strong></p></td><td nowrap="nowrap"><p><strong>汇编行数</strong></p></td><td nowrap="nowrap"><p><strong>freebsd_5.0</strong></p></td><td nowrap="nowrap"><p><strong>freebsd_5.1</strong></p></td><td nowrap="nowrap"><p><strong>freebsd_5.2</strong></p></td><td nowrap="nowrap"><p><strong>freebsd_5.2.1</strong></p></td><td nowrap="nowrap"><p><strong>freebsd_5.3</strong></p></td><td nowrap="nowrap"><p><strong>freebsd_5.4</strong></p></td><td nowrap="nowrap"><p><strong>freebsd_5.5.b4</strong></p></td><td nowrap="nowrap"><p><strong>freebsd_6.0</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.0</strong></p></td><td nowrap="nowrap"><p><strong>913,353</strong></p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>697423</strong></p></td><td nowrap="nowrap"><p><strong>712361</strong></p></td><td nowrap="nowrap"><p>714811</p></td><td nowrap="nowrap"><p><strong>969174</strong></p></td><td nowrap="nowrap"><p><strong>1001579</strong></p></td><td nowrap="nowrap"><p><strong>1016967</strong></p></td><td nowrap="nowrap"><p><strong>1146371</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.1</strong></p></td><td nowrap="nowrap"><p><strong>958,699</strong></p></td><td nowrap="nowrap"><p>652223</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>682433</strong></p></td><td nowrap="nowrap"><p><strong>681769</strong></p></td><td nowrap="nowrap"><p>1029692</p></td><td nowrap="nowrap"><p><strong>1002484</strong></p></td><td nowrap="nowrap"><p><strong>1034263</strong></p></td><td nowrap="nowrap"><p><strong>1112613</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.2</strong></p></td><td nowrap="nowrap"><p><strong>1,048,418</strong></p></td><td nowrap="nowrap"><p>572280</p></td><td nowrap="nowrap"><p>604662</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>3252</strong></p></td><td nowrap="nowrap"><p><strong>817759</strong></p></td><td nowrap="nowrap"><p><strong>865407</strong></p></td><td nowrap="nowrap"><p><strong>850969</strong></p></td><td nowrap="nowrap"><p><strong>1124929</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.2.1</strong></p></td><td nowrap="nowrap"><p><strong>1,049,592</strong></p></td><td nowrap="nowrap"><p><strong>493098</strong></p></td><td nowrap="nowrap"><p>607199</p></td><td nowrap="nowrap"><p>2078</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>816434</strong></p></td><td nowrap="nowrap"><p><strong>870479</strong></p></td><td nowrap="nowrap"><p><strong>881654</strong></p></td><td nowrap="nowrap"><p><strong>1124304</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.3</strong></p></td><td nowrap="nowrap"><p><strong>1,161,593</strong></p></td><td nowrap="nowrap"><p>742327</p></td><td nowrap="nowrap"><p><strong>762747</strong></p></td><td nowrap="nowrap"><p>705826</p></td><td nowrap="nowrap"><p>724190</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>35581</strong></p></td><td nowrap="nowrap"><p><strong>78219</strong></p></td><td nowrap="nowrap"><p>977778</p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.4</strong></p></td><td nowrap="nowrap"><p><strong>1,174,287</strong></p></td><td nowrap="nowrap"><p>744511</p></td><td nowrap="nowrap"><p>811979</p></td><td nowrap="nowrap"><p>732332</p></td><td nowrap="nowrap"><p>733290</p></td><td nowrap="nowrap"><p>22906</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>25985</strong></p></td><td nowrap="nowrap"><p>901307</p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.5.b4</strong></p></td><td nowrap="nowrap"><p><strong>1,187,447</strong></p></td><td nowrap="nowrap"><p>741616</p></td><td nowrap="nowrap"><p>783626</p></td><td nowrap="nowrap"><p>735617</p></td><td nowrap="nowrap"><p>734211</p></td><td nowrap="nowrap"><p>40295</p></td><td nowrap="nowrap"><p>12975</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>358820</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_6.0</strong></p></td><td nowrap="nowrap"><p><strong>1,271,723</strong></p></td><td nowrap="nowrap"><p>791490</p></td><td nowrap="nowrap"><p>805184</p></td><td nowrap="nowrap"><p>905427</p></td><td nowrap="nowrap"><p>907359</p></td><td nowrap="nowrap"><p><strong>753022</strong></p></td><td nowrap="nowrap"><p><strong>766311</strong></p></td><td nowrap="nowrap"><p>622653</p></td><td nowrap="nowrap"><p>–</p></td></tr></tbody></table><p>上表中所列出的是 FreeBSD 的各个版本之间的差异行数,即前面所说到的 c。左边列出的是原始内核,顶端列出的是目的内核。左边给出了原始内核的行数。</p><p>差异行数和相似度具有相同的含义,毕竟相似度也是通过差异行数计算出来的,因此在以后的叙述中,我们将只列出相似度对比的表格。</p><p>下面就是 FreeBSD 各个版本之间的内核相似度比较。</p><table><tbody><tr><td nowrap="nowrap"><p><strong>原始内核</strong><strong> \</strong><strong> 目的内核</strong></p></td><td nowrap="nowrap"><p><strong>汇编行数</strong></p></td><td nowrap="nowrap"><p><strong>freebsd_5.0</strong></p></td><td nowrap="nowrap"><p><strong>freebsd_5.1</strong></p></td><td nowrap="nowrap"><p><strong>freebsd_5.2</strong></p></td><td nowrap="nowrap"><p><strong>freebsd_5.2.1</strong></p></td><td nowrap="nowrap"><p><strong>freebsd_5.3</strong></p></td><td nowrap="nowrap"><p><strong>freebsd_5.4</strong></p></td><td nowrap="nowrap"><p><strong>freebsd_5.5.b4</strong></p></td><td nowrap="nowrap"><p><strong>freebsd_6.0</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.0</strong></p></td><td nowrap="nowrap"><p><strong>913,353</strong></p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>28.61%</strong></p></td><td nowrap="nowrap"><p><strong>36.79%</strong></p></td><td nowrap="nowrap"><p>36.65%</p></td><td nowrap="nowrap"><p><strong>21.07%</strong></p></td><td nowrap="nowrap"><p><strong>18.91%</strong></p></td><td nowrap="nowrap"><p><strong>18.67%</strong></p></td><td nowrap="nowrap"><p><strong>13.72%</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.1</strong></p></td><td nowrap="nowrap"><p><strong>958,699</strong></p></td><td nowrap="nowrap"><p>27.24%</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>38.18%</strong></p></td><td nowrap="nowrap"><p><strong>38.37%</strong></p></td><td nowrap="nowrap"><p>13.76%</p></td><td nowrap="nowrap"><p><strong>17.92%</strong></p></td><td nowrap="nowrap"><p><strong>15.98%</strong></p></td><td nowrap="nowrap"><p><strong>16.60%</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.2</strong></p></td><td nowrap="nowrap"><p><strong>1,048,418</strong></p></td><td nowrap="nowrap"><p>32.53%</p></td><td nowrap="nowrap"><p>33.77%</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>99.80%</strong></p></td><td nowrap="nowrap"><p><strong>32.80%</strong></p></td><td nowrap="nowrap"><p><strong>29.46%</strong></p></td><td nowrap="nowrap"><p><strong>32.09%</strong></p></td><td nowrap="nowrap"><p><strong>14.00%</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.2.1</strong></p></td><td nowrap="nowrap"><p><strong>1,049,592</strong></p></td><td nowrap="nowrap"><p><strong>40.04%</strong></p></td><td nowrap="nowrap"><p>33.49%</p></td><td nowrap="nowrap"><p>99.69%</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>32.89%</strong></p></td><td nowrap="nowrap"><p><strong>28.95%</strong></p></td><td nowrap="nowrap"><p><strong>29.13%</strong></p></td><td nowrap="nowrap"><p><strong>14.05%</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.3</strong></p></td><td nowrap="nowrap"><p><strong>1,161,593</strong></p></td><td nowrap="nowrap"><p>14.72%</p></td><td nowrap="nowrap"><p><strong>16.87%</strong></p></td><td nowrap="nowrap"><p>29.49%</p></td><td nowrap="nowrap"><p>28.01%</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>98.03%</strong></p></td><td nowrap="nowrap"><p><strong>95.49%</strong></p></td><td nowrap="nowrap"><p>25.31%</p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.4</strong></p></td><td nowrap="nowrap"><p><strong>1,174,287</strong></p></td><td nowrap="nowrap"><p>14.38%</p></td><td nowrap="nowrap"><p>12.49%</p></td><td nowrap="nowrap"><p>26.92%</p></td><td nowrap="nowrap"><p>26.94%</p></td><td nowrap="nowrap"><p>96.97%</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>98.91%</strong></p></td><td nowrap="nowrap"><p>31.54%</p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.5.b4</strong></p></td><td nowrap="nowrap"><p><strong>1,187,447</strong></p></td><td nowrap="nowrap"><p>14.46%</p></td><td nowrap="nowrap"><p>14.74%</p></td><td nowrap="nowrap"><p>26.34%</p></td><td nowrap="nowrap"><p>26.56%</p></td><td nowrap="nowrap"><p>94.43%</p></td><td nowrap="nowrap"><p>97.80%</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>76.88%</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_6.0</strong></p></td><td nowrap="nowrap"><p><strong>1,271,723</strong></p></td><td nowrap="nowrap"><p>9.58%</p></td><td nowrap="nowrap"><p>12.07%</p></td><td nowrap="nowrap"><p>11.24%</p></td><td nowrap="nowrap"><p>11.18%</p></td><td nowrap="nowrap"><p><strong>32.13%</strong></p></td><td nowrap="nowrap"><p><strong>32.08%</strong></p></td><td nowrap="nowrap"><p>44.41%</p></td><td nowrap="nowrap"><p>–</p></td></tr></tbody></table><p>由于操作系统是逐步发展而来的,因此从 5.0-5.5 beta 4 都是在前者的基础上,修补前者中出现的 bug,并增添新的特性而产生的。我们可以从这个 FreeBSD 的相似度表中看到这种传承关系。我们可以看出,基本上是越靠近当前版本相似度越高,而离当前版本越远相似度就越低。其中有一些特例的情况,5.1 和 5.2 似乎比较特殊,可能是由于某种原因在 5.1 中策略有所调整,而在 5.2.1 或者 5.3 中又逐渐的恢复回来。</p><p>5.2.1 和 5.2 的相似度达到了 99.80%,这是正常的,由于在 5.2 之后,有一系列关键服务,如 wu-ftp, OpenSSH 和 XFree86 等的缓冲区溢出的漏洞被揭露出来,致使 FreeBSD 出于安全考虑而在 5.2 发布后仅一个月多的时间就立即发布了新的版本,因此 5.2.1 和 5.2 的内核上的差异实际上很低,主要是在外围程序上修补了很多安全漏洞 [15]。但是出乎我意料的,我没想到在很容易被干扰而降低相似度的情况下,竟然可以达到这么高的相似度,说明这种分析方法对于代码相似度分析在一般情况下是有效的。究其原因,应该是因为 FreeBSD 的前后传承关系,所以不同的版本虽然代码有不少变动,但是默认的内核配置文件变动不大,因此才有可能出现这种比较高的相似度。另外我们也可以看出,FreeBSD 在 5.3 以后,包括 5.4 和 5.5 的内核变动量都不大,由此可以感觉到 5.x 的系统可能已经基本成熟。</p><p>FreeBSD 6.0 与 5.3 以前版本的相似度都不太高,主要是因为 6.0 已经是和 5.x 属于不同的代码分支,相对于 5.x 来说代码有了较大的变化。而另一方面,6.0 的分支是在 5.4 版本发布后建立的,因此,6.0 的内核与之前内核的相似度偏低,却和 FreeBSD 5.3, 5.4, 5.5 beta 4 的相似度较高。</p><p>总体上,基本符合版本相近,代码相近的客观事实,分析方法是成功的。</p><p>2.2.2 FreeBSD、NetBSD 和 OpenBSD 的内核相似度分析</p><p>NetBSD 和 FreeBSD 一样,也是从美国加州伯克利大学的 4.3BSD 和 386BSD 衍生出来的 Unix 操作系统。它以设计简洁、代码规范和高可移植性的特点而著称。从服务器到嵌入式设备都有它的身影 [10]。而 OpenBSD 则是从 NetBSD 1.0 衍生而来的 [11]。因此 OpenBSD 和 NetBSD 相对 FreeBSD 而言具有更近的血亲关系。</p><table><tbody><tr><td nowrap="nowrap"><p><strong>原始内核</strong><strong> \</strong><strong> 目标内核</strong></p></td><td nowrap="nowrap"><p><strong>汇编行数</strong></p></td><td nowrap="nowrap"><p><strong>freebsd_5.3</strong></p></td><td nowrap="nowrap"><p><strong>freebsd_6.0</strong></p></td><td nowrap="nowrap"><p><strong>netbsd_2.1</strong></p></td><td nowrap="nowrap"><p><strong>netbsd_3.0</strong></p></td><td nowrap="nowrap"><p><strong>openbsd_3.7</strong></p></td><td nowrap="nowrap"><p><strong>openbsd_3.8</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.3</strong></p></td><td nowrap="nowrap"><p><strong>1,161,593</strong></p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p>25.31%</p></td><td nowrap="nowrap"><p><strong>16.55%</strong></p></td><td nowrap="nowrap"><p><strong>16.61%</strong></p></td><td nowrap="nowrap"><p><strong>16.78%</strong></p></td><td nowrap="nowrap"><p><strong>16.74%</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_6.0</strong></p></td><td nowrap="nowrap"><p><strong>1,271,723</strong></p></td><td nowrap="nowrap"><p><strong>32.13%</strong></p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>16.65%</strong></p></td><td nowrap="nowrap"><p><strong>16.22%</strong></p></td><td nowrap="nowrap"><p>15.89%</p></td><td nowrap="nowrap"><p>16.24%</p></td></tr><tr><td nowrap="nowrap"><p><strong>netbsd_2.1</strong></p></td><td nowrap="nowrap"><p><strong>1,503,585</strong></p></td><td nowrap="nowrap"><p>13.08%</p></td><td nowrap="nowrap"><p>13.68%</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>53.35%</strong></p></td><td nowrap="nowrap"><p>17.53%</p></td><td nowrap="nowrap"><p>16.72%</p></td></tr><tr><td nowrap="nowrap"><p><strong>netbsd_3.0</strong></p></td><td nowrap="nowrap"><p><strong>1,616,659</strong></p></td><td nowrap="nowrap"><p>11.76%</p></td><td nowrap="nowrap"><p>12.65%</p></td><td nowrap="nowrap"><p>24.40%</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p>13.96%</p></td><td nowrap="nowrap"><p>14.61%</p></td></tr><tr><td nowrap="nowrap"><p><strong>openbsd_3.7</strong></p></td><td nowrap="nowrap"><p><strong>1,228,137</strong></p></td><td nowrap="nowrap"><p>15.60%</p></td><td nowrap="nowrap"><p><strong>16.54%</strong></p></td><td nowrap="nowrap"><p><strong>20.77%</strong></p></td><td nowrap="nowrap"><p><strong>18.44%</strong></p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>88.89%</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>openbsd_3.8</strong></p></td><td nowrap="nowrap"><p><strong>1,260,707</strong></p></td><td nowrap="nowrap"><p>15.26%</p></td><td nowrap="nowrap"><p><strong>16.52%</strong></p></td><td nowrap="nowrap"><p><strong>20.65%</strong></p></td><td nowrap="nowrap"><p><strong>18.47%</strong></p></td><td nowrap="nowrap"><p>84.56%</p></td><td nowrap="nowrap"><p>–</p></td></tr></tbody></table><p>从这个数据表中,我们可以看出计算出来的数据可以反映这种已知的血亲关系。FreeBSD 与 NetBSD 和 OpenBSD 的相似度基本在 16.5% 左右,而 NetBSD 与 OpenBSD 的相似度则相对较高。NetBSD 2.1 和 OpenBSD 的相似度为 20.65% ~ 20.77%,NetBSD 3.0 和 OpenBSD 的相似度也有 18.44%,都高于 FreeBSD 与 NetBSD 和 OpenBSD 的相似度。虽然数值差别并不大,但是具有规律性,基本上也是客观地反映了真实的情况的。</p><p>2.2.3 Kylin 与 FreeBSD, OpenBSD, NetBSD, Linux, Solaris 的内核相似度分析</p><p>现在我们开始对银河麒麟操作系统进行相似度比对。参与比对的开放源代码操作系统内核有 FreeBSD 5.0, FreeBSD 5.2, FreeBSD 6.0, NetBSD 2.1, NetBSD 3.0, OpenBSD 3.7, OpenBSD 3.8, Linux 2.6.16, OpenSolaris 5.11,共 9 个内核。</p><p>除了刚才介绍过的 FreeBSD, NetBSD 和 OpenBSD 外,还增加了 Linux 和 Solaris。Linux 是 Linus 基本上从零起步写出来的操作系统,虽然参考了 Minix 和 Unix 的实现,但是基本上没有大量的使用任何其它 Unix 发布的代码 [12]。因此,虽然 Linux 也是一个类 Unix 系统,然而由于是独立开发的,所以它和前面所列出的 BSD 衍生操作系统和后面将要提到的 Solaris 的血亲关系比较远。</p><p>从历史的角度来讲,Solaris 和 BSD 很有渊源。在 80 年代,Sun 基于 BSD Unix 发布了自己版本的 UNIX,SunOS。而在 90 年代初,由于受到 AT&T 与 BSD 的官司影响,Sun 将其 SunOS 4 替换为与 AT&T 共同开发的 UNIX System V Release 4 的一个版本,并更名为 Solaris 2[13]。在 2004 年早期,Sun 开始了一项计划,名为 OpenSolaris,将 Solaris 逐步的放到开放源代码社区中。并在 2005 年的 6 月中旬开放了大部分的 Solaris 源代码 [14]。现在已经有一些基于 OpenSolaris 源代码的操作系统,这次采用的就是一个名为 Belenix 的 Live CD 发布版本 0.4.2 种的内核,uname 显示的是 SunOS 5.11。</p><p>此次引入 Solaris 来进行比对,也是从一方面希望能够从分析数据中客观地反映出 Solaris,相比 Linux 而言,和 BSD 有更近的血亲关系。</p><p>关于参与比对的麒麟操作系统内核,我们将从发布版本中获得的四个版本的内核拿来进行比对,Kylin 2.0.0, Kylin 2.0.14, Kylin 2.0.21, Kylin 2.0.21 lsb。需要说明的是,官方网站上发布了 2.0.14 和 2.0.18。其中 Kylin 2.0.0 是来自于麒麟系统安装盘的引导部分,通过 uname –a 显示出的版本是 2.0.0。Kylin 2.0.21 虽然是官方网站给出的光盘镜像的版本号,可是启动后,通过 uname –a 得到的版本号却是 2.0.18,这点可能是麒麟开发组在版本管理上的混乱所导致的。</p><p>下面就是分析后得到的数据表;</p><table><tbody><tr><td nowrap="nowrap"><p><strong>原始内核</strong><strong> \</strong><strong> 目标内核</strong></p></td><td nowrap="nowrap"><p><strong>汇编行数</strong></p></td><td nowrap="nowrap"><p><strong>fb 5.0</strong></p></td><td nowrap="nowrap"><p><strong>fb 5.2</strong></p></td><td nowrap="nowrap"><p><strong>fb 6.0</strong></p></td><td nowrap="nowrap"><p><strong>k 2-0</strong></p></td><td nowrap="nowrap"><p><strong>k 2-14</strong></p></td><td nowrap="nowrap"><p><strong>k 2-21</strong></p></td><td nowrap="nowrap"><p><strong>k 2-21 lsb</strong></p></td><td nowrap="nowrap"><p><strong>l 2.6.16</strong></p></td><td nowrap="nowrap"><p><strong>nb 2.1</strong></p></td><td nowrap="nowrap"><p><strong>nb 3.0</strong></p></td><td nowrap="nowrap"><p><strong>ob 3.7</strong></p></td><td nowrap="nowrap"><p><strong>ob 3.8</strong></p></td><td nowrap="nowrap"><p><strong>os 5.11</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.0</strong></p></td><td nowrap="nowrap"><p><strong>913,353</strong></p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>36.79%</strong></p></td><td nowrap="nowrap"><p><strong>13.72%</strong></p></td><td nowrap="nowrap"><p><strong>40.53%</strong></p></td><td nowrap="nowrap"><p><strong>30.43%</strong></p></td><td nowrap="nowrap"><p><strong>30.43%</strong></p></td><td nowrap="nowrap"><p><strong>40.53%</strong></p></td><td nowrap="nowrap"><p>6.46%</p></td><td nowrap="nowrap"><p><strong>11.24%</strong></p></td><td nowrap="nowrap"><p><strong>11.37%</strong></p></td><td nowrap="nowrap"><p><strong>10.91%</strong></p></td><td nowrap="nowrap"><p><strong>10.87%</strong></p></td><td nowrap="nowrap"><p>5.02%</p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.2</strong></p></td><td nowrap="nowrap"><p><strong>1,048,418</strong></p></td><td nowrap="nowrap"><p>32.53%</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>14.00%</strong></p></td><td nowrap="nowrap"><p><strong>48.18%</strong></p></td><td nowrap="nowrap"><p><strong>34.02%</strong></p></td><td nowrap="nowrap"><p><strong>34.02%</strong></p></td><td nowrap="nowrap"><p><strong>48.18%</strong></p></td><td nowrap="nowrap"><p>5.75%</p></td><td nowrap="nowrap"><p><strong>11.02%</strong></p></td><td nowrap="nowrap"><p><strong>10.91%</strong></p></td><td nowrap="nowrap"><p><strong>10.95%</strong></p></td><td nowrap="nowrap"><p><strong>10.94%</strong></p></td><td nowrap="nowrap"><p>4.55%</p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_6.0</strong></p></td><td nowrap="nowrap"><p><strong>1,271,723</strong></p></td><td nowrap="nowrap"><p>9.58%</p></td><td nowrap="nowrap"><p>11.24%</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p>12.63%</p></td><td nowrap="nowrap"><p>13.19%</p></td><td nowrap="nowrap"><p>13.14%</p></td><td nowrap="nowrap"><p>12.63%</p></td><td nowrap="nowrap"><p>6.61%</p></td><td nowrap="nowrap"><p><strong>16.65%</strong></p></td><td nowrap="nowrap"><p><strong>16.22%</strong></p></td><td nowrap="nowrap"><p>15.89%</p></td><td nowrap="nowrap"><p>16.24%</p></td><td nowrap="nowrap"><p>5.21%</p></td></tr><tr><td nowrap="nowrap"><p><strong>kylin_2.0.0</strong></p></td><td nowrap="nowrap"><p><strong>1,120,079</strong></p></td><td nowrap="nowrap"><p>31.92%</p></td><td nowrap="nowrap"><p>41.94%</p></td><td nowrap="nowrap"><p><strong>14.55%</strong></p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>91.06%</strong></p></td><td nowrap="nowrap"><p><strong>91.06%</strong></p></td><td nowrap="nowrap"><p><strong>100.00%</strong></p></td><td nowrap="nowrap"><p><strong>5.38%</strong></p></td><td nowrap="nowrap"><p><strong>10.83%</strong></p></td><td nowrap="nowrap"><p><strong>10.31%</strong></p></td><td nowrap="nowrap"><p><strong>10.20%</strong></p></td><td nowrap="nowrap"><p><strong>10.35%</strong></p></td><td nowrap="nowrap"><p>4.35%</p></td></tr><tr><td nowrap="nowrap"><p><strong>kylin_2.0.14</strong></p></td><td nowrap="nowrap"><p><strong>1,190,443</strong></p></td><td nowrap="nowrap"><p>23.55%</p></td><td nowrap="nowrap"><p>29.98%</p></td><td nowrap="nowrap"><p><strong>24.61%</strong></p></td><td nowrap="nowrap"><p>85.60%</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>100.00%</strong></p></td><td nowrap="nowrap"><p>85.60%</p></td><td nowrap="nowrap"><p>5.04%</p></td><td nowrap="nowrap"><p><strong>10.63%</strong></p></td><td nowrap="nowrap"><p><strong>10.64%</strong></p></td><td nowrap="nowrap"><p><strong>10.30%</strong></p></td><td nowrap="nowrap"><p><strong>10.44%</strong></p></td><td nowrap="nowrap"><p>4.06%</p></td></tr><tr><td nowrap="nowrap"><p><strong>kylin_2.0.21</strong></p></td><td nowrap="nowrap"><p><strong>1,190,562</strong></p></td><td nowrap="nowrap"><p>23.52%</p></td><td nowrap="nowrap"><p>29.95%</p></td><td nowrap="nowrap"><p><strong>21.04%</strong></p></td><td nowrap="nowrap"><p>85.57%</p></td><td nowrap="nowrap"><p>99.99%</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p>85.57%</p></td><td nowrap="nowrap"><p>5.03%</p></td><td nowrap="nowrap"><p><strong>10.72%</strong></p></td><td nowrap="nowrap"><p><strong>10.63%</strong></p></td><td nowrap="nowrap"><p><strong>10.29%</strong></p></td><td nowrap="nowrap"><p><strong>10.44%</strong></p></td><td nowrap="nowrap"><p>4.06%</p></td></tr><tr><td nowrap="nowrap"><p><strong>kylin_2.0.21_lsb</strong></p></td><td nowrap="nowrap"><p><strong>1,120,079</strong></p></td><td nowrap="nowrap"><p>31.92%</p></td><td nowrap="nowrap"><p>41.94%</p></td><td nowrap="nowrap"><p><strong>14.55%</strong></p></td><td nowrap="nowrap"><p>100.00%</p></td><td nowrap="nowrap"><p><strong>91.06%</strong></p></td><td nowrap="nowrap"><p><strong>91.06%</strong></p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>5.38%</strong></p></td><td nowrap="nowrap"><p><strong>10.83%</strong></p></td><td nowrap="nowrap"><p><strong>10.31%</strong></p></td><td nowrap="nowrap"><p><strong>10.20%</strong></p></td><td nowrap="nowrap"><p><strong>10.35%</strong></p></td><td nowrap="nowrap"><p>4.35%</p></td></tr><tr><td nowrap="nowrap"><p><strong>linux_2.6.16</strong></p></td><td nowrap="nowrap"><p><strong>666,204</strong></p></td><td nowrap="nowrap"><p><strong>9.47%</strong></p></td><td nowrap="nowrap"><p><strong>9.71%</strong></p></td><td nowrap="nowrap"><p><strong>13.13%</strong></p></td><td nowrap="nowrap"><p>5.38%</p></td><td nowrap="nowrap"><p><strong>5.38%</strong></p></td><td nowrap="nowrap"><p><strong>5.39%</strong></p></td><td nowrap="nowrap"><p>5.38%</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>11.89%</strong></p></td><td nowrap="nowrap"><p><strong>12.09%</strong></p></td><td nowrap="nowrap"><p><strong>12.21%</strong></p></td><td nowrap="nowrap"><p><strong>12.07%</strong></p></td><td nowrap="nowrap"><p>6.30%</p></td></tr><tr><td nowrap="nowrap"><p><strong>netbsd_2.1</strong></p></td><td nowrap="nowrap"><p><strong>1,503,585</strong></p></td><td nowrap="nowrap"><p>6.49%</p></td><td nowrap="nowrap"><p>7.42%</p></td><td nowrap="nowrap"><p>13.68%</p></td><td nowrap="nowrap"><p>8.06%</p></td><td nowrap="nowrap"><p>8.18%</p></td><td nowrap="nowrap"><p>7.97%</p></td><td nowrap="nowrap"><p>8.06%</p></td><td nowrap="nowrap"><p>5.20%</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>53.35%</strong></p></td><td nowrap="nowrap"><p>17.53%</p></td><td nowrap="nowrap"><p>16.72%</p></td><td nowrap="nowrap"><p>4.10%</p></td></tr><tr><td nowrap="nowrap"><p><strong>netbsd_3.0</strong></p></td><td nowrap="nowrap"><p><strong>1,616,659</strong></p></td><td nowrap="nowrap"><p>6.19%</p></td><td nowrap="nowrap"><p>7.11%</p></td><td nowrap="nowrap"><p>12.65%</p></td><td nowrap="nowrap"><p>7.54%</p></td><td nowrap="nowrap"><p>7.90%</p></td><td nowrap="nowrap"><p>7.89%</p></td><td nowrap="nowrap"><p>7.54%</p></td><td nowrap="nowrap"><p>4.98%</p></td><td nowrap="nowrap"><p>24.40%</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p>13.96%</p></td><td nowrap="nowrap"><p>14.61%</p></td><td nowrap="nowrap"><p>3.73%</p></td></tr><tr><td nowrap="nowrap"><p><strong>openbsd_3.7</strong></p></td><td nowrap="nowrap"><p><strong>1,228,137</strong></p></td><td nowrap="nowrap"><p>7.95%</p></td><td nowrap="nowrap"><p>9.58%</p></td><td nowrap="nowrap"><p><strong>16.54%</strong></p></td><td nowrap="nowrap"><p>9.27%</p></td><td nowrap="nowrap"><p>9.97%</p></td><td nowrap="nowrap"><p>9.71%</p></td><td nowrap="nowrap"><p>9.27%</p></td><td nowrap="nowrap"><p>6.43%</p></td><td nowrap="nowrap"><p><strong>20.77%</strong></p></td><td nowrap="nowrap"><p><strong>18.44%</strong></p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>88.89%</strong></p></td><td nowrap="nowrap"><p>5.20%</p></td></tr><tr><td nowrap="nowrap"><p><strong>openbsd_3.8</strong></p></td><td nowrap="nowrap"><p><strong>1,260,707</strong></p></td><td nowrap="nowrap"><p>7.72%</p></td><td nowrap="nowrap"><p>8.84%</p></td><td nowrap="nowrap"><p><strong>16.52%</strong></p></td><td nowrap="nowrap"><p>8.88%</p></td><td nowrap="nowrap"><p>9.53%</p></td><td nowrap="nowrap"><p>9.52%</p></td><td nowrap="nowrap"><p>8.88%</p></td><td nowrap="nowrap"><p>6.29%</p></td><td nowrap="nowrap"><p><strong>20.65%</strong></p></td><td nowrap="nowrap"><p><strong>18.47%</strong></p></td><td nowrap="nowrap"><p>84.56%</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p>5.00%</p></td></tr><tr><td nowrap="nowrap"><p><strong>OpenSolaris_5.11</strong></p></td><td nowrap="nowrap"><p><strong>396,534</strong></p></td><td nowrap="nowrap"><p>11.87%</p></td><td nowrap="nowrap"><p><strong>12.00%</strong></p></td><td nowrap="nowrap"><p><strong>16.84%</strong></p></td><td nowrap="nowrap"><p><strong>12.50%</strong></p></td><td nowrap="nowrap"><p><strong>12.46%</strong></p></td><td nowrap="nowrap"><p><strong>12.46%</strong></p></td><td nowrap="nowrap"><p><strong>12.50%</strong></p></td><td nowrap="nowrap"><p><strong>13.37%</strong></p></td><td nowrap="nowrap"><p><strong>15.90%</strong></p></td><td nowrap="nowrap"><p><strong>15.82%</strong></p></td><td nowrap="nowrap"><p><strong>16.66%</strong></p></td><td nowrap="nowrap"><p><strong>16.49%</strong></p></td><td nowrap="nowrap"><p>–</p></td></tr></tbody></table><p>从数据表中反映出来的血亲关系来看,Kylin 2.0 的内核和 FreeBSD 5.x 的血亲关系最近,在 30.43%-48.18% 之间,和 FreeBSD 6.0 的关系稍远,在 14.55%-24.61% 之间。而和其他的操作系统关系都比较疏远。和 NetBSD、OpenBSD 的相似度在 10% 左右,而同 Linux 的相似度只有 5.38%,</p><p>与 OpenSolaris 的相似度虽然比 NetBSD 和 OpenBSD 还高,达到了 12.50%,但是这个绝对数值不应该视为 OpenSolaris 与麒麟的关系更接近。因为,OpenSolaris 的代码行数仅有 396,534 行,仅相当于 NetBSD 的 1/4。在相似度计算公式中,分母较小,容易致使结果的相似度较大,因此不应该说麒麟内核和 Solaris 更相似,应该说麒麟内核同 Solaris,NetBSD 和 OpenBSD 的相似度相当。</p><p>另外,我们可以注意到 OpenSolaris 和 FreeBSD 6, NetBSD, OpenBSD 的相似度略高于其他系统内核,但是都比较低。我们从这个不大的差异中可以感觉到 Solaris 同 BSD 的或近或远的关系。其实虽然 Solaris 代码已经不是基于 BSD 构建的 Unix 了,但是由于 SVR4 中也吸收了 BSD 的部分代码,因此 Solaris 在相似度上,还是客观的体现了和 BSD 偏近的关系。</p><p>从数据中我们还可以看到麒麟的这几个内核的相似度很高。Kylin 2.0.0 和 Kylin 2.0.21 lsb 的相似度是 100%,Kylin 2.0.14 和 2.0.21 的相似度也是接近 100.00%。其中的具体差异行数如下:</p><table><tbody><tr><td nowrap="nowrap"><p><strong>原始内核</strong><strong> \</strong><strong> 目标内核</strong></p></td><td nowrap="nowrap"><p><strong>汇编行数</strong></p></td><td nowrap="nowrap"><p><strong>kylin_2.0.0</strong></p></td><td nowrap="nowrap"><p><strong>kylin_2.0.14</strong></p></td><td nowrap="nowrap"><p><strong>kylin_2.0.21</strong></p></td><td nowrap="nowrap"><p><strong>kylin_2.0.21_lsb</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>kylin_2.0.0</strong></p></td><td nowrap="nowrap"><p><strong>1,120,079</strong></p></td><td nowrap="nowrap"><p><strong> –</strong></p></td><td nowrap="nowrap"><p><strong>170,553</strong></p></td><td nowrap="nowrap"><p><strong>170,641</strong></p></td><td nowrap="nowrap"><p><strong>0</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>kylin_2.0.14</strong></p></td><td nowrap="nowrap"><p><strong>1,190,443</strong></p></td><td nowrap="nowrap"><p><strong>101,029</strong></p></td><td nowrap="nowrap"><p><strong> –</strong></p></td><td nowrap="nowrap"><p><strong>145</strong></p></td><td nowrap="nowrap"><p><strong>101,029</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>kylin_2.0.21</strong></p></td><td nowrap="nowrap"><p><strong>1,190,562</strong></p></td><td nowrap="nowrap"><p><strong>101,328</strong></p></td><td nowrap="nowrap"><p><strong>26</strong></p></td><td nowrap="nowrap"><p><strong> –</strong></p></td><td nowrap="nowrap"><p><strong>101,328</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>kylin_2.0.21_lsb</strong></p></td><td nowrap="nowrap"><p><strong>1,120,079</strong></p></td><td nowrap="nowrap"><p><strong>0</strong></p></td><td nowrap="nowrap"><p><strong>170,553</strong></p></td><td nowrap="nowrap"><p><strong>170,641</strong></p></td><td nowrap="nowrap"><p><strong> –</strong></p></td></tr></tbody></table><p>我们可以看出其实光盘引导用的内核同安装后的 / boot/kernel_lsb/ 目录下的内核是相同的。而 Kylin 2.0.21 和 2.0.14 相比仅仅修改了几十行代码而已,变动很小,从数值上看,变动主要是增加了一些代码。而从 2.0.0 到 2.0.14 变动稍大一些。</p><p>在后面的分析中,我们没必要对很相似的内核一起进行重复分析,因此,将基于 Kylin 2.0.0 和 Kylin 2.0.21 这两个麒麟内核进行分析。</p><p>从现在的结果我们已经可以看出麒麟和 FreeBSD 的 5.x 版本有很近的血亲关系,最高达到了与 FreeBSD 5.2 的 48.18% 的相似度,这种相似性甚至已经明显超过了和 FreeBSD 具有很近的同源关系的 NetBSD, OpenBSD。即使是最初基于 NetBSD 的代码而建立的 OpenBSD,在与其渊源极深的 NetBSD 比较时,最高也不过 20.77% 的相似度。</p><p>至此,我们基本上可以确定麒麟操作系统内核中有大量的 FreeBSD 5.x 的源代码。为了进一步确定麒麟操作系统和 FreeBSD 的相似性到底有多少,我们接下来将针对 Kylin 内核和 FreeBSD 的内核作比较。</p><p>2.2.4 Kylin 与 FreeBSD 各个版本间的内核相似度分析</p><p>这次我们针对 Kylin 和 FreeBSD 这两个操作系统的内核进行相似度的比对。参与比对的将包括 Kylin 的 2 个典型内核和 FreeBSD 5.x 全系列内核,具体是 Kylin 2.0.0, Kylin 2.0.21, FreeBSD 5.0, FreeBSD 5.1, FreeBSD 5.2, FreeBSD 5.2.1, FreeBSD 5.3, FreeBSD 5.4, FreeBSD 5.5 beta4。</p><table><tbody><tr><td nowrap="nowrap"><p><strong>原始内核</strong><strong> \</strong><strong> 目标内核</strong></p></td><td nowrap="nowrap"><p><strong>汇编行数</strong></p></td><td nowrap="nowrap"><p><strong>fb 5.0</strong></p></td><td nowrap="nowrap"><p><strong>fb 5.1</strong></p></td><td nowrap="nowrap"><p><strong>fb 5.2</strong></p></td><td nowrap="nowrap"><p><strong>fb 5.2.1</strong></p></td><td nowrap="nowrap"><p><strong>fb 5.3</strong></p></td><td nowrap="nowrap"><p><strong>fb 5.4</strong></p></td><td nowrap="nowrap"><p><strong>fb 5.5.b4</strong></p></td><td nowrap="nowrap"><p><strong>kylin_2.0.0</strong></p></td><td nowrap="nowrap"><p><strong>kylin_2.0.21</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.0</strong></p></td><td nowrap="nowrap"><p><strong>913,353</strong></p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>28.61%</strong></p></td><td nowrap="nowrap"><p><strong>36.79%</strong></p></td><td nowrap="nowrap"><p>36.65%</p></td><td nowrap="nowrap"><p><strong>21.07%</strong></p></td><td nowrap="nowrap"><p><strong>18.91%</strong></p></td><td nowrap="nowrap"><p><strong>18.67%</strong></p></td><td nowrap="nowrap"><p><strong>40.53%</strong></p></td><td nowrap="nowrap"><p><strong>30.43%</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.1</strong></p></td><td nowrap="nowrap"><p><strong>958,699</strong></p></td><td nowrap="nowrap"><p>27.24%</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>38.18%</strong></p></td><td nowrap="nowrap"><p><strong>38.37%</strong></p></td><td nowrap="nowrap"><p>13.76%</p></td><td nowrap="nowrap"><p><strong>17.92%</strong></p></td><td nowrap="nowrap"><p><strong>15.98%</strong></p></td><td nowrap="nowrap"><p><strong>28.94%</strong></p></td><td nowrap="nowrap"><p><strong>26.11%</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.2</strong></p></td><td nowrap="nowrap"><p><strong>1,048,418</strong></p></td><td nowrap="nowrap"><p>32.53%</p></td><td nowrap="nowrap"><p>33.77%</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>99.80%</strong></p></td><td nowrap="nowrap"><p><strong>32.80%</strong></p></td><td nowrap="nowrap"><p><strong>29.46%</strong></p></td><td nowrap="nowrap"><p><strong>32.09%</strong></p></td><td nowrap="nowrap"><p><strong>48.18%</strong></p></td><td nowrap="nowrap"><p><strong>34.02%</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.2.1</strong></p></td><td nowrap="nowrap"><p><strong>1,049,592</strong></p></td><td nowrap="nowrap"><p><strong>40.04%</strong></p></td><td nowrap="nowrap"><p>33.49%</p></td><td nowrap="nowrap"><p>99.69%</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>32.89%</strong></p></td><td nowrap="nowrap"><p><strong>28.95%</strong></p></td><td nowrap="nowrap"><p><strong>29.13%</strong></p></td><td nowrap="nowrap"><p><strong>48.15%</strong></p></td><td nowrap="nowrap"><p><strong>34.47%</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.3</strong></p></td><td nowrap="nowrap"><p><strong>1,161,593</strong></p></td><td nowrap="nowrap"><p>14.72%</p></td><td nowrap="nowrap"><p><strong>16.87%</strong></p></td><td nowrap="nowrap"><p>29.49%</p></td><td nowrap="nowrap"><p>28.01%</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>98.03%</strong></p></td><td nowrap="nowrap"><p><strong>95.49%</strong></p></td><td nowrap="nowrap"><p>57.94%</p></td><td nowrap="nowrap"><p>50.48%</p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.4</strong></p></td><td nowrap="nowrap"><p><strong>1,174,287</strong></p></td><td nowrap="nowrap"><p>14.38%</p></td><td nowrap="nowrap"><p>12.49%</p></td><td nowrap="nowrap"><p>26.92%</p></td><td nowrap="nowrap"><p>26.94%</p></td><td nowrap="nowrap"><p>96.97%</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>98.91%</strong></p></td><td nowrap="nowrap"><p>56.24%</p></td><td nowrap="nowrap"><p><strong>51.88%</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.5.b4</strong></p></td><td nowrap="nowrap"><p><strong>1,187,447</strong></p></td><td nowrap="nowrap"><p>14.46%</p></td><td nowrap="nowrap"><p>14.74%</p></td><td nowrap="nowrap"><p>26.34%</p></td><td nowrap="nowrap"><p>26.56%</p></td><td nowrap="nowrap"><p>94.43%</p></td><td nowrap="nowrap"><p>97.80%</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p>39.47%</p></td><td nowrap="nowrap"><p>50.16%</p></td></tr><tr><td nowrap="nowrap"><p><strong>kylin_2.0.0</strong></p></td><td nowrap="nowrap"><p><strong>1,120,079</strong></p></td><td nowrap="nowrap"><p>31.92%</p></td><td nowrap="nowrap"><p>20.99%</p></td><td nowrap="nowrap"><p>41.94%</p></td><td nowrap="nowrap"><p>41.97%</p></td><td nowrap="nowrap"><p><strong>60.26%</strong></p></td><td nowrap="nowrap"><p><strong>59.04%</strong></p></td><td nowrap="nowrap"><p><strong>42.59%</strong></p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>91.06%</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>kylin_2.0.21</strong></p></td><td nowrap="nowrap"><p><strong>1,190,562</strong></p></td><td nowrap="nowrap"><p>23.52%</p></td><td nowrap="nowrap"><p>16.68%</p></td><td nowrap="nowrap"><p>29.95%</p></td><td nowrap="nowrap"><p>29.93%</p></td><td nowrap="nowrap"><p><strong>52.04%</strong></p></td><td nowrap="nowrap"><p>50.87%</p></td><td nowrap="nowrap"><p><strong>50.35%</strong></p></td><td nowrap="nowrap"><p>85.57%</p></td><td nowrap="nowrap"><p>–</p></td></tr></tbody></table><p>Kylin 2.0.0 和 FreeBSD 5.3 的相似度达到了 60.26%,与 FreeBSD 也达到了 59.04% 的相似度。我们可以注意到,即使是 FreeBSD 的 5.0 – 5.3 版本之间的相似度也没有超过 40.04%。5.3、5.4 和 5.5 的高相似度前面已经解释了,应该是 5.x 系列的内核趋于稳定了,因此修补较多增添新的特性较少所致。</p><p>按照麒麟开发人员的解释,麒麟操作系统内核服务层使用的是 FreeBSD 5.0 的代码。可是,从我们的分析数据可以明显看出,Kylin 2.0.0 和 FreeBSD 5.0 的相似度有 40.53%,而与 FreeBSD 5.3 的相似度达到了 60.26%,因此我们有理由相信麒麟使用的是 FreeBSD 5.3 或者 5.4 的代码。</p><p>当然,我们可以理解为这是开发人员的声明 [3] 中的一个笔误,他想说 FreeBSD 5.x,而不是 FreeBSD 5.0。但是,另一方面,如果说仅仅是外围服务层使用的是 FreeBSD 的话,那么麒麟与 FreeBSD 5.3 的相似度不应该高过 FreeBSD 自家不同版本之间的相似度。既然麒麟 2.0.0 内核与 FreeBSD 5.3 达到了 60.26% 的相似度,那么我们可以肯定地说,麒麟操作系统内核源代码至少有一半以上使用的是 FreeBSD 5.3 的源代码。</p><p>2.2.5 Kylin 与 FreeBSD 5.3, 5.4 不同编译配置下的内核相似度分析</p><p>为了能够进一步了解麒麟操作系统内核同 FreeBSD 内核的相似度,接下来,我们将对 FreeBSD 5.3 和 5.4 在不变动任何源代码的情况下,重新进行编译,增加一些在 Kylin 2.0 中出现的模块。这样做的是希望在不修改 FreeBSD 代码的前提下,看看不同的编译配置是否能够使得 FreeBSD 与麒麟操作系统内核的相似度更高。</p><p>这次,我们在 FreeBSD 的内核编译配置文件 GENERIC 中增加如下三个选项:</p><p>options COMPAT_LINUX</p><p>options LINPROCFS</p><p>device sound</p><p>因为麒麟内核的一个亮点就是可以做到和 Linux 的二进制兼容,所以这主要是增加 FreeBSD 的 Linux 兼容性。其实事实上 FreeBSD 已经可以很好的兼容 Linux 二进制代码了,按照 FreeBSD 的内核设计,它完全可以同时支持多种 ABI(应用程序二进制接口),并支持同时运行不同系统可执行文件。通过加载 COMPAT_LINUX 模块,FreeBSD 就已经做到了和 Linux 可执行文件间的二进制兼容,可以执行大部分 Linux 程序 [17]。</p><p>而 LINPROCFS 模块则是模拟了 Linux 的进程文件系统,也就是我们在 Linux 下见到的 / proc 目录,很多 Linux 的程序需要用到这个系统,因此加载这个模块后,可以让 Linux 更好的在 FreeBSD 上运行 [18]。</p><p>最后增加了 sound 设备,因为我们通过分析,发现 Kylin 内核里面加载了各种声卡驱动。需要提及的是,麒麟系统启动比较慢,有可能也是因为编译了过多的不必要的模块进内核所导致的。</p><table><tbody><tr><td nowrap="nowrap"><p><strong>原始内核</strong><strong> \</strong><strong> 目标内核</strong></p></td><td nowrap="nowrap"><p><strong>汇编行数</strong></p></td><td nowrap="nowrap"><p><strong>freebsd_5.3</strong></p></td><td nowrap="nowrap"><p><strong>freebsd_5.3_1</strong></p></td><td nowrap="nowrap"><p><strong>freebsd_5.4</strong></p></td><td nowrap="nowrap"><p><strong>freebsd_5.4_1</strong></p></td><td nowrap="nowrap"><p><strong>kylin_2.0.0</strong></p></td><td nowrap="nowrap"><p><strong>kylin_2.0.21</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.3</strong></p></td><td nowrap="nowrap"><p><strong>1,161,593</strong></p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>97.47%</strong></p></td><td nowrap="nowrap"><p><strong>98.03%</strong></p></td><td nowrap="nowrap"><p>73.12%</p></td><td nowrap="nowrap"><p>57.94%</p></td><td nowrap="nowrap"><p>50.48%</p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.3_1</strong></p></td><td nowrap="nowrap"><p><strong>1,198,401</strong></p></td><td nowrap="nowrap"><p>93.78%</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p>80.82%</p></td><td nowrap="nowrap"><p><strong>98.07%</strong></p></td><td nowrap="nowrap"><p>56.49%</p></td><td nowrap="nowrap"><p>56.64%</p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.4</strong></p></td><td nowrap="nowrap"><p><strong>1,174,287</strong></p></td><td nowrap="nowrap"><p>96.97%</p></td><td nowrap="nowrap"><p><strong>94.55%</strong></p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>96.58%</strong></p></td><td nowrap="nowrap"><p>56.24%</p></td><td nowrap="nowrap"><p><strong>51.88%</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.4_1</strong></p></td><td nowrap="nowrap"><p><strong>1,210,928</strong></p></td><td nowrap="nowrap"><p><strong>91.68%</strong></p></td><td nowrap="nowrap"><p>97.05%</p></td><td nowrap="nowrap"><p>94.56%</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p>55.66%</p></td><td nowrap="nowrap"><p><strong>55.29%</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>kylin_2.0.0</strong></p></td><td nowrap="nowrap"><p><strong>1,120,079</strong></p></td><td nowrap="nowrap"><p><strong>60.26%</strong></p></td><td nowrap="nowrap"><p><strong>61.19%</strong></p></td><td nowrap="nowrap"><p><strong>59.04%</strong></p></td><td nowrap="nowrap"><p><strong>60.17%</strong></p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>91.06%</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>kylin_2.0.21</strong></p></td><td nowrap="nowrap"><p><strong>1,190,562</strong></p></td><td nowrap="nowrap"><p><strong>52.04%</strong></p></td><td nowrap="nowrap"><p><strong>57.02%</strong></p></td><td nowrap="nowrap"><p>50.87%</p></td><td nowrap="nowrap"><p>54.38%</p></td><td nowrap="nowrap"><p>85.57%</p></td><td nowrap="nowrap"><p>–</p></td></tr></tbody></table><p>通过比对,我们可以看到,随着增加了 Linux 兼容性和声卡驱动模块后,Kylin 2.0 与 FreeBSD 的 5.3、5.4 的相似度均有小幅提高。其中 Kylin 2.0.0 内核和 FreeBSD 5.3 的相似度为 61.19%。我们有理由相信,随着更多合适的内核模块的加入,Kylin 2.0 和 FreeBSD 的内核相似度有可能会进一步提高。</p><p>实际上,经过内核模块的比对,我们也发现了 Kylin 内核中出现了很多疑似是 FreeBSD 的其他模块,但是由于每次编译和比对要花费大量的时间,因此,我没有能够一一的加以测试。如果有兴趣的朋友可以进一步测试麒麟系统内核与不同的内核配置文件之间的相似度。</p><p>2.2.6 同一份 FreeBSD 5.3 代码,不同编译配置下的内核相似度分析</p><p>接下来,我们将在不修改任何 FreeBSD 5.3 内核源代码的前提下,尝试用不同的内核编译配置文件对 FreeBSD 5.3 内核进行编译。希望能够通过这样的尝试看出,同一份源代码,在不同配置文件下能够产生最低多低的相似度,换句话说,就是使相似度下降多少百分比。</p><p>在测试中,由于编译和比对的时间太慢,所以,我只用 3 个不同的内核配置文件编译内核,这相对于可能出现的内核数量是一个很小的比例。因此,我不能够得出最低使相似度下降的百分比,但是我能够得出至少可以使相似度下降多少百分比。换句话说,我能够测试出一个相似度可能被降低的范围,但是实际能够降低的范围比这个还要大。</p><table><tbody><tr><td nowrap="nowrap"><p><strong>原始内核</strong><strong> \</strong><strong> 目标内核</strong></p></td><td nowrap="nowrap"><p><strong>汇编行数</strong></p></td><td nowrap="nowrap"><p><strong>freebsd_5.3</strong></p></td><td nowrap="nowrap"><p><strong>freebsd_5.3_1</strong></p></td><td nowrap="nowrap"><p><strong>freebsd_5.3_2</strong></p></td><td nowrap="nowrap"><p><strong>freebsd_5.3_3</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.3</strong></p></td><td nowrap="nowrap"><p><strong>1,161,593</strong></p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>97.47%</strong></p></td><td nowrap="nowrap"><p><strong>72.01%</strong></p></td><td nowrap="nowrap"><p><strong>71.62%</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.3_1</strong></p></td><td nowrap="nowrap"><p><strong>1,198,401</strong></p></td><td nowrap="nowrap"><p>93.78%</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>96.95%</strong></p></td><td nowrap="nowrap"><p><strong>94.32%</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.3_2</strong></p></td><td nowrap="nowrap"><p><strong>1,256,264</strong></p></td><td nowrap="nowrap"><p>66.54%</p></td><td nowrap="nowrap"><p>45.25%</p></td><td nowrap="nowrap"><p>–</p></td><td nowrap="nowrap"><p><strong>98.11%</strong></p></td></tr><tr><td nowrap="nowrap"><p><strong>freebsd_5.3_3</strong></p></td><td nowrap="nowrap"><p><strong>1,271,301</strong></p></td><td nowrap="nowrap"><p>67.10%</p></td><td nowrap="nowrap"><p>89.43%</p></td><td nowrap="nowrap"><p>96.95%</p></td><td nowrap="nowrap"><p>–</p></td></tr></tbody></table><p>我只是很少的修改了几个内核编译选项,我尽量使生成的内核大小不要差异太大。最后选定了 3 个比较合适的内核配置文件,它们与 FreeBSD 5.3 默认配置的内核差异从 71.62% 到 97.47%。我们可以看到仅仅将内核配置文件稍加改动,就可以使同一份源代码编译出来的内核文件降低将近 30% 的相似度。可以预知的趋势是,随着改动的增大,将能够降低更多的相似度。</p><p>既然在不变动源代码的情况下,就可以将相似度降低到 70% 左右,那么仅仅是服务层采用 FreeBSD 5.3 代码的麒麟系统内核本应该有相当低的相似度,但是分析数据却得到了 61.19% 高相似度,因此麒麟操作系统内核的自主代码的比例确实是一个比较值得关注的问题。</p><p>2.3 结论</p><p>经过这次分析,我们比较了麒麟操作系统内核同 FreeBSD, NetBSD, OpenBSD, Linux 和 Solaris 内核的相似度。在发现麒麟内核与 FreeBSD 5.x 有 30.43%-48.18% 的相似度后,将麒麟内核与 FreeBSD 5.x 各个版本进行了比对。通过比对看到麒麟系统与 FreeBSD 5.3 默认内核达到了 60.26% 的相似度,在经过微小调整内核配置文件后,相似度又得到了进一步的提高,达到了 61.19%。在继续调整内核配置文件之后,这个相似度还有进一步提升的空间。</p><p>随后,我们在不修改 FreeBSD 5.3 源代码的情况下,仅仅通过配置文件的变动,就使内核相似度降低到了 71.62%,而且还有可能降的更低。</p><p>经过分析,我们可以看出麒麟操作系统与 FreeBSD 5.3 具有血亲关系,而且麒麟系统相对于 FreeBSD 5.3 的改动,还没有 FreeBSD 5.3 相对于 FreeBSD 5.2.1 改动大。从 61.19% 的相似度,我们可以认定,麒麟操作系统中至少有 60% 的代码是来自于 FreeBSD 5.3 的源代码。</p><p>由于简单的修改配置文件就可以使相同代码相似度降低到 71.62%,而我们最终所得到的 61.19% 又是仅仅是麒麟内核同 FreeBSD 5.3 内核相似度的最小值,因此,实际的麒麟操作系统与 FreeBSD 5.3 在源代码上的相似度很有可能会达到甚至超过 90%。</p><p>我们可以推测 (但不确定) 麒麟操作系统内核可能是通过以下几个步骤产生的。</p><p>首先是在 FreeBSD 5.3 内核源代码的基础上进行了部分的修改,可能是为了增强与 LSB 的兼容性。</p><p>然后,开发了 Keta 内核模块,来实现 Kernel-based 静态页面 web 加速器。</p><p>最后,以 FreeBSD 的默认内核配置文件 GENERIC 为基础,编译了更多的可选模块进内核。这么做的目的可能是为了让内核更具有通用性。</p><p>如果确实如此,那么生成的麒麟操作系统内核与其说是一个新的操作系统内核,不如说是被麒麟开发者打了内核补丁的 FreeBSD 5.3 更为恰当。</p><h2 id="三、尾声"><a href="#三、尾声" class="headerlink" title="三、尾声"></a>三、尾声</h2><p>我们很难推测麒麟在内核创新的百分比,从已知的数据我们只能说,创新可能只有 10% 到 20% 之间。</p><p>首先,麒麟的官方说明中提到 “主要是由具有 Mach 风格的基本内核层、具有 BSD 风格的系统服务层和具有 Windows 界面风格的桌面环境组成,前两层在核态运行。” 采用 Mach 微内核层 + FreeBSD 内核服务层的做法是其一个亮点。微内核构架加上一个成熟操作系统的服务层,是目前比较流行的一个做法,Mac OS X 就是这样。在对 Mac OS X 的 xnu 内核源代码分析过程中,就可以看到其中的两层内核结构,很清晰。不过在我们反汇编麒麟操作系统内核的分析过程中,竟然连一个与 Mach 相关的内核函数都没有看到,许多关键的模块也基本上和 FreeBSD 相同而看不到 Mach 的身影,因此我们对于麒麟操作系统内核是否真如官方说明所宣称的那样,“具有 Mach 风格的基本内核层”,还是抱有很大疑问的。</p><p>其次,从其对外宣称的一些麒麟的特性上看,绝大多数都是 FreeBSD 已经成熟的特性。比如,对 Linux 达到二进制兼容,事实上,FreeBSD 很早以前就已经做到了和 Linux 二进制兼容了,麒麟直接采用了 FreeBSD 的内核源代码,也自然而然的支持了这个特性,无非是在于 LSB 兼容上进一步的做了一些工作。麒麟系统的所宣称的安全性应该也是继承于 FreeBSD 长期积累下来的健壮和稳定性上。</p><p>至于内核级的 Web 服务器 Keta,确实是来自国防科技大学的原创,可以从 <a href="http://openketa.sourceforge.net/">http://openketa.sourceforge.net/</a> 取得源代码。不过恰恰是这个内核级的 Web 服务器 Keta,降低了麒麟所宣称的安全性,而且也暴露了国防科技大学在安全性上认知的不足。</p><p>内核级代码确实可以大幅提高性能,Linux 在 2.4 的时候也曾经采用一个叫做 TUX 的内核级的 Web 加速器来进行静态页面的加速处理。不过这个一直是争论的焦点,相当多的安全人士不推荐 Linux 这样设计,因为内核级代码虽然较快,但是,一旦发生溢出等安全攻击,那么攻击者就可以直接将自己的代码注入内核空间执行,具有系统最高权限,而不受约束。这将给系统安全性带来极大的隐患。另外,内核级的 Web 加速器也有其自身弱点,由于功能受限,而不能够用动态页面,只能够支持静态页面,所有的动态页面只有转交给另一个真实的 Web 服务器,比如 Apache Web Server,才能够处理。所以对于动态页面,内核的 Web 加速器并没有什么明显效果。随着 Linux 2.6 的 NPTL 引入,用户模式下的多任务性能得到了大幅提高,TUX 就很快被移出标准内核了。而 FreeBSD 的多任务模型和 Linux 很不同,特别是在 FreeBSD 5.x 后多任务模型有很大的改进,FreeBSD 的用户模式的多任务性能并不是很差,为了这个不大的性能提高,而严重的降低系统安全性,实在是一个不明智的举动。在这种情况下,还宣称自己是高安全性,显得很不伦不类。</p><p>而且,从编译进麒麟内核的模块看,我们可以感到很多桌面系统的模块被加到了默认内核中,但是对外却宣称是服务器操作系统。我们都知道,安全的原则是最小化服务原则。多一个服务,多一个驱动,就多引入了一份不稳定和不安全。可是麒麟内核却加载了很多类似于屏幕保护模块、声卡模块、显卡图形驱动模块、ACPI 电源管理的内核模块,这些模块对于一个服务器来说,并不是必须的,而且其中很多代码会给系统带来很大的安全隐患。这绝不单单是引导速度变慢的问题,麒麟宣称自己是服务器操作系统,但是在这点的选择上也是很不明智的。</p><p>最后需要提及的是,麒麟所安装的软件大部分是 GNU 的开放源代码软件,这些软件遵循 GPL。它要求如果对任何代码进行了修改,必须开放修改过的源代码。但不幸的是,麒麟操作系统虽然修改了部分的代码,却没有开放出修改后的源代码。从这种意义上说,麒麟操作系统对这些 GNU 的开源软件有侵权嫌疑。</p><h2 id="附录-A-进一步分析"><a href="#附录-A-进一步分析" class="headerlink" title="附录 A 进一步分析"></a>附录 A 进一步分析</h2><p>如果想进一步的分析麒麟与其他操作系统的相似性,也可以从 objdump 导出的函数名称的相似度来比较。我曾经分析过 FreeBSD 5.3 内核和麒麟内核 objdump 出的函数名的差异。FreeBSD 5.3 有 14101 个函数,Kylin 2.0 有 14399 个函数,其中有 4 个函数出现在了 FreeBSD 5.3 而没有出现在 Kylin 2.0 中;有 302 个函数出现在了 Kylin 2.0 objdump 的文件里,而没有出现在 FreeBSD 5.3 的 objdump 文件里。经过分析,这 302 个函数中有 223 都可以在 FreeBSD 5.3 的源代码里找到,没有被 objdump 出来有可能是因为编译环境不同。还剩下 79 个函数可能是麒麟新增的函数,他们是:</p><p>如果单从函数名比对的统计上看的话,14399 个函数,只有 79 个函数可能是原创的。与 FreeBSD 5.3 在函数名上的相似度有 99.45%。这个相似程度十分惊人,但是仅凭函数名相似不足以说明逻辑上相似,因此,在分析报告中,这个分析数据只作为参考数据放到附录中。感兴趣的朋友可以进一步的分析。</p>]]></content>
<categories>
<category> 摘记 </category>
</categories>
<tags>
<tag> 麒麟操作系统 </tag>
</tags>
</entry>
<entry>
<title>BlackGoat</title>
<link href="/post/b2acf578.html"/>
<url>/post/b2acf578.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="卡尔维诺的黑羊"><a href="#卡尔维诺的黑羊" class="headerlink" title="卡尔维诺的黑羊"></a>卡尔维诺的黑羊</h1><p>从前有个国家,里面人人是贼。一到傍晚,他们手持万能钥匙和遮光灯笼出门,走到邻居家里行窃。破晓时分,他们提着偷来的东西回到家里,总能发现自己家也失窃了。</p><p> 他们就这样幸福地居住在一起。没有不幸的人,因为每个人都从别人那里偷东西,别人又再从别人那里偷,依次下去,直到最后一个人去第一个窃贼家行窃。该国贸易也就不可避免地是买方和卖方的双向欺骗。政府是个向臣民行窃的犯罪机构,而臣民也仅对欺骗政府感兴趣。所以日子倒也平稳,没有富人和穷人</p><p> 有一天——到底是怎么回事没人知道——总之是有个诚实人到了该地定居。到晚上,他没有携袋提灯地出门,却呆在家里抽烟读小说。贼来了,见灯亮着,就没进去。</p><p> 这样持续了有一段时间。后来他们感到必要向他挑明一下,纵使他想什么都不做地过日子,可他没理由妨碍别人做事。他天天晚上呆在家里,这就意味着有一户人家第二天没了口粮。诚实人感到他无力反抗这样的逻辑。从此他也像他们一样,晚上出门,次日早晨回家,但他不行窃。他是诚实的。对此,你是无能为力的。他走到远处的桥上,看河水打桥下流过。每次回家,他都会发现家里失窃了。</p><p> 不到一星期,诚实人就发现自己已经一文不名了;他家徒四壁,没任何东西可吃。但 这不能算不了什么,因为那是他自己的错;不,问题是他的行为使其他人很不安。因为他让别人偷走了他的一切却不从别人那儿偷任何东西;这样总有人在黎明回家时,发现家里没被动过–那本该是由诚实人进去行窃的。不久以后,那些没有被偷过的人家发现他们比人家就富了,就不想再行窃了。更糟的是,那些跑到诚实人家里去行窃的人,总发现里面空空如也,因此他们就变穷了。</p><p> 同时,富起来的那些人和诚实人一样,养成了晚上去桥上的习惯,他们也看河水打桥下流过。这样,事态就更混乱了,因为这意味着更多的人在变富,也有更多的人在变穷。</p><p> 现在,那些富人发现,如果他们天天去桥上,他们很快也会变穷的。他们就想:“我们雇那些穷的去替我们行窃吧。”他们签下合同,敲定了工资和如何分成。自然,他们依然是贼,依然互相欺骗。但形势表明,富人是越来越富,穷人是越来越穷。</p><p> 有些人富裕得已经根本无须亲自行窃或雇人行窃就可保持富有。但一旦他们停止行窃的话,他们就会变穷,因为穷人会偷他们。因此他们又雇了穷人中的最穷者来帮助他们看守财富,以免遭穷人行窃,这就意味着要建立警察局和监狱。</p><p> 因此,在那诚实人出现后没几年,人们就不再谈什么偷盗或被偷盗了,而只说穷人和富人;但他们个个都还是贼。</p><p> 唯一诚实的只有开头的那个人,但他不久便死了,饿死的。</p><p> 诚实人的死表达了人们的绝望:我们的社会,经常是劣币驱逐良币,浑浊污染纯净。正如黑格尔所说,一种恶假如很小却很普及,这种恶就会根深蒂固,很难被清除。在人人都认同的“恶境”下,清白的人反而没有立足之地,会成为公众的敌人。</p><p> 现代社会的形成过程,不也正是这样?文明的进程从来都是以牺牲那些不应该牺牲的人的生命和利益为代价的,从某种意义上说,这些牺牲是公众共谋的结果。独善其身的人会被荒诞的社会吞噬,在不正常的社会里,正常的反而不正常,不正常的反而正常。任何不正常都带有潜规则,谁要是触犯了这些规则,就要会受到惩罚。,自私、占有、不劳而获是人的本能。社会规则能约束这种本能,也能激发这种本能。</p>]]></content>
<categories>
<category> 杂文 </category>
</categories>
<tags>
<tag> 摘记 </tag>
</tags>
</entry>
<entry>
<title>Mysql-replication</title>
<link href="/post/cfd35582.html"/>
<url>/post/cfd35582.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="数据库集群"><a href="#数据库集群" class="headerlink" title="数据库集群"></a><a href="https://www.cnblogs.com/ricklz/p/17335755.html">数据库集群</a></h1><h2 id="MySQL-Replication"><a href="#MySQL-Replication" class="headerlink" title="MySQL Replication"></a><a href="https://www.cnblogs.com/ricklz/p/17335755.html">MySQL Replication</a></h2><p><code>MySQL Replication</code> 是官方提供的主从同步方案,用于将一个 MySQL 的实例同步到另一个实例中。Replication 为保证数据安全做了重要的保证,是目前运用最广的 MySQL 容灾方案。Replication 用两个或以上的实例搭建了 MySQL 主从复制集群,提供单点写入,多点读取的服务,实现了读的 扩展。</p><p><img src="https://oss.luhuhu.cn/202406051032506.png" alt="一主多从读写分离"></p><blockquote><p>一个主库(M),三个从库(S),通过 replication,Master 生成 event 的 binlog,然后发给 slave,Slave 将 event 写入 relaylog,然后将其提交到自身数据库中,实现主从数据同步。</p><p>对于数据库之上的业务层来说,基于 MySQL 的主从复制集群,单点写入 Master ,在 event 同步到 Slave 后,读逻辑可以从任何一个 Slave 读取数据,以读写分离的方式,大大降低 Master 的运行负载,同时提升了 Slave 的资源利用。</p><p>优点:</p><ol><li><p>通过读写分离实现横向扩展的能力,写入和更新操作在源服务器上进行,从服务器中进行数据的读取操作,通过增大从服务器的个数,能够极大的增强数据库的读取能力;</p></li><li><p>数据安全,因为副本可以暂停复制过程,所以可以在副本上运行备份服务而不会破坏相应的源数据;</p></li><li><p>便进行数据分析,可以在写库中创建实时数据,数据的分析操作在从库中进行,不会影响到源数据库的性能;</p></li></ol><p>实现原理</p><p>在主从复制中,从库利用主库上的 binlog 进行重播,实现主从同步,复制的过程中主要使用到了 <code>dump thread,I/O thread,sql thread</code> 这三个线程。</p><p><code>IO thread</code>: 在从库执行 <code>start slave</code> 语句时创建,负责连接主库,请求 binlog,接收 binlog 并写入 relay-log;</p><p><code>dump thread</code>:用于主库同步 binlog 给从库,负责响应从 <code>IO thread</code> 的请求。主库会给每个从库的连接创建一个 <code>dump thread</code>,然后同步 binlog 给从库;</p><p><code>sql thread</code>:读取 <code>relay log</code> 执行命令实现从库数据的更新。</p><p>来看下复制的流程:</p><ol><li><p>主库收到更新命令,执行更新操作,生成 binlog;</p></li><li><p>从库在主从之间建立长连接;</p></li><li><p>主库 dump_thread 从本地读取 binlog 传送刚给从库;</p></li><li><p>从库从主库获取到 binlog 后存储到本地,成为 <code>relay log</code>(中继日志);</p></li><li><p>sql_thread 线程读取 <code>relay log</code> 解析、执行命令更新数据。</p></li></ol><p>不过 <code>MySQL Replication</code> 有个严重的缺点就是主从同步延迟。</p><p>因为数据是进行主从同步的,那么就会遇到主从同步延迟的情况。</p><p>为什么会出现主从延迟?</p><ol><li><p>从库机器的性能比主库差;</p></li><li><p>从库的压力大;</p></li></ol><ul><li>大量查询放在从库上,可能会导致从库上耗费了大量的 CPU 资源,进而影响了同步速度,造成主从延迟。</li></ul><ol start="3"><li>大事务的执行;</li></ol><ul><li>有事务产生的时候,主库必须要等待事务完成之后才能写入到 binlog,假定执行的事务是一个非常大的数据插入,这些数据传输到从库,从库同步这些数据也需要一定的时间,就会导致从节点出现数据延迟。</li></ul><ol start="4"><li>从库的复制能力较差;</li></ol><p>如果从库的复制能力,低于主库,那么在主库写入压力很大的情况下,就会造成从库长时间数据延迟的情况出现。</p><p>如何解决?</p><ol><li><p>优化业务逻辑,避免出现多线程大事务的并发场景;</p></li><li><p>提高从库的机器性能,减少主库写 binlog 和从库读 binlog 的效率差;</p></li><li><p>保证主库和从库的网络连接,避免出现网络延迟导致的 binlog 传输延迟;</p></li><li><p>强行读主库;</p></li><li><p>配合 semi-sync 半同步复制;</p></li></ol><p><strong>semi-sync 半同步复制</strong></p><p>MySQL 有三种同步模式,分别是:</p><ol><li><p>异步复制:MySQL 中默认的复制是异步的,主库在执行完客户端提交的事务后会立即将结果返回给客户端,并不关心从库是否已经接收并且处理。存在问题就是,如果主库的日志没有及时同步到从库,然后主库宕机了,这时候执行故障转移,在从库冲选主,可能会存在选出的主库中数据不完整;</p></li><li><p>全同步复制:指当主库执行完一个事务,并且等到所有从库也执行完成这个事务的时候,主库在提交事务,并且返回数据给客户端。因为要等待所有从库都同步到主库中的数据才返回数据,所以能够保证主从数据的一致性,但是数据库的性能必然受到影响;</p></li><li><p>半同步复制:是介于全同步和全异步同步的一种,主库至少需要等待一个从库接收并写入到 <code>Relay Log</code> 文件即可,主库不需要等待所有从库给主库返回 ACK。主库收到 ACK ,标识这个事务完成,返回数据给客户端。</p></li></ol><p>MySQL 中默认的复制是异步的,所以主库和从库的同步会存在一定的延迟,更重要的是异步复制还可能引起数据的丢失。全同步复制的性能又太差了,所以从 <code>MySQL 5.5</code> 开始,MySQL 以插件的形式支持 semi-sync 半同步复制。</p><p>半同步复制潜在的问题</p><p>在传统的半同步复制中,主库写数据到 binlog,并且执行 commit 提交事务后,会一直等待一个从库的 ACK。从库会在写入 <code>Relay Log</code> 后,将数据落盘,然后回复给主库 ACK,主库收到这个 ACK 才能给客户端事务完成的确认。</p><p>这样会存在问题就是,主库已经将该事务的 commit 存储到了引擎层,应用已经可以看到数据的变化了,只是在等待从库的返回,如果此时主库宕机,可能从库还没有写入 Relay Log,就会发生主从库数据不一致。</p><p>为了解决这个问题,<code>MySQL 5.7</code> 引入了增强半同步复制。主库写入数据到 binlog 后,就开始等待从库的应答 ACK,直到至少一个从库写入 <code>Relay Log</code> 后,并将数据落盘,然后返回给主库 ACK,通知主库可以进行 commit 操作,然后主库再将事务提交到事务引擎,应用此时才能看到数据的变化。</p><p>不过看下来增强半同步复制,在同步给从库之后,因为自己的数据还没有提交,然后宕机了,主库中也是会存在数据的丢失,不过应该想到的是,这时候主库宕机了,是会重新在从库中选主的,这样新选出的主库数据是没有发生丢失的。</p></blockquote><h2 id="MySQL-Group-Replication"><a href="#MySQL-Group-Replication" class="headerlink" title="MySQL Group Replication"></a>MySQL Group Replication</h2><p>由Oracle MySQL 推出的一个高可用高扩展解决方案,MGT由若干个节点组成复制组,一个事务的提交必须经过组内半数以上协议并通过才能得以提交</p><p><img src="https://oss.luhuhu.cn/202406051032446.jpeg" alt="MGR"></p><blockquote><p>当客户端发起一个更新事务时,该事务先在本地执行,执行完成之后就要发起对事务的提交操作。在还没有真正提交之前,需要将产生的复制写集广播出去,复制到其它成员。因为事务是通过原子广播发送的,所以组中的成员要么都接收事务,要么都不接收事务。如果组中的所有成员收到了该广播消息(事务),那么他们会按照之前发送事务的相同顺序收到该广播消息。因此,所有组成员都以相同的顺序接收事务的写集,并为事务建立全局顺序。因此,所有组成员都以相同的顺序接收事务的写集,并为事务建立全局顺序。</p><p>在不同组成员并发执行的事务可能存在冲突。冲突是通过检查和比较两个不同并发事务的 <code>write set</code> 来验证的,这个过程称为认证。在认证期间,冲突检测在行级别执行的:如果在不同组成员上执行的两个并发事务更新了同一行数据,则存在冲突。根据冲突认证检测机制判断,按照顺序,第一次提交的会正常执行,第二次提交的事务会在事务发起的原始组成员上执行回滚,,组中的其他成员对该事务执行删除。如果两个事务经常发生冲突,那么最好将这两个事务放在同一个组成员中执行,这样它们在本地锁管理器的协调下将都有机会提交成功,而不至于因为处在两个不同的组成员中由于冲突认证而导致其中一个事务被频繁回滚。</p><p>最终,所有组内成员以相同的顺序接收同一组事务。因此组内成员以相同的顺序应用相同的修改,保证组内数据强一致性。</p><p>有下面的几种特性:</p><ol><li><p>避免脑裂:MGR 中不会出现脑裂的现象;</p></li><li><p>数据一致性保障:MGR 的冗余能力很好,能够保证 <code>Binlog Event</code> 至少被复制到超过一半的成员上,只要同时宕机的成员不超过半数便不会导致数据丢失。MGR还保证只要 <code>Binlog Event</code> 没有被传输到半数以上的成员,本地成员不会将事务的 <code>Binlog Event</code> 写入 Binlog 文件和提交事务,从而保证宕机的服务器上不会有组内在线成员上不存在的数据。因此,宕机的服务器重启后,不再需要特殊的处理就可以加入组;</p></li><li><p>多节点写入支持:多写模式下支持集群中的所有节点都可以写入。</p></li></ol><p>组复制的应用场景</p><ol><li><p>弹性复制:需要非常灵活的复制基础设施的环境,其中MySQL Server的数量必须动态增加或减少,并且在增加或减少Server的过程中,对业务的副作用尽可能少。例如,云数据库服务;</p></li><li><p>高可用分片:分片是实现写扩展的一种流行方法。基于 组复制 实现的高可用分片,其中每个分片都会映射到一个复制组上(逻辑上需要一一对应,但在物理上,一个复制组可以承载多个分片);</p></li><li><p>替代主从复制:在某些情况下,使用一个主库会造成单点争用。在某些情况下,向整个组内的多个成员同时写入数据,对应用来说可能伸缩性更强;</p></li><li><p>自治系统:可以利用组复制内置的自动故障转移、数据在不同组成员之间的原子广播和最终数据一致性的特性来实现一些运维自动化。</p></li></ol></blockquote><h2 id="InnoDB-Cluster"><a href="#InnoDB-Cluster" class="headerlink" title="InnoDB Cluster"></a>InnoDB Cluster</h2><p><code>InnoDB Cluster</code> 是官方提供的高可用方案,是 MySQL 的一种高可用性(HA)解决方案,它通过使用 <code>MySQL Group Replication</code> 来实现数据的自动复制和高可用性。</p><p><img src="https://oss.luhuhu.cn/202406051032421.png" alt="HA"></p><blockquote><p><code>InnoDB Cluster</code> 通常包含下面三个关键组件:</p><ol><li><p><code>MySQL Shell</code>: 它是 MySQL 的高级管理客户端;</p></li><li><p><code>MySQL Server</code> 和 <code>MGR</code>,使得一组 <code>MySQL</code> 实例能够提供高可用性,对于 MGR,<code>Innodb Cluster</code> 提供了一种更加易于编程的方式来处理 MGR;</p></li><li><p><code>MySQL Router</code>,一种轻量级中间件,主要进行路由请求,将客户端发送过来的请求路由到不同的 MySQL 服务器节点。</p></li></ol><p><code>MySQL Server</code> 基于 <code>MySQL Group Replication</code> 构建,提供自动成员管理,容错,自动故障转移动能等。<code>InnoDB Cluster</code> 通常以单主模式运行,一个读写实例和多个只读实例。不过也可以选用多主模式。</p><p>优点:</p><ol><li><p>高可用性:通过 <code>MySQL Group Replication</code>,<code>InnoDB Cluster</code> 能够实现数据在集群中的自动复制,从而保证数据的可用性;</p></li><li><p>简单易用:<code>InnoDB Cluster</code> 提供了一个简单易用的管理界面,使得管理员可以快速部署和管理集群;</p></li><li><p>全自动故障转移: <code>InnoDB Cluster</code> 能够自动检测和诊断故障,并进行必要的故障转移,使得数据可以继续可用。</p></li></ol><p>缺点:</p><ol><li><p>复杂性:<code>InnoDB Cluster</code> 的部署和管理比较复杂,需要对 MySQL 的工作原理有一定的了解;</p></li><li><p>性能影响:由于自动复制和高可用性的要求,<code>InnoDB Cluster</code> 可能对 MySQL 的性能造成一定的影响;</p></li><li><p>限制:<code>InnoDB Cluster</code> 的功能对于一些特殊的应用场景可能不够灵活,需要更多的定制。</p></li></ol></blockquote><h2 id="InnoDB-ClusterSet"><a href="#InnoDB-ClusterSet" class="headerlink" title="InnoDB ClusterSet"></a>InnoDB ClusterSet</h2><p><code>MySQL InnoDB ClusterSet</code> 通过将主 <code>InnoDB Cluster</code> 与其在备用位置(例如不同数据中心)的一个或多个副本链接起来,为 <code>InnoDB Cluster</code> 部署提供容灾能力。</p><p><code>InnoDB ClusterSet</code> 使用专用的 ClusterSet 复制通道自动管理从主集群到副本集群的复制。如果主集群由于数据中心损坏或网络连接丢失而变得无法使用,用户可以激活副本集群以恢复服务的可用性。</p><p><img src="https://oss.luhuhu.cn/202406051032496.png" alt="Cluster"></p><blockquote><p>InnoDB ClusterSet 的特点:</p><ol><li>主集群和副本集群之间的紧急故障转移可以由管理员通过 <code>MySQL Shell</code>,使用 AdminAPI 进行操作;</li><li>InnoDB ClusterSet 部署中可以拥有的副本集群的数量没有定义的限制;</li><li>异步复制通道将事务从主集群复制到副本集群。<code>clusterset_replication</code> 在 <code>InnoDB ClusterSet</code> 创建过程中,在每个集群上都设置了名为 ClusterSet 的复制通道,当集群是副本时,它使用该通道从主集群复制事务。底层组复制技术管理通道并确保复制始终在主集群的主服务器(作为发送方)和副本集群的主服务器(作为接收方)之间进行;</li><li>每个 <code>InnoDB ClusterSet</code> 集群,只有主集群能够接收写请求,大多数的读请求流量也会被路由到主集群,不过也可以指定读请求到其他的集群;</li></ol><p>InnoDB ClusterSet 的限制:</p><ol><li><p>InnoDB ClusterSet 只支持异步复制,不能使用半同步复制,无法避免异步复制的缺陷:数据延迟、数据一致性等;</p></li><li><p>InnoDB ClusterSet 仅支持Cluster实例的单主模式,不支持多主模式。 即只能包含一个读写主集群, 所有副本集群都是只读的, 不允许具有多个主集群的双活设置,因为在集群发生故障时无法保证数据一致性;</p></li><li><p>已有的 InnoDB Cluster 不能用作 InnoDB ClusterSet 部署中的副本集群。副本集群必须从单个服务器实例启动,作为新的 InnoDB 集群;</p></li><li><p>只支持 MySQL 8.0。</p></li></ol></blockquote><h2 id="InnoDB-ReplicaSet"><a href="#InnoDB-ReplicaSet" class="headerlink" title="InnoDB ReplicaSet"></a>InnoDB ReplicaSet</h2><p><code>InnoDB ReplicaSet</code> 是 MySQL 团队在 2020 年推出的一款产品,用来帮助用户快速部署和管理主从复制,在数据库层仍然使用的是主从复制技术。</p><p><code>InnoDB ReplicaSet</code>由单个主节点和多个辅助节点(传统上称为 MySQL 复制源和副本)组成。</p><p>与<code>InnoDB cluster</code> 类似, <code>MySQL Router</code> 支持针对 <code>InnoDB ReplicaSet</code> 的引导, 这意味着可以自动配置 <code>MySQL Router</code> 以使用 <code>InnoDB ReplicaSet</code>, 而无需手动配置文件. 这使得 <code>InnoDB ReplicaSet</code> 成为一种快速简便的方法, 可以启动和运行 MySQL 复制和 <code>MySQL Router</code>, 非常适合扩展读取, 并在不需要 InnoDB 集群提供高可用性的用例中提供手动故障转移功能。</p><p><img src="https://oss.luhuhu.cn/202406051032526.png" alt="InnoDB ReplicaSet"></p><blockquote><p><code>InnoDB ReplicaSet</code> 的限制:</p><ol><li><p>没有自动故障转移,在主节点不可用的情况下,需要使用 AdminAPI 手动触发故障转移,然后才能再次进行任何更改。但是,辅助实例仍可用于读取;</p></li><li><p>由于意外停止或不可用,无法防止部分数据丢失:在意外停止时未完成的事务可能会丢失;</p></li><li><p>在意外退出或不可用后无法防止不一致。如果手动故障转移提升了一个辅助实例,而前一个主实例仍然可用,例如,由于网络分区,裂脑情况可能会导致数据不一致;</p></li><li><p>InnoDB ReplicaSet 不支持多主模式。允许写入所有成员的经典复制拓扑无法保证数据一致性;</p></li><li><p>读取横向扩展是有限的。<code>InnoDB ReplicaSet</code> 基于异步复制,因此无法像 <code>Group Replication</code> 那样调整流量控制;</p></li><li><p>一个 ReplicaSet 最多由一个主实例组成。支持一个或多个辅助。尽管可以添加到 ReplicaSet 的辅助节点的数量没有限制,但是连接到 ReplicaSet 的每个 MySQL Router 都必须监视每个实例。因此,一个 ReplicaSet 中加入的实例越多,监控就越多。</p></li></ol><p>使用 <code>InnoDB ReplicaSets</code> 的主要原因是你有更好的写性能。使用 <code>InnoDB ReplicaSets</code> 的另一个原因是它们允许在不稳定或慢速网络上部署,而 <code>InnoDB Cluster</code> 则不允许。</p></blockquote><h2 id="MMM"><a href="#MMM" class="headerlink" title="MMM"></a>MMM</h2><p>Master-Master replication manager for MySQL是一套支持双主故障切换和双主日常管理的脚本程序。MMM 使用 Perl 语言开发,主要用来监控和管理 <code>MySQL Master-Master</code>(双主)复制,可以说是 MySQL 主主复制管理器。</p><p>双主模式,业务上同一时刻只能一个主库进行数据的写入。另一个主备库,会在主服务器失效时,进行主备切换和故障转移。</p><p>MMM 中是通过一个 VIP(虚拟 IP) 的机制来保证集群的高可用的。整个集群中,在主节点会提供一个 VIP 地址来提供数据读写服务,当出现故障的时候,VIP 就会从原来的主节点便宜到其他节点,由其他节点提供服务。</p><p><img src="https://oss.luhuhu.cn/202406051032536.png" alt="MMM"></p><blockquote><p>MMM无法完全的保证数据一致性,所以适用于对数据的一致性要求不是很高的场景。(因为主备上的数据不一定是最新的,可能还没从库的新。解决方法:开启半同步)。</p><p>MMM 的优缺点</p><p>优点:高可用性,扩展性好,出现故障自动切换,对于主主同步,在同一时间只提供一台数据库写操作,保证数据的一致性。</p><p>缺点:无法完全保数据的一致性,建议采用半同步复制方式,减少失败的概率;目前 MMM 社区已经缺少维护,不支持基于 GTID 的复制。</p><p>适用场景:</p><p>MMM的适用场景为数据库访问量大,业务增长快,并且能实现读写分离的场景。</p></blockquote><h2 id="MHA"><a href="#MHA" class="headerlink" title="MHA"></a>MHA</h2><p>Master High Availability Manager and Tools for MySQL,简称 MHA 。是一套优秀的作为 MySQL 高可用性环境下故障切换和主从提升的高可用软件。</p><p>这个工具专门用于监控主库的状态,当发现 master 节点故障的时候,会自动提升其中拥有新数据的 slave 节点成为新的 master 节点,在此期间,MHA 会通过其他从节点获取额外的信息来避免数据一致性问题。MHA 还提供了 mater 节点的在线切换功能,即按需切换 master-slave 节点。MHA 能够在30秒内实现故障切换,并能在故障切换过程中,最大程度的保证数据一致性。</p><p><img src="https://oss.luhuhu.cn/202406051032009.png" alt="MHA"></p><blockquote><p>MHA 由两部分组成;</p><p>MHA Manager(管理节点)和MHA Node(数据节点)。</p><p><code>MHA Manager</code> 可以单独部署在一台独立的机器上管理多个 master-slave 集群,也可以部署在一台 slave节点上。<code>MHA Node</code> 运行在每台 MySQL 服务器上,<code>MHA Manager</code> 会定时探测集群中的 master 节点,当 master 出现故障时,它可以自动将最新数据的 slave 提升为新的 master,然后将所有其他的 slave 重新指向新的 master。</p><p>整个故障转移过程对应用程序完全透明。</p><p>在 MHA 自动故障切换过程中,MHA 试图从宕机的主服务器上最大限度的保存二进制日志,最大程度的保证数据的不丢失,但这并不总是可行的。例如,主服务器硬件故障或无法通过 ssh 访问,MHA 没法保存二进制日志,只进行故障转移而丢失了最新的数据。</p><p>使用 <code>MySQL 5.5</code> 开始找支持的半同步复制,可以大大降低数据丢失的风险。MHA可以与半同步复制结合起来。如果只有一个 slave 已经收到了最新的二进制日志,MHA 可以将最新的二进制日志应用于其他所有的 slave 服务器上,因此可以保证所有节点的数据一致性。</p><p>目前 MHA 主要支持一主多从的架构,要搭建 MHA,要求一个复制集群中必须最少有三台数据库服务器 ,一主二从,即一台 master,一台充当备用 master,另外一台充当从库,因为至少需要三台服务器。</p><p>MHA 工作原理总结如下:</p><ol><li><p>从宕机崩溃的 master 保存二进制日志事件(binlog events);</p></li><li><p>识别最新更新的 slave;</p></li><li><p>应用差异的中继日志(relay log) 到其他slave;</p></li><li><p>应用从master保存的二进制日志事件(binlog events);</p></li><li><p>提升一个 slave 为新master;</p></li><li><p>使用其他的 slave 连接新的 master 进行复制。</p></li></ol><p>优点:</p><ol><li><p>可以支持基于 GTID 的复制模式;</p></li><li><p>MHA 在进行故障转移时更不易产生数据丢失;</p></li><li><p>同一个监控节点可以监控多个集群。</p></li></ol><p>缺点:</p><ol><li><p>需要编写脚本或利用第三方工具来实现 Vip 的配置;</p></li><li><p>MHA 启动后只会对主数据库进行监控;</p></li><li><p>需要基于 SSH 免认证配置,存在一定的安全隐患。</p></li></ol></blockquote><h2 id="Galera-Cluster"><a href="#Galera-Cluster" class="headerlink" title="Galera Cluster"></a>Galera Cluster</h2><p><code>Galera Cluster</code> 是由 Codership 开发的MySQL多主集群,包含在 MariaDB 中,同时支持 <code>Percona xtradb、MySQL</code>,是一个易于使用的高可用解决方案,在数据完整性、可扩展性及高性能方面都有可接受的表现。</p><p>其本身具有 multi-master 特性,支持多点写入,<code>Galera Cluster</code> 中每个实例都是对等的,互为主从。当客户端读写数据的时候,可以选择任一 MySQL 实例,对于读操作,每个实例读取到的数据都是相同的。对于写操作,当数据写入某一节点后,集群会将其同步到其它节点。这种架构不共享任何数据,是一种高冗余架构。</p><p><img src="https://oss.luhuhu.cn/202406051032899.png" alt="Galera Cluster"></p><blockquote><p><strong>主要功能</strong></p><ol><li><p>同步复制;</p></li><li><p>真正的 multi-master,即所有节点可以同时读写数据库;</p></li><li><p>自动的节点成员控制,失效节点自动被清除;</p></li><li><p>新节点加入数据自动复制;</p></li><li><p>真正的并行复制,行级;</p></li><li><p>用户可以直接连接集群,使用感受上与 MySQL 完全一致。</p></li></ol><p><strong>优势</strong></p><ol><li><p>数据一致:同步复制保证了整个集群的数据一致性,无论何时在任何节点执行相同的select查询,结果都一样;</p></li><li><p>高可用性:由于所有节点数据一致,单个节点崩溃不需要执行复杂耗时的故障切换,也不会造成丢失数据或停止服务;</p></li><li><p>性能改进:同步复制允许在集群中的所有节点上并行执行事务,从而提高读写性能;</p></li><li><p>更小的客户端延迟;</p></li><li><p>同时具有读和写的扩展能力。</p></li></ol><p>分析下原理</p><p><code>Galera Cluster</code> 中主要用到了同步复制,主库中的单个更新事务需要在所有从库中同步更新,当主库提交事务,集群中的所有节点数据保持一致。</p><p>异步复制,主库将数据更新传播给从库后立即提交事务,而不论从库是否成功读取或重放数据变化,所以异步复制会存在短暂的,主从数据同步不一致的情况出现。</p><p>不过同步复制的缺点也是很明显的,同步复制协议通常使用两阶段提交或分布式锁协调不同节点的操作,也及时说节点越多需要协调的节点也就越多,那么事务冲突和死锁的概率也就会随之增加。</p><p>我们知道 MGR 组复制的引入也是为了解决传统异步复制和半同步复制可能产生数据不一致的问题,MGR 中的组复制,基于 Paxos 协议,原则上事务的提交,主要大多数节点 ACK 就可以提交了。</p><p><code>Galera Cluster</code> 中的同步需要同步数据到所有节点,保证所有节点都成功。基于专有通信组系统 GCommon ,所有节点都必须有 ACK。</p><p>Galera 复制是一种基于验证的复制,基于验证的复制使用通信和排序技术实现同步复制,通过广播并发事务之间建立的全局总序来协调事务提交。简单的讲就是事务必须以相同的顺序应用于所有实例。</p><p>事务现在本地执行,然后发送的其他节点做冲突验证,没有冲突的时候所有节点提交事务,否则在所有节点回滚。</p><p><img src="https://oss.luhuhu.cn/202406051032946.png" alt="mysql"></p><p>当客户端发出 commit 命令时,在实际提交之前,对数据所做的更改都会收集到一个写集合中,写集合中包含事务信息和所更改行的主键,数据库将写集发送到其它节点。</p><p>节点用写集中的主键与当前节点中未完成事务的所有写集的主键比较,确定节点是否可以提交事务,同时满足下面三个条件会被任务存在冲突,验证失败:</p><ol><li><p>两个事务来源于不同节点;</p></li><li><p>两个事务包含相同的主键;</p></li><li><p>老事务对新事务不可见,即老事务未提交完成。新老事务的划定依赖于全局事务总序,即 GTID。</p></li></ol><p>验证失败,节点将删除写集,集群将回滚原始事务,对于所有的节点都是如此,每个节点单独进行验证。因为所有节点都以相同的顺序接收事务,它们对事务的结果都会做出相同的决定,要么全成功,要么都失败。成功后自然就提交了,所有的节点又会重新达到数据一致的状态。节点之间不交换“是否冲突”的信息,各个节点独立异步处理事务。</p></blockquote><h2 id="MySQL-Cluster"><a href="#MySQL-Cluster" class="headerlink" title="MySQL Cluster"></a>MySQL Cluster</h2><p><code>MySQL Cluster</code> 是一个高度可扩展的,兼容 ACID 事务的实时数据库,基于分布式架构不存在单点故障,<code>MySQL Cluster</code> 支持自动水平扩容,并能做自动的读写负载均衡。</p><p><code>MySQL Cluster</code> 使用了一个叫 NDB 的内存存储引擎来整合多个 MySQL 实例,提供一个统一的服务集群。</p><p>NDB 是一种内存性的存储引擎,使用 Sarding-Nothing 的无共享的架构。Sarding-Nothing 指的是每个节点有独立的处理器,磁盘和内存,节点之间没有共享资源完全独立互不干扰,节点之间通过告诉网络组在一起,每个节点相当于是一个小型的数据库,存储部分数据。这种架构的好处是可以利用节点的分布性并行处理数据,调高整体的性能,还有就是有很高的水平扩展性能,只需要增加节点就能增加数据的处理能力。</p><p><img src="https://oss.luhuhu.cn/202406051032994.png" alt="MySQL Cluster"></p><blockquote><p><code>MySql Cluster</code> 中包含三种节点,分别是管理节点(NDB Management Server)、数据节点(Data Nodes)和 SQL查询节点(SQL Nodes) 。</p><p><code>SQL Nodes</code> 是应用程序的接口,像普通的 mysqld 服务一样,接受用户的 SQL 输入,执行并返回结果。<code>Data Nodes</code> 是数据存储节点,<code>NDB Management Server</code> 用来管理集群中的每个 node。</p><p>其中数据节点会存储集群中的数据分区和分区的副本,来看下 <code>MySql Cluster</code> 是如何对数据进行分片的操作的,首先来了解下下面几个概念</p><ul><li>节点组(Node Group): 一组数据节点的集合。节点组的个数=<code>节点数 / 副本数</code>;</li></ul><p>比如有集群中 4 个节点,副本数为 2(对应 NoOfReplicas 的设置),那么节点组个数为2。</p><p>另外,在可用性方面,数据的副本在组内交叉分配,一个节点组内只有要一台机器可用,就可以保证整个集群的数据完整性,实现服务的整体可用。</p><ul><li>分区(Partition):<code>MySql Cluster</code> 是一个分布式的存储系统,数据按照 分区 划分成多份存储在各数据节点中,分区个数由系统自动计算,<code>分区数 = 数据节点数 / LDM 线程数</code>;</li><li>副本(Replica):分区数据的备份,有几个分区就有几个副本,为了避免单点,保证 <code>MySql Cluster</code> 集群的高可用,原始数据对应的分区和副本通常会保存在不同的主机上,在一个节点组内进行交叉备份。</li></ul><p><img src="https://oss.luhuhu.cn/202406051032069.png" alt="mysql"></p><p>栗如,上面的例子,有四个数据节点(使用ndbd),副本数为2的集群,节点组被分为2组(4/2),数据被分为4个分区,数据分配情况如下:</p><p>分区0(Partition 0)保存在节点组 0(Node Group 0)中,分区数据(主副本 — Primary Replica)保存在节点1(node 1) 中,备份数据(备份副本,Backup Replica)保存在节点2(node 2) 中;</p><p>分区1(Partition 1)保存在节点组 1(Node Group 1)中,分区数据(主副本 — Primary Replica)保存在节点3(node 3) 中,备份数据(备份副本,Backup Replica)保存在节点4(node 4) 中;</p><p>分区2(Partition 2)保存在节点组 0(Node Group 0)中,分区数据(主副本 — Primary Replica)保存在节点2(node 2) 中,备份数据(备份副本,Backup Replica)保存在节点1(node 1) 中;</p><p>分区3(Partition 2)保存在节点组 1(Node Group 1)中,分区数据(主副本 — Primary Replica)保存在节点4(node 4) 中,备份数据(备份副本,Backup Replica)保存在节点3(node 3) 中;</p><p>这样,对于一张表的一个 Partition 来说,在整个集群有两份数据,并分布在两个独立的 Node 上,实现了数据容灾。同时,每次对一个 Partition 的写操作,都会在两个 Replica 上呈现,如果 <code>Primary Replica</code> 异常,那么 <code>Backup Replica</code> 可以立即提供服务,实现数据的高可用。</p><p><code>mysql cluster</code> 的优点</p><ol><li><p>99.999%的高可用性;</p></li><li><p>快速的自动失效切换;</p></li><li><p>灵活的分布式体系结构,没有单点故障;</p></li><li><p>高吞吐量和低延迟;</p></li><li><p>可扩展性强,支持在线扩容。</p></li></ol><p><code>mysql cluster</code> 的缺点</p><ol><li><p>存在很多限制,比如:不支持外键,数据行不能超过8K(不包括BLOB和text中的数据);</p></li><li><p>部署、管理、配置很复杂;</p></li><li><p>占用磁盘空间大,内存大;</p></li><li><p>备份和恢复不方便;</p></li><li><p>重启的时候,数据节点将数据 load 到内存需要很长时间。</p></li></ol></blockquote><h2 id="MySQL-Fabric"><a href="#MySQL-Fabric" class="headerlink" title="MySQL Fabric"></a>MySQL Fabric</h2><p><code>MySQL Fabric</code> 会组织多个 MySQL 数据库,将大的数据分散到多个数据库中,即数据分片<code>(Data Shard)</code>,同时同一个分片数据库中又是一个主从结构,Fabric 会挑选合适的库作为主库,当主库挂掉的时候,又会重新在从库中选出一个主库。</p><p><img src="https://oss.luhuhu.cn/202406051032151.png" alt="MySQL Fabric"></p><blockquote><p><code>MySQL Fabric</code> 的特点:</p><ol><li><p>高可用;</p></li><li><p>使用数据分片的横向功能。</p></li></ol><p><code>MySQL Fabric-aware</code> 连接器把从 <code>MySQL Fabric</code> 获取的路由信息存储到缓存中,然后凭借该信息将事务或查询发送给正确的 MySQL 服务器。</p><p>同时,每一个分片组,可以又多个一个服务器组成,构成主从结构,当主库挂掉的时候,又会重新在从库中选出一个主库。保证节点的高可用。</p><p><code>HA Group</code> 保证访问指定 <code>HA Group</code> 的数据总是可用的,同时其基础的数据复制是基于 <code>MySQL Replication</code> 实现的。</p><p>缺点</p><p>事务及查询只支持在同一个分片内,事务中更新的数据不能跨分片,查询语句返回的数据也不能跨分片。</p></blockquote><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><ol><li><p><code>MySQL Replication</code> 是官方提供的主从同步方案,用于将一个 MySQL 的实例同步到另一个实例中,在主从复制中,从库利用主库上的 binlog 进行重播,实现主从同步,默认是异步同步,针对其在不同场景下的一些缺陷,衍生出了半同步复制,强同步复制等数据高可用的方案;</p></li><li><p><code>MySQL Group Replication</code> 组复制又称为 MGR,引入复制组主要是为了解决传统异步复制和半同步复制可能产生数据不一致的问题, MGR 由若干个节点共同组成一个复制组,一个事务的提交,必须经过组内大多数节点 (N / 2 + 1) 决议并通过,才能得以提交;</p></li><li><p><code>InnoDB Cluster</code> 是官方提供的高可用方案,是 MySQL 的一种高可用性(HA)解决方案,它通过使用<code>MySQL Group Replication</code> 来实现数据的自动复制和高可用性;</p></li><li><p><code>InnoDB ClusterSet</code> 通过将主 <code>InnoDB Cluster</code> 与其在备用位置(例如不同数据中心)的一个或多个副本链接起来,为 <code>InnoDB Cluster</code> 部署提供容灾能力,每个节点就是一个 <code>InnoDB Cluster</code>;</p></li><li><p><code>InnoDB ReplicaSet</code> 与<code>InnoDB cluster</code> 类似, <code>MySQL Router</code> 支持针对 <code>InnoDB ReplicaSet</code> 的引导, 这意味着可以自动配置 <code>MySQL Router</code> 以使用 <code>InnoDB ReplicaSet</code>, 而无需手动配置文件. 这使得 <code>InnoDB ReplicaSet</code> 成为一种快速简便的方法, 可以启动和运行 MySQL 复制和 <code>MySQL Router</code>, 非常适合扩展读取, 并在不需要 InnoDB 集群提供高可用性的用例中提供手动故障转移功能;</p></li><li><p>MMM(Master-Master replication manager for MySQL)是一套支持双主故障切换和双主日常管理的脚本程序。MMM 使用 Perl 语言开发,主要用来监控和管理 MySQL Master-Master(双主)复制,可以说是 MySQL 主主复制管理器;</p></li><li><p><code>Master High Availability Manager and Tools for MySQL</code>,简称 MHA 。是一套优秀的作为 MySQL 高可用性环境下故障切换和主从提升的高可用软件,这个工具专门用于监控主库的状态,当发现 master 节点故障的时候,会自动提升其中拥有新数据的 slave 节点成为新的 master 节点,在此期间,MHA 会通过其他从节点获取额外的信息来避免数据一致性问题。MHA 还提供了 mater 节点的在线切换功能,即按需切换 master-slave 节点。MHA 能够在30秒内实现故障切换,并能在故障切换过程中,最大程度的保证数据一致性;</p></li><li><p><code>Galera Cluster</code> 是由 Codership 开发的MySQL多主集群,包含在 MariaDB 中,同时支持 Percona xtradb、MySQL,是一个易于使用的高可用解决方案,在数据完整性、可扩展性及高性能方面都有可接受的表现,本身具有 multi-master 特性,支持多点写入,Galera Cluster 中每个实例都是对等的,互为主从。当客户端读写数据的时候,可以选择任一 MySQL 实例,对于读操作,每个实例读取到的数据都是相同的。对于写操作,当数据写入某一节点后,集群会将其同步到其它节点。这种架构不共享任何数据,是一种高冗余架构;</p></li><li><p><code>MySQL Cluster</code> 是一个高度可扩展的,兼容 ACID 事务的实时数据库,基于分布式架构不存在单点故障,<code>MySQL Cluster</code> 支持自动水平扩容,并能做自动的读写负载均衡,MySQL Cluster 使用了一个叫 NDB 的内存存储引擎来整合多个 MySQL 实例,提供一个统一的服务集群;</p></li><li><p><code>MySQL Fabric</code> 会组织多个 MySQL 数据库,将大的数据分散到多个数据库中,即数据分片(Data Shard),同时同一个分片数据库中又是一个主从结构,Fabric 会挑选合适的库作为主库,当主库挂掉的时候,又会重新在从库中选出一个主库。</p></li></ol><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><p><a href="https://book.douban.com/subject/23008813/">【高性能MySQL(第3版)】</a><br><a href="https://time.geekbang.org/column/100020801">【MySQL 实战 45 讲】</a><br><a href="https://book.douban.com/subject/24708143/">【MySQL技术内幕】</a><br><a href="https://github.com/boilingfrog/Go-POINT/tree/master/mysql">【MySQL学习笔记】</a><br><a href="https://dev.mysql.com/doc/refman/8.0/en/replication.html">【MySQL文档】</a><br><a href="http://www.linkedkeeper.com/1503.html">【浅谈 MySQL binlog 主从同步】</a></p><h2 id="实践"><a href="#实践" class="headerlink" title="实践"></a>实践</h2><h3 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h3><p>单CentOS7服务器,3个mysql实例</p><pre class=" language-bash"><code class="language-bash"><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># systemctl list-units --type=service | grep mysql</span>mysqld-3306.service loaded active running MySQL Servermysqld-3307.service loaded active running MySQL Servermysqld-3308.service loaded active running MySQL Server</code></pre><h3 id="MySQL-Replication-1"><a href="#MySQL-Replication-1" class="headerlink" title="MySQL Replication"></a>MySQL Replication</h3>]]></content>
<categories>
<category> CS </category>
</categories>
<tags>
<tag> MySql </tag>
</tags>
</entry>
<entry>
<title>MySql-cnf</title>
<link href="/post/b32c4d99.html"/>
<url>/post/b32c4d99.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="MySQL配置解析"><a href="#MySQL配置解析" class="headerlink" title="MySQL配置解析"></a>MySQL配置解析</h1><p><a href="https://blog.csdn.net/u010797364/article/details/123356025">cnf配置优化</a></p><h2 id="TIPS"><a href="#TIPS" class="headerlink" title="TIPS"></a>TIPS</h2><p><code>socket</code>是一种抽象层,应用程序通过它收发数据,用于<code>本地连接</code>(同一台机器的客户端和服务器),这种通信方式比<code>TCP/IP</code>更快,因为避免了网络协议栈的开销</p><h2 id="client"><a href="#client" class="headerlink" title="[client]"></a>[client]</h2><pre class=" language-bash"><code class="language-bash"><span class="token comment" spellcheck="true"># 客户端连接信息端口号、socket路径,字符集</span>port <span class="token operator">=</span> 3306socket <span class="token operator">=</span> /path/***.sockdefault-character-set<span class="token operator">=</span>utf8mb4</code></pre><h2 id="mysqld"><a href="#mysqld" class="headerlink" title="[mysqld]"></a>[mysqld]</h2><pre class=" language-bash"><code class="language-bash"><span class="token comment" spellcheck="true"># mysql基本配置信息,监听的IP、端口号、socket路径、数据目录、临时目录</span>bind-address <span class="token operator">=</span> 0.0.0.0 <span class="token comment" spellcheck="true"># 默认0.0.0.0 监听所有来源IP的访问</span>port <span class="token operator">=</span> 3306 <span class="token comment" spellcheck="true"># 默认3306端口,需要和client端口保持一致</span>pid-file <span class="token operator">=</span> /path/***.pid <span class="token comment" spellcheck="true"># 唯一数字标识符,标识MySQL服务器进程避免冲突</span>socket <span class="token operator">=</span> /path/***.sock <span class="token comment" spellcheck="true"># 本地socket访问,需要和client保持一致</span>basedir <span class="token operator">=</span> /path/mysqldatadir <span class="token operator">=</span> /path/mysql/datatmpdir <span class="token operator">=</span> /path/mysql/tmp<span class="token comment" spellcheck="true"># 监听队列连接数上限,如果有搞的连接率需求且出现connection refused</span>back-log <span class="token operator">=</span> 50 <span class="token comment" spellcheck="true"># 关闭TCP/IP监听,当服务器只允许本地访问数据库时,增强安全</span><span class="token comment" spellcheck="true"># skip-networking</span><span class="token comment" spellcheck="true"># 服务所允许的会话数上限</span>max_connections <span class="token operator">=</span> 100<span class="token variable"><span class="token variable">`</span>max_connections 控制的是 MySQL 服务器允许的并发连接总数,而 back_log 控制的是在短时间内可以积压的未完成连接请求的数量。<span class="token variable">`</span></span>max_connections 影响的是服务器处理连接的能力,而 back_log 影响的是服务器在网络繁忙时处理新连接请求的能力。<span class="token variable"><span class="token variable">`</span>max_connections 的值通常设置得较高,以适应预期的并发用户数,而 back_log 的值通常设置得较低,因为它只在网络端口非常繁忙时起作用。<span class="token variable">`</span></span><span class="token comment" spellcheck="true"># 每个客户端连接最大错误允许数量</span>max_connect_errors <span class="token operator">=</span> 10<span class="token comment" spellcheck="true"># 所有线程所打开表的数量,决定了服务器可以同时打开的表的最大数量.</span><span class="token comment" spellcheck="true"># 增加此值就增加了mysqld所需要的文件描述符的数量</span><span class="token comment" spellcheck="true"># 这样你需要确认在[mysqld_safe]中 “open-files-limit” 变量设置打开文件数量允许至少4096</span>table_cache <span class="token operator">=</span> 2048<span class="token comment" spellcheck="true"># 外部锁</span>external-locking<span class="token comment" spellcheck="true"># 请求包最大</span>max_allowed_packet <span class="token operator">=</span> 16Mbinlog_cache_size <span class="token operator">=</span> 1Mmax_heap_table_size <span class="token operator">=</span> 64Msort_buffer_size <span class="token operator">=</span> 8Mjoin_buffer_size <span class="token operator">=</span> 8Mthread_cache_size <span class="token operator">=</span> 8<span class="token punctuation">..</span>.</code></pre><hr><h2 id="mysqldump"><a href="#mysqldump" class="headerlink" title="[mysqldump]"></a>[mysqldump]</h2><h2 id="mysql"><a href="#mysql" class="headerlink" title="[mysql]"></a>[mysql]</h2><h2 id="myisamchk"><a href="#myisamchk" class="headerlink" title="[myisamchk]"></a>[myisamchk]</h2><h2 id="mysqlhotcopy"><a href="#mysqlhotcopy" class="headerlink" title="[mysqlhotcopy]"></a>[mysqlhotcopy]</h2>]]></content>
<categories>
<category> CS </category>
</categories>
<tags>
<tag> MySql </tag>
</tags>
</entry>
<entry>
<title>Docker</title>
<link href="/post/f5f9fa9b.html"/>
<url>/post/f5f9fa9b.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><p><img src="https://oss.luhuhu.cn/202406051137820.jpeg"></p><h1 id="Docker"><a href="#Docker" class="headerlink" title="Docker"></a>Docker</h1><h2 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h2><h3 id="镜像(Image)"><a href="#镜像(Image)" class="headerlink" title="镜像(Image)"></a>镜像(Image)</h3><blockquote><p><strong>Docker 镜像</strong> 是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像 <strong>不包含</strong> 任何动态数据,其内容在构建之后也不会被改变。</p></blockquote><h3 id="容器-Container"><a href="#容器-Container" class="headerlink" title="容器(Container)"></a>容器(Container)</h3><blockquote><p>镜像(<code>Image</code>)和容器(<code>Container</code>)的关系,就像是面向对象程序设计中的 <code>类</code> 和 <code>实例</code> 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。</p><p>容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的 <a href="https://en.wikipedia.org/wiki/Linux_namespaces">命名空间</a>。因此容器可以拥有自己的 <code>root</code> 文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。这种特性使得容器封装的应用比直接在宿主运行更加安全。也因为这种隔离的特性,很多人初学 Docker 时常常会混淆容器和虚拟机。</p><p>按照 Docker 最佳实践的要求,容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入操作,都应该使用 <a href="https://yeasy.gitbook.io/docker_practice/data_management/volume">数据卷(Volume)</a>、或者 <a href="https://yeasy.gitbook.io/docker_practice/data_management/bind-mounts">绑定宿主目录</a>,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。</p><p>数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此,使用数据卷后,容器删除或者重新运行之后,数据却不会丢失。</p></blockquote><h3 id="仓库"><a href="#仓库" class="headerlink" title="仓库"></a>仓库</h3><blockquote><p>镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,<a href="https://yeasy.gitbook.io/docker_practice/repository/registry">Docker Registry</a> 就是这样的服务。</p></blockquote>]]></content>
<categories>
<category> CS </category>
</categories>
<tags>
<tag> docker </tag>
</tags>
</entry>
<entry>
<title>Redis</title>
<link href="/post/bae4ff13.html"/>
<url>/post/bae4ff13.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="Redis"><a href="#Redis" class="headerlink" title="Redis"></a>Redis</h1><h2 id="主从及集群"><a href="#主从及集群" class="headerlink" title="主从及集群"></a>主从及集群</h2><ul><li>主从架构<ul><li>全量同步</li><li>增量同步</li></ul></li><li>集群分片</li></ul><h2 id="场景"><a href="#场景" class="headerlink" title="场景"></a>场景</h2><ul><li>缓存<ul><li>redis是基于内存的,读写速度比磁盘要快很多,并且贵很多。<strong>缓存在什么时候会更新,什么是缓存穿透</strong><br><img src="https://oss.luhuhu.cn/202407291040520.png" alt="redis缓存"></li></ul></li><li>分布式锁<ul><li>在微服务框架中,本地锁已经不能满足我们的需求,redis的高效可以很好的实现分布式锁功能(配合redission)。<strong>在redis集群中如何保障锁状态的一致性?单节点多服务器中的一致性问题?</strong><br><img src="https://oss.luhuhu.cn/202407291046913.png" alt="分布式锁"></li></ul></li><li>计数器<ul><li>Redis由于单线程执行命令的特性,实现计数器不会有锁的竞争</li></ul></li><li>消息队列<ul><li>在 简单场景中可以利用Redis实现消息队列功能,但是功能和性能都比不上正常的消息中间件Rocket MQ、Kafka等,不推荐实现</li></ul></li><li>实时系统<ul><li>高性能特性可与被用来构建实时系统,如抽奖、秒杀、排行榜等</li></ul></li></ul>]]></content>
<categories>
<category> CS </category>
</categories>
<tags>
<tag> redis </tag>
</tags>
</entry>
<entry>
<title>Vim</title>
<link href="/post/104c461b.html"/>
<url>/post/104c461b.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><p><img src="https://oss.luhuhu.cn/202406051149842.png"></p><h1 id="Vim"><a href="#Vim" class="headerlink" title="Vim"></a>Vim</h1><blockquote><p>《Vim Tutor》</p><p>《Viim 实用技巧》</p></blockquote><h2 id="Vim-Tutor"><a href="#Vim-Tutor" class="headerlink" title="Vim Tutor"></a>Vim Tutor</h2><h3 id="打开-保存-退出"><a href="#打开-保存-退出" class="headerlink" title="打开 保存 退出"></a>打开 保存 退出</h3><p><strong>在命令模式下</strong></p><table><thead><tr><th>命令</th><th>功能</th></tr></thead><tbody><tr><td>:e test.md</td><td>打开 test.md文件, 如果不存在则创建。</td></tr><tr><td>:w</td><td>保存</td></tr><tr><td>:w!</td><td>强制保存</td></tr><tr><td>:q</td><td>退出</td></tr><tr><td>:wq</td><td>保存并退出</td></tr><tr><td>:x</td><td>同:wq</td></tr><tr><td>:q!</td><td>强制退出 不保存并退出</td></tr><tr><td>hjkl</td><td>←↓↑→</td></tr></tbody></table><h3 id="删除和追加"><a href="#删除和追加" class="headerlink" title="删除和追加"></a>删除和追加</h3><table><thead><tr><th>命令</th><th>功能</th></tr></thead><tbody><tr><td>x</td><td>删除光标处的一个字符</td></tr><tr><td>a</td><td>追加文本</td></tr><tr><td>i</td><td>插入文本</td></tr></tbody></table><h3 id="关于对象的小清单"><a href="#关于对象的小清单" class="headerlink" title="关于对象的小清单"></a>关于对象的小清单</h3><table><thead><tr><th>命令</th><th>功能</th></tr></thead><tbody><tr><td>w</td><td>到下一个单词头,除开所在的第一个字符。</td></tr><tr><td>b</td><td>到上一个单词头,包括所在单词的第一个字符。</td></tr><tr><td>e</td><td>到下一个单词尾,包括所在单词的最后一个字符。</td></tr><tr><td>$</td><td>到行尾,包括了最后一个字符。</td></tr><tr><td>0</td><td>到行首,包含空格。</td></tr><tr><td>^</td><td>到行首,不含空格。</td></tr><tr><td>G</td><td>到文本最后一行首</td></tr><tr><td>gg</td><td>到文本首行。</td></tr></tbody></table><h3 id="恢复命令"><a href="#恢复命令" class="headerlink" title="恢复命令"></a>恢复命令</h3><table><thead><tr><th>命令</th><th>功能</th></tr></thead><tbody><tr><td>u</td><td>恢复之前的动作</td></tr><tr><td>U</td><td>恢复对一行的所有改变</td></tr><tr><td>CTRL+R</td><td>反恢复</td></tr></tbody></table><h3 id="删除操作"><a href="#删除操作" class="headerlink" title="删除操作"></a>删除操作</h3><table><thead><tr><th>命令</th><th>功能</th></tr></thead><tbody><tr><td>d</td><td>删除</td></tr><tr><td>dd</td><td>删除一行</td></tr><tr><td>d3w</td><td>删除三个词</td></tr></tbody></table><h3 id="粘贴"><a href="#粘贴" class="headerlink" title="粘贴"></a>粘贴</h3><table><thead><tr><th>命令</th><th>功能</th></tr></thead><tbody><tr><td>p</td><td>以在光标处粘贴先前删除的文本</td></tr><tr><td>r</td><td>替换</td></tr><tr><td>c</td><td>修改,功能等于删除单词并定位到插入模式。c 和 d 一样属于操作码</td></tr></tbody></table><h3 id="文件状态、光标定位"><a href="#文件状态、光标定位" class="headerlink" title="文件状态、光标定位"></a>文件状态、光标定位</h3><table><thead><tr><th>命令</th><th>功能</th></tr></thead><tbody><tr><td>Ctrl+G</td><td>查看文件状态及光标定位</td></tr><tr><td>100G</td><td>跳转到100行</td></tr></tbody></table><h3 id="搜索"><a href="#搜索" class="headerlink" title="搜索"></a>搜索</h3><table><thead><tr><th>命令</th><th>功能</th></tr></thead><tbody><tr><td>/keyword</td><td>搜索</td></tr><tr><td>?keyword</td><td>反向搜索</td></tr><tr><td>n</td><td>搜索下一条</td></tr><tr><td>N</td><td>搜索上一条</td></tr><tr><td>CTRL+o</td><td>搜索下一条</td></tr><tr><td>CTRL+i</td><td>搜索上一条</td></tr><tr><td>%</td><td>括号匹配搜索,可匹配 (,),[,],{ or },跳转到对应的起点/终点</td></tr></tbody></table><h3 id="替换命令"><a href="#替换命令" class="headerlink" title="替换命令"></a>替换命令</h3><table><thead><tr><th>命令</th><th>功能</th></tr></thead><tbody><tr><td>:s/old/new</td><td>替换本行第一个的</td></tr><tr><td>:s/old/new/g</td><td>替换本行所有的</td></tr><tr><td>:%s/old/new/g</td><td>更改全文件中的所有</td></tr><tr><td>:%s/old/new/gc</td><td>更改全文件中的所有,并给出替换与否的提示</td></tr><tr><td>:#,#s/old/new/g</td><td>#,#是要更改的行号的范围</td></tr></tbody></table><h3 id="外部命令"><a href="#外部命令" class="headerlink" title="外部命令"></a>外部命令</h3><table><thead><tr><th>命令</th><th>功能</th></tr></thead><tbody><tr><td>:!command</td><td>:!command 执行外部 shell 命令。例如 :!ls</td></tr><tr><td>:w FILENAME</td><td>将当前的vim 文件以FILENAME 文件名写进磁盘</td></tr><tr><td>v 对象 :w FILENAME</td><td>保存选定选择行到FILENAME 文件</td></tr><tr><td>:r FILENAME</td><td>恢复磁盘文件FILENAME到光标下</td></tr><tr><td>:r !ls</td><td>读取 ls 命令的输出并粘贴到光标下</td></tr></tbody></table><table><thead><tr><th>命令</th><th>功能</th></tr></thead><tbody><tr><td>o</td><td>在光标后插入一行,并进入插入模式</td></tr><tr><td>O</td><td>以在光标前插入一行</td></tr><tr><td>a</td><td>在光标后插入文本</td></tr><tr><td>A</td><td>在行尾插入文本</td></tr><tr><td>y</td><td>复制命令</td></tr><tr><td>p</td><td>粘贴命令</td></tr><tr><td>R</td><td>进入替换模式,直到按下</td></tr><tr><td>:set xxx</td><td>进入替换模式,直到按下</td></tr><tr><td>‘ic’ ‘ignorecase’</td><td>搜索时忽略大小写,例如 :set ic</td></tr><tr><td>‘is’ ‘incsearch’</td><td>部分显示匹配的搜索短语</td></tr><tr><td>‘hls’ ‘hlsearch’</td><td>高亮所有匹配的短语</td></tr><tr><td>:set noic</td><td>前置”no”以关闭选项</td></tr></tbody></table><table><thead><tr><th>命令</th><th>功能</th></tr></thead><tbody><tr><td>:help</td><td>或以打开帮助窗口</td></tr><tr><td>:help cmd</td><td>找出关于cmd的帮助</td></tr><tr><td>CTRL+w</td><td>跳转到另一窗口</td></tr><tr><td>:command, press CTRL+d</td><td>以查看可能的补齐</td></tr></tbody></table><h2 id="Vim实用技巧"><a href="#Vim实用技巧" class="headerlink" title="Vim实用技巧"></a>Vim实用技巧</h2><blockquote><p>. 命令会重复上次的操作</p></blockquote><table><thead><tr><th>命令</th><th>功能</th></tr></thead><tbody><tr><td>.</td><td>重复上次操作,是一个微型<strong>宏</strong></td></tr><tr><td>>G</td><td>全文缩进</td></tr><tr><td>A</td><td>=$a</td></tr><tr><td>f+<br>s + <br>;.</td><td>替换+前后增加空格<br>var foo = “method(“+argument1+”,”+argument2+”)”;<br>-><br>var foo = “method(“ + argument1 + “,” + argument2 + “)”;</td></tr><tr><td></td><td></td></tr></tbody></table>]]></content>
<categories>
<category> CS </category>
</categories>
<tags>
<tag> Vim </tag>
</tags>
</entry>
<entry>
<title>Armbian</title>
<link href="/post/589d671b.html"/>
<url>/post/589d671b.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="Armbian"><a href="#Armbian" class="headerlink" title="Armbian"></a>Armbian</h1><h2 id="硬件设备"><a href="#硬件设备" class="headerlink" title="硬件设备"></a>硬件设备</h2><p>hisense-hs530r<br>rk3399<br>4+16G</p><h2 id="软件"><a href="#软件" class="headerlink" title="软件"></a>软件</h2><ul><li><p>系统:Armbian_23.08.0-trunk_Hisense-hs530r_jammy_edge_6.5.5_xfce_desktop.img**[GUI]**</p></li><li><p>驱动:DriverAssitant_v5.12 <strong>只支持win10及以下</strong></p></li><li><p>刷机工具:海信可用Armbian_21.08.1_sm3399mb_focal_current_5.10.60</p></li></ul><h2 id="遇到的问题"><a href="#遇到的问题" class="headerlink" title="遇到的问题"></a>遇到的问题</h2><h3 id="谨慎更新"><a href="#谨慎更新" class="headerlink" title="谨慎更新"></a>谨慎更新</h3><p>系统安装完成之后第一时间update + upgrade之后reboot发现无法进入系统,屏幕花屏,需要强制重新刷机</p><hr><p><a href="https://www.right.com.cn/forum/thread-8354223-1-1.html">armbian系统不能随便更新</a> 即apt-get update + upgrade</p><p><img src="https://oss.luhuhu.cn/202405121600507.png" alt="image-20240512160037300"></p><p>做的一些工作:初始化系统之后将现有的所有待更新包屏蔽自动更新,经过实测update+upgrade已经可以reboot二次进系统</p><pre class=" language-bash"><code class="language-bash"><span class="token comment" spellcheck="true"># 装机完成之后查看可更新包</span>root@hisense-hs530r:~<span class="token comment" spellcheck="true"># apt list --upgradable</span>Listing<span class="token punctuation">..</span>. Donearmbian-config/jammy,jammy 23.8.3 all <span class="token punctuation">[</span>upgradable from: 23.08.0-trunk<span class="token punctuation">]</span>armbian-firmware/jammy,jammy 23.8.3 all <span class="token punctuation">[</span>upgradable from: 23.08.0-trunk<span class="token punctuation">]</span>armbian-jammy-desktop-xfce/jammy,jammy 23.8.1 all <span class="token punctuation">[</span>upgradable from: 23.08.0-trunk<span class="token punctuation">]</span>armbian-plymouth-theme/jammy,jammy 23.8.3 all <span class="token punctuation">[</span>upgradable from: 23.08.0-trunk<span class="token punctuation">]</span>armbian-zsh/jammy,jammy 23.8.3 all <span class="token punctuation">[</span>upgradable from: 23.08.0-trunk<span class="token punctuation">]</span>base-files/jammy 23.8.3-jammy arm64 <span class="token punctuation">[</span>upgradable from: 23.08.0-trunk-jammy<span class="token punctuation">]</span>fake-ubuntu-advantage-tools/jammy,jammy 23.8.3 all <span class="token punctuation">[</span>upgradable from: 23.08.0-trunk<span class="token punctuation">]</span>linux-dtb-edge-rockchip64/jammy 23.8.1 arm64 <span class="token punctuation">[</span>upgradable from: 23.08.0-trunk<span class="token punctuation">]</span>linux-image-edge-rockchip64/jammy 23.8.1 arm64 <span class="token punctuation">[</span>upgradable from: 23.08.0-trunk<span class="token punctuation">]</span>linux-libc-dev/jammy 23.02.2 arm64 <span class="token punctuation">[</span>upgradable from: 5.15.0-86.96<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># 禁止这些包的自动更新</span><span class="token function">sudo</span> apt-mark hold armbian-config<span class="token function">sudo</span> apt-mark hold armbian-firmware<span class="token function">sudo</span> apt-mark hold armbian-jammy-desktop-xfce<span class="token function">sudo</span> apt-mark hold armbian-plymouth-theme<span class="token function">sudo</span> apt-mark hold armbian-zsh<span class="token function">sudo</span> apt-mark hold base-files<span class="token function">sudo</span> apt-mark hold fake-ubuntu-advantage-tools<span class="token function">sudo</span> apt-mark hold linux-dtb-edge-rockchip64<span class="token function">sudo</span> apt-mark hold linux-image-edge-rockchip64<span class="token function">sudo</span> apt-mark hold linux-libc-dev</code></pre><h3 id="存储扩容"><a href="#存储扩容" class="headerlink" title="存储扩容"></a>存储扩容</h3><p>自带的存储大小为16G,想要通过插外置存储扩容root分区</p><hr><p>在实际操作中发现并未使用lvm管理磁盘,即<code>mmcblk0</code>未建pv,而pv的创建需要格式化磁盘,因此无法通过lvm 逻辑卷手段扩容root分区,目前没有找到办法直接扩容,磁盘挂载等内容参考Linux LVM相关</p><pre class=" language-bash"><code class="language-bash">root@hisense-hs530r:~<span class="token comment" spellcheck="true"># lsblk</span>NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTSsda 8:0 1 116.7G 0 diskmmcblk0 179:0 0 14.6G 0 disk└─mmcblk0p1 179:1 0 14.4G 0 part /var/log.hdd /mmcblk0boot0 179:32 0 4M 1 diskmmcblk0boot1 179:64 0 4M 1 diskzram0 252:0 0 1.9G 0 disk <span class="token punctuation">[</span>SWAP<span class="token punctuation">]</span>zram1 252:1 0 50M 0 disk /var/logzram2 252:2 0 0B 0 diskroot@hisense-hs530r:~<span class="token comment" spellcheck="true"># pvdisplay</span> --- Physical volume --- PV Name /dev/sda VG Name myVG PV Size <span class="token operator"><</span>116.70 GiB / not usable 4.00 MiB Allocatable <span class="token function">yes</span> <span class="token punctuation">(</span>but full<span class="token punctuation">)</span> PE Size 4.00 MiB Total PE 29874 Free PE 0 Allocated PE 29874 PV UUID PceY81-pM6c-SGma-mKGN-gdWY-5urX-7petarroot@hisense-hs530r:~<span class="token comment" spellcheck="true"># vgdisplay</span> --- Volume group --- VG Name myVG System ID Format lvm2 Metadata Areas 1 Metadata Sequence No 5 VG Access read/write VG Status resizable MAX LV 0 Cur LV 1 Open LV 0 Max PV 0 Cur PV 1 Act PV 1 VG Size <span class="token operator"><</span>116.70 GiB PE Size 4.00 MiB Total PE 29874 Alloc PE / Size 29874 / <span class="token operator"><</span>116.70 GiB Free PE / Size 0 / 0 VG UUID dYVDgP-a9OF-vBmt-sE7V-egwC-f5rJ-LSaXVVroot@hisense-hs530r:~<span class="token comment" spellcheck="true"># lvdisplay</span> --- Logical volume --- LV Path /dev/myVG/lvol0 LV Name lvol0 VG Name myVG LV UUID MM3o5D-gNWh-M4NH-ik3J-tqH9-OrFw-KMSr0x LV Write Access read/write LV Creation host, <span class="token function">time</span> hisense-hs530r, 2024-05-12 02:49:59 +0800 LV Status NOT available LV Size <span class="token operator"><</span>116.70 GiB Current LE 29874 Segments 1 Allocation inherit Read ahead sectors auto</code></pre><h3 id="wifi信号差"><a href="#wifi信号差" class="headerlink" title="wifi信号差"></a>wifi信号差</h3><p>没有天线,无线信号很差,建议自增天线或者使用有线</p><h2 id="杂项"><a href="#杂项" class="headerlink" title="杂项"></a>杂项</h2><h3 id="命令行颜色"><a href="#命令行颜色" class="headerlink" title="命令行颜色"></a>命令行颜色</h3><pre class=" language-bash"><code class="language-bash">root@hisense-hs530r:~<span class="token comment" spellcheck="true"># vi ~/.bashrc</span><span class="token operator">==</span><span class="token operator">==</span><span class="token comment" spellcheck="true"># force_color_prompt=yes 去掉该行的注释</span><span class="token operator">==</span><span class="token operator">==</span>root@hisense-hs530r:~<span class="token comment" spellcheck="true"># source ~/.bashrc</span></code></pre><p><img src="https://oss.luhuhu.cn/202405121616398.png" alt="命令行颜色效果图"></p>]]></content>
<categories>
<category> CS </category>
</categories>
<tags>
<tag> armbian </tag>
</tags>
</entry>
<entry>
<title>KTV记事</title>
<link href="/post/c97e3aa1.html"/>
<url>/post/c97e3aa1.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="KTV记事"><a href="#KTV记事" class="headerlink" title="KTV记事"></a>KTV记事</h1><p>应邀去了ktv (也是自己想去喝点酒唱唱歌),不会胸腔发声,把喉咙唱疲惫。</p><p>先后发生了些许事情,简单记录下<br>我老婆要在家里看小孩儿,且对于这类局也是兴趣缺缺,所以我就是一个人去赴约了。nkt开玩笑似得问我要不要叫swy,我觉得有点怪,与她的关系可能比同事稍多那两杯咖啡的交情,也聊的来一些天,但跟朋友的关系差着还远,倒不是说抗拒她来,而是怕如果出现一些状况,在场又只有我一个人熟悉,我一个家里老婆陪着娃自己出来唱歌的人,进退失度,所以她要是带着男朋友来,于我才是安全的,但是她如果带着男朋友来,又要她来做甚?</p><p>有个柯桥的老板跟伟哥喝酒,我过去给倒。nkt跟我说不用给人倒酒,我不是很理解,我想了很多可能的原因,但是也不能确认。我觉得听他的不会有错。</p><p>szxg的老板娘我见过,但是她应该是并不认得我,早早的回家了。<br>nkt说:“按理说,相互介绍认识,你应当叫过来一起聊个天随便说些什么,不至于把气氛搞尴尬。”我没有这个意识,猜大概她是单个来的,我也是单个来的缘故?有些许逢场作戏的味道?<br>我不认为nkt说的有什么不对,我不应当让人觉得拘束,但是事实就是我让人感觉拘谨、尴尬。我回nkt:“我不知道要同她说些什么,也不能把握这个尺度,所以我不会去做这个事情”。礼貌令人尴尬,冒犯又显得低级。<br>让我想起几天前看到的一段话:有的人,喜欢想的多且深刻,但表现得无动于衷,高知而低能。大抵说的就是我这种吧。<br>syw拉着我胡言乱语了许多话,我接不大上,不晓得他在同我说些什么,到最后我才听懂他的腰椎突出、身体不好全来自于我给人的拘束感,他想要我松快一些、自然一些。辛苦伟哥,心存感激。</p><p>在面对陌生人的时候,我倾向于观察、揣测他的社交边界,有了初步的判断之后才会有进一步的沟通交涉尝试。但我又是一个极无聊的人,总不能与人聊些最近看了哪些书、有哪些新鲜的观点,聊些深刻的话题,发表一些中年愤青的愤世嫉俗,扫了人来寻开心的兴致。对于他们尝试与你沟通的努力,又会被我判断成胡言乱语(syw),不知道要回些什么,给人一种特别难搞的样子,使气氛凝固。其实我自己很自在,只是给别人带去了不自在的感受,这个是他们自己产生的感受,却是我带去的,我不能说我全无责任。冷场光环,怎么办还不知道。</p><p>syw说,出来玩80%的时候是为了快乐,20%是带着目的、任务。我出来玩100%为了快乐,从也不愿也无能出售自己的情绪价值。期间加了一个人的微信,还是人主动加我的,身份高,我是凭着开裆裤情分才与他有了交集,一个高冷的臭搬砖的(码农)。让我想起《人民的名义》里面一段对话,高育良让祁同伟多去陈岩石家,告诉他要烧冷锅,祁厅长不去,但是沙瑞金一来,祁厅长就上赶着给人犁地种菜去了。我好像做不了锅炉工,上进心不足、努力程度不够,显得有一些痴傻,如此这般就是遇见贵人,也是留不下一些印象。我认为归根到底我内心是不认同这种功利思想的。</p><p>中间玩了一个叫做婊子游戏的游戏,有撕纸巾、真心话、大冒险等活动的综合体,对这类游戏我其实早有我自己的判断——不适合。我脑测这类游戏核心的玩法在于年轻人之间近距离的眼神交互,从而摩擦出一些火花已增进关系,于我这种已婚已育的中年人,道德和法律已从精神层面将自我绝育,自我抑制了荷尔蒙分泌,通过这类游戏可以看到我真正拘谨的样子,我是一个严肃且无自控力的人。不过好在,我的左边右边都坐着我熟悉的人,不管是不是刻意的保护,都感恩。syw总是表现的神经很大条,无动机的扮丑是对身边人最大的体贴,大冒险游戏对lsw说我爱你,送了台阶过去,聪明体贴。玩儿这个游戏的时候,我感受到了大家形态各异的拘谨。</p><p>lsw带了女朋友过来,叫做66。我在散场之后跟nkt说lsw品味有点差,我失言了。在并不了解全貌的情况下,但从2个小时不到的时间里,把她定了调。她表现的很卑微,外溢的曲意逢迎,与在场的其他正女主相较,有种现实的低级感。人有欲望、动机并不是什么坏事情,但是如果那种迫切感让人察觉到,总让人感觉好像很便宜,虽说这其实也是人努力强烈的一种表现,但终归是看上去用力过猛,不太舒服。</p><p>散场之后,xyh回百合了,nkt说随她去,细微的不悦,想来应该是婆媳间的那点事情,也不多嘴问。望平安</p><p>快乐的一天。</p><p>2024年5月2日</p>]]></content>
<categories>
<category> 杂文 </category>
</categories>
<tags>
<tag> 手记 </tag>
</tags>
</entry>
<entry>
<title>Linux</title>
<link href="/post/53d0684b.html"/>
<url>/post/53d0684b.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><p><img src="https://oss.luhuhu.cn/202406051153791.png"></p><h1 id="Linux"><a href="#Linux" class="headerlink" title="Linux"></a>Linux</h1><blockquote><p>GNU宣言<br>“我认为:如果我喜欢一个程序的话,那我就应该将它分享给其他喜欢这个程序的人<br>这句话是我的座右铭。软件商想各个击破用户,使他们同意不把软件和他人分享。我拒绝以<br>这种方式破坏用户之间的团结。我的良心使我不会签下一个不开放的合约或是软件许可证协<br>议,在麻省理工学院人工智能实验室工作的多年时间里,我一直反对这样的趋势与冷漠,但<br>是最后事情槽糕到:我无法在一个处理事情的方法与我的意愿相违背的机构呆下去,”<br>“为了能继续使用电脑而不感到羞愧,我决定将一大堆自由软件集合在一起,从而使<br>我可以不必再使用不自由的软件。因此,我辞去了人工智能实验室的工作,不给麻省理工<br>学院任何法律上的借口来阻止我把GNU送给其他人…”<br>“很多程序员对系统软件的商业化感到不悦。这虽然可以使他们赚更多的线,但是这<br>使他们觉得自己与其他程序员处于对立状态,而不是同志之间的感觉。程序员对友谊的最<br>基本表现就是共享程序,而当前的市场运作基本上禁止程序员将其他程序员作为朋友看待,<br>软件购买者必须在友谊和守法之间做一选择。自然地,有很多人选择了友谊。但是那些相<br>信法律的人常常没办法安心地做这一选择。他们会变得愤世嫉俗,认为写程序只不过是赚<br>钱的一种方法而已。”<br>“复制全部或者部分程序对程序员来说就和呼吸一样是自然有益的事。复制软件就应<br>该这么自由…”<br>“从长远来看,免贵提供软件是迈向大同世界的一步,在那个时代中,没有人再为了生<br>计而努力工作。在每周10小时的必要劳动(如立法、家政服务、机器人修理和行星观察)之后,<br>人们自由地参与各种自己感兴趣的活动,例如编程。那时候就不必靠写程序来过活了…”</p></blockquote><p>《Linux命令与shell脚本变成大全》第四版</p><p>《Unix&Linux大学教程》</p><h2 id="什么是Linux"><a href="#什么是Linux" class="headerlink" title="什么是Linux"></a>什么是Linux</h2><p>Unix是一种多用户、多任务处理的操作系统;</p><p>Linux是任何使用Linux内核的Unix的操作系统</p><h2 id="文件管理系统"><a href="#文件管理系统" class="headerlink" title="文件管理系统"></a>文件管理系统</h2><h3 id="日志文件系统"><a href="#日志文件系统" class="headerlink" title="日志文件系统"></a>日志文件系统</h3><ul><li>ex4,最大支持16T,默认有序模式,支持加密压缩及单目录不限数量的子目录</li><li>XFS,回写模式的日志方法,高性能但是存在风险,因为实际数据并未存入日志文件</li></ul><h3 id="文件系统的使用"><a href="#文件系统的使用" class="headerlink" title="文件系统的使用"></a>文件系统的使用</h3><h4 id="创建分区"><a href="#创建分区" class="headerlink" title="创建分区"></a>创建分区</h4><ul><li>fdisk,只能处理2T以下的硬盘</li><li>gdisk,如果存储设备要使用GUID分区表,就需要用到gdisk</li><li>GNU parted,允许调整现有分区大小,可以收缩或者扩大磁盘分区</li></ul><h4 id="创建文件系统(格式化)"><a href="#创建文件系统(格式化)" class="headerlink" title="创建文件系统(格式化)"></a>创建文件系统(格式化)</h4><ul><li><p>mkfs.ext4</p><pre class=" language-bash"><code class="language-bash"><span class="token comment" spellcheck="true"># 创建挂载点</span><span class="token function">mkdir</span> /home/data<span class="token comment" spellcheck="true"># 挂载磁盘</span><span class="token function">mount</span> -t ext4 /dev/sda /home/datalsblk -f /dev /sda<span class="token comment" spellcheck="true"># 自动挂载</span>etc/fstab</code></pre></li><li><p>mkfs.xfs</p></li><li><p>mkfs.btrfs</p></li></ul><h3 id="卷文件系统"><a href="#卷文件系统" class="headerlink" title="卷文件系统"></a>卷文件系统</h3><p>从一个或多个磁盘创建存储池提供了生成虚拟磁盘(卷)的能力,通过存储池可以根据需要增加卷,提供灵活性的同时大大减少停机时间</p><ul><li>ZFS文件系统</li><li>Btrfs</li><li>Stratis</li></ul><h4 id="LVM"><a href="#LVM" class="headerlink" title="LVM"></a>LVM</h4><ul><li><p>LVM布局</p><ul><li><p>物理卷(PV),指定一个未使用的磁盘分区或整个驱动由LVM使用</p></li><li><p>卷组(VG)(VG),用于将PV加入存储池,用于构建各种逻辑卷(LV)</p></li><li><p>逻辑卷(LV),<strong>核心步骤</strong>,由VG的存储空间块组成,可以使用文件系统格式化LV,且不能跨VG创建。当数据量超过已有文件系统上限时,只能在同一个物理磁盘内调整分区大小,逻辑卷(LV)就是用来将<strong>另外一块硬盘上的分区加入已有的文件系统来动态添加存储空间的工具</strong></p></li></ul></li></ul><h4 id="Linux中的LVM"><a href="#Linux中的LVM" class="headerlink" title="Linux中的LVM"></a>Linux中的LVM</h4><p>Linux中通过lvm2软件管理LVM</p><h5 id="首次设置逻辑卷-LV-步骤"><a href="#首次设置逻辑卷-LV-步骤" class="headerlink" title="首次设置逻辑卷(LV)步骤"></a>首次设置逻辑卷(LV)步骤</h5><blockquote><ol><li>创建物理卷(PV)</li><li>创建卷组(VG)</li><li>创建逻辑卷(LV)</li><li>格式化逻辑卷(LV)</li><li>挂载逻辑卷(LV)</li><li>VG、LV扩缩容</li></ol></blockquote><h5 id="示例"><a href="#示例" class="headerlink" title="示例"></a>示例</h5><ul><li><p>命令行清单</p><pre class=" language-bash"><code class="language-bash"><span class="token comment" spellcheck="true"># 命令行帮助</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># lvm help <command></span><span class="token comment" spellcheck="true"># 查看硬盘情况</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># lsblk</span><span class="token comment" spellcheck="true"># 1. 创建物理卷(PV)</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># pvcreate /dev/vdb /dev/vdc</span><span class="token comment" spellcheck="true"># 2. 创建卷(VG)组包含vdb、vdc</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># vgcreate vg00 /dev/vdb /dev/vdc</span><span class="token comment" spellcheck="true"># 3.创建逻辑卷(LV)</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># lvcreate -L 1g -v vg00</span><span class="token comment" spellcheck="true"># 4.1 格式化逻辑卷(LV)</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># mkfs.ext4 /dev/vg00/lvol0</span><span class="token comment" spellcheck="true"># 4.2 挂载LV</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># mkdir my_LV</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># mount -t ext4 /dev/vg00/lvol0 my_LV</span><span class="token comment" spellcheck="true"># 容量变更</span><span class="token comment" spellcheck="true"># 查看vg详细信息,VG中LV、PV信息</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># vgdisplay -v <vg00></span><span class="token comment" spellcheck="true"># VG缩扩PV</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># vgreduce vg00 /dev/vdc</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># vgextend vg00 /dev/vdc</span><span class="token comment" spellcheck="true"># LV缩扩容量,只能使用所归属的VG容量</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># lvextend -L 10G /dev/mapper/vg00-lvol0</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># lvextend -l +100%FREE /dev/mapper/vg00-lvol0</span><span class="token comment" spellcheck="true"># 刷新磁盘空间ext4 和xfs格式</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># resize2fs /dev/mapper/vg00-lvol0</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># xfs_growfs /dev/mapper/vg00-lvol0</span></code></pre></li><li><p>命令行及返回</p><pre class=" language-bash"><code class="language-bash"><span class="token comment" spellcheck="true"># 查看硬盘情况</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># lsblk</span>NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTfd0 2:0 1 4K 0 disksr0 11:0 1 490.2M 0 rom /mediavda 252:0 0 40G 0 disk├─vda1 252:1 0 1G 0 part /boot└─vda2 252:2 0 39G 0 part ├─centos-root 253:0 0 35.1G 0 lvm / └─centos-swap 253:1 0 3.9G 0 lvm <span class="token punctuation">[</span>SWAP<span class="token punctuation">]</span>vdb 252:16 0 100G 0 diskvdc 252:32 0 1G 0 disk<span class="token comment" spellcheck="true"># 1. 创建物理卷(PV)</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># pvcreate /dev/vdb /dev/vdc</span> Physical volume <span class="token string">"/dev/vdb"</span> successfully created. Physical volume <span class="token string">"/dev/vdc"</span> successfully created.<span class="token comment" spellcheck="true"># 2. 创建卷组(VG)包含vdb、vdc</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># vgcreate vg00 /dev/vdb /dev/vdc</span> Volume group <span class="token string">"vg00"</span> successfully created<span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># vgdisplay</span> --- Volume group --- VG Name centos<span class="token punctuation">..</span>. --- Volume group --- VG Name vg00 System ID Format lvm2 Metadata Areas 2 Metadata Sequence No 1 VG Access read/write VG Status resizable MAX LV 0 Cur LV 0 Open LV 0 Max PV 0 Cur PV 2 Act PV 2 VG Size 100.99 GiB PE Size 4.00 MiB Total PE 25854 Alloc PE / Size 0 / 0 Free PE / Size 25854 / 100.99 GiB VG UUID 4sQhAV-ES7y-rQBe-PJLo-7PuO-479o-Y6T9sn<span class="token comment" spellcheck="true"># 3.创建逻辑卷(LV)</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># lvcreate -L 1g -v vg00</span> Archiving volume group <span class="token string">"vg00"</span> metadata <span class="token punctuation">(</span>seqno 1<span class="token punctuation">)</span>. Creating logical volume lvol0 Creating volume group backup <span class="token string">"/etc/lvm/backup/vg00"</span> <span class="token punctuation">(</span>seqno 2<span class="token punctuation">)</span>. Activating logical volume vg00/lvol0. activation/volume_list configuration setting not defined: Checking only host tags <span class="token keyword">for</span> vg00/lvol0. Creating vg00-lvol0 Loading table <span class="token keyword">for</span> vg00-lvol0 <span class="token punctuation">(</span>253:2<span class="token punctuation">)</span>. Resuming vg00-lvol0 <span class="token punctuation">(</span>253:2<span class="token punctuation">)</span>. Wiping known signatures on logical volume <span class="token string">"vg00/lvol0"</span> Initializing 4.00 KiB of logical volume <span class="token string">"vg00/lvol0"</span> with value 0. Logical volume <span class="token string">"lvol0"</span> created.<span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># lvdisplay /dev/vg00/lvol0</span> --- Logical volume --- LV Path /dev/vg00/lvol0 LV Name lvol0 VG Name vg00 LV UUID bT0lhQ-vHVn-TXPc-9TxH-C7eU-AI8d-8FXJfw LV Write Access read/write LV Creation host, <span class="token function">time</span> localhost.localdomain, 2024-05-11 10:02:51 +0800 LV Status available <span class="token comment" spellcheck="true"># open 0</span> LV Size 1.00 GiB Current LE 256 Segments 1 Allocation inherit Read ahead sectors auto - currently <span class="token keyword">set</span> to 8192 Block device 253:2<span class="token comment" spellcheck="true"># 4.1 格式化逻辑卷(LV)</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># mkfs.ext4 /dev/vg00/lvol0</span>mke2fs 1.42.9 <span class="token punctuation">(</span>28-Dec-2013<span class="token punctuation">)</span>Filesystem label<span class="token operator">=</span>OS type: LinuxBlock size<span class="token operator">=</span>4096 <span class="token punctuation">(</span>log<span class="token operator">=</span>2<span class="token punctuation">)</span>Fragment size<span class="token operator">=</span>4096 <span class="token punctuation">(</span>log<span class="token operator">=</span>2<span class="token punctuation">)</span>Stride<span class="token operator">=</span>0 blocks, Stripe width<span class="token operator">=</span>0 blocks65536 inodes, 262144 blocks13107 blocks <span class="token punctuation">(</span>5.00%<span class="token punctuation">)</span> reserved <span class="token keyword">for</span> the super userFirst data block<span class="token operator">=</span>0Maximum filesystem blocks<span class="token operator">=</span>2684354568 block <span class="token function">groups</span>32768 blocks per group, 32768 fragments per group8192 inodes per groupSuperblock backups stored on blocks: 32768, 98304, 163840, 229376Allocating group tables: <span class="token keyword">done</span>Writing inode tables: <span class="token keyword">done</span>Creating journal <span class="token punctuation">(</span>8192 blocks<span class="token punctuation">)</span>: <span class="token keyword">done</span>Writing superblocks and filesystem accounting information: <span class="token keyword">done</span><span class="token comment" spellcheck="true"># 4.2 挂载LV</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># mkdir my_LV</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># mount -t ext4 /dev/vg00/lvol0 my_LV</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># ls my_LV/</span>lost+found<span class="token comment" spellcheck="true"># 4.3 扩容、收缩VG&LV</span><span class="token comment" spellcheck="true"># 查看VG下的pv内容</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># vgdisplay -v <vg00></span> --- Volume group --- VG Name vg00 System ID Format lvm2 Metadata Areas 2 Metadata Sequence No 6 VG Access read/write VG Status resizable MAX LV 0 Cur LV 1 Open LV 1 Max PV 0 Cur PV 2 Act PV 2 VG Size 100.99 GiB PE Size 4.00 MiB Total PE 25854 Alloc PE / Size 1280 / 5.00 GiB Free PE / Size 24574 / 95.99 GiB VG UUID 4sQhAV-ES7y-rQBe-PJLo-7PuO-479o-Y6T9sn --- Logical volume --- LV Path /dev/vg00/lvol0 LV Name lvol0 VG Name vg00 LV UUID bT0lhQ-vHVn-TXPc-9TxH-C7eU-AI8d-8FXJfw LV Write Access read/write LV Creation host, <span class="token function">time</span> localhost.localdomain, 2024-05-11 10:02:51 +0800 LV Status available <span class="token comment" spellcheck="true"># open 1</span> LV Size 5.00 GiB Current LE 1280 Segments 1 Allocation inherit Read ahead sectors auto - currently <span class="token keyword">set</span> to 8192 Block device 253:2 --- Physical volumes --- PV Name /dev/vdb PV UUID pC2xLf-UvnW-I4zy-3pq6-d93H-7Ff8-bc2O9o PV Status allocatable Total PE / Free PE 25599 / 24319 PV Name /dev/vdc PV UUID UrrpAy-wgq3-cBF0-oWND-tdwp-E3FV-cfgA1d PV Status allocatable Total PE / Free PE 255 / 255<span class="token comment" spellcheck="true"># VG缩扩PV</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># vgreduce vg00 /dev/vdc</span> Removed <span class="token string">"/dev/vdc"</span> from volume group <span class="token string">"vg00"</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># vgextend vg00 /dev/vdc</span> Volume group <span class="token string">"vg00"</span> successfully extended<span class="token comment" spellcheck="true"># LV缩扩容量,只能使用所归属的VG容量</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># lvextend -L 10G /dev/mapper/vg00-lvol0</span> Size of logical volume vg00/lvol0 changed from 1.00 GiB <span class="token punctuation">(</span>256 extents<span class="token punctuation">)</span> to 10.00 GiB <span class="token punctuation">(</span>2560 extents<span class="token punctuation">)</span>. Logical volume vg00/lvol0 successfully resized.<span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># lvextend -l 100%FREE /dev/mapper/vg00-lvol0</span><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># lvreduce -L 5G /dev/mapper/vg00-lvol0</span> WARNING: Reducing active and <span class="token function">open</span> logical volume to 5.00 GiB. THIS MAY DESTROY YOUR DATA <span class="token punctuation">(</span>filesystem etc.<span class="token punctuation">)</span>Do you really want to reduce vg00/lvol0? <span class="token punctuation">[</span>y/n<span class="token punctuation">]</span>: y Size of logical volume vg00/lvol0 changed from 10.00 GiB <span class="token punctuation">(</span>2560 extents<span class="token punctuation">)</span> to 5.00 GiB <span class="token punctuation">(</span>1280 extents<span class="token punctuation">)</span>. Logical volume vg00/lvol0 successfully resized.</code></pre></li></ul><h2 id="实战"><a href="#实战" class="headerlink" title="实战"></a>实战</h2><h3 id="本地yum源"><a href="#本地yum源" class="headerlink" title="本地yum源"></a><a href="https://blog.itpub.net/70004783/viewspace-2790196/">本地yum源</a></h3><ol><li><p>系统环境</p><pre class=" language-bash"><code class="language-bash"><span class="token punctuation">[</span>root@localhost repo<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># cat /etc/redhat-release</span>CentOS Linux release 7.9.2009 <span class="token punctuation">(</span>Core<span class="token punctuation">)</span></code></pre></li><li><p>防火墙&SELinux</p><pre class=" language-bash"><code class="language-bash"><span class="token comment" spellcheck="true"># 开启防火墙80端口</span><span class="token punctuation">[</span>root@yumserver ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># firewall-cmd --add-port=80/tcp --permanent </span>success<span class="token punctuation">[</span>root@yumserver ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># firewall-cmd --reload</span>success<span class="token comment" spellcheck="true"># 临时关闭、开启SElinux</span>setenforce 0setenforce 1<span class="token comment" spellcheck="true"># 永久关闭SELinnux</span><span class="token punctuation">[</span>root@yumserver ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># cat /etc/selinux/config </span><span class="token comment" spellcheck="true"># This file controls the state of SELinux on the system.</span><span class="token comment" spellcheck="true"># SELINUX= can take one of these three values:</span><span class="token comment" spellcheck="true"># enforcing - SELinux security policy is enforced.</span><span class="token comment" spellcheck="true"># permissive - SELinux prints warnings instead of enforcing.</span><span class="token comment" spellcheck="true"># disabled - No SELinux policy is loaded.</span>SELINUX<span class="token operator">=</span>disabled<span class="token comment" spellcheck="true"># SELINUXTYPE= can take one of three values:</span><span class="token comment" spellcheck="true"># targeted - Targeted processes are protected,</span><span class="token comment" spellcheck="true"># minimum - Modification of targeted policy. Only selected processes are protected. </span><span class="token comment" spellcheck="true"># mls - Multi Level Security protection.</span>SELINUXTYPE<span class="token operator">=</span>targeted</code></pre></li><li><p>添加阿里云yum源</p><pre class=" language-bash"><code class="language-bash"><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># cd /etc/yum.repos.d/</span><span class="token punctuation">[</span>root@localhost yum.repos.d<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># ls</span>bak bakcup CentOS-Base.repo epel.repo<span class="token comment" spellcheck="true"># 获取阿里云yum配置文件</span>curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repocurl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repoyum makecacheyum repolist</code></pre></li><li><p>安装同步软件</p><p>yum-utils:reposync同步工具</p><p>createrepo:编辑yum库工具</p><p>httpd:通过Apache软件提供web服务</p><pre class=" language-bash"><code class="language-bash">yum <span class="token function">install</span> -y <span class="token function">wget</span> <span class="token function">make</span> cmake gcc gcc-c++ pcre-devel zlib-devel openssl openssl-devel httpd yum-utils createrepo</code></pre></li><li><p>同步阿里云yum源到本地指定目录/mirror</p><pre class=" language-bash"><code class="language-bash"><span class="token function">mkdir</span> -p /mirror<span class="token function">chown</span> -R apache:apache /mirror<span class="token function">chmod</span> -R 755 /mirror<span class="token comment" spellcheck="true">###参数-n指下载最新软件包,-p指定目录,指定本地的源--repoid(如果不指定就同步本地服务器所有的源),下载过程比较久</span>reposync -n --repoid<span class="token operator">=</span>extras --repoid<span class="token operator">=</span>updates --repoid<span class="token operator">=</span>base --repoid<span class="token operator">=</span>epel -p /mirror<span class="token punctuation">[</span>root@yumserver ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># du -sh /mirror/*</span>9.0G /mirror/base16G /mirror/epel321M /mirror/extras2.2G /mirror/updates</code></pre></li><li><p>创建仓库索引</p><pre class=" language-bash"><code class="language-bash">createrepo -po /mirror/base/ /mirror/base/createrepo -po /mirror/extras/ /mirror/extras/createrepo -po /mirror/updates/ /mirror/updates/createrepo -po /mirror/epel/ /mirror/epel/</code></pre><ol start="7"><li>更新数据源</li></ol><pre class=" language-bash"><code class="language-bash">createrepo --update /mirror/base/createrepo --update /mirror/extras/createrepo --update /mirror/updates/createrepo --update /mirror/epel/</code></pre><ol start="8"><li>启动httpd及增加对应配置</li></ol><pre class=" language-bash"><code class="language-bash">systemctl start httpdsystemctl <span class="token function">enable</span> httpdsystemctl status httpd<span class="token punctuation">[</span>root@yumserver ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># vim /etc/httpd/conf/httpd.conf</span><span class="token comment" spellcheck="true">### 增加以下配置</span><span class="token punctuation">..</span>.DocumentRoot <span class="token string">"/mirror/"</span><span class="token operator"><</span>Directory <span class="token string">"/mirror/"</span><span class="token operator">></span> Options Indexes FollowSymLinks AllowOverride None Order allow,deny Allow from all Require all granted<span class="token operator"><</span>/Directory<span class="token operator">></span><span class="token punctuation">..</span>.</code></pre><ol start="9"><li>更新index.html</li></ol><pre class=" language-bash"><code class="language-bash"><span class="token function">cat</span> <span class="token operator"><<</span> EOF <span class="token operator">></span> /usr/share/httpd/noindex/index.html<span class="token operator"><</span><span class="token operator">!</span>DOCTYPE html<span class="token operator">></span><span class="token operator"><</span>html<span class="token operator">></span><span class="token operator"><</span>head<span class="token operator">></span><span class="token operator"><</span>meta charset<span class="token operator">=</span><span class="token string">"utf-8"</span><span class="token operator">></span><span class="token operator"><</span>title<span class="token operator">></span>CentOS 7 镜像<span class="token operator"><</span>/title<span class="token operator">></span><span class="token operator"><</span>script<span class="token operator">></span>document.createElement<span class="token punctuation">(</span><span class="token string">"myHero"</span><span class="token punctuation">)</span><span class="token operator"><</span>/script<span class="token operator">></span><span class="token operator"><</span>style<span class="token operator">></span>myHero <span class="token punctuation">{</span> display: block<span class="token punctuation">;</span> background-color: <span class="token comment" spellcheck="true">#ddd;</span> padding: 10px<span class="token punctuation">;</span> font-size: 20px<span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token operator"><</span>/style<span class="token operator">></span> <span class="token operator"><</span>/head<span class="token operator">></span><span class="token operator"><</span>body<span class="token operator">></span> <span class="token operator"><</span>h1<span class="token operator">></span>简介<span class="token operator"><</span>/h1<span class="token operator">></span> <span class="token operator"><</span>hr<span class="token operator">></span> <span class="token operator"><</span>p<span class="token operator">></span>CentOS,是基于 Red Hat Linux 提供的可自由使用源代码的企业级 Linux 发行版本。<span class="token operator"><</span>/p<span class="token operator">></span> <span class="token operator"><</span>hr<span class="token operator">></span> <span class="token operator"><</span>br<span class="token operator">></span> <span class="token operator"><</span>br<span class="token operator">></span> <span class="token operator"><</span>h1<span class="token operator">></span>CentOS 7 配置内部YUM源<span class="token operator"><</span>/h1<span class="token operator">></span> <span class="token operator"><</span>br<span class="token operator">></span> <span class="token operator"><</span>h2<span class="token operator">></span>1、备份<span class="token operator"><</span>/h2<span class="token operator">></span> <span class="token operator"><</span>myHero<span class="token operator">></span>mkdir /etc/yum.repos.d/backup <span class="token operator"><</span>/myHero<span class="token operator">></span> <span class="token operator"><</span>myHero<span class="token operator">></span>mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/backup/<span class="token operator"><</span>/myHero<span class="token operator">></span> <span class="token operator"><</span>br<span class="token operator">></span> <span class="token operator"><</span>h2<span class="token operator">></span>2、下载新的 CentOS-Base.repo 到 /etc/yum.repos.d/ <span class="token operator"><</span>/h2<span class="token operator">></span> <span class="token operator"><</span>myHero<span class="token operator">></span>curl -o /etc/yum.repos.d/CentOS-Base.repo http://10.59.3.14/repo/CentOS-Base.repo<span class="token operator"><</span>/myHero<span class="token operator">></span> <span class="token operator"><</span>br<span class="token operator">></span> <span class="token operator"><</span>h2<span class="token operator">></span>3、运行 yum makecache 生成缓存<span class="token operator"><</span>/h2<span class="token operator">></span> <span class="token operator"><</span>br<span class="token operator">></span> <span class="token operator"><</span>h2<span class="token operator">></span>4、运行 yum repolist 查看已经生成缓存<span class="token operator"><</span>/h2<span class="token operator">></span> <span class="token operator"><</span>br<span class="token operator">></span> <span class="token operator"><</span>br<span class="token operator">></span><span class="token operator"><</span>/body<span class="token operator">></span><span class="token operator"><</span>/html<span class="token operator">></span>EOF</code></pre><ol start="10"><li>创建客户端需要的源配置文件</li></ol><pre class=" language-bash"><code class="language-bash"><span class="token punctuation">[</span>root@localhost repo<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># pwd</span>/mirror/repo<span class="token punctuation">[</span>root@localhost repo<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># vi CentOS-Base.repo</span><span class="token comment" spellcheck="true">### CentOS-Base.repo</span><span class="token punctuation">[</span>base<span class="token punctuation">]</span>name<span class="token operator">=</span>CentOS- - Base - 10.59.3.14failovermethod<span class="token operator">=</span>prioritybaseurl<span class="token operator">=</span>http://10.59.3.14/base/enable<span class="token operator">=</span>1gpgcheck<span class="token operator">=</span>0<span class="token comment" spellcheck="true">#released updates</span><span class="token punctuation">[</span>updates<span class="token punctuation">]</span>name<span class="token operator">=</span>CentOS- - Updates - 10.59.3.14failovermethod<span class="token operator">=</span>prioritybaseurl<span class="token operator">=</span>http://10.59.3.14/updates/enable<span class="token operator">=</span>1gpgcheck<span class="token operator">=</span>0<span class="token comment" spellcheck="true">#additional packages that may be useful</span><span class="token punctuation">[</span>extras<span class="token punctuation">]</span>name<span class="token operator">=</span>CentOS- - Extras - 10.59.3.14failovermethod<span class="token operator">=</span>prioritybaseurl<span class="token operator">=</span>http://10.59.3.14/extras/enable<span class="token operator">=</span>1gpgcheck<span class="token operator">=</span>0<span class="token comment" spellcheck="true">#additional packages that may be useful</span><span class="token punctuation">[</span>epel<span class="token punctuation">]</span>name<span class="token operator">=</span>CentOS- - Epel - 10.59.3.14failovermethod<span class="token operator">=</span>prioritybaseurl<span class="token operator">=</span>http://10.59.3.14/epel/enable<span class="token operator">=</span>1gpgcheck<span class="token operator">=</span>0</code></pre><ol start="11"><li>配置自动更新脚本</li></ol><pre class=" language-bash"><code class="language-bash"><span class="token shebang important">#!/bin/bash</span><span class="token comment" spellcheck="true"># 设置日志文件名</span>LOG_FILE<span class="token operator">=</span><span class="token string">"/var/log/aliyunYumUpdatelog.log"</span><span class="token comment" spellcheck="true"># 执行 createrepo 命令</span>createrepo --update /mirror/base/ <span class="token operator">>></span> <span class="token variable">$LOG_FILE</span> 2<span class="token operator">></span><span class="token operator">&</span>1createrepo --update /mirror/extras/ <span class="token operator">>></span> <span class="token variable">$LOG_FILE</span> 2<span class="token operator">></span><span class="token operator">&</span>1createrepo --update /mirror/updates/ <span class="token operator">>></span> <span class="token variable">$LOG_FILE</span> 2<span class="token operator">></span><span class="token operator">&</span>1createrepo --update /mirror/epel/ <span class="token operator">>></span> <span class="token variable">$LOG_FILE</span> 2<span class="token operator">></span><span class="token operator">&</span>1<span class="token comment" spellcheck="true"># 检查命令是否成功执行</span><span class="token keyword">if</span> <span class="token punctuation">[</span> <span class="token variable">$?</span> -eq 0 <span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">then</span> <span class="token keyword">echo</span> <span class="token string">"<span class="token variable"><span class="token variable">$(</span><span class="token function">date</span> +%Y-%m-%d<span class="token variable">)</span></span>_aliyum_yum update successful"</span> <span class="token operator">>></span> <span class="token variable">$LOG_FILE</span><span class="token keyword">else</span> <span class="token keyword">echo</span> <span class="token string">"<span class="token variable"><span class="token variable">$(</span><span class="token function">date</span> +%Y-%m-%d<span class="token variable">)</span></span>_aliyum_yum update failed"</span> <span class="token operator">>></span> <span class="token variable">$LOG_FILE</span><span class="token keyword">fi</span></code></pre><pre class=" language-bash"><code class="language-bash"><span class="token comment" spellcheck="true"># 定时运行脚本(周日12点)</span>0 12 * * 0 /mirror/script/aliyum_update.sh</code></pre><ol start="12"><li>效果</li></ol><p> <img src="https://oss.luhuhu.cn/202405271658177.png" alt="image-20240527165831072"></p></li></ol><p></p><h3 id="防火墙"><a href="#防火墙" class="headerlink" title="防火墙"></a>防火墙</h3><h4 id="firewall-cmd"><a href="#firewall-cmd" class="headerlink" title="firewall-cmd"></a>firewall-cmd</h4><blockquote><p>在CentOS 7中,新引入了firewalld防火墙,取代了CentOS 6之前的iptables防火墙。</p><p> iptables用于过滤数据包,属于网络层防火墙。iptables主要是基于接口,来设置规则,从而判断网络的安全性。</p><p> firewalld能够允许哪些服务可用,哪些端口可用等等,属于更高一层的防火墙。firewalld提供了支持网络区域所定义的网络链接以及接口安全等级的动态防火墙管理工具。它支持IPv4、IPv6防火墙设置以及以太网桥(在某些高级服务可能会用到,比如云计算), 并且拥有两种配置模式:运行时(Runtime)模式、永久(Permanent)模式。</p><p> firewalld和iptables都是用来管理防火墙的工具(属于用户态)来定义防火墙的各种规则功能,内部结构都指向netfilter网络过过滤子系统(属于内核态)来实现包过滤防火墙功能。<br> firewalld自身并不具备防火墙的功能,而是和iptables一样需要通过内核的netfilter来实现,也就是说firewalld和 iptables一样,他们的作用都是用于维护规则,而真正使用规则干活的是内核的netfilter,只不过firewalld和iptables的结构以及使用方法不一样罢了。</p><p> firewall-cmd是firewalld的字符界面管理工具,firewall-config是firewalld的图形用户界面管理工具。</p><p> firewalld是centos7的一大特性,最大的好处有两个:支持动态更新,不用重启服务;第二个就是加入了防火墙的“zone”概念。<br> 首先,将所有网络流量分为多个区域(zone),然后,根据数据包的源IP地址或传入的网络接口等条件将流量传入相应区域,同时,每个区域都定义了自己打开或者关闭的端口和服务列表。</p></blockquote><h5 id="常用操作"><a href="#常用操作" class="headerlink" title="常用操作"></a>常用操作</h5><pre class=" language-bash"><code class="language-bash"><span class="token comment" spellcheck="true"># 查看状态</span>systemctl status firewalldfirewall-cmd --state <span class="token comment" spellcheck="true"># 开启/关闭/重启</span>systemctl start firewalldsystemctl stop firewalldsystemctl restart firewalld<span class="token comment" spellcheck="true"># 查看是否开机自启、开机自启</span>systemctl is-enabled firewalldsystemctl <span class="token function">enable</span> firewalldsystemctl disable firewalld<span class="token comment" spellcheck="true"># 白名单及端口开放</span>firewall-cmd --permanent --add-port<span class="token operator">=</span>3306/tcpfirewall-cmd --permanent --add-rich-rule<span class="token operator">=</span><span class="token string">"rule family="</span>ipv4<span class="token string">" source address="</span>10.59.88.6<span class="token string">" port protocol="</span>tcp<span class="token string">" port="</span>3306<span class="token string">" accept"</span>firewall-cmd --permanent --remove-rich-rule<span class="token operator">=</span><span class="token string">"rule family="</span>ipv4<span class="token string">" source address="</span>10.42.136.247<span class="token string">" port protocol="</span>tcp<span class="token string">" port="</span>3306<span class="token string">" accept"</span><span class="token comment" spellcheck="true"># 默认开启了22端口的public权限,关闭public权限</span><span class="token function">sudo</span> firewall-cmd --list-services<span class="token function">sudo</span> firewall-cmd --permanent --zone<span class="token operator">=</span>public --remove-service<span class="token operator">=</span>ssh<span class="token function">sudo</span> firewall-cmd --reload<span class="token comment" spellcheck="true"># 防火墙清单</span>firewall-cmd --list-all<span class="token comment" spellcheck="true"># 重载防火墙(不中断服务、中断服务)</span>firewall-cmd --reloadfirewall-cmd --complete-reload</code></pre><h4 id="iptables"><a href="#iptables" class="headerlink" title="iptables"></a>iptables</h4><blockquote><p>iptables 是一个基于用户空间的防火墙工具,用于配置 Linux 内核防火墙的规则集。它可以用来过滤、修改和转发网络数据包</p></blockquote><h4 id="SELinux"><a href="#SELinux" class="headerlink" title="SELinux"></a>SELinux</h4><blockquote><p>Security-Enhanced Linux简称SELinux,它是一个Linux内核模块,也是Linux的一个安全子系统。<br>SELinux的结构及配置非常复杂,而且有大量概念性的东西,学习难度较大。很多Linux系统管理员嫌麻烦都把SELinux关闭了。<br>系统资源都是通过进程来读取更改的,为了保证系统资源的安全,传统的Linux使用用户、文件权限的概念来限制资源的访问,通过对比进程的发起用户和文件权限以此来保证系统资源的安全,这是一种自由访问控制方式(DAC);但是随着系统资源安全性要求提高,出现了在Linux下的一种安全强化机制(SELinux),该机制为进程和文件加入了除权限之外更多的限制来增强访问条件,这种方式为强制访问控制(MAC)。这两种方式最直观的对比就是,采用传统DAC,root可以访问任何文件,而在MAC下,root只能访问设定允许的文件。</p></blockquote><pre class=" language-bash"><code class="language-bash"><span class="token comment" spellcheck="true"># 关闭SELinux</span><span class="token punctuation">[</span>root@snow ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># vim /etc/selinux/config</span><span class="token comment" spellcheck="true"># This file controls the state of SELinux on the system.</span><span class="token comment" spellcheck="true"># SELINUX= can take one of these three values:</span><span class="token comment" spellcheck="true"># enforcing - SELinux security policy is enforced.</span><span class="token comment" spellcheck="true"># permissive - SELinux prints warnings instead of enforcing.</span><span class="token comment" spellcheck="true"># disabled - No SELinux policy is loaded.</span>SELINUX<span class="token operator">=</span>disabled<span class="token comment" spellcheck="true"># SELINUXTYPE= can take one of three values:</span><span class="token comment" spellcheck="true"># targeted - Targeted processes are protected,</span><span class="token comment" spellcheck="true"># minimum - Modification of targeted policy. Only selected processes are protected.</span><span class="token comment" spellcheck="true"># mls - Multi Level Security protection.</span>SELINUXTYPE<span class="token operator">=</span>targeted</code></pre><h3 id="工具"><a href="#工具" class="headerlink" title="工具"></a>工具</h3><h4 id="yum"><a href="#yum" class="headerlink" title="yum"></a>yum</h4><h4 id="apt-get"><a href="#apt-get" class="headerlink" title="apt-get"></a>apt-get</h4><h4 id="rpm"><a href="#rpm" class="headerlink" title="rpm"></a>rpm</h4><ul><li><p>简介 </p><blockquote><p><strong>RPM</strong>的全名是<strong>Red Hat Package Manager</strong>,本意是Red Hat 软件包管理,顾名思义是Red Hat 贡献出来的软件包管理</p></blockquote></li><li><p>优缺点</p><ul><li><p>优点</p><ul><li><p>由于已经编译完成并且打包,所以安装很方便</p></li><li><p>由于套件信息已经记录在Linux主机的数据库中,方便查询、升级与卸载</p></li></ul></li><li><p>缺点</p></li></ul><ul><li><p>安装环境必须与打包时的环境一致</p></li><li><p>需要满足软件的依赖属性需求</p></li><li><p>卸载时需要特别小心,最底层的软件不可以先删除,否则可能造成整个系统出问题</p></li></ul></li></ul><h4 id="dpkg"><a href="#dpkg" class="headerlink" title="dpkg"></a>dpkg</h4><h2 id="路由"><a href="#路由" class="headerlink" title="路由"></a>路由</h2><h3 id="路由选择顺序"><a href="#路由选择顺序" class="headerlink" title="路由选择顺序"></a><a href="https://blog.csdn.net/fengxingzhe008/article/details/127437511">路由选择顺序</a></h3><blockquote><p>在不考虑<a href="https://so.csdn.net/so/search?q=%E7%AD%96%E7%95%A5%E8%B7%AF%E7%94%B1&spm=1001.2101.3001.7020">策略路由</a>等其他情况下,对IP包进行路由时,通常按照如下顺序进行。</p><ol><li><p>最长掩码匹配原则</p></li><li><p>管理距离/AD/路由协议优先级</p></li><li><p>路由花销/Cost/Metric</p></li></ol></blockquote><h3 id="设置永久静态路由"><a href="#设置永久静态路由" class="headerlink" title="设置永久静态路由"></a><a href="https://segmentfault.com/a/1190000041160755">设置永久静态路由</a></h3><h3 id="双网卡定向设置路由"><a href="#双网卡定向设置路由" class="headerlink" title="双网卡定向设置路由"></a>双网卡定向设置路由</h3><p>centos有两张网卡分别为192网段和10网段,要求分别使用各自的网关<br>业务场景为服务器192内网需要映射到外网215上提供服务,10网段真实地址为接口等应用使用的真实地址<br>实现:</p><pre class=" language-bash"><code class="language-bash"><span class="token comment" spellcheck="true"># 设置eth0走10网段网卡</span>route add -net 10.0.0.0 netmask 255.0.0.0 gw 10.59.0.254<span class="token comment" spellcheck="true"># 设置脚本自动启动</span><span class="token function">cd</span> /etc/sysconfig/network-scripts/<span class="token function">touch</span> route-eth0<span class="token function">vi</span> route-eth0 ···<span class="token comment" spellcheck="true">#!/bin/bash</span>route add -net 10.0.0.0 netmask 255.0.0.0 gw 10.59.0.254···<span class="token function">chmod</span> +x /etc/sysconfig/network-scripts/route-eth0 <span class="token function">sudo</span> <span class="token function">touch</span> /etc/sysconfig/network-scripts/ifup-local<span class="token function">sudo</span> <span class="token function">chmod</span> +x /etc/sysconfig/network-scripts/ifup-local<span class="token function">vi</span> ifup-local···/etc/sysconfig/network-scripts/route-eth0···<span class="token comment" spellcheck="true"># 查看route</span>route -n···<span class="token comment" spellcheck="true"># 设置eth0走10网段网卡</span>route add -net 10.0.0.0 netmask 255.0.0.0 gw 10.59.0.254route add -net 10.42.248.0 netmask 255.255.255.0 gw 192.168.200.254<span class="token comment" spellcheck="true"># 设置脚本自动启动</span><span class="token function">cd</span> /etc/sysconfig/network-scripts/<span class="token function">touch</span> route-eth0<span class="token function">vi</span> route-eth0 ···<span class="token comment" spellcheck="true">#!/bin/bash</span>route add -net 10.0.0.0 netmask 255.0.0.0 gw 10.59.0.254···<span class="token function">chmod</span> +x /etc/sysconfig/network-scripts/route-eth0 <span class="token function">sudo</span> <span class="token function">touch</span> /etc/sysconfig/network-scripts/ifup-local<span class="token function">sudo</span> <span class="token function">chmod</span> +x /etc/sysconfig/network-scripts/ifup-local<span class="token function">vi</span> ifup-local···/etc/sysconfig/network-scripts/route-eth0···<span class="token comment" spellcheck="true"># 查看route</span>route -n···Kernel IP routing tableDestination Gateway Genmask Flags Metric Ref Use Iface0.0.0.0 192.168.200.254 0.0.0.0 UG 121 0 0 eth110.0.0.0 10.59.0.254 255.0.0.0 UG 0 0 0 eth010.42.248.0 192.168.200.254 255.255.255.0 UG 0 0 0 eth110.59.0.0 0.0.0.0 255.255.255.0 U 120 0 0 eth0192.168.200.0 0.0.0.0 255.255.255.0 U 121 0 0 eth1···</code></pre>]]></content>
<categories>
<category> CS </category>
</categories>
<tags>
<tag> Linux </tag>
</tags>
</entry>
<entry>
<title>GIT</title>
<link href="/post/c72923f6.html"/>
<url>/post/c72923f6.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><p><img src="https://oss.luhuhu.cn/202406051142097.jpeg"></p><h1 id="GIT"><a href="#GIT" class="headerlink" title="GIT"></a>GIT</h1><p>书籍:《Pro Git》</p><p><a href="https://boardmix.cn/app/editor/5DoZAx7lQy_6KA8ZfVaotQ">pic</a></p><p><img src="https://oss.luhuhu.cn/202404241653764.png" alt="git"></p><h2 id="版本控制"><a href="#版本控制" class="headerlink" title="版本控制"></a>版本控制</h2><ul><li>集中式:svn</li><li>分布式:git</li><li>本地</li></ul><blockquote><p>本地版本控制:在硬盘上保存补丁集,不能协同工作</p><p>集中化版本控制:实现协同工作,但是由于由中央服务器统一维护,存在丢失风险</p><p>分布式版本控制:把代码仓库完整镜像保存下来,包括完整的历史记录,去中心化</p></blockquote><h2 id="Local"><a href="#Local" class="headerlink" title="Local"></a>Local</h2><p>工作区、缓存区、提交区</p><h2 id="Remote"><a href="#Remote" class="headerlink" title="Remote"></a>Remote</h2><h2 id="冲突"><a href="#冲突" class="headerlink" title="冲突"></a>冲突</h2><h3 id="单分支冲突"><a href="#单分支冲突" class="headerlink" title="单分支冲突"></a>单分支冲突</h3><p><strong>单分支冲突场景:</strong>在单位提交了push iss1到dev分支,在家里没有pull iss1的情况下 进行了iss2的工作,当 push时会reject要求解决iss1 和iss2的冲突之后再push</p><h3 id="多分支冲突"><a href="#多分支冲突" class="headerlink" title="多分支冲突"></a>多分支冲突</h3><p><strong>多分支冲突场景:</strong></p><ol><li>开发某个网站。</li><li>为实现某个新的用户需求issue,创建一个分支。</li><li>在这个分支上开展工作。<br>正在此时,你突然接到一个电话说有个很严重的问题需要紧急修补。 你将按照如下方式来处理:<ol><li>切换到你的线上分支(main)。</li><li>为这个紧急任务新建一个分支hotfix,并在其中修复它。</li><li>在测试通过之后,切换回线上分支,然后合并这个修补分支(merge hotfix),最后将改动推送到线上分支,删除hotfix分支(branch -d hotfix)。</li></ol></li><li>切换回你最初工作的分支issue上,继续工作。</li><li>完成issue的开发工作,合并issue分支(<strong>merge issue</strong> 出现分支冲突)</li><li>需要处理conflicts,然后git add, commit, push, branch -d issue分支</li></ol><h3 id="分支操作"><a href="#分支操作" class="headerlink" title="分支操作"></a>分支操作</h3><pre class=" language-bash"><code class="language-bash"><span class="token comment" spellcheck="true"># 创建并切换到newbranch分支</span><span class="token function">git</span> checkout -b newbranch<span class="token comment" spellcheck="true"># 分支重命名dev</span><span class="token function">git</span> branch -m newbranch dev<span class="token comment" spellcheck="true"># 创建远程dev分支,并push</span><span class="token function">git</span> push origin dev<span class="token comment" spellcheck="true"># 删除本地dev分支</span><span class="token function">git</span> branch -d dev<span class="token comment" spellcheck="true"># 删除远程dev分支</span><span class="token function">git</span> push origin --delete dev<span class="token comment" spellcheck="true"># 查看分支</span><span class="token function">git</span> branch -v<span class="token comment" spellcheck="true"># 查看当前分支merge关系</span><span class="token function">git</span> branch --merged/--nomerged</code></pre><h2 id="分支开发工作流"><a href="#分支开发工作流" class="headerlink" title="分支开发工作流"></a>分支开发工作流</h2><h3 id="长期分支"><a href="#长期分支" class="headerlink" title="长期分支"></a>长期分支</h3><blockquote><p>只在 master 分支上保留完全稳定的代码——有可能仅仅是已经发布或即将发布的代码。 他们还有一些名为 develop 或者 next 的平行分支,被用来做后续开发或者测试稳定性——这些分支不必保持绝对稳定,但是一旦达到稳定状态,它们就可以被合并入 master 分支了。 这样,在确保这些已完成的主题分支(短期分支,比如之前的 iss53 分支)能够通过所有测试,并且不会引入更多 bug 之后,就可以合并入主干分支中,等待下一次的发布。</p></blockquote><p><img src="https://oss.luhuhu.cn/202404251034138.png" alt="work silos"></p><h3 id="主题分支"><a href="#主题分支" class="headerlink" title="主题分支"></a>主题分支</h3><p>只在本地git版本库中,不与服务器发生交互</p><blockquote><p>主题分支是一种短期分支,它被用来实现单一特性或其相关工作。 也许你从来没有在其他的版本控制系统(VCS)上这么做过,因为在那些版本控制系统中创建和合并分支通常很费劲。然而,在 Git 中一天之内多次创建、使用、合并、删除分支都很常见。</p></blockquote><p><img src="https://oss.luhuhu.cn/202404251036872.png" alt="image-20240425103637564"></p><h2 id="远程分支"><a href="#远程分支" class="headerlink" title="远程分支"></a>远程分支</h2><blockquote><p>远程引用是对远程仓库的引用(指针),包括分支、标签等等。 你可以通过 git ls-remote <remote> 来<br>显式地获得远程引用的完整列表, 或者通过 git remote show <remote> 获得远程分支的更多信息。 然<br>而,一个更常见的做法是利用远程跟踪分支。</remote></remote></p></blockquote><p>head中留存的是远程分支的指针</p><pre class=" language-bash"><code class="language-bash"><span class="token function">git</span> remote -v<span class="token function">git</span> remote show origin<span class="token comment" spellcheck="true"># 拉取远程分支到本地head</span><span class="token function">git</span> fetch<span class="token comment" spellcheck="true"># 合并</span><span class="token function">git</span> pull <span class="token operator">=</span> <span class="token function">git</span> fetch + <span class="token function">git</span> merge origin/<span class="token operator"><</span>branchName<span class="token operator">></span><span class="token comment" spellcheck="true"># 查看本地分支和远程分支的差异</span><span class="token function">git</span> branch -vv<span class="token comment" spellcheck="true"># 删除远程分支</span><span class="token function">git</span> push origin -d <span class="token operator"><</span>branchName<span class="token operator">></span></code></pre><h2 id="变基"><a href="#变基" class="headerlink" title="变基"></a>变基</h2><p><strong>善待同事Skill</strong> GET<br>整合分支主要方法:merge、rebase</p><p>变基需要遵守的准则:如果提交存在于仓库之外,那么不要执行变基——<strong>私有仓库/分支使用,如果已经提交出去的分支不要执行变基,可能丢失别人的修改!不要尝试在仓库外变基,否则人民群众会仇恨你,你的朋友和家人会嘲笑你,唾弃你。</strong></p><p>变基的意义:merge和rebase在实现的最终结果上没什么区别,但是可以使提交历史更加整洁。尽管开发工作是并行的,但是看上去像是串行的,一般这么做的目的是为了确保向远程分支推送时能保持历史的整洁。<strong>应用场景:首先在自己的分支进行开发,完成时变基到origin/main上,然后向主项目提交修改,这样该项目的维护者就不需要进行整合操作,只需要快速合并便可。</strong></p><ul><li><p>merge:两个分支,三方合并,形成新的快照</p><pre class=" language-bash"><code class="language-bash"><span class="token function">git</span> merge experiment</code></pre><p><img src="https://oss.luhuhu.cn/202404251138426.png" alt="merge"></p></li><li><p>rebase:找出C3、C4共同祖先C2,将C4修改指针只想C3,最后合并</p><pre class=" language-bash"><code class="language-bash"><span class="token function">git</span> checkout experiment<span class="token function">git</span> rebase master<span class="token function">git</span> checkout master<span class="token function">git</span> merge experiment</code></pre><p><img src="https://oss.luhuhu.cn/202404251138130.png" alt="rebase"></p></li></ul><h2 id="服务器上的git"><a href="#服务器上的git" class="headerlink" title="服务器上的git"></a>服务器上的git</h2><p>略</p><h2 id="如何对开源项目做贡献"><a href="#如何对开源项目做贡献" class="headerlink" title="如何对开源项目做贡献"></a>如何对开源项目做贡献</h2><ol><li>fork开源项目</li><li>修改、推送到自己的私有仓库</li><li>请求维护者拉取自己的更新</li><li>维护者合并修改,推送到主仓库</li></ol>]]></content>
<categories>
<category> CS </category>
</categories>
<tags>
<tag> GIT </tag>
</tags>
</entry>
<entry>
<title>How2Read</title>
<link href="/post/3643dde7.html"/>
<url>/post/3643dde7.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="How-to-Read"><a href="#How-to-Read" class="headerlink" title="How to Read"></a>How to Read</h1><p>《如何阅读一本书》莫提默·J·艾德勒 查尔斯·范多伦</p><h2 id="阅读的层次"><a href="#阅读的层次" class="headerlink" title="阅读的层次"></a>阅读的层次</h2><ul><li>基础阅读<br>识字层次</li><li>检视阅读<br>在一定时间内,抓出一本书的重点,识别书的类型、写了什么内容,判断是否值得进一步阅读</li><li>分析阅读<br>咀嚼、消化一本书,核心在于理解,在无限时间里,最好最完整的阅读,直到这本书成为他自己</li><li>主题阅读<br>读很多这一系列的书,列举出相关处,架构出主题分析,类似于科研</li></ul><h2 id="阅读方式"><a href="#阅读方式" class="headerlink" title="阅读方式"></a>阅读方式</h2><h3 id="逗留和倒退"><a href="#逗留和倒退" class="headerlink" title="逗留和倒退"></a>逗留和倒退</h3><p>矫正逗留和倒退的不好习惯,提高阅读的速度</p><h3 id="理解力"><a href="#理解力" class="headerlink" title="理解力"></a>理解力</h3><p>提高阅读速度的同时,需要集中精力训练理解力</p><h3 id="略读"><a href="#略读" class="headerlink" title="略读"></a>略读</h3><p>遇到难读的书时,不要企图了解每一个字句,而是先理解能理解的,通过重复来真正的读懂这本书</p><h2 id="主动阅读"><a href="#主动阅读" class="headerlink" title="主动阅读"></a>主动阅读</h2><ol><li>这本书整体在谈论什么,核心主题是什么</li><li>作者细说了什么,怎么说的?主要的想法、声明、论点</li><li>这本书说的有道理么,全部有道理?部分有道理?</li><li>这本书说的跟你又什么关系,你获得了哪些咨询,这些咨询的意义,给了什么启示</li></ol><h3 id="笔记"><a href="#笔记" class="headerlink" title="笔记"></a>笔记</h3><ul><li>结构笔记</li><li>概念笔记</li><li>辩证笔记</li></ul>]]></content>
<categories>
<category> 技能 </category>
</categories>
<tags>
<tag> 阅读 </tag>
</tags>
</entry>
<entry>
<title>NAS</title>
<link href="/post/9e4507d2.html"/>
<url>/post/9e4507d2.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="NAS"><a href="#NAS" class="headerlink" title="NAS"></a>NAS</h1><h2 id="设备信息"><a href="#设备信息" class="headerlink" title="设备信息"></a>设备信息</h2><p>群晖920+<br>系统:DSM 7.2.1<br>CPU:INTEL Celeron J4125<br>内存:4+16G<br>硬盘:4T 西数紫盘</p><h2 id="APPs"><a href="#APPs" class="headerlink" title="APPs"></a>APPs</h2><h3 id="Active-Backup-for-Business"><a href="#Active-Backup-for-Business" class="headerlink" title="Active Backup for Business"></a>Active Backup for Business</h3><p>Win/Mac Backup Tasks</p><h3 id="Audio-Station"><a href="#Audio-Station" class="headerlink" title="Audio Station"></a>Audio Station</h3><h3 id="Download-Station"><a href="#Download-Station" class="headerlink" title="Download Station"></a>Download Station</h3><h3 id="Container-Manager-(Docker)"><a href="#Container-Manager-(Docker)" class="headerlink" title="Container Manager (Docker)"></a>Container Manager (Docker)</h3><h4 id="ddnp-ip"><a href="#ddnp-ip" class="headerlink" title="ddnp_ip"></a>ddnp_ip</h4><h4 id="clash"><a href="#clash" class="headerlink" title="clash"></a>clash</h4><h4 id="calibre"><a href="#calibre" class="headerlink" title="calibre"></a>calibre</h4><h4 id="homarr"><a href="#homarr" class="headerlink" title="homarr"></a>homarr</h4><h3 id="Synology-Drive"><a href="#Synology-Drive" class="headerlink" title="Synology Drive"></a>Synology Drive</h3><h3 id="Synology-Photos"><a href="#Synology-Photos" class="headerlink" title="Synology Photos"></a>Synology Photos</h3><h3 id="Video-Station"><a href="#Video-Station" class="headerlink" title="Video Station"></a>Video Station</h3><h3 id="Cloud-Sync"><a href="#Cloud-Sync" class="headerlink" title="Cloud Sync"></a>Cloud Sync</h3><h3 id="Web-Station"><a href="#Web-Station" class="headerlink" title="Web Station"></a>Web Station</h3><h3 id="Antivirus-Essentail"><a href="#Antivirus-Essentail" class="headerlink" title="Antivirus Essentail"></a>Antivirus Essentail</h3><h1 id="ECS"><a href="#ECS" class="headerlink" title="ECS"></a>ECS</h1><p>aliyunEcs(2core,2GiB,40GB),99/YEAR,之前用于获取ICP备案码</p><h2 id="Nacos"><a href="#Nacos" class="headerlink" title="Nacos"></a>Nacos</h2><h2 id="Nginx"><a href="#Nginx" class="headerlink" title="Nginx"></a>Nginx</h2><h2 id="WordPress"><a href="#WordPress" class="headerlink" title="WordPress"></a>WordPress</h2><p>ECS性能太差不适合使用</p><h1 id="Domain"><a href="#Domain" class="headerlink" title="Domain"></a>Domain</h1><p>aliyunDomain 39/YEAR,用于配合ddns_ip 远程访问NAS</p><p>ICP备案</p><h1 id="OSS"><a href="#OSS" class="headerlink" title="OSS"></a>OSS</h1><p>aliyunOss 图床需求</p>]]></content>
<categories>
<category> CS </category>
</categories>
<tags>
<tag> NAS </tag>
</tags>
</entry>
<entry>
<title>Note</title>
<link href="/post/6f8f552a.html"/>
<url>/post/6f8f552a.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="手记"><a href="#手记" class="headerlink" title="手记"></a>手记</h1><h2 id="2024年3月29日"><a href="#2024年3月29日" class="headerlink" title="2024年3月29日"></a>2024年3月29日</h2><p>我仔细地在想不离开的原因,我与你的精神没有共鸣,身体没有共振,喜好性情大相径庭,经济生活不相依附。孩子是婚姻的纽带,也是自由的脚镣。</p><p>但归根到底,束缚自由的并不是外界的事物,而是内心对生活、对未来的迷茫,我的停滞与感情无关,跟责任、担当无关,孩子的单纯给我带来的欢乐是凄惨精神世界唯一仅存的慰藉,而并不是镣铐。</p><p>逃离是最懒惰的办法,思想上的匮乏令你在世俗的种种评价前脆弱不堪,摆脱一种状态除了毁掉现状之外,更重要的是想清楚之后的重建,是对理想、自由的奔赴,想到这点就应鼓起勇气往前走、向远处看,静止的事物终将被抛弃,疼痛会带来生的鲜活感。</p><hr><p>人与人之间是极难感同身受的,期望越大失望越大,但人又无法脱离与人的关系,孔乙己问茴字有几种写法,刻画更多的是灵魂的孤独,而不是时代的赞歌。精神渴求着回应却不可得,人群中的孤独是最深刻的孤独。</p><p>“我的灵魂离我如此遥远,而我的存在却如此真实。”</p><p>人的脆弱性使其能够承受的唯一真理便是自身的愚蠢和残缺。</p><p>鲁迅生活的时代就是最好的时代,那是封建气数将尽,公民意志觉醒的时代。极权压迫越用力,民主自由之风便越兴盛,越来越多的人或站出来、或写出来,为了自己,也为了别人,更为了未来。那是一种人格的英勇,不是动物性的趋利避害,蝇营狗苟。</p><h2 id="2024年4月19日"><a href="#2024年4月19日" class="headerlink" title="2024年4月19日"></a>2024年4月19日</h2><p>儿子生病了,合胞病毒感染,但是精神状态良好,不像是生病的样子。恰好她又出差在外地,家里像丢了主心骨,平日里不需我操心的事情都要我来经手判断,而我又没有她的“威望”,奶奶、外婆就开始叽叽喳喳起来,开始提一些不是很靠谱的建议。</p><p>血脉亲情里面大致是不太会有心怀恶意的去伤害你,他们只能从自己的认知范围内去做他们认为对你好的事情。就比如时下的各种爸爸妈妈们的催房、催婚、催娃,但是又说不清这里面的好意。在警惕别人的恶意时候,也要谨慎的接受别人的好意,毕竟日子还是你自己过。为了你好的说辞,是他们对自己错误的自我谅解,游说你不要过多的责怪他们,归根到底还是一种不自知的自私表现。</p><p>周末,她回来了,我一直紧绷着的神经舒展开来。就好像老虎回了家,一下子安静整齐起来,我又可以赖在沙发上看我的小人书。她的脾气不好就像是给所有人做了一个封装,我只需对付她,不需要管她身与别人的矛盾、冲突,是省心生活的一个必要条件。</p><img src="https://oss.luhuhu.cn/202404192242640.png" alt="生病了" style="zoom:30%;"><hr><p>最近看到 一本小书《多谈谈问题》,有些比较有新意的观点摘录如下:</p><p><strong>真理有可能早过时代,但是寻找真理与时代无关——钟叔河</strong></p><blockquote><p>万不可以以自己的学问为职业。——陈寅恪</p><p>如果你以学问为职业,那你就得有老板,这个老板或者是国家,或者是资本家,那你就得听他的话,你的学术研究就不可能是自由的。我原来觉得,我做好一门手艺,养家糊口,我再去干自己想干的事,这个生活是蛮惬意的。没想到现实世界,变成强迫你去做,或者说我必须做这个东西,不做就没有饭吃,这个乐趣就会减少。——钟叔河</p></blockquote><blockquote><p>驱除鞑虏,恢复中华,建立民国,平均地权。——孙中山</p><p>中国的传统重担特别沉重。中国有悠久的传统文明,这一点是我们应该用骄傲的口气来说的,但正因如此,这种文化的自我复制能力特别强,惯性特别大。物理学上讲,体量越大的东西惯性越大,我们十几亿人口摆在这个地方,那么多典籍摆在这个地方,这个体量够大的了。所以这种国家的更新、革新、改革,会特别艰难,它不会再一两代人之间就很轻易的完成。所以我觉得这些书虽然是百年前的作品,但现在也还是他们所摸索的进程的继续,那个过程并没有终止,也没有圆满地到达终点,它也不会有终点。他们有时候的一些苦恼,他们的一些摸索,他们的一些,对于我们现代的人,还有直接的意义。我认为我们现在很多的人,包括我自己,还没有达到当时他们的最高水平。<br>我们走向全球文明的道路会是一条漫长曲折的道路,想从根本上解决这个问题,还是要使所有人的思想现代化起来。有人觉得读了大学、又读了研究生的人的思想当然是现代化的思想,那不见得,我自己的体会是如此,不一定。朱正跟我说过一句话,1957年“反右”以后,搞过一个运动叫“除四害”,每人每天要交上多少蚊子、苍蝇。这种事作为全民运动是没有任何意义的。不上班,大家晚上都不睡觉去捉蚊子、捉苍蝇,捉不完的,蚊子滋生的环境没有改变。另外一个人说,我们现在这些人,如果又一半的人像我们这样认识,这个运动自然就没有了。我认为这个话说到点子上了,我不可能去反对这个运动,我不动可以吧?装病,我病了,我睡在床上,不上班。假如我们都有这个认识,我不干这个事情,全国人民都不干,自然就干不了。这里有些人不仅是干,而且他还更积极,领导讲消灭一个,他还要消灭十个。有这样的人,就是这样的现实。这有什么办法,就要尽力去启蒙。<br>——钟叔河</p></blockquote><blockquote><p>我不是有勇气或者有可能讲我所有想讲的话,但是我绝不讲一句我不想讲的话。——钟叔河</p></blockquote><p><strong>火焰与黑洞——媒介的变化,如何改变我们——戴锦华</strong></p><blockquote><p>我们整体地陷入了认识论危机。今日的互联网结构(大数据、精准投放——信息茧房)令我们无法从互联网上获取新知、发现未知,甚至丧失了求知的意识和愿望。经由网络、传播,我们只会印证自己的已知,确信自己的正确,因此我们无从形成新的观点,丧失了质疑既有观点和立场的可能性。——戴锦华</p></blockquote><p><strong>在人性残缺的时代,成为一个完整的人——景凯旋</strong></p><blockquote><p>在中国文化中,“活在当下”是有特定含义的,即把活着本身作为最高目的,没有生命的过程感和意义感。海德格尔说,人向死而在,所以人有世界,动物没有世界。由此看来,“活在当下”其实是一个人没有世界的表现。</p><p>“活在当下不是一种自由,只有活在真实中才是自由”,生活在真实中源于西方文化的求真精神,它首先指追求真相,拒绝生活在谎言中,因为生活在谎言中导致人性的危机,人的自我认同的危机,其中也包括道德的危机。其次,它是指追求真理,亦即这句话还具有形而上的层面。在西方语言中,真实和真理往往是同一个次。“生活在真实中”意味着对真理的不断追求。而在东欧作家看来,真理的源头不是主观自我,而是绝对的超验之物,坚持善、自由等价值都是源自某个更高的存在物,只有相信这个价值源头,人们才会具有对抗现实的道德勇气。东欧作家之所以提出这个命题,是因为<strong>现代人已经失去了超越的世界观,所有价值都是基于人的自我保全,人本身成为价值的源头,那么很显然,由人创造的价值都是相对的,于是谁拥有力量谁就拥有真理、拥有良善生活的解释权。这种情况下,何谈真正的良善生活。</strong></p><p>多元文化主义不可避免的矛盾在于,<strong>如果它禁止极端观念,就会违背自己的原则,如果它容忍极端观念,又会导致自己的失败。</strong>我觉得,今天的西方社会就是如此。</p><p>没有内心自由的人就没有自我,它的自我来自于别人眼中的自我,因此不能独立做出自己的判断。内心自由就是康德所说的自由意志,这是人的本质属性,没有内心自由的人永远都是随大流,把自己融入到大众之中,所以他也不会有真正的私人生活。<strong>我们生活中常常看到这样的人,当自己的私人生活遭到他人干预时,他不会觉得这是对自己尊严的侵犯,他心甘情愿地服从,甚至方案哪些不愿意服从的人,这正是阿特伦所说的“无思”。</strong>只有那些有自我意识的人才有可能拥有内心自由,虽然我们也许永远无法认识那个真正的自我,但至少可以讲陈寅恪先生所说的“独立之精神,自由之思想”看作自我的表现。内心自由的人不仅意味着敢于独立思考,还意味着服从自己的良知。现代人已经不再喜欢使用良知这个词,说出这个词会感到很过时,但在这个越来越同质化的时代,人性变得越来越残缺不全的时代,我们不仅应当重温康德的话,要敢于独立运用自己的理性,而且还要重新唤起自己的良知。只有这样才会成为一个完整的人。</p></blockquote>]]></content>
<categories>
<category> 杂文 </category>
</categories>
<tags>
<tag> 手记 </tag>
</tags>
</entry>
<entry>
<title>DataStructure</title>
<link href="/post/ba907200.html"/>
<url>/post/ba907200.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="数据结构"><a href="#数据结构" class="headerlink" title="数据结构"></a>数据结构</h1><h2 id="线性结构"><a href="#线性结构" class="headerlink" title="线性结构"></a>线性结构</h2><h3 id="数组、单链表、双链表"><a href="#数组、单链表、双链表" class="headerlink" title="数组、单链表、双链表"></a>数组、单链表、双链表</h3><ul><li>数组:连续,随机访问速度快;Collection集合中提供了ArrayList和Vector<ul><li>ArrayList:线程不安全,不够用时扩展0.5倍,Collections.synchronizedList<List<t> list>实现线程安全</t></li><li>(<strong>弃用</strong>)Vector:线程安全,不够用时扩展1倍</li></ul></li><li>单链表:节点的链接方向是单向的;相对于数组来说,单链表的的随机访问速度较慢,但是单链表删除/添加数据的效率很高。</li><li>双链表:双链表的优点是可以从头部或尾部访问,也可以直接访问中间的元素。此外,由于有指向前一个节点的指针,因此可以从尾部或中间删除元素,而不需要遍历整个链表,缺点是每个节点需要更多的存储空间(两个指针)</li></ul><h3 id="栈"><a href="#栈" class="headerlink" title="栈"></a>栈</h3><ul><li>LIFO:后进先出</li><li>操作只能从栈顶进行操作</li><li>push、pop、peek:进栈、出栈、返回栈顶元素</li><li>应用场景:函数调用和递归;表达式求值、括号匹配;回溯算法DFS深度优先搜索</li></ul><h3 id="队列"><a href="#队列" class="headerlink" title="队列"></a>队列</h3><ul><li>FIFO:先进先出</li><li>只允许在队首进行删除、队尾进行插入操作</li><li>应用场景:任务调度;缓冲区;优先级队列;广度优先搜索BFS</li></ul><h2 id="树形结构"><a href="#树形结构" class="headerlink" title="树形结构"></a>树形结构</h2><h3 id="遍历"><a href="#遍历" class="headerlink" title="遍历"></a>遍历</h3><p>先序、中序、后序,取决于何时读取根节点</p><h3 id="二叉查找树"><a href="#二叉查找树" class="headerlink" title="二叉查找树"></a>二叉查找树</h3><p>时间复杂度O(logN),极端情况下会变成线性结构O(N)</p><ul><li>若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;</li><li>任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;</li><li>任意节点的左、右子树也分别为二叉查找树;</li><li>没有键值相等的节点(no duplicate nodes);</li></ul><h3 id="AVL树"><a href="#AVL树" class="headerlink" title="AVL树"></a>AVL树</h3><p>因为规定了左右子树高度差,所以不会变成线性链表,时间复杂度O(logN),由于需要保持自身平衡,需要频繁旋转,多次磁盘IO</p><ul><li>任何节点的两个子树最大高度差为1</li></ul><h3 id="B树"><a href="#B树" class="headerlink" title="B树"></a>B树</h3><p>自然平衡树。内部通过分裂机制,保持数据有序。单节点可以保存2~4个信息,节点内有序,节点间间隔,减少磁盘IO次数。<br>适合单点查询的场景,如MongoDB。<br>不适合的场景:所有节点都放在磁盘上,读写性能差;范围查时,如果范围跨节点会出现节点间反复横跳情况。</p><h3 id="B-树"><a href="#B-树" class="headerlink" title="B+树"></a>B+树</h3><p>B+树为了解决B树存在的缺陷而设计。相比B树,B+树非叶子节点仅保留数据间相对关系(索引)<br>,真实信息均包含在叶子节点中,相对关系信息(非叶子节点)就可以放在内存中,真实信息放在磁盘中。<br>MySql的存储引擎InnoDB用的就是B+树。<br>B+树信息存在磁盘中,且非顺序写入,所以查询性能很高,但是写入性能偏低,即B+树结构不适合频繁大数据量的写入,核心原因是因为非顺序写入。</p><h3 id="B-树-1"><a href="#B-树-1" class="headerlink" title="B*树"></a>B*树</h3><p>B* 树是对B+树的再一次改进,在B+树构建过程中,节点的合并拆分比较费时,所以B*树就是为了减少构建过程中节点合并和拆分的次数,从而提升树的数据插入、删除性能。</p><p>与B+树的区别:</p><ol><li>关键字个数限制问题,B+树初始化的关键字初始化个数是cei(m/2),b<em>树的初始化个数为(cei(2/3</em>m))</li><li>B+树节点满时就会分裂,而B*树节点满时会检查兄弟节点是否满(因为每个节点都有指向兄弟的指针),如果兄弟节点未满则向兄弟节点转移关键字,如果兄弟节点已满,则从当前节点和兄弟节点各拿出1/3的数据创建一个新的节点出来</li></ol><h3 id="伸展树"><a href="#伸展树" class="headerlink" title="伸展树"></a>伸展树</h3><ul><li>当某个节点被访问时,会旋转使该节点成为根,下次访问该节点时,能迅速访问到</li></ul><h3 id="红黑树"><a href="#红黑树" class="headerlink" title="红黑树"></a>红黑树</h3><p><img src="https://oss.luhuhu.cn/202404021529279.png" alt="RBTree.png"></p><ul><li>每个节点或者是黑色,或者是红色。</li><li>根节点是黑色。</li><li>每个叶子节点(NIL)是黑色。 [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!]</li><li>如果一个节点是红色的,则它的子节点必须是黑色的。</li><li>从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。</li></ul><h3 id="哈夫曼树"><a href="#哈夫曼树" class="headerlink" title="哈夫曼树"></a>哈夫曼树</h3><blockquote><p>哈夫曼又称最优二叉树, 是一种带权路径长度最短的二叉树。<br>应用场景主要:数据压缩;编码;通信;图像处理</p></blockquote><h3 id="前缀树"><a href="#前缀树" class="headerlink" title="前缀树"></a>前缀树</h3><p>trie tree,又称字典树,用于前缀匹配、字符串检索、词频统计、字符串排序<br><img src="https://oss.luhuhu.cn/202404021529262.png" alt="TrieTree.png"></p><p>基本性质:</p><ul><li>根节点不包含字符,除根节点外的每一个子节点都包含一个字符;</li><li>从根节点到某一个节点,路径上经过的字符连接起来,为该节点对应的字符串;</li><li>每个节点的所有子节点包含的字符互不相同;</li><li>从第一字符开始有连续重复的字符只占用一个节点,比如上面的to,和ten,中重复的单词t只占用了一个节点。</li></ul><h3 id="常见的问题:"><a href="#常见的问题:" class="headerlink" title="常见的问题:"></a>常见的问题:</h3><ol><li><p>HashMap为什么使用红黑树不使用B树</p><blockquote><p>jdk1.8之前使用链表散列实现,<br>jdk1.8之后当链表长度超过阈值(8)时会进行检测,如果长度小于64会进行数组扩容,大于64转化为红黑树<br>TreeMap、TreeSet以及jdk1.8之后的Hashmap都是用了红黑树,为了解决二叉查找树的缺陷——在某些情况下二叉查找树会退化成一个线性结构</p></blockquote></li><li><p>HashMap为什么使用红黑树,不使用B树</p><blockquote><p>效率和复杂度,红黑树在插入、删除、查找等操作上平衡性更好,且节点数比B树小,占用内存更少,适合存储在内存中的数据结构<br>3.</p></blockquote></li></ol><h2 id="图"><a href="#图" class="headerlink" title="图"></a>图</h2><p>由顶点的又穷非空集合和顶点之间的边的集合组成</p><h3 id="图的存储结构"><a href="#图的存储结构" class="headerlink" title="图的存储结构"></a>图的存储结构</h3><ul><li>邻接矩阵表示法<br><img src="https://oss.luhuhu.cn/202404021529258.png" alt="AdjacencyMatrix.png"><br>当图为稀疏图时,会造成极大空间浪费</li><li>邻接表表示法<br><img src="https://oss.luhuhu.cn/202404021529200.png" alt="img_3.png"></li><li>带权图<br><img src="https://oss.luhuhu.cn/202404021529282.png" alt="img.png"></li></ul><h3 id="遍历-1"><a href="#遍历-1" class="headerlink" title="遍历"></a>遍历</h3><ul><li>深度优先</li><li>广度优先</li></ul><h3 id="最小生成树"><a href="#最小生成树" class="headerlink" title="最小生成树"></a>最小生成树</h3><blockquote><ul><li>连通图:在无向图中,若任意两个顶点vivi与vjvj都有路径相通,则称该无向图为连通图。</li><li>强连通图:在有向图中,若任意两个顶点vivi与vjvj都有路径相通,则称该有向图为强连通图。</li><li>连通网:在连通图中,若图的边具有一定的意义,每一条边都对应着一个数,称为权;权代表着连接连个顶点的代价,称这种连通图叫做连通网。</li><li>生成树:一个连通图的生成树是指一个连通子图,它含有图中全部n个顶点,但只有足以构成一棵树的n-1条边。一颗有n个顶点的生成树有且仅有n-1条边,如果生成树中再添加一条边,则必定成环。</li><li>最小生成树:在连通网的所有生成树中,所有边的代价和最小的生成树,称为最小生成树。</li></ul></blockquote><h3 id="最小生成树算法"><a href="#最小生成树算法" class="headerlink" title="最小生成树算法"></a>最小生成树算法</h3><ul><li>Kruskal算法:大量对边操作,适用于稀疏图</li><li>Prim算法:适用于稠密图,但对优化的prim更适用于系数图,时间复杂度取决于边的数量</li></ul><h3 id="最短路径"><a href="#最短路径" class="headerlink" title="最短路径"></a>最短路径</h3><p>查找图中两点之间最短路径(权值最小)<br>Dijkstra算法和Floyd算法都是用于求解单源最短路径问题的算法,但是它们在处理有向图时存在一些区别。</p><p>Dijkstra算法是一种贪心算法,它从源点开始,逐步扩展已知的最短路径集合,直到所有顶点都被包含在内。Dijkstra算法的基本思想是:从源点开始,逐步扩展已知的最短路径集合,直到所有顶点都被包含在内。Dijkstra算法在处理有向图时,会根据边的权值来更新最短路径。<br>Dijkstra算法和Floyd算法的优劣势如下:</p><ul><li><p>Dijkstra算法的优势:</p><ol><li>Dijkstra算法可以处理有负权边的有向图,只要图中不存在负权环。</li><li>Dijkstra算法的时间复杂度较低,为O(V^2)或O(E log V),其中V是顶点数,E是边数。</li></ol></li><li><p>Dijkstra算法的劣势:</p><ol><li>Dijkstra算法需要额外的空间来存储最短路径集合,空间复杂度为O(V)。</li><li>Dijkstra算法在处理有向图时,如果图中存在负权边,可能会导致算法无法找到最短路径。</li></ol></li></ul><p>Floyd算法是一种动态规划算法,它通过迭代地更新所有顶点对之间的最短路径来求解单源最短路径问题。Floyd算法的基本思想是:通过迭代地更新所有顶点对之间的最短路径,来求解单源最短路径问题。Floyd算法在处理有向图时,会根据边的权值来更新最短路径。</p><ul><li><p>Floyd算法的优势:</p><ol><li>Floyd算法可以处理有负权边的有向图,只要图中不存在负权环。</li><li>Floyd算法不需要额外的空间来存储最短路径集合,空间复杂度为O(V^2)。</li></ol></li><li><p>Floyd算法的劣势:</p><ol><li>Floyd算法的时间复杂度较高,为O(V^3),其中V是顶点数。</li><li>Floyd算法在处理有向图时,如果图中存在负权环,可能会导致算法无法找到最短路径。</li></ol></li></ul><h3 id="拓扑排序"><a href="#拓扑排序" class="headerlink" title="拓扑排序"></a>拓扑排序</h3><p>主要用来解决有向图中的依赖解析问题</p><p>当且仅当一个有向无环图,才能得到对应该图的拓扑排序<br>入度、出度:指节点被指向和指向其他节点的边的数目</p><h3 id="AOE-关键路径"><a href="#AOE-关键路径" class="headerlink" title="AOE&关键路径"></a>AOE&关键路径</h3><p>AOE&AOV,常用于工程管理、流程控制</p><ul><li>AOV:顶点表示活动的网,只描述活动之间制约关系</li><li>AOE:用边表示活动的网,权值表示持续时间</li></ul><h1 id="算法"><a href="#算法" class="headerlink" title="算法"></a>算法</h1><h2 id="排序"><a href="#排序" class="headerlink" title="排序"></a>排序</h2><p><img src="https://oss.luhuhu.cn/202404031606436.png" alt="img"></p><h3 id="常见算法"><a href="#常见算法" class="headerlink" title="常见算法"></a>常见算法</h3><ol><li><p>冒泡排序</p><p>每次遍历比较相邻数大小,如果后者比前者小则交换位置,重复操作,直到整个数列有序</p><pre class=" language-java"><code class="language-java"> <span class="token comment" spellcheck="true">/** * bubbleSort * @param aList */</span> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">bubbleSort</span><span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span> aList<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">int</span> tmp<span class="token punctuation">;</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"begin"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> aList<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">print</span><span class="token punctuation">(</span>aList<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> aList<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> j <span class="token operator">=</span> i<span class="token punctuation">;</span> j <span class="token operator"><</span> aList<span class="token punctuation">.</span>length<span class="token punctuation">;</span> j<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>aList<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">></span> aList<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> tmp <span class="token operator">=</span> aList<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span> aList<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> aList<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">;</span> aList<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">=</span> tmp<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"\nend"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> aList<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">print</span><span class="token punctuation">(</span>aList<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span></code></pre></li><li><p><strong>快速排序</strong><br>分治思想,随机选择基准数,通过排序分隔为两部分,一部分比基准小、另一部分比基准大,递归快排</p><pre class=" language-java"><code class="language-java"> <span class="token comment" spellcheck="true">/** * quickSort * @param aList * @param l * @param r */</span> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">quickSort</span><span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span> aList<span class="token punctuation">,</span> <span class="token keyword">int</span> l<span class="token punctuation">,</span> <span class="token keyword">int</span> r<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>l <span class="token operator"><</span> r<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">int</span> i<span class="token punctuation">,</span> j<span class="token punctuation">,</span> x<span class="token punctuation">;</span> i <span class="token operator">=</span> l<span class="token punctuation">;</span> j <span class="token operator">=</span> r<span class="token punctuation">;</span> x <span class="token operator">=</span> aList<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">while</span> <span class="token punctuation">(</span>i <span class="token operator"><</span> j<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">while</span> <span class="token punctuation">(</span>i <span class="token operator"><</span> j <span class="token operator">&&</span> aList<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">></span> x<span class="token punctuation">)</span> j<span class="token operator">--</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// 从右向左找第一个小于x的数</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>i <span class="token operator"><</span> j<span class="token punctuation">)</span> aList<span class="token punctuation">[</span>i<span class="token operator">++</span><span class="token punctuation">]</span> <span class="token operator">=</span> aList<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">while</span> <span class="token punctuation">(</span>i <span class="token operator"><</span> j <span class="token operator">&&</span> aList<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator"><</span> x<span class="token punctuation">)</span> i<span class="token operator">++</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// 从左向右找第一个大于x的数</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>i <span class="token operator"><</span> j<span class="token punctuation">)</span> aList<span class="token punctuation">[</span>j<span class="token operator">--</span><span class="token punctuation">]</span> <span class="token operator">=</span> aList<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> aList<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> x<span class="token punctuation">;</span> <span class="token function">quickSort</span><span class="token punctuation">(</span>aList<span class="token punctuation">,</span> l<span class="token punctuation">,</span> i <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">/* 递归调用 */</span> <span class="token function">quickSort</span><span class="token punctuation">(</span>aList<span class="token punctuation">,</span> i <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">,</span> r<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">/* 递归调用 */</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span></code></pre></li><li><p>插入排序</p></li><li><p><strong>希尔排序</strong><br>分组插入方法</p></li><li><p>选择排序</p></li><li><p>选择排序</p></li><li><p>堆排序</p></li><li><p><strong>归并排序</strong></p></li><li><p>桶排序</p></li><li><p>基数排序</p></li></ol>]]></content>
<categories>
<category> CS </category>
</categories>
<tags>
<tag> 数据结构 </tag>
</tags>
</entry>
<entry>
<title>MySql-base</title>
<link href="/post/e2efbbbb.html"/>
<url>/post/e2efbbbb.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="MySQL-base"><a href="#MySQL-base" class="headerlink" title="MySQL-base"></a>MySQL-base</h1><h2 id="Linux安装mysql"><a href="#Linux安装mysql" class="headerlink" title="Linux安装mysql"></a>Linux安装mysql</h2><h3 id="屏蔽防火墙"><a href="#屏蔽防火墙" class="headerlink" title="屏蔽防火墙"></a>屏蔽防火墙</h3><pre class=" language-bash"><code class="language-bash"><span class="token comment" spellcheck="true"># 确认服务器防火墙等安全配置关闭</span><span class="token comment" spellcheck="true"># 防火墙关闭</span><span class="token punctuation">[</span>root@localhost mysql<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># firewall-cmd --state</span>not running<span class="token comment" spellcheck="true"># iptables 无策略</span><span class="token punctuation">[</span>root@localhost mysql<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># iptables -L</span>Chain INPUT <span class="token punctuation">(</span>policy ACCEPT<span class="token punctuation">)</span>target prot opt <span class="token function">source</span> destinationChain FORWARD <span class="token punctuation">(</span>policy ACCEPT<span class="token punctuation">)</span>target prot opt <span class="token function">source</span> destinationChain OUTPUT <span class="token punctuation">(</span>policy ACCEPT<span class="token punctuation">)</span>target prot opt <span class="token function">source</span> destination<span class="token comment" spellcheck="true"># SELinux安全组件关闭</span><span class="token punctuation">[</span>root@localhost mysql<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># sestatus</span>SELinux status: disabled<span class="token comment" spellcheck="true"># 在正常安装完成之后,再开启安全相关的组件及添加相关的安全配置</span><span class="token comment" spellcheck="true"># Linux安全组件相关移步Linux相关内容学习</span></code></pre><h3 id="rpm安装mysql"><a href="#rpm安装mysql" class="headerlink" title="rpm安装mysql"></a>rpm安装mysql</h3><ol><li><p>查看MySQL用户组和用户信息</p><pre class=" language-bash"><code class="language-bash"><span class="token comment" spellcheck="true"># 查看是否存在mysql相关的用户组和用户信息</span><span class="token function">groups</span> mysql<span class="token comment" spellcheck="true"># 创建mysql用户组和用户</span><span class="token function">groupadd</span> mysql <span class="token operator">&&</span> <span class="token function">useradd</span> -r -g mysql mysql<span class="token comment" spellcheck="true"># 数据目录授权</span><span class="token function">chown</span> mysql:mysql -R /data/mysql</code></pre></li><li><p>删除已存在的MySQL、mariadb</p><pre class=" language-bash"><code class="language-bash">rpm -qa<span class="token operator">|</span><span class="token function">grep</span> mysqlrpm -qa<span class="token operator">|</span><span class="token function">grep</span> mariadbrpm -e --nodeps mysql-libs-5.1.73-1.el6.x86_64rpm -e --nodeps mariadb-libs-5.5.56-2.el7.x86_64</code></pre></li><li><p>提升/tmp权限</p><p>因为默认安装会在tmp下面创建sock</p><pre class=" language-bash"><code class="language-bash"><span class="token function">chmod</span> -R 777 /tmp</code></pre></li><li><p>检查依赖</p><pre class=" language-bash"><code class="language-bash">rpm -qa<span class="token operator">|</span><span class="token function">grep</span> libaiorpm -qa<span class="token operator">|</span><span class="token function">grep</span> net-toolsyum -y <span class="token function">install</span> libaio net-tools</code></pre></li><li><p>准备安装包</p><p>官网下载对应的rpm,以下rpm是必要的</p><blockquote><p>mysql-community-common-5.7.16-1.el6.x86_64.rpm<br>mysql-community-libs-5.7.16-1.el6.x86_64.rpm<br>mysql-community-client-5.7.16-1.el6.x86_64.rpm<br>mysql-community-server-5.7.16-1.el6.x86_64.rpm</p></blockquote></li><li><p>依次执行安装</p><pre class=" language-bash"><code class="language-bash"><span class="token comment" spellcheck="true"># 卸载</span>rpm -e mysql-community-server-xxx.rpm <span class="token comment" spellcheck="true"># 安装</span>rpm -ivh mysql-community-common-5.7.16-1.el7.x86_64.rpm rpm -ivh mysql-community-libs-5.7.16-1.el7.x86_64.rpmrpm -ivh mysql-community-client-5.7.16-1.el7.x86_64.rpm rpm -ivh mysql-community-server-5.7.16-1.el7.x86_64.rpm</code></pre></li></ol><h3 id="单实例"><a href="#单实例" class="headerlink" title="单实例"></a>单实例</h3><p>默认cnf配置</p><pre class=" language-bash"><code class="language-bash"><span class="token punctuation">[</span>root@localhost mysql<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># cat /etc/my.cnf</span><span class="token comment" spellcheck="true"># mysql 默认cnf 配置</span><span class="token comment" spellcheck="true"># For advice on how to change settings please see</span><span class="token comment" spellcheck="true"># http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html</span><span class="token punctuation">[</span>mysqld<span class="token punctuation">]</span><span class="token comment" spellcheck="true">#</span><span class="token comment" spellcheck="true"># Remove leading # and set to the amount of RAM for the most important data</span><span class="token comment" spellcheck="true"># cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.</span><span class="token comment" spellcheck="true"># innodb_buffer_pool_size = 128M</span><span class="token comment" spellcheck="true">#</span><span class="token comment" spellcheck="true"># Remove leading # to turn on a very important data integrity option: logging</span><span class="token comment" spellcheck="true"># changes to the binary log between backups.</span><span class="token comment" spellcheck="true"># log_bin</span><span class="token comment" spellcheck="true">#</span><span class="token comment" spellcheck="true"># Remove leading # to set options mainly useful for reporting servers.</span><span class="token comment" spellcheck="true"># The server defaults are faster for transactions and fast SELECTs.</span><span class="token comment" spellcheck="true"># Adjust sizes as needed, experiment to find the optimal values.</span><span class="token comment" spellcheck="true"># join_buffer_size = 128M</span><span class="token comment" spellcheck="true"># sort_buffer_size = 2M</span><span class="token comment" spellcheck="true"># read_rnd_buffer_size = 2M</span>datadir<span class="token operator">=</span>/var/lib/mysqlsocket<span class="token operator">=</span>/var/lib/mysql/mysql.sock<span class="token comment" spellcheck="true"># Disabling symbolic-links is recommended to prevent assorted security risks</span>symbolic-links<span class="token operator">=</span>0log-error<span class="token operator">=</span>/var/log/mysqld.logpid-file<span class="token operator">=</span>/var/run/mysqld/mysqld.pid</code></pre><ol><li><p>初始化MySQL</p><pre class=" language-bash"><code class="language-bash">mysqld --initialize --user<span class="token operator">=</span>mysql<span class="token comment" spellcheck="true"># 获取初始密码</span><span class="token function">cat</span> /var/log/mysqld.log <span class="token operator">|</span> <span class="token function">tail</span> -n 10</code></pre></li><li><p>启动MySQL服务</p><pre class=" language-bash"><code class="language-bash">systemctl start mysqld.servicesystemctl status mysqld<span class="token comment" spellcheck="true"># 设置开机自启</span>systemctl <span class="token function">enable</span> mysqld.sercice</code></pre></li><li><p>初始化(首次登陆)</p><pre class=" language-bash"><code class="language-bash"><span class="token comment" spellcheck="true"># 通过sock登陆</span>mysql -u root -p --socket<span class="token operator">=</span>/data/mysql/mysql_3306/tmp/mysql3306.sock<span class="token comment" spellcheck="true"># 初次登陆要求修改密码</span>ALTER USER <span class="token string">'root'</span>@<span class="token string">'localhost'</span> IDENTIFIED BY <span class="token string">'root123'</span><span class="token punctuation">;</span><span class="token comment" spellcheck="true"># 授权所有Host可登陆</span>UPDATE mysql.user SET Host <span class="token operator">=</span> <span class="token string">'%'</span> WHERE User <span class="token operator">=</span> <span class="token string">'root'</span><span class="token punctuation">;</span><span class="token comment" spellcheck="true"># 授权登陆 注意还有Linux的防火墙端口监听、白名单设置,参见Linux相关内容</span>GRANT ALL PRIVILEGES ON *.* TO <span class="token string">'root'</span>@<span class="token string">'%'</span><span class="token punctuation">;</span>FLUSH PRIVILEGES<span class="token punctuation">;</span><span class="token comment" spellcheck="true"># 修改字符集</span>show variables like <span class="token string">'character%'</span><span class="token punctuation">;</span><span class="token function">vi</span> /etc/my.cnf <span class="token comment" spellcheck="true"># 增加以下配置</span> character_set_server<span class="token operator">=</span>utf8 init_connect<span class="token operator">=</span>’SET NAMES utf8’systemctl restart mysqld</code></pre></li></ol><h3 id="多实例"><a href="#多实例" class="headerlink" title="多实例"></a>多实例</h3><h4 id="配置文件"><a href="#配置文件" class="headerlink" title="配置文件"></a>配置文件</h4><ol><li>my.cnf</li></ol><pre class=" language-bash"><code class="language-bash"><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># cat /etc/my.cnf.d/mysql-3306.cnf</span><span class="token punctuation">[</span>mysqld<span class="token punctuation">]</span>port<span class="token operator">=</span>3306datadir<span class="token operator">=</span>/data/mysql/mysql_3306socket<span class="token operator">=</span>/data/mysql/mysql_3306/tmp/mysql3306.socksymbolic-links<span class="token operator">=</span>0<span class="token punctuation">[</span>mysqld_safe<span class="token punctuation">]</span>log-error<span class="token operator">=</span>/data/mysql/mysql_3306/log/3306.logpid-file<span class="token operator">=</span>/data/mysql/mysql_3306/3306.pid<span class="token punctuation">[</span>client<span class="token punctuation">]</span>port<span class="token operator">=</span>3306socket<span class="token operator">=</span>/data/mysql/mysql_3306/tmp/mysql3306.sock</code></pre><ol start="2"><li>mysql.service</li></ol><pre class=" language-bash"><code class="language-bash"><span class="token punctuation">[</span>root@localhost ~<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># cat /etc/systemd/system/mysqld-3306.service</span><span class="token punctuation">[</span>Unit<span class="token punctuation">]</span>Description<span class="token operator">=</span>MySQL ServerAfter<span class="token operator">=</span>network.target<span class="token punctuation">[</span>Service<span class="token punctuation">]</span>Type<span class="token operator">=</span>simpleUser<span class="token operator">=</span>mysqlGroup<span class="token operator">=</span>mysqlExecStart<span class="token operator">=</span>/usr/sbin/mysqld --defaults-file<span class="token operator">=</span>/etc/my.cnf.d/mysql-3306.cnfRestart<span class="token operator">=</span>always<span class="token punctuation">[</span>Install<span class="token punctuation">]</span>WantedBy<span class="token operator">=</span>multi-user.target</code></pre><ol start="3"><li>文件目录,cnf配置中依赖的文件路径都需要手动创建,实例化数据库不会 自动创建</li></ol><pre class=" language-bash"><code class="language-bash"><span class="token punctuation">[</span>root@localhost mysql<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># tree /data/mysql/ -d</span>/data/mysql/├── mysql_3306│<span class="token operator">&</span>nbsp<span class="token punctuation">;</span><span class="token operator">&</span>nbsp<span class="token punctuation">;</span> ├── log│<span class="token operator">&</span>nbsp<span class="token punctuation">;</span><span class="token operator">&</span>nbsp<span class="token punctuation">;</span> ├── mysql│<span class="token operator">&</span>nbsp<span class="token punctuation">;</span><span class="token operator">&</span>nbsp<span class="token punctuation">;</span> ├── performance_schema│<span class="token operator">&</span>nbsp<span class="token punctuation">;</span><span class="token operator">&</span>nbsp<span class="token punctuation">;</span> ├── sys│<span class="token operator">&</span>nbsp<span class="token punctuation">;</span><span class="token operator">&</span>nbsp<span class="token punctuation">;</span> └── tmp├── mysql_3307│<span class="token operator">&</span>nbsp<span class="token punctuation">;</span><span class="token operator">&</span>nbsp<span class="token punctuation">;</span> ├── log│<span class="token operator">&</span>nbsp<span class="token punctuation">;</span><span class="token operator">&</span>nbsp<span class="token punctuation">;</span> ├── mysql│<span class="token operator">&</span>nbsp<span class="token punctuation">;</span><span class="token operator">&</span>nbsp<span class="token punctuation">;</span> ├── performance_schema│<span class="token operator">&</span>nbsp<span class="token punctuation">;</span><span class="token operator">&</span>nbsp<span class="token punctuation">;</span> ├── sys│<span class="token operator">&</span>nbsp<span class="token punctuation">;</span><span class="token operator">&</span>nbsp<span class="token punctuation">;</span> └── tmp└── mysql_3308 ├── log ├── mysql ├── performance_schema ├── sys └── tmp</code></pre><h4 id="实例化"><a href="#实例化" class="headerlink" title="实例化"></a>实例化</h4><pre class=" language-bash"><code class="language-bash"><span class="token comment" spellcheck="true"># 实例化MySQL</span>/usr/sbin/mysqld --defaults-file<span class="token operator">=</span>/etc/my.cnf.d/mysql-3306.cnf --initialize --user<span class="token operator">=</span>mysql<span class="token comment" spellcheck="true"># 启动服务 </span>systemctl start mysql-3306.service<span class="token comment" spellcheck="true"># 查看当前mysql相关的服务</span><span class="token punctuation">[</span>root@localhost mysql<span class="token punctuation">]</span><span class="token comment" spellcheck="true"># systemctl list-units --type=service | grep mysql</span>mysqld-3306.service loaded active running MySQL Servermysqld-3307.service loaded active running MySQL Servermysqld-3308.service loaded active running MySQL Server</code></pre><h2 id="mysql语法基础"><a href="#mysql语法基础" class="headerlink" title="mysql语法基础"></a>mysql语法基础</h2><h3 id="SQL分类"><a href="#SQL分类" class="headerlink" title="SQL分类"></a>SQL分类</h3><h4 id="DDL数据定义语言"><a href="#DDL数据定义语言" class="headerlink" title="DDL数据定义语言"></a>DDL数据定义语言</h4><p>定义数据库对象,核心指令<strong>CREATE、ALTER、DROP</strong></p><h4 id="DML数据库操纵语言"><a href="#DML数据库操纵语言" class="headerlink" title="DML数据库操纵语言"></a>DML数据库操纵语言</h4><p>访问数据CRUD(CREATE,READ,UPDATE,DELETE),即增删改查</p><h4 id="TCL事务控制语言"><a href="#TCL事务控制语言" class="headerlink" title="TCL事务控制语言"></a>TCL事务控制语言</h4><p>管理数据库中的事务,核心指令COMMIT、ROLLBAK</p><h4 id="DCL数据控制语言"><a href="#DCL数据控制语言" class="headerlink" title="DCL数据控制语言"></a>DCL数据控制语言</h4><p>对数据访问权控制,核心指令GRANT,REVOKE</p><p>可以控制的权限有:CONNECT,SELECT,INSERT,UPDATE,DELETE,EXECUTE,USAGE,REFERENCES</p><h3 id="连接和组合"><a href="#连接和组合" class="headerlink" title="连接和组合"></a>连接和组合</h3><h4 id="JOIN"><a href="#JOIN" class="headerlink" title="JOIN"></a>JOIN</h4><p>连接可以代替子查询,效率一般比子查询高。</p><p><img src="https://oss.luhuhu.cn/202402080934962.png" alt="join"></p><h4 id="组合"><a href="#组合" class="headerlink" title="组合"></a>组合</h4><p>UNION会去除相同行,UNION ALL 会保留相同行。</p><p>JOIN vs UNION:</p><ul><li>JOIN 中连接的列可能不同,UNION中列、列顺序必须相同</li><li>UNION 讲查询结果行放在一起(垂直放置)但JOIN将查询结果列放在一起(水平放置),即它构成一个笛卡尔积</li></ul><h3 id="函数"><a href="#函数" class="headerlink" title="函数"></a>函数</h3><h4 id="文本处理"><a href="#文本处理" class="headerlink" title="文本处理"></a>文本处理</h4><table><thead><tr><th align="left">函数</th><th align="left">说明</th></tr></thead><tbody><tr><td align="left"><code>LEFT()</code>、<code>RIGHT()</code></td><td align="left">左边或者右边的字符</td></tr><tr><td align="left"><code>LOWER()</code>、<code>UPPER()</code></td><td align="left">转换为小写或者大写</td></tr><tr><td align="left"><code>LTRIM()</code>、<code>RTIM()</code></td><td align="left">去除左边或者右边的空格</td></tr><tr><td align="left"><code>LENGTH()</code></td><td align="left">长度</td></tr><tr><td align="left"><code>SOUNDEX()</code></td><td align="left">转换为语音值</td></tr></tbody></table><h4 id="日期和时间处理"><a href="#日期和时间处理" class="headerlink" title="日期和时间处理"></a>日期和时间处理</h4><table><thead><tr><th align="left">函 数</th><th align="left">说 明</th></tr></thead><tbody><tr><td align="left"><code>AddDate()</code></td><td align="left">增加一个日期(天、周等)</td></tr><tr><td align="left"><code>AddTime()</code></td><td align="left">增加一个时间(时、分等)</td></tr><tr><td align="left"><code>CurDate()</code></td><td align="left">返回当前日期</td></tr><tr><td align="left"><code>CurTime()</code></td><td align="left">返回当前时间</td></tr><tr><td align="left"><code>Date()</code></td><td align="left">返回日期时间的日期部分</td></tr><tr><td align="left"><code>DateDiff()</code></td><td align="left">计算两个日期之差</td></tr><tr><td align="left"><code>Date_Add()</code></td><td align="left">高度灵活的日期运算函数</td></tr><tr><td align="left"><code>Date_Format()</code></td><td align="left">返回一个格式化的日期或时间串</td></tr><tr><td align="left"><code>Day()</code></td><td align="left">返回一个日期的天数部分</td></tr><tr><td align="left"><code>DayOfWeek()</code></td><td align="left">对于一个日期,返回对应的星期几</td></tr><tr><td align="left"><code>Hour()</code></td><td align="left">返回一个时间的小时部分</td></tr><tr><td align="left"><code>Minute()</code></td><td align="left">返回一个时间的分钟部分</td></tr><tr><td align="left"><code>Month()</code></td><td align="left">返回一个日期的月份部分</td></tr><tr><td align="left"><code>Now()</code></td><td align="left">返回当前日期和时间</td></tr><tr><td align="left"><code>Second()</code></td><td align="left">返回一个时间的秒部分</td></tr><tr><td align="left"><code>Time()</code></td><td align="left">返回一个日期时间的时间部分</td></tr><tr><td align="left"><code>Year()</code></td><td align="left">返回一个日期的年份部分</td></tr></tbody></table><h4 id="数值处理"><a href="#数值处理" class="headerlink" title="数值处理"></a>数值处理</h4><table><thead><tr><th align="left">函数</th><th align="left">说明</th></tr></thead><tbody><tr><td align="left">SIN()</td><td align="left">正弦</td></tr><tr><td align="left">COS()</td><td align="left">余弦</td></tr><tr><td align="left">TAN()</td><td align="left">正切</td></tr><tr><td align="left">ABS()</td><td align="left">绝对值</td></tr><tr><td align="left">SQRT()</td><td align="left">平方根</td></tr><tr><td align="left">MOD()</td><td align="left">余数</td></tr><tr><td align="left">EXP()</td><td align="left">指数</td></tr><tr><td align="left">PI()</td><td align="left">圆周率</td></tr><tr><td align="left">RAND()</td><td align="left">随机数</td></tr></tbody></table><h4 id="汇总"><a href="#汇总" class="headerlink" title="汇总"></a>汇总</h4><table><thead><tr><th align="left">函 数</th><th align="left">说 明</th></tr></thead><tbody><tr><td align="left"><code>AVG()</code></td><td align="left">返回某列的平均值</td></tr><tr><td align="left"><code>COUNT()</code></td><td align="left">返回某列的行数</td></tr><tr><td align="left"><code>MAX()</code></td><td align="left">返回某列的最大值</td></tr><tr><td align="left"><code>MIN()</code></td><td align="left">返回某列的最小值</td></tr><tr><td align="left"><code>SUM()</code></td><td align="left">返回某列值之和</td></tr></tbody></table><h3 id="排序与分组"><a href="#排序与分组" class="headerlink" title="排序与分组"></a>排序与分组</h3><h4 id="排序"><a href="#排序" class="headerlink" title="排序"></a>排序</h4><p>ORDER BY ASC/DESC;</p><blockquote><p>// 指定多个列的排序方向</p><p><strong>SELECT</strong> * <strong>FROM</strong> products<br><strong>ORDER</strong> <strong>BY</strong> prod_price <strong>DESC</strong>, prod_name <strong>ASC</strong>;</p></blockquote><h4 id="分组"><a href="#分组" class="headerlink" title="分组"></a>分组</h4><ul><li>GROUP BY</li><li>HAVING<ul><li>HAVING 用于对汇总的GROUP BY 结果进行过滤</li><li>HAVING 要求存在一个GROUP BY子句</li><li>与WHERE差异:HAVING 用于汇总的组记录,WHERE 用于单个记录</li></ul></li></ul><h3 id="视图、索引"><a href="#视图、索引" class="headerlink" title="视图、索引"></a>视图、索引</h3><h4 id="视图"><a href="#视图" class="headerlink" title="视图"></a>视图</h4><ul><li>基于SQL语句结果可视化的表</li><li>虚拟表,不能进行索引操作</li><li>主要用于简化SQL操作</li><li>通过给视图访问权限保证数据安全</li></ul><h4 id="索引"><a href="#索引" class="headerlink" title="索引"></a>索引</h4><ul><li>通过索引更高效地查询数据</li><li>用户无法看到索引,只能用来加速查询</li><li>更新一个包含索引的表需要比更新一个没有索引的表花费更多的时间,这是由于索引本身也需要更新。因此,理想的做法是仅仅在常常被搜索的列(以及表)上面创建索引。</li><li>唯一索引表明此索引的每一个索引值只对应唯一的数据记录。</li></ul><blockquote><p>// 创建索引</p><p><strong>CREATE</strong> <strong>INDEX</strong> user_index<br><strong>ON</strong> <strong>user</strong> (<strong>id</strong>);</p><p>//创建唯一索引</p><p><strong>CREATE</strong> <strong>UNIQUE</strong> <strong>INDEX</strong> user_index<br><strong>ON</strong> <strong>user</strong> (<strong>id</strong>);</p><p>//删除索引</p><p><strong>ALTER</strong> <strong>TABLE</strong> <strong>user</strong><br><strong>DROP</strong> <strong>INDEX</strong> user_index;</p></blockquote><h3 id="存储过程"><a href="#存储过程" class="headerlink" title="存储过程"></a>存储过程</h3><ul><li>存储过程可以看成是对一系列SQL操作的批处理</li><li>优点<ul><li>代码封装</li><li>代码复用</li><li>因为是预先编译,所以性能很高</li></ul></li><li>创建存储过程<ul><li>命令行中创建存储过程需要自定义分隔符,因为命令行是以 <code>;</code> 为结束符,而存储过程中也包含了分号,因此会错误把这部分分号当成是结束符,造成语法错误。</li><li>包含 in、out 和 inout 三种参数。</li><li>给变量赋值都需要用 select into 语句。</li><li>每次只能给一个变量赋值,不支持集合的操作。</li></ul></li></ul><blockquote><p><strong>DROP</strong> <strong>PROCEDURE</strong> <strong>IF</strong> <strong>EXISTS</strong> <code>proc_adder</code>;<br>DELIMITER ;;<br><strong>CREATE</strong> DEFINER=<code>root</code>@<code>localhost</code> <strong>PROCEDURE</strong> <code>proc_adder</code>(<strong>IN</strong> a int, <strong>IN</strong> b int, <strong>OUT</strong> <strong>sum</strong> int)<br><strong>BEGIN</strong><br><strong>DECLARE</strong> c int;<br>if a is null then <strong>set</strong> a = 0;<br><strong>end</strong> <strong>if</strong>;</p><p>if b is null then <strong>set</strong> b = 0;<br><strong>end</strong> <strong>if</strong>;</p><p><strong>set</strong> <strong>sum</strong> = a + b;<br><strong>END</strong><br>;;<br>DELIMITER ;</p></blockquote><blockquote><p><strong>set</strong> @b=5;<br><strong>call</strong> proc_adder(2,@b,@s);<br><strong>select</strong> @s <strong>as</strong> <strong>sum</strong>;</p></blockquote><h3 id="游标"><a href="#游标" class="headerlink" title="游标"></a>游标</h3><p>游标是一个存储在DBMS服务器上的数据库查询,不是SELECT语句,而是SELECT检索的结果集。</p><p>主要用于交互式应用,用户需要对数据集重的任意行进行浏览和修改。</p><blockquote><p>DELIMITER $<br><strong>CREATE</strong> <strong>PROCEDURE</strong> getTotal()<br><strong>BEGIN</strong><br><strong>DECLARE</strong> total INT;<br><em>– 创建接收游标数据的变量</em><br><strong>DECLARE</strong> <strong>sid</strong> INT;<br><strong>DECLARE</strong> sname VARCHAR(10);<br><em>– 创建总数变量</em><br><strong>DECLARE</strong> sage INT;<br><em>– 创建结束标志变量</em><br><strong>DECLARE</strong> done INT <strong>DEFAULT</strong> false;<br><em>– 创建游标</em><br><strong>DECLARE</strong> cur <strong>CURSOR</strong> <strong>FOR</strong> <strong>SELECT</strong> <strong>id</strong>,<strong>name</strong>,age <strong>from</strong> cursor_table <strong>where</strong> age>30;<br><em>– 指定游标循环结束时的返回值</em><br><strong>DECLARE</strong> CONTINUE <strong>HANDLER</strong> <strong>FOR</strong> <strong>NOT</strong> <strong>FOUND</strong> <strong>SET</strong> done = true;<br><strong>SET</strong> total = 0;<br>OPEN cur;<br>FETCH cur INTO sid, sname, sage;<br>WHILE(NOT done)<br><strong>DO</strong><br> <strong>SET</strong> total = total + 1;<br> FETCH cur INTO sid, sname, sage;<br><strong>END</strong> <strong>WHILE</strong>;</p><p>CLOSE cur;<br><strong>SELECT</strong> total;<br><strong>END</strong> $<br>DELIMITER ;</p><p><em>– 调用存储过程</em><br><strong>call</strong> getTotal();</p></blockquote><h3 id="触发器"><a href="#触发器" class="headerlink" title="触发器"></a>触发器</h3><p>触发器是一种与表操作有关的数据库对象,当表出现指定时间时,将调用该对象。</p><h4 id="new-old"><a href="#new-old" class="headerlink" title="new/old"></a>new/old</h4><ul><li>MySQL 中定义了 <code>NEW</code> 和 <code>OLD</code> 关键字,用来表示触发器的所在表中,触发了触发器的那一行数据。</li><li>在 <code>INSERT</code> 型触发器中,<code>NEW</code> 用来表示将要(<code>BEFORE</code>)或已经(<code>AFTER</code>)插入的新数据;</li><li>在 <code>UPDATE</code> 型触发器中,<code>OLD</code> 用来表示将要或已经被修改的原数据,<code>NEW</code> 用来表示将要或已经修改为的新数据;</li><li>在 <code>DELETE</code> 型触发器中,<code>OLD</code> 用来表示将要或已经被删除的原数据;</li><li>使用方法:<code>NEW.columnName</code> (columnName 为相应数据表某一列名)</li></ul><blockquote><p>DELIMITER $<br><strong>CREATE</strong> <strong>TRIGGER</strong> <code>trigger_insert_user</code><br><strong>AFTER</strong> <strong>INSERT</strong> <strong>ON</strong> <code>user</code><br><strong>FOR</strong> <strong>EACH</strong> <strong>ROW</strong><br><strong>BEGIN</strong><br><strong>INSERT</strong> <strong>INTO</strong> <code>user_history</code>(user_id, operate_type, operate_time)<br><strong>VALUES</strong> (NEW.id, ‘add a user’, <strong>now</strong>());<br><strong>END</strong> $<br>DELIMITER ;</p></blockquote>]]></content>
<categories>
<category> CS </category>
</categories>
<tags>
<tag> MySql </tag>
</tags>
</entry>
<entry>
<title>MyBatis</title>
<link href="/post/1bff3c65.html"/>
<url>/post/1bff3c65.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><p><img src="https://oss.luhuhu.cn/202406051159806.png"></p><h1 id="Mybatis简介"><a href="#Mybatis简介" class="headerlink" title="Mybatis简介"></a>Mybatis简介</h1><h2 id="MyBatis历史"><a href="#MyBatis历史" class="headerlink" title="MyBatis历史"></a>MyBatis历史</h2><ul><li>MyBatis最初是Apache的一个开源项目iBatis, 2010年6月这个项目由Apache Software Foundation迁移到了Google Code。随着开发团队转投Google Code旗下,iBatis3.x正式更名为MyBatis。代码于2013年11月迁移到Github</li><li>iBatis一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBatis提供的持久层框架包括SQL Maps和Data Access Objects(DAO)</li></ul><h2 id="MyBatis特性"><a href="#MyBatis特性" class="headerlink" title="MyBatis特性"></a>MyBatis特性</h2><ol><li>MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架</li><li>MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集</li><li>MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录</li><li>MyBatis 是一个 半自动的ORM(Object Relation Mapping)框架</li></ol><h2 id="MyBatis下载"><a href="#MyBatis下载" class="headerlink" title="MyBatis下载"></a>MyBatis下载</h2><ul><li><a href="https://github.com/mybatis/mybatis-3">MyBatis下载地址</a></li><li><img src="https://oss.luhuhu.cn/202402080922656.png"></li></ul><h2 id="和其它持久化层技术对比"><a href="#和其它持久化层技术对比" class="headerlink" title="和其它持久化层技术对比"></a>和其它持久化层技术对比</h2><ul><li>JDBC </li><li>SQL 夹杂在Java代码中耦合度高,导致硬编码内伤 <ul><li>维护不易且实际开发需求中 SQL 有变化,频繁修改的情况多见 </li><li>代码冗长,开发效率低</li></ul></li><li>Hibernate 和 JPA</li><li>操作简便,开发效率高 <ul><li>程序中的长难复杂 SQL 需要绕过框架 </li><li>内部自动生产的 SQL,不容易做特殊优化 </li><li>基于全映射的全自动框架,大量字段的 POJO 进行部分映射时比较困难。 </li><li>反射操作太多,导致数据库性能下降</li></ul></li><li>MyBatis</li><li>轻量级,性能出色 <ul><li>SQL 和 Java 编码分开,功能边界清晰。Java代码专注业务、SQL语句专注数据 </li><li>开发效率稍逊于HIbernate,但是完全能够接受</li></ul></li></ul><h1 id="搭建MyBatis"><a href="#搭建MyBatis" class="headerlink" title="搭建MyBatis"></a>搭建MyBatis</h1><h2 id="开发环境"><a href="#开发环境" class="headerlink" title="开发环境"></a>开发环境</h2><ul><li>IDE:idea 2019.2 </li><li>构建工具:maven 3.5.4 </li><li>MySQL版本:MySQL 5.7 </li><li>MyBatis版本:MyBatis 3.5.7</li></ul><h2 id="创建maven工程"><a href="#创建maven工程" class="headerlink" title="创建maven工程"></a>创建maven工程</h2><ul><li><p>打包方式:jar</p></li><li><p>引入依赖</p><pre class=" language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependencies</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- Mybatis核心 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>org.mybatis<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>mybatis<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>3.5.7<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- junit测试 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>junit<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>junit<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>4.12<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>scope</span><span class="token punctuation">></span></span>test<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>scope</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- MySQL驱动 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>mysql<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>mysql-connector-java<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>5.1.3<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependencies</span><span class="token punctuation">></span></span></code></pre></li></ul><h2 id="创建MyBatis的核心配置文件"><a href="#创建MyBatis的核心配置文件" class="headerlink" title="创建MyBatis的核心配置文件"></a>创建MyBatis的核心配置文件</h2><blockquote><p>习惯上命名为<code>mybatis-config.xml</code>,这个文件名仅仅只是建议,并非强制要求。将来整合Spring之后,这个配置文件可以省略,所以大家操作时可以直接复制、粘贴。<br>核心配置文件主要用于配置连接数据库的环境以及MyBatis的全局配置信息<br>核心配置文件存放的位置是src/main/resources目录下</p></blockquote><pre class=" language-xml"><code class="language-xml"><span class="token prolog"><?xml version="1.0" encoding="UTF-8" ?></span> <span class="token doctype"><!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>configuration</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!--设置连接数据库的环境--></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>environments</span> <span class="token attr-name">default</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>development<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>environment</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>development<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>transactionManager</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>JDBC<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dataSource</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>POOLED<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>property</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>driver<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>com.mysql.cj.jdbc.Driver<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>property</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>url<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>jdbc:mysql://localhost:3306/MyBatis<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>property</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>username<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>root<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>property</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>password<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>123456<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dataSource</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>environment</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>environments</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!--引入映射文件--></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>mappers</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>mapper</span> <span class="token attr-name">resource</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>mappers/UserMapper.xml<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>mappers</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>configuration</span><span class="token punctuation">></span></span></code></pre><h2 id="创建mapper接口"><a href="#创建mapper接口" class="headerlink" title="创建mapper接口"></a>创建mapper接口</h2><blockquote><p>MyBatis中的mapper接口相当于以前的dao。但是区别在于,mapper仅仅是接口,我们不需要提供实现类</p></blockquote><pre class=" language-java"><code class="language-java"><span class="token keyword">package</span> com<span class="token punctuation">.</span>atguigu<span class="token punctuation">.</span>mybatis<span class="token punctuation">.</span>mapper<span class="token punctuation">;</span> <span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">UserMapper</span> <span class="token punctuation">{</span> <span class="token comment" spellcheck="true">/** * 添加用户信息 */</span> <span class="token keyword">int</span> <span class="token function">insertUser</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span></code></pre><h2 id="创建MyBatis的映射文件"><a href="#创建MyBatis的映射文件" class="headerlink" title="创建MyBatis的映射文件"></a>创建MyBatis的映射文件</h2><ul><li>相关概念:ORM(Object Relationship Mapping)对象关系映射。 </li><li>对象:Java的实体类对象 <ul><li>关系:关系型数据库 </li><li>映射:二者之间的对应关系</li></ul></li></ul><table><thead><tr><th>Java概念</th><th>数据库概念</th></tr></thead><tbody><tr><td>类</td><td>表</td></tr><tr><td>属性</td><td>字段/列</td></tr><tr><td>对象</td><td>记录/行</td></tr></tbody></table><ul><li>映射文件的命名规则</li><li>表所对应的实体类的类名+Mapper.xml<ul><li>例如:表t_user,映射的实体类为User,所对应的映射文件为UserMapper.xml </li><li>因此一个映射文件对应一个实体类,对应一张表的操作</li><li>MyBatis映射文件用于编写SQL,访问以及操作表中的数据</li><li>MyBatis映射文件存放的位置是src/main/resources/mappers目录下</li></ul></li><li>MyBatis中可以面向接口操作数据,要保证两个一致</li><li>mapper接口的全类名和映射文件的命名空间(namespace)保持一致<ul><li>mapper接口中方法的方法名和映射文件中编写SQL的标签的id属性保持一致</li></ul></li></ul><pre class=" language-xml"><code class="language-xml"><span class="token prolog"><?xml version="1.0" encoding="UTF-8" ?></span> <span class="token doctype"><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>mapper</span> <span class="token attr-name">namespace</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>com.atguigu.mybatis.mapper.UserMapper<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!--int insertUser();--></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>insert</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>insertUser<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> insert into t_user values(null,'张三','123',23,'女') <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>insert</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>mapper</span><span class="token punctuation">></span></span></code></pre><h2 id="通过junit测试功能"><a href="#通过junit测试功能" class="headerlink" title="通过junit测试功能"></a>通过junit测试功能</h2><ul><li>SqlSession:代表Java程序和数据库之间的会话。(HttpSession是Java程序和浏览器之间的会话)</li><li>SqlSessionFactory:是“生产”SqlSession的“工厂”</li><li>工厂模式:如果创建某一个对象,使用的过程基本固定,那么我们就可以把创建这个对象的相关代码封装到一个“工厂类”中,以后都使用这个工厂类来“生产”我们需要的对象</li></ul><pre class=" language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">UserMapperTest</span> <span class="token punctuation">{</span> <span class="token annotation punctuation">@Test</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">testInsertUser</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> IOException <span class="token punctuation">{</span> <span class="token comment" spellcheck="true">//读取MyBatis的核心配置文件</span> InputStream is <span class="token operator">=</span> Resources<span class="token punctuation">.</span><span class="token function">getResourceAsStream</span><span class="token punctuation">(</span><span class="token string">"mybatis-config.xml"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">//获取SqlSessionFactoryBuilder对象</span> SqlSessionFactoryBuilder sqlSessionFactoryBuilder <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SqlSessionFactoryBuilder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">//通过核心配置文件所对应的字节输入流创建工厂类SqlSessionFactory,生产SqlSession对象</span> SqlSessionFactory sqlSessionFactory <span class="token operator">=</span> sqlSessionFactoryBuilder<span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span>is<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">//获取sqlSession,此时通过SqlSession对象所操作的sql都必须手动提交或回滚事务</span> <span class="token comment" spellcheck="true">//SqlSession sqlSession = sqlSessionFactory.openSession();</span> <span class="token comment" spellcheck="true">//创建SqlSession对象,此时通过SqlSession对象所操作的sql都会自动提交 </span> SqlSession sqlSession <span class="token operator">=</span> sqlSessionFactory<span class="token punctuation">.</span><span class="token function">openSession</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">//通过代理模式创建UserMapper接口的代理实现类对象</span> UserMapper userMapper <span class="token operator">=</span> sqlSession<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span>UserMapper<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">//调用UserMapper接口中的方法,就可以根据UserMapper的全类名匹配元素文件,通过调用的方法名匹配映射文件中的SQL标签,并执行标签中的SQL语句</span> <span class="token keyword">int</span> result <span class="token operator">=</span> userMapper<span class="token punctuation">.</span><span class="token function">insertUser</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">//提交事务</span> <span class="token comment" spellcheck="true">//sqlSession.commit();</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"result:"</span> <span class="token operator">+</span> result<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">}</span></code></pre><ul><li>此时需要手动提交事务,如果要自动提交事务,则在获取sqlSession对象时,使用<code>SqlSession sqlSession = sqlSessionFactory.openSession(true);</code>,传入一个Boolean类型的参数,值为true,这样就可以自动提交</li></ul><h2 id="加入log4j日志功能"><a href="#加入log4j日志功能" class="headerlink" title="加入log4j日志功能"></a>加入log4j日志功能</h2><ol><li><p>加入依赖</p><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!-- log4j日志 --></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>log4j<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>log4j<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>1.2.17<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span></code></pre></li><li><p>加入log4j的配置文件</p><ul><li>log4j的配置文件名为log4j.xml,存放的位置是src/main/resources目录下</li><li>日志的级别:FATAL(致命)>ERROR(错误)>WARN(警告)>INFO(信息)>DEBUG(调试) 从左到右打印的内容越来越详细</li></ul><pre class=" language-xml"><code class="language-xml"><span class="token prolog"><?xml version="1.0" encoding="UTF-8" ?></span><span class="token doctype"><!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token namespace">log4j:</span>configuration</span> <span class="token attr-name"><span class="token namespace">xmlns:</span>log4j</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>http://jakarta.apache.org/log4j/<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>appender</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>STDOUT<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>org.apache.log4j.ConsoleAppender<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>param</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Encoding<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>UTF-8<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>layout</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>org.apache.log4j.PatternLayout<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>param</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>ConversionPattern<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>layout</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>appender</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>logger</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>java.sql<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>level</span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>debug<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>logger</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>logger</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>org.apache.ibatis<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>level</span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>info<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>logger</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>root</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>level</span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>debug<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>appender-ref</span> <span class="token attr-name">ref</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>STDOUT<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>root</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span><span class="token namespace">log4j:</span>configuration</span><span class="token punctuation">></span></span></code></pre></li></ol><h1 id="核心配置文件详解"><a href="#核心配置文件详解" class="headerlink" title="核心配置文件详解"></a>核心配置文件详解</h1><blockquote><p>核心配置文件中的标签必须按照固定的顺序(有的标签可以不写,但顺序一定不能乱):<br>properties、settings、typeAliases、typeHandlers、objectFactory、objectWrapperFactory、reflectorFactory、plugins、environments、databaseIdProvider、mappers</p></blockquote><pre class=" language-xml"><code class="language-xml"><span class="token prolog"><?xml version="1.0" encoding="UTF-8" ?></span><span class="token doctype"><!DOCTYPE configuration PUBLIC "-//MyBatis.org//DTD Config 3.0//EN" "http://MyBatis.org/dtd/MyBatis-3-config.dtd"></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>configuration</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!--引入properties文件,此时就可以${属性名}的方式访问属性值--></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>properties</span> <span class="token attr-name">resource</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>jdbc.properties<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>properties</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>settings</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!--将表中字段的下划线自动转换为驼峰--></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>setting</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>mapUnderscoreToCamelCase<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span> <span class="token comment" spellcheck="true"><!--开启延迟加载--></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>setting</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>lazyLoadingEnabled<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>settings</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>typeAliases</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- typeAlias:设置某个具体的类型的别名 属性: type:需要设置别名的类型的全类名 alias:设置此类型的别名,且别名不区分大小写。若不设置此属性,该类型拥有默认的别名,即类名 --></span> <span class="token comment" spellcheck="true"><!--<typeAlias type="com.atguigu.mybatis.bean.User"></typeAlias>--></span> <span class="token comment" spellcheck="true"><!--<typeAlias type="com.atguigu.mybatis.bean.User" alias="user"> </typeAlias>--></span> <span class="token comment" spellcheck="true"><!--以包为单位,设置改包下所有的类型都拥有默认的别名,即类名且不区分大小写--></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>package</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>com.atguigu.mybatis.bean<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>typeAliases</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- environments:设置多个连接数据库的环境 属性: default:设置默认使用的环境的id --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>environments</span> <span class="token attr-name">default</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>mysql_test<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- environment:设置具体的连接数据库的环境信息 属性: id:设置环境的唯一标识,可通过environments标签中的default设置某一个环境的id,表示默认使用的环境 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>environment</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>mysql_test<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- transactionManager:设置事务管理方式 属性: type:设置事务管理方式,type="JDBC|MANAGED" type="JDBC":设置当前环境的事务管理都必须手动处理 type="MANAGED":设置事务被管理,例如spring中的AOP --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>transactionManager</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>JDBC<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span> <span class="token comment" spellcheck="true"><!-- dataSource:设置数据源 属性: type:设置数据源的类型,type="POOLED|UNPOOLED|JNDI" type="POOLED":使用数据库连接池,即会将创建的连接进行缓存,下次使用可以从缓存中直接获取,不需要重新创建 type="UNPOOLED":不使用数据库连接池,即每次使用连接都需要重新创建 type="JNDI":调用上下文中的数据源 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dataSource</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>POOLED<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!--设置驱动类的全类名--></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>property</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>driver<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>${jdbc.driver}<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span> <span class="token comment" spellcheck="true"><!--设置连接数据库的连接地址--></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>property</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>url<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>${jdbc.url}<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span> <span class="token comment" spellcheck="true"><!--设置连接数据库的用户名--></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>property</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>username<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>${jdbc.username}<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span> <span class="token comment" spellcheck="true"><!--设置连接数据库的密码--></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>property</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>password<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>${jdbc.password}<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dataSource</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>environment</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>environments</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!--引入映射文件--></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>mappers</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- <mapper resource="UserMapper.xml"/> --></span> <span class="token comment" spellcheck="true"><!-- 以包为单位,将包下所有的映射文件引入核心配置文件 注意: 1. 此方式必须保证mapper接口和mapper映射文件必须在相同的包下 2. mapper接口要和mapper映射文件的名字一致 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>package</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>com.atguigu.mybatis.mapper<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>mappers</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>configuration</span><span class="token punctuation">></span></span></code></pre><ul><li><img src="https://oss.luhuhu.cn/202402080923480.png"></li></ul><h1 id="默认的类型别名"><a href="#默认的类型别名" class="headerlink" title="默认的类型别名"></a>默认的类型别名</h1><p><img src="https://oss.luhuhu.cn/202402080923140.png"><br><img src="C:/Users/loaderland/Desktop/Learn/MyBatis/Resources/默认的类型别名2.png"></p><h1 id="MyBatis的增删改查"><a href="#MyBatis的增删改查" class="headerlink" title="MyBatis的增删改查"></a>MyBatis的增删改查</h1><ol><li><p>添加</p><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--int insertUser();--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>insert</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>insertUser<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> insert into t_user values(null,'admin','123456',23,'男','[email protected]')<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>insert</span><span class="token punctuation">></span></span></code></pre></li><li><p>删除</p><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--int deleteUser();--></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>delete</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>deleteUser<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> delete from t_user where id = 6 <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>delete</span><span class="token punctuation">></span></span></code></pre></li><li><p>修改</p><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--int updateUser();--></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>update</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>updateUser<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> update t_user set username = '张三' where id = 5 <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>update</span><span class="token punctuation">></span></span></code></pre></li><li><p>查询一个实体类对象</p><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--User getUserById();--></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>getUserById<span class="token punctuation">"</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>com.atguigu.mybatis.bean.User<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select * from t_user where id = 2 <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span></code></pre></li><li><p>查询集合</p><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--List<User> getUserList();--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>getUserList<span class="token punctuation">"</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>com.atguigu.mybatis.bean.User<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select * from t_user<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span></code></pre></li></ol><ul><li><p>注意:</p><ol><li>查询的标签select必须设置属性resultType或resultMap,用于设置实体类和数据库表的映射关系 <ul><li>resultType:自动映射,用于属性名和表中字段名一致的情况 </li><li>resultMap:自定义映射,用于一对多或多对一或字段名和属性名不一致的情况</li></ul></li><li>当查询的数据为多条时,不能使用实体类作为返回值,只能使用集合,否则会抛出异常TooManyResultsException;但是若查询的数据只有一条,可以使用实体类或集合作为返回值</li></ol></li></ul><h1 id="MyBatis获取参数值的两种方式(重点)"><a href="#MyBatis获取参数值的两种方式(重点)" class="headerlink" title="MyBatis获取参数值的两种方式(重点)"></a>MyBatis获取参数值的两种方式(重点)</h1><ul><li>MyBatis获取参数值的两种方式:${}和#{} </li><li>${}的本质就是字符串拼接,#{}的本质就是占位符赋值 </li><li>${}使用字符串拼接的方式拼接sql,若为字符串类型或日期类型的字段进行赋值时,需要手动加单引号;但是#{}使用占位符赋值的方式拼接sql,此时为字符串类型或日期类型的字段进行赋值时,可以自动添加单引号</li></ul><h2 id="单个字面量类型的参数"><a href="#单个字面量类型的参数" class="headerlink" title="单个字面量类型的参数"></a>单个字面量类型的参数</h2><ul><li>若mapper接口中的方法参数为单个的字面量类型,此时可以使用${}和#{}以任意的名称(最好见名识意)获取参数的值,注意${}需要手动加单引号</li></ul><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--User getUserByUsername(String username);--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>getUserByUsername<span class="token punctuation">"</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>User<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select * from t_user where username = #{username}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span></code></pre><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--User getUserByUsername(String username);--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>getUserByUsername<span class="token punctuation">"</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>User<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select * from t_user where username = '${username}' <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span></code></pre><h2 id="多个字面量类型的参数"><a href="#多个字面量类型的参数" class="headerlink" title="多个字面量类型的参数"></a>多个字面量类型的参数</h2><ul><li><p>若mapper接口中的方法参数为多个时,此时MyBatis会自动将这些参数放在一个map集合中</p><ol><li>以arg0,arg1…为键,以参数为值;</li><li>以param1,param2…为键,以参数为值;</li></ol></li><li><p>因此只需要通过${}和#{}访问map集合的键就可以获取相对应的值,注意${}需要手动加单引号。</p></li><li><p>使用arg或者param都行,要注意的是,arg是从arg0开始的,param是从param1开始的</p></li></ul><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--User checkLogin(String username,String password);--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>checkLogin<span class="token punctuation">"</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>User<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select * from t_user where username = #{arg0} and password = #{arg1} <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span></code></pre><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--User checkLogin(String username,String password);--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>checkLogin<span class="token punctuation">"</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>User<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select * from t_user where username = '${param1}' and password = '${param2}'<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span></code></pre><h2 id="map集合类型的参数"><a href="#map集合类型的参数" class="headerlink" title="map集合类型的参数"></a>map集合类型的参数</h2><ul><li>若mapper接口中的方法需要的参数为多个时,此时可以手动创建map集合,将这些数据放在map中只需要通过${}和#{}访问map集合的键就可以获取相对应的值,注意${}需要手动加单引号</li></ul><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--User checkLoginByMap(Map<String,Object> map);--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>checkLoginByMap<span class="token punctuation">"</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>User<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select * from t_user where username = #{username} and password = #{password}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span></code></pre><pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Test</span><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">checkLoginByMap</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> SqlSession sqlSession <span class="token operator">=</span> SqlSessionUtils<span class="token punctuation">.</span><span class="token function">getSqlSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> ParameterMapper mapper <span class="token operator">=</span> sqlSession<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span>ParameterMapper<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> Map<span class="token operator"><</span>String<span class="token punctuation">,</span>Object<span class="token operator">></span> map <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HashMap</span><span class="token operator"><</span><span class="token operator">></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> map<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">"usermane"</span><span class="token punctuation">,</span><span class="token string">"admin"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> map<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">"password"</span><span class="token punctuation">,</span><span class="token string">"123456"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> User user <span class="token operator">=</span> mapper<span class="token punctuation">.</span><span class="token function">checkLoginByMap</span><span class="token punctuation">(</span>map<span class="token punctuation">)</span><span class="token punctuation">;</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span></code></pre><h2 id="实体类类型的参数"><a href="#实体类类型的参数" class="headerlink" title="实体类类型的参数"></a>实体类类型的参数</h2><ul><li>若mapper接口中的方法参数为实体类对象时此时可以使用${}和#{},通过访问实体类对象中的属性名获取属性值,注意${}需要手动加单引号</li></ul><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--int insertUser(User user);--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>insert</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>insertUser<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> insert into t_user values(null,#{username},#{password},#{age},#{sex},#{email})<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>insert</span><span class="token punctuation">></span></span></code></pre><pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Test</span><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">insertUser</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> SqlSession sqlSession <span class="token operator">=</span> SqlSessionUtils<span class="token punctuation">.</span><span class="token function">getSqlSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> ParameterMapper mapper <span class="token operator">=</span> sqlSession<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span>ParameterMapper<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> User user <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">User</span><span class="token punctuation">(</span>null<span class="token punctuation">,</span><span class="token string">"Tom"</span><span class="token punctuation">,</span><span class="token string">"123456"</span><span class="token punctuation">,</span><span class="token number">12</span><span class="token punctuation">,</span><span class="token string">"男"</span><span class="token punctuation">,</span><span class="token string">"[email protected]"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> mapper<span class="token punctuation">.</span><span class="token function">insertUser</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span></code></pre><h2 id="使用-Param标识参数"><a href="#使用-Param标识参数" class="headerlink" title="使用@Param标识参数"></a>使用@Param标识参数</h2><ul><li><p>可以通过@Param注解标识mapper接口中的方法参数,此时,会将这些参数放在map集合中 </p><ol><li>以@Param注解的value属性值为键,以参数为值;</li><li>以param1,param2…为键,以参数为值;</li></ol></li><li><p>只需要通过${}和#{}访问map集合的键就可以获取相对应的值,注意${}需要手动加单引号</p></li></ul><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--User CheckLoginByParam(@Param("username") String username, @Param("password") String password);--></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>CheckLoginByParam<span class="token punctuation">"</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>User<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select * from t_user where username = #{username} and password = #{password} <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span></code></pre><pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Test</span><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">checkLoginByParam</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> SqlSession sqlSession <span class="token operator">=</span> SqlSessionUtils<span class="token punctuation">.</span><span class="token function">getSqlSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> ParameterMapper mapper <span class="token operator">=</span> sqlSession<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span>ParameterMapper<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> mapper<span class="token punctuation">.</span><span class="token function">CheckLoginByParam</span><span class="token punctuation">(</span><span class="token string">"admin"</span><span class="token punctuation">,</span><span class="token string">"123456"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span></code></pre><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><ul><li><p>建议分成两种情况进行处理</p><ol><li>实体类类型的参数</li><li>使用@Param标识参数</li></ol></li></ul><h1 id="MyBatis的各种查询功能"><a href="#MyBatis的各种查询功能" class="headerlink" title="MyBatis的各种查询功能"></a>MyBatis的各种查询功能</h1><ol><li>如果查询出的数据只有一条,可以通过<ol><li>实体类对象接收</li><li>List集合接收</li><li>Map集合接收,结果<code>{password=123456, sex=男, id=1, age=23, username=admin}</code></li></ol></li><li>如果查询出的数据有多条,一定不能用实体类对象接收,会抛异常TooManyResultsException,可以通过<ol><li>实体类类型的LIst集合接收</li><li>Map类型的LIst集合接收</li><li>在mapper接口的方法上添加@MapKey注解</li></ol></li></ol><h2 id="查询一个实体类对象"><a href="#查询一个实体类对象" class="headerlink" title="查询一个实体类对象"></a>查询一个实体类对象</h2><pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">/** * 根据用户id查询用户信息 * @param id * @return */</span>User <span class="token function">getUserById</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Param</span><span class="token punctuation">(</span><span class="token string">"id"</span><span class="token punctuation">)</span> <span class="token keyword">int</span> id<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--User getUserById(@Param("id") int id);--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>getUserById<span class="token punctuation">"</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>User<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select * from t_user where id = #{id}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span></code></pre><h2 id="查询一个List集合"><a href="#查询一个List集合" class="headerlink" title="查询一个List集合"></a>查询一个List集合</h2><pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">/** * 查询所有用户信息 * @return */</span>List<span class="token operator"><</span>User<span class="token operator">></span> <span class="token function">getUserList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--List<User> getUserList();--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>getUserList<span class="token punctuation">"</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>User<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select * from t_user<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span></code></pre><h2 id="查询单个数据"><a href="#查询单个数据" class="headerlink" title="查询单个数据"></a>查询单个数据</h2><pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">/** * 查询用户的总记录数 * @return * 在MyBatis中,对于Java中常用的类型都设置了类型别名 * 例如:java.lang.Integer-->int|integer * 例如:int-->_int|_integer * 例如:Map-->map,List-->list */</span> <span class="token keyword">int</span> <span class="token function">getCount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--int getCount();--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>getCount<span class="token punctuation">"</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>_integer<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select count(id) from t_user<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span></code></pre><h2 id="查询一条数据为map集合"><a href="#查询一条数据为map集合" class="headerlink" title="查询一条数据为map集合"></a>查询一条数据为map集合</h2><pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">/** * 根据用户id查询用户信息为map集合 * @param id * @return */</span> Map<span class="token operator"><</span>String<span class="token punctuation">,</span> Object<span class="token operator">></span> <span class="token function">getUserToMap</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Param</span><span class="token punctuation">(</span><span class="token string">"id"</span><span class="token punctuation">)</span> <span class="token keyword">int</span> id<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--Map<String, Object> getUserToMap(@Param("id") int id);--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>getUserToMap<span class="token punctuation">"</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>map<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select * from t_user where id = #{id}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span><span class="token comment" spellcheck="true"><!--结果:{password=123456, sex=男, id=1, age=23, username=admin}--></span></code></pre><h2 id="查询多条数据为map集合"><a href="#查询多条数据为map集合" class="headerlink" title="查询多条数据为map集合"></a>查询多条数据为map集合</h2><h3 id="方法一"><a href="#方法一" class="headerlink" title="方法一"></a>方法一</h3><pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">/** * 查询所有用户信息为map集合 * @return * 将表中的数据以map集合的方式查询,一条数据对应一个map;若有多条数据,就会产生多个map集合,此时可以将这些map放在一个list集合中获取 */</span> List<span class="token operator"><</span>Map<span class="token operator"><</span>String<span class="token punctuation">,</span> Object<span class="token operator">>></span> <span class="token function">getAllUserToMap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--Map<String, Object> getAllUserToMap();--></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>getAllUserToMap<span class="token punctuation">"</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>map<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select * from t_user <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span><span class="token comment" spellcheck="true"><!-- 结果: [{password=123456, sex=男, id=1, age=23, username=admin}, {password=123456, sex=男, id=2, age=23, username=张三}, {password=123456, sex=男, id=3, age=23, username=张三}]--></span></code></pre><h3 id="方法二"><a href="#方法二" class="headerlink" title="方法二"></a>方法二</h3><pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">/** * 查询所有用户信息为map集合 * @return * 将表中的数据以map集合的方式查询,一条数据对应一个map;若有多条数据,就会产生多个map集合,并且最终要以一个map的方式返回数据,此时需要通过@MapKey注解设置map集合的键,值是每条数据所对应的map集合 */</span><span class="token annotation punctuation">@MapKey</span><span class="token punctuation">(</span><span class="token string">"id"</span><span class="token punctuation">)</span>Map<span class="token operator"><</span>String<span class="token punctuation">,</span> Object<span class="token operator">></span> <span class="token function">getAllUserToMap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--Map<String, Object> getAllUserToMap();--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>getAllUserToMap<span class="token punctuation">"</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>map<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select * from t_user<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span><span class="token comment" spellcheck="true"><!-- 结果: { 1={password=123456, sex=男, id=1, age=23, username=admin}, 2={password=123456, sex=男, id=2, age=23, username=张三}, 3={password=123456, sex=男, id=3, age=23, username=张三} }--></span></code></pre><h1 id="特殊SQL的执行"><a href="#特殊SQL的执行" class="headerlink" title="特殊SQL的执行"></a>特殊SQL的执行</h1><h2 id="模糊查询"><a href="#模糊查询" class="headerlink" title="模糊查询"></a>模糊查询</h2><pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">/** * 根据用户名进行模糊查询 * @param username * @return java.util.List<com.atguigu.mybatis.pojo.User> * @date 2022/2/26 21:56 */</span>List<span class="token operator"><</span>User<span class="token operator">></span> <span class="token function">getUserByLike</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Param</span><span class="token punctuation">(</span><span class="token string">"username"</span><span class="token punctuation">)</span> String username<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--List<User> getUserByLike(@Param("username") String username);--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>getUserByLike<span class="token punctuation">"</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>User<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!--select * from t_user where username like '%${mohu}%'--></span> <span class="token comment" spellcheck="true"><!--select * from t_user where username like concat('%',#{mohu},'%')--></span> select * from t_user where username like "%"#{mohu}"%"<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span></code></pre><ul><li>其中<code>select * from t_user where username like "%"#{mohu}"%"</code>是最常用的</li></ul><h2 id="批量删除"><a href="#批量删除" class="headerlink" title="批量删除"></a>批量删除</h2><ul><li>只能使用${},如果使用#{},则解析后的sql语句为<code>delete from t_user where id in ('1,2,3')</code>,这样是将<code>1,2,3</code>看做是一个整体,只有id为<code>1,2,3</code>的数据会被删除。正确的语句应该是<code>delete from t_user where id in (1,2,3)</code>,或者<code>delete from t_user where id in ('1','2','3')</code></li></ul><pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">/** * 根据id批量删除 * @param ids * @return int * @date 2022/2/26 22:06 */</span><span class="token keyword">int</span> <span class="token function">deleteMore</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Param</span><span class="token punctuation">(</span><span class="token string">"ids"</span><span class="token punctuation">)</span> String ids<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><pre class=" language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>delete</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>deleteMore<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> delete from t_user where id in (${ids})<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>delete</span><span class="token punctuation">></span></span></code></pre><pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">//测试类</span><span class="token annotation punctuation">@Test</span><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">deleteMore</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> SqlSession sqlSession <span class="token operator">=</span> SqlSessionUtils<span class="token punctuation">.</span><span class="token function">getSqlSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> SQLMapper mapper <span class="token operator">=</span> sqlSession<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span>SQLMapper<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">int</span> result <span class="token operator">=</span> mapper<span class="token punctuation">.</span><span class="token function">deleteMore</span><span class="token punctuation">(</span><span class="token string">"1,2,3,8"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span></code></pre><h2 id="动态设置表名"><a href="#动态设置表名" class="headerlink" title="动态设置表名"></a>动态设置表名</h2><ul><li>只能使用${},因为表名不能加单引号</li></ul><pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">/** * 查询指定表中的数据 * @param tableName * @return java.util.List<com.atguigu.mybatis.pojo.User> * @date 2022/2/27 14:41 */</span>List<span class="token operator"><</span>User<span class="token operator">></span> <span class="token function">getUserByTable</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Param</span><span class="token punctuation">(</span><span class="token string">"tableName"</span><span class="token punctuation">)</span> String tableName<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--List<User> getUserByTable(@Param("tableName") String tableName);--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>getUserByTable<span class="token punctuation">"</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>User<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select * from ${tableName}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span></code></pre><h2 id="添加功能获取自增的主键"><a href="#添加功能获取自增的主键" class="headerlink" title="添加功能获取自增的主键"></a>添加功能获取自增的主键</h2><ul><li><p>使用场景</p></li><li><p>t_clazz(clazz_id,clazz_name) </p><ul><li>t_student(student_id,student_name,clazz_id)</li></ul><ol><li>添加班级信息 </li><li>获取新添加的班级的id </li><li>为班级分配学生,即将某学的班级id修改为新添加的班级的id</li></ol></li><li><p>在mapper.xml中设置两个属性</p></li><li><p>useGeneratedKeys:设置使用自增的主键 </p><ul><li>keyProperty:因为增删改有统一的返回值是受影响的行数,因此只能将获取的自增的主键放在传输的参数user对象的某个属性中</li></ul></li></ul><pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">/** * 添加用户信息 * @param user * @date 2022/2/27 15:04 */</span><span class="token keyword">void</span> <span class="token function">insertUser</span><span class="token punctuation">(</span>User user<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--void insertUser(User user);--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>insert</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>insertUser<span class="token punctuation">"</span></span> <span class="token attr-name">useGeneratedKeys</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token attr-name">keyProperty</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>id<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> insert into t_user values (null,#{username},#{password},#{age},#{sex},#{email})<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>insert</span><span class="token punctuation">></span></span></code></pre><pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">//测试类</span><span class="token annotation punctuation">@Test</span><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">insertUser</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> SqlSession sqlSession <span class="token operator">=</span> SqlSessionUtils<span class="token punctuation">.</span><span class="token function">getSqlSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> SQLMapper mapper <span class="token operator">=</span> sqlSession<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span>SQLMapper<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> User user <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">User</span><span class="token punctuation">(</span>null<span class="token punctuation">,</span> <span class="token string">"ton"</span><span class="token punctuation">,</span> <span class="token string">"123"</span><span class="token punctuation">,</span> <span class="token number">23</span><span class="token punctuation">,</span> <span class="token string">"男"</span><span class="token punctuation">,</span> <span class="token string">"[email protected]"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> mapper<span class="token punctuation">.</span><span class="token function">insertUser</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">//输出:user{id=10, username='ton', password='123', age=23, sex='男', email='[email protected]'},自增主键存放到了user的id属性中</span><span class="token punctuation">}</span></code></pre><h1 id="自定义映射resultMap"><a href="#自定义映射resultMap" class="headerlink" title="自定义映射resultMap"></a>自定义映射resultMap</h1><h2 id="resultMap处理字段和属性的映射关系"><a href="#resultMap处理字段和属性的映射关系" class="headerlink" title="resultMap处理字段和属性的映射关系"></a>resultMap处理字段和属性的映射关系</h2><ul><li>resultMap:设置自定义映射 </li><li>属性: <ul><li>id:表示自定义映射的唯一标识,不能重复</li><li>type:查询的数据要映射的实体类的类型 </li><li>子标签: </li><li>id:设置主键的映射关系 <ul><li>result:设置普通字段的映射关系 </li><li>子标签属性: </li><li>property:设置映射关系中实体类中的属性名 <ul><li>column:设置映射关系中表中的字段名</li></ul></li></ul></li></ul></li><li>若字段名和实体类中的属性名不一致,则可以通过resultMap设置自定义映射,即使字段名和属性名一致的属性也要映射,也就是全部属性都要列出来</li></ul><pre class=" language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>resultMap</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>empResultMap<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Emp<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>id</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>eid<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>eid<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>id</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>empName<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>emp_name<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>age<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>age<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sex<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sex<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>email<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>email<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>resultMap</span><span class="token punctuation">></span></span><span class="token comment" spellcheck="true"><!--List<Emp> getAllEmp();--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>getAllEmp<span class="token punctuation">"</span></span> <span class="token attr-name">resultMap</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>empResultMap<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select * from t_emp<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span></code></pre><ul><li><p>若字段名和实体类中的属性名不一致,但是字段名符合数据库的规则(使用_),实体类中的属性名符合Java的规则(使用驼峰)。此时也可通过以下两种方式处理字段名和实体类中的属性的映射关系 </p><ol><li>可以通过为字段起别名的方式,保证和实体类中的属性名保持一致 <pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--List<Emp> getAllEmp();--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>getAllEmp<span class="token punctuation">"</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Emp<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select eid,emp_name empName,age,sex,email from t_emp<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span></code></pre></li><li>可以在MyBatis的核心配置文件中的<code>setting</code>标签中,设置一个全局配置信息mapUnderscoreToCamelCase,可以在查询表中数据时,自动将_类型的字段名转换为驼峰,例如:字段名user_name,设置了mapUnderscoreToCamelCase,此时字段名就会转换为userName。<a href="#%E6%A0%B8%E5%BF%83%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E8%AF%A6%E8%A7%A3">核心配置文件详解</a><pre class=" language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>settings</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>setting</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>mapUnderscoreToCamelCase<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>settings</span><span class="token punctuation">></span></span></code></pre></li></ol></li></ul><h2 id="多对一映射处理"><a href="#多对一映射处理" class="headerlink" title="多对一映射处理"></a>多对一映射处理</h2><blockquote><p>查询员工信息以及员工所对应的部门信息</p></blockquote><pre class=" language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Emp</span> <span class="token punctuation">{</span> <span class="token keyword">private</span> Integer eid<span class="token punctuation">;</span> <span class="token keyword">private</span> String empName<span class="token punctuation">;</span> <span class="token keyword">private</span> Integer age<span class="token punctuation">;</span> <span class="token keyword">private</span> String sex<span class="token punctuation">;</span> <span class="token keyword">private</span> String email<span class="token punctuation">;</span> <span class="token keyword">private</span> Dept dept<span class="token punctuation">;</span> <span class="token comment" spellcheck="true">//...构造器、get、set方法等</span><span class="token punctuation">}</span></code></pre><h3 id="级联方式处理映射关系"><a href="#级联方式处理映射关系" class="headerlink" title="级联方式处理映射关系"></a>级联方式处理映射关系</h3><pre class=" language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>resultMap</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>empAndDeptResultMapOne<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Emp<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>id</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>eid<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>eid<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>id</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>empName<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>emp_name<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>age<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>age<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sex<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sex<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>email<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>email<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>dept.did<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>did<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>dept.deptName<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>dept_name<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>resultMap</span><span class="token punctuation">></span></span><span class="token comment" spellcheck="true"><!--Emp getEmpAndDept(@Param("eid")Integer eid);--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>getEmpAndDept<span class="token punctuation">"</span></span> <span class="token attr-name">resultMap</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>empAndDeptResultMapOne<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select * from t_emp left join t_dept on t_emp.eid = t_dept.did where t_emp.eid = #{eid}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span></code></pre><h3 id="使用association处理映射关系"><a href="#使用association处理映射关系" class="headerlink" title="使用association处理映射关系"></a>使用association处理映射关系</h3><ul><li>association:处理多对一的映射关系</li><li>property:需要处理多对的映射关系的属性名</li><li>javaType:该属性的类型</li></ul><pre class=" language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>resultMap</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>empAndDeptResultMapTwo<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Emp<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>id</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>eid<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>eid<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>id</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>empName<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>emp_name<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>age<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>age<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sex<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sex<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>email<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>email<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>association</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>dept<span class="token punctuation">"</span></span> <span class="token attr-name">javaType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Dept<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>id</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>did<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>did<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>id</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>deptName<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>dept_name<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>association</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>resultMap</span><span class="token punctuation">></span></span><span class="token comment" spellcheck="true"><!--Emp getEmpAndDept(@Param("eid")Integer eid);--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>getEmpAndDept<span class="token punctuation">"</span></span> <span class="token attr-name">resultMap</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>empAndDeptResultMapTwo<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select * from t_emp left join t_dept on t_emp.eid = t_dept.did where t_emp.eid = #{eid}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span></code></pre><h3 id="分步查询"><a href="#分步查询" class="headerlink" title="分步查询"></a>分步查询</h3><h4 id="1-查询员工信息"><a href="#1-查询员工信息" class="headerlink" title="1. 查询员工信息"></a>1. 查询员工信息</h4><ul><li>select:设置分布查询的sql的唯一标识(namespace.SQLId或mapper接口的全类名.方法名)</li><li>column:设置分步查询的条件</li></ul><pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">//EmpMapper里的方法</span><span class="token comment" spellcheck="true">/** * 通过分步查询,员工及所对应的部门信息 * 分步查询第一步:查询员工信息 * @param * @return com.atguigu.mybatis.pojo.Emp * @date 2022/2/27 20:17 */</span>Emp <span class="token function">getEmpAndDeptByStepOne</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Param</span><span class="token punctuation">(</span><span class="token string">"eid"</span><span class="token punctuation">)</span> Integer eid<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><pre class=" language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>resultMap</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>empAndDeptByStepResultMap<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Emp<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>id</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>eid<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>eid<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>id</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>empName<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>emp_name<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>age<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>age<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sex<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sex<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>email<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>email<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>association</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>dept<span class="token punctuation">"</span></span> <span class="token attr-name">select</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>did<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>association</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>resultMap</span><span class="token punctuation">></span></span><span class="token comment" spellcheck="true"><!--Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>getEmpAndDeptByStepOne<span class="token punctuation">"</span></span> <span class="token attr-name">resultMap</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>empAndDeptByStepResultMap<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select * from t_emp where eid = #{eid}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span></code></pre><h4 id="2-查询部门信息"><a href="#2-查询部门信息" class="headerlink" title="2. 查询部门信息"></a>2. 查询部门信息</h4><pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">//DeptMapper里的方法</span><span class="token comment" spellcheck="true">/** * 通过分步查询,员工及所对应的部门信息 * 分步查询第二步:通过did查询员工对应的部门信息 * @param * @return com.atguigu.mybatis.pojo.Emp * @date 2022/2/27 20:23 */</span>Dept <span class="token function">getEmpAndDeptByStepTwo</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Param</span><span class="token punctuation">(</span><span class="token string">"did"</span><span class="token punctuation">)</span> Integer did<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--此处的resultMap仅是处理字段和属性的映射关系--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>resultMap</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>EmpAndDeptByStepTwoResultMap<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Dept<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>id</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>did<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>did<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>id</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>deptName<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>dept_name<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>resultMap</span><span class="token punctuation">></span></span><span class="token comment" spellcheck="true"><!--Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>getEmpAndDeptByStepTwo<span class="token punctuation">"</span></span> <span class="token attr-name">resultMap</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>EmpAndDeptByStepTwoResultMap<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select * from t_dept where did = #{did}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span></code></pre><h2 id="一对多映射处理"><a href="#一对多映射处理" class="headerlink" title="一对多映射处理"></a>一对多映射处理</h2><pre class=" language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Dept</span> <span class="token punctuation">{</span> <span class="token keyword">private</span> Integer did<span class="token punctuation">;</span> <span class="token keyword">private</span> String deptName<span class="token punctuation">;</span> <span class="token keyword">private</span> List<span class="token operator"><</span>Emp<span class="token operator">></span> emps<span class="token punctuation">;</span> <span class="token comment" spellcheck="true">//...构造器、get、set方法等</span><span class="token punctuation">}</span></code></pre><h3 id="collection"><a href="#collection" class="headerlink" title="collection"></a>collection</h3><ul><li>collection:用来处理一对多的映射关系</li><li>ofType:表示该属性对饮的集合中存储的数据的类型</li></ul><pre class=" language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>resultMap</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>DeptAndEmpResultMap<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Dept<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>id</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>did<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>did<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>id</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>deptName<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>dept_name<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>collection</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>emps<span class="token punctuation">"</span></span> <span class="token attr-name">ofType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Emp<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>id</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>eid<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>eid<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>id</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>empName<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>emp_name<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>age<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>age<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sex<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sex<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>email<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>email<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>collection</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>resultMap</span><span class="token punctuation">></span></span><span class="token comment" spellcheck="true"><!--Dept getDeptAndEmp(@Param("did") Integer did);--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>getDeptAndEmp<span class="token punctuation">"</span></span> <span class="token attr-name">resultMap</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>DeptAndEmpResultMap<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select * from t_dept left join t_emp on t_dept.did = t_emp.did where t_dept.did = #{did}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span></code></pre><h3 id="分步查询-1"><a href="#分步查询-1" class="headerlink" title="分步查询"></a>分步查询</h3><h4 id="1-查询部门信息"><a href="#1-查询部门信息" class="headerlink" title="1. 查询部门信息"></a>1. 查询部门信息</h4><pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">/** * 通过分步查询,查询部门及对应的所有员工信息 * 分步查询第一步:查询部门信息 * @param did * @return com.atguigu.mybatis.pojo.Dept * @date 2022/2/27 22:04 */</span>Dept <span class="token function">getDeptAndEmpByStepOne</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Param</span><span class="token punctuation">(</span><span class="token string">"did"</span><span class="token punctuation">)</span> Integer did<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><pre class=" language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>resultMap</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>DeptAndEmpByStepOneResultMap<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Dept<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>id</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>did<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>did<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>id</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>deptName<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>dept_name<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>collection</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>emps<span class="token punctuation">"</span></span> <span class="token attr-name">select</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>com.atguigu.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>did<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>collection</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>resultMap</span><span class="token punctuation">></span></span><span class="token comment" spellcheck="true"><!--Dept getDeptAndEmpByStepOne(@Param("did") Integer did);--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>getDeptAndEmpByStepOne<span class="token punctuation">"</span></span> <span class="token attr-name">resultMap</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>DeptAndEmpByStepOneResultMap<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select * from t_dept where did = #{did}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span></code></pre><h4 id="2-根据部门id查询部门中的所有员工"><a href="#2-根据部门id查询部门中的所有员工" class="headerlink" title="2. 根据部门id查询部门中的所有员工"></a>2. 根据部门id查询部门中的所有员工</h4><pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">/** * 通过分步查询,查询部门及对应的所有员工信息 * 分步查询第二步:根据部门id查询部门中的所有员工 * @param did * @return java.util.List<com.atguigu.mybatis.pojo.Emp> * @date 2022/2/27 22:10 */</span>List<span class="token operator"><</span>Emp<span class="token operator">></span> <span class="token function">getDeptAndEmpByStepTwo</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Param</span><span class="token punctuation">(</span><span class="token string">"did"</span><span class="token punctuation">)</span> Integer did<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>getDeptAndEmpByStepTwo<span class="token punctuation">"</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Emp<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select * from t_emp where did = #{did}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span></code></pre><h2 id="延迟加载"><a href="#延迟加载" class="headerlink" title="延迟加载"></a>延迟加载</h2><ul><li>分步查询的优点:可以实现延迟加载,但是必须在核心配置文件中设置全局配置信息:</li><li>lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载 <ul><li>aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。 否则,每个属性会按需加载</li></ul></li><li>此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql。此时可通过association和collection中的fetchType属性设置当前的分步查询是否使用延迟加载,fetchType=”lazy(延迟加载)|eager(立即加载)”</li></ul><pre class=" language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>settings</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!--开启延迟加载--></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>setting</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>lazyLoadingEnabled<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>settings</span><span class="token punctuation">></span></span></code></pre><pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Test</span><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">getEmpAndDeptByStepOne</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> SqlSession sqlSession <span class="token operator">=</span> SqlSessionUtils<span class="token punctuation">.</span><span class="token function">getSqlSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> EmpMapper mapper <span class="token operator">=</span> sqlSession<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span>EmpMapper<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> Emp emp <span class="token operator">=</span> mapper<span class="token punctuation">.</span><span class="token function">getEmpAndDeptByStepOne</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>emp<span class="token punctuation">.</span><span class="token function">getEmpName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span></code></pre><ul><li>关闭延迟加载,两条SQL语句都运行了<img src="https://oss.luhuhu.cn/202402080923170.png"></li><li>开启延迟加载,只运行获取emp的SQL语句<br><img src="https://oss.luhuhu.cn/202402080923009.png"></li></ul><pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Test</span><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">getEmpAndDeptByStepOne</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> SqlSession sqlSession <span class="token operator">=</span> SqlSessionUtils<span class="token punctuation">.</span><span class="token function">getSqlSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> EmpMapper mapper <span class="token operator">=</span> sqlSession<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span>EmpMapper<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> Emp emp <span class="token operator">=</span> mapper<span class="token punctuation">.</span><span class="token function">getEmpAndDeptByStepOne</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>emp<span class="token punctuation">.</span><span class="token function">getEmpName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"----------------"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>emp<span class="token punctuation">.</span><span class="token function">getDept</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span></code></pre><ul><li><p>开启后,需要用到查询dept的时候才会调用相应的SQL语句<img src="https://oss.luhuhu.cn/202402080925729.png"></p></li><li><p>fetchType:当开启了全局的延迟加载之后,可以通过该属性手动控制延迟加载的效果,fetchType=”lazy(延迟加载)|eager(立即加载)”</p><pre class=" language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>resultMap</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>empAndDeptByStepResultMap<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Emp<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>id</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>eid<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>eid<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>id</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>empName<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>emp_name<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>age<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>age<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sex<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sex<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>result</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>email<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>email<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>result</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>association</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>dept<span class="token punctuation">"</span></span> <span class="token attr-name">select</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo<span class="token punctuation">"</span></span> <span class="token attr-name">column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>did<span class="token punctuation">"</span></span> <span class="token attr-name">fetchType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>lazy<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>association</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>resultMap</span><span class="token punctuation">></span></span></code></pre></li></ul><h1 id="动态SQL"><a href="#动态SQL" class="headerlink" title="动态SQL"></a>动态SQL</h1><ul><li>Mybatis框架的动态SQL技术是一种根据特定条件动态拼装SQL语句的功能,它存在的意义是为了解决拼接SQL语句字符串时的痛点问题</li></ul><h2 id="if"><a href="#if" class="headerlink" title="if"></a>if</h2><ul><li>if标签可通过test属性(即传递过来的数据)的表达式进行判断,若表达式的结果为true,则标签中的内容会执行;反之标签中的内容不会执行</li><li>在where后面添加一个恒成立条件<code>1=1</code></li><li>这个恒成立条件并不会影响查询的结果<ul><li>这个<code>1=1</code>可以用来拼接<code>and</code>语句,例如:当empName为null时</li><li>如果不加上恒成立条件,则SQL语句为<code>select * from t_emp where and age = ? and sex = ? and email = ?</code>,此时<code>where</code>会与<code>and</code>连用,SQL语句会报错<ul><li>如果加上一个恒成立条件,则SQL语句为<code>select * from t_emp where 1= 1 and age = ? and sex = ? and email = ?</code>,此时不报错</li></ul></li></ul></li></ul><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--List<Emp> getEmpByCondition(Emp emp);--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>getEmpByCondition<span class="token punctuation">"</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Emp<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select * from t_emp where 1=1 <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>if</span> <span class="token attr-name">test</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>empName !<span class="token punctuation">=</span> null and empName !<span class="token punctuation">=</span><span class="token punctuation">'</span><span class="token punctuation">'</span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span> and emp_name = #{empName} <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>if</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>if</span> <span class="token attr-name">test</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>age !<span class="token punctuation">=</span> null and age !<span class="token punctuation">=</span><span class="token punctuation">'</span><span class="token punctuation">'</span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span> and age = #{age} <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>if</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>if</span> <span class="token attr-name">test</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sex !<span class="token punctuation">=</span> null and sex !<span class="token punctuation">=</span><span class="token punctuation">'</span><span class="token punctuation">'</span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span> and sex = #{sex} <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>if</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>if</span> <span class="token attr-name">test</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>email !<span class="token punctuation">=</span> null and email !<span class="token punctuation">=</span><span class="token punctuation">'</span><span class="token punctuation">'</span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span> and email = #{email} <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>if</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span></code></pre><h2 id="where"><a href="#where" class="headerlink" title="where"></a>where</h2><ul><li>where和if一般结合使用:</li><li>若where标签中的if条件都不满足,则where标签没有任何功能,即不会添加where关键字 <ul><li>若where标签中的if条件满足,则where标签会自动添加where关键字,并将条件最前方多余的and/or去掉</li></ul></li></ul><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--List<Emp> getEmpByCondition(Emp emp);--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>getEmpByCondition<span class="token punctuation">"</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Emp<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select * from t_emp <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>where</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>if</span> <span class="token attr-name">test</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>empName !<span class="token punctuation">=</span> null and empName !<span class="token punctuation">=</span><span class="token punctuation">'</span><span class="token punctuation">'</span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span> emp_name = #{empName} <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>if</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>if</span> <span class="token attr-name">test</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>age !<span class="token punctuation">=</span> null and age !<span class="token punctuation">=</span><span class="token punctuation">'</span><span class="token punctuation">'</span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span> and age = #{age} <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>if</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>if</span> <span class="token attr-name">test</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sex !<span class="token punctuation">=</span> null and sex !<span class="token punctuation">=</span><span class="token punctuation">'</span><span class="token punctuation">'</span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span> and sex = #{sex} <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>if</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>if</span> <span class="token attr-name">test</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>email !<span class="token punctuation">=</span> null and email !<span class="token punctuation">=</span><span class="token punctuation">'</span><span class="token punctuation">'</span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span> and email = #{email} <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>if</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>where</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span></code></pre><ul><li><p>注意:where标签不能去掉条件后多余的and/or</p><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--这种用法是错误的,只能去掉条件前面的and/or,条件后面的不行--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>if</span> <span class="token attr-name">test</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>empName !<span class="token punctuation">=</span> null and empName !<span class="token punctuation">=</span><span class="token punctuation">'</span><span class="token punctuation">'</span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span>emp_name = #{empName} and<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>if</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>if</span> <span class="token attr-name">test</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>age !<span class="token punctuation">=</span> null and age !<span class="token punctuation">=</span><span class="token punctuation">'</span><span class="token punctuation">'</span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span> age = #{age}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>if</span><span class="token punctuation">></span></span></code></pre></li></ul><h2 id="trim"><a href="#trim" class="headerlink" title="trim"></a>trim</h2><ul><li>trim用于去掉或添加标签中的内容 </li><li>常用属性</li><li>prefix:在trim标签中的内容的前面添加某些内容 <ul><li>suffix:在trim标签中的内容的后面添加某些内容 </li><li>prefixOverrides:在trim标签中的内容的前面去掉某些内容 </li><li>suffixOverrides:在trim标签中的内容的后面去掉某些内容</li></ul></li><li>若trim中的标签都不满足条件,则trim标签没有任何效果,也就是只剩下<code>select * from t_emp</code></li></ul><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--List<Emp> getEmpByCondition(Emp emp);--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>getEmpByCondition<span class="token punctuation">"</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Emp<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select * from t_emp <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>trim</span> <span class="token attr-name">prefix</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>where<span class="token punctuation">"</span></span> <span class="token attr-name">suffixOverrides</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>and|or<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>if</span> <span class="token attr-name">test</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>empName !<span class="token punctuation">=</span> null and empName !<span class="token punctuation">=</span><span class="token punctuation">'</span><span class="token punctuation">'</span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span> emp_name = #{empName} and <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>if</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>if</span> <span class="token attr-name">test</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>age !<span class="token punctuation">=</span> null and age !<span class="token punctuation">=</span><span class="token punctuation">'</span><span class="token punctuation">'</span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span> age = #{age} and <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>if</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>if</span> <span class="token attr-name">test</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sex !<span class="token punctuation">=</span> null and sex !<span class="token punctuation">=</span><span class="token punctuation">'</span><span class="token punctuation">'</span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span> sex = #{sex} or <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>if</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>if</span> <span class="token attr-name">test</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>email !<span class="token punctuation">=</span> null and email !<span class="token punctuation">=</span><span class="token punctuation">'</span><span class="token punctuation">'</span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span> email = #{email} <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>if</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>trim</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span></code></pre><pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">//测试类</span><span class="token annotation punctuation">@Test</span><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">getEmpByCondition</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> SqlSession sqlSession <span class="token operator">=</span> SqlSessionUtils<span class="token punctuation">.</span><span class="token function">getSqlSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> DynamicSQLMapper mapper <span class="token operator">=</span> sqlSession<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span>DynamicSQLMapper<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> List<span class="token operator"><</span>Emp<span class="token operator">></span> emps<span class="token operator">=</span> mapper<span class="token punctuation">.</span><span class="token function">getEmpByCondition</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Emp</span><span class="token punctuation">(</span>null<span class="token punctuation">,</span> <span class="token string">"张三"</span><span class="token punctuation">,</span> null<span class="token punctuation">,</span> null<span class="token punctuation">,</span> null<span class="token punctuation">,</span> null<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>emps<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span></code></pre><p><img src="https://oss.luhuhu.cn/202402080923435.png"></p><h2 id="choose、when、otherwise"><a href="#choose、when、otherwise" class="headerlink" title="choose、when、otherwise"></a>choose、when、otherwise</h2><ul><li><code>choose、when、otherwise</code>相当于<code>if...else if..else</code></li><li>when至少要有一个,otherwise至多只有一个</li></ul><pre class=" language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>getEmpByChoose<span class="token punctuation">"</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Emp<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select * from t_emp <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>where</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>choose</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>when</span> <span class="token attr-name">test</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>empName !<span class="token punctuation">=</span> null and empName !<span class="token punctuation">=</span> <span class="token punctuation">'</span><span class="token punctuation">'</span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span> emp_name = #{empName} <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>when</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>when</span> <span class="token attr-name">test</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>age !<span class="token punctuation">=</span> null and age !<span class="token punctuation">=</span> <span class="token punctuation">'</span><span class="token punctuation">'</span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span> age = #{age} <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>when</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>when</span> <span class="token attr-name">test</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sex !<span class="token punctuation">=</span> null and sex !<span class="token punctuation">=</span> <span class="token punctuation">'</span><span class="token punctuation">'</span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span> sex = #{sex} <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>when</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>when</span> <span class="token attr-name">test</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>email !<span class="token punctuation">=</span> null and email !<span class="token punctuation">=</span> <span class="token punctuation">'</span><span class="token punctuation">'</span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span> email = #{email} <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>when</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>otherwise</span><span class="token punctuation">></span></span> did = 1 <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>otherwise</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>choose</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>where</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span></code></pre><pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Test</span><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">getEmpByChoose</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> SqlSession sqlSession <span class="token operator">=</span> SqlSessionUtils<span class="token punctuation">.</span><span class="token function">getSqlSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> DynamicSQLMapper mapper <span class="token operator">=</span> sqlSession<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span>DynamicSQLMapper<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> List<span class="token operator"><</span>Emp<span class="token operator">></span> emps <span class="token operator">=</span> mapper<span class="token punctuation">.</span><span class="token function">getEmpByChoose</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Emp</span><span class="token punctuation">(</span>null<span class="token punctuation">,</span> <span class="token string">"张三"</span><span class="token punctuation">,</span> <span class="token number">23</span><span class="token punctuation">,</span> <span class="token string">"男"</span><span class="token punctuation">,</span> <span class="token string">"[email protected]"</span><span class="token punctuation">,</span> null<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>emps<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span></code></pre><p><img src="C:/Users/loaderland/Desktop/Learn/MyBatis/Resources/choose测试结果.png"></p><ul><li>相当于<code>if a else if b else if c else d</code>,只会执行其中一个</li></ul><h2 id="foreach"><a href="#foreach" class="headerlink" title="foreach"></a>foreach</h2><ul><li><p>属性: </p></li><li><p>collection:设置要循环的数组或集合 </p><ul><li>item:表示集合或数组中的每一个数据 </li><li>separator:设置循环体之间的分隔符,分隔符前后默认有一个空格,如<code>,</code></li><li>open:设置foreach标签中的内容的开始符 </li><li>close:设置foreach标签中的内容的结束符</li></ul></li><li><p>批量删除</p><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--int deleteMoreByArray(Integer[] eids);--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>delete</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>deleteMoreByArray<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> delete from t_emp where eid in <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>foreach</span> <span class="token attr-name">collection</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>eids<span class="token punctuation">"</span></span> <span class="token attr-name">item</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>eid<span class="token punctuation">"</span></span> <span class="token attr-name">separator</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>,<span class="token punctuation">"</span></span> <span class="token attr-name">open</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>(<span class="token punctuation">"</span></span> <span class="token attr-name">close</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>)<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> #{eid} <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>foreach</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>delete</span><span class="token punctuation">></span></span></code></pre><pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Test</span><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">deleteMoreByArray</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> SqlSession sqlSession <span class="token operator">=</span> SqlSessionUtils<span class="token punctuation">.</span><span class="token function">getSqlSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> DynamicSQLMapper mapper <span class="token operator">=</span> sqlSession<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span>DynamicSQLMapper<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">int</span> result <span class="token operator">=</span> mapper<span class="token punctuation">.</span><span class="token function">deleteMoreByArray</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Integer</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">{</span><span class="token number">6</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">,</span> <span class="token number">9</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span></code></pre><p> <img src="/Resources/foreach%E6%B5%8B%E8%AF%95%E7%BB%93%E6%9E%9C1.png"></p></li><li><p>批量添加</p><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--int insertMoreByList(@Param("emps") List<Emp> emps);--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>insert</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>insertMoreByList<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> insert into t_emp values <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>foreach</span> <span class="token attr-name">collection</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>emps<span class="token punctuation">"</span></span> <span class="token attr-name">item</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>emp<span class="token punctuation">"</span></span> <span class="token attr-name">separator</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>,<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> (null,#{emp.empName},#{emp.age},#{emp.sex},#{emp.email},null) <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>foreach</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>insert</span><span class="token punctuation">></span></span></code></pre><pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Test</span><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">insertMoreByList</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> SqlSession sqlSession <span class="token operator">=</span> SqlSessionUtils<span class="token punctuation">.</span><span class="token function">getSqlSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> DynamicSQLMapper mapper <span class="token operator">=</span> sqlSession<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span>DynamicSQLMapper<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> Emp emp1 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Emp</span><span class="token punctuation">(</span>null<span class="token punctuation">,</span><span class="token string">"a"</span><span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string">"男"</span><span class="token punctuation">,</span><span class="token string">"[email protected]"</span><span class="token punctuation">,</span>null<span class="token punctuation">)</span><span class="token punctuation">;</span> Emp emp2 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Emp</span><span class="token punctuation">(</span>null<span class="token punctuation">,</span><span class="token string">"b"</span><span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string">"男"</span><span class="token punctuation">,</span><span class="token string">"[email protected]"</span><span class="token punctuation">,</span>null<span class="token punctuation">)</span><span class="token punctuation">;</span> Emp emp3 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Emp</span><span class="token punctuation">(</span>null<span class="token punctuation">,</span><span class="token string">"c"</span><span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string">"男"</span><span class="token punctuation">,</span><span class="token string">"[email protected]"</span><span class="token punctuation">,</span>null<span class="token punctuation">)</span><span class="token punctuation">;</span> List<span class="token operator"><</span>Emp<span class="token operator">></span> emps <span class="token operator">=</span> Arrays<span class="token punctuation">.</span><span class="token function">asList</span><span class="token punctuation">(</span>emp1<span class="token punctuation">,</span> emp2<span class="token punctuation">,</span> emp3<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">int</span> result <span class="token operator">=</span> mapper<span class="token punctuation">.</span><span class="token function">insertMoreByList</span><span class="token punctuation">(</span>emps<span class="token punctuation">)</span><span class="token punctuation">;</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span></code></pre><p> <img src="/Resources/foreach%E6%B5%8B%E8%AF%95%E7%BB%93%E6%9E%9C2.png"></p></li></ul><h2 id="SQL片段"><a href="#SQL片段" class="headerlink" title="SQL片段"></a>SQL片段</h2><ul><li>sql片段,可以记录一段公共sql片段,在使用的地方通过include标签进行引入</li><li>声明sql片段:<code><sql></code>标签</li></ul><pre class=" language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>sql</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>empColumns<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>eid,emp_name,age,sex,email<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>sql</span><span class="token punctuation">></span></span></code></pre><ul><li>引用sql片段:<code><include></code>标签</li></ul><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!--List<Emp> getEmpByCondition(Emp emp);--></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>select</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>getEmpByCondition<span class="token punctuation">"</span></span> <span class="token attr-name">resultType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Emp<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> select <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>include</span> <span class="token attr-name">refid</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>empColumns<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>include</span><span class="token punctuation">></span></span> from t_emp<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>select</span><span class="token punctuation">></span></span></code></pre><h1 id="MyBatis的缓存"><a href="#MyBatis的缓存" class="headerlink" title="MyBatis的缓存"></a>MyBatis的缓存</h1><h2 id="MyBatis的一级缓存"><a href="#MyBatis的一级缓存" class="headerlink" title="MyBatis的一级缓存"></a>MyBatis的一级缓存</h2><ul><li><p>一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问 </p></li><li><p>使一级缓存失效的四种情况: </p><ol><li>不同的SqlSession对应不同的一级缓存 </li><li>同一个SqlSession但是查询条件不同</li><li>同一个SqlSession两次查询期间执行了任何一次增删改操作</li><li>同一个SqlSession两次查询期间手动清空了缓存</li></ol></li></ul><h2 id="MyBatis的二级缓存"><a href="#MyBatis的二级缓存" class="headerlink" title="MyBatis的二级缓存"></a>MyBatis的二级缓存</h2><ul><li><p>二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取 </p></li><li><p>二级缓存开启的条件</p><ol><li>在核心配置文件中,设置全局配置属性cacheEnabled=”true”,默认为true,不需要设置</li><li>在映射文件中设置标签<cache></cache></li><li>二级缓存必须在SqlSession关闭或提交之后有效</li><li>查询的数据所转换的实体类类型必须实现序列化的接口</li></ol></li><li><p>使二级缓存失效的情况:两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效</p></li></ul><h2 id="二级缓存的相关配置"><a href="#二级缓存的相关配置" class="headerlink" title="二级缓存的相关配置"></a>二级缓存的相关配置</h2><ul><li>在mapper配置文件中添加的cache标签可以设置一些属性</li><li>eviction属性:缓存回收策略 </li><li>LRU(Least Recently Used) – 最近最少使用的:移除最长时间不被使用的对象。 <ul><li>FIFO(First in First out) – 先进先出:按对象进入缓存的顺序来移除它们。 </li><li>SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。 </li><li>WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。</li><li>默认的是 LRU</li></ul></li><li>flushInterval属性:刷新间隔,单位毫秒</li><li>默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句(增删改)时刷新</li><li>size属性:引用数目,正整数</li><li>代表缓存最多可以存储多少个对象,太大容易导致内存溢出</li><li>readOnly属性:只读,true/false</li><li>true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。 <ul><li>false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false</li></ul></li></ul><h2 id="MyBatis缓存查询的顺序"><a href="#MyBatis缓存查询的顺序" class="headerlink" title="MyBatis缓存查询的顺序"></a>MyBatis缓存查询的顺序</h2><ul><li>先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用 </li><li>如果二级缓存没有命中,再查询一级缓存 </li><li>如果一级缓存也没有命中,则查询数据库 </li><li>SqlSession关闭之后,一级缓存中的数据会写入二级缓存</li></ul><h2 id="整合第三方缓存EHCache(了解)"><a href="#整合第三方缓存EHCache(了解)" class="headerlink" title="整合第三方缓存EHCache(了解)"></a>整合第三方缓存EHCache(了解)</h2><h3 id="添加依赖"><a href="#添加依赖" class="headerlink" title="添加依赖"></a>添加依赖</h3><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!-- Mybatis EHCache整合包 --></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>org.mybatis.caches<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>mybatis-ehcache<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>1.2.1<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span><span class="token comment" spellcheck="true"><!-- slf4j日志门面的一个具体实现 --></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>ch.qos.logback<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>logback-classic<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>1.2.3<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span></code></pre><h3 id="各个jar包的功能"><a href="#各个jar包的功能" class="headerlink" title="各个jar包的功能"></a>各个jar包的功能</h3><table><thead><tr><th>jar包名称</th><th>作用</th></tr></thead><tbody><tr><td>mybatis-ehcache</td><td>Mybatis和EHCache的整合包</td></tr><tr><td>ehcache</td><td>EHCache核心包</td></tr><tr><td>slf4j-api</td><td>SLF4J日志门面包</td></tr><tr><td>logback-classic</td><td>支持SLF4J门面接口的一个具体实现</td></tr></tbody></table><h3 id="创建EHCache的配置文件ehcache-xml"><a href="#创建EHCache的配置文件ehcache-xml" class="headerlink" title="创建EHCache的配置文件ehcache.xml"></a>创建EHCache的配置文件ehcache.xml</h3><ul><li>名字必须叫<code>ehcache.xml</code></li></ul><pre class=" language-xml"><code class="language-xml"><span class="token prolog"><?xml version="1.0" encoding="utf-8" ?></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ehcache</span> <span class="token attr-name"><span class="token namespace">xmlns:</span>xsi</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>http://www.w3.org/2001/XMLSchema-instance<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">xsi:</span>noNamespaceSchemaLocation</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>../config/ehcache.xsd<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- 磁盘保存路径 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>diskStore</span> <span class="token attr-name">path</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>D:\atguigu\ehcache<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>defaultCache</span> <span class="token attr-name">maxElementsInMemory</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1000<span class="token punctuation">"</span></span> <span class="token attr-name">maxElementsOnDisk</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>10000000<span class="token punctuation">"</span></span> <span class="token attr-name">eternal</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span> <span class="token attr-name">overflowToDisk</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token attr-name">timeToIdleSeconds</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>120<span class="token punctuation">"</span></span> <span class="token attr-name">timeToLiveSeconds</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>120<span class="token punctuation">"</span></span> <span class="token attr-name">diskExpiryThreadIntervalSeconds</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>120<span class="token punctuation">"</span></span> <span class="token attr-name">memoryStoreEvictionPolicy</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>LRU<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>defaultCache</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ehcache</span><span class="token punctuation">></span></span></code></pre><h3 id="设置二级缓存的类型"><a href="#设置二级缓存的类型" class="headerlink" title="设置二级缓存的类型"></a>设置二级缓存的类型</h3><ul><li>在xxxMapper.xml文件中设置二级缓存类型</li></ul><pre class=" language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>cache</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>org.mybatis.caches.ehcache.EhcacheCache<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span></code></pre><h3 id="加入logback日志"><a href="#加入logback日志" class="headerlink" title="加入logback日志"></a>加入logback日志</h3><ul><li>存在SLF4J时,作为简易日志的log4j将失效,此时我们需要借助SLF4J的具体实现logback来打印日志。创建logback的配置文件<code>logback.xml</code>,名字固定,不可改变</li></ul><pre class=" language-xml"><code class="language-xml"><span class="token prolog"><?xml version="1.0" encoding="UTF-8"?></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>configuration</span> <span class="token attr-name">debug</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- 指定日志输出的位置 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>appender</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>STDOUT<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>ch.qos.logback.core.ConsoleAppender<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>encoder</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- 日志输出的格式 --></span> <span class="token comment" spellcheck="true"><!-- 按照顺序分别是:时间、日志级别、线程名称、打印日志的类、日志主体内容、换行 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>pattern</span><span class="token punctuation">></span></span>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>pattern</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>encoder</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>appender</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- 设置全局日志级别。日志级别按顺序分别是:DEBUG、INFO、WARN、ERROR --></span> <span class="token comment" spellcheck="true"><!-- 指定任何一个日志级别都只打印当前级别和后面级别的日志。 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>root</span> <span class="token attr-name">level</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>DEBUG<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- 指定打印日志的appender,这里通过“STDOUT”引用了前面配置的appender --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>appender-ref</span> <span class="token attr-name">ref</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>STDOUT<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>root</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- 根据特殊需求指定局部日志级别 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>logger</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>com.atguigu.crowd.mapper<span class="token punctuation">"</span></span> <span class="token attr-name">level</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>DEBUG<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>configuration</span><span class="token punctuation">></span></span></code></pre><h3 id="EHCache配置文件说明"><a href="#EHCache配置文件说明" class="headerlink" title="EHCache配置文件说明"></a>EHCache配置文件说明</h3><table><thead><tr><th>属性名</th><th>是否必须</th><th>作用</th></tr></thead><tbody><tr><td>maxElementsInMemory</td><td>是</td><td>在内存中缓存的element的最大数目</td></tr><tr><td>maxElementsOnDisk</td><td>是</td><td>在磁盘上缓存的element的最大数目,若是0表示无穷大</td></tr><tr><td>eternal</td><td>是</td><td>设定缓存的elements是否永远不过期。 如果为true,则缓存的数据始终有效, 如果为false那么还要根据timeToIdleSeconds、timeToLiveSeconds判断</td></tr><tr><td>overflowToDisk</td><td>是</td><td>设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上</td></tr><tr><td>timeToIdleSeconds</td><td>否</td><td>当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时, 这些数据便会删除,默认值是0,也就是可闲置时间无穷大</td></tr><tr><td>timeToLiveSeconds</td><td>否</td><td>缓存element的有效生命期,默认是0.,也就是element存活时间无穷大</td></tr><tr><td>diskSpoolBufferSizeMB</td><td>否</td><td>DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区</td></tr><tr><td>diskPersistent</td><td>否</td><td>在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false</td></tr><tr><td>diskExpiryThreadIntervalSeconds</td><td>否</td><td>磁盘缓存的清理线程运行间隔,默认是120秒。每个120s, 相应的线程会进行一次EhCache中数据的清理工作</td></tr><tr><td>memoryStoreEvictionPolicy</td><td>否</td><td>当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。 默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出</td></tr></tbody></table><h1 id="MyBatis的逆向工程"><a href="#MyBatis的逆向工程" class="headerlink" title="MyBatis的逆向工程"></a>MyBatis的逆向工程</h1><ul><li>正向工程:先创建Java实体类,由框架负责根据实体类生成数据库表。Hibernate是支持正向工程的</li><li>逆向工程:先创建数据库表,由框架负责根据数据库表,反向生成如下资源: </li><li>Java实体类 <ul><li>Mapper接口 </li><li>Mapper映射文件</li></ul></li></ul><h2 id="创建逆向工程的步骤"><a href="#创建逆向工程的步骤" class="headerlink" title="创建逆向工程的步骤"></a>创建逆向工程的步骤</h2><h3 id="添加依赖和插件"><a href="#添加依赖和插件" class="headerlink" title="添加依赖和插件"></a>添加依赖和插件</h3><pre class=" language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependencies</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- MyBatis核心依赖包 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>org.mybatis<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>mybatis<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>3.5.9<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- junit测试 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>junit<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>junit<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>4.13.2<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>scope</span><span class="token punctuation">></span></span>test<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>scope</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- MySQL驱动 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>mysql<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>mysql-connector-java<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>8.0.27<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- log4j日志 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>log4j<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>log4j<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>1.2.17<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependencies</span><span class="token punctuation">></span></span><span class="token comment" spellcheck="true"><!-- 控制Maven在构建过程中相关配置 --></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>build</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- 构建过程中用到的插件 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>plugins</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- 具体插件,逆向工程的操作是以构建过程中插件形式出现的 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>plugin</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>org.mybatis.generator<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>mybatis-generator-maven-plugin<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>1.3.0<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- 插件的依赖 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependencies</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- 逆向工程的核心依赖 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>org.mybatis.generator<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>mybatis-generator-core<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>1.3.2<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- 数据库连接池 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>com.mchange<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>c3p0<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>0.9.2<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- MySQL驱动 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>mysql<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>mysql-connector-java<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>8.0.27<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependencies</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>plugin</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>plugins</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>build</span><span class="token punctuation">></span></span></code></pre><h3 id="创建MyBatis的核心配置文件-1"><a href="#创建MyBatis的核心配置文件-1" class="headerlink" title="创建MyBatis的核心配置文件"></a>创建MyBatis的核心配置文件</h3><pre class=" language-xml"><code class="language-xml"><span class="token prolog"><?xml version="1.0" encoding="UTF-8" ?></span><span class="token doctype"><!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>configuration</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>properties</span> <span class="token attr-name">resource</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>jdbc.properties<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>typeAliases</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>package</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span><span class="token punctuation">"</span></span><span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>typeAliases</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>environments</span> <span class="token attr-name">default</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>development<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>environment</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>development<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>transactionManager</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>JDBC<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dataSource</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>POOLED<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>property</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>driver<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>${jdbc.driver}<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>property</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>url<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>${jdbc.url}<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>property</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>username<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>${jdbc.username}<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>property</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>password<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>${jdbc.password}<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dataSource</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>environment</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>environments</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>mappers</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>package</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span><span class="token punctuation">"</span></span><span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>mappers</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>configuration</span><span class="token punctuation">></span></span></code></pre><h3 id="创建逆向工程的配置文件"><a href="#创建逆向工程的配置文件" class="headerlink" title="创建逆向工程的配置文件"></a>创建逆向工程的配置文件</h3><ul><li>文件名必须是:<code>generatorConfig.xml</code></li></ul><pre class=" language-xml"><code class="language-xml"><span class="token prolog"><?xml version="1.0" encoding="UTF-8"?></span><span class="token doctype"><!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>generatorConfiguration</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- targetRuntime: 执行生成的逆向工程的版本 MyBatis3Simple: 生成基本的CRUD(清新简洁版) MyBatis3: 生成带条件的CRUD(奢华尊享版) --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>context</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>DB2Tables<span class="token punctuation">"</span></span> <span class="token attr-name">targetRuntime</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>MyBatis3Simple<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- 数据库的连接信息 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>jdbcConnection</span> <span class="token attr-name">driverClass</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>com.mysql.cj.jdbc.Driver<span class="token punctuation">"</span></span> <span class="token attr-name">connectionURL</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>jdbc:mysql://localhost:3306/mybatis<span class="token punctuation">"</span></span> <span class="token attr-name">userId</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>root<span class="token punctuation">"</span></span> <span class="token attr-name">password</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>123456<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>jdbcConnection</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- javaBean的生成策略--></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>javaModelGenerator</span> <span class="token attr-name">targetPackage</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>com.atguigu.mybatis.pojo<span class="token punctuation">"</span></span> <span class="token attr-name">targetProject</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>.\src\main\java<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>property</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>enableSubPackages<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>property</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>trimStrings<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>javaModelGenerator</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- SQL映射文件的生成策略 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>sqlMapGenerator</span> <span class="token attr-name">targetPackage</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>com.atguigu.mybatis.mapper<span class="token punctuation">"</span></span> <span class="token attr-name">targetProject</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>.\src\main\resources<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>property</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>enableSubPackages<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>sqlMapGenerator</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- Mapper接口的生成策略 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>javaClientGenerator</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>XMLMAPPER<span class="token punctuation">"</span></span> <span class="token attr-name">targetPackage</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>com.atguigu.mybatis.mapper<span class="token punctuation">"</span></span> <span class="token attr-name">targetProject</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>.\src\main\java<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>property</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>enableSubPackages<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>javaClientGenerator</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!-- 逆向分析的表 --></span> <span class="token comment" spellcheck="true"><!-- tableName设置为*号,可以对应所有表,此时不写domainObjectName --></span> <span class="token comment" spellcheck="true"><!-- domainObjectName属性指定生成出来的实体类的类名 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>table</span> <span class="token attr-name">tableName</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>t_emp<span class="token punctuation">"</span></span> <span class="token attr-name">domainObjectName</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Emp<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>table</span> <span class="token attr-name">tableName</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>t_dept<span class="token punctuation">"</span></span> <span class="token attr-name">domainObjectName</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Dept<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>context</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>generatorConfiguration</span><span class="token punctuation">></span></span></code></pre><h3 id="执行MBG插件的generate目标"><a href="#执行MBG插件的generate目标" class="headerlink" title="执行MBG插件的generate目标"></a>执行MBG插件的generate目标</h3><ul><li><img src="https://oss.luhuhu.cn/202402080925929.png"></li><li>如果出现报错:<code>Exception getting JDBC Driver</code>,可能是pom.xml中,数据库驱动配置错误</li><li>dependency中的驱动<img src="https://oss.luhuhu.cn/202402080925724.png"><ul><li>mybatis-generator-maven-plugin插件中的驱动<img src="https://oss.luhuhu.cn/202402080925417.png"></li><li>两者的驱动版本应该相同</li></ul></li><li>执行结果<img src="https://oss.luhuhu.cn/202402080926178.png"></li></ul><h2 id="QBC"><a href="#QBC" class="headerlink" title="QBC"></a>QBC</h2><h3 id="查询"><a href="#查询" class="headerlink" title="查询"></a>查询</h3><ul><li><code>selectByExample</code>:按条件查询,需要传入一个example对象或者null;如果传入一个null,则表示没有条件,也就是查询所有数据</li><li><code>example.createCriteria().xxx</code>:创建条件对象,通过andXXX方法为SQL添加查询添加,每个条件之间是and关系</li><li><code>example.or().xxx</code>:将之前添加的条件通过or拼接其他条件<br><img src="https://oss.luhuhu.cn/202402080926003.png"></li></ul><pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Test</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">testMBG</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> IOException <span class="token punctuation">{</span> InputStream is <span class="token operator">=</span> Resources<span class="token punctuation">.</span><span class="token function">getResourceAsStream</span><span class="token punctuation">(</span><span class="token string">"mybatis-config.xml"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> SqlSessionFactoryBuilder sqlSessionFactoryBuilder <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SqlSessionFactoryBuilder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> SqlSessionFactory sqlSessionFactory <span class="token operator">=</span> sqlSessionFactoryBuilder<span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span>is<span class="token punctuation">)</span><span class="token punctuation">;</span> SqlSession sqlSession <span class="token operator">=</span> sqlSessionFactory<span class="token punctuation">.</span><span class="token function">openSession</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span> EmpMapper mapper <span class="token operator">=</span> sqlSession<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span>EmpMapper<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> EmpExample example <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">EmpExample</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">//名字为张三,且年龄大于等于20</span> example<span class="token punctuation">.</span><span class="token function">createCriteria</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">andEmpNameEqualTo</span><span class="token punctuation">(</span><span class="token string">"张三"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">andAgeGreaterThanOrEqualTo</span><span class="token punctuation">(</span><span class="token number">20</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">//或者did不为空</span> example<span class="token punctuation">.</span><span class="token function">or</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">andDidIsNotNull</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> List<span class="token operator"><</span>Emp<span class="token operator">></span> emps <span class="token operator">=</span> mapper<span class="token punctuation">.</span><span class="token function">selectByExample</span><span class="token punctuation">(</span>example<span class="token punctuation">)</span><span class="token punctuation">;</span> emps<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span>System<span class="token punctuation">.</span>out<span class="token operator">:</span><span class="token operator">:</span>println<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span></code></pre><p><img src="https://oss.luhuhu.cn/202402080926449.png"></p><h3 id="增改"><a href="#增改" class="headerlink" title="增改"></a>增改</h3><ul><li><code>updateByPrimaryKey</code>:通过主键进行数据修改,如果某一个值为null,也会将对应的字段改为null</li><li><code>mapper.updateByPrimaryKey(new Emp(1,"admin",22,null,"[email protected]",3));</code><ul><li><img src="https://oss.luhuhu.cn/202402080926102.png"></li></ul></li><li><code>updateByPrimaryKeySelective()</code>:通过主键进行选择性数据修改,如果某个值为null,则不修改这个字段</li><li><code>mapper.updateByPrimaryKeySelective(new Emp(2,"admin2",22,null,"[email protected]",3));</code><ul><li><img src="https://oss.luhuhu.cn/202402080926757.png"></li></ul></li></ul><h1 id="分页插件"><a href="#分页插件" class="headerlink" title="分页插件"></a>分页插件</h1><h2 id="分页插件使用步骤"><a href="#分页插件使用步骤" class="headerlink" title="分页插件使用步骤"></a>分页插件使用步骤</h2><h3 id="添加依赖-1"><a href="#添加依赖-1" class="headerlink" title="添加依赖"></a>添加依赖</h3><pre class=" language-xml"><code class="language-xml"><span class="token comment" spellcheck="true"><!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper --></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>com.github.pagehelper<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>pagehelper<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>5.2.0<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span></code></pre><h3 id="配置分页插件"><a href="#配置分页插件" class="headerlink" title="配置分页插件"></a>配置分页插件</h3><ul><li>在MyBatis的核心配置文件(mybatis-config.xml)中配置插件</li><li><img src="C:/Users/loaderland/Desktop/Learn/MyBatis/Resources/配置分页插件.png"></li></ul><pre class=" language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>plugins</span><span class="token punctuation">></span></span> <span class="token comment" spellcheck="true"><!--设置分页插件--></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>plugin</span> <span class="token attr-name">interceptor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>com.github.pagehelper.PageInterceptor<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>plugin</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>plugins</span><span class="token punctuation">></span></span></code></pre><h2 id="分页插件的使用"><a href="#分页插件的使用" class="headerlink" title="分页插件的使用"></a>分页插件的使用</h2><h3 id="开启分页功能"><a href="#开启分页功能" class="headerlink" title="开启分页功能"></a>开启分页功能</h3><ul><li>在查询功能之前使用<code>PageHelper.startPage(int pageNum, int pageSize)</code>开启分页功能</li><li>pageNum:当前页的页码 <ul><li>pageSize:每页显示的条数</li></ul></li></ul><pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Test</span><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">testPageHelper</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> IOException <span class="token punctuation">{</span> InputStream is <span class="token operator">=</span> Resources<span class="token punctuation">.</span><span class="token function">getResourceAsStream</span><span class="token punctuation">(</span><span class="token string">"mybatis-config.xml"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> SqlSessionFactoryBuilder sqlSessionFactoryBuilder <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SqlSessionFactoryBuilder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> SqlSessionFactory sqlSessionFactory <span class="token operator">=</span> sqlSessionFactoryBuilder<span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span>is<span class="token punctuation">)</span><span class="token punctuation">;</span> SqlSession sqlSession <span class="token operator">=</span> sqlSessionFactory<span class="token punctuation">.</span><span class="token function">openSession</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span> EmpMapper mapper <span class="token operator">=</span> sqlSession<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span>EmpMapper<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">//访问第一页,每页四条数据</span> PageHelper<span class="token punctuation">.</span><span class="token function">startPage</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">;</span> List<span class="token operator"><</span>Emp<span class="token operator">></span> emps <span class="token operator">=</span> mapper<span class="token punctuation">.</span><span class="token function">selectByExample</span><span class="token punctuation">(</span>null<span class="token punctuation">)</span><span class="token punctuation">;</span> emps<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span>System<span class="token punctuation">.</span>out<span class="token operator">:</span><span class="token operator">:</span>println<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span></code></pre><p><img src="https://oss.luhuhu.cn/202402080926300.png"></p><h3 id="分页相关数据"><a href="#分页相关数据" class="headerlink" title="分页相关数据"></a>分页相关数据</h3><h4 id="方法一:直接输出"><a href="#方法一:直接输出" class="headerlink" title="方法一:直接输出"></a>方法一:直接输出</h4><pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Test</span><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">testPageHelper</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> IOException <span class="token punctuation">{</span> InputStream is <span class="token operator">=</span> Resources<span class="token punctuation">.</span><span class="token function">getResourceAsStream</span><span class="token punctuation">(</span><span class="token string">"mybatis-config.xml"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> SqlSessionFactoryBuilder sqlSessionFactoryBuilder <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SqlSessionFactoryBuilder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> SqlSessionFactory sqlSessionFactory <span class="token operator">=</span> sqlSessionFactoryBuilder<span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span>is<span class="token punctuation">)</span><span class="token punctuation">;</span> SqlSession sqlSession <span class="token operator">=</span> sqlSessionFactory<span class="token punctuation">.</span><span class="token function">openSession</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span> EmpMapper mapper <span class="token operator">=</span> sqlSession<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span>EmpMapper<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">//访问第一页,每页四条数据</span> Page<span class="token operator"><</span>Object<span class="token operator">></span> page <span class="token operator">=</span> PageHelper<span class="token punctuation">.</span><span class="token function">startPage</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">;</span> List<span class="token operator"><</span>Emp<span class="token operator">></span> emps <span class="token operator">=</span> mapper<span class="token punctuation">.</span><span class="token function">selectByExample</span><span class="token punctuation">(</span>null<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">//在查询到List集合后,打印分页数据</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>page<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span></code></pre><ul><li><p>分页相关数据:</p><pre><code>Page{count=true, pageNum=1, pageSize=4, startRow=0, endRow=4, total=8, pages=2, reasonable=false, pageSizeZero=false}[Emp{eid=1, empName='admin', age=22, sex='男', email='[email protected]', did=3}, Emp{eid=2, empName='admin2', age=22, sex='男', email='[email protected]', did=3}, Emp{eid=3, empName='王五', age=12, sex='女', email='[email protected]', did=3}, Emp{eid=4, empName='赵六', age=32, sex='男', email='[email protected]', did=1}]</code></pre></li></ul><h4 id="方法二使用PageInfo"><a href="#方法二使用PageInfo" class="headerlink" title="方法二使用PageInfo"></a>方法二使用PageInfo</h4><ul><li>在查询获取list集合之后,使用<code>PageInfo<T> pageInfo = new PageInfo<>(List<T> list, intnavigatePages)</code>获取分页相关数据</li><li>list:分页之后的数据 <ul><li>navigatePages:导航分页的页码数</li></ul></li></ul><pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Test</span><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">testPageHelper</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> IOException <span class="token punctuation">{</span> InputStream is <span class="token operator">=</span> Resources<span class="token punctuation">.</span><span class="token function">getResourceAsStream</span><span class="token punctuation">(</span><span class="token string">"mybatis-config.xml"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> SqlSessionFactoryBuilder sqlSessionFactoryBuilder <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SqlSessionFactoryBuilder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> SqlSessionFactory sqlSessionFactory <span class="token operator">=</span> sqlSessionFactoryBuilder<span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span>is<span class="token punctuation">)</span><span class="token punctuation">;</span> SqlSession sqlSession <span class="token operator">=</span> sqlSessionFactory<span class="token punctuation">.</span><span class="token function">openSession</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span> EmpMapper mapper <span class="token operator">=</span> sqlSession<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span>EmpMapper<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> PageHelper<span class="token punctuation">.</span><span class="token function">startPage</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">;</span> List<span class="token operator"><</span>Emp<span class="token operator">></span> emps <span class="token operator">=</span> mapper<span class="token punctuation">.</span><span class="token function">selectByExample</span><span class="token punctuation">(</span>null<span class="token punctuation">)</span><span class="token punctuation">;</span> PageInfo<span class="token operator"><</span>Emp<span class="token operator">></span> page <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">PageInfo</span><span class="token operator"><</span><span class="token operator">></span><span class="token punctuation">(</span>emps<span class="token punctuation">,</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>page<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span></code></pre><ul><li><p>分页相关数据:</p><pre><code>PageInfo{pageNum=1, pageSize=4, size=4, startRow=1, endRow=4, total=8, pages=2, list=Page{count=true, pageNum=1, pageSize=4, startRow=0, endRow=4, total=8, pages=2, reasonable=false, pageSizeZero=false}[Emp{eid=1, empName='admin', age=22, sex='男', email='[email protected]', did=3}, Emp{eid=2, empName='admin2', age=22, sex='男', email='[email protected]', did=3}, Emp{eid=3, empName='王五', age=12, sex='女', email='[email protected]', did=3}, Emp{eid=4, empName='赵六', age=32, sex='男', email='[email protected]', did=1}], prePage=0, nextPage=2, isFirstPage=true, isLastPage=false, hasPreviousPage=false, hasNextPage=true, navigatePages=5, navigateFirstPage=1, navigateLastPage=2, navigatepageNums=[1, 2]}</code></pre></li><li><p>其中list中的数据等同于方法一中直接输出的page数据</p></li></ul><h4 id="常用数据:"><a href="#常用数据:" class="headerlink" title="常用数据:"></a>常用数据:</h4><ul><li>pageNum:当前页的页码 </li><li>pageSize:每页显示的条数 </li><li>size:当前页显示的真实条数 </li><li>total:总记录数 </li><li>pages:总页数 </li><li>prePage:上一页的页码 </li><li>nextPage:下一页的页码</li><li>isFirstPage/isLastPage:是否为第一页/最后一页 </li><li>hasPreviousPage/hasNextPage:是否存在上一页/下一页 </li><li>navigatePages:导航分页的页码数 </li><li>navigatepageNums:导航分页的页码,[1,2,3,4,5]</li></ul>]]></content>
<categories>
<category> CS </category>
</categories>
<tags>
<tag> MyBatis </tag>
</tags>
</entry>
<entry>
<title>nacos</title>
<link href="/post/2428cc0.html"/>
<url>/post/2428cc0.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="Nacos"><a href="#Nacos" class="headerlink" title="Nacos"></a>Nacos</h1><p>nacos本质上也是一个springboot 项目</p><h2 id="aliyunECS部署单机nacos"><a href="#aliyunECS部署单机nacos" class="headerlink" title="aliyunECS部署单机nacos"></a>aliyunECS部署单机nacos</h2><pre class=" language-bash"><code class="language-bash"><span class="token comment" spellcheck="true"># java环境依赖</span>yum <span class="token function">install</span> -y java-1.8.0-openjdk-devel.x86_64</code></pre><p><a href="https://github.com/alibaba/nacos/releases">下载nacostar.gz</a></p><pre class=" language-bash"><code class="language-bash"><span class="token comment" spellcheck="true"># 解压</span><span class="token function">tar</span> -zxvf nacos-server-2.3.0.tar.gz <span class="token comment" spellcheck="true"># 单机模式启动</span>./startup.sh -m standalone </code></pre><p>aliyun安全组<br>8848端口:web访问<br>9848端口:gRPC协议client访问<br>9849端口:服务端gRPC请求服务端端口,用于服务间同步等<br><a href="https://blog.csdn.net/qq_38173650/article/details/120560160">nacos2.x需要多暴露两个端口</a></p><p>SDKCaller测试类</p><pre class=" language-java"><code class="language-java"><span class="token keyword">package</span> com<span class="token punctuation">.</span>test<span class="token punctuation">.</span>nacos<span class="token punctuation">.</span>SDK<span class="token punctuation">;</span><span class="token keyword">import</span> com<span class="token punctuation">.</span>alibaba<span class="token punctuation">.</span>nacos<span class="token punctuation">.</span>api<span class="token punctuation">.</span>NacosFactory<span class="token punctuation">;</span><span class="token keyword">import</span> com<span class="token punctuation">.</span>alibaba<span class="token punctuation">.</span>nacos<span class="token punctuation">.</span>api<span class="token punctuation">.</span>PropertyKeyConst<span class="token punctuation">;</span><span class="token keyword">import</span> com<span class="token punctuation">.</span>alibaba<span class="token punctuation">.</span>nacos<span class="token punctuation">.</span>api<span class="token punctuation">.</span>config<span class="token punctuation">.</span>ConfigService<span class="token punctuation">;</span><span class="token keyword">import</span> com<span class="token punctuation">.</span>alibaba<span class="token punctuation">.</span>nacos<span class="token punctuation">.</span>api<span class="token punctuation">.</span>config<span class="token punctuation">.</span>listener<span class="token punctuation">.</span>Listener<span class="token punctuation">;</span><span class="token keyword">import</span> com<span class="token punctuation">.</span>alibaba<span class="token punctuation">.</span>nacos<span class="token punctuation">.</span>api<span class="token punctuation">.</span>exception<span class="token punctuation">.</span>NacosException<span class="token punctuation">;</span><span class="token keyword">import</span> java<span class="token punctuation">.</span>time<span class="token punctuation">.</span>LocalDateTime<span class="token punctuation">;</span><span class="token keyword">import</span> java<span class="token punctuation">.</span>util<span class="token punctuation">.</span>Properties<span class="token punctuation">;</span><span class="token keyword">import</span> java<span class="token punctuation">.</span>util<span class="token punctuation">.</span>concurrent<span class="token punctuation">.</span>Executor<span class="token punctuation">;</span><span class="token comment" spellcheck="true">/** * @projectName: nacos * @package: com.SDKCaller.nacos.SDK * @className: SDKCaller * @author: ludi * @description: TODO * @date: 2024/2/5 15:23 * @version: 1.0 */</span><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">SDKCaller</span> <span class="token punctuation">{</span> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span>String<span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">try</span> <span class="token punctuation">{</span><span class="token comment" spellcheck="true">// String serverAddr = "172.23.74.116:8848";</span> String serverAddr <span class="token operator">=</span> <span class="token string">"114.55.131.223:8848"</span><span class="token punctuation">;</span> String dataId <span class="token operator">=</span> <span class="token string">"druidDemoDev"</span><span class="token punctuation">;</span><span class="token comment" spellcheck="true">// String dataId = "test1";</span> String group <span class="token operator">=</span> <span class="token string">"DEFAULT_GROUP"</span><span class="token punctuation">;</span> String content <span class="token operator">=</span> <span class="token string">"testContent"</span><span class="token punctuation">;</span> Properties properties <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Properties</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> properties<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">"serverAddr"</span><span class="token punctuation">,</span> serverAddr<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment" spellcheck="true">// properties.put(PropertyKeyConst.NAMESPACE, "public");</span> properties<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span>PropertyKeyConst<span class="token punctuation">.</span>NAMESPACE<span class="token punctuation">,</span> <span class="token string">"2ce82298-746d-4566-aef5-88508bb20294"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> properties<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span>PropertyKeyConst<span class="token punctuation">.</span>USERNAME<span class="token punctuation">,</span> <span class="token string">"nacos"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> properties<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span>PropertyKeyConst<span class="token punctuation">.</span>PASSWORD<span class="token punctuation">,</span> <span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">;</span> ConfigService configService <span class="token operator">=</span> NacosFactory<span class="token punctuation">.</span><span class="token function">createConfigService</span><span class="token punctuation">(</span>properties<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment" spellcheck="true">// create(configService, "createTesting", group, "createTesting");</span> String newContent <span class="token operator">=</span> <span class="token string">"testUpdateTesting"</span> <span class="token operator">+</span> LocalDateTime<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment" spellcheck="true">// update(configService, dataId, group, newContent);</span> <span class="token function">pull</span><span class="token punctuation">(</span>configService<span class="token punctuation">,</span> dataId<span class="token punctuation">,</span> group<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment" spellcheck="true">// listener(configService, dataId, group);</span><span class="token comment" spellcheck="true">// ServiceInit.serviceCall();</span><span class="token comment" spellcheck="true">// 阻塞主线程,保持监听状态</span> <span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">try</span> <span class="token punctuation">{</span> Thread<span class="token punctuation">.</span><span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">InterruptedException</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span> e<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">NacosException</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span> e<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment" spellcheck="true">/** * 创建配置 * * @param configService * @param dataId * @param group * @param content * @throws NacosException */</span> <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">create</span><span class="token punctuation">(</span>ConfigService configService<span class="token punctuation">,</span> String dataId<span class="token punctuation">,</span> String group<span class="token punctuation">,</span> String content<span class="token punctuation">)</span> <span class="token keyword">throws</span> NacosException <span class="token punctuation">{</span> <span class="token comment" spellcheck="true">// 发布配置</span> <span class="token keyword">boolean</span> publishSuccess <span class="token operator">=</span> configService<span class="token punctuation">.</span><span class="token function">publishConfig</span><span class="token punctuation">(</span>dataId<span class="token punctuation">,</span> group<span class="token punctuation">,</span> content<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>publishSuccess<span class="token punctuation">)</span> <span class="token punctuation">{</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"Config published successfully."</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"Failed to publish config."</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment" spellcheck="true">/** * 更新配置 * * @param configService * @param dataId * @param group * @param newContent * @throws NacosException */</span> <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">update</span><span class="token punctuation">(</span>ConfigService configService<span class="token punctuation">,</span> String dataId<span class="token punctuation">,</span> String group<span class="token punctuation">,</span> String newContent<span class="token punctuation">)</span> <span class="token keyword">throws</span> NacosException <span class="token punctuation">{</span> <span class="token keyword">boolean</span> updateSuccess <span class="token operator">=</span> configService<span class="token punctuation">.</span><span class="token function">publishConfig</span><span class="token punctuation">(</span>dataId<span class="token punctuation">,</span> group<span class="token punctuation">,</span> newContent<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>updateSuccess<span class="token punctuation">)</span> <span class="token punctuation">{</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"Config updated successfully."</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"Failed to update config."</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment" spellcheck="true">/** * 拉取配置 * * @param configService * @param dataId * @param group * @return * @throws NacosException */</span> <span class="token keyword">private</span> <span class="token keyword">static</span> String <span class="token function">pull</span><span class="token punctuation">(</span>ConfigService configService<span class="token punctuation">,</span> String dataId<span class="token punctuation">,</span> String group<span class="token punctuation">)</span> <span class="token keyword">throws</span> NacosException <span class="token punctuation">{</span> String content <span class="token operator">=</span> configService<span class="token punctuation">.</span><span class="token function">getConfig</span><span class="token punctuation">(</span>dataId<span class="token punctuation">,</span> group<span class="token punctuation">,</span> <span class="token number">5000</span><span class="token punctuation">)</span><span class="token punctuation">;</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"pull:"</span> <span class="token operator">+</span> content<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> content<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment" spellcheck="true">/** * 监听配置 * * @param configService * @param dataId * @param group * @throws NacosException */</span> <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">listener</span><span class="token punctuation">(</span>ConfigService configService<span class="token punctuation">,</span> String dataId<span class="token punctuation">,</span> String group<span class="token punctuation">)</span> <span class="token keyword">throws</span> NacosException <span class="token punctuation">{</span> String result<span class="token punctuation">;</span> configService<span class="token punctuation">.</span><span class="token function">addListener</span><span class="token punctuation">(</span>dataId<span class="token punctuation">,</span> group<span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token class-name">Listener</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token annotation punctuation">@Override</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">receiveConfigInfo</span><span class="token punctuation">(</span>String configInfo<span class="token punctuation">)</span> <span class="token punctuation">{</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"Config changed: "</span> <span class="token operator">+</span> configInfo<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token annotation punctuation">@Override</span> <span class="token keyword">public</span> Executor <span class="token function">getExecutor</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment" spellcheck="true">// 如果有需要,可以返回一个自定义的Executor</span> <span class="token keyword">return</span> null<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">}</span></code></pre><h2 id="nacos鉴权开启"><a href="#nacos鉴权开启" class="headerlink" title="nacos鉴权开启"></a>nacos鉴权开启</h2><pre class=" language-bash"><code class="language-bash"><span class="token function">cd</span> /opt/nacos/conf<span class="token function">vi</span> application.properties<span class="token operator">></span> nacos.core.auth.enabled<span class="token operator">=</span>truenacos.core.auth.server.identity.key<span class="token operator">=</span>***nacos.core.auth.server.identity.value<span class="token operator">=</span>***nacos.core.auth.plugin.nacos.token.secret.key<span class="token operator">=</span>***</code></pre><h2 id="Springboot整合nacos"><a href="#Springboot整合nacos" class="headerlink" title="Springboot整合nacos"></a>Springboot整合nacos</h2><p>pom.xml依赖增加,<strong>注意springboot、springcloud和nacos三者之间的版本兼容问题</strong>,如果springboot和springcloud不兼容会出现bean创建失败无法启动<br><a href="https://spring.io/projects/spring-cloud">spring-cloud</a>我这边使用的springboot版本为2.7.2对应cloud为2021.0.x,在2020.0.x版本开始默认不开启bootstrap会导致bootstrap.yml加载不进来,所以这边又在pom中增加了spring-cloud-starter-bootstrap的依赖</p><pre class=" language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>com.alibaba.nacos<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>nacos-client<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>2.2.2<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>com.alibaba.cloud<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>spring-cloud-starter-alibaba-nacos-config<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>2021.0.5.0<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>com.alibaba.cloud<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>spring-cloud-starter-alibaba-nacos-discovery<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>2021.0.5.0<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>org.springframework.cloud<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>spring-cloud-starter-bootstrap<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>3.0.3<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span></code></pre><p>增加注解</p><pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@SpringBootApplication</span><span class="token annotation punctuation">@EnableDiscoveryClient</span><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">DruidDemoApplication</span> <span class="token punctuation">{</span> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span>String<span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span> SpringApplication<span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span>DruidDemoApplication<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span> args<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">}</span></code></pre><p>bootstrap.yml</p><pre class=" language-yaml"><code class="language-yaml"><span class="token key atrule">spring</span><span class="token punctuation">:</span> <span class="token key atrule">application</span><span class="token punctuation">:</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> druidDemoDev <span class="token comment" spellcheck="true">#为服务名</span> <span class="token key atrule">cloud</span><span class="token punctuation">:</span> <span class="token key atrule">nacos</span><span class="token punctuation">:</span> <span class="token key atrule">username</span><span class="token punctuation">:</span> nacos <span class="token key atrule">password</span><span class="token punctuation">:</span> <span class="token key atrule">discovery</span><span class="token punctuation">:</span> <span class="token comment" spellcheck="true"># namespace 只识别命名空间id</span> <span class="token key atrule">namespace</span><span class="token punctuation">:</span> 2ce82298<span class="token punctuation">-</span>746d<span class="token punctuation">-</span>4566<span class="token punctuation">-</span>aef5<span class="token punctuation">-</span>88508bb20294 <span class="token key atrule">group</span><span class="token punctuation">:</span> DEFAULT_GROUP <span class="token key atrule">server-addr</span><span class="token punctuation">:</span> 114.55.131.223<span class="token punctuation">:</span><span class="token number">8848</span> <span class="token key atrule">config</span><span class="token punctuation">:</span> <span class="token key atrule">file-extension</span><span class="token punctuation">:</span> yaml <span class="token comment" spellcheck="true">#后缀名,只支持 properties 和 yaml 类型</span> <span class="token key atrule">prefix</span><span class="token punctuation">:</span> druidDemoDev <span class="token comment" spellcheck="true">#文件名,如果没有配置则默认为 ${spring.appliction.name}</span> <span class="token key atrule">namespace</span><span class="token punctuation">:</span> 2ce82298<span class="token punctuation">-</span>746d<span class="token punctuation">-</span>4566<span class="token punctuation">-</span>aef5<span class="token punctuation">-</span>88508bb20294 <span class="token key atrule">auto-refresh</span><span class="token punctuation">:</span> <span class="token boolean important">true</span> <span class="token key atrule">enable-remote-sync-config</span><span class="token punctuation">:</span> <span class="token boolean important">true </span><span class="token comment" spellcheck="true">#启用远程同步配置,</span> <span class="token key atrule">timeout</span><span class="token punctuation">:</span> <span class="token number">3000</span> <span class="token key atrule">group</span><span class="token punctuation">:</span> DEFAULT_GROUP <span class="token comment" spellcheck="true">#配置组</span> <span class="token key atrule">refresh-enabled</span><span class="token punctuation">:</span> <span class="token boolean important">true</span> <span class="token key atrule">server-addr</span><span class="token punctuation">:</span> 114.55.131.223<span class="token punctuation">:</span><span class="token number">8848</span><span class="token key atrule">server</span><span class="token punctuation">:</span> <span class="token key atrule">port</span><span class="token punctuation">:</span> <span class="token number">8090</span></code></pre><p><img src="https://oss.luhuhu.cn/202402081515329.png" alt="image-20240208151516360"></p>]]></content>
<categories>
<category> CS </category>
</categories>
<tags>
<tag> nacos </tag>
</tags>
</entry>
<entry>
<title>商君书</title>
<link href="/post/43991583.html"/>
<url>/post/43991583.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="《商鞅与商君书》讲座——鲍鹏山"><a href="#《商鞅与商君书》讲座——鲍鹏山" class="headerlink" title="《商鞅与商君书》讲座——鲍鹏山"></a><a href="https://www.youtube.com/watch?v=eYHB5iKKzt0">《商鞅与商君书》讲座——鲍鹏山</a></h1><p>商鞅做了一些什么嘛?我们昨天在讲的过程中应该说,虽然比较简略,但整体上应该都讲到了。但是商鞅说了一些什么,那是说了很多很多。我们今天要讲可能真是有一点挂一漏万。我要说明一下今天我们所看到的《商君书》不一定全部由商鞅本人所作。所以我现在讲的“商鞅所说”的实际上讲的就是《商君书》所说的,就作为这本书,我们整体来研究它、来考察它,就这本书它讲了一些什么?这些东西对我们中国的历史产生了什么样的影响?这本书在中国历史上产生了很坏的影响,非常糟糕的影响。那你说这本书难道没有一点正面的价值吗?那肯定有。我刚才讲了,我今天讲的是挂一漏万的,我们可能只能选一点比较重要的,或者说,我觉得有必要跟大家讲的。所以我今天可能更多的讲《商君书》里面负面的东西,让我们了解一下,在中国的历史上曾经有过一种什么样的理论。这种理论,如果我们不去实际地接触它,你可能想象不到在中国历史上曾经有人这样提倡过,并且,实际上在中国古代的专制的政治里面,在实际的政治生活里面,一再地被运用,也就是说,我们这个民族在几千年的历史里面,实际上广大的人民,在很大的程度上,确实承受着这样黑暗的政治所带来的痛苦。当然我们说,这样的痛苦、这样黑暗的政治,不能由商鞅以及《商君书》这一本书来负责任,但是它确实提供了这样的一种理论。</p><h2 id="壹民理论"><a href="#壹民理论" class="headerlink" title="壹民理论"></a>壹民理论</h2><p> 关于《商君书》,我想主要讲三个内容。第一个内容,就是他所谓的“<strong>壹民理论</strong>”。壹就是壹贰叁肆伍的壹,在这个地方当动词讲:统一、唯一;民就是人民。什么叫壹民呢?就是在国家里面,只要一种人,除了这种人之外,其他的人必须通过政策,使其走投无路,让他改行,让他变成这种人。如果他不能变成这种人,等待他的就是监狱、就是杀头。这是我们今天要讲的第一个内容。就是壹民理论,简单地讲,就是国家只要一种民,哪一种民呢?就是生产的机器与战争的机器。所以《商君书》啊,法家的思想——商鞅也好,后来的韩非也好——他们是完全站在专制君主的一边,完全站所谓的国家利益的一边。所以,我们看这个标题,国家只要一种民。他站在国家的立场上,国家不是为人民服务的,恰恰相反,人民是为国家服务的。如果你不能做到这一点,那么等待你的就是惩罚,而且是非常严酷的惩罚。</p><p> 我们今天讲的是《商君书》的内容,所以我们会引用很多《商君书》中的原话来加以说明。</p><p> 那么关于壹民的理论,我这里有一个简单的概括,所谓壹民的理论,包括两个含义:第一、国家只要一种“民”,就是耕战之民。平时你为国家生产,战时你为国家当炮灰。你的存在的价值就在这两点。如果你不能作为这两种工具存在,你就是无用之民。国家只要一种民,而且还包含着第二个含义,国民只做一件事,就是耕和战。只要一种人,而且这些人只做一件事。实际上讲到这个地方的时候,我们如果稍微有一点逻辑思维和推理的能力,我们就能知道这种理论是多么的残酷,因为我们每个人都有不同的志趣,每个人都有自己不同的追求,每个人都有自己不同的爱好,每个人也都有自己不同的天赋的方向。所以马克思讲共产主义的理论是什么?共产主义的最高理想是什么?那就是每个的人性的自由的全面的发展。那每个人人性是不一样的,他的爱好是不一样的,他的志趣是不一样的,他的追求是不一样的。一个国家如果让所有的人把自己的爱好能够得到充分的发展,自己的天赋得到很好的发展,这样的国家就能够给人民提供幸福了,这样的国家也有他道德的基础了。但是商鞅的这种观点,我们显然在这样的国家里面你看不到。</p><p> 我们接着往下看,比如说他讲到这样的理论时讲到:“圣人之为国也,壹赏,壹刑,壹教。”(《赏刑》)全是壹。圣人治理国家的时候——注意他这个圣人跟儒家讲的圣人又是不一样的,概念一不样的,法家讲的圣人当然就是法王,就是专制的君主,就是像秦始皇这样的人,他们就称之为圣人——这样的人治理国家的时候,“壹赏,壹刑,壹教”:统一赏罚、统一教化。赏赐是统一的。这个赏赐统一,不是说每次赏的东西是一样的,而是赏的理由是一样的。你为国家生产的粮食多了,就给你赏赐了,你只有为国家生产粮食多了,我才给你赏赐。你说我做一个学者,我有很多的思想,很多的学术成果,有没有赏赐?没有,只有惩罚,你进监狱吧,他不需要这个东西。所以壹赏的含意是什么呢?只赏赐一种行为,只赏赐一种人,你为国家生产粮食,你为国家打仗,杀了敌人的脑袋多,带回来敌人的头颅多,只有这两种情况给你赏赐,这叫作壹赏。</p><p> 然后统一刑罚,还有统一教化。统一教化,实际上就是愚民政策。实际上我们知道真正的愚民政策,说白了不是不让人民受教育。如果不让人民受教育,人民也不一定听他的。所以真正的愚民教育政策是什么呢?真正的愚民政策是让人民只受一种教育,也就是说只接受他的教育,只接受他的思想,只接受他的观点:你必须听我的。所以壹教也就是这样:用一种思想、一种观点来教导他,其他所有的思想都是邪恶的,都是异端,都应该被清除掉。</p><p> 他接着讲到了:“入使民壹于农,出使民壹于战……民壹则农,农则朴,朴则安居而恶出。”(《算地》)对内就是种田,对外就是战争。然后他讲到了:“民壹则农”,只会种田的人,就会变得很朴实。这个朴实实际上就是很愚昧啊!他已经没有思想了,也没有眼界了,他没有见识过别的,他只会干这一项,自然就会变得所谓的朴实,这个朴实实际上是愚昧的意思。那么一个愚昧的人,一个无知的人,就会“安居而恶出”,他会很安分地待在自己的家里面,而不愿意出去。</p><p> “民之所欲万,而利之所出一。”(《说民》)老百姓有很多很多的欲望,但是国家应该让他所有的欲望都从一个渠道来实现:那就是你种田,你为国家去打仗。你做到这一点,那我们就可以赏赐你;如果你不这样做,就要惩罚你。所以“利出壹空者,其国无敌”。(《靳令》)“利出壹空”,就是利出一门,国家所有的资源都控制起来,把所有的社会资源都控制起来,然后只让它从一种渠道出去,这样国家就具有了绝对的控制社会资源的能力,国家就会变得很强大,就会无敌。我们说,治理国家应该说有两个目标,就今天来说也同样如此:人民富裕安乐是一个重要目标,然后国家强大。但是国家仅仅以一个强大作为它唯一的目标,那末人民生活在这个国家里面就不会有幸福。所以我们看儒家的治国的理想,包括道家的很多想法,他们是希望把国家治理成一个富裕的安乐的国家,是一个人民安居乐业的国家,而他们不愿意谈战争。所以孔子、孟子都是明确地反对战争的,庄子也是明确地反对战争的。我们把这个做个比较,就会发现一个很有趣的现象,法家正好相反:人民在这个国家里面能否幸福他们完全置之度外,这不是国家的目标,国家的目标就是一个:强大能攻。把国家的目标如此的绝对化,实际上就表明,在法家的政治理论里面,人民的幸福不在他们的考虑范围之内。所以我刚才讲到了,法家的理论实际上从骨子里面讲,他就完全为专制君主着想。我讲这个话,一点也没有委屈他们。</p><p> 那么这样的结果会导致一个什么问题呢?导致整个社会没有个性发展的空间,没有个体的幸福。因为国家只要一种人,当然,所有的人里面可能有人适合于种田,也可能有人喜欢当一个农民,但是很多人可能不喜欢,很多人可能在其他方面很有天赋,他在其他地方很有兴趣,但是你现在的国家只允许这一种人存在,所以在这样的国家里面,没有个性存在的空间,没有个性发展的可能,也没有个体的幸福,不存在个体的幸福。这是第一个问题。第二个问题是整个的社会目标,在一个专制的社会里面,社会的目标,他的合理性,他的正当性,是不能得到保障的。因为整个社会决策的层次,他的决策的机制,不是合理的,不是有序的,不是可控的。他是由一个专制君主根据他自己的喜怒无常的心情来决定的,今天高兴了,他就这样;明天不高兴了,他又那样。所以我们不要以为一个专制的社会里面,政府可以有一个道德上的目标,做不到的!</p><p> 所以,在专制的社会里面可能会得到一个效果:就是万众一心。但是你要知道万众一心的时候,当我们所有的人都向一个方向想的时候,它就会存在两个问题:第一、个体的思想、个体的精神都没有了;其次,万众一心必须是通过专制才能得到的,它必须通过思想控制才能得到的。然后这样确立的目标是由谁来决定的呢?不可能是一个很合理的决策者,他一定是由专制的阶层,尤其是有一个独立的、某一个单个的君主来决定的。所以这样的国家的目标,是不能保证它的合理性和正当性。所以商鞅的这样的治国方略到最后让秦国变成了什么呢?实际上秦国最终变成了一个监狱。所以按照《商君书》这样的一种理论,最好的政治就是刑律、刑法、法律;最好的国家就是监狱。这是我对秦国社会的一个总结。</p><p> 在《商君书》的理论里面,实际上最终秦国也确实把这些理论实现了。这是讲他的壹民的理论。</p><h2 id="胜民理论"><a href="#胜民理论" class="headerlink" title="胜民理论"></a>胜民理论</h2><p> 与之相关的还有一点,我们说第二点:胜民理论、制民理论。胜就是战胜的意思,制就是法制的制,制服的制——把老百姓制服了。我们要知道,作为一个个体的人,总是有他独立的个体的意志的。所以你要让他完全地照国家的意愿来行动,一定要有相应的手段逼迫他这样做,包括监狱,包括赏,包括罚。所以商鞅在提出了壹民理论以后,自然的从逻辑上讲,肯定会提出胜民理论。现在我们来看看胜民理论,这是一个非常残酷的理论。什么叫胜民呢?就是政府或者说是国家战胜人民。国家一定要战胜人民,国家一定要压服人民。他把国家和人民看成是个跷跷板:如果国家上去了,人民就必须下来;如果人民上去了,国家就会下去。所以为了让国家强大,国家一定要战胜人民。这是他的一种理论,比如他说到了:“民弱国强,国强民弱,故有道之国,务在弱民。”(《弱民》)</p><p> 《商君书》这一本书它里面有很多的思想,很多的言论,我们看不出来它有什么逻辑的论证。像这样的话,我实在是找不出来他的理论的根据是什么?为什么人民弱了国家就强大了?为什么国家强大了,人民就一定要弱下去?我们不知道他为什么这个论证是怎么来的?但他就是这么提倡的,他就这么主观认定。所以他讲到了“有道之国,务在弱民”,所以那个有秩序的国家一定要削弱人民的力量。所以我们知道:中国古代有愚民政策。我们读完《商君书》以后应该知道:还有一个弱民政策。让老百姓愚当然是让他弱的一种方法。你看他把国家和人民如此尖锐地对立起来。</p><p> “昔之能制天下者,必先制其民者也;能先胜敌者,必先胜其民者也。故胜民之本在制民,若冶于金,陶于土也。”他说古代那些把天下治理好的圣王,他一定是先把人民给制服了。“能先胜敌者,必先胜其民者也”,如果你要在战场上战胜敌人,打败其他的国家,你必须在国内先战胜你的人民。所以他说“胜民之本在制民”,要战胜人民的根本,就在于要有一个好的办法来制服他,就象一个冶金的工匠锤炼他的金属一样,就象一个陶器工匠来培埴泥胎一样。</p><h2 id="制民理论"><a href="#制民理论" class="headerlink" title="制民理论"></a>制民理论</h2><p> 商鞅呢,我觉得他就是中国的专制政治的最黑暗的核心。《商君书》是中国的传统的专制政治的最黑暗的核心,是中国古代专制君主秘不示人的他们的统治的秘诀。我们现在把这个秘诀给打开让大家来看一看,里面到底有多少黑暗的东西,有五个,<strong>一个就是以弱去强,以奸驭良,实行流氓政治,小人政治。我们下面一个一个讲。第二个就是壹教,实行思想统治。第三个就是剥夺私有资产,造成一个无恒产、无恒心的社会。我们知道剥夺私有资产,实际上就是剥夺个人自由的条件。第四个就是辱民、贫民、弱民。侮辱人民,让人民变得很贫困,让人民变得很愚弱,然后这样有利于统治。最后,如果前面的四种手段被告下来以后,还有一些人民比较强大的话,怎么办?杀!</strong></p><h3 id="以弱去强,以奸驭良,实行流氓政治,小人政治"><a href="#以弱去强,以奸驭良,实行流氓政治,小人政治" class="headerlink" title="以弱去强,以奸驭良,实行流氓政治,小人政治"></a>以弱去强,以奸驭良,实行流氓政治,小人政治</h3><p> 下面我们先看第一个:以弱去强,以奸驭良,实行流氓政治,小人政治。</p><p> 国家的人民里面,总有比较强悍的比较弱小的。这个强悍和弱小有两个层次的,一个是体格上的,你个子长得高,你体格比较魁梧,你体力比较壮,这是一种人。这种人到战场上打仗当然是好士兵,你为国家种田也很好。但是平时你如果跟国家作对,这样的人就很危险。这是一种强民。还有一种强民是什么呢?有思想的人,有知识的人,有文化的人,有见解的人。这样都属于强民。国家要强大,这样的强民必须要消灭。然后他提出来这样一句话:“以强去强者弱,以弱去强者强。”(《去强》)这句话在《商君书》的两篇文章里面一字不差地出现了两次。它应该说是商鞅很得意的一个政治格言。翻译一下,用一部分的强民去消灭另一部分强民,国家不能强大。只有用弱小的人民去消灭所有的强民,国家才能够强大。为什么是这样呢?我们来看一看,商鞅在这里说的倒是很有逻辑性。你用一部分强民去消灭了另一部分强民,存下来的怎么样?还是强民。你国家面对的还是那些强民,民强了国就弱了嘛。他前面不是有了那个前提了吗?所以他要让所有的弱民起来去消灭所有的强民,结果剩下的就全部都是弱民。这些弱民没思想的、没文化的、没知识的、愚昧的,这样的人国家就好控制他了。</p><p> 下面我引的一段话就是商鞅自己对这段话作的解释。你看这两篇文章,一个叫《去强》一个叫《弱民》。题目就很明白,“去强”就是去除强民,“弱民”弱当动词讲:削弱人民。“以强攻强,弱,强存。以弱攻弱,强,强去。强存则弱,强去则王,故经强攻弱,削。以弱攻强,王也。”(《弱民》)“以强攻强,弱,强存”,以强攻强,不行,国家会弱的,原因是什么?因为强还存在下来,还有一部分人强保存下来了。“以弱攻弱,强,强去”,这个以弱攻弱后面这个弱字,根据高享等人的解释,这个地方应该是强,就是“以弱攻强,强”。用弱民去攻打强民,国家就会强大,原因是强去,强民消灭了,国家就强大了,所以“强存则弱,强去则王”。强民一旦存在,国家就会弱,强民一旦消失了,国家就会强大。</p><p> 这个理论真的是被实行过啊!秦始皇统一中国以后,你们知道他干过什么事吗?大家都知道他焚书坑儒,焚书当然是弱民的手段之一,坑儒是把那些已经有思想的,思想上的强民给消灭掉。除此之外,他还干什么呢?杀豪俊。你看那个贾谊的《过秦论》上就讲到了“杀豪俊”。什么叫豪俊啊?就是强民嘛,强梁啊。把那些体格健壮的、性情暴亢的、不大容易服从的,都集中起来杀掉。然后留下的都是弱小之民。这是以弱民去强民。</p><p> 还有一种更为不可思议的,就是以奸民来统治良民,就是以奸驭良。在一个地方里面,比如在一个乡村里面,你选什么样的人来做乡长,选什么样的人来做村长呢?商鞅给专制君主出主意,你要选流氓出来,选恶棍出来,让这样的人去统治那些善良的老百姓,天下、国家就强大了。这可是他的原话,我可不是胡说的,你看下面的引文《去强》里面:“国以善民治奸民者,必乱,至削;国以奸民治善民者,必治,至强。”(《去强》)你一个国家如果让善民去治那些奸民,你把善民选拔出来,让他当官,让他当乡长,去治理那些奸民,那国家肯定会乱的,国家一定会削弱的。所以最好的办法是什么呢?“国以奸民治善民者,必治,至强。”让奸民去治善良的民,他认为这样的国家一定能治理好,国家一定会强大。</p><p> 我们不读这样的话,你能不能想象在中国的历史上,在全人类的历史上,还有这样的一种混账的理论啊!所以我说中国传统的专制社会里,最黑暗的核心里面,到底有些什么东西?我们可能大多数人真的是不知道的,我们只看到表面上一再地说仁义道德,一再讲我们是礼义之邦,一再讲我们有五千年文明,我们根本不知道:我们传统的政治的最黑暗的核心里面,是一些什么样的东西,是一些多么可怕的东西。</p><p> 这就是商鞅、《商君书》,还有韩非子,还有慎到,还有申不害,这一帮人给专制君主们,给他们的统治人民的手段和秘诀。</p><p> 以弱民去除强民,以奸民驾驭良民,我们想这样的社会会变成什么样的社会?这就是黑社会啊!中国几千年的社会,我可以讲就是黑社会!没问题的。所以我为什么看到有人说什么康乾盛世,我就非常生气呢?那些无知的什么人写《康煕大帝》、《乾隆王朝》,我们可能是有过所谓的专制君主们津津乐道的盛世,那秦国被商鞅治理了以后也变成强大的国家了嘛。他最后真是非常强大,所向无敌,六国都不是他的对手,统一六国了。但是这样的国家对人民意味着什么呢?你愿意生活在这样强大的国家里面吗?你愿意生活在我们今天这样自由的生活里,还是愿意生活在“康乾盛世”里?我想我们在座的各位没有一个傻到愿意活在那个时代。但是我们就有些作家喜欢生活在那样的时代,他喜欢那样的专制君主再活五百年,起码的一点价值判断的能力都没有。</p><p> 实际上对于传统的政治的这样的一种弱民政策、愚民政策,以弱民去强民的政策,进行反思的人,历代都是有的,我这儿举一个清代龚自珍。龚自珍可以说是清代末年思想解放的先驱,他对中国传统社会很多的观察非常深刻,我为什么说他很深刻?那么多年过去了,一百多年过去了,跟我们今天相比,他还那么深刻,说明什么呢?你可以说他很伟大,但是也可以得出个结论:我们实在太渺小。</p><p> “当彼其世也,而才士与才民出,则百不才督之缚之,以至于戮之……戮其能忧心,能愤心,能思虑心,能作为心,能有廉耻心,能无渣滓心。”(龚自珍《乙丙之际箸议第九》)</p><p> 龚自珍在他的《乙丙之际箸议第九》这篇文章里面讲到,有一种时代,看起来怎么看都象一个盛世,国家好象很强大,尤其是国家显得特别稳定,但是在这个国家里面是怎么样的呢?“才士与才民出,则百不才督之缚之,以至于戮之”,如果出了一个有才华的老百姓,一个有天赋的人民,周围一百个无才无德的人就会监督他、束缚他,甚至最后杀掉他。而且这种杀他的是什么呢?不一定是消灭他的肉体。是消灭他的什么呢?消灭他的“能忧心,能愤心,能思虑心,能作为心,能有廉耻心,能无渣滓心。”这是龚自珍给我们讲他的那个时代,而且这个时代表面上,从什么地方看,都像是一个盛世,都像是一个太平盛世。但是这样的结果是什么?龚自珍非常痛苦地讲到,这样的结果是,在这样的社会里面,在这样的国家家里面,在这样的民族里面,不仅我们找不到一个才士,一个才民,一个才商,有才能的知识分子,有才能的老百姓,有才能的商人,不用说这些人我们找不到了,甚至连才偷才盗,我们也找不到了,小偷和强盗都不需要技术含量就可以作案了。</p><p> 专制政治通过对个体的天赋和发展空间的挤压,最终让一个民族失去了活力,唯一得利的就是专制君主本人,就是他所代表的那些阶层。</p><p> 这是第一个,“以弱去强,以奸驭良”最终导致这样的结果。</p><h3 id="壹教"><a href="#壹教" class="headerlink" title="壹教"></a>壹教</h3><p> 二,壹教——就是思想统治。思想统治是中国的传统,对我们来说,这也不算太新鲜。所以这一点,我们放在这儿不讲了,过去吧,大家都知道,我们就不讲了。</p><h3 id="剥夺个人资本,造成一个无恒产,无恒心的社会"><a href="#剥夺个人资本,造成一个无恒产,无恒心的社会" class="headerlink" title="剥夺个人资本,造成一个无恒产,无恒心的社会"></a>剥夺个人资本,造成一个无恒产,无恒心的社会</h3><p> 我们讲第三点——剥夺个人资本,造成一个无恒产,无恒心的社会。孟子有一次和齐宣王谈话的时候,他讲到一个非常重要的东西。他说一个王者治理天下,一定要让人民有恒产,要“上可以事父母,下可以育子女”。一个人,像我们现在的中年人,国家给我们定的工资标准是什么呢?你拿这个工资,对上,能养活父母亲;对下,可以把子女抚养大。孟子说:一个想称王天下的人,一定要在这个基础上制定人民收入的标准,要保证这样的收入标准。为什么要有这样的收入标准?孟子说:人一般都是这样,有恒产的人有恒心,无恒产的无恒心。有一个固定的收入,有一个基本的生活保障,可以让你不堕落。什么叫恒心?就是保留着善良的本性,不要天天想着歪门邪道,不要想着坑蒙拐骗。有时候想想小偷,他可能真的是被生活所迫,实在是没有办法。所以孔子也好,孟子也好,他们经常的,他们在解释犯罪的时候,我觉得儒家在这个地方做得很可敬,孔子和孟子解释犯罪的时候,他不认为犯罪是由于这个人很坏,他会认为是社会原因所导致,是由于国家让人民没有基本的生活保障,然后他不得不去犯罪。所以孟子跟齐宣王讲,你要让人民有恒心,让人民保持自己的道德不堕落,在一定的道德水平上,然后能够向善。你必须给他恒产,有基本的生活保障。这是儒家的理论。</p><p> 我们来看看商鞅是怎么讲的,恰恰相反,我们讲了愚民、弱民,现在还要讲“贫民”,就要让你人民什么都没有,一无所有,然后好控制,你不听我的话没饭吃。先让你没饭吃,然后你想吃饭吗?好,听我的,听我一次给你发一点。吃完了还要听我的,再给你发一点。然后他就导致整个的人民,所有的人民道德上的堕落。所以我们刚刚讲到了:愚民,让你愚昧;弱民,让你没有能力;贫民,又导致你道德上的堕落,人格上的下流。所以你不要以为专制统治下的国民会强大,不可能强大。美国的黑人领袖马丁.路德.金,大家都知道的,他讲过一段很好的话。他说:国家的强大不在于武力的强大,不在于国家的公共设施有多强大,也不在于国家的经济有多发达。国家的强大在于公民自身,我们的公民是否很强大。这话真是讲的非常好。</p><p> 商鞅的这样一种剥夺个人资产、剥夺个人资本造成无恒产无恒心的社会,然后让人民道德普遍滑坡,道德上变得很下流。你看他讲的那些话:“治国能令贫者富,富者贫,则国多力,多力则王。”(《去强》)他就要这么折腾你,让贫的人富起来,让富的人穷下去,然后这个人富起来怎么样?再让他贫下去,就要反复折腾。为什么你知道吗?反复折腾的结果,就让你没有安全感。一个国家的老百姓没有安全感,他就没有一个定性,就没有固定的品德,就没有恒心。你没有安全感,就老要找一个外在的强权,你去依附他。没有安全感怎么办?那就有依附感。所以有人研究过狗为什么那么忠诚?是因为狗是最没有安全感的动物,所以它特别忠诚。</p><p> 除了有形的资产之外,无形的资产,他也要把你去除。比如他在《算地》这篇文章里讲到有这么一些人,比如说“谈说之士资在于口”。每个人都有他的资本,你有钱是资本,那我有无形的资本啊。谈说之士,他的资本就是口。那我今天来给大家作讲座,我的资本就是这张嘴巴。那我有这个资本,比如说你国家不给我发工资也没问题,我到处讲演也能挣点钱。那商鞅说:行。我就把你嘴封起来。“处士之资在于意”,有些思想家,他的资本是什么呢?是因为他有思想,也要控制他的思想。“勇士资在于气”,他很勇敢,他有勇气。好,也得把他勇气消灭掉。“技艺之士资在于手”,你说我什么都没有了,我学一门手艺行吧?学补皮鞋,在大街上整天给人补皮鞋,我也能活,我不要从你的体制里拿钱。你有手艺吗?好的,把你的手砍掉。你所有的你个人所能依附的全部给你破坏掉,然后你想活,你只有一个渠道,从他体制里面去拿那一份他给你的。所以剥夺个人的资本,不光是有形的物质资本,也包括你所有的赖以生存的技能、思想、学问等等,全部给你剥夺得一干二净。你想活着吗?去吧,到那儿登记去。然后让他给你分配几亩地,你去种去吧!打仗的时候你打仗去吧!这是第三点。</p><h3 id="辱民、贫民、弱民。侮辱人民,让人民贫穷,削弱人民"><a href="#辱民、贫民、弱民。侮辱人民,让人民贫穷,削弱人民" class="headerlink" title="辱民、贫民、弱民。侮辱人民,让人民贫穷,削弱人民"></a>辱民、贫民、弱民。侮辱人民,让人民贫穷,削弱人民</h3><p> 第四点,辱民、贫民、弱民。侮辱人民,让人民贫穷,削弱人民。这个地方,我们来看看他有些话,实际上这个跟前面的内容有些交叉的地方,但我专门列出来,是因为他有些话讲的,你看:“民,辱则贵爵,弱则尊官,贫则重赏。以刑治,民则乐用;以赏战,民则轻死……民有私荣,则贱列卑官,富则轻赏。治民羞辱以刑,战则战。”(《弱民》)我刚才讲了,他主要是要把体制的地位抬高,让人民在体制之外无所依存。所以让你耻辱,让你没有地位,没有尊严,没有体面,然后你就怎样呢?把国家的爵位看得很重了。你本来什么都没有,你是一个毫无体面的人,你是一个活得没有任何尊严的人,你要想有尊严怎么办?好办啊,到前线去呀,砍几个人头过来。给你一个爵位:五十石、一百石。现在我有身份了,你不要瞧不起我,我现在是有一百石的官了。但是先要把你弄到没有体面、没有尊严、没有名声,让你觉得实在没有办法活下去了,然后你就走到他那条路上。所以这叫“辱则贵爵”、“弱则尊官”。什么都没有,你一点能力都没有,只好靠官来保护你。所以我们为什么有那么多的清官意识啊?我们一直在搞清官意识。</p><p> 我记得在九十年代初,92、93年的时候,电视里天天放《包青天》,那就是清官时代。后来发现清官实在找不到几个了,没办法,那就看有没有皇上好的,就是《康熙大帝》、《乾隆王朝》了。我说皇上再靠不住怎么办呢?我说会出现神仙了,我们等着吧!我看神仙现在大致差不多也出现了。我们就没有想到建立一种制度来保护自己。商鞅倒想到了,但是他从另外一个角度想到的。然后“贫则重赏”,你不是穷得没办法吗?给你一点奖金,你就很高兴啊。我几年前看到一篇文章,说“发奖金的艺术”,写这样的文章的人都是心地不大善良的人。所以我一再讲:一个作家也好,一个学者也好,一定要让自己站在弱势群体的一边,一定要站在人民的一边。站在老板的一边,帮他出主意,这是很下流的人干的事情。</p><p> 商鞅讲是是不是这个意思啊?“贫则重赏”。你一个单位平时一个月的工资就是一万元钱,年终的时候给你发一万无钱的奖金,你没有什么感觉的。如果你平时一个月也就一千钱,年终突然给你发一万元钱奖金,你是什么感觉?不一样了吧?同是一万元钱,感觉不一样。商鞅这个家伙真是阴险,他很懂心理学。他平时把你搞得很穷,给你发一百元钱,然后年终给你一千元钱,你激动得不得了,这就叫作“贫则重赏”。然后你天天想着国家的爵位,天天想着讨好那些做官的,天天想着把国家的奖赏拿到手,你的心思是不是全在他那儿了?你的思想是不是被他控制了?很厉害啊。商鞅是绝顶聪明的人,可惜的,他又是太坏的人。一个人特别聪明如果又特别坏,那就很糟糕了。</p><p> “农有余食,则薄燕于岁。商有淫利,有美好,伤器。”农民如果有余粮,他可能就一年不好好地干活了。那怎么办呢?让他没有余粮,让他吃了上顿没下顿。就是让你没有安全感,然后就让你像蚂蚁一样,拼命地劳动。我们的寓言故事里面,把蚂蚁看成很正面的形象。到秋天了,蚂蚁开始忙了,往洞穴里面搬粮食,然后知了在那儿唱歌,蚂蚁说你别唱了,你搬粮食吧。知了不听,冬天来了,蚂蚁丰衣足食,知了饿死了。从这个角度讲,也对。我们平时应该努力一点,应该勤奋一点,应该有点储备。但是蚂蚁的这种生活状态,也太低层次了一点,一年到头就忙这点吃的,这至少不是人的生活啊,人除了物质还应该有精神啊,人应该是蚂蚁的生活和知了的生活的结合,除了搬运粮食之外还要唱歌。可是商鞅说,我就让你吃了上顿没下顿,让你天天搬动粮食都来不及,你唱歌。你别说,商鞅在文章里还专门讲到过,有一些演出的艺人,在商鞅那个时代,已经有艺人了,有时候到乡里面唱唱歌,然后老百姓给他一点东西。他说:这些人绝不允许他们到农村里面去,到农村去了,农民一看唱歌也能挣钱,他就不劳动了。</p><p> 除了这个之外,商鞅还提出了一种,无论是从政治伦理,还是法律伦理,还是法律的角度,都是非常荒谬的观点:“重刑轻赏”。“重刑轻赏,则上爱民,民死上;重赏轻罚,则上不爱民,民不死上。”(《去强》)我们知道儒家的观点是“轻刑重赏”,这是人儒家的基本观点。在《尚书》里面就明确讲到了“疑罪从轻,疑赏从重”,就是对这个人他的罪行,到底该判五年还是该判三年,这时候应该怎么办?判三年,叫“疑罪从轻”。那么“疑赏从重”,是赏他一百元还是一千元呢?那就赏一千元吧,这是儒家的思想。所以儒家的思想有很多不好的东西,我对儒家有很多的批评,但是他确实有很多人道的地方,跟法家一比,你就知道他确实是太好了。好坏是对比看看的嘛,没有绝对的好坏。但商鞅可是正相反,“重刑轻赏”。他还讲“刑重而必得”,刑一定要重。“禁奸止过,莫若重刑”。</p><p> 所以我刚才讲了,我说在商鞅的观念里面,最好的政治就是刑律啊,最有效啊。实际上商鞅的这种观念里面,我们再看下面,他还有话:“重刑轻赏,则上爱民,民死上;重赏轻罚,则上不爱民,民不死上。”这话我先翻译一下然后你看看,能不能理解他的逻辑。这个商鞅的思维跟我们是不一样的。他说对老百姓惩罚得重一点,赏得轻一点,这正好可以表现君王是热爱老百姓的,老百姓也愿意为君王去死的;反过来,如果你对老百姓赏得很多,惩罚得轻一点。那正好说明你这个国君是不热爱老百姓的,老百姓也不愿意为你去死。你能理解这样的理论吗?除非你是个受虐狂。我收拾你越厉害,你越喜欢我,那受虐狂才有这样的心理。商鞅就这么写的。所以法家思想真的是把人分成两类:专制君主就是施虐狂,老百姓就是受虐狂,全社会就是由这两种病态的人组成的。你除非从这个角度理解,否则无法理解他的话。你给我赏多一点,给我的罚轻一点,我反而不喜欢你了;你把我处罚得重一点,给我的赏特别少,我反而喜欢你。你说我有没有病啊?但这是商鞅说的话啊。所以你读《商君书》有的时候想不通,你要从病态心理学的角度去读。专制的思想真的是病态,然后他把全社会都变得很病态。</p><p> 商鞅的这个理论,即使从法律的角度讲,也是讲不通的,因为法律它有个平衡的问题,有个量刑的轻重,它一定要根据罪行的轻重来量刑。所以韩非在这一点上比他要好一点,韩非在他的文章叫《难二》里面讲到:“刑当无多,不当无少。”这话讲的纯粹从法律的角度讲,韩非讲的是对的。你给一个人的惩罚如果是恰当的,和他所犯的罪行是对等的,那就无所谓轻重。那有的人杀人了,我们就判他死刑。判死刑重不重啊?对他来说不重。但是有的人就因为偷了东西,你判他死刑,那怎样?重了。所以韩非讲“刑当无多”,只要是恰当的,就不多也不少;如果不当,你再轻也不行。如果一个人在大街上吐了一口痰,你把他逮起来,投入监狱,判了一年。然后你说没判他死刑,很轻的。那不行,这不当。吐口痰最多罚他五十。你判他一年,已经很重了。这一点韩非就比商鞅好。</p><p> 实际上商鞅的这个理论,我在读《汉书》时,看到有一个例子:《苏武传》。苏武出使匈奴,苏武手下人个副使叫张胜,和匈奴的一些人,偷偷密谋,想把单于手下的一个大臣叫卫律的杀掉。后来这个事情败露了,苏武也受牵连,就被他们逮起来审讯,苏武坚决不屈。这个故事大家都知道的。但是这里面对于苏武等人的量刑,当时有个争论,卫律对单于说:这些人,他们竟然想谋杀单于的大臣,应该把他们全部斩首。但是单于手下有另外一个人,叫左伊秩訾的人,这是个匈奴人,他说不能够斩首。这些人是谋杀单于的大臣,而且是谋杀未遂,如果你把他斩首,那么如果下一次有人说:我干脆了,我也不杀他的大臣了,我就直接把单于给杀了,你怎么再加重惩罚呢?所以左伊秩訾说:这样的人只要他愿意投降,就可以赦免他。</p><p> 左伊秩訾在提出对苏武等人量刑建议的时候,他提出了一个非常重要的法律原则,就是说:不是说我们痛恨一种现象,我们加重刑罚就可以了,因为这样会造成整个法律秩序的混乱。假如我偷一个东西你就判我死刑,那我不偷了,那我干脆抢了。抢也不过是死刑啊。是不是这个道理啊?假如我轻微地伤害了你,你就判我死刑,那干脆就把你杀了。所以法律如果这样判,如果没有差距的话,那你就逼着犯罪的人都犯最严重的罪行。因为犯最严重的罪行,对他来说是最有效益的罪行。所以,商鞅在这里讲的,一味地强调重刑,不仅是不人道的,而且也会破坏法律的秩序。</p><p> 在这儿我们可以把商鞅的很多思想,和与他同时代的春秋和战国时候的其他一些思想作比较。在《弱民》这篇文章里他讲到:“政作民之所恶,民弱。政作民之所乐,民强。民弱国强,民强国弱。”这样的理论,如果今天不把原话引出来,你也不相信会有人提出这样的政治理论。什么意思呢?国家制定政策,如果制定一个让老百姓特别讨厌、特别害怕的政策,那老百姓就弱了。老百姓弱了,你就知道结果是什么呢?国家就强了嘛。如果你制定了一个政策是符合老百姓利益的,是人民喜欢的,那么老百姓就强了。最后“民弱国强,国强民弱”,所以选择是什么呢?制定政策一定要制定一个让老百姓不喜欢的政策,要制定一个让老百姓很讨厌的政策。中国历史上有没有这样的时期啊?很多。削弱人民,就要制定一个对老百姓不利的政策,对老百姓不利了国家就强了。商鞅作为国家政策的制定者,作为一个政治理论的倡导者,他竟然公开提出来要制定削弱人民的政策,制定让人民厌恶的政策。公开这样说,真的是让人匪夷所思。我们很多专制君主是这么干的,偷偷摸摸干的。但是商鞅可是公开这么说的,白纸黑字、铁证如山。只不过我们在座的诸位大多没看过。</p><p> 我们来做个比较,我们把他和先秦其他的思想家做个比较。比如说,我们看看管仲。管仲我们在文革的时候,也把他看成是法家的人物。实际上严格地讲,他不是法家,他不是儒家,也不是道家。管仲严格意义上讲,他就是个经济学家,但是他在这里讲到了:国家制定经济政策应该怎么样?“俗之所欲,因而予之;俗之所否,因而去之。”(管仲)你看顺应民俗,顺应人民的想法。所以管仲才能取得那么大的成功啊!管仲在齐国帮助齐桓公将近四十年的时间,整个春秋时期,到了春秋后期,老百姓活得最好的时期,就是管仲的时期了。他不仅把齐国治好了,齐国是霸主嘛。他把天下各路诸侯都召集来开会,你们都必须给我规规矩矩的。天下的诸侯都很规矩,那段时间几乎没有什么战争。如果有外族入侵的话,管仲、齐桓公还带着齐国的军队,把诸侯召集起来共同抵抗。所以管仲四十年施政,在中国历史上有那么大的功劳,孔子对管仲的评价非常高。孔子批评管仲就讲这个人不懂礼仪,因为他生活比较奢侈,但是他对管仲评价很高。有人说管仲这个人是不是不好?孔子说:管仲是个仁人。用“仁”来评价管仲,多高啊!然后有人说管仲这个人是不是不好?孔子说:你不要骂管仲。“微管仲,吾其披发左衽矣。”这句话简单地说,就是没有管仲的话,我们现在中原的文化可能都不存在了啊!我们就已经被外族入侵了,整个中原都被别人占领了,我们都变成少数民族了。你看孔子对管仲的评价有多高。他为什么能取得这么大的成绩?我们就从这十六个字来看一看:他要的,我给他;他不要的,我把它改掉。顺应人民的想法,顺应人民的意愿。这才是真正的伟大的政治家,这是管仲。</p><p> 下面我们再看看庄子,庄子讲的治国。在《庄子.徐无鬼》里面,他讲了一个故事,这个原文你可以不看,我放在这儿只是表明我有根据的,不是我胡说的。黄帝把天下治得差不多了,然后他听说在昆仑山那个地方,有个天师很厉害,他想着我再去向天师讨教讨教,怎么样把国家治理得更好。他带着大臣们就去了,找了半天找不到天师。后来在路上碰到一个放牛的小孩,就问这个小孩:天师在哪里?我们想找他。这个小孩就问他:你找天师干什么啊?黄帝说:我想向天师请教一下如何治国?这个放牛的小孩就告诉他:治理国家很容易啊!就像我放牛一样,牛喜欢吃的草,你就让它吃;不喜欢吃的草,你就不让它吃。黄帝一听,马上就跪下来了:你就是天师啊!确实他就是天师。看看,道家的观点:人民喜欢的就给他,不喜欢的就改掉。这是道家的。</p><p> 儒家怎么样呢?那孔子孟子的思想我们知道了,我现在再举另外一个例子,《国语.周语》上的一段话。在召公对周厉王的一段劝说词里面,他讲到了“行善备败”。什么意思?在制定政策之前,要多方面征求意见;征求意见以后,先把这个政策进行实施。实施完了以后再考察一下,哪些政策人民喜欢,我就推广,这叫行善;哪些政策不合人民的利益,我就把它改掉,这叫备败。</p><p> 所以管仲也好,道家也好,儒家也好,他们的政治理念应该说是正常的政治理念,而商鞅的政治理念是病态的政治理念。但是我们不得不说的是,在中国古代几千年的封建统治里面,是商鞅的这个东西成了专制君主统治天下的最黑暗的内核。我们不要动不动说我们有五千年的文明史,有时候我们真的要想一下:我们有五千年的黑暗史。</p><h3 id="杀力"><a href="#杀力" class="headerlink" title="杀力"></a>杀力</h3><p> 最后讲杀力。这个杀力简单讲就是战争,发动战争。发动战争有两个好处,第一、可以“杀掉”其他的诸侯国家,可以削弱对方;其次,在战场上也把自己国家的强民杀掉了。我们等会儿要讲到,后来秦国在列国纷争里面,我们来看看他们的“战绩”。这个战绩我是打引号的。“国贫而务战,毒生于敌,无六虱,必强。”(《靳令》)国家很穷了怎么办?我们说国家穷了就别打仗了嘛。这不是正常思维吗?都穷成这样了,你还打什么仗啊?那个朝鲜,都穷成那个样了,还在搞什么核武器,然后粮食全靠中国、靠韩国、靠美国给他送去。这可能也是学了商鞅学坏的,国贫还天天要打仗。商鞅说“毒生于敌”,这样结果是什么呢?把毒转移到对方去了,国内就没有那么多坏人了——这个“虱”,就是对国家无用的六种人——就强大了。那么“国强而不战,毒输于内,礼乐虱害生,必削;国遂战,毒输于敌,国无礼乐虱害,必强。”(《去强》)如果国家强大了,你却不去发动战争,那末这个毒素就在你内部消化了,“礼乐虱害生,必削”,然后什么礼乐啊,各种各样的老百姓都产生出来了,国家就肯定会削弱。这个时候怎么办?要打仗。打了以后把毒就输给敌人了,国家又强大了。所以他讲:圣人治国,“能抟力,能杀力”。能够集中老百姓的力量,同时又能够把这些力量给杀掉,就是发动战争。“故能生力不能杀力,曰自攻之国,必削。”(《说民》)你把这些人的力量集中起来,然后你要带着他们去打仗,在战场上一方面消灭敌人,一方面也自我消灭,这样国家就越来越强大了。“能生不能杀,曰自攻之国,必削;能生能杀,曰攻敌之国,必强。”(《去强》)你把老百姓都搞得很强大,却不让他们去打仗,有那么多强大的人民在国内自己闹事,所以叫“自攻之国”,自己互相打起来了,这样的国家就会削弱了。所以要让一个国家怎样呢?“能生能杀”,要生出一些强民来,然后把他送到战场上去,又杀人,又自杀。商鞅的理论发展到最后,就是自杀,就是人体炸弹。</p><p> 这是我们对商鞅的制民的、胜民的理论,我们主要简单地讲这五点。刚才讲了,我们是挂一漏万,只是举例说明的。下面我们讲一讲,最后商鞅自身有什么样的下场,叫作法自毙啊。商鞅用他的这样一种理论来治理秦国,他确实收到了短期的明显的效果。一下子,首先秦国的粮食多了;其次,秦国军队的战斗力成倍增长,那老百姓在前方不得不卖命啊。你要他不挎几个人头回去,你得不到赏不说,你还要受罚呀。如果你在前方打败了,你投降,你的父母、子女都在那儿变成人质了。所以你宁愿在前线战死,你也不能让你的父母、子女在那个地方受苦啊。所以秦国军队的战斗力是成倍增长,一下子让六国的军队在战场上根本就不敢碰到秦国的军队,一看秦国的军队来了,他们不用打,自己都吓跑了,所以战斗力很强。</p><p> 在后来的汉代的一本书《盐铁论》里面——这个《盐铁论》我上次介绍过的——西汉政府曾经开过一次经济会议,专门讨论盐铁专卖问题。在这次会议上,关于国家很多的相关的政策,都有一些非常激烈的争论。当时国家的财政大臣就是桑弘羊,和桑弘羊辩论的是一帮所谓的文学之士。在辩论里面,其中有一个很重要的话题,就是对历史上的商鞅进行评价。这个话题后来集结成一篇文章叫《非鞅》,对商鞅进行否定。其中有这样一段话:“知其为秦开帝业,不知其为秦致亡道。”(《盐铁论.非鞅》)这话确实是很有历史眼光。就是说我们不能看一时的得失,从短时期讲,商鞅确实让秦国变得有粮食了,军队的战斗力也强大了,在列国纷争里面一下子占了上风了,并且所向无敌,把六国灭了,建立了统一的王朝,这是商鞅是成功,这就叫他“为秦开帝业”。</p><p> 但是,这样一个王朝是不可能长久的。秦王朝统一以后,十六年的时间就灭亡了,一个强大的王朝,十六年,中国历史上最短命的王朝。为什么?我们一定要找到它最后的根本的原因。那就是商鞅的这个理论,包含着它致命的弱点,他让秦国一时取得了成功,但是又为秦朝的最终灭亡埋下了祸根。在他的统治之下,在商鞅的这种政策指导下,秦国是一个无声的世界。鲁迅曾经写过一篇文章,叫“无声的中国”,一个没有声音的中国。秦国就是一个无声的秦国,秦王朝也就是一个无声的秦王朝。</p><p> 所以在商鞅死前的五个月,赵国有一个读书人见到了商鞅。商鞅专门向他请教的,说你能不能跟我谈一谈:你对我在秦国施政的政绩做一点评价,你觉得我做得怎么样?这个赵良可以说对他做了全面的否定的评价。然后赵良有一句许说得很好。他说:“千人之诺诺,不如一士之谔谔。武王谔谔以昌,殷纣墨墨以亡。”一千个人对你唯唯诺诺,都在说你好,不如一个人对你提出反对意见。一定要听取不同的意见,没有不同意见的国家,看起来是盛世,看起来非常稳定,但是就象鲁迅所讲的:“不在沉默中灭亡,就在沉默中爆发。”所以秦朝最后的灭亡,就是有一个人喊出了一句话,就是陈胜啊:“王侯将相,宁有种乎!”就是振臂一呼,天下云集响应,一个那么强大的秦王朝,被谁给灭了呢?就被一个小小的陈胜,就被陈胜所带的那个七百个人,七百个连兵器都没有的人,“折木为兵,揭竿为旗”,然后天下英雄云集响应。项羽出来了,刘邦也出来了,他秦王朝就灭了。</p><p> 当然在秦灭之前,商鞅本人也已经尝到了这样的后果,赵良已经警告了他,说:你现在靠着秦孝公,如果秦孝公死了以后,你会有什么样的结局你知道吗?秦国想杀你的人有多少你知道吗?商鞅不听啊。五个月以后秦孝公死了,太子即位了。我们知道太子的两个师傅,一个被割了鼻子,一个在脸上刺了字。那个公子虔被割了鼻子。我昨天讲了,贵族最讲的就是体面啊。你把他鼻子割了,把他脸上刺了字,他不能出来见人啊,这是多大的仇恨啊!公子虔被割了鼻子以后,八年的时间没出过门,你想他在家干什么?他唯一的愿望就是等。所以这边老秦王秦孝公这边双腿一蹬刚死,那边太子一即位,公子虔马上就上了一道奏疏:商君是谋反者。马上秦王新的秦国君王就派兵抓捕商鞅,商鞅赶紧逃跑。</p><p> 在逃跑的时候碰到两件事。在路途中,他想住一下旅店。旅店的人不认识商鞅,那时候没有电视,有电视可以天天看到他,不认识商鞅;商鞅那时也不敢说他就是商鞅。旅店的老板告诉他,说:我们国家,商君有一个很严厉的法令,旅店里面的住客如果没有官府开的介绍信,那是不允许住的,住了以后我要受惩罚的,所以我没法接待你。商鞅这个时候就尝到滋味了。他有一句感慨,他说:我没有想到,实行法治,最后是这样的结果啊。所以现在有个成语,我们的标题上写的“作法自毙”,这个成语就从那儿来的。搬起石头砸自己的脚。这是一件事。然后他逃到了魏国,魏国人不接待他。他不是魏国人吗?魏国人不要他了。本来在六国的时候,有这样的一种风气的,你在这个国家犯了罪,你逃到别的国家去了,大家就不管了,很正常,这个事情很多。比如孔子的时代,有那么多的乱臣贼子,你看孔子最讨厌的季氏手下的家臣,那个阳货。那个阳货在鲁国叛乱,最后被打败了,然后逃到赵国,赵简子把他收留了,也就算了。只要你逃了,也就没人管了。商鞅想着,我不行了,跑到魏国去,那也就算了嘛,也就过去了嘛。可是魏国的人对他是什么感情呢?我们是知道的,魏国人说:我们现在不敢接待你。为什么?因为你曾经竟然欺骗你的老朋友公子卬,用那样卑鄙的手段欺骗他,所以我们对你的人品不放心,这样的人我们不敢接待你,你还是走吧。商鞅说那好吧,我从你这儿过路,我到别的国家去。魏国人说那不行,你到别的国家不行,现在秦国这么强大,我们又打不过他,你是他们的罪人,我如果让你从我们国家经过,到别的国家去了,如果秦国找这个借口来找我们麻烦,我们怎么办?你还是回去。逼着他回到了秦国,不然他怎么会被找起来呢?他如果穿过魏国,比如跑到齐国去了,那不也没问题了吗?</p><p> 那齐国在山东,秦国在陕西,离这么远,中间隔了好几个国家,没问题的。但是魏国的人就不允许他经过,你做事做得太绝了,所以后来的《吕氏春秋》上讲到了:“士自行不可不审也。”一个人做事情,不能不审视一下后果,不能不留后路啊。商鞅现在碰到的是什么样的情况呢?“所逃莫之隐,所归莫之容。”(《新序》)没有一个地方的人愿意隐瞒他,把他隐藏起来;没有一个地方愿意接纳他。</p><p> 没有一个地方愿意接纳和隐瞒他的原因的两个,其中一个,当然是商君的人品已经让人们不齿,没有人愿意接待这样的人。还有一个,真是非常有黑色幽默的色彩,是因为商鞅的变法让秦国太强大,所以其他国家的人不敢收留秦国的罪犯。他自己让秦国强大然后导致自己以后没路可走,这真是黑色幽默。回到秦国是无路可走了,以前封他商於之地十五邑,现在还是他的吗?体制能够给你的,随时可以收回。所以我有时候在想:一门手艺比一个文凭更好,文凭可以不承认你,手艺他不能不承认吧?我在大街上修皮鞋,不要你承认,穿皮鞋的人承认就可以了。你商鞅十五邑的土地是国君分封给他的,前一代国王封给他的,那后一代国王可以收回来。可以吗?</p><p> 他现在无路可走了,他手下一帮人,那帮可能受过他一点好处的徒属,他就带着这么几十个人,上百号人向北去攻打郑国,这简直是无望的困兽之斗啊。那几百号人能打郑国吗?他为什么要打郑国呢?他想把郑国打下一块地方来,然后就在那个地方安身啊。很是可笑,真的太可笑了,完全不可能。但是他没有路可走了,他死马当活马医啊。他这边进攻郑国,后边秦国的军队就跟来了,所以最终在郑国黾池这个地方,把商君逮起来了,杀死了,然后车裂。</p><p> 这个《史记》上记载有一点矛盾的地方:《史记.商君列传》的记载,是杀死了以后再车裂的,就是五马分尸啊;但是《史记.秦本记》上面记载,好像是直接活着五马分尸的。不管是死了以后还要给他五马分尸,还是活着的时候让他五马分尸,你都可以看出来,这些人对他有多大的仇恨。死了以后还要把他的尸体拉开,这不是仇恨吗?活着把他活活地拉开,把他撕碎,不也是仇恨吗?种下的是仇恨,收获的也一定是仇恨。这就是商鞅本人的非常悲惨的下场。</p><p> 《盐铁论》上有这样一段话:“故孝公卒之日,举国而攻之,东西南北莫可奔走,仰天而叹:‘嗟乎!为政之弊至于斯极也!’卒车裂族夷,为天下人笑。斯人自杀,非人杀之也。”(《盐铁论.非鞅》)注意这样的话,这个“举国而攻之”这样的措辞是跟孔子学的。孔子在写《春秋》的时候,他特别注意字斟句酌。如果这一个人是被这个国家里面的某些人杀害的,他就会写有人杀;如果这个人让全国的人民都恨他,是人民的公敌,那么就不是有些人杀他了。你看这里的写法是“举国”,全国的人都要杀他。说明什么?说明杀死商鞅的不仅仅是公子虔,不仅仅是这些人,不仅有秦国的王公贵族,而且还有秦国普通的老百姓,人人痛恨他,真是太失败了。所以商鞅做事是成功了,但是做人太失败了。最后的结果就是“东西南北莫可奔走”,四面八方无路可走,把自己弄得无路可走,四面都是墙壁,然后只能仰天而叹。</p><p> 最后我们也知道,商鞅死了,不仅仅他一个人死了,一族都灭了,包括他的白发苍苍的老母亲,真的是很残忍,而且罪名是什么呢?反叛。你说这是不是又是一个黑色幽默啊?一个把所有的一切都献给了秦国,把良心都献给了秦国的人,就为了秦国强大,他什么都不顾了。这样忠诚的一个人,最终的罪名是反叛。所以在专制社会里面,什么样的黑色幽默都可以制造出来的。</p><p> 《盐铁论》上最后讲到“为天下笑”,注意这个笑,没有人为他哭啊。大家都为他笑,嘲笑他,成为一个笑料,成为一个笑柄。最后还有一个结论:“斯人自杀,非人杀之也。我刚才讲举国而攻之,是全国人民要杀他,不是一部分人要杀他。三个层次,一、不仅仅是王公贵族、公子虔这些人要杀他,是全国人民都要杀他,是各个诸侯国的人。因为他们不收留他,是都想杀他,是全天下的人都要杀他。不仅是王公贵族,是秦国的老百姓;不仅仅是秦国的老百姓,是当时所有诸侯国的人,是天下人。而且到最后,还不是天下人要杀他,是他自杀,自找的。</p><p> 商鞅这个人真是太值得我们去研究了,他的成功真是太成功了,他的失败也真是一败涂地。</p><p> 最后一个问题:商鞅留下了一个什么样的秦国,他死了,但是他留下了一个什么样的秦国,留下了什么样的传统。简单地说,秦国在春秋时候是落后的国家、愚昧的国家,但是到了战国的时候,在家看看《战国策》,包括《史记》上,你会看到:在战国时期的各国人士的口中讲到秦国的时候,频繁出现的四个字“虎狼之国”,这就是商鞅变法的后果。概括的一句话就是:商鞅变法让落后的秦国变成了强大的秦国,让一个愚昧的秦国变成了一个野蛮的秦国。缺少的是文明,没有文明,落后的变强大了,愚昧的变野蛮了。</p><p> 你看商鞅在《商君书.境内》里面,给军队规定的任务:“能攻城围邑、斩首八千已上,则盈论;野战,斩首二千则盈论。”(《商君书.境内》)什么叫盈论?符合朝廷给你规定的最低标准了,回来以后,你这场战争完成基本的目标了,如果在野外打仗,斩首二千以上,就符合标准了。整个的《境内》这篇文章,血淋淋的两个字:“斩首”不断地出现。战争就是以消灭对方的肉体作为目标。当然这种转变,战争变得不择手段,这种转变从《孙子兵法》就开始了。《孙子兵法》就讲到了“兵不厌诈”,开始向不择手段转变。</p><p> 实际上我们以前跟大家讲过,中原的战争传统,至少在春秋的时候,非常人道的,像一个游戏一样。你就是跟对方打仗,如果我俩一块儿,你拿着刀砍我,我拿矛攻你,打了以后我发现打不过你,我转身就跑。我已经转身跑了,你当然可以追,但是追是有规定的,你追五十步。一边追,你还要数着,一二三四五,追到五十步必须停下来,否则你就犯规了。那我已经跑了嘛,已经认输了嘛,然后我发现对方来了个人,他头发是花白的,怎么办?不打了,“不擒二毛”。头发花白是老人,是不能跟他打的,那是不人道的。我和对方打仗,如果对方已经伤了,失去战斗力了,不能再攻击他,“不重伤”。这些规定跟我们现在的国际上的一些战争法很相近啊,很人道,“不重伤”、“不擒二毛”。那你说秦国的军队行吗?我管你二毛不二毛,砍一个人头回去有五十石粮食呢!</p><p> 我们用一个个案来说明,秦国的将军白起。在《史记》里面找一个白起的传记来看一看,作为个案,秦国的将军白起的战绩。折起后来被封为武安君,因为打仗打得特别好嘛,被封为武安君。他一生带着秦国的军队攻取六国的城池有七十多座。我现在统计的,只是《史记》里面明确记载到他在这场战争里杀了多少人。《史记》里面,把这个地方攻下来没有说杀多少人,我也不统计。你看有这么几个数字:“昭王十四年,……攻韩、魏于伊阙,斩首二十四万。昭王三十四年,白起攻魏,……斩首十三万。与赵将贾偃战,沈其卒二万人于河中。昭王四十三年,白起攻韩陉城,拔五城,斩首五万。(昭王四十七年)坑杀降卒四十万。”(《史记.白起王翦列传》)二十四万回去这么一堆,然后商鞅就给他算账了,多少钱给你;二万人俘虏了以后,把他们身上绑上石头,沉到黄河里淹死;“长平之战”四十万。他就一个将军,算起来就有八十多万了。</p><p> 在这些统计里面,我要加个说明:我们还没有统计秦国士兵死亡的人数。不可能那些人都把脑袋伸着让你杀呀,你杀别人十个,人家至少要杀你一个吧。秦国士兵死亡的人数没有统计,但是有一个事情可以说明,秦国士兵死亡的人数也非常多。为什么?你想:假如你对方来的人是秦国的士兵,他一定要把你斩首,你如果有地方逃跑当然没有问题,但是你到无路可逃的时候,你怎么样?你只能是拼死反抗,因为他没有优待俘虏的政策,他不会缴枪不杀的。所以这个结果是什么?秦国的士兵杀对方的人数很多,但是秦国的士兵也必须承担巨大的牺牲,因为对方一定战到最后一个。这也是商鞅既定的政策嘛,他战争的目的就是要杀对方的人,同时也让对方把自己消灭掉一些嘛。</p><p> 我举长平之战,我们来看一看,根据司马迁的记载,在长平之战进入到相持阶段的时候,为了取得这场决定性战役的胜利,白起在前方,秦王在后方,颁布了一个政令:全国所有的老百姓每人赐爵一级,然后把十五岁以上的人,全部征调到前线长平。那就是说,我们打一点折扣吧,可能《史记》上这个地方有点夸张。《史记》是这么写的:“十五以上悉诣长平。”全部都送到长平,因为这场战争对他们来说是生死之战,他是孤注一掷了。我们打点折扣,至少可以想象,当时秦国已经用尽全力了,十五岁以上的人都已经去了。这场战争最后结果我们知道,是赵国四十万人被活埋,秦国到底死了多少?后来白起在一次讲话中说到:“秦虽破长平军,而秦卒死者过半,国内空。”秦国的士兵也死了过半,超过一半,整个国家的人口都空了。赵国死了四十万,秦国应该搭进去多少万呢?</p><p> 你可以想象,战争到了最后,通过商鞅的变法,用秦国倡导的这样一种残酷的战争方式,最终在战国时期,在中国的大地上,战争的规模、战争的血腥程度。我告诉你们,现在学术界,尤其是西方的学术界,不承认这个数字,他们无法想象战争会如此的残酷和血腥。你看剑桥的《中国秦汉史》,西方的学者对《史记》上的这些数字不相信,就因为他们觉得这个数字太大,他们太善良,他们读读《商君书》就相信了。</p><p> 这场战争结束了,我们现在还有一个统计数字:秦国在统一过程中斩杀的六国人数在150万以上。(据《史记》累计)这同样不包括秦国士兵死亡人数。除了这个数字以个,我再提供另一个数字作对比,当时全国人口总数2000万。所以秦国的统一的过程是什么过程?就是一个大屠杀的过程。</p><p> 这样屠杀的结果,秦国固然在军事上占有优势,在军事上是频频得手,但是在政治上,秦国是一败涂地。为什么?可以从两个史料来看。第一个史料,就是在《商君书》里面有一篇文章叫《徕民》,就是招徕人口。你知道那个时候人口就是第一生产力,哪个国家人口多,哪个国家力量大。所以《商君书.徕民》有一条就是让其他诸侯国的人口到秦国来。在这篇文章里有这样几句话:“三晋不胜秦,四世矣……小大之战,三晋之所亡于秦者,不可胜数也,若此而不服。秦能取其地,不能夺其民也。”赵魏韩这三个国家,跟秦国接壤的三个国家,已经四代无法战胜秦国了,大大小小的战争,三晋这个地方,被秦国占领的土地不可胜数,但是,即使到这样老百姓不服,所以他最后自己也很悲哀地说:“秦能取其地,不能夺其民也。”你可以通过武力把他的土地占过来,但是你无法征服他的民心,老百姓早跑光了——这是商鞅的。</p><p> 我们再看看白起是怎么讲的,白起后来——我举的例子都是在《史记.白起王翦列传》上的——白起后来跟秦昭王说:我们以前把赵国上党这个地方攻下来以后,上党的老百姓怎么样呢?“上党民不乐为秦而归赵。”上党的老百姓不愿意做秦国的老百姓,然后纷纷逃亡,逃回赵国,纷纷逃走了。</p><p> 再举另外一个例子,我们知道苏秦这个人物,苏秦还有个弟弟叫苏代,也是很有名的一个外交家。苏代后来到秦国,找到秦国的国相叫范睢,跟范睢说:你们这样战争的结果是不能收服人心的。他也举了这样一些例子,他说:“秦尝攻韩,围邢丘,困上党,上党之民皆反为赵。”你曾经攻打韩国,把邢这个地方攻下来了,把上党也攻下来了,可是老百姓全部逃跑了,不愿意在你秦国,都回到了赵国,所以“天下不乐为秦民之日久矣”,天下的老百姓不愿意做你秦国的老百姓已经很久很久了。</p><p> 我想说明什么问题?就是说明这样的国家很强大,但是这样的国家人民没有幸福,人民不愿意生活在仅仅是一个强大的国家里面,人民一定要生活在富裕的、安乐的国家里面,哪怕这个国家不够强大。</p><p> 最后我做一个总结。一个历史学家叫诺曼.卡曾基,他对希特勒的一本书《我的奋斗》作了一个统计,最后的结果是这样:“……《我的奋斗》这本书里,每一个字让125人丧失了生命;每一页字让4700人丧失了生命;每一个章平均让120万人丧失了生命。”那现在,我最后一个问题就是:《商君书》让多少中国人丧失了生命?问题在于希特勒的《我的奋斗》随着二战结束,他的危害就结束了。《商君书》可是一直影响中国封建社会啊!一直到清代,它到底让多少人丧失了生命?这个真的让我们反思,至少我们要警惕。</p><p> 最后,我引用泰戈尔的一段话:“谢谢上帝,我不是权力的轮子,而是被压在轮子下的活人之一。”我们都是有可能成为被压在轮子下面的活人,你不要以为你就是轮子!</p>]]></content>
<categories>
<category> 影视 </category>
</categories>
<tags>
<tag> 讲座 </tag>
<tag> 笔录 </tag>
</tags>
</entry>
<entry>
<title>0127record</title>
<link href="/post/32e9cf31.html"/>
<url>/post/32e9cf31.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><p>去参加了一个国企的笔试,写了篇反动的文章。</p><p>与一个好友分享了下大概的情况,说我这是在玩票,这种文章给我高分弄不好会影响自己的前途,必须给你打低分。哈哈哈,我觉得他说的有道理。</p><p>我似乎是在自己给自己找不痛快,既然要去考试又不肯守他们的规矩,即想要进他们的门,又不肯表现的顺从。从本质上讲,所谓的公务员、事业单位、国企的考试,是一种服从性测试,想要入门必须要学会的第一课是怎么讲漂亮话。偏偏我没学会这个技能,从小到大的教育把我改造的很好。</p><p>文章的底色就是一个人的内核,人没有办法想清楚自己认识之外的东西,我写的东西如果我自己都不信,如何让别人去相信?“不需要让人相信,大家都是相互虚假的弄一下。”我学不来。</p><p>我们的社会在惩罚认真的人,你越认真,你就越痛苦。</p><blockquote><p>当我还是个傻逼的时候,被他们那套谎言骗得热泪盈眶义愤填膺。你要小心这世上的人,他们都憋着劲儿教你学好,然后由着他们使坏。——王朔</p></blockquote><p>几千年来,君君臣臣父父子子,我们被驯化的很好,社会筛选规则的第一条就是服从性,人是群居动物,无法独自存在、延续,服从性差的自然而然会被社会所淘汰掉,留下来的都是服从性很好的,或者假装服从性很好的人,可恨从小到大教我们的都是真善美,是为了更好管理么?</p><p>生活在这样的环境里是很痛苦的,你得把认真丢掉,或者你得学会伪装,因为你没有什么能力去改变这个世界,只能去适应他。我为我儿子的未来感到担忧,对于该如何教育他感到困惑。</p>]]></content>
<categories>
<category> 杂文 </category>
</categories>
<tags>
<tag> 手记 </tag>
</tags>
</entry>
<entry>
<title>作</title>
<link href="/post/f978aef4.html"/>
<url>/post/f978aef4.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="作"><a href="#作" class="headerlink" title="作"></a>作</h1><blockquote><p>所谓傻逼,即一开口便是民族、国家和政府的安危、盛衰和荣辱,但对于自己的基本权利、自由和尊严,却从不思考,对于身边的各种不公不义和无数无辜、无助和无告的弱者,却漠不关心,这便是中国式的傻逼脑残。——王朔</p></blockquote><p>自小便是一个作文困难户,思绪很杂乱想到哪里便写到哪里,作不成“文”,看过各种满分作文、写作技巧,也被有心的老师隔三岔五的拉到办公室辅导,以期不要因作文拉了我升学考试的后腿,十分努力且不见成效。现在只觉得,作文哪里有什么教的办法,写作是自内而外的东西,教的至多是一些技法,不能代替作为内核的思想。自此之后我便放开了,写作是一种不需顾忌个体身份、社会角色等杂质的倾诉,阅卷老师无法知道你是谁,却不得不看你的作文。一篇篇尽作凤头猪肚豹尾的模样,我计划换个赛道,只管把自己真实面目展露出来,不见得美,但究一真。</p><p>很喜欢一幅漫画,大约是三个人分别在脚下有不同数量的书,脚下书最少的那个看到了美丽的世界,脚下书多一些的看到的是一片废土,再多的那个人看到了星辰。其实除了读书之外,人的年龄也会让你对世界有新的认识。</p><p>我们的社会病了,病的很重。自抗战胜利至今,近80个年头,在历史长河中这只是一个小小片段,却发生了太多太多事情。这里面我们走过许多弯路,也获得了很多成就。现在的我吃饱穿暖,甚至开起了小车、背起了房贷一副小资产阶级做派,物资水平相较于我的父辈、祖辈优越不知道多少倍,但是我的精神没有寄托,我的前面看不到光。原先说好的年终奖说没就没了,降薪职工代表大会开了一次又一次开成了滑稽大会;三鹿田文华马上要出狱了;鼠头鸭头傻傻分不清;核酸造假、科兴行贿;十年烂尾无人问一朝停贷天下知;继基尼系数之后就业率也停止公布了;2023年gdp涨幅5.2%,股市暴涨0.5%;<em>全面小康说完成就完成了;先辈留下的制度说改就改了……</em>近些年来,能说的能做的事情越来越少,浑身上下都是敏感点,一个个都在粉饰太平,李文亮们或者死了,或者自主不自主的闭上了嘴。人民是愚蠢的么?或只是在被愚弄!我的朋友让我警惕并远离那些张口闭口宏大叙事,却没有底层关怀的人。当一个人跟你大谈家国情怀、集体主义的时候,大约在下一刻他将牺牲你的个人成就他的集体,这类人要么是既得利益的坏人,要么是自我感动的蠢蛋。</p><p>恩格斯在《家庭、私有制和国家的起源》中说——“国家是私有制社会的产物,是为了保护统治阶级的利益和维护社会秩序,通过立法、法律和暴力力量维持私有制存在,对剥削阶级实施统治和控制。”罗翔的一个视频里面说:“法律是统治阶级意志的体现,是为维护统治阶级利益,以最大程度压制阶级矛盾爆发的工具。” 因此,也不难理解为什么我们的法律在我们身上像个摆设,许老板500倍杠杆炸雷熟视无睹——六朝何事,只成门户私计。你爱祖国,祖国爱你么?你还把自己应得的权益寄希望于在位者的大恩大德?祥子没有好的生活是因为他拉车不够努力,买不起花西子多找找自己的原因。你问我爱国吗?我想说“工人阶级没有祖国,不要去做王朔口中的中国式傻逼脑残。“</p><p>软弱的人总是寄希望于未来,寄希望于在位者的恩赐,虽然无动于衷却期望将来越来越好,宁可麻木,不要痛苦。然而如果过去的事情就这么过去了,未来只会越来越糟。 ”愿中国青年都摆脱冷气,只向上走,不必听自暴自弃者流的话。能做事的做事,能发声的发声。有一份热,发一分光。就如萤火一般,也可以在黑暗中发出一点光,不必等候炬火。“不止是青年,愿中国中年、中国老年一并摆脱冷气,去做一个愤怒的人,去做事,去发声,去唤醒团结那些被愚弄的人民,去掀掉这个铁屋子 ,不在沉默中爆发,就在沉默中死亡,即便会死去也要嘶吼着死去。</p>]]></content>
<categories>
<category> 杂文 </category>
</categories>
<tags>
<tag> 手记 </tag>
</tags>
</entry>
<entry>
<title>kubernetes</title>
<link href="/post/d597c8d0.html"/>
<url>/post/d597c8d0.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><p>Kubernetes</p><p><strong>特性:</strong></p><p>容器编排,通过配置文件<br>高可用,自动重启、重建等<br>可扩展,提高性能利用率<br>灾难恢复、弹性回复等</p><p>组件:</p><ul><li><p>Node节点:虚拟机、物理机</p></li><li><p>Pod:最小调度单元,一般情况1个pod一个应用程序,或者多个高耦合应用1个pod</p></li><li><p>Svc:入口代理,解决pod故障重启导致的IP变化</p></li><li><p>Ingress:配置转发规则等</p></li><li><p>ConfigMap:封装配置信息,应用程序和数据库的解耦</p></li><li><p>Secret:类似configMap,base64编码敏感信息</p></li><li><p>Volumes:持久化组件</p></li><li><p>Deployment:定义、管理应用程序的副本数量、更新策略,多个pod热备,提供服务健壮性需求</p></li><li><p>StatefulSet:定义、管理副本数量策略等,动态扩缩容,有状态类的应用需要保存在这里比如数据库</p></li></ul><p>架构:</p><ul><li>master-worker<ul><li>workNode<ul><li>kublet:管理维护每个节点的pod;定期从api-serv拉去新的规范,监控工作节点的运行状态汇报给api-serv</li><li>kube-proxy:网络代理、负载均衡</li><li>container-runtime</li></ul></li><li>masterNode<ul><li>kube-apiserv:api接口服务,集群的网关;对所有资源的crud进行权限控制鉴定</li><li>Scheduler:调度器</li><li>controller manager:故障监控</li><li>etcd:键值存储信息,存储所有资源对象的状态信息,数据存储中心</li><li>cloudControllerManager:云平台相关的控制器</li></ul></li></ul></li></ul><p>搭建环境:</p><ul><li>minikube、kubectl</li></ul>]]></content>
<categories>
<category> CS </category>
</categories>
<tags>
<tag> k8s </tag>
</tags>
</entry>
<entry>
<title>TheSecretLivesOfKyotoFolk</title>
<link href="/post/ca095017.html"/>
<url>/post/ca095017.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="The-secret-Lives-of-Kyoto-Folk"><a href="#The-secret-Lives-of-Kyoto-Folk" class="headerlink" title="The secret Lives of Kyoto Folk"></a>The secret Lives of Kyoto Folk</h1><blockquote><p>先前去过京都,对京都人礼貌、友善印象深刻,引起对知晓其来源的强烈渴望。</p></blockquote><p>纪录片已经看完了,计划重新看一遍把每集的大概做个记录。——TO DO</p><hr>]]></content>
<categories>
<category> 影视 </category>
</categories>
<tags>
<tag> 纪录片 </tag>
</tags>
</entry>
<entry>
<title>JLPT</title>
<link href="/post/7ad0db58.html"/>
<url>/post/7ad0db58.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="日语JLPT-N2"><a href="#日语JLPT-N2" class="headerlink" title="日语JLPT-N2"></a>日语JLPT-N2</h1><h2 id="入门课"><a href="#入门课" class="headerlink" title="入门课"></a>入门课</h2><h3 id="五十音"><a href="#五十音" class="headerlink" title="五十音"></a>五十音</h3><p><img src="https://loaderland-picgo.oss-cn-shanghai.aliyuncs.com/202312300107248.jpg" alt="五十音"></p><p><img src="http://oss.luhuhu.cn/202401251508878.jpg" alt="image"></p><h3 id="资料"><a href="#资料" class="headerlink" title="资料"></a>资料</h3><p>青空文库<br>weblio<br>ojad<br>筑波语料库</p><h2 id="新标日000"><a href="#新标日000" class="headerlink" title="新标日000"></a>新标日000</h2><ol><li>单词、课文都要会背</li><li>课后题&同步练习全要写</li><li>课文带读/单词带背/课</li><li>自学建议:单词 - 语法 - 背单词 - 背课文 - 课后练习/同步练习册</li><li>笔记</li></ol><p>日语等级考试: 每年7月和12月第一周周日举行考试,报名时间在大概提前3个月 </p><p><strong>浙江考点</strong></p><table><thead><tr><th>序号</th><th>名称</th><th>地址</th><th>电话</th><th>网址</th></tr></thead><tbody><tr><td>1021402</td><td>浙江工商大学(下沙校区)</td><td>杭州市下沙高教园区学正街18号,浙江工商大学下沙校区310012</td><td>0571-88066397</td><td><a href="http://flc.zjgsu.edu.cn/news/?87_5895.html">http://flc.zjgsu.edu.cn/news/?87_5895.html</a></td></tr><tr><td>1021403</td><td>浙江教育考试服务中心 (浙江工业大学之江学院 )</td><td>绍兴市柯桥区越州大道958号浙江工业大学之江学院致知楼 3C310018</td><td>0571-96399</td><td><a href="https://www.zjzs.net/moban/index/8a11f15486be1bb60186bee8979a0001.html">https://www.zjzs.net/moban/index/8a11f15486be1bb60186bee8979a0001.html</a></td></tr><tr><td>1022701</td><td>宁波大学</td><td>宁波市风华路818号宁波大学教学楼 <a href="http://ffl.nbu.edu.cn/315211">http://ffl.nbu.edu.cn/315211</a></td><td>0574-87600022, 0574-87601650</td><td><a href="http://fls.nbu.edu.cn/cgks.htm">http://fls.nbu.edu.cn/cgks.htm</a></td></tr><tr><td>1021401</td><td>浙江大学(紫金港校区)</td><td>杭州市西湖区三墩镇浙江大学紫金港校区东一教学楼310058</td><td>0571-88273293</td><td><a href="http://www.sis.zju.edu.cn/sischinese/2023/0302/c12616a2722717/page.htm">http://www.sis.zju.edu.cn/sischinese/2023/0302/c12616a2722717/page.htm</a></td></tr><tr><td>1024301</td><td>浙江越秀外国语学院</td><td>绍兴市会稽路428号F幢教学楼312000</td><td>0575-89184015</td><td><a href="https://cj.zyufl.edu.cn/2022/0225/c1025a46739/page.htm">https://cj.zyufl.edu.cn/2022/0225/c1025a46739/page.htm</a></td></tr></tbody></table><h2 id="新标日001"><a href="#新标日001" class="headerlink" title="新标日001"></a>新标日001</h2><ol><li>~は~です</li><li>~は~では ありません<br>~は~じゃ ありません</li><li>~は~ですか<br>はい,そうです<br>いいえ,ちがいます<br>わかりません,どうもすみません</li><li>~の~です</li><li>わたし/あなた/あのひと</li><li>はじめまして,どうぞよろしくあねがいします<br>こちらこそ,よろしく</li></ol><h2 id="新标日002"><a href="#新标日002" class="headerlink" title="新标日002"></a>新标日002</h2><ol><li><p>これ/それ/あれ/どれ;この/その/あの/どの<br>这/那(你)/那(他)/哪(三个以上),の后需要跟名词<br>eg.これは だれの ほん ですか<br>eg.どの つくえ は 小野さん ですか</p></li><li><p>なん / だれ(どなた)<br>什么/谁(敬)</p><p>*なに & なん<br>eg.それは なん ですか<br>eg.それは だれ ですか<br>eg.スミスさん は どなた ですか</p></li><li><p>ひと/かた<br>人 <br>eg.あのひと は だれ ですか<br>eg.あのかた は どなた ですか</p></li><li><p>なんさい/おいくつですか <br>年龄(礼貌用语)<br>eg.~は なんさい ですか<br>eg.~は おいくつ ですか</p></li><li><p>どうぞ<br>eg.どうぞ よろしくあねがいします</p></li><li><p>どうも ありません ございます</p></li></ol><h2 id="新标日003"><a href="#新标日003" class="headerlink" title="新标日003"></a>新标日003</h2><ol><li><p>ここ/そこ/あそこ/どこ</p><p>こちら/そちら/あちら/どちら<br>指示场所,位置关系与これ/それ/あれ相同<br>eg.ここは デパート です<br>eg.こちらは デパート です</p></li><li><p>~も~です<br>也</p></li><li><p>~は いくらですか<br>询价<br>eg.これは いくらですか</p></li><li><p>あのう</p></li></ol><h2 id="新标日004"><a href="#新标日004" class="headerlink" title="新标日004"></a>新标日004</h2><ol><li>あります/います<br>eg.へや に ねこ が います<br>eg.ねこ は へや に います<br>eg.ここ に ほん が あります<br>eg.ほん は ここ に あります<br>eg.へや には なにも ありません<br>eg.へや には だれも いません</li><li>と<br>并列,<del>和</del></li><li>うえ/した/まえ/うしろ/なか/そと<br>上下前后邻中外,表达具体位置前加の<br>eg.しくら の うえ に なこ います<br>eg.なこ は はこの なか に います</li></ol>]]></content>
<categories>
<category> 语言 </category>
</categories>
<tags>
<tag> 日语 </tag>
</tags>
</entry>
<entry>
<title>Lijingming</title>
<link href="/post/77c7a536.html"/>
<url>/post/77c7a536.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="《李金明》"><a href="#《李金明》" class="headerlink" title="《李金明》"></a>《李金明》</h1><blockquote><p>名字是假的,痛苦是真的。</p></blockquote><div id="dplayer0" class="dplayer hexo-tag-dplayer-mark" style="margin-bottom: 20px;"></div><script>(function(){var player = new DPlayer({"container":document.getElementById("dplayer0"),"theme":"#FFFFFF","video":{"url":"http://oss.luhuhu.cn/Lijingming.mp4","pic":"http://oss.luhuhu.cn/202401041046761.jpg"}});window.dplayers||(window.dplayers=[]);window.dplayers.push(player);})()</script>]]></content>
<categories>
<category> 影视 </category>
</categories>
<tags>
<tag> 李金明 </tag>
<tag> 闫泽欢 </tag>
</tags>
</entry>
<entry>
<title>京都6日</title>
<link href="/post/fbf3747f.html"/>
<url>/post/fbf3747f.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><p><img src="https://loaderland-picgo.oss-cn-shanghai.aliyuncs.com/202312191652028.jpg" alt="京都_八坂神社"></p><p>京都旅行第三天,为避免叙事混乱要先讲清楚来由:<br>旅行计划为12月8日至12月13日,周五13:20的航班,到大阪当地时间18时余。<br>接机小哥,中国人,路途漫长便搭上了几句话,高中毕业学了两年海员由于是家中独子便到日本想换份行当,至今已有13个年头,其妻是二手奢侈品专柜前台(中国籍),有两个小孩已带来日本,计划明年申请永居。对他的现状羡慕但又没那么羡慕。羡慕他在日本即将扎下根来,不羡慕他做的还是一些较辛苦的工作——来自国内根深蒂固非正确认识<br>我想要的生活,应该是没有996的压迫和无意义内卷,人与人之间有更多的尊重和自省,可以平静的工作、生活,不被裹挟地前进,可以选择停留、甚至后退。我想要更多的自由度,更多的空间,更多的可能,但这个渴望似乎不够强烈,不足以摧毁我对现状的依赖,既要又要,贪得无厌。</p><p>日本是一个非常干净的国家,路上的小汽车都泛着光,连混凝土搅拌车都秀气了很多,街面上也找不到一个垃圾桶,这里的人们好像不会生产垃圾似的,我找了好些地方也没找到一个丢垃圾的地方,终于在一户人家门前找到一个貌似丢垃圾的地方,上面写了些字,大约是“禁止偷倒”的意思。</p><p>这儿的人很奇怪,经常看到有些走着走着憩在有太阳的地方不动了,过一会儿又走掉了,就没个正经事情要忙吗?在景点里经常可以遇到着日服的青年男女,记得是最后一天上午吧,天气很好,建仁寺内,一个穿着通身白色和服的女孩子,走在石板路上发着光,让我睁不开眼睛,我应该拍一个照片的。在路边还可以看到许多一眼6、70的老人,右手拄着登山杖或拐杖,左手拿着一个小20厘米镜头的单反,戴个金丝的老花镜,在这个干净的小巷子里到处找风景,我大约是老不成这样的。这里的笑脸仿佛很便宜,在路边走着就要时不时点头回应一些陌生的问候,令我局促和不适应。</p><p>去了一些神社,看了一些鸟居,到处都是乌鸦,阿阿阿叫个不停,文说这是立体声环绕,并且它们好像不太聪明,离得我们很近。我说:“大概是不好吃吧?”,文想要讲我,但又没有好的措辞,“你这个人,真的是…”,用崇洋媚外好像太高了,说我土比较合适吧,那我的确土。<br>在这里似乎神和鬼都按在一个地方,上山的路边总能看到有名有姓的碑。装一个大的铃铛,置一块门槛石,人立在上面摇几下铃铛,大力合掌两三次,双手合十做虔诚状许愿祈祷。我是不信的,但是看上去挺有意思。<br>又去了一些打卡点,像“鸭川”、“京都塔”之类的,就我感觉来说还是小气了一些,像这种小河、小塔,国内不说到处都是,也是很容易找到的,若都要取个名字怕是禽类的名字都要被用完。就好像吃惯了麻辣火锅,尝不出米其林的精细,只觉得贵。</p>]]></content>
<categories>
<category> 游历 </category>
</categories>
<tags>
<tag> 旅游 </tag>
</tags>
</entry>
<entry>
<title>Record</title>
<link href="/post/9c989aa7.html"/>
<url>/post/9c989aa7.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="一些文字"><a href="#一些文字" class="headerlink" title="一些文字"></a>一些文字</h1><h2 id="民主、自由"><a href="#民主、自由" class="headerlink" title="民主、自由"></a>民主、自由</h2><p><img src="https://loaderland-picgo.oss-cn-shanghai.aliyuncs.com/202312281633549.jpeg" alt="Equality&Equity&Justice"></p><blockquote><p>我们知道民主思想起源于古希腊古罗马——公民可以直接参与政治和法律决策,每个公民有平等的权利和义务,人身自由不受奴役和束缚。但是我们从来不谈古希腊、古罗马它公民的比例可能只占到10%左右,这种民主和自由是建立在90%奴隶人口负责生产,10%自由人人口做文化建设,形成了以自由民为主题的文化表达。这是建立再奴役、压迫大多数人的基础上的民主自由。 ——温铁军</p></blockquote><p>自由像是一个漂亮的花瓶,美丽且脆弱。我们可以为了自由去抗争,但是不能用自由去抗争,它是面旗帜更多的是提供精神鼓舞的作用。在追求它的时,人们可以众志成城,但是一旦获得了自由就会瞬间失去力量,在这点上宗教比它有优势。个体对自由的感受大程度上取决于统治阶级的统治自信,越自信你就越自由,越自由你就越发现你的自由来自你的虚弱,假使你有那么一点力量能威胁到统治,他们就会毫不手软的连你带自由一起拔除掉。</p><hr><p>民主,我们追求的民主是到底是什么?是生而平等还是公平?民选的政权总说自己选择相对意义上的公平,最起码得假装成那个样子。古希腊、古罗马的民主是建立在少数人奴役压迫大多数人,少数人负责文化建设,多数人负责生产,价值观话语权被少数人掌握,广大人民的意志不被表达,最后形成了少数人奴役压迫多数人的现状。只看到了高高举起的民主自由的旗帜,旗帜下的累累白骨极少提及,那我们的民主是不是一样呢?宣传大跨步向现代化前进,却极少提起摆在面前的房地产暴雷、就业率失控的现状。因为“没有大国崛起,何谈小民尊严”,用爱国主义、集体主义牺牲个体时变得理所当然,人血馒头好吃。</p><hr><p>维系政权有几个关键的要点:1. 让大多数人觉得自己是被代表的,爱国民族集体主义教育是主要手段,加上一定程度的信息封锁 2. 在国际上要有自己的位置,主要体现在国防建设、经济发展上。<br>真正的集体主义应该是尊重每个个体选择的,如果一个集体主义是以通过压迫牺牲个体来实现的,这时候集体主义是实现独裁统治最好的面具。警惕每个和你谈集体主义的人,当他跟你大谈集体主义的时候,往往下一秒他就想要把你牺牲掉。<br>在国际局势中要有自己的位置,如果只醉心于对内的统治,仅靠经济发展、信息封锁是不能长久的,清初的人口只有7千万,而到了清晚期人口达到了4亿之巨,你不能说他经济发展是失败的,这说明白银是不能替代军舰大炮的。</p><hr><p>知识分子的权力依附性<br>知识本身不能体现为权力,只有通过和政治权力关联才能得到权力。因而知识分子如果想拥有权力就必须选择和拥有政治权力的个人或群体联系在一起,但如果掌握了知识但是没有获得权力,由于不满于现状,继而和掌权者的形成权力竞争关系,既反权力的人也是为了追求权力。</p><hr><p>形式和仪式。前些日子参加了一个婚礼,新娘很漂亮,婚纱也很闪,新郎挺帅且很有才情,差点把婚礼现场变成了个人演唱会,当然还有风格很古怪的《武陵外传》。或许大多数人都比较拘谨,不太会表露情感,我当初结婚的时候也是同样的,婚礼好像是一个流水线,表演节目、主持人致辞、戴戒指等等,形式感大过仪式感太多,就好像昨天写的课文今天要交的作业,脑子里时时刻刻都是下一句是什么,没多少情感的色彩,乏味。<br>回家的路上,我跟文聊天。</p><blockquote><p>“今天我们桌的女孩子只有你没有化妆。”<br>“好还是不好?”<br>“好。”<br>“怎么说?”<br>“用力过度,过犹不及,让我感觉有点突兀。同样化妆在京都遇到的女孩子给人的感受自然的多”<br>“因为人家的精致是从头到脚的精致,从内而外的精致”</p></blockquote><p>让我想起一段采访,大约是记者问名媛为什么没有纹身之类的,她回答你会在一个璞玉上涂鸦吗。人不会因为你背了个LV,脸上化的妆而改变她的品质,如果因为配饰和形象的层次参差不齐反而会起到反作用,是所谓品味。</p>]]></content>
<categories>
<category> 杂文 </category>
</categories>
<tags>
<tag> 手记 </tag>
</tags>
</entry>
<entry>
<title>hexoGuide</title>
<link href="/post/72e1a522.html"/>
<url>/post/72e1a522.html</url>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="HexoInitGuide"><a href="#HexoInitGuide" class="headerlink" title="HexoInitGuide"></a>HexoInitGuide</h1><h2 id="环境依赖"><a href="#环境依赖" class="headerlink" title="环境依赖"></a>环境依赖</h2><p><img src="https://oss.luhuhu.cn/202406051131649.png" alt="Hexo系列个人博客网站 - 知乎"></p><h3 id="开发环境"><a href="#开发环境" class="headerlink" title="开发环境"></a>开发环境</h3><pre class=" language-bash"><code class="language-bash">$ <span class="token function">npm</span> -v8.19.4$ node -vv16.19.1$ <span class="token function">npm</span> config <span class="token keyword">set</span> registry https://registry.npm.taobao.org$ <span class="token function">npm</span> [email protected] E:\Hexo-blog\hexo├── [email protected]├── [email protected]├── [email protected]├── [email protected]├── [email protected]├── [email protected]├── [email protected]├── [email protected]├── [email protected]├── [email protected]├── [email protected]├── [email protected]├── [email protected]├── [email protected]└── [email protected]</code></pre><p><a href="https://easyhexo.com/">EasyHexo</a><br><a href="https://blinkfox.github.io/2018/09/28/qian-duan/hexo-bo-ke-zhu-ti-zhi-hexo-theme-matery-de-jie-shao/">hexo&hexo-theme-matery 使用指北</a></p><h3 id="其他"><a href="#其他" class="headerlink" title="其他"></a>其他</h3><h4 id="Typora"><a href="#Typora" class="headerlink" title="Typora"></a>Typora</h4><p>md编辑工具</p><h4 id="PicGo"><a href="#PicGo" class="headerlink" title="PicGo"></a>PicGo</h4><p>图床工具</p><h4 id="aliyunOss"><a href="#aliyunOss" class="headerlink" title="aliyunOss"></a>aliyunOss</h4><p>图床oss存储(需付费)</p><h4 id="jsdelivr"><a href="#jsdelivr" class="headerlink" title="jsdelivr"></a>jsdelivr</h4><p>免费公共cdn,不是很稳定后续考虑更换,存在缓存不及时更新的问题<br>更新缓存link:<a href="https://purge.jsdelivr.net/gh/loaderland/loaderland.github.io">https://purge.jsdelivr.net/gh/loaderland/loaderland.github.io</a><br>代理link:<a href="https://cdn.jsdelivr.net/gh/loaderland/loaderland.github.io">https://cdn.jsdelivr.net/gh/loaderland/loaderland.github.io</a></p><h4 id="github"><a href="#github" class="headerlink" title="github"></a>github</h4><p>部署静态页面</p><h4 id="域名代理"><a href="#域名代理" class="headerlink" title="域名代理"></a>域名代理</h4><p>aliyun域名CNAME转发(需付费)<br>每次clean generate deploy 都会清理掉public目录,会导致CNAME文件丢失,可以把CNAME放到source文件夹中</p><h4 id="视音频"><a href="#视音频" class="headerlink" title="视音频"></a>视音频</h4><p>md文件中插入视频、音频:</p><ol><li><p>oss存储视频文件,需要使用自定义域名功能(<a href="https://help.aliyun.com/zh/oss/how-to-play-videos-online-in-oss">原因</a>),本地PicGo图床需要同步设置自定义域名——完成之后可以通过浏览器验证是否生效</p></li><li><p>hexo安装使用aplayer、dplayer插件</p><p>安装插件</p><pre class=" language-bash"><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> hexo-tag-aplayer<span class="token function">npm</span> <span class="token function">install</span> hexo-tag-dplayer</code></pre><p><a href="https://github.com/MoePlayer/hexo-tag-aplayer">hexo-tag-aplayer</a></p><p><a href="https://github.com/MoePlayer/hexo-tag-dplayer">hexo-tag_dplayer</a></p><p>使用插件</p><pre class=" language-markdown"><code class="language-markdown">{% <span class="token code keyword"> dplayer </span><span class="token code keyword"> "url=http://oss.luhuhu.cn/Lijingming.mp4" //设置视频目录,这里我放在了网站根目录下面,也就是public目录下面 </span><span class="token code keyword"> "pic=http://oss.luhuhu.cn/202401041046761.jpg" //设置封面图,同样是放在根目录下面 </span><span class="token code keyword"> "loop=yes" //循环播放</span><span class="token code keyword"> "theme=#FADFA3" //主题</span><span class="token code keyword"> "autoplay=true" //自动播放</span><span class="token code keyword"> "screenshot=true" //允许截屏</span><span class="token code keyword"> "hotkey=true" //允许hotKey,比如点击空格暂停视频等操作</span><span class="token code keyword"> "preload=auto" //预加载:auto</span><span class="token code keyword"> "volume=0.9" //初始音量</span><span class="token code keyword"> "playbackSpeed=1"//播放速度1倍速,可以选择1.5,2等</span><span class="token code keyword"> "lang=zh-cn"//语言</span><span class="token code keyword"> "mutex=true"//播放互斥,就比如其他视频播放就会导致这个视频自动暂停</span> <span class="token code keyword"> //下面是弹幕相关</span><span class="token code keyword"> "id=9E2E3368B56CD123BB4"</span><span class="token code keyword"> "api=https://api.prprpr.me/dplayer/"</span><span class="token code keyword"> "token=tokendemo"</span><span class="token code keyword"> "maximum=1000"</span><span class="token code keyword"> "addition=['https://api.prprpr.me/dplayer/v3/bilibili?aid=?']"</span><span class="token code keyword"> "user=DIYgod"</span><span class="token code keyword"> "bottom=15%"</span><span class="token code keyword"> "unlimited=true"</span> %}</code></pre></li></ol><div id="dplayer1" class="dplayer hexo-tag-dplayer-mark" style="margin-bottom: 20px;"></div><script>(function(){var player = new DPlayer({"container":document.getElementById("dplayer1"),"theme":"#FFFFFF","video":{"url":"http://oss.luhuhu.cn/Lijingming.mp4","pic":"http://oss.luhuhu.cn/202401041046761.jpg"}});window.dplayers||(window.dplayers=[]);window.dplayers.push(player);})()</script><p><a href="https://easyliu-ly.github.io/2020/11/22/hexo/insert_video/#:~:text=Hexo%E5%8D%9A%E5%AE%A2%E4%B8%AD%E6%8F%92%E5%85%A5%E9%9F%B3%E4%B9%90%2F%E8%A7%86%E9%A2%91%2F%20DPlayer,http%3A%2F%2Fdplayer.js.org%2Fguide.html%23quick-start%20%E7%84%B6%E5%90%8E%E5%9C%A8md%E6%96%87%E4%BB%B6%E4%B8%AD%E6%8F%92%E5%85%A5%E5%A6%82%E4%B8%8B%E4%BB%A3%E7%A0%81%EF%BC%8C%E8%A7%86%E9%A2%91%E5%B0%B1%E6%AD%A3%E5%B8%B8%E5%8A%A0%E8%BD%BD%E8%B5%B7%E6%92%AD%E4%BA%86%EF%BC%8C%E8%BF%99%E9%87%8C%E6%92%AD%E6%94%BE%E7%9A%84%E6%98%AF%E6%9C%AC%E5%9C%B0%E8%A7%86%E9%A2%91%EF%BC%81">hexo插入音频和视频</a></p><h4 id="图片加载问题"><a href="#图片加载问题" class="headerlink" title="图片加载问题"></a><a href="https://blog.csdn.net/qq_40838461/article/details/121270040">图片加载问题</a></h4><p>由于git主站https 和oss服务器没有经过ssl认证http不同而导致图片加载失败。<br>申请aliyun免费ssl证书部署到oss域名既可。</p><h4 id="文章加密"><a href="#文章加密" class="headerlink" title="文章加密"></a>文章加密</h4><ol><li>在theme config.yml中开启<code>verifyPassword</code>功能;</li><li>文章front中增加<code>password</code>,要求为<code>SHA256</code>加密后的的值</li></ol><h4 id="文章图片显示"><a href="#文章图片显示" class="headerlink" title="文章图片显示"></a>文章图片显示</h4><p>front 中有<code>img</code>标签</p>]]></content>
<categories>
<category> CS </category>
</categories>
<tags>
<tag> hexo </tag>
<tag> blog </tag>
</tags>
</entry>
</search>