-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatom.xml
415 lines (219 loc) · 413 KB
/
atom.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
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>九月的生活</title>
<subtitle>无限进步! | blog.sakurasep.site</subtitle>
<link href="https://blog.sakurasep.site/atom.xml" rel="self"/>
<link href="https://blog.sakurasep.site/"/>
<updated>2024-10-22T06:29:10.000Z</updated>
<id>https://blog.sakurasep.site/</id>
<author>
<name>上杉九月</name>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>EmbyBot使用指南</title>
<link href="https://blog.sakurasep.site/posts/emby_bot/"/>
<id>https://blog.sakurasep.site/posts/emby_bot/</id>
<published>2024-10-22T06:29:10.000Z</published>
<updated>2024-10-22T06:29:10.000Z</updated>
<content type="html"><![CDATA[<h2 id="使用教程"><a href="#使用教程" class="headerlink" title="使用教程"></a>使用教程</h2><h3 id="1-添加-TGBot"><a href="#1-添加-TGBot" class="headerlink" title="1. 添加 TGBot"></a>1. 添加 TGBot</h3><div class="tag-plugin link dis-select"><a class="link-card rich" title="九月的 EmbyBot" href="https://t.me/sakurasep_emby_bot" target="_blank" rel="external nofollow noopener noreferrer" cardlink api="https://site-info-api-git-main-sakurasep.vercel.app/api/v1?url=https://t.me/sakurasep_emby_bot" autofill="icon,desc"><div class="top"><div class="lazy img" data-bg="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/link/8f277b4ee0ecd.svg"></div><span class="cap link footnote">https://t.me/sakurasep_emby_bot</span></div><div class="bottom"><span class="title">九月的 EmbyBot</span><span class="cap desc footnote"></span></div></a></div><p><img src="/../../img/EmbyBot%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20241023143405912.png" alt="image-20241023143405912"></p><p><img src="/../../img/EmbyBot%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20241023144235152.png" alt="image-20241023144235152"></p><p>点击<code>频道入口</code>或者<code>群组入口</code>加入交流群</p><p><img src="/../../img/EmbyBot%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20241023144403473.png" alt="image-20241023144403473"></p><p>此时机器人的聊天框就变成可输入的,输入<code>/start</code>开始使用</p><p><img src="/../../img/EmbyBot%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20241023144922732.png" alt="image-20241023144922732"></p><h3 id="2-使用指南"><a href="#2-使用指南" class="headerlink" title="2. 使用指南"></a>2. 使用指南</h3><h4 id="2-1-账号注册"><a href="#2-1-账号注册" class="headerlink" title="2.1 账号注册"></a>2.1 账号注册</h4><p><img src="/../../img/EmbyBot%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20241023150529986.png" alt="image-20241023150529986"></p><p>媒体库仅为内部交流使用,暂时不开放注册,内测时使用注册码注册,请联系群主获取注册码,然后点击使用注册码。</p><p><img src="/../../img/EmbyBot%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20241023151519425.png" alt="image-20241023151519425"></p><p>输入 test 123456 也就是说明你的媒体库登录账号为 test,这里的安全码并非媒体库密码,而是你账号绑定后的操作密码,用于进行高危操作时验证身份</p><p><img src="/../../img/EmbyBot%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20241023152007869.png" alt="image-20241023152007869"></p><div class="tag-plugin colorful note" ><div class="title">提示</div><div class="body"><p>注册成功会显示账号密码等信息,请记住安全码!</p></div></div><p>可以在<code>用户功能-重置密码</code>中修改媒体库账号的密码</p><p><img src="/../../img/EmbyBot%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20241023152526718.png" alt="image-20241023152526718"></p><h4 id="2-2-求片中心"><a href="#2-2-求片中心" class="headerlink" title="2.2 求片中心"></a>2.2 求片中心</h4><div class="tag-plugin colorful note" ><div class="title">求片提示</div><div class="body"><p>目前还没有做到全自动化求片,下载完成群主会收到消息然后手动入库。等 115 网盘做活动的时候就能搞全自动入库了</p></div></div><p><img src="/../../img/EmbyBot%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20241023152836478.png" alt="image-20241023152836478"></p><p>点击求片,输入想要看的片名就可以自动下载了。根据描述输入你想看的资源,回复编号开始下载。</p><p><img src="/../../img/EmbyBot%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20241023153548165.png" alt="image-20241023153548165"></p><p>此时如果显示添加下载队列成功,表明已经开始下载。</p><p><img src="/../../img/EmbyBot%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20241023153644678.png" alt="image-20241023153644678"></p><p>点击<code>查看下载进度</code>即可查看求片进度。</p><p><img src="/../../img/EmbyBot%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20241023153733175.png" alt="image-20241023153733175"></p><h4 id="2-3-媒体库搜索"><a href="#2-3-媒体库搜索" class="headerlink" title="2.3 媒体库搜索"></a>2.3 媒体库搜索</h4><p>在媒体库交流群组中@机器人即可唤出搜索面板。</p><p><img src="/../../img/EmbyBot%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20241023153843874.png" alt="image-20241023153843874"></p><p><img src="/../../img/EmbyBot%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20241023153909627.png" alt="image-20241023153909627"></p><p>点击收藏即可将该资源加入媒体库账号的收藏夹。</p><p><img src="/../../img/EmbyBot%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20241023154007321.png" alt="image-20241023154007321"></p><h3 id="3-连接媒体库"><a href="#3-连接媒体库" class="headerlink" title="3. 连接媒体库"></a>3. 连接媒体库</h3><p>详细介绍请看我另一篇文章</p><div class="tag-plugin link dis-select"><a class="link-card rich" title="媒体库使用指南" href="https://blog.sakurasep.site/posts/How-To-Use-MediaServer/" target="_blank" rel="external nofollow noopener noreferrer" cardlink api="https://site-info-api-git-main-sakurasep.vercel.app/api/v1?url=https://blog.sakurasep.site/posts/How-To-Use-MediaServer/" autofill="icon,desc"><div class="top"><div class="lazy img" data-bg="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/link/8f277b4ee0ecd.svg"></div><span class="cap link footnote">https://blog.sakurasep.site/posts/How-To-Use-MediaServer/</span></div><div class="bottom"><span class="title">媒体库使用指南</span><span class="cap desc footnote"></span></div></a></div><div class="tag-plugin link dis-select"><a class="link-card rich" title="安卓平台推荐使用 Yamby 密码:1023" href="https://cloud.sakurasep.top/s/rJhv" target="_blank" rel="external nofollow noopener noreferrer" cardlink api="https://site-info-api-git-main-sakurasep.vercel.app/api/v1?url=https://cloud.sakurasep.top/s/rJhv" autofill="icon,desc"><div class="top"><div class="lazy img" data-bg="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/link/8f277b4ee0ecd.svg"></div><span class="cap link footnote">https://cloud.sakurasep.top/s/rJhv</span></div><div class="bottom"><span class="title">安卓平台推荐使用 Yamby 密码:1023</span><span class="cap desc footnote"></span></div></a></div><div class="tag-plugin link dis-select"><a class="link-card rich" title="Windows 平台推荐 Emby for Windows 密码:1023" href="https://cloud.sakurasep.top/s/Pvu4" target="_blank" rel="external nofollow noopener noreferrer" cardlink api="https://site-info-api-git-main-sakurasep.vercel.app/api/v1?url=https://cloud.sakurasep.top/s/Pvu4" autofill="icon,desc"><div class="top"><div class="lazy img" data-bg="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/link/8f277b4ee0ecd.svg"></div><span class="cap link footnote">https://cloud.sakurasep.top/s/Pvu4</span></div><div class="bottom"><span class="title">Windows 平台推荐 Emby for Windows 密码:1023</span><span class="cap desc footnote"></span></div></a></div><p>iOS 平台推荐使用 Vidhub,Infuse</p><p>macOS 平台推荐使用 Vidhub,Infuse,Fileball</p><p><img src="/../../img/EmbyBot%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20241023155043174.png" alt="image-20241023155043174"></p><p><img src="/../../img/EmbyBot%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20241023154958040.png" alt="image-20241023154958040"></p><p><img src="/../../img/EmbyBot%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20241023155450159.png" alt="image-20241023155450159"></p><hr><p><img src="/../../assets/user/about_me.jpg" alt="关于我"> </p>]]></content>
<summary type="html">简易的EmbyBot使用指南,附带各平台播放器推荐应用</summary>
<category term="媒体库" scheme="https://blog.sakurasep.site/categories/%E5%AA%92%E4%BD%93%E5%BA%93/"/>
<category term="Emby" scheme="https://blog.sakurasep.site/tags/Emby/"/>
<category term="动漫" scheme="https://blog.sakurasep.site/tags/%E5%8A%A8%E6%BC%AB/"/>
<category term="TGBot" scheme="https://blog.sakurasep.site/tags/TGBot/"/>
</entry>
<entry>
<title>动漫年鉴 - BDRip</title>
<link href="https://blog.sakurasep.site/posts/anime-collect-bdrip/"/>
<id>https://blog.sakurasep.site/posts/anime-collect-bdrip/</id>
<published>2024-10-05T05:30:24.000Z</published>
<updated>2024-10-05T05:30:24.000Z</updated>
<content type="html"><![CDATA[<p>对于入坑作是 Re0 时代的二次元,很多老番只是听过它们的大名,但是却一直没机会去观看,正巧最近整理媒体库,打算根据泛式的新番时光机来补番。同时,我的朋友与同学也提供了不少有趣的动漫,这些内容将分为不同板块存在 Onedrive 中,后续有资金后会购入硬盘存在本地。</p><div class="tag-plugin colorful note" ><div class="title">Tips:</div><div class="body"><p>资源来自 U2 等 PT 站点,故不开放注册,本媒体库仅用于朋友同学之间交流使用</p></div></div><h2 id="新番时光机-泛式"><a href="#新番时光机-泛式" class="headerlink" title="新番时光机 - 泛式"></a>新番时光机 - 泛式</h2><h3 id="2010-年-10-月新番"><a href="#2010-年-10-月新番" class="headerlink" title="2010 年 10 月新番"></a>2010 年 10 月新番</h3><div class="tag-plugin posters-wrap"><div class="tag-plugin gallery grid-box" layout="grid" ratio="portrait" size="m"><div class="grid-cell poster-card"><a class="card-link" target="_blank" rel="external nofollow noopener noreferrer" href="https://bgm.tv/subject/7157"><img src="https://lain.bgm.tv/pic/cover/l/6e/01/7157_QV8Rz.jpg" onerror="javascript:this.removeAttribute("data-src");this.src="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/cover/76b86c0226ffd.svg";"/><div class="image-meta"><span class="image-caption">缘之空</span></div></a></div><div class="grid-cell poster-card"><a class="card-link" target="_blank" rel="external nofollow noopener noreferrer" href="https://bgm.tv/subject/3428"><img src="https://lain.bgm.tv/r/400/pic/cover/l/45/00/3428_NPdDd.jpg" onerror="javascript:this.removeAttribute("data-src");this.src="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/cover/76b86c0226ffd.svg";"/><div class="image-meta"><span class="image-caption">爆漫王 S01</span></div></a></div><div class="grid-cell poster-card"><a class="card-link" target="_blank" rel="external nofollow noopener noreferrer" href="https://bgm.tv/subject/22588"><img src="https://lain.bgm.tv/r/400/pic/cover/l/45/8c/22588_xECYm.jpg" onerror="javascript:this.removeAttribute("data-src");this.src="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/cover/76b86c0226ffd.svg";"/><div class="image-meta"><span class="image-caption">爆漫王 S02</span></div></a></div><div class="grid-cell poster-card"><a class="card-link" target="_blank" rel="external nofollow noopener noreferrer" href="https://bgm.tv/subject/33352"><img src="https://lain.bgm.tv/r/400/pic/cover/l/eb/09/33352_J6F40.jpg" onerror="javascript:this.removeAttribute("data-src");this.src="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/cover/76b86c0226ffd.svg";"/><div class="image-meta"><span class="image-caption">爆漫王 S03</span></div></a></div></div></div><h3 id="2011-年-1-月新番"><a href="#2011-年-1-月新番" class="headerlink" title="2011 年 1 月新番"></a>2011 年 1 月新番</h3><div class="tag-plugin posters-wrap"><div class="tag-plugin gallery grid-box" layout="grid" ratio="portrait" size="m"><div class="grid-cell poster-card"><a class="card-link" target="_blank" rel="external nofollow noopener noreferrer" href="https://bgm.tv/subject/9800"><img src="https://lain.bgm.tv/r/400/pic/cover/l/0f/bc/9800_eIkZW.jpg" onerror="javascript:this.removeAttribute("data-src");this.src="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/cover/76b86c0226ffd.svg";"/><div class="image-meta"><span class="image-caption">无限斯特拉托斯</span></div></a></div></div></div><h2 id="动漫年鉴-Notion"><a href="#动漫年鉴-Notion" class="headerlink" title="动漫年鉴 - Notion"></a>动漫年鉴 - Notion</h2><p><a href="https://fire-mackerel-e3f.notion.site/12b88f3698208017a67dd7e5abb9d85d?v=12b88f369820810485c6000c7d457d94&pvs=4">Notion 笔记</a></p><p>此 Notion 笔记模板是由哔哩哔哩up主 <a href="https://space.bilibili.com/172085">Azuki咔咔</a> 所制作。</p><p>总表是使用的年份进行记录</p><p><img src="/../../img/%E6%96%B0%E7%95%AA%E6%97%B6%E5%85%89%E6%9C%BA/image-20241104195336682.png" alt="image-20241104195336682"></p><p>表格记录了已经收录的动漫,可以查看压制组等具体的内容</p><p><img src="/../../img/%E6%96%B0%E7%95%AA%E6%97%B6%E5%85%89%E6%9C%BA/image-20241104195527316.png" alt="image-20241104195527316"></p><hr><p><img src="/../../assets/user/about_me.jpg" alt="关于我"></p>]]></content>
<summary type="html">媒体库动漫入库通知</summary>
<category term="媒体库" scheme="https://blog.sakurasep.site/categories/%E5%AA%92%E4%BD%93%E5%BA%93/"/>
<category term="Emby" scheme="https://blog.sakurasep.site/tags/Emby/"/>
<category term="动漫" scheme="https://blog.sakurasep.site/tags/%E5%8A%A8%E6%BC%AB/"/>
<category term="BDRip" scheme="https://blog.sakurasep.site/tags/BDRip/"/>
</entry>
<entry>
<title>Unraid中如何使得容器获取IPV6地址</title>
<link href="https://blog.sakurasep.site/posts/Unraid-IPV6/"/>
<id>https://blog.sakurasep.site/posts/Unraid-IPV6/</id>
<published>2024-07-20T11:30:06.000Z</published>
<updated>2024-07-20T11:30:06.000Z</updated>
<content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>对于我们现在很多地区的运营商来说,公网 IPV4 是极其难去申请的,就算可以申请到,也会让你加不少钱改套餐,对于普通用户来说有些划不来。IPV6 是连通公网的一个不错的方法,只需要给当地运营商的运维打个电话,把光猫拨号改为桥接,再从路由器中拨号并打开 IPV6 功能,此时便可以轻松将你的设备开放给公网。</p><p>对于开放在公网的设备来说,IPV6 的复杂程度以及动态变更的特点,让公网的设备面对暴露的风险时还是有一定的防御能力,但是我仍然不推荐将所有端口都开放到公网,以免出现安全问题。</p><h2 id="一、路由器的设置"><a href="#一、路由器的设置" class="headerlink" title="一、路由器的设置"></a>一、路由器的设置</h2><p>不同的路由器的设置内容略有不同,这里我是 TP-LINK 的主路由,所以暂时先给出该型号路由器配置的详细图文教程。</p><p>只要记住一点,Unraid 目前可以通过 DHCPv6 或者 SLAAC 获取到 IPV6 地址,但是 Unraid 的 Docker 服务并不可以直接使用 DHCPv6 所分配的 IPV6 地址,而且 Android 设备貌似也不能使用 DHCPv6,所以最好还是使用 SLAAC 进行分配。</p><h3 id="TP-LINK-路由器"><a href="#TP-LINK-路由器" class="headerlink" title="TP-LINK 路由器"></a>TP-LINK 路由器</h3><h4 id="1-1-关闭-IPV6-桥接模式"><a href="#1-1-关闭-IPV6-桥接模式" class="headerlink" title="1.1 关闭 IPV6 桥接模式"></a>1.1 关闭 IPV6 桥接模式</h4><p>首先需要关闭 IPV6 桥接模式,如果你的 TP-LINK 路由器为二级路由,那就开启桥接模式。</p><p><img src="/../../img/Unraid%E4%B8%AD%E5%A6%82%E4%BD%95%E4%BD%BF%E5%BE%97%E5%AE%B9%E5%99%A8%E8%8E%B7%E5%8F%96IPV6%E5%9C%B0%E5%9D%80/image-20240720223803951.png" alt="image-20240720223803951"></p><h4 id="1-2-路由拨号与获取前缀授权"><a href="#1-2-路由拨号与获取前缀授权" class="headerlink" title="1.2 路由拨号与获取前缀授权"></a>1.2 路由拨号与获取前缀授权</h4><p>在确定光猫端设置为桥接之后,在路由器进行拨号。</p><p><img src="/../../img/Unraid%E4%B8%AD%E5%A6%82%E4%BD%95%E4%BD%BF%E5%BE%97%E5%AE%B9%E5%99%A8%E8%8E%B7%E5%8F%96IPV6%E5%9C%B0%E5%9D%80/image-20240720224118351.png" alt="image-20240720224118351"></p><p>这里复用 IPV4 的拨号链路,因为如果这里仍然拨号就会产生冲突。</p><div class="tag-plugin colorful note" ><div class="title">前缀授权</div><div class="body"><p>前缀授权也就是本地路由向 ISP 运营商的 DHCP 获取一个 IPV6 地址的前缀,然后本地就可以继续根据这一个 IPV6 地址继续分配给其他设备或创建子网</p></div></div><p><img src="/../../img/Unraid%E4%B8%AD%E5%A6%82%E4%BD%95%E4%BD%BF%E5%BE%97%E5%AE%B9%E5%99%A8%E8%8E%B7%E5%8F%96IPV6%E5%9C%B0%E5%9D%80/image-20240720224609803.png" alt="image-20240720224609803"></p><h4 id="1-3-设置-SLAAC-分配-IPV6-地址给其他设备"><a href="#1-3-设置-SLAAC-分配-IPV6-地址给其他设备" class="headerlink" title="1.3 设置 SLAAC 分配 IPV6 地址给其他设备"></a>1.3 设置 SLAAC 分配 IPV6 地址给其他设备</h4><p>设置一下 LAN 口相关设置,首先选择 WAN 口的前缀授权接口,下一步选择 SLAAC 对其他设备授权 IPV6 地址。</p><p><img src="/../../img/Unraid%E4%B8%AD%E5%A6%82%E4%BD%95%E4%BD%BF%E5%BE%97%E5%AE%B9%E5%99%A8%E8%8E%B7%E5%8F%96IPV6%E5%9C%B0%E5%9D%80/image-20240720230312790.png" alt="image-20240720230312790"></p><p><img src="/../../img/Unraid%E4%B8%AD%E5%A6%82%E4%BD%95%E4%BD%BF%E5%BE%97%E5%AE%B9%E5%99%A8%E8%8E%B7%E5%8F%96IPV6%E5%9C%B0%E5%9D%80/image-20240720230455698.png" alt="image-20240720230455698"></p><h2 id="二、Unraid-的设置"><a href="#二、Unraid-的设置" class="headerlink" title="二、Unraid 的设置"></a>二、Unraid 的设置</h2><p>我这里使用的是 Unraid 6.11.5,Unraid 不同版本在某些设置可能存在差异,如有问题请在评论区提出。</p><h3 id="Unraid-网络设置"><a href="#Unraid-网络设置" class="headerlink" title="Unraid 网络设置"></a>Unraid 网络设置</h3><p>在修改网络设置前,需要关闭 Docker 服务以及虚拟机服务。</p><p><img src="/../../img/Unraid%E4%B8%AD%E5%A6%82%E4%BD%95%E4%BD%BF%E5%BE%97%E5%AE%B9%E5%99%A8%E8%8E%B7%E5%8F%96IPV6%E5%9C%B0%E5%9D%80/image-20240720231533035.png" alt="image-20240720231533035"></p><p><img src="/../../img/Unraid%E4%B8%AD%E5%A6%82%E4%BD%95%E4%BD%BF%E5%BE%97%E5%AE%B9%E5%99%A8%E8%8E%B7%E5%8F%96IPV6%E5%9C%B0%E5%9D%80/image-20240720232033230.png" alt="image-20240720232033230"></p><h3 id="设置-Docker-应用的网络类型"><a href="#设置-Docker-应用的网络类型" class="headerlink" title="设置 Docker 应用的网络类型"></a>设置 Docker 应用的网络类型</h3><p>Unraid 提供的 Docker 网络模式主要有以下几种:</p><ol><li><p><strong>bridge</strong>:</p><ul><li>默认的网络模式。容器连接到一个虚拟的桥接网络,可以通过桥接网络相互通信。</li><li>容器通过NAT共享主机的IP地址。</li></ul></li><li><p><strong>host</strong>:</p><ul><li>容器与主机共享网络命名空间,使用主机的IP地址和端口。</li><li>容器的端口直接暴露在主机上,没有NAT。</li></ul></li><li><p><strong>none</strong>:</p><ul><li>容器没有网络连接,仅有回环接口(lo)。</li><li>适用于不需要网络的应用或自定义网络配置。</li></ul></li><li><p><strong>custom</strong>:</p><ul><li>自定义网络模式,允许用户创建和配置自己的桥接或macvlan网络。</li><li>可以通过Unraid的网络设置界面进行配置,适用于需要特定网络设置的应用。</li></ul></li></ol><h5 id="custom-模式(推荐)"><a href="#custom-模式(推荐)" class="headerlink" title="custom 模式(推荐)"></a>custom 模式(推荐)</h5><p><img src="/../../img/Unraid%E4%B8%AD%E5%A6%82%E4%BD%95%E4%BD%BF%E5%BE%97%E5%AE%B9%E5%99%A8%E8%8E%B7%E5%8F%96IPV6%E5%9C%B0%E5%9D%80/image-20240720233020909.png" alt="image-20240720233020909"></p><p>等待容器启动完成,我们打开控制台,输入命令<code>ifconfig</code>查看容器是否成功获取了 IPV6 地址。如下图所示,eth0 网卡已经成功获取了公网 IPV6 地址。</p><p><img src="/../../img/Unraid%E4%B8%AD%E5%A6%82%E4%BD%95%E4%BD%BF%E5%BE%97%E5%AE%B9%E5%99%A8%E8%8E%B7%E5%8F%96IPV6%E5%9C%B0%E5%9D%80/image-20240720233403634.png" alt="image-20240720233403634"></p><h5 id="host-模式"><a href="#host-模式" class="headerlink" title="host 模式"></a>host 模式</h5><p><img src="/../../img/Unraid%E4%B8%AD%E5%A6%82%E4%BD%95%E4%BD%BF%E5%BE%97%E5%AE%B9%E5%99%A8%E8%8E%B7%E5%8F%96IPV6%E5%9C%B0%E5%9D%80/image-20240720234749101.png" alt="image-20240720234749101"></p><p>我这里因为 AutoBangumi 没法连接 custom 模式下的 qBittorrent,所以只能使用 host 模式,一般来说不建议使用 host 模式直接暴露 Unraid 的 IPV6 地址,毕竟在 qBittorrent 中是可以直接看到 IPV6 地址的。</p><p>等待容器启动完成,我们打开控制台,输入命令<code>ifconfig</code>查看容器是否成功获取了 IPV6 地址。如下图所示,br0 网卡已经成功获取了公网 IPV6 地址。</p><p><img src="/../../img/Unraid%E4%B8%AD%E5%A6%82%E4%BD%95%E4%BD%BF%E5%BE%97%E5%AE%B9%E5%99%A8%E8%8E%B7%E5%8F%96IPV6%E5%9C%B0%E5%9D%80/image-20240720235207300.png" alt="image-20240720235207300"></p><h3 id="应用的具体设置"><a href="#应用的具体设置" class="headerlink" title="应用的具体设置"></a>应用的具体设置</h3><h4 id="qBittorrent"><a href="#qBittorrent" class="headerlink" title="qBittorrent"></a>qBittorrent</h4><p>在 qBittorrent 的<code>设置-高级</code>中修改网络接口为控制台中查询到的 Unraid 的网卡。具体的网络接口可以从 Unraid 的<code>网络设置-路由表</code>中看到。</p><p>此外,qBittorrent 绑定到的 IP 地址选择所有地址,只要你的 NAT 类型不是太差,IPV4 还是可以连接到的,只是上传的连通性会变得很差。</p><p><img src="/../../img/Unraid%E4%B8%AD%E5%A6%82%E4%BD%95%E4%BD%BF%E5%BE%97%E5%AE%B9%E5%99%A8%E8%8E%B7%E5%8F%96IPV6%E5%9C%B0%E5%9D%80/image-20240720235539667.png" alt="image-20240720235539667"></p><p><img src="/../../img/Unraid%E4%B8%AD%E5%A6%82%E4%BD%95%E4%BD%BF%E5%BE%97%E5%AE%B9%E5%99%A8%E8%8E%B7%E5%8F%96IPV6%E5%9C%B0%E5%9D%80/image-20240720235340256.png" alt="image-20240720235340256"></p><h2 id="后记"><a href="#后记" class="headerlink" title="后记"></a>后记</h2><p>目前我个人不太经常使用 IPV6,毕竟在外面的话,除了流量是 IPV6,其他地方的网络很多是没有开启 IPV6 的,所以在外面访问家里的服务我使用的是 Tailscale,感觉还是挺不错的,基本能跑满。</p><p>这篇文章算是我自己使用 Unraid 中遇到的问题,然后随手写的解决方案,后续也会继续写一些有趣的文章。</p><hr><p><img src="/../../assets/user/about_me.jpg" alt="关于我"></p>]]></content>
<summary type="html">对于Unraid中很多需要与公网连通的容器来说,获取IPV6地址变的十分重要,对于家用路由器的 IPV6分配方式,Unraid也有着不同的需求。</summary>
<category term="Unraid" scheme="https://blog.sakurasep.site/categories/Unraid/"/>
<category term="Unraid" scheme="https://blog.sakurasep.site/tags/Unraid/"/>
</entry>
<entry>
<title>云服务器的简单使用指南</title>
<link href="https://blog.sakurasep.site/posts/ZeroLinux/"/>
<id>https://blog.sakurasep.site/posts/ZeroLinux/</id>
<published>2024-07-19T03:19:51.000Z</published>
<updated>2024-08-23T00:10:34.000Z</updated>
<content type="html"><![CDATA[<h2 id="一、选购服务器"><a href="#一、选购服务器" class="headerlink" title="一、选购服务器"></a>一、选购服务器</h2><p>关于在本地使用虚拟机创建Linux服务器和使用云服务器,两者的区别在于你的应用方向。本地的服务器通常有着较高的性能,可以挂载更多的服务,承接更高的性能需求。对于云服务器,更多的价值在于公网 IP,对于我们个人来说,面向互联网的服务多数资源消耗较少,因此花钱买到公网 IP 更符合我对个人使用云服务器的看法。</p><p>国内有不少的云服务厂商,他们的价格和服务器配置差距挺大,作为一个初次使用云服务的用户,很多厂商都可以白嫖到试用机会。建议在确定好要购买长期使用之前,先试用一下,感受一下网页控制台是否足够方便,是否符合自己的使用习惯。</p><p>当你选定一家云服务商后,这里建议域名注册,备案等等服务也都在同一家云服务商进行购买。例如我个人的服务器,CDN,对象存储服务都是使用的腾讯云,这样使用起来更方便,不用切换其他云服务的控制台。</p><p>最后注意一下,一定要关注各家云服务厂商的优惠活动,建议首选知名的云服务商,以便保证后续服务。</p><p>以下是我的服务器运行情况</p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240823131805706.png" alt="image-20240823131805706"></p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240823131852562.png" alt="image-20240823131852562"></p><h2 id="二、安装基本环境"><a href="#二、安装基本环境" class="headerlink" title="二、安装基本环境"></a>二、安装基本环境</h2><p>整篇文章都将使用华为云的 2H2G 服务器进行测试演示,一年只需要 36 元,感觉十分合适,如果活动还在是很推荐入手的。</p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240823133032756.png" alt="image-20240823133032756"></p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240823133104941.png" alt="image-20240823133104941"></p><h3 id="1-安装-SSH-工具"><a href="#1-安装-SSH-工具" class="headerlink" title="1. 安装 SSH 工具"></a>1. 安装 SSH 工具</h3><p>SSH 工具有很多,这里我在 macOS 上经常使用的是FinalShell,个人感觉还是很方便的,界面也很清晰。</p><div class="tag-plugin link dis-select"><a class="link-card rich" title="FinalShell SSH工具" href="https://www.hostbuf.com/t/988.html" target="_blank" rel="external nofollow noopener noreferrer" cardlink api="https://site-info-api-git-main-sakurasep.vercel.app/api/v1?url=https://www.hostbuf.com/t/988.html" autofill="icon,desc"><div class="top"><div class="lazy img" data-bg="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/link/8f277b4ee0ecd.svg"></div><span class="cap link footnote">https://www.hostbuf.com/t/988.html</span></div><div class="bottom"><span class="title">FinalShell SSH工具</span><span class="cap desc footnote"></span></div></a></div><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240823132517010.png" alt="image-20240823132517010"></p><p>当然在 windows 端我更推荐使用MobaXterm,GitHub 上有位大佬精心做了汉化。</p><div class="tag-plugin link dis-select"><a class="link-card rich" title="FinalShell SSH工具" href="https://github.com/RipplePiam/MobaXterm-Chinese-Simplified" target="_blank" rel="external nofollow noopener noreferrer" cardlink api="https://site-info-api-git-main-sakurasep.vercel.app/api/v1?url=https://github.com/RipplePiam/MobaXterm-Chinese-Simplified" autofill="icon,desc"><div class="top"><div class="lazy img" data-bg="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/link/8f277b4ee0ecd.svg"></div><span class="cap link footnote">https://github.com/RipplePiam/MobaXterm-Chinese-Simplified</span></div><div class="bottom"><span class="title">FinalShell SSH工具</span><span class="cap desc footnote"></span></div></a></div><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240823132827441.png" alt="image-20240823132827441"></p><h2 id="三、服务器基本配置"><a href="#三、服务器基本配置" class="headerlink" title="三、服务器基本配置"></a>三、服务器基本配置</h2><h3 id="1-镜像选择与重置密码"><a href="#1-镜像选择与重置密码" class="headerlink" title="1. 镜像选择与重置密码"></a>1. 镜像选择与重置密码</h3><p>镜像的选择其实差别并不是很大,Ubuntu 和 Debian 二选一就可以了。</p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240823133449356.png" alt="image-20240823133449356"></p><p>建议在装完系统后手动重置一下密码,并牢记此密码。</p><h3 id="2-配置SSH工具"><a href="#2-配置SSH工具" class="headerlink" title="2. 配置SSH工具"></a>2. 配置SSH工具</h3><p>在 Finalshell 中配置 SSH 连接,在主机处填入云服务器的公网 IP,用户名默认为 root。</p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240823135404142.png" alt="image-20240823135404142"></p><p>连接成功如下所示,可以看到 Finalshell 能够显示服务器基本的负载信息,并且可以在软件底部实现上传操作。</p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240823135554361.png" alt="image-20240823135554361"></p><h2 id="四、-安装面板"><a href="#四、-安装面板" class="headerlink" title="四、 安装面板"></a>四、 安装面板</h2><h3 id="4-1-常见面板介绍"><a href="#4-1-常见面板介绍" class="headerlink" title="4.1 常见面板介绍"></a>4.1 常见面板介绍</h3><p>相比于使用终端进行操作,对于小白来说,使用面板更加方便。</p><p>目前有两个比较流行的面板,宝塔和 1Panel,宝塔稳定性更强,但是界面含有不少的付费要素,且必须绑定宝塔账号。1Panel的界面干净整洁,在去年的使用中出现了几个小 bug,稳定性相较于宝塔逊色一点。本篇文章将会使用 1Panel 进行演示。</p><div class="tag-plugin colorful note" ><div class="body"><p>宝塔面板</p></div></div><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/bt_video.gif" alt="img"></p><div class="tag-plugin colorful note" ><div class="body"><p>1Panel</p></div></div><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240823140227086.png" alt="image-20240823140227086"></p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240823141957121.png" alt="image-20240823141957121"></p><p>在宝塔和 1Panel 之外还有一些其他的面板,朋友们也可以尝试一下。</p><div class="tag-plugin colorful note" ><div class="body"><p>耗子面板</p></div></div><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240823215318516.png" alt="image-20240823215318516"></p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/ui.png" alt="UI 截图"></p><h3 id="4-2-一键安装面板"><a href="#4-2-一键安装面板" class="headerlink" title="4.2 一键安装面板"></a>4.2 一键安装面板</h3><p>在终端输入以下命令安装 1Panel 面板。</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">curl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o quick_start.sh && sudo bash quick_start.sh</span><br></pre></td></tr></table></figure><p>设置面板的安装目录,这里保持默认即可。</p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240823140752948.png" alt="image-20240823140752948"></p><p>由于国内连接 Docker 服务不够稳定,后续在线安装 Docker 服务可能会出现错误提示,请不要在意,整体的下载速度较慢。</p><p>Docker 安装完成后,安装程序会让你选择访问面板的端口,这里建议更换默认端口为一个你容易记住的端口。</p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240823141052909.png" alt="image-20240823141052909"></p><p>设置完成端口后,需要设置一个安全入口,同样设置一个你能够记住的字符串。</p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240823141211825.png" alt="image-20240823141211825"></p><p>后续需要配置面板管理的用户名和密码,请尽量保证密码的复杂,不要使用简单密码。</p><p>当安装程序结束后,你将可以看到外网访问地址,此时请在云服务商的安全组策略中放行刚刚设置的面板端口。这里以华为云为例,在策略组的入方向规则中放行端口。</p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240823141803564.png" alt="image-20240823141803564"></p><p>此时访问<code>http://ip地址:端口/安全入口字符串</code>就可以进入面板。</p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240823141920724.png" alt="image-20240823141920724"></p><h2 id="五、-Docker-相关配置"><a href="#五、-Docker-相关配置" class="headerlink" title="五、 Docker 相关配置"></a>五、 Docker 相关配置</h2><h3 id="5-1-Docker-镜像加速配置"><a href="#5-1-Docker-镜像加速配置" class="headerlink" title="5.1 Docker 镜像加速配置"></a>5.1 Docker 镜像加速配置</h3><p>目前国内不少 Docker 的镜像站都不再提供服务,这里我提供一些正常运营的 Docker 镜像站。</p><h4 id="5-1-1-使用终端设置镜像源"><a href="#5-1-1-使用终端设置镜像源" class="headerlink" title="5.1.1 使用终端设置镜像源"></a>5.1.1 使用终端设置镜像源</h4><p>在终端使用命令行,设置镜像源。</p><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">sudo tee /etc/docker/daemon.json <<EOF</span><br><span class="line">{</span><br><span class="line"> "registry-mirrors": ["加速镜像1"]</span><br><span class="line">}</span><br><span class="line">EOF</span><br><span class="line"></span><br><span class="line">sudo systemctl daemon-reload</span><br><span class="line">sudo systemctl restart docker</span><br></pre></td></tr></table></figure><h4 id="5-1-2-在面板中修改镜像源"><a href="#5-1-2-在面板中修改镜像源" class="headerlink" title="5.1.2 在面板中修改镜像源"></a>5.1.2 在面板中修改镜像源</h4><p>在 1Panel 面板的<code>容器 - 配置</code>中添加镜像加速地址。</p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240823223541183.png" alt="image-20240823223541183"></p><div class="tag-plugin colorful note" ><div class="body"><p>可以直接使用的镜像站</p></div></div><p>以下是可以直接使用的镜像源,如果其中有源失效,请及时告知博主。</p><p>如果你有比较可靠的镜像源,也请在评论区留言,感谢!</p><figure class="highlight markdown"><table><tr><td class="code"><pre><span class="line"><span class="section">## 1Panel</span></span><br><span class="line">https://docker.1panel.live</span><br><span class="line"><span class="section">## DaoCloud/public-image-mirror</span></span><br><span class="line">https://docker.m.daocloud.io</span><br><span class="line"><span class="section">## 耗子面板公益加速</span></span><br><span class="line">https://hub.rat.dev/</span><br><span class="line"><span class="section">## dockerhub.icu</span></span><br><span class="line">https://dockerhub.icu</span><br><span class="line"><span class="section">## docker.awsl9527.cn</span></span><br><span class="line">https://docker.awsl9527.cn</span><br><span class="line"><span class="section">## AtomHub</span></span><br><span class="line">https://atomhub.openatom.cn</span><br></pre></td></tr></table></figure><div class="tag-plugin colorful note" ><div class="body"><p>需要特定条件才能使用的镜像站</p></div></div><p>仅支持阿里云相关云产品使用,每一个账号有独立的镜像地址,如果购买的云服务商为阿里云,那就可以使用阿里云提供的 Docker 镜像加速。</p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240823155437975.png" alt="image-20240823155437975"></p><div class="tag-plugin link dis-select"><a class="link-card rich" title="容器镜像服务" href="https://cr.console.aliyun.com/cn-hangzhou/instances" target="_blank" rel="external nofollow noopener noreferrer" cardlink api="https://site-info-api-git-main-sakurasep.vercel.app/api/v1?url=https://cr.console.aliyun.com/cn-hangzhou/instances" autofill="icon,desc"><div class="top"><div class="lazy img" data-bg="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/link/8f277b4ee0ecd.svg"></div><span class="cap link footnote">https://cr.console.aliyun.com/cn-hangzhou/instances</span></div><div class="bottom"><span class="title">容器镜像服务</span><span class="cap desc footnote"></span></div></a></div><h4 id="5-1-3-测试拉取镜像"><a href="#5-1-3-测试拉取镜像" class="headerlink" title="5.1.3 测试拉取镜像"></a>5.1.3 测试拉取镜像</h4><p>在<code>容器 - 镜像 - 拉取镜像</code>中测试拉取<code>linuxserver/qbittorrent</code>镜像。</p><p>由于镜像站不会镜像 DockerHub 全部的镜像,有些冷门镜像无法拉取很正常。</p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240823224808190.png" alt="image-20240823224808190"></p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240823224823649.png" alt="image-20240823224823649"></p><h2 id="六、ShellClash-代理配置"><a href="#六、ShellClash-代理配置" class="headerlink" title="六、ShellClash 代理配置"></a>六、ShellClash 代理配置</h2><p>由于例如 GitHub,DockerHub 等服务在国内的服务器上难以访问,还是建议各位在服务器上安装一个简易的 Clash,方便克隆 Github 仓库以及拉取 Docker 镜像。</p><h3 id="6-1-安装-ShellClash"><a href="#6-1-安装-ShellClash" class="headerlink" title="6.1 安装 ShellClash"></a>6.1 安装 ShellClash</h3><p>在终端执行以下命令</p><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">export url='https://fastly.jsdelivr.net/gh/juewuy/ShellCrash@master' && wget -q --no-check-certificate -O /tmp/install.sh $url/install.sh && bash /tmp/install.sh && source /etc/profile &> /dev/null</span><br></pre></td></tr></table></figure><p>选择公测版 - 在/usr/share目录安装 - 确定,一键安装 ShellClash</p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240824000835902.png" alt="image-20240824000835902"></p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240824002820883.png" alt="image-20240824002820883"></p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240823230402111.png" alt="image-20240823230402111"></p><h3 id="6-2-配置-ShellClash"><a href="#6-2-配置-ShellClash" class="headerlink" title="6.2 配置 ShellClash"></a>6.2 配置 ShellClash</h3><p>在终端输入 clash 进入管理界面,首先选择Linux设备代理本机流量</p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240824101921256.png" alt="image-20240824101921256"></p><p>然后开启公网访问dashboard面板,以便管理 clash 的配置文件</p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240823230707027.png" alt="image-20240823230707027"></p><p>设置面板访问密钥,并开启自动任务</p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240823230856726.png" alt="image-20240823230856726"></p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240823230834577.png" alt="image-20240823230834577"></p><p>选择在线生成配置文件,并在之后的提示中导入订阅链接。</p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240823231102732.png" alt="image-20240823231102732"></p><p>此时就可以愉快的访问 Github 与 Docker Hub了。</p><p>为了方便管理,这里建议安装 dashboard 面板</p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240824003331811.png" alt="image-20240824003331811"></p><p>此时在安全组放行 9999 端口,即可访问后台管理面板<code>公网IP:9999/ui</code></p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240824003740843.png" alt="image-20240824003740843"></p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240824003730792.png" alt="image-20240824003730792"></p><h4 id="6-3-测试以及注意事项"><a href="#6-3-测试以及注意事项" class="headerlink" title="6.3 测试以及注意事项"></a>6.3 测试以及注意事项</h4><p>可以看到,当你配置镜像加速的时候,如果可以从镜像站拉取到镜像,会优先从镜像站下载。</p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240824103208297.png" alt="image-20240824103208297"></p><p>如果到了实在没有镜像站可用的时候,或者镜像站并没有对应的镜像,便可以通过代理下载。</p><p><img src="/../../img/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240824104314126.png" alt="image-20240824104314126"></p><p>注意,当不需要使用代理的时候,请及时关闭代理,同时建议关闭 shellclash 的开机自启,以免影响服务器其他服务正常的运行。</p><hr><p><img src="/../../assets/user/about_me.jpg" alt="欢迎关注我的其他平台"></p>]]></content>
<summary type="html">简单教你如何采购服务器,配置服务器基本环境,并获得流畅的Docker使用环境。</summary>
<category term="技术分享" scheme="https://blog.sakurasep.site/categories/%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/"/>
<category term="零基础" scheme="https://blog.sakurasep.site/tags/%E9%9B%B6%E5%9F%BA%E7%A1%80/"/>
<category term="Linux" scheme="https://blog.sakurasep.site/tags/Linux/"/>
</entry>
<entry>
<title>基于UA3F的校园网防检测指南</title>
<link href="https://blog.sakurasep.site/posts/UA3F/"/>
<id>https://blog.sakurasep.site/posts/UA3F/</id>
<published>2024-07-12T07:14:23.000Z</published>
<updated>2024-07-12T07:14:23.000Z</updated>
<content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>作为QFNU曾在北公寓住宿过的学生,当转入校内宿舍楼居住的时候马上体会到了网络带来的不便,之前网线入户带来的便捷取而代之的是移动加私企垄断的局面。</p><p>之前有竞争的时候,移动 10 元 100 兆宽带或是联通 300 兆宽带都能满足不同的需要,对于宿舍 6-8 人的需求,100 兆在非下载资源的时间段是绰绰有余的,对于学生来说资费也很合适,毕竟出了宿舍开热点用流量还是更加方便。</p><p>对于新校区将校园网普及到宿舍,这本身是一件好事,可是被无良公司当成了赚钱的工具。当初承诺的每一个人单设备独享 100 兆带宽,可是一到晚上速度就会降到 20 兆到 30 兆的速度。让我们计算一下,一个宿舍楼的出口带宽是 80Gbps,一个宿舍楼有11层楼,一层楼差不多30个宿舍,一个宿舍6个人,11 x 30 x 6=1980,按照 2000 人来算,如果所有人都办理校园网外加全部都下载资源跑满下行,每个设备都应该有 40 兆的带宽。</p><p>其次是所谓的安全问题,校园网采用的是锐捷的系统,能够清楚地知道哪一个 IP 访问了什么内容,这样来进行管理时没有问题的。然而防共享检测将每个账号的使用设备控制在 2 个,电脑加手机,多的平板就不能上网了。校园网之前说可以提供设备的 mac 地址来扩展设备数量,但是直到现在都没有实行,纯纯的画大饼。就算放开共享,现在已经实现了 ap 入户,每一个宿舍都有一个独立的 ap,后台仍然可以精准定位异常访问,精准到某个宿舍,难道很难吗。共享检测做的这么严密,其实不过是垄断之后想要狠狠地赚钱罢了。</p><p>好了,作为毕业的老东西,哥们终于可以分享如何绕过校园网的检测,实现宿舍上网自由。</p><div class="tag-plugin colorful note" ><div class="title">注意事项,本教程适用于锐捷</div><div class="body"><p>web 认证,其他认证请加 TG 群 @crack_campus_network 讨论</p></div></div><p>以下是锐捷 web 认证网页端,如果确定是此类型的校园网认证,可以尝试本教程内容</p><p><img src="/../../img/%E5%9F%BA%E4%BA%8EUA3F%E7%9A%84%E6%A0%A1%E5%9B%AD%E7%BD%91%E9%98%B2%E6%A3%80%E6%B5%8B%E6%8C%87%E5%8D%97/image-20240712171129545.png" alt="锐捷 web 认证"></p><p><img src="/../../img/%E5%9F%BA%E4%BA%8EUA3F%E7%9A%84%E6%A0%A1%E5%9B%AD%E7%BD%91%E9%98%B2%E6%A3%80%E6%B5%8B%E6%8C%87%E5%8D%97/image-20240712171206628.png" alt="锐捷 web 认证"></p><h3 id="一、准备工作"><a href="#一、准备工作" class="headerlink" title="一、准备工作"></a>一、准备工作</h3><div class="tag-plugin colorful checkbox" ><input type="radio" checked="true"/><span>一台支持 openwrt 的设备</span></div><div class="tag-plugin colorful checkbox" ><input type="radio" checked="true"/><span>一个校园网账号</span></div><div class="tag-plugin colorful checkbox" ><input type="radio" checked="true"/><span>一个较为稳定的机场</span></div><h3 id="二、UA3F-Clash-在-openwrt-的安装"><a href="#二、UA3F-Clash-在-openwrt-的安装" class="headerlink" title="二、UA3F + Clash 在 openwrt 的安装"></a>二、UA3F + Clash 在 openwrt 的安装</h3><p>对于 QFNU 的共享检测机制,是检测 UA 和腾讯系流量,因此传统的 UA2F 会遇到经常性的封禁问题,一旦连接路由的设备出现了访问腾讯系应用,就可能触发延迟封禁(不会秒封,猜测是有阈值),由于 UA2F 不能与 Clash 等代理共存,所以 UA2F 不能很好的处理锐捷针对腾讯流量的检测。但是好在,UA3F 诞生了。</p><p>UA3F 作为一个 SOCK5 服务,可以直接与 Clash 进行交流,我们让 Clash 接管设备的所有流量,根据规则将 http 协议的链接走 UA3F 进行 UA 的修改,然后将其他特殊的流量走代理加密,剩余不需要处理的流量直连即可。</p><h4 id="1-挑选合适的设备"><a href="#1-挑选合适的设备" class="headerlink" title="1. 挑选合适的设备"></a>1. 挑选合适的设备</h4><p>UA3F 支持常见的架构设备,只要你的设备支持 openwrt,内存大于 256 兆,基本就可以使用。这里我个人推荐购买一台 RAX3000M(20231027版本),WIFI6,免拆刷机,512 兆内存,闲鱼购买价格在 100 左右是超值的价格。闲鱼购买时可以选择让卖家刷好 openwrt 后发出,便可以直接跳转到安装教程。</p><p><img src="/../../img/%E5%9F%BA%E4%BA%8EUA3F%E7%9A%84%E6%A0%A1%E5%9B%AD%E7%BD%91%E9%98%B2%E6%A3%80%E6%B5%8B%E6%8C%87%E5%8D%97/Snipaste_2024-06-24_22-37-18.png" alt="设备的基本概览"></p><p><img src="/../../img/%E5%9F%BA%E4%BA%8EUA3F%E7%9A%84%E6%A0%A1%E5%9B%AD%E7%BD%91%E9%98%B2%E6%A3%80%E6%B5%8B%E6%8C%87%E5%8D%97/Snipaste_2024-06-24_22-57-02.png" alt="这台设备的WIFI双频合一,记得分开"></p><p>其他的路由器在确定内存满足要求后,便可以去恩山无线论坛查看是否有 openwrt 的刷机包,以及刷机是否方便。</p><p>如果你有自己的小型服务器,而且这个服务器还有两个 wan 口,那么你可以在服务器装虚拟机,然后随便外接一个路由实现无线功能。</p><h4 id="2-安装-UA3F"><a href="#2-安装-UA3F" class="headerlink" title="2. 安装 UA3F"></a>2. 安装 UA3F</h4><h5 id="2-1-使用-SSH-工具连接到设备"><a href="#2-1-使用-SSH-工具连接到设备" class="headerlink" title="2.1 使用 SSH 工具连接到设备"></a>2.1 使用 SSH 工具连接到设备</h5><p><img src="/../../img/%E5%9F%BA%E4%BA%8EUA3F%E7%9A%84%E6%A0%A1%E5%9B%AD%E7%BD%91%E9%98%B2%E6%A3%80%E6%B5%8B%E6%8C%87%E5%8D%97/Snipaste_2024-06-24_22-57-50.png" alt="SSH连接设备"></p><p>确保此时你只有一台设备连接到路由器,以免触发校园网的封禁。</p><h5 id="2-2-更新软件包以及安装依赖"><a href="#2-2-更新软件包以及安装依赖" class="headerlink" title="2.2 更新软件包以及安装依赖"></a>2.2 更新软件包以及安装依赖</h5><p>在控制台输入以下指令</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">opkg update</span><br><span class="line">opkg install curl libcurl luci-compat</span><br></pre></td></tr></table></figure><p><img src="/../../img/%E5%9F%BA%E4%BA%8EUA3F%E7%9A%84%E6%A0%A1%E5%9B%AD%E7%BD%91%E9%98%B2%E6%A3%80%E6%B5%8B%E6%8C%87%E5%8D%97/Snipaste_2024-06-24_22-58-09.png" alt="更新软件包"></p><p><img src="/../../img/%E5%9F%BA%E4%BA%8EUA3F%E7%9A%84%E6%A0%A1%E5%9B%AD%E7%BD%91%E9%98%B2%E6%A3%80%E6%B5%8B%E6%8C%87%E5%8D%97/Snipaste_2024-06-24_22-58-31.png" alt="安装依赖"></p><h5 id="2-3-安装-UA3F"><a href="#2-3-安装-UA3F" class="headerlink" title="2.3 安装 UA3F"></a>2.3 安装 UA3F</h5><p>输入以下指令安装 UA3F,当出现 <code>Install UA3F success</code>说明安装完成</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="built_in">export</span> url=<span class="string">'https://blog.sunbk201.site/cdn'</span> && sh -c <span class="string">"<span class="subst">$(curl -kfsSl $url/install.sh)</span>"</span></span><br><span class="line">service ua3f reload</span><br></pre></td></tr></table></figure><p><img src="/../../img/%E5%9F%BA%E4%BA%8EUA3F%E7%9A%84%E6%A0%A1%E5%9B%AD%E7%BD%91%E9%98%B2%E6%A3%80%E6%B5%8B%E6%8C%87%E5%8D%97/Snipaste_2024-06-24_22-59-08.png" alt="安装UA3F"></p><p>此时就可以在 openwrt 侧边栏的<code>服务 - UA3F</code>中找到 luci 界面进行管理</p><p><img src="/../../img/%E5%9F%BA%E4%BA%8EUA3F%E7%9A%84%E6%A0%A1%E5%9B%AD%E7%BD%91%E9%98%B2%E6%A3%80%E6%B5%8B%E6%8C%87%E5%8D%97/Snipaste_2024-06-24_23-09-00.png" alt="管理界面"></p><h4 id="3-shellclash-的安装"><a href="#3-shellclash-的安装" class="headerlink" title="3. shellclash 的安装"></a>3. shellclash 的安装</h4><h5 id="3-1-安装稳定版-shellclash"><a href="#3-1-安装稳定版-shellclash" class="headerlink" title="3.1 安装稳定版 shellclash"></a>3.1 安装稳定版 shellclash</h5><p>相比于 openclash,这里更推荐 shellclash,因为占用小,性能较好。</p><p>同样在控制台输入以下指令</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="built_in">export</span> url=<span class="string">'https://fastly.jsdelivr.net/gh/juewuy/ShellCrash@master'</span> && wget -q --no-check-certificate -O /tmp/install.sh <span class="variable">$url</span>/install.sh && sh /tmp/install.sh && <span class="built_in">source</span> /etc/profile &> /dev/null</span><br></pre></td></tr></table></figure><p>请选择 <code>稳定版</code> 以及 <code>在/etc目录下安装</code></p><p><img src="/../../img/%E5%9F%BA%E4%BA%8EUA3F%E7%9A%84%E6%A0%A1%E5%9B%AD%E7%BD%91%E9%98%B2%E6%A3%80%E6%B5%8B%E6%8C%87%E5%8D%97/Snipaste_2024-06-24_23-03-14.png" alt="shellclash安装"></p><h5 id="3-2-导入修改后的配置文件"><a href="#3-2-导入修改后的配置文件" class="headerlink" title="3.2 导入修改后的配置文件"></a>3.2 导入修改后的配置文件</h5><p>此时你需要修改 UA3F 作者提供的配置文件</p><div class="tag-plugin link dis-select"><a class="link-card rich" title="UA3F 增强版配置文件" href="https://cdn.jsdelivr.net/gh/SunBK201/UA3F@master/clash/ua3f-global-enhance.yaml" target="_blank" rel="external nofollow noopener noreferrer" cardlink api="https://site-info-api-git-main-sakurasep.vercel.app/api/v1?url=https://cdn.jsdelivr.net/gh/SunBK201/UA3F@master/clash/ua3f-global-enhance.yaml" autofill="icon,desc"><div class="top"><div class="lazy img" data-bg="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/link/8f277b4ee0ecd.svg"></div><span class="cap link footnote">https://cdn.jsdelivr.net/gh/SunBK201/UA3F@master/clash/ua3f-global-enhance.yaml</span></div><div class="bottom"><span class="title">UA3F 增强版配置文件</span><span class="cap desc footnote"></span></div></a></div><p><img src="/../../img/%E5%9F%BA%E4%BA%8EUA3F%E7%9A%84%E6%A0%A1%E5%9B%AD%E7%BD%91%E9%98%B2%E6%A3%80%E6%B5%8B%E6%8C%87%E5%8D%97/image-20240712164927043.png" alt="填入机场订阅链接"></p><p>修改完配置文件后,可以将文件上传到我的网盘获取直链,同时我的网盘也支持在线编辑</p><div class="tag-plugin link dis-select"><a class="link-card rich" title="上杉九月的网盘" href="https://cloud.sakurasep.top" target="_blank" rel="external nofollow noopener noreferrer" cardlink api="https://site-info-api-git-main-sakurasep.vercel.app/api/v1?url=https://cloud.sakurasep.top" autofill="icon,desc"><div class="top"><div class="lazy img" data-bg="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/link/8f277b4ee0ecd.svg"></div><span class="cap link footnote">https://cloud.sakurasep.top</span></div><div class="bottom"><span class="title">上杉九月的网盘</span><span class="cap desc footnote"></span></div></a></div><p>注册完成后点击网站右下角的加号选择文件上传,上传后双击文件进行在线编辑,最后右键文件获取外链</p><p><img src="/../../img/%E5%9F%BA%E4%BA%8EUA3F%E7%9A%84%E6%A0%A1%E5%9B%AD%E7%BD%91%E9%98%B2%E6%A3%80%E6%B5%8B%E6%8C%87%E5%8D%97/image-20240712165330354.png" alt="上传文件到网盘"></p><p><img src="/../../img/%E5%9F%BA%E4%BA%8EUA3F%E7%9A%84%E6%A0%A1%E5%9B%AD%E7%BD%91%E9%98%B2%E6%A3%80%E6%B5%8B%E6%8C%87%E5%8D%97/image-20240712165528283.png" alt="在线编辑配置文件"></p><p><img src="/../../img/%E5%9F%BA%E4%BA%8EUA3F%E7%9A%84%E6%A0%A1%E5%9B%AD%E7%BD%91%E9%98%B2%E6%A3%80%E6%B5%8B%E6%8C%87%E5%8D%97/image-20240712165603289.png" alt="右键配置文件获取外链"></p><p>在 shellclash 的控制台,选择 <code>导入配置文件 - 在线获取完整配置文件</code></p><p><img src="/../../img/%E5%9F%BA%E4%BA%8EUA3F%E7%9A%84%E6%A0%A1%E5%9B%AD%E7%BD%91%E9%98%B2%E6%A3%80%E6%B5%8B%E6%8C%87%E5%8D%97/image-20240712165834179.png" alt="导入配置文件"></p><p><img src="/../../img/%E5%9F%BA%E4%BA%8EUA3F%E7%9A%84%E6%A0%A1%E5%9B%AD%E7%BD%91%E9%98%B2%E6%A3%80%E6%B5%8B%E6%8C%87%E5%8D%97/image-20240712165919130.png" alt="image-20240712165919130"></p><h5 id="3-3-安装本地面板"><a href="#3-3-安装本地面板" class="headerlink" title="3.3 安装本地面板"></a>3.3 安装本地面板</h5><p>安装本地面板方便管理配置</p><p><img src="/../../img/%E5%9F%BA%E4%BA%8EUA3F%E7%9A%84%E6%A0%A1%E5%9B%AD%E7%BD%91%E9%98%B2%E6%A3%80%E6%B5%8B%E6%8C%87%E5%8D%97/image-20240712164534223.png" alt="安装本地面板"></p><p><img src="/../../img/%E5%9F%BA%E4%BA%8EUA3F%E7%9A%84%E6%A0%A1%E5%9B%AD%E7%BD%91%E9%98%B2%E6%A3%80%E6%B5%8B%E6%8C%87%E5%8D%97/image-20240712164625141.png" alt="推荐 2 或者 3"></p><h5 id="3-4-关闭只代理常用端口"><a href="#3-4-关闭只代理常用端口" class="headerlink" title="3.4 关闭只代理常用端口"></a>3.4 关闭只代理常用端口</h5><p>最后一定要关闭 <code>只代理常用端口</code></p><p><img src="/../../img/%E5%9F%BA%E4%BA%8EUA3F%E7%9A%84%E6%A0%A1%E5%9B%AD%E7%BD%91%E9%98%B2%E6%A3%80%E6%B5%8B%E6%8C%87%E5%8D%97/Snipaste_2024-06-24_23-06-08.png" alt="关闭代理常用端口"></p><h5 id="3-5-访问管理界面"><a href="#3-5-访问管理界面" class="headerlink" title="3.5 访问管理界面"></a>3.5 访问管理界面</h5><p>此时点击 CN 策略组的测速按钮,测得 ua3f 是可以连通的,说明配置是正确的。</p><p>然后多连几个设备,打开腾讯系应用,在管理界面的连接页面看一下是否触发了规则,走的是机场代理。</p><p><img src="/../../img/%E5%9F%BA%E4%BA%8EUA3F%E7%9A%84%E6%A0%A1%E5%9B%AD%E7%BD%91%E9%98%B2%E6%A3%80%E6%B5%8B%E6%8C%87%E5%8D%97/Snipaste_2024-06-24_23-12-33.png" alt="clash 管理界面"></p><h3 id="三、注意事项"><a href="#三、注意事项" class="headerlink" title="三、注意事项"></a>三、注意事项</h3><p>目前我在使用的时候,发现 bilibili 手机端默认使用 http 协议播放视频,这会导致看 bilibili 的视频走代理,请在手机端的<code>设置-播放设置-其他播放设置</code>中开始使用 https 播放。</p><p>如果有其他问题欢迎在评论区交流反馈,感谢!</p><p><img src="/../../img/%E5%9F%BA%E4%BA%8EUA3F%E7%9A%84%E6%A0%A1%E5%9B%AD%E7%BD%91%E9%98%B2%E6%A3%80%E6%B5%8B%E6%8C%87%E5%8D%97/image-20240823115751812.png" alt="image-20240823115751812"></p><h2 id="后记"><a href="#后记" class="headerlink" title="后记"></a>后记</h2><p>前几天看科技宅小明测北京高校的网速,才感觉那句老话说的好,一流大学抓学术、二流大学抓技术、三流大学抓纪律。校园网全覆盖自然是好的,比如说在新的图书馆,有 WIFI 看课啥的都很爽。但是宿舍这地方还搞一堆限制,完全就是搞人心态。现在山东宽带费用不贵吧,千兆宽带一年也就 300 左右,校园网在宿舍可真赚了不少钱。之前和校园网代理还在微信聊过,还说自己也难,没人办理,成本收不回来。哥们你猜为啥没人办,又贵又垃圾,能用流量就流量,能开热点开热点,自然不会加办你这烂的稀碎的校园网。</p><hr><p><img src="/../../assets/user/about_me.jpg" alt="关于我"></p>]]></content>
<summary type="html">校园网的垄断,带来的是限制、高昂的费用与低质量</summary>
<category term="零基础教程" scheme="https://blog.sakurasep.site/categories/%E9%9B%B6%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B/"/>
<category term="UA3F" scheme="https://blog.sakurasep.site/tags/UA3F/"/>
<category term="校园网" scheme="https://blog.sakurasep.site/tags/%E6%A0%A1%E5%9B%AD%E7%BD%91/"/>
<category term="Clash" scheme="https://blog.sakurasep.site/tags/Clash/"/>
<category term="Openwrt" scheme="https://blog.sakurasep.site/tags/Openwrt/"/>
</entry>
<entry>
<title>使用第三方 Cron 定时执行 Github Action</title>
<link href="https://blog.sakurasep.site/posts/cron-github-action/"/>
<id>https://blog.sakurasep.site/posts/cron-github-action/</id>
<published>2024-03-23T01:25:41.000Z</published>
<updated>2024-03-23T01:25:41.000Z</updated>
<content type="html"><![CDATA[<h2 id="为什么不使用-Github-Action-自带的-schedule"><a href="#为什么不使用-Github-Action-自带的-schedule" class="headerlink" title="为什么不使用 Github Action 自带的 schedule"></a>为什么不使用 Github Action 自带的 schedule</h2><div class="tag-plugin colorful note" ><div class="title">Github</div><div class="body"><p>官方对与 schedule 的定义</p></div></div><p>Scheduled events(预定事件) The <strong>Schedule</strong> event allows you to trigger a workflow at a scheduled time.(该<strong>Schedule</strong>事件允许您在预定时间触发工作流。)<br>Note: The <strong>Schedule</strong> event can be delayed during periods of high loads of GitHub Actions workflow runs. High load times include the start of every hour. To decrease the chance of delay, schedule your workflow to run at a different time of the hour.</p><p>注意:<strong>Schedule</strong>在 GitHub 操作工作流运行的高负载期间,事件可能会延迟。高负载时间包括每小时开始。为了减少延迟的可能性,请安排您的工作流在不同的时间运行。</p><p>从官方的定义可以看出,schedule 是到了设置的时间把你的任务加入一个待执行队列,如果这时队列出现了拥堵的情况,最糟糕的可能是超过定时时间 1-2 小时还没有执行。也就是说对于执行时间比较敏感的任务,建议使用第三方 cron 平台。</p><h2 id="如何使用-cron-job-实现精确的定时任务"><a href="#如何使用-cron-job-实现精确的定时任务" class="headerlink" title="如何使用 cron-job 实现精确的定时任务"></a>如何使用 cron-job 实现精确的定时任务</h2><p><code>repository_dispatch</code> 是 GitHub Actions 中的一个事件类型,它允许您通过使用 GitHub API 手动触发存储库中的工作流程运行。所以我们可以使用 cron-job 定时调用 Github 的 API,实现精准的定时执行。</p><h3 id="1-更改action文件的触发条件"><a href="#1-更改action文件的触发条件" class="headerlink" title="1. 更改action文件的触发条件"></a>1. 更改action文件的触发条件</h3><div class="tag-plugin colorful note" ><div class="body"><p>添加repository_dispatch</p></div></div><figure class="highlight yml"><table><tr><td class="code"><pre><span class="line"><span class="attr">on:</span></span><br><span class="line"> <span class="attr">workflow_dispatch:</span></span><br><span class="line"> <span class="attr">repository_dispatch:</span></span><br><span class="line"> <span class="attr">types:</span> [<span class="string">schedule-run</span>]</span><br></pre></td></tr></table></figure><h3 id="2-获取-Personal-access-tokens"><a href="#2-获取-Personal-access-tokens" class="headerlink" title="2. 获取 Personal access tokens"></a>2. 获取 Personal access tokens</h3><p>在个人 Github 的 Settings/Developer Settings 创建 token</p><p><img src="/../../img/%E4%BD%BF%E7%94%A8%E7%AC%AC%E4%B8%89%E6%96%B9cron%E5%AE%9A%E6%97%B6%E6%89%A7%E8%A1%8CGithub_Action/image-20240323101856723.png" alt="image-20240323101856723"></p><p>选择创建经典的 token</p><p><img src="/../../img/%E4%BD%BF%E7%94%A8%E7%AC%AC%E4%B8%89%E6%96%B9cron%E5%AE%9A%E6%97%B6%E6%89%A7%E8%A1%8CGithub_Action/image-20240323101931254.png" alt="image-20240323101931254"></p><p>选择 token 权限为 repo</p><p><img src="/../../img/%E4%BD%BF%E7%94%A8%E7%AC%AC%E4%B8%89%E6%96%B9cron%E5%AE%9A%E6%97%B6%E6%89%A7%E8%A1%8CGithub_Action/image-20240323102220951.png" alt="image-20240323102220951"></p><p>此时就获得了你的 token,保存好。</p><h3 id="3-配置-cron-job"><a href="#3-配置-cron-job" class="headerlink" title="3. 配置 cron-job"></a>3. 配置 cron-job</h3><div class="tag-plugin link dis-select"><a class="link-card rich" title="cron-job 官网" href="https://cron-job.org/en/" target="_blank" rel="external nofollow noopener noreferrer" cardlink api="https://site-info-api-git-main-sakurasep.vercel.app/api/v1?url=https://cron-job.org/en/" autofill="icon,desc"><div class="top"><div class="lazy img" data-bg="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/link/8f277b4ee0ecd.svg"></div><span class="cap link footnote">https://cron-job.org/en/</span></div><div class="bottom"><span class="title">cron-job 官网</span><span class="cap desc footnote"></span></div></a></div><p>注册完成后进入控制台,可以在右上角设置中文</p><p><code>需要填写</code>改为下图内容,需要定时执行哪一个工作流就把对应内容粘贴到网址中</p><p><img src="/../../img/%E4%BD%BF%E7%94%A8%E7%AC%AC%E4%B8%89%E6%96%B9cron%E5%AE%9A%E6%97%B6%E6%89%A7%E8%A1%8CGithub_Action/image-20240323102803464.png" alt="image-20240323102803464"></p><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">https://api.github.com/repos/需要填写/dispatches</span><br></pre></td></tr></table></figure><p><img src="/../../img/%E4%BD%BF%E7%94%A8%E7%AC%AC%E4%B8%89%E6%96%B9cron%E5%AE%9A%E6%97%B6%E6%89%A7%E8%A1%8CGithub_Action/image-20240323102550509.png" alt="image-20240323102550509"></p><p>然后在进阶选项中添加标头和请求内容</p><p>标头键为 Authorization 值为 <code>token 刚才获取的token</code></p><p>请求体为</p><figure class="highlight json"><table><tr><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"ref"</span><span class="punctuation">:</span> <span class="string">"main"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><p><img src="/../../img/%E4%BD%BF%E7%94%A8%E7%AC%AC%E4%B8%89%E6%96%B9cron%E5%AE%9A%E6%97%B6%E6%89%A7%E8%A1%8CGithub_Action/image-20240323103023142.png" alt="image-20240323103023142"></p><p>此时保存后进行测试,显示 204 即为成功,此时你对应的 Github Action 便就执行成功了</p><p><img src="/../../img/%E4%BD%BF%E7%94%A8%E7%AC%AC%E4%B8%89%E6%96%B9cron%E5%AE%9A%E6%97%B6%E6%89%A7%E8%A1%8CGithub_Action/image-20240323103556994.png" alt="image-20240323103556994"></p><hr><p><img src="/../../assets/user/about_me.jpg" alt="关于我"></p>]]></content>
<summary type="html">由于 Github 默认的定时计划是将程序在所设置的时间加入执行队列,对于需要较高精确执行时间的程序来说就存在着问题,使用第三方的 cron 服务便可以轻松解决这个问题。</summary>
<category term="实用工具" scheme="https://blog.sakurasep.site/categories/%E5%AE%9E%E7%94%A8%E5%B7%A5%E5%85%B7/"/>
<category term="cron" scheme="https://blog.sakurasep.site/tags/cron/"/>
<category term="Github" scheme="https://blog.sakurasep.site/tags/Github/"/>
</entry>
<entry>
<title>Java的集合框架</title>
<link href="https://blog.sakurasep.site/posts/Java_Collection/"/>
<id>https://blog.sakurasep.site/posts/Java_Collection/</id>
<published>2024-03-20T07:10:42.000Z</published>
<updated>2024-03-20T07:10:42.000Z</updated>
<content type="html"><![CDATA[<div class="tag-plugin quot"><p class="content" type="text"><span class="empty"></span><span class="text">集合框架基本概念</span><span class="empty"></span></p></div><p>Collection 集合框架中用于存储一个个元素的容器,List 和 Set 是它的子类</p><ul><li><p>List: 存储有序的,可重复的数据</p><ul><li>ArrayList(主要实现类)、LinkedList、Vector</li></ul></li><li><p>Set: 存储无序的,不可重复的数据</p><ul><li>HashSet(主要实现类)、LinkedHashSet、TreeSet</li></ul></li></ul><p>Map 集合框架中用于存储 key 到 value 的键值映射的容器</p><ul><li><p>Map:存储一对一对的数据</p><ul><li>HashMap(主要实现类)、LinkedHashMap、TreeMap、Hashtable、Properties</li></ul></li></ul><p>Collections 用于操作集合框架的一个工具类</p><h2 id="Collection-常用方法"><a href="#Collection-常用方法" class="headerlink" title="Collection 常用方法"></a>Collection 常用方法</h2><div class="tag-plugin colorful note" ><div class="body"><p>定义两个集合</p></div></div><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="type">Collection</span> <span class="variable">collection</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ArrayList</span>();</span><br><span class="line"><span class="type">Collection</span> <span class="variable">collection1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ArrayList</span>();</span><br><span class="line">collection.add(<span class="string">"test"</span>);</span><br><span class="line">collection.add(<span class="string">"测试"</span>);</span><br><span class="line"><span class="type">Person</span> <span class="variable">person</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">10</span>, <span class="string">"xiaohua"</span>);</span><br><span class="line">collection.add(person);</span><br><span class="line">collection1.addAll(collection);</span><br><span class="line">collection1.add(<span class="string">"123"</span>);</span><br></pre></td></tr></table></figure><div class="tag-plugin colorful note" ><div class="body"><p>add、addAll</p></div></div><p>前者用于添加对象元素,后者用于添加一整个集合比较常见</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line">System.out.println(collection);</span><br><span class="line">System.out.println(collection1);</span><br></pre></td></tr></table></figure><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240320183228912.png" alt="image-20240320183228912"></p><div class="tag-plugin colorful note" ><div class="body"><p>clear、isEmpty、size</p></div></div><p>清除集合内的元素,用于查看集合是否为空,查看集合元素数量</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line">collection1.clear();</span><br><span class="line">System.out.println(collection1.isEmpty());</span><br><span class="line">System.out.println(collection1.size());</span><br></pre></td></tr></table></figure><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240320183427511.png" alt="image-20240320183427511"></p><div class="tag-plugin colorful note" ><div class="body"><p>contains、containsAll</p></div></div><p>前者是判断集合中是否含有某个对象,后者是判断一个集合是否包含另一个集合</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 没有重写 equals 方法 对于对象的比较相当于 ==</span></span><br><span class="line"><span class="comment">// 注意,String 已经默认重写了 equals</span></span><br><span class="line">System.out.println(collection);</span><br><span class="line">System.out.println(collection1);</span><br><span class="line">System.out.println(collection.contains(person)); <span class="comment">// true</span></span><br><span class="line">System.out.println(collection.contains(<span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">10</span>, <span class="string">"xiaohua"</span>)));<span class="comment">// false</span></span><br><span class="line">System.out.println(collection.contains(<span class="string">"test"</span>)); <span class="comment">// true</span></span><br><span class="line"><span class="comment">// 集合之间的包含关系</span></span><br><span class="line">System.out.println(collection.containsAll(collection1)); <span class="comment">// false</span></span><br><span class="line">System.out.println(collection1.containsAll(collection)); <span class="comment">// true</span></span><br></pre></td></tr></table></figure><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240320184032131.png" alt="image-20240320184032131"></p><div class="tag-plugin colorful note" ><div class="body"><p>remove、removeAll、retainAll</p></div></div><p>删除指定元素,删除两个集合的交集,只保留两个集合的交集</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line">System.out.println(collection);</span><br><span class="line">System.out.println(collection1);</span><br><span class="line">collection1.removeAll(collection);</span><br><span class="line">System.out.println(collection1);</span><br><span class="line"></span><br><span class="line">System.out.println(<span class="string">"******************"</span>);</span><br><span class="line"></span><br><span class="line">collection1.add(<span class="string">"test"</span>);</span><br><span class="line">collection1.add(<span class="string">"1234"</span>);</span><br><span class="line">System.out.println(collection);</span><br><span class="line">System.out.println(collection1);</span><br><span class="line">collection1.retainAll(collection);</span><br><span class="line">System.out.println(collection1);</span><br></pre></td></tr></table></figure><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240320191555533.png" alt="image-20240320191555533"></p><div class="tag-plugin colorful note" ><div class="title">toArray</div><div class="body"><p>&& asList</p></div></div><p>把集合转换成数组</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test4</span><span class="params">()</span> {</span><br><span class="line"> <span class="type">Collection</span> <span class="variable">collection</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ArrayList</span>();</span><br><span class="line"> collection.add(<span class="string">"test"</span>);</span><br><span class="line"> collection.add(<span class="string">"测试"</span>);</span><br><span class="line"> collection.add(<span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">10</span>, <span class="string">"xiaohua"</span>));</span><br><span class="line"> <span class="comment">// 其他方法</span></span><br><span class="line"> Object[] arr = collection.toArray();</span><br><span class="line"> System.out.println(Arrays.toString(arr));</span><br><span class="line"> System.out.println(arr[<span class="number">0</span>]);</span><br><span class="line"> System.out.println(arr[<span class="number">1</span>]);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240320184520055.png" alt="image-20240320184520055"></p><p>Arrays中的asList 可以将数组转换成集合</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test6</span><span class="params">()</span> {</span><br><span class="line"> String[] strings = <span class="keyword">new</span> <span class="title class_">String</span>[]{<span class="string">"a"</span>, <span class="string">"b"</span>, <span class="string">"c"</span>};</span><br><span class="line"> <span class="type">Collection</span> <span class="variable">collection</span> <span class="operator">=</span> Arrays.asList(strings);</span><br><span class="line"> System.out.println(collection);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><div class="tag-plugin colorful note" ><div class="title">Iterator</div><div class="body"><p>迭代器</p></div></div><p>迭代器是用来遍历元素的</p><div class="tag-plugin colorful note" ><div class="title">next、hasNext</div><div class="body"><p>获取集合中下一个元素,hasNext 能够判断是否有下一个元素</p></div></div><p>next 两个作用,第一个是指针下移,第二个是获取当前的元素</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test1</span><span class="params">()</span> {</span><br><span class="line"> <span class="type">Collection</span> <span class="variable">collection</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ArrayList</span>();</span><br><span class="line"> collection.add(<span class="string">"test"</span>);</span><br><span class="line"> collection.add(<span class="string">"测试"</span>);</span><br><span class="line"> <span class="type">Person</span> <span class="variable">person</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">10</span>, <span class="string">"xiaohua"</span>);</span><br><span class="line"> collection.add(person);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 获取迭代器对象</span></span><br><span class="line"> System.out.println(collection);</span><br><span class="line"> <span class="type">Iterator</span> <span class="variable">iterator</span> <span class="operator">=</span> collection.iterator();</span><br><span class="line"><span class="comment">// for (int i = 0; i < collection.size(); i++) {</span></span><br><span class="line"><span class="comment">// System.out.println(iterator.next());</span></span><br><span class="line"><span class="comment">// }</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">// hasNext</span></span><br><span class="line"> <span class="keyword">while</span> (iterator.hasNext()) {</span><br><span class="line"> System.out.println(iterator.next());</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>对于遍历元素还有一种方式,就是增强的 for 循环</p><p>使用增强 for 循环的时候,修改 for 循环中的临时变量,将不会修改原有的数据。因为增强 for 循环是将原有的数据赋值给临时变量。</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 增强 for 循环</span></span><br><span class="line"><span class="keyword">for</span> (Object obj : collection) {</span><br><span class="line"> System.out.println(obj);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240321144919864.png" alt="image-20240321144919864"></p><h2 id="List-常用方法"><a href="#List-常用方法" class="headerlink" title="List 常用方法"></a>List 常用方法</h2><p>和 Collection 相同,大体上的方法作用是相同的。这里仅介绍 List 作为有序的集合,相比于 Collection 的不同。</p><h3 id="List-不同类的区别"><a href="#List-不同类的区别" class="headerlink" title="List 不同类的区别"></a>List 不同类的区别</h3><ul><li>ArrayList:List 主要实现类,线程不安全,效率高,底层使用 Object[] 数组储存</li><li>LinkedList:底层使用双向链表的方式进行储存,适用于频繁插入删除的操作</li><li>Vector:List 的古老实现类,线程安全,效率低,底层使用 Object[] 数组储存</li></ul><h3 id="List-的特殊方法"><a href="#List-的特殊方法" class="headerlink" title="List 的特殊方法"></a>List 的特殊方法</h3><div class="tag-plugin colorful note" ><div class="title">add(index,</div><div class="body"><p>element)</p></div></div><p>add 方法相对于 Collection 多了索引,所以可以在指定位置插入元素。同样,addAll也有这样的特性。</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test1</span><span class="params">()</span> {</span><br><span class="line"> <span class="type">List</span> <span class="variable">list</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ArrayList</span>();</span><br><span class="line"> list.add(<span class="string">"test"</span>);</span><br><span class="line"> list.add(<span class="number">123</span>);</span><br><span class="line"> <span class="type">Person</span> <span class="variable">person</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">10</span>, <span class="string">"xiaohu"</span>);</span><br><span class="line"> list.add(person);</span><br><span class="line"> System.out.println(list);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// add 插入指定索引的元素</span></span><br><span class="line"> list.add(<span class="number">2</span>, <span class="string">"321"</span>);</span><br><span class="line"> System.out.println(list);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// addAll 插入指定索引的集合</span></span><br><span class="line"> <span class="type">List</span> <span class="variable">list1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ArrayList</span>();</span><br><span class="line"> list1.add(<span class="string">"test"</span>);</span><br><span class="line"> list1.add(<span class="string">"test"</span>);</span><br><span class="line"> list1.add(<span class="string">"test"</span>);</span><br><span class="line"> list1.addAll(<span class="number">1</span>, list);</span><br><span class="line"> System.out.println(list1);</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240321153732711.png" alt="image-20240321153732711"></p><div class="tag-plugin colorful note" ><div class="title">remove(index)</div><div class="body"><p>remove</p></div></div><p>方法删除的是索引位置的元素,如果要删除数据,用Integer的 valueof 赋值成一个对象即可</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// remove 元素删除的指定索引的元素</span></span><br><span class="line">list1.remove(<span class="number">0</span>);</span><br><span class="line">list1.remove(<span class="number">0</span>);</span><br><span class="line">System.out.println(list1);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用Integer创建对象来删除指定元素</span></span><br><span class="line">list1.remove(Integer.valueOf(<span class="number">123</span>));</span><br><span class="line">System.out.println(list1);</span><br></pre></td></tr></table></figure><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240321154311522.png" alt="image-20240321154311522"></p><div class="tag-plugin colorful note" ><div class="body"><p>set,get方法</p></div></div><p>因为 List 有序,所以说对于某一个位置的元素获取变的更加容易</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// get,set 方法</span></span><br><span class="line">list.set(<span class="number">0</span>, person);</span><br><span class="line">System.out.println(list.get(<span class="number">0</span>));</span><br></pre></td></tr></table></figure><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240321154642258.png" alt="image-20240321154642258"></p><div class="tag-plugin colorful note" ><div class="title">indexOf,lastIndexOf,subList</div><div class="body"><p>第一个是获取指定元素的首次出现的位置,第二个是获取指定元素的最后出现的位置,subList 是获取从 start 到 end 的所有元素</p></div></div><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test2</span><span class="params">()</span> {</span><br><span class="line"> <span class="type">List</span> <span class="variable">list</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ArrayList</span>();</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i < <span class="number">10</span>; i ++){</span><br><span class="line"> list.add(i);</span><br><span class="line"> list.add(i+<span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"> System.out.println(list);</span><br><span class="line"> System.out.println(list.indexOf(<span class="number">1</span>));</span><br><span class="line"> System.out.println(list.lastIndexOf(<span class="number">1</span>));</span><br><span class="line"> System.out.println(list.subList(<span class="number">0</span>, <span class="number">10</span>));</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240321155806789.png" alt="image-20240321155806789"></p><h3 id="List-综合测试"><a href="#List-综合测试" class="headerlink" title="List 综合测试"></a>List 综合测试</h3><h4 id="综合测试一"><a href="#综合测试一" class="headerlink" title="综合测试一"></a>综合测试一</h4><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240321183700520.png" alt="image-20240321183700520"></p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">StudentTest</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line"> <span class="type">List</span> <span class="variable">student</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ArrayList</span>();</span><br><span class="line"> <span class="type">Scanner</span> <span class="variable">scanner</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Scanner</span>(System.in);</span><br><span class="line"></span><br><span class="line"> <span class="type">int</span> <span class="variable">flag</span> <span class="operator">=</span> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span> (flag == <span class="number">1</span>) {</span><br><span class="line"> System.out.println(<span class="string">"请输入学生的姓名:"</span>);</span><br><span class="line"> <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> scanner.next();</span><br><span class="line"> System.out.println(<span class="string">"请输入学生的年龄:"</span>);</span><br><span class="line"> <span class="type">int</span> <span class="variable">age</span> <span class="operator">=</span> scanner.nextInt();</span><br><span class="line"> student.add(<span class="keyword">new</span> <span class="title class_">Student</span>(name, age));</span><br><span class="line"> System.out.println(<span class="string">"输入 1 继续录入,输入 0 停止录入"</span>);</span><br><span class="line"> flag = scanner.nextInt();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (Object obj : student) {</span><br><span class="line"> <span class="type">Student</span> <span class="variable">stu</span> <span class="operator">=</span> (Student) obj;</span><br><span class="line"> System.out.println(stu.toString());</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> scanner.close();</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="综合测试二"><a href="#综合测试二" class="headerlink" title="综合测试二"></a>综合测试二</h4><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240321183805554.png" alt="image-20240321183805554"></p><p>对于这个题,list 中存的是 char 字符类型,有两种解决方法。</p><p>第一种,存入 list 中的时候在后边加一个 <code>""</code></p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line">list.add((<span class="type">char</span>)number + <span class="string">""</span>);</span><br></pre></td></tr></table></figure><p>第二种,在比较的时候对 char 使用 String 的 valueOf 方法进行赋值</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="type">String</span> <span class="variable">c</span> <span class="operator">=</span> String.valueOf(iterator.next());</span><br><span class="line"><span class="type">String</span> <span class="variable">c</span> <span class="operator">=</span> String.valueOf(obj);</span><br></pre></td></tr></table></figure><div class="tag-plugin colorful note" ><div class="body"><p>完整代码</p></div></div><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">StringTest</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line"> <span class="type">ArrayList</span> <span class="variable">list</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ArrayList</span>();</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i < <span class="number">30</span>; i++) {</span><br><span class="line"> <span class="type">int</span> <span class="variable">max</span> <span class="operator">=</span> <span class="number">122</span> - <span class="number">97</span> + <span class="number">1</span>;</span><br><span class="line"> <span class="type">int</span> <span class="variable">number</span> <span class="operator">=</span> (<span class="type">int</span>) (Math.random() * max + <span class="number">97</span>);</span><br><span class="line"> list.add((<span class="type">char</span>)number + <span class="string">""</span>);</span><br><span class="line"> }</span><br><span class="line"> System.out.println(list);</span><br><span class="line"> <span class="type">int</span> <span class="variable">aCount</span> <span class="operator">=</span> listTest1(list, <span class="string">"a"</span>);</span><br><span class="line"> <span class="type">int</span> <span class="variable">bCount</span> <span class="operator">=</span> listTest1(list, <span class="string">"b"</span>);</span><br><span class="line"> <span class="type">int</span> <span class="variable">cCount</span> <span class="operator">=</span> listTest1(list, <span class="string">"c"</span>);</span><br><span class="line"> <span class="type">int</span> <span class="variable">xCount</span> <span class="operator">=</span> listTest1(list, <span class="string">"x"</span>);</span><br><span class="line"> System.out.printf(<span class="string">"%d %d %d %d\n"</span>, aCount, bCount, cCount, xCount);</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// 迭代器</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="type">int</span> <span class="title function_">listTest2</span><span class="params">(Collection list, String s)</span> {</span><br><span class="line"> <span class="type">int</span> <span class="variable">count</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"> <span class="type">Iterator</span> <span class="variable">iterator</span> <span class="operator">=</span> list.iterator();</span><br><span class="line"> <span class="keyword">while</span> (iterator.hasNext()) {</span><br><span class="line"> <span class="type">String</span> <span class="variable">c</span> <span class="operator">=</span> String.valueOf(iterator.next());</span><br><span class="line"> <span class="keyword">if</span>(c.equals(s)){</span><br><span class="line"> count++;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> count;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 增强 for 循环</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="type">int</span> <span class="title function_">listTest1</span><span class="params">(Collection list, String s)</span> {</span><br><span class="line"> <span class="type">int</span> <span class="variable">count</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span> (Object obj : list) {</span><br><span class="line"> <span class="type">String</span> <span class="variable">c</span> <span class="operator">=</span> String.valueOf(obj);</span><br><span class="line"> <span class="keyword">if</span> (c.equals(s)) {</span><br><span class="line"> count++;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> count;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240321200435573.png" alt="image-20240321200435573"></p><h2 id="Set-常用方法"><a href="#Set-常用方法" class="headerlink" title="Set 常用方法"></a>Set 常用方法</h2><p>Set 声明的方法与 Collection 中声明的 15 个抽象方法相同</p><p>对于 Set 来说,我们更重要的是研究他的两个特性。</p><h3 id="Set-的常见实现类"><a href="#Set-的常见实现类" class="headerlink" title="Set 的常见实现类"></a>Set 的常见实现类</h3><ul><li>HashSet:主要实现类,底层使用 HashMap,也就是使用了数组,单向链表,红黑树结构进行存储<ul><li>LinkedSet:HashSet 的子类,相比与父类,它在不同的元素之间增加了指针,实现了顺序遍历</li></ul></li><li>TreeSet:底层使用红黑树存储, 可以根据添加的元素对指定的属性大小进行遍历。</li></ul><h3 id="Set-的无序性"><a href="#Set-的无序性" class="headerlink" title="Set 的无序性"></a>Set 的无序性</h3><p>这里的无序性并不是随机性,对与 Set 来说,它保存是数据的方法是 HashMap,也就是对于将要保存的元素,计算它的哈希值,哈希值即为这个元素的保存位置,所以当添加完元素后,你输入的数据将不会按照顺序保存,而是根据自己的计算结果保存到不同位置,这就是 Set 的无序性。</p><p>按照 1-> 5 的顺序进行输入,经过哈希算法计算后排列的位置如下图所示</p><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240322093201232.png" alt="image-20240322093201232"></p><p>LinkedSet 相当于增加了一个指针,让 1 指向 2,2 指向 3,以此类推,最后遍历的时候便可以根据指针进行遍历。</p><h3 id="Set-的不可重复性"><a href="#Set-的不可重复性" class="headerlink" title="Set 的不可重复性"></a>Set 的不可重复性</h3><p>比较的标准是首先判断 HashCode 得到的哈希值是否相同,如果相等则进行 euqals。只有两者都相同,则认为元素是相同的。</p><h3 id="演示代码-HashSet"><a href="#演示代码-HashSet" class="headerlink" title="演示代码 HashSet"></a>演示代码 HashSet</h3><p>这里可能会有疑问,不是说 Set 中不存在重复的元素,难道对自定义的实体类不生效吗。</p><p>我们从Set 存入数据的过程看到,Set 首先要对元素进行哈希计算,这里我们 new 的两个 Person 对象,他们的实体类中没有重写 HashCode 方法,因此调用的是 Object 的方法,该方法并不会把这两个赋值相同的对象计算得到相同的哈希值,所以 Set 会把两个元素看做不同的元素。</p><p>为了避免这种问题,我们需要重写实体类中的 HashCode。</p><div class="tag-plugin colorful note" ><div class="body"><p>测试代码</p></div></div><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test2</span><span class="params">()</span> {</span><br><span class="line"> <span class="type">Set</span> <span class="variable">set</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">HashSet</span>();</span><br><span class="line"> set.add(<span class="string">"test"</span>);</span><br><span class="line"> set.add(<span class="number">123</span>);</span><br><span class="line"> set.add(<span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">10</span>,<span class="string">"xiaohua"</span>));</span><br><span class="line"> set.add(<span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">10</span>,<span class="string">"xiaohua"</span>));</span><br><span class="line"></span><br><span class="line"> System.out.println(set);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240322094309728.png" alt="image-20240322094309728"></p><div class="tag-plugin colorful note" ><div class="title">重写</div><div class="body"><p>HashCode</p></div></div><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> <span class="type">int</span> <span class="title function_">hashCode</span><span class="params">()</span> {</span><br><span class="line"> <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> age;</span><br><span class="line"> result = <span class="number">31</span> * result + (name != <span class="literal">null</span> ? name.hashCode() : <span class="number">0</span>);</span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><div class="tag-plugin colorful note" ><div class="body"><p>此时的运行结果</p></div></div><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240322094417769.png" alt="image-20240322094417769"></p><h3 id="演示代码-LinkedSet"><a href="#演示代码-LinkedSet" class="headerlink" title="演示代码 LinkedSet"></a>演示代码 LinkedSet</h3><p>LinkedSet 的优势就是能按照输入顺序输出</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test1</span><span class="params">()</span> {</span><br><span class="line"> <span class="comment">// LinkedHashSet 实现了记录添加元素的顺序,方便进行遍历</span></span><br><span class="line"> <span class="type">Set</span> <span class="variable">set</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">LinkedHashSet</span>();</span><br><span class="line"> <span class="type">Person</span> <span class="variable">person</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">10</span>,<span class="string">"xiaohua"</span>);</span><br><span class="line"> set.add(<span class="string">"test"</span>);</span><br><span class="line"> set.add(<span class="number">123</span>);</span><br><span class="line"> set.add(person);</span><br><span class="line"> System.out.println(set);</span><br><span class="line"> <span class="type">Iterator</span> <span class="variable">iterator</span> <span class="operator">=</span> set.iterator();</span><br><span class="line"> <span class="keyword">while</span> (iterator.hasNext()) {</span><br><span class="line"> System.out.println(iterator.next());</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240322112159406.png" alt="image-20240322112159406"></p><h3 id="演示代码-TreeSet"><a href="#演示代码-TreeSet" class="headerlink" title="演示代码 TreeSet"></a>演示代码 TreeSet</h3><p>对于 TreeSet 来说,最主要的用处是对插入元素的排序。例如对字符串进行排序</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test3</span><span class="params">()</span> {</span><br><span class="line"> <span class="type">Set</span> <span class="variable">set</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TreeSet</span>();</span><br><span class="line"></span><br><span class="line"> set.add(<span class="string">"BB"</span>);</span><br><span class="line"> set.add(<span class="string">"AA"</span>);</span><br><span class="line"> set.add(<span class="string">"GG"</span>);</span><br><span class="line"> set.add(<span class="string">"ZZ"</span>);</span><br><span class="line"> set.add(<span class="string">"YY"</span>);</span><br><span class="line"> <span class="comment">// 同一个 TreeSet 中不能添加不同类型的元素,以下添加 123 就会出错</span></span><br><span class="line"> set.add(<span class="number">123</span>);</span><br><span class="line"></span><br><span class="line"> System.out.println(set);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><div class="tag-plugin colorful note" ><div class="body"><p>运行结果</p></div></div><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240322104916658.png" alt="image-20240322104916658"></p><p>对于 TreeSet 添加自定义的实体类,进行排序的时候如何进行的判断,实际上是使用了自然排序和自定义排序,compareTo 和 compare 的返回值</p><p>以下代码中我重写了 User 中 compareTo 的方法,使得元素按照年龄排序,由于 TreeSet 采用的是红黑树的数据结构,存入的数据不能重复,所以说在按照年龄进行排序的时候,还需要别的元素进行辅助排序。</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test4</span><span class="params">()</span> {</span><br><span class="line"> <span class="type">Set</span> <span class="variable">set</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TreeSet</span>();</span><br><span class="line"></span><br><span class="line"> <span class="type">Person</span> <span class="variable">p1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">10</span>,<span class="string">"xiaohua"</span>);</span><br><span class="line"> <span class="type">Person</span> <span class="variable">p2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">12</span>,<span class="string">"xiaohua1"</span>);</span><br><span class="line"> <span class="type">Person</span> <span class="variable">p3</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">12</span>,<span class="string">"xiaohua2"</span>);</span><br><span class="line"> <span class="type">Person</span> <span class="variable">p4</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">13</span>,<span class="string">"xiaohua3"</span>);</span><br><span class="line"> <span class="type">Person</span> <span class="variable">p5</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">14</span>,<span class="string">"xiaohua4"</span>);</span><br><span class="line"></span><br><span class="line"> set.add(p1);</span><br><span class="line"> set.add(p2);</span><br><span class="line"> set.add(p3);</span><br><span class="line"> set.add(p4);</span><br><span class="line"> set.add(p5);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (Object o : set) {</span><br><span class="line"> System.out.println(o);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><div class="tag-plugin colorful note" ><div class="title">重写的</div><div class="body"><p>compareTo 方法</p></div></div><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> <span class="type">int</span> <span class="title function_">compareTo</span><span class="params">(Object o)</span> {</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">this</span> == o) {</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (o <span class="keyword">instanceof</span> Person) {</span><br><span class="line"> <span class="type">Person</span> <span class="variable">p</span> <span class="operator">=</span> (Person) o;</span><br><span class="line"> <span class="type">int</span> <span class="variable">number</span> <span class="operator">=</span> <span class="built_in">this</span>.age - p.age;</span><br><span class="line"> <span class="keyword">if</span> (number != <span class="number">0</span>){</span><br><span class="line"> <span class="keyword">return</span> number;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">this</span>.name.compareTo(p.name);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">RuntimeException</span>(<span class="string">"类型不匹配"</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><div class="tag-plugin colorful note" ><div class="body"><p>输出结果</p></div></div><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240322110733499.png" alt="image-20240322110733499"></p><p>对于不方便修改实体类中的比较方法的情况,可以直接给 TreeSet 一个 Comparator 方法</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test4</span><span class="params">()</span> {</span><br><span class="line"> <span class="type">Comparator</span> <span class="variable">comparator</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Comparator</span>() {</span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">compare</span><span class="params">(Object o1, Object o2)</span> {</span><br><span class="line"> <span class="keyword">if</span> (o1 <span class="keyword">instanceof</span> Person && o2 <span class="keyword">instanceof</span> Person) {</span><br><span class="line"> <span class="type">Person</span> <span class="variable">p1</span> <span class="operator">=</span> (Person) o1;</span><br><span class="line"> <span class="type">Person</span> <span class="variable">p2</span> <span class="operator">=</span> (Person) o2;</span><br><span class="line"></span><br><span class="line"> <span class="type">int</span> <span class="variable">value</span> <span class="operator">=</span> p1.getName().compareTo(p2.getName());</span><br><span class="line"> <span class="keyword">if</span> (value != <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">return</span> value;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">return</span> p1.getAge() - p2.getAge();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">RuntimeException</span>(<span class="string">"数据类型不匹配"</span>);</span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line"></span><br><span class="line"> <span class="type">Set</span> <span class="variable">set</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TreeSet</span>(comparator);</span><br><span class="line"></span><br><span class="line"> <span class="type">Person</span> <span class="variable">p1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">10</span>,<span class="string">"A1"</span>);</span><br><span class="line"> <span class="type">Person</span> <span class="variable">p2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">13</span>,<span class="string">"A1"</span>);</span><br><span class="line"> <span class="type">Person</span> <span class="variable">p3</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">10</span>,<span class="string">"B"</span>);</span><br><span class="line"> <span class="type">Person</span> <span class="variable">p4</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">13</span>,<span class="string">"C"</span>);</span><br><span class="line"> <span class="type">Person</span> <span class="variable">p5</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">13</span>,<span class="string">"D"</span>);</span><br><span class="line"></span><br><span class="line"> set.add(p1);</span><br><span class="line"> set.add(p2);</span><br><span class="line"> set.add(p3);</span><br><span class="line"> set.add(p4);</span><br><span class="line"> set.add(p5);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (Object o : set) {</span><br><span class="line"> System.out.println(o);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240322111924107.png" alt="image-20240322111924107"></p><h3 id="Set-综合测试"><a href="#Set-综合测试" class="headerlink" title="Set 综合测试"></a>Set 综合测试</h3><h4 id="综合测试一-1"><a href="#综合测试一-1" class="headerlink" title="综合测试一"></a>综合测试一</h4><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240322112623167.png" alt="image-20240322112623167"></p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test5</span><span class="params">()</span> {</span><br><span class="line"> <span class="type">List</span> <span class="variable">list</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ArrayList</span>();</span><br><span class="line"></span><br><span class="line"> list.add(<span class="number">11</span>);</span><br><span class="line"> list.add(<span class="number">11</span>);</span><br><span class="line"> list.add(<span class="number">11</span>);</span><br><span class="line"> list.add(<span class="number">11</span>);</span><br><span class="line"> list.add(<span class="number">22</span>);</span><br><span class="line"> list.add(<span class="number">22</span>);</span><br><span class="line"> list.add(<span class="number">22</span>);</span><br><span class="line"> list.add(<span class="number">22</span>);</span><br><span class="line"> list.add(<span class="number">33</span>);</span><br><span class="line"> list.add(<span class="number">33</span>);</span><br><span class="line"> list.add(<span class="number">33</span>);</span><br><span class="line"> list.add(<span class="number">33</span>);</span><br><span class="line"></span><br><span class="line"> System.out.println(list);</span><br><span class="line"> System.out.println(duplicateList(list));</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> List <span class="title function_">duplicateList</span><span class="params">(List list)</span>{</span><br><span class="line"> <span class="type">Set</span> <span class="variable">set</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">LinkedHashSet</span>(list);</span><br><span class="line"> <span class="type">List</span> <span class="variable">new_list</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ArrayList</span>(set);</span><br><span class="line"> <span class="keyword">return</span> new_list;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240322113252614.png" alt="image-20240322113252614"></p><h4 id="综合测试二-1"><a href="#综合测试二-1" class="headerlink" title="综合测试二"></a>综合测试二</h4><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240322113353691.png" alt="image-20240322113353691"></p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test7</span><span class="params">()</span> {</span><br><span class="line"> <span class="type">Set</span> <span class="variable">set</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">HashSet</span>();</span><br><span class="line"> <span class="keyword">while</span> (set.size() < <span class="number">10</span>) {</span><br><span class="line"> <span class="type">int</span> <span class="variable">randomNumber</span> <span class="operator">=</span> (<span class="type">int</span>)(Math.random() * <span class="number">20</span>) + <span class="number">1</span>;</span><br><span class="line"> set.add(randomNumber);</span><br><span class="line"> }</span><br><span class="line"> System.out.println(set);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240322113754482.png" alt="image-20240322113754482"></p><h2 id="Map-常用方法"><a href="#Map-常用方法" class="headerlink" title="Map 常用方法"></a>Map 常用方法</h2><h3 id="Map-不同类的区别"><a href="#Map-不同类的区别" class="headerlink" title="Map 不同类的区别"></a>Map 不同类的区别</h3><div class="tag-plugin colorful note" ><div class="title">java.util.Map:</div><div class="body"><p>存储一对一对的数据,也就是 key-value 键值对</p></div></div><ul><li>HashMap: 主要实现类,线程不安全的,效率高的。可以添加 null 的 key 与 value。底层使用数组,单向链表,红黑树的数据结构。<ul><li>LinkedMap:HashMap 的子类,添加了一对双向链表,记录添加的元素的先后顺序。</li></ul></li><li>TreeMap: 底层使用红黑树的数据结构,可以根据添加的 key 元素指定的属性大小进行遍历。</li><li>Hashtable: 古老实现类,线程安全的,效率低的。不可以添加 null 的 key 和 value。底层使用数组,单向链表的数据结构。<ul><li>Properties:</li></ul></li></ul><h3 id="演示代码-HashMap"><a href="#演示代码-HashMap" class="headerlink" title="演示代码 HashMap"></a>演示代码 HashMap</h3><p>在 HashMap 中,key 是不能够相同的,并且是无序的。而 value 是可以相同的,但由于 value 是 key 的映射,key 是无序的,value 也是无序的。</p><ul><li><p>HashMap 中所有的 key 构成了一个 Set 集合,key 所在的类,需要重写 equals 和 HashCode 方法。</p></li><li><p>HashMap 中所有的 value 构成了一个Collection 集合,value 所在的类,需要重写 equals 方法。</p></li></ul><h4 id="增删改查"><a href="#增删改查" class="headerlink" title="增删改查"></a>增删改查</h4><div class="tag-plugin colorful note" ><div class="body"><p>put、putAll、remove、put、get</p></div></div><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test</span><span class="params">()</span> {</span><br><span class="line"> <span class="comment">// 增</span></span><br><span class="line"> <span class="type">Map</span> <span class="variable">map</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">HashMap</span>();</span><br><span class="line"> <span class="type">Person</span> <span class="variable">p1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">10</span>,<span class="string">"xiaoming"</span>);</span><br><span class="line"></span><br><span class="line"> map.put(<span class="string">"AA"</span>, <span class="number">123</span>);</span><br><span class="line"> map.put(<span class="string">"BB"</span>, <span class="number">13</span>);</span><br><span class="line"> map.put(<span class="string">"CC"</span>, <span class="number">23</span>);</span><br><span class="line"></span><br><span class="line"> map.put(p1, <span class="number">55</span>);</span><br><span class="line"></span><br><span class="line"> System.out.println(map);</span><br><span class="line"></span><br><span class="line"> <span class="type">Map</span> <span class="variable">map1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">HashMap</span>();</span><br><span class="line"> map1.putAll(map);</span><br><span class="line"></span><br><span class="line"> System.out.println(map1);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240322175056275.png" alt="image-20240322175056275"></p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test2</span><span class="params">()</span> {</span><br><span class="line"> <span class="comment">// 删 && 改 && 查</span></span><br><span class="line"> <span class="type">Map</span> <span class="variable">map</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">HashMap</span>();</span><br><span class="line"> <span class="type">Person</span> <span class="variable">p1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">10</span>,<span class="string">"xiaoming"</span>);</span><br><span class="line"></span><br><span class="line"> map.put(<span class="string">"AA"</span>, <span class="number">123</span>);</span><br><span class="line"> map.put(<span class="string">"BB"</span>, <span class="number">13</span>);</span><br><span class="line"> map.put(<span class="string">"CC"</span>, <span class="number">23</span>);</span><br><span class="line"></span><br><span class="line"> map.put(p1, <span class="number">55</span>);</span><br><span class="line"></span><br><span class="line"> <span class="type">Object</span> <span class="variable">value</span> <span class="operator">=</span> map.remove(<span class="string">"BB"</span>);</span><br><span class="line"> System.out.println(value);</span><br><span class="line"></span><br><span class="line"> map.put(<span class="string">"CC"</span>, <span class="number">15</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// value</span></span><br><span class="line"> System.out.println(map.get(<span class="string">"CC"</span>));</span><br><span class="line"></span><br><span class="line"> System.out.println(map);</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="长度-遍历"><a href="#长度-遍历" class="headerlink" title="长度 遍历"></a>长度 遍历</h4><div class="tag-plugin colorful note" ><div class="body"><p>size、keySet、values、entrySet</p></div></div><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test3</span><span class="params">()</span> {</span><br><span class="line"> <span class="type">Map</span> <span class="variable">map</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">HashMap</span>();</span><br><span class="line"> <span class="type">Person</span> <span class="variable">p1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">10</span>, <span class="string">"xiaoming"</span>);</span><br><span class="line"></span><br><span class="line"> map.put(<span class="string">"AA"</span>, <span class="number">123</span>);</span><br><span class="line"> map.put(<span class="string">"BB"</span>, <span class="number">13</span>);</span><br><span class="line"> map.put(<span class="string">"CC"</span>, <span class="number">23</span>);</span><br><span class="line"></span><br><span class="line"> map.put(p1, <span class="number">55</span>);</span><br><span class="line"></span><br><span class="line"> System.out.println(map.size());</span><br><span class="line"></span><br><span class="line"> <span class="comment">// keySet 遍历 key</span></span><br><span class="line"> <span class="type">Set</span> <span class="variable">keySet</span> <span class="operator">=</span> map.keySet();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (Object o :keySet) {</span><br><span class="line"> System.out.println(o);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// values 遍历 value</span></span><br><span class="line"> <span class="type">Collection</span> <span class="variable">values</span> <span class="operator">=</span> map.values();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (Object o : values) {</span><br><span class="line"> System.out.println(o);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// entrySet 遍历 entry 键值对</span></span><br><span class="line"> <span class="type">Set</span> <span class="variable">entrySet</span> <span class="operator">=</span> map.entrySet();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (Object o :entrySet) {</span><br><span class="line"> System.out.println(o);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240322175647489.png" alt="image-20240322175647489"></p><h3 id="演示代码-TreeMap"><a href="#演示代码-TreeMap" class="headerlink" title="演示代码 TreeMap"></a>演示代码 TreeMap</h3><p>对于 TreeMap 来说,和 TreeSet 一样,重要的是自然排序和定制排序的写法。</p><div class="tag-plugin colorful note" ><div class="title">自然排序,根据实体类中的</div><div class="body"><p>compareTo 方法</p></div></div><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test2</span><span class="params">()</span> {</span><br><span class="line"> <span class="comment">// 自然排序</span></span><br><span class="line"> <span class="type">Map</span> <span class="variable">map</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TreeMap</span>();</span><br><span class="line"> <span class="type">Person</span> <span class="variable">p1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">10</span>, <span class="string">"zeus"</span>);</span><br><span class="line"> <span class="type">Person</span> <span class="variable">p2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">14</span>, <span class="string">"faker"</span>);</span><br><span class="line"> <span class="type">Person</span> <span class="variable">p3</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">12</span>, <span class="string">"jerry"</span>);</span><br><span class="line"> <span class="type">Person</span> <span class="variable">p4</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">12</span>, <span class="string">"tom"</span>);</span><br><span class="line"></span><br><span class="line"> map.put(p1, <span class="number">12</span>);</span><br><span class="line"> map.put(p2, <span class="number">63</span>);</span><br><span class="line"> map.put(p3, <span class="number">42</span>);</span><br><span class="line"> map.put(p4, <span class="number">31</span>);</span><br><span class="line"></span><br><span class="line"> <span class="type">Set</span> <span class="variable">entry</span> <span class="operator">=</span> map.entrySet();</span><br><span class="line"> <span class="keyword">for</span> (Object o : entry) {</span><br><span class="line"> System.out.println(o);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240322183609548.png" alt="image-20240322183609548"></p><div class="tag-plugin colorful note" ><div class="title">定制排序,TreeMap</div><div class="body"><p>同样可以传入一个 comparator,在这里 comparator 中我们可以自定义按照类的什么属性进行排序</p></div></div><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test1</span><span class="params">()</span> {</span><br><span class="line"></span><br><span class="line"> <span class="type">Comparator</span> <span class="variable">comparator</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Comparator</span>() {</span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">compare</span><span class="params">(Object o1, Object o2)</span> {</span><br><span class="line"> <span class="keyword">if</span> (o1 <span class="keyword">instanceof</span> Person && o2 <span class="keyword">instanceof</span> Person) {</span><br><span class="line"> <span class="type">Person</span> <span class="variable">p1</span> <span class="operator">=</span> (Person) o1;</span><br><span class="line"> <span class="type">Person</span> <span class="variable">p2</span> <span class="operator">=</span> (Person) o2;</span><br><span class="line"></span><br><span class="line"> <span class="type">int</span> <span class="variable">value</span> <span class="operator">=</span> p1.getName().compareTo(p2.getName());</span><br><span class="line"> <span class="keyword">if</span> (value != <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">return</span> value;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">return</span> p1.getAge() - p2.getAge();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">RuntimeException</span>(<span class="string">"数据类型不匹配"</span>);</span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line"></span><br><span class="line"> <span class="type">Map</span> <span class="variable">map</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TreeMap</span>(comparator);</span><br><span class="line"> <span class="type">Person</span> <span class="variable">p1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">10</span>, <span class="string">"zeus"</span>);</span><br><span class="line"> <span class="type">Person</span> <span class="variable">p2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">14</span>, <span class="string">"faker"</span>);</span><br><span class="line"> <span class="type">Person</span> <span class="variable">p3</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">12</span>, <span class="string">"jerry"</span>);</span><br><span class="line"> <span class="type">Person</span> <span class="variable">p4</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="number">12</span>, <span class="string">"tom"</span>);</span><br><span class="line"></span><br><span class="line"> map.put(p1, <span class="number">12</span>);</span><br><span class="line"> map.put(p2, <span class="number">63</span>);</span><br><span class="line"> map.put(p3, <span class="number">42</span>);</span><br><span class="line"> map.put(p4, <span class="number">31</span>);</span><br><span class="line"></span><br><span class="line"> <span class="type">Set</span> <span class="variable">entry</span> <span class="operator">=</span> map.entrySet();</span><br><span class="line"> <span class="keyword">for</span> (Object o : entry) {</span><br><span class="line"> System.out.println(o);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240322183750711.png" alt="image-20240322183750711"></p><h3 id="演示代码-Properties"><a href="#演示代码-Properties" class="headerlink" title="演示代码 Properties"></a>演示代码 Properties</h3><p>Properties 多用于在文件的 IO 流中,使用 Properties 读取配置文件可以有效的提高代码的可维护性。</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test1</span><span class="params">()</span> <span class="keyword">throws</span> IOException {</span><br><span class="line"> <span class="type">File</span> <span class="variable">file</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">File</span>(<span class="string">"config.properties"</span>);</span><br><span class="line"> System.out.println(file.getAbsolutePath());</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="type">FileInputStream</span> <span class="variable">fileInputStream</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">FileInputStream</span>(file);</span><br><span class="line"> <span class="type">Properties</span> <span class="variable">properties</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Properties</span>();</span><br><span class="line"> properties.load(fileInputStream);</span><br><span class="line"></span><br><span class="line"> System.out.println(properties.get(<span class="string">"name"</span>));</span><br><span class="line"> System.out.println(properties.get(<span class="string">"password"</span>));</span><br><span class="line"></span><br><span class="line"> fileInputStream.close();</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240322194853229.png" alt="image-20240322194853229"></p><h2 id="Collections-工具类"><a href="#Collections-工具类" class="headerlink" title="Collections 工具类"></a>Collections 工具类</h2><h3 id="排序操作"><a href="#排序操作" class="headerlink" title="排序操作"></a>排序操作</h3><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 排序操作</span></span><br><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test1</span><span class="params">()</span> {</span><br><span class="line"> <span class="type">List</span> <span class="variable">list</span> <span class="operator">=</span> Arrays.asList(<span class="number">1</span>,<span class="number">42</span>,<span class="number">32</span>,<span class="number">43</span>,<span class="number">45</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">53</span>,<span class="number">23</span>,<span class="number">31</span>,<span class="number">45</span>,<span class="number">98</span>);</span><br><span class="line"> System.out.println(list);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// reverse 反转 list 中元素的顺序</span></span><br><span class="line"> Collections.reverse(list);</span><br><span class="line"> System.out.println(list);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// shuffle 对 list 中的元素进行随机排序</span></span><br><span class="line"> Collections.shuffle(list);</span><br><span class="line"> System.out.println(list);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// sort 对 list 中的元素进行自然排序</span></span><br><span class="line"> Collections.sort(list);</span><br><span class="line"> System.out.println(list);</span><br><span class="line"></span><br><span class="line"> <span class="type">Comparator</span> <span class="variable">comparator</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Comparator</span>() {</span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">compare</span><span class="params">(Object o1, Object o2)</span> {</span><br><span class="line"> <span class="keyword">if</span> (o1 <span class="keyword">instanceof</span> Integer && o2 <span class="keyword">instanceof</span> Integer) {</span><br><span class="line"> <span class="type">Integer</span> <span class="variable">i1</span> <span class="operator">=</span> (Integer) o1;</span><br><span class="line"> <span class="type">Integer</span> <span class="variable">i2</span> <span class="operator">=</span> (Integer) o2;</span><br><span class="line"> <span class="keyword">return</span> -(i1.intValue() - i2.intValue());</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">RuntimeException</span>(<span class="string">"类型不匹配"</span>);</span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line"> <span class="comment">// sort 对 list 中的元素进行定制排序</span></span><br><span class="line"> Collections.sort(list, comparator);</span><br><span class="line"> System.out.println(list);</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240322202849252.png" alt="image-20240322202849252"></p><h3 id="查找操作"><a href="#查找操作" class="headerlink" title="查找操作"></a>查找操作</h3><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 查找操作</span></span><br><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test2</span><span class="params">()</span> {</span><br><span class="line"> <span class="type">List</span> <span class="variable">list</span> <span class="operator">=</span> Arrays.asList(<span class="number">1</span>, <span class="number">42</span>, <span class="number">1</span>, <span class="number">43</span>, <span class="number">45</span>, <span class="number">1</span>, <span class="number">4</span>, <span class="number">53</span>, <span class="number">23</span>, <span class="number">31</span>, <span class="number">45</span>, <span class="number">98</span>);</span><br><span class="line"> System.out.println(list);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// max 获取 list 中的最大值</span></span><br><span class="line"> <span class="type">Object</span> <span class="variable">max</span> <span class="operator">=</span> Collections.max(list);</span><br><span class="line"> System.out.println(max);</span><br><span class="line"></span><br><span class="line"> <span class="type">Comparator</span> <span class="variable">comparator</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Comparator</span>() {</span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">compare</span><span class="params">(Object o1, Object o2)</span> {</span><br><span class="line"> <span class="keyword">if</span> (o1 <span class="keyword">instanceof</span> Integer && o2 <span class="keyword">instanceof</span> Integer) {</span><br><span class="line"> <span class="type">Integer</span> <span class="variable">i1</span> <span class="operator">=</span> (Integer) o1;</span><br><span class="line"> <span class="type">Integer</span> <span class="variable">i2</span> <span class="operator">=</span> (Integer) o2;</span><br><span class="line"> <span class="keyword">return</span> -(i1.intValue() - i2.intValue());</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">RuntimeException</span>(<span class="string">"类型不匹配"</span>);</span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line"> <span class="comment">// max 同样可以接受一个 comparator,因为它获取的逻辑是排序后的最右边的数据,如果 comparator 传入的是倒序,最大值反而是最小值</span></span><br><span class="line"> <span class="type">Object</span> <span class="variable">max1</span> <span class="operator">=</span> Collections.max(list, comparator);</span><br><span class="line"> System.out.println(max1);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// frequency 返回 list 中指定元素出现的个数</span></span><br><span class="line"> <span class="type">int</span> <span class="variable">number</span> <span class="operator">=</span> Collections.frequency(list, <span class="number">1</span>);</span><br><span class="line"> System.out.println(number);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240322202931047.png" alt="image-20240322202931047"></p><h3 id="复制,替换操作"><a href="#复制,替换操作" class="headerlink" title="复制,替换操作"></a>复制,替换操作</h3><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test3</span><span class="params">()</span> {</span><br><span class="line"> <span class="type">List</span> <span class="variable">list</span> <span class="operator">=</span> Arrays.asList(<span class="number">1</span>, <span class="number">42</span>, <span class="number">1</span>, <span class="number">43</span>, <span class="number">45</span>, <span class="number">1</span>, <span class="number">4</span>, <span class="number">53</span>, <span class="number">23</span>, <span class="number">31</span>, <span class="number">45</span>, <span class="number">98</span>);</span><br><span class="line"> System.out.println(list);</span><br><span class="line"> <span class="comment">// copy 将一个 list 赋值到一个新的 list,但是新的 list 的 size 必须大于等于旧的 list</span></span><br><span class="line"> <span class="type">List</span> <span class="variable">new_list</span> <span class="operator">=</span> Arrays.asList(<span class="keyword">new</span> <span class="title class_">Object</span>[list.size()]);</span><br><span class="line"> Collections.copy(new_list, list);</span><br><span class="line"> System.out.println(new_list);</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240323105340302.png" alt="image-20240323105340302"></p><div class="tag-plugin colorful note" ><div class="title">unmodifiableList</div><div class="body"><p>生成一个只读格式的 list</p></div></div><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test4</span><span class="params">()</span> {</span><br><span class="line"> <span class="type">List</span> <span class="variable">list</span> <span class="operator">=</span> Arrays.asList(<span class="number">1</span>, <span class="number">42</span>, <span class="number">1</span>, <span class="number">43</span>, <span class="number">45</span>, <span class="number">1</span>, <span class="number">4</span>, <span class="number">53</span>, <span class="number">23</span>, <span class="number">31</span>, <span class="number">45</span>, <span class="number">98</span>);</span><br><span class="line"> System.out.println(list);</span><br><span class="line"> <span class="type">List</span> <span class="variable">new_list</span> <span class="operator">=</span> Collections.unmodifiableList(list);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// unmodifiableList 将 list 转换成一个新的只读的 list</span></span><br><span class="line"> new_list.add(<span class="number">12</span>); </span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="/../../img/Java%E7%9A%84%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/image-20240323111052535.png" alt="image-20240323111052535"></p><hr><p><img src="/../../assets/user/about_me.jpg" alt="关于我"></p>]]></content>
<summary type="html">Java的集合框架相关内容</summary>
<category term="学习笔记" scheme="https://blog.sakurasep.site/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
<category term="Java" scheme="https://blog.sakurasep.site/tags/Java/"/>
<category term="学习笔记" scheme="https://blog.sakurasep.site/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
<category term="集合框架" scheme="https://blog.sakurasep.site/tags/%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/"/>
</entry>
<entry>
<title>算法通关村第一关-链表白银挑战笔记</title>
<link href="https://blog.sakurasep.site/posts/Yupi-01-Second/"/>
<id>https://blog.sakurasep.site/posts/Yupi-01-Second/</id>
<published>2024-03-20T06:30:46.000Z</published>
<updated>2024-03-20T06:32:12.000Z</updated>
<content type="html"><![CDATA[<div class="tag-plugin quot"><p class="content" type="text"><span class="empty"></span><span class="text">题目练习</span><span class="empty"></span></p></div><h2 id="JZ52-两个链表的第一个公共结点"><a href="#JZ52-两个链表的第一个公共结点" class="headerlink" title="JZ52 两个链表的第一个公共结点"></a>JZ52 两个链表的第一个公共结点</h2><h3 id="描述"><a href="#描述" class="headerlink" title="描述"></a>描述</h3><p>输入两个无环的单向链表,找出它们的第一个公共结点,如果没有公共节点则返回空。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)</p><p>数据范围: $n \leq 1000$</p><p>要求:$O(1)$,时间复杂度 $O(1)$</p><p>例如,输入{1,2,3},{4,5},{6,7}时,两个无环的单向链表的结构如下图所示:</p><p><img src="/../../img/%E9%B1%BC%E7%9A%AE%E7%9A%84%E7%AE%97%E6%B3%95%E8%AE%AD%E7%BB%83%E8%90%A5_Day01_%E7%99%BD%E9%93%B6/394BB7AFD5CEA3DC64D610F62E6647A6-20240320145912324.png" alt="img"></p><p>可以看到它们的第一个公共结点的结点值为6,所以返回结点值为6的结点。</p><h3 id="输入描述"><a href="#输入描述" class="headerlink" title="输入描述"></a>输入描述</h3><p>输入分为是3段,第一段是第一个链表的非公共部分,第二段是第二个链表的非公共部分,第三段是第一个链表和第二个链表的公共部分。 后台会将这3个参数组装为两个链表,并将这两个链表对应的头节点传入到函数FindFirstCommonNode里面,用户得到的输入只有pHead1和pHead2。</p><h3 id="返回值描述"><a href="#返回值描述" class="headerlink" title="返回值描述"></a>返回值描述</h3><p>返回传入的pHead1和pHead2的第一个公共结点,后台会打印以该节点为头节点的链表。</p><h3 id="样例"><a href="#样例" class="headerlink" title="样例"></a>样例</h3><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入: {1,2,3},{4,5},{6,7}</span><br><span class="line">输出: {6,7}</span><br><span class="line"></span><br><span class="line">输入: {1},{2,3},{}</span><br><span class="line">输出: {}</span><br></pre></td></tr></table></figure><hr><div class="tag-plugin link dis-select"><a class="link-card rich" title="欢迎关注我的其他平台" href="../../assets/user/about_me.jpg" cardlink api="https://site-info-api-git-main-sakurasep.vercel.app/api/v1?url=https://blog.sakurasep.site/assets/user/about_me.jpg" autofill="icon,desc"><div class="top"><div class="lazy img" data-bg="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/link/8f277b4ee0ecd.svg"></div><span class="cap link footnote">https://blog.sakurasep.site/assets/user/about_me.jpg</span></div><div class="bottom"><span class="title">欢迎关注我的其他平台</span><span class="cap desc footnote"></span></div></a></div>]]></content>
<summary type="html">记录自己的算法学习日常</summary>
<category term="学习笔记" scheme="https://blog.sakurasep.site/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
<category term="Java" scheme="https://blog.sakurasep.site/tags/Java/"/>
<category term="学习笔记" scheme="https://blog.sakurasep.site/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
<category term="鱼皮的算法通关村" scheme="https://blog.sakurasep.site/tags/%E9%B1%BC%E7%9A%AE%E7%9A%84%E7%AE%97%E6%B3%95%E9%80%9A%E5%85%B3%E6%9D%91/"/>
</entry>
<entry>
<title>算法通关村第一关-链表青铜挑战笔记</title>
<link href="https://blog.sakurasep.site/posts/Yupi-01-First/"/>
<id>https://blog.sakurasep.site/posts/Yupi-01-First/</id>
<published>2024-03-19T08:30:46.000Z</published>
<updated>2024-03-18T16:00:00.000Z</updated>
<content type="html"><![CDATA[<div class="tag-plugin colorful note" ><div class="title">重要说明</div><div class="body"><p>图片与实际代码无关,这里引用的图片有很大一部分是把头结点当做链表的第一个元素,我写的示例代码不将头结点视为第一个元素</p></div></div><h2 id="链表的概念"><a href="#链表的概念" class="headerlink" title="链表的概念"></a>链表的概念</h2><p>简单来说就是说从头结点出发,每一个结点都有一个指向后继结点的 next 指针,表中最后一个元素的 next 指向 null</p><p><img src="/../../img/%E9%B1%BC%E7%9A%AE%E7%9A%84%E7%AE%97%E6%B3%95%E8%AE%AD%E7%BB%83%E8%90%A5_Day01/1688996783296-c6398d73-228e-4fc6-912a-6a97f832737a.png" alt="img"></p><h2 id="链表的构造结构"><a href="#链表的构造结构" class="headerlink" title="链表的构造结构"></a>链表的构造结构</h2><p>这里我们使用 Java 来创建单链表的基本结构,这里是 Leetcode 常用的构建方法</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ListNode</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="type">int</span> val;</span><br><span class="line"> <span class="keyword">public</span> ListNode next;</span><br><span class="line"> ListNode(<span class="type">int</span> x) {</span><br><span class="line"> val = x;</span><br><span class="line"> next = <span class="literal">null</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="type">ListNode</span> <span class="variable">node</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ListNode</span>(<span class="number">1</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>对于简化的构造方法,你应该使用以下的代码对结点进行修改赋值</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line">node.next = new_node;</span><br><span class="line">node.val = number;</span><br></pre></td></tr></table></figure><p>为了练习 Java 的面向对象特性,这里我不用简化的构造方法。</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ListNode</span> {</span><br><span class="line"> <span class="comment">// 链表数据</span></span><br><span class="line"> <span class="keyword">private</span> <span class="type">int</span> data;</span><br><span class="line"> <span class="comment">// 链表指针</span></span><br><span class="line"> <span class="keyword">private</span> ListNode next;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">ListNode</span><span class="params">(<span class="type">int</span> data)</span> {</span><br><span class="line"> <span class="built_in">this</span>.data = data;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">getData</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> data;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setData</span><span class="params">(<span class="type">int</span> data)</span> {</span><br><span class="line"> <span class="built_in">this</span>.data = data;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> ListNode <span class="title function_">getNext</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> next;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setNext</span><span class="params">(ListNode next)</span> {</span><br><span class="line"> <span class="built_in">this</span>.next = next;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>而这种方式的修改赋值就是调用 get 和 set 办法</p><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">node.setNext(new_node);</span><br><span class="line">node.setNext(new_node.getNext());</span><br><span class="line">node.setData(number);</span><br><span class="line">node.getData();</span><br></pre></td></tr></table></figure><h2 id="链表的增删改查-增"><a href="#链表的增删改查-增" class="headerlink" title="链表的增删改查 - 增"></a>链表的增删改查 - 增</h2><p>任何数据结构都避免不了的最基础的操作,首先来看最基础的构建链表。</p><p>对于单链表来说,构建链表有两种方式,一种是头插法,一种是尾插法。</p><h3 id="头插法"><a href="#头插法" class="headerlink" title="头插法"></a>头插法</h3><p>头插法简单说来就是逆序插入,每次插入将新节点的 next 指向头结点的 next,然后将头结点的 next 指向新结点。</p><p><img src="/../../img/%E9%B1%BC%E7%9A%AE%E7%9A%84%E7%AE%97%E6%B3%95%E8%AE%AD%E7%BB%83%E8%90%A5_Day01/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Iqx6Ze05Y2K55uY5qOL,size_12,color_FFFFFF,t_70,g_se,x_16.png" alt="头插法"></p><div class="tag-plugin colorful note" ><div class="body"><p>示例代码</p></div></div><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 头插法插入新结点</span></span><br><span class="line"><span class="keyword">public</span> ListNode <span class="title function_">headInsert</span><span class="params">(ListNode head, ListNode node)</span> {</span><br><span class="line"> node.setNext(head.getNext());</span><br><span class="line"> head.setNext(node);</span><br><span class="line"> <span class="keyword">return</span> head;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="尾插法"><a href="#尾插法" class="headerlink" title="尾插法"></a>尾插法</h3><p>尾插法简单来说就是顺序插入,每次插入都将此时的“头结点”的 next 改成新结点 node,然后将新结点 node 座位链表尾部,next 改为 null。和头插法不一样的是,尾插法每次返回的结点并不是头结点,所以在构建链表的时候记得保存头结点的信息。</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 尾插法插入新结点</span></span><br><span class="line"><span class="keyword">public</span> ListNode <span class="title function_">tailInsert</span><span class="params">(ListNode head, ListNode node)</span> {</span><br><span class="line"> head.setNext(node);</span><br><span class="line"> node.setNext(<span class="literal">null</span>);</span><br><span class="line"> <span class="keyword">return</span> node;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="构建链表"><a href="#构建链表" class="headerlink" title="构建链表"></a>构建链表</h3><p>这段代码展示了在测试类中初始化链表的全过程,这里我用 L 结点保存尾插时头结点的信息,后续会用到。</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line"> <span class="type">ListNodeTest</span> <span class="variable">test</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ListNodeTest</span>();</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">// 初始化头结点</span></span><br><span class="line"> <span class="type">ListNode</span> <span class="variable">head</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ListNode</span>(-<span class="number">1</span>);</span><br><span class="line"> head.setNext(<span class="literal">null</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 复制头结点</span></span><br><span class="line"> <span class="type">ListNode</span> <span class="variable">L</span> <span class="operator">=</span> head;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 构建链表</span></span><br><span class="line"> test.initList(head, <span class="number">5</span>);</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 构建新链表</span></span><br><span class="line"> <span class="keyword">public</span> ListNode <span class="title function_">initList</span><span class="params">(ListNode head, <span class="type">int</span> number)</span> {</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i < number; i++) {</span><br><span class="line"> <span class="type">ListNode</span> <span class="variable">new_node</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ListNode</span>(i);</span><br><span class="line"> <span class="comment">// 头插法</span></span><br><span class="line">head = headInsert(head, new_node);</span><br><span class="line"> <span class="comment">// 尾插法</span></span><br><span class="line"> head = tailInsert(head, new_node);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> head;</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><h3 id="综合练习"><a href="#综合练习" class="headerlink" title="综合练习"></a>综合练习</h3><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 具体位置插入结点</span></span><br><span class="line"><span class="keyword">public</span> ListNode <span class="title function_">insertNode</span><span class="params">(ListNode head, ListNode node, <span class="type">int</span> position)</span> {</span><br><span class="line"> <span class="comment">// 头结点为空,意味着链表为空,故此时返回要插入的结点</span></span><br><span class="line"> <span class="keyword">if</span> (head == <span class="literal">null</span>) {</span><br><span class="line"> <span class="keyword">return</span> node;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// 检查插入的位置是否越界, 返回头结点等待下次插入</span></span><br><span class="line"> <span class="type">int</span> <span class="variable">length</span> <span class="operator">=</span> getListLength(head);</span><br><span class="line"> <span class="keyword">if</span> (position > length + <span class="number">2</span> || position < <span class="number">1</span>) {</span><br><span class="line"> System.out.println(<span class="string">"位置参数越界"</span>);</span><br><span class="line"> <span class="keyword">return</span> head;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 遍历找到前驱节点,使用头插法插入新结点</span></span><br><span class="line"> <span class="type">ListNode</span> <span class="variable">P</span> <span class="operator">=</span> head;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span> ; i < position; i++) {</span><br><span class="line"> P = P.getNext();</span><br><span class="line"> }</span><br><span class="line"> headInsert(P, node);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> head;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><div class="tag-plugin colorful note" ><div class="body"><p>运行结果</p></div></div><p><img src="/../../img/%E9%B1%BC%E7%9A%AE%E7%9A%84%E7%AE%97%E6%B3%95%E8%AE%AD%E7%BB%83%E8%90%A5_Day01/image-20240320101925597.png" alt="image-20240320101925597"></p><h2 id="链表的增删改查-查"><a href="#链表的增删改查-查" class="headerlink" title="链表的增删改查 - 查"></a>链表的增删改查 - 查</h2><p>先来看看链表的查询,对于单链表来说,一定是从头结点逐个向后访问,因此,头结点是一定不可以丢掉的。</p><p>我们写一个遍历函数,同时输出链表长度</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 获取链表长度</span></span><br><span class="line"><span class="keyword">public</span> <span class="type">int</span> <span class="title function_">getListLength</span><span class="params">(ListNode head)</span> {</span><br><span class="line"> <span class="type">int</span> <span class="variable">length</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"> <span class="type">ListNode</span> <span class="variable">node</span> <span class="operator">=</span> head;</span><br><span class="line"> <span class="keyword">while</span>(node != <span class="literal">null</span>) {</span><br><span class="line"> length++;</span><br><span class="line"> System.out.printf(<span class="string">"%d "</span>, node.getData());</span><br><span class="line"> node = node.getNext();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> length;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>这里可以看出,传入遍历函数的结点不同,因为头插法返回的都是头结点,此时的 head 可以说是没变,直接传入。而对于尾插法来说,我这里的处理是用了一个 L 结点存储头结点信息,所以传入遍历函数的是 L 结点。</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 头插法获取链表可以直接传入返回的 head,因为头插法每次返回的都是头结点</span></span><br><span class="line"><span class="comment">// 尾插法获取链表需要传入之前复制的头结点信息,因为尾插法每次返回的是结点</span></span><br><span class="line">System.out.println(<span class="string">"链表长度为: "</span> + (test.getListLength(head) - <span class="number">1</span>));</span><br><span class="line">System.out.println(<span class="string">"链表长度为: "</span> + (test.getListLength(L) - <span class="number">1</span>));</span><br></pre></td></tr></table></figure><h2 id="链表的增删改查-删"><a href="#链表的增删改查-删" class="headerlink" title="链表的增删改查 - 删"></a>链表的增删改查 - 删</h2><p>对于删除来说还是挺好办的,处理以下特殊位置,其他位置遍历到前驱结点,然后将前驱结点的 next 直接设置为删除结点的后置结点。</p><h3 id="表头"><a href="#表头" class="headerlink" title="表头"></a>表头</h3><p>这种情况只需要 <code>head = head.getNext();</code></p><p><img src="/../../img/%E9%B1%BC%E7%9A%AE%E7%9A%84%E7%AE%97%E6%B3%95%E8%AE%AD%E7%BB%83%E8%90%A5_Day01/1688480747297-f69945b0-d7de-492f-b98f-0fc05fa0aec4.png" alt="img"></p><h3 id="表尾和其他"><a href="#表尾和其他" class="headerlink" title="表尾和其他"></a>表尾和其他</h3><p>遍历到删除结点的前驱就可以进行操作了</p><p><img src="/../../img/%E9%B1%BC%E7%9A%AE%E7%9A%84%E7%AE%97%E6%B3%95%E8%AE%AD%E7%BB%83%E8%90%A5_Day01/1688480890507-49487e33-103a-425f-a6cc-3aa3b0c7c9fd.png" alt="img"></p><p><img src="/../../img/%E9%B1%BC%E7%9A%AE%E7%9A%84%E7%AE%97%E6%B3%95%E8%AE%AD%E7%BB%83%E8%90%A5_Day01/1688480912895-f80a951d-8d1e-40cd-b4cd-3b857c09e0a1.png" alt="img"></p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 删除目标结点</span></span><br><span class="line"><span class="keyword">public</span> ListNode <span class="title function_">deleteNode</span><span class="params">(ListNode head, <span class="type">int</span> position)</span> {</span><br><span class="line"> <span class="comment">// 头结点为空,意味着链表为空,无法删除</span></span><br><span class="line"> <span class="keyword">if</span> (head == <span class="literal">null</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// 检查插入的位置是否越界, 返回头结点等待下次插入</span></span><br><span class="line"> <span class="type">int</span> <span class="variable">length</span> <span class="operator">=</span> getListLength(head);</span><br><span class="line"> <span class="keyword">if</span> (position > length + <span class="number">1</span> || position < <span class="number">1</span>) {</span><br><span class="line"> System.out.println(<span class="string">"位置参数越界"</span>);</span><br><span class="line"> <span class="keyword">return</span> head;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 表头元素删除</span></span><br><span class="line"> <span class="keyword">if</span> (position == <span class="number">1</span>) {</span><br><span class="line"> head.setNext(head.getNext().getNext());</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 表尾和其他位置</span></span><br><span class="line"> <span class="type">ListNode</span> <span class="variable">P</span> <span class="operator">=</span> head;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i < position - <span class="number">1</span>; i++) {</span><br><span class="line"> P = P.getNext();</span><br><span class="line"> }</span><br><span class="line"> P.setNext(P.getNext().getNext());</span><br><span class="line"> <span class="keyword">return</span> head;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><div class="tag-plugin colorful note" ><div class="body"><p>运行结果</p></div></div><p><img src="/../../img/%E9%B1%BC%E7%9A%AE%E7%9A%84%E7%AE%97%E6%B3%95%E8%AE%AD%E7%BB%83%E8%90%A5_Day01/image-20240320104420596.png" alt="image-20240320104420596"></p><h2 id="链表的增删改查-改"><a href="#链表的增删改查-改" class="headerlink" title="链表的增删改查 - 改"></a>链表的增删改查 - 改</h2><p>改也是水到渠成,同样的操作,只不过这次直接遍历到需要修改的结点即可</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 修改目标结点</span></span><br><span class="line"><span class="keyword">public</span> ListNode <span class="title function_">changeNode</span><span class="params">(ListNode head, <span class="type">int</span> data, <span class="type">int</span> position)</span> {</span><br><span class="line"> <span class="comment">// 头结点为空,意味着链表为空,无法删除</span></span><br><span class="line"> <span class="keyword">if</span> (head == <span class="literal">null</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// 检查插入的位置是否越界, 返回头结点等待下次插入</span></span><br><span class="line"> <span class="type">int</span> <span class="variable">length</span> <span class="operator">=</span> getListLength(head);</span><br><span class="line"> <span class="keyword">if</span> (position > length + <span class="number">1</span> || position < <span class="number">1</span>) {</span><br><span class="line"> System.out.println(<span class="string">"位置参数越界"</span>);</span><br><span class="line"> <span class="keyword">return</span> head;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// 遍历后修改</span></span><br><span class="line"> <span class="type">ListNode</span> <span class="variable">P</span> <span class="operator">=</span> head;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i < position; i++) {</span><br><span class="line"> P = P.getNext();</span><br><span class="line"> }</span><br><span class="line"> P.setData(data);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> head;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><div class="tag-plugin colorful note" ><div class="body"><p>运行结果</p></div></div><p><img src="/../../img/%E9%B1%BC%E7%9A%AE%E7%9A%84%E7%AE%97%E6%B3%95%E8%AE%AD%E7%BB%83%E8%90%A5_Day01/image-20240320104845697.png" alt="image-20240320104845697"></p><hr><p><img src="/../../assets/user/about_me.jpg" alt="欢迎关注我的其他平台"></p>]]></content>
<summary type="html">记录自己的算法学习日常</summary>
<category term="学习笔记" scheme="https://blog.sakurasep.site/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
<category term="Java" scheme="https://blog.sakurasep.site/tags/Java/"/>
<category term="学习笔记" scheme="https://blog.sakurasep.site/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
<category term="鱼皮的算法通关村" scheme="https://blog.sakurasep.site/tags/%E9%B1%BC%E7%9A%AE%E7%9A%84%E7%AE%97%E6%B3%95%E9%80%9A%E5%85%B3%E6%9D%91/"/>
</entry>
<entry>
<title>Java的面向对象</title>
<link href="https://blog.sakurasep.site/posts/Java_OOP/"/>
<id>https://blog.sakurasep.site/posts/Java_OOP/</id>
<published>2024-03-12T07:47:58.000Z</published>
<updated>2024-03-19T06:47:00.000Z</updated>
<content type="html"><![CDATA[<h2 id="多态"><a href="#多态" class="headerlink" title="多态"></a>多态</h2><h3 id="多态的基本使用"><a href="#多态的基本使用" class="headerlink" title="多态的基本使用"></a>多态的基本使用</h3><h4 id="实体类"><a href="#实体类" class="headerlink" title="实体类"></a>实体类</h4><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> Person;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> sakurasep</span></span><br><span class="line"><span class="comment"> * * <span class="doctag">@date</span> 2024/3/13</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Person</span> {</span><br><span class="line"> String name;</span><br><span class="line"> <span class="type">int</span> age;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">eat</span><span class="params">()</span>{</span><br><span class="line"> System.out.println(<span class="string">"人吃饭"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">walk</span><span class="params">()</span>{</span><br><span class="line"> System.out.println(<span class="string">"人走路"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">package</span> Person;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> sakurasep</span></span><br><span class="line"><span class="comment"> * * <span class="doctag">@date</span> 2024/3/13</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Man</span> <span class="keyword">extends</span> <span class="title class_">Person</span>{</span><br><span class="line"> <span class="type">boolean</span> isSomking;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">eat</span><span class="params">()</span>{</span><br><span class="line"> System.out.println(<span class="string">"男人吃肉"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">walk</span><span class="params">()</span>{</span><br><span class="line"> System.out.println(<span class="string">"男人走路"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">play</span><span class="params">()</span>{</span><br><span class="line"> System.out.println(<span class="string">"男人打游戏"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">package</span> Person;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> sakurasep</span></span><br><span class="line"><span class="comment"> * * <span class="doctag">@date</span> 2024/3/13</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Woman</span> <span class="keyword">extends</span> <span class="title class_">Person</span>{</span><br><span class="line"> <span class="type">boolean</span> isBeauty;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">eat</span><span class="params">()</span>{</span><br><span class="line"> System.out.println(<span class="string">"女人吃甜点"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">walk</span><span class="params">()</span>{</span><br><span class="line"> System.out.println(<span class="string">"女人走路"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">watch</span><span class="params">()</span>{</span><br><span class="line"> System.out.println(<span class="string">"女人看剧"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> Person;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> sakurasep</span></span><br><span class="line"><span class="comment"> * * <span class="doctag">@date</span> 2024/3/13</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">PersonTest</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line"> <span class="type">Person</span> <span class="variable">person</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>();</span><br><span class="line"> person.eat();</span><br><span class="line"> person.walk();</span><br><span class="line"></span><br><span class="line"> <span class="type">Man</span> <span class="variable">man</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Man</span>();</span><br><span class="line"> man.eat();</span><br><span class="line"> man.walk();</span><br><span class="line"></span><br><span class="line"> <span class="type">Woman</span> <span class="variable">woman</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Woman</span>();</span><br><span class="line"> woman.eat();</span><br><span class="line"> woman.walk();</span><br><span class="line"></span><br><span class="line"> System.out.println(<span class="string">"*********多态性********"</span>);</span><br><span class="line"></span><br><span class="line"> <span class="type">Person</span> <span class="variable">person1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Man</span>();</span><br><span class="line"> person1.eat();</span><br><span class="line"> person1.walk();</span><br><span class="line"></span><br><span class="line"> <span class="type">Person</span> <span class="variable">person2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Woman</span>();</span><br><span class="line"> person2.eat();</span><br><span class="line"> person2.walk();</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="测试方法"><a href="#测试方法" class="headerlink" title="测试方法"></a>测试方法</h4><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> Person;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> sakurasep</span></span><br><span class="line"><span class="comment"> * * <span class="doctag">@date</span> 2024/3/13</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">PersonTest</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line"> <span class="type">Person</span> <span class="variable">person</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>();</span><br><span class="line"> person.eat();</span><br><span class="line"> person.walk();</span><br><span class="line"></span><br><span class="line"> <span class="type">Man</span> <span class="variable">man</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Man</span>();</span><br><span class="line"> man.eat();</span><br><span class="line"> man.walk();</span><br><span class="line"></span><br><span class="line"> <span class="type">Woman</span> <span class="variable">woman</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Woman</span>();</span><br><span class="line"> woman.eat();</span><br><span class="line"> woman.walk();</span><br><span class="line"></span><br><span class="line"> System.out.println(<span class="string">"*********多态性********"</span>);</span><br><span class="line"></span><br><span class="line"> <span class="type">Person</span> <span class="variable">person1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Man</span>();</span><br><span class="line"> person1.eat();</span><br><span class="line"> person1.walk();</span><br><span class="line"></span><br><span class="line"> <span class="type">Person</span> <span class="variable">person2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Woman</span>();</span><br><span class="line"> person2.eat();</span><br><span class="line"> person2.walk();</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="输出结果"><a href="#输出结果" class="headerlink" title="输出结果"></a>输出结果</h4><p><img src="/../../img/Java%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/image-20240313164918351.jpg" alt="image-20240313164918351"></p><h3 id="多态的实际使用"><a href="#多态的实际使用" class="headerlink" title="多态的实际使用"></a>多态的实际使用</h3><h4 id="测试方法-1"><a href="#测试方法-1" class="headerlink" title="测试方法"></a>测试方法</h4><div class="tag-plugin colorful note" ><div class="title">源码</div><div class="body"><p>当不存在多态性的时候</p></div></div><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> Person;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> sakurasep</span></span><br><span class="line"><span class="comment"> * * <span class="doctag">@date</span> 2024/3/13</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AccountTest</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line"> <span class="type">AccountTest</span> <span class="variable">test</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">AccountTest</span>();</span><br><span class="line"> test.console(<span class="keyword">new</span> <span class="title class_">Account</span>());</span><br><span class="line"> System.out.println(<span class="string">"-------------"</span>);</span><br><span class="line"> test.console(<span class="keyword">new</span> <span class="title class_">CheckAccount</span>());</span><br><span class="line"> System.out.println(<span class="string">"-------------"</span>);</span><br><span class="line"> test.console(<span class="keyword">new</span> <span class="title class_">SaveAccount</span>());</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">console</span><span class="params">(Account account)</span>{</span><br><span class="line"> account.saveMoney(<span class="number">100</span>);</span><br><span class="line"> account.getMoney(<span class="number">40</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">console</span><span class="params">(CheckAccount account)</span>{</span><br><span class="line"> account.saveMoney(<span class="number">100</span>);</span><br><span class="line"> account.getMoney(<span class="number">40</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">console</span><span class="params">(SaveAccount account)</span>{</span><br><span class="line"> account.saveMoney(<span class="number">100</span>);</span><br><span class="line"> account.getMoney(<span class="number">40</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Account</span> {</span><br><span class="line"> String username;</span><br><span class="line"> String password;</span><br><span class="line"> <span class="type">int</span> money; <span class="comment">// 余额</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">// 存钱</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">saveMoney</span><span class="params">(<span class="type">int</span> money)</span> {</span><br><span class="line"> <span class="built_in">this</span>.money = money;</span><br><span class="line"> System.out.printf(<span class="string">"普通账户余额为: %d\n"</span>, <span class="built_in">this</span>.money);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 取钱</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">getMoney</span><span class="params">(<span class="type">int</span> money)</span> {</span><br><span class="line"> <span class="keyword">if</span>(money <= <span class="built_in">this</span>.money) {</span><br><span class="line"> <span class="built_in">this</span>.money -= money;</span><br><span class="line"> System.out.printf(<span class="string">"普通账户余额为: %d\n"</span>, <span class="built_in">this</span>.money);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> {</span><br><span class="line"> System.out.println(<span class="string">"普通账户余额不足"</span>);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">CheckAccount</span> <span class="keyword">extends</span> <span class="title class_">Account</span> {</span><br><span class="line"> <span class="type">int</span> <span class="variable">quota</span> <span class="operator">=</span> <span class="number">500</span>; <span class="comment">// 额度</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">saveMoney</span><span class="params">(<span class="type">int</span> money)</span> {</span><br><span class="line"> <span class="built_in">this</span>.money = money + quota;</span><br><span class="line"> System.out.printf(<span class="string">"信用卡账户余额为: %d\n"</span>, <span class="built_in">this</span>.money);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 取钱</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">getMoney</span><span class="params">(<span class="type">int</span> money)</span></span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span>(<span class="built_in">this</span>.money >= money) {</span><br><span class="line"> <span class="built_in">this</span>.money -= money;</span><br><span class="line"> System.out.printf(<span class="string">"信用卡余额为: %d\n"</span>, <span class="built_in">this</span>.money);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> {</span><br><span class="line"> System.out.println(<span class="string">"信用卡余额不足"</span>);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">SaveAccount</span> <span class="keyword">extends</span> <span class="title class_">Account</span> {</span><br><span class="line"> <span class="type">float</span> money;</span><br><span class="line"> <span class="type">float</span> <span class="variable">rate</span> <span class="operator">=</span> <span class="number">0.2F</span>; <span class="comment">// 利率</span></span><br><span class="line"> <span class="type">float</span> interest; <span class="comment">// 利息</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">saveMoney</span><span class="params">(<span class="type">int</span> money)</span> {</span><br><span class="line"> interest = money * rate;</span><br><span class="line"> <span class="built_in">this</span>.money = money + interest;</span><br><span class="line"> System.out.printf(<span class="string">"储蓄卡预期余额为: %f\n"</span>, <span class="built_in">this</span>.money);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">getMoney</span><span class="params">(<span class="type">int</span> money)</span> {</span><br><span class="line"> <span class="keyword">if</span>(<span class="built_in">this</span>.money - interest > money) {</span><br><span class="line"> <span class="built_in">this</span>.money -= money;</span><br><span class="line"> System.out.printf(<span class="string">"储蓄卡余额为: %f\n"</span>, <span class="built_in">this</span>.money);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> {</span><br><span class="line"> System.out.println(<span class="string">"储蓄卡余额不足"</span>);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>正常情况下,如果没有 Java 的多态性,那么对于不同对象的方法调用,就需要如下这样写多个同名方法,赋予不同对象的形参</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">console</span><span class="params">(Account account)</span>{</span><br><span class="line"> account.saveMoney(<span class="number">100</span>);</span><br><span class="line"> account.getMoney(<span class="number">40</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">console</span><span class="params">(CheckAccount account)</span>{</span><br><span class="line"> account.saveMoney(<span class="number">100</span>);</span><br><span class="line"> account.getMoney(<span class="number">40</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">console</span><span class="params">(SaveAccount account)</span>{</span><br><span class="line"> account.saveMoney(<span class="number">100</span>);</span><br><span class="line"> account.getMoney(<span class="number">40</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>而因为 Java 的多态性,这里的方法便可以省略重复调用,在实际的项目中,多态很有用,符合开闭原则。对于增加新的子类,方法都不需要进行改变,只定义一个父类即可。</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">console</span><span class="params">(Account account)</span>{</span><br><span class="line"> account.saveMoney(<span class="number">100</span>);</span><br><span class="line"> account.getMoney(<span class="number">40</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="输出结果-1"><a href="#输出结果-1" class="headerlink" title="输出结果"></a>输出结果</h4><p><img src="/../../img/Java%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/image-20240319110110588.png" alt="image-20240319110110588"></p><h3 id="Java-向下转型"><a href="#Java-向下转型" class="headerlink" title="Java 向下转型"></a>Java 向下转型</h3><h4 id="测试方法-2"><a href="#测试方法-2" class="headerlink" title="测试方法"></a>测试方法</h4><p>虽然创建的子类的对象,也加载了子类的特有的方法和属性,但是因为我们声明的是父类的引用,所以没有办法直接调用子类特有的属性和方法。</p><p>注意,在向下转型的时候可能会出现类型转换异常,即你要转换的类型并不是你声明的类型</p><p>所以在进行向下转型之前,为了程序的健壮性,最好使用 instanceof 进行判断</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AccountTest</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line"> <span class="type">AccountTest</span> <span class="variable">test</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">AccountTest</span>();</span><br><span class="line"> test.console(<span class="keyword">new</span> <span class="title class_">CheckAccount</span>());</span><br><span class="line"> test.console(<span class="keyword">new</span> <span class="title class_">SaveAccount</span>());</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">console</span><span class="params">(Account account)</span>{</span><br><span class="line"> account.saveMoney(<span class="number">100</span>);</span><br><span class="line"> account.getMoney(<span class="number">40</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 避免出现类型转换异常</span></span><br><span class="line"> <span class="keyword">if</span> (account <span class="keyword">instanceof</span> CheckAccount){</span><br><span class="line"> <span class="type">CheckAccount</span> <span class="variable">check_account</span> <span class="operator">=</span> (CheckAccount)account;</span><br><span class="line"> check_account.getQuota();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (account <span class="keyword">instanceof</span> SaveAccount){</span><br><span class="line"> <span class="type">SaveAccount</span> <span class="variable">save_account</span> <span class="operator">=</span> (SaveAccount)account;</span><br><span class="line"> save_account.getInterest();</span><br><span class="line"> save_account.getRate();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="输出结果-2"><a href="#输出结果-2" class="headerlink" title="输出结果"></a>输出结果</h4><p><img src="/../../img/Java%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/image-20240319143347946.png" alt="image-20240319143347946"></p><h3 id="多态案例练习"><a href="#多态案例练习" class="headerlink" title="多态案例练习"></a>多态案例练习</h3><p>题目</p><p><img src="/../../img/Java%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/image-20240319134006979.png" alt="image-20240319134006979"></p><p>关系图</p><p><img src="/../../img/Java%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/image-20240319134130028.png" alt="image-20240319134130028"></p><h4 id="实体类-1"><a href="#实体类-1" class="headerlink" title="实体类"></a>实体类</h4><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> Geometric;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> sakurasep</span></span><br><span class="line"><span class="comment"> * * <span class="doctag">@date</span> 2024/3/19</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">GeometricObject</span> {</span><br><span class="line"> <span class="keyword">protected</span> String color;</span><br><span class="line"> <span class="keyword">protected</span> <span class="type">double</span> weight;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">protected</span> <span class="title function_">GeometricObject</span><span class="params">(String color, <span class="type">double</span> weight)</span> {</span><br><span class="line"> <span class="built_in">this</span>.color = color;</span><br><span class="line"> <span class="built_in">this</span>.weight = weight;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> String <span class="title function_">getColor</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> color;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setColor</span><span class="params">(String color)</span> {</span><br><span class="line"> <span class="built_in">this</span>.color = color;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="type">double</span> <span class="title function_">getWeight</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> weight;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setWeight</span><span class="params">(<span class="type">double</span> weight)</span> {</span><br><span class="line"> <span class="built_in">this</span>.weight = weight;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="type">double</span> <span class="title function_">findArea</span><span class="params">()</span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">package</span> Geometric;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> sakurasep</span></span><br><span class="line"><span class="comment"> * * <span class="doctag">@date</span> 2024/3/19</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Circle</span> <span class="keyword">extends</span> <span class="title class_">GeometricObject</span> {</span><br><span class="line"> <span class="keyword">private</span> <span class="type">double</span> radius;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">Circle</span><span class="params">(String color, <span class="type">double</span> weight, <span class="type">double</span> radius)</span> {</span><br><span class="line"> <span class="built_in">super</span>(color, weight);</span><br><span class="line"> <span class="built_in">this</span>.radius = radius;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="type">double</span> <span class="title function_">getRadius</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> radius;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setRadius</span><span class="params">(<span class="type">double</span> radius)</span> {</span><br><span class="line"> <span class="built_in">this</span>.radius = radius;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> <span class="type">double</span> <span class="title function_">findArea</span><span class="params">()</span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="number">3.14</span> * radius * radius;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">package</span> Geometric;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> sakurasep</span></span><br><span class="line"><span class="comment"> * * <span class="doctag">@date</span> 2024/3/19</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyRectangle</span> <span class="keyword">extends</span> <span class="title class_">GeometricObject</span>{</span><br><span class="line"> <span class="keyword">private</span> <span class="type">double</span> width;</span><br><span class="line"> <span class="keyword">private</span> <span class="type">double</span> height;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">MyRectangle</span><span class="params">(String color, <span class="type">double</span> weight, <span class="type">double</span> width, <span class="type">double</span> height)</span> {</span><br><span class="line"> <span class="built_in">super</span>(color, weight);</span><br><span class="line"> <span class="built_in">this</span>.width = width;</span><br><span class="line"> <span class="built_in">this</span>.height = height;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="type">double</span> <span class="title function_">getWidth</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> width;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setWidth</span><span class="params">(<span class="type">double</span> width)</span> {</span><br><span class="line"> <span class="built_in">this</span>.width = width;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="type">double</span> <span class="title function_">getHeight</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> height;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setHeight</span><span class="params">(<span class="type">double</span> height)</span> {</span><br><span class="line"> <span class="built_in">this</span>.height = height;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> <span class="type">double</span> <span class="title function_">findArea</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> width * height;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="测试方法-3"><a href="#测试方法-3" class="headerlink" title="测试方法"></a>测试方法</h4><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> Geometric;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> Person.Man;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> sakurasep</span></span><br><span class="line"><span class="comment"> * * <span class="doctag">@date</span> 2024/3/19</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">GeometricTest</span> {</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line"> <span class="type">GeometricTest</span> <span class="variable">test</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">GeometricTest</span>();</span><br><span class="line"> <span class="type">Circle</span> <span class="variable">c1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Circle</span>(<span class="string">"red"</span>, <span class="number">1.0</span>, <span class="number">4</span>);</span><br><span class="line"> <span class="type">Circle</span> <span class="variable">c2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Circle</span>(<span class="string">"bule"</span>, <span class="number">1.0</span>, <span class="number">4</span>);</span><br><span class="line"> <span class="type">MyRectangle</span> <span class="variable">m1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyRectangle</span>(<span class="string">"red"</span>, <span class="number">1.0</span>, <span class="number">4</span>, <span class="number">4</span>);</span><br><span class="line"> test.displayGeometricObject(c1);</span><br><span class="line"> test.displayGeometricObject(c2);</span><br><span class="line"> test.displayGeometricObject(m1);</span><br><span class="line"></span><br><span class="line"> <span class="type">boolean</span> <span class="variable">isEquals</span> <span class="operator">=</span> test.equalsArea(c1, c2);</span><br><span class="line"> <span class="keyword">if</span> (isEquals){</span><br><span class="line"> System.out.println(<span class="string">"面积相等"</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> {</span><br><span class="line"> System.out.println(<span class="string">"面积不等"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">equalsArea</span><span class="params">(GeometricObject object1, GeometricObject object2)</span>{</span><br><span class="line"> <span class="keyword">return</span> object1.findArea() == object2.findArea();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">displayGeometricObject</span><span class="params">(GeometricObject object)</span>{</span><br><span class="line"> System.out.println(<span class="string">"几何图形的面积为: "</span> + object.findArea());</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="输出结果-3"><a href="#输出结果-3" class="headerlink" title="输出结果"></a>输出结果</h4><p><img src="/../../img/Java%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/image-20240319140928531.png" alt="image-20240319140928531"></p><h2 id="重写对象方法"><a href="#重写对象方法" class="headerlink" title="重写对象方法"></a>重写对象方法</h2><h3 id="重写-Object-类的-equals-方法"><a href="#重写-Object-类的-equals-方法" class="headerlink" title="重写 Object 类的 equals() 方法"></a>重写 Object 类的 equals() 方法</h3><p>对于 String,File ,包装类等已经重写了 Object 的 equals 方法。我们自己用的时候,通常也可以重写 equals 方法实现对象的应用。</p><p>当然 IDEA 自带重写 equals 方法</p><h4 id="实体类-2"><a href="#实体类-2" class="headerlink" title="实体类"></a>实体类</h4><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">User</span> {</span><br><span class="line"> <span class="keyword">private</span> <span class="type">int</span> age;</span><br><span class="line"> <span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">User</span><span class="params">()</span> {</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">User</span><span class="params">(<span class="type">int</span> age, String name)</span> {</span><br><span class="line"> <span class="built_in">this</span>.age = age;</span><br><span class="line"> <span class="built_in">this</span>.name = name;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">equals</span><span class="params">(Object obj)</span> {</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">this</span> == obj) {</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (obj <span class="keyword">instanceof</span> User) {</span><br><span class="line"> <span class="type">User</span> <span class="variable">user</span> <span class="operator">=</span> (User) obj;</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">this</span>.age == user.age && <span class="built_in">this</span>.name.equals(user.name);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">equals</span><span class="params">(Object o)</span> {</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">this</span> == o) <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> <span class="keyword">if</span> (o == <span class="literal">null</span> || getClass() != o.getClass()) <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line"> <span class="type">User</span> <span class="variable">user</span> <span class="operator">=</span> (User) o;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (age != user.age) <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> <span class="keyword">return</span> Objects.equals(name, user.name);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="测试方法-4"><a href="#测试方法-4" class="headerlink" title="测试方法"></a>测试方法</h4><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserTest</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line"></span><br><span class="line"> <span class="type">User</span> <span class="variable">u1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">User</span>(<span class="number">10</span>, <span class="string">"lihua"</span>);</span><br><span class="line"> <span class="type">User</span> <span class="variable">u2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">User</span>(<span class="number">10</span>, <span class="string">"xiaoli"</span>);</span><br><span class="line"> <span class="type">User</span> <span class="variable">u3</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">User</span>(<span class="number">10</span>,<span class="string">"lihua"</span>);</span><br><span class="line"> System.out.println(u1.equals(u2));</span><br><span class="line"> System.out.println(u1.equals(u3));</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="输出结果-4"><a href="#输出结果-4" class="headerlink" title="输出结果"></a>输出结果</h4><p><img src="/../../img/Java%E7%9A%84Object%E7%B1%BB/image-20240319155034611.png" alt="image-20240319155034611"></p><h3 id="重写-toString-方法"><a href="#重写-toString-方法" class="headerlink" title="重写 toString() 方法"></a>重写 toString() 方法</h3><p>和 equals 一样,String,File 等也已经预先重写了 toString 方法,对于自定义类,我们同样可以进行重写</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> String <span class="title function_">toString</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"Use r"</span> + <span class="string">"name: "</span> + name + <span class="string">" age: "</span> + age;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="/../../img/Java%E7%9A%84Object%E7%B1%BB/image-20240319183944770.png" alt="image-20240319183944770"></p><p>当然,IDEA 也可以自动生成对象的 toString 方法</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> String <span class="title function_">toString</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"User{"</span> +</span><br><span class="line"> <span class="string">"age="</span> + age +</span><br><span class="line"> <span class="string">", name='"</span> + name + <span class="string">'\''</span> +</span><br><span class="line"> <span class="string">'}'</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="关键字-Static"><a href="#关键字-Static" class="headerlink" title="关键字 Static"></a>关键字 Static</h2><hr><p><img src="/../../assets/user/about_me.jpg" alt="关于我"></p>]]></content>
<summary type="html">Java面向对象的相关内容</summary>
<category term="学习笔记" scheme="https://blog.sakurasep.site/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
<category term="Java" scheme="https://blog.sakurasep.site/tags/Java/"/>
<category term="学习笔记" scheme="https://blog.sakurasep.site/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
</entry>
<entry>
<title>SpringBoot学习笔记</title>
<link href="https://blog.sakurasep.site/posts/SpringBoot_01/"/>
<id>https://blog.sakurasep.site/posts/SpringBoot_01/</id>
<published>2024-03-12T07:47:58.000Z</published>
<updated>2024-03-12T07:47:58.000Z</updated>
<content type="html"><![CDATA[<div class="tag-plugin quot"><p class="content" type="text"><span class="empty"></span><span class="text">Spring Boot 入门</span><span class="empty"></span></p></div><h2 id="需求一"><a href="#需求一" class="headerlink" title="需求一"></a>需求一</h2><p>使用 Spring Boot 开发 Web 应用,浏览器发起/hello请求,返回字符串”hello wordld”</p><h3 id="步骤"><a href="#步骤" class="headerlink" title="步骤"></a>步骤</h3><ol><li>创建 Maven 工程</li><li>导入spring-boot-stater-web 起步依赖</li><li>编写 Controller</li><li>提供启动类</li></ol><h3 id="实现"><a href="#实现" class="headerlink" title="实现"></a>实现</h3><p>创建项目</p><p><img src="/../../img/SpringBoot/image-20240312160228482.jpg" alt="image-20240312160228482"></p><p>添加依赖</p><p><img src="/../../img/SpringBoot/image-20240312160345157.jpg" alt="image-20240312160345157"></p><p>创建 Controller 包,HelloController 类</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> com.sakurasep.springboot.controller;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.PostMapping;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RequestMapping;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RestController;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> sakurasep</span></span><br><span class="line"><span class="comment"> * * <span class="doctag">@date</span> 2024/3/12</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="meta">@RestController</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HelloController</span> {</span><br><span class="line"> <span class="meta">@RequestMapping("/hello")</span></span><br><span class="line"> <span class="keyword">public</span> String <span class="title function_">hello</span><span class="params">()</span></span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"hello world"</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>运行启动类</p><p><img src="/../../img/SpringBoot/image-20240312161419900.jpg" alt="image-20240312161419900"></p><p> 测试结果</p><p><img src="/../../img/SpringBoot/image-20240312161431165.jpg" alt="image-20240312161431165"></p><h2 id="需求二"><a href="#需求二" class="headerlink" title="需求二"></a>需求二</h2><p>认识配置文件 - application.yml</p><p>相比于 properties 更推荐 yml</p><figure class="highlight yml"><table><tr><td class="code"><pre><span class="line"><span class="attr">server:</span></span><br><span class="line"> <span class="attr">port:</span> <span class="number">9090</span></span><br><span class="line"> <span class="attr">servlet:</span></span><br><span class="line"> <span class="attr">context-path:</span> <span class="string">/start</span></span><br></pre></td></tr></table></figure><p><img src="/../../img/SpringBoot/image-20240312162059563.jpg" alt="image-20240312162059563"></p><p>使用 @Value 注解获取配置文件键名</p><figure class="highlight yml"><table><tr><td class="code"><pre><span class="line"><span class="attr">email:</span></span><br><span class="line"><span class="attr">user:</span> <span class="string">sakurasep@qq.com</span></span><br><span class="line"><span class="attr">auth:</span> <span class="literal">true</span></span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Value("{email.user}")</span></span><br><span class="line"><span class="keyword">public</span> String user;</span><br><span class="line"><span class="meta">@Value("{email.auth}")</span></span><br><span class="line"><span class="keyword">public</span> <span class="type">boolean</span> auth</span><br></pre></td></tr></table></figure><p>使用 @ConfigurationProperties 注解获取配置文件</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@ConfigurationProperties(prefix = "email")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">User</span> {</span><br><span class="line"> <span class="keyword">public</span> String user;</span><br><span class="line"> <span class="keyword">public</span> <span class="type">boolean</span> auth;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="需求三"><a href="#需求三" class="headerlink" title="需求三"></a>需求三</h2><p>使用 Spring 整合 mybatis,实现web 访问 /findByid?id=1 将从数据库读取 id 为1的数据</p><p>编写 application.yml 配置文件</p><figure class="highlight yml"><table><tr><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line"> <span class="attr">datasource:</span></span><br><span class="line"> <span class="attr">driver-class-name:</span> <span class="string">com.mysql.cj.jdbc.Driver</span></span><br><span class="line"> <span class="attr">username:</span> <span class="string">root</span></span><br><span class="line"> <span class="attr">password:</span> <span class="number">123456</span></span><br><span class="line"> <span class="attr">url:</span> <span class="string">jdbc:mysql://localhost:3306/tlias</span></span><br></pre></td></tr></table></figure><p>在 pom.xml 添加 mybatis 和 mysql 驱动依赖(添加完成后使用 Maven 构建一下)</p><figure class="highlight xml"><table><tr><td class="code"><pre><span class="line"><span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.mybatis.spring.boot<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>mybatis-spring-boot-starter<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>3.0.0<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"><span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"></span><br><span class="line"><span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.mysql<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>mysql-connector-j<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"><span class="tag"></<span class="name">dependency</span>></span></span><br></pre></td></tr></table></figure><p>在 pojo 层下面创建 User 实体类</p><div class="tag-plugin colorful note" ><div class="title">pojo层的用途</div><div class="body"><p>在Spring Boot项目中,通常会创建一个名为<code>pojo</code>(Plain Old Java Object)的软件包。POJO是指普通的Java对象,它们是没有任何特殊限制的简单Java对象,用于表示应用程序中的数据实体或值对象。这些对象通常只包含私有字段和公共访问器方法,没有特定的框架或库的依赖。</p></div></div><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> com.sakurasep.springboot.pojo;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> sakurasep</span></span><br><span class="line"><span class="comment"> * * <span class="doctag">@date</span> 2024/3/12</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">User</span> {</span><br><span class="line"> <span class="keyword">private</span> Integer id;</span><br><span class="line"> <span class="keyword">private</span> String username;</span><br><span class="line"> <span class="keyword">private</span> String password;</span><br><span class="line"> <span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> Integer <span class="title function_">getId</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> id;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setId</span><span class="params">(Integer id)</span> {</span><br><span class="line"> <span class="built_in">this</span>.id = id;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> String <span class="title function_">getUsername</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> username;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setUsername</span><span class="params">(String username)</span> {</span><br><span class="line"> <span class="built_in">this</span>.username = username;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> String <span class="title function_">getPassword</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> password;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setPassword</span><span class="params">(String password)</span> {</span><br><span class="line"> <span class="built_in">this</span>.password = password;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> String <span class="title function_">getName</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> name;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setName</span><span class="params">(String name)</span> {</span><br><span class="line"> <span class="built_in">this</span>.name = name;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> Integer <span class="title function_">getGender</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> gender;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setGender</span><span class="params">(Integer gender)</span> {</span><br><span class="line"> <span class="built_in">this</span>.gender = gender;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> Integer gender;</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>在 mapper 层下创建 UserMapper 接口,用于 Mybatis 实现对数据库的操作</p><div class="tag-plugin colorful note" ><div class="title">mapper层的用途</div><div class="body"><p>在Spring Boot项目中,<code>mapper</code>包通常用于存放数据访问对象(DAO)的接口或类。这些接口或类通常用于定义与数据持久化相关的操作,如数据库的CRUD(创建、读取、更新、删除)操作。</p></div></div><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> com.sakurasep.springboot.mapper;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.sakurasep.springboot.pojo.User;</span><br><span class="line"><span class="keyword">import</span> org.apache.ibatis.annotations.Mapper;</span><br><span class="line"><span class="keyword">import</span> org.apache.ibatis.annotations.Select;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> sakurasep</span></span><br><span class="line"><span class="comment"> * * <span class="doctag">@date</span> 2024/3/12</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="meta">@Mapper</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">UserMapper</span> {</span><br><span class="line"> <span class="meta">@Select("select * from emp where id = #{id}")</span></span><br><span class="line"> <span class="keyword">public</span> User <span class="title function_">findByid</span><span class="params">(Integer id)</span>;</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>在 service 层 创建 UserService 接口 以及 具体的业务逻辑代码 UserServiceImpl 类</p><div class="tag-plugin colorful note" ><div class="title">Service层的用途</div><div class="body"><p>在Spring Boot项目中,Service层通常是业务逻辑层,用于处理应用程序的业务逻辑。Service层在MVC(模型-视图-控制器)架构中位于控制器层和持久化层之间,它负责处理业务逻辑、协调不同的持久化操作,并提供一组服务供控制器层调用。</p></div></div><div class="tag-plugin colorful note" ><div class="title">impl包的用途</div><div class="body"><p>在一个典型的Spring Boot项目中,Service层下通常会有一个名为<code>impl</code>(implementation的缩写)的包,它是Service层的具体实现。这个包中包含了实际执行业务逻辑的类。</p></div></div><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> com.sakurasep.springboot.service;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.sakurasep.springboot.pojo.User;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> sakurasep</span></span><br><span class="line"><span class="comment"> * * <span class="doctag">@date</span> 2024/3/12</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">UserService</span> {</span><br><span class="line"> <span class="keyword">public</span> User <span class="title function_">findByid</span><span class="params">(Integer id)</span>;</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> com.sakurasep.springboot.service.impl;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.sakurasep.springboot.mapper.UserMapper;</span><br><span class="line"><span class="keyword">import</span> com.sakurasep.springboot.pojo.User;</span><br><span class="line"><span class="keyword">import</span> com.sakurasep.springboot.service.UserService;</span><br><span class="line"><span class="keyword">import</span> org.apache.ibatis.annotations.Select;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Service;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> sakurasep</span></span><br><span class="line"><span class="comment"> * * <span class="doctag">@date</span> 2024/3/12</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">UserService</span> {</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> UserMapper userMapper;</span><br><span class="line"> <span class="keyword">public</span> User <span class="title function_">findByid</span><span class="params">(Integer id)</span>{</span><br><span class="line"> <span class="keyword">return</span> userMapper.findByid(id);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>在 Controller 层 编写 UserController 类</p><div class="tag-plugin colorful note" ><div class="title">Controller层的用途</div><div class="body"><p>Controller是Spring Boot项目中的一个组成部分,负责处理客户端请求并将结果返回给客户端。它充当了应用程序的入口点,并与用户交互,通常用于接收HTTP请求、调用Service层处理业务逻辑,并将处理结果返回给客户端。</p></div></div><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> com.sakurasep.springboot.controller;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.sakurasep.springboot.mapper.UserMapper;</span><br><span class="line"><span class="keyword">import</span> com.sakurasep.springboot.pojo.User;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RequestMapping;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RestController;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> sakurasep</span></span><br><span class="line"><span class="comment"> * * <span class="doctag">@date</span> 2024/3/12</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserController</span> {</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> UserMapper userMapper;</span><br><span class="line"> <span class="meta">@RequestMapping("/findByid")</span></span><br><span class="line"> <span class="keyword">public</span> User <span class="title function_">findByid</span><span class="params">(Integer id)</span>{</span><br><span class="line"> <span class="keyword">return</span> userMapper.findByid(id);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>测试结果</p><p><img src="/../../img/SpringBoot/image-20240312183054692.jpg" alt="image-20240312183054692"></p><hr><p><img src="/../../assets/user/about_me.jpg" alt="关于我"></p>]]></content>
<summary type="html">项目开发的学习基础</summary>
<category term="学习笔记" scheme="https://blog.sakurasep.site/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
<category term="SpringBoot" scheme="https://blog.sakurasep.site/tags/SpringBoot/"/>
<category term="学习笔记" scheme="https://blog.sakurasep.site/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
</entry>
<entry>
<title>SpringBoot后端工程搭建</title>
<link href="https://blog.sakurasep.site/posts/Xiaoha_Blog_02/"/>
<id>https://blog.sakurasep.site/posts/Xiaoha_Blog_02/</id>
<published>2024-03-12T02:19:06.000Z</published>
<updated>2024-03-11T16:00:00.000Z</updated>
<content type="html"><![CDATA[<div class="tag-plugin quot"><p class="content" type="text"><span class="empty"></span><span class="text">SpringBoot后端工程搭建</span><span class="empty"></span></p></div><h2 id="搭建-Spring-Boot-多模块工程(通过-Spring-Initializr)"><a href="#搭建-Spring-Boot-多模块工程(通过-Spring-Initializr)" class="headerlink" title="搭建 Spring Boot 多模块工程(通过 Spring Initializr)"></a>搭建 Spring Boot 多模块工程(通过 Spring Initializr)</h2><h3 id="什么是多模块项目"><a href="#什么是多模块项目" class="headerlink" title="什么是多模块项目"></a>什么是多模块项目</h3><p>多模块项目是项目构建中的概念。拿 Maven 来说,多模块项目(Multi-Module Project)是其一个重要特性,<strong>它允许我们在一个项目中管理多个子模块。</strong></p><p>在一个 Maven 多模块项目中,每个模块都是一个独立的项目,拥有自己的 POM 文件(Project Object Model,项目对象模型)。这些模块可以互相依赖,也可以被其他项目依赖。但是,所有的模块都会被统一管理,它们共享同一套构建系统和依赖管理。</p><h3 id="为什么要使用多模块项目"><a href="#为什么要使用多模块项目" class="headerlink" title="为什么要使用多模块项目"></a>为什么要使用多模块项目</h3><p>主要有以下几个原因:</p><ul><li><strong>代码组织</strong>:在大型项目中,我们经常需要把代码分成多个模块,以便更好地组织代码。每个模块可以聚焦于一个特定的功能或领域,这样可以提高代码的可读性和可维护性。</li><li><strong>依赖管理</strong>:Maven 多模块项目可以帮助我们更好地管理项目的依赖。在父项目的 POM 文件中,我们可以定义所有模块共享的依赖,这样可以避免重复的依赖定义,也方便我们管理和升级依赖。</li><li><strong>构建和部署</strong>:Maven 多模块项目的另一个优点是它可以统一管理项目的构建和部署。我们只需要在父项目中执行 Maven 命令,就可以对所有模块进行构建和部署。这大大简化了开发者的工作。</li></ul><h3 id="IDEA-搭建-Spring-Boot-多模块工程骨架"><a href="#IDEA-搭建-Spring-Boot-多模块工程骨架" class="headerlink" title="IDEA 搭建 Spring Boot 多模块工程骨架"></a>IDEA 搭建 Spring Boot 多模块工程骨架</h3><h4 id="构建父项目-weblog"><a href="#构建父项目-weblog" class="headerlink" title="构建父项目 - weblog"></a>构建父项目 - weblog</h4><div class="tag-plugin colorful note" ><div class="title">没有找到JDK8?</div><div class="body"><p>服务器url替换成aliyun,否则无法使用jdk8</p></div></div><p><img src="/../../img/SpringBoot%E5%90%8E%E7%AB%AF%E5%B7%A5%E7%A8%8B%E6%90%AD%E5%BB%BA/image-20240107111727516.jpg" alt="image-20240107111727516"></p><p>项目初始化目录,删除无用的文件</p><p><img src="/../../img/SpringBoot%E5%90%8E%E7%AB%AF%E5%B7%A5%E7%A8%8B%E6%90%AD%E5%BB%BA/image-20240107112249405.jpg" alt="image-20240107112249405"></p><h4 id="创建-web-访问模块"><a href="#创建-web-访问模块" class="headerlink" title="创建 web 访问模块"></a>创建 web 访问模块</h4><p>这是项目的入口,maven 打包的打包插件在这里存放,同时,博客的前端相关内容也统一存放在这里。</p><p><img src="/../../img/SpringBoot%E5%90%8E%E7%AB%AF%E5%B7%A5%E7%A8%8B%E6%90%AD%E5%BB%BA/image-20240107112343774.jpg" alt="image-20240107112343774"></p><p>勾选依赖 Lombok 和 Spring Web</p><p><img src="/../../img/SpringBoot%E5%90%8E%E7%AB%AF%E5%B7%A5%E7%A8%8B%E6%90%AD%E5%BB%BA/image-20240107112431469.jpg" alt="image-20240107112431469"></p><h4 id="创建后台管理模块"><a href="#创建后台管理模块" class="headerlink" title="创建后台管理模块"></a>创建后台管理模块</h4><p>该模块负责统一放置和管理后台相关的功能</p><p>依赖仅用 Lombok,后续再增加新的模块</p><p><img src="/../../img/SpringBoot%E5%90%8E%E7%AB%AF%E5%B7%A5%E7%A8%8B%E6%90%AD%E5%BB%BA/image-20240107113025777.jpg" alt="image-20240107113025777"></p><h4 id="创建通用模块"><a href="#创建通用模块" class="headerlink" title="创建通用模块"></a>创建通用模块</h4><p>该模块存放一些通用的功能,比如接口的日志切面,全局异常管理</p><p><img src="/../../img/SpringBoot%E5%90%8E%E7%AB%AF%E5%B7%A5%E7%A8%8B%E6%90%AD%E5%BB%BA/image-20240107140837391.jpg" alt="image-20240107140837391"></p><h3 id="pom-文件解析"><a href="#pom-文件解析" class="headerlink" title="pom 文件解析"></a>pom 文件解析</h3><h4 id="weblog"><a href="#weblog" class="headerlink" title="weblog"></a>weblog</h4><p>在父项目的 pom.xml 文件中对项目进行统一管理</p><div class="tag-plugin colorful note" ><div class="body"><p>对项目的版本号进行统一管理</p></div></div><ol><li>项目版本号,主要是涉及项目自身的开发版本,JDK 版本,项目编码</li><li>Maven 相关内容,依赖的是 JDK 版本</li><li>项目依赖包的版本号</li></ol><figure class="highlight xml"><table><tr><td class="code"><pre><span class="line"><span class="comment"><!-- 版本号统一管理 --></span></span><br><span class="line"> <span class="tag"><<span class="name">properties</span>></span></span><br><span class="line"> <span class="comment"><!-- 项目版本号 --></span></span><br><span class="line"> <span class="tag"><<span class="name">revision</span>></span>0.0.1-SNAPSHOT<span class="tag"></<span class="name">revision</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">java.version</span>></span>1.8<span class="tag"></<span class="name">java.version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">project.build.sourceEncoding</span>></span>UTF-8<span class="tag"></<span class="name">project.build.sourceEncoding</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="comment"><!-- Maven 相关 --></span></span><br><span class="line"> <span class="tag"><<span class="name">maven.compiler.source</span>></span>${java.version}<span class="tag"></<span class="name">maven.compiler.source</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">maven.compiler.target</span>></span>${java.version}<span class="tag"></<span class="name">maven.compiler.target</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="comment"><!-- 依赖包版本 --></span></span><br><span class="line"> <span class="tag"><<span class="name">lombok.version</span>></span>1.18.28<span class="tag"></<span class="name">lombok.version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">guava.version</span>></span>31.1-jre<span class="tag"></<span class="name">guava.version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">commons-lang3.version</span>></span>3.12.0<span class="tag"></<span class="name">commons-lang3.version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">jackson.version</span>></span>2.15.2<span class="tag"></<span class="name">jackson.version</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"></<span class="name">properties</span>></span></span><br></pre></td></tr></table></figure><div class="tag-plugin colorful note" ><div class="body"><p>项目相关依赖的管理</p></div></div><ol><li>子模块的名称以及版本号</li><li>常用依赖工具的名称以及版本号</li></ol><figure class="highlight xml"><table><tr><td class="code"><pre><span class="line"><span class="comment"><!-- 统一依赖管理 --></span></span><br><span class="line"> <span class="tag"><<span class="name">dependencyManagement</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">dependencies</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.sakurasep<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>weblog-admin<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>${revision}<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.sakurasep<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>weblog-common<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>${revision}<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="comment"><!-- 常用工具库 --></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.google.guava<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>guava<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>${guava.version}<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.apache.commons<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>commons-lang3<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>${commons-lang3.version}<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="comment"><!-- Jackson --></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.fasterxml.jackson.core<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>jackson-databind<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>${jackson.version}<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependencies</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependencyManagement</span>></span></span><br></pre></td></tr></table></figure><div class="tag-plugin colorful note" ><div class="title">项目的构建设置</div><div class="body"><p>这里添加了spring-boot-maven-plugin</p></div></div><figure class="highlight xml"><table><tr><td class="code"><pre><span class="line"><span class="tag"><<span class="name">build</span>></span></span><br><span class="line"> <span class="comment"><!-- 统一插件管理 --></span></span><br><span class="line"> <span class="tag"><<span class="name">pluginManagement</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">plugins</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">plugin</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.springframework.boot<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>spring-boot-maven-plugin<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">configuration</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">excludes</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">exclude</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.projectlombok<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>lombok<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">exclude</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">excludes</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">configuration</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">plugin</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">plugins</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">pluginManagement</span>></span></span><br><span class="line"><span class="tag"></<span class="name">build</span>></span></span><br></pre></td></tr></table></figure><h4 id="weblog-web"><a href="#weblog-web" class="headerlink" title="weblog-web"></a>weblog-web</h4><figure class="highlight xml"><table><tr><td class="code"><pre><span class="line"><span class="meta"><?xml version=<span class="string">"1.0"</span> encoding=<span class="string">"UTF-8"</span>?></span></span><br><span class="line"><span class="tag"><<span class="name">project</span> <span class="attr">xmlns</span>=<span class="string">"http://maven.apache.org/POM/4.0.0"</span> <span class="attr">xmlns:xsi</span>=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">xsi:schemaLocation</span>=<span class="string">"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">modelVersion</span>></span>4.0.0<span class="tag"></<span class="name">modelVersion</span>></span></span><br><span class="line"> <span class="comment"><!-- 指定父项目为 weblog-springboot --></span></span><br><span class="line"> <span class="tag"><<span class="name">parent</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.sakurasep<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>weblog-springboot<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>${revision}<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">parent</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.sakurasep<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>weblog-web<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">name</span>></span>weblog-web<span class="tag"></<span class="name">name</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">description</span>></span>weblog-web (入口项目,负责博客前台展示相关功能,打包也放在这个模块负责)<span class="tag"></<span class="name">description</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">dependencies</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.sakurasep<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>weblog-common<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.sakurasep<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>weblog-admin<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="comment"><!-- Web 依赖 --></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.springframework.boot<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>spring-boot-starter-web<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="comment"><!-- 免写冗余的 Java 样板式代码 --></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.projectlombok<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>lombok<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">optional</span>></span>true<span class="tag"></<span class="name">optional</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"> <span class="comment"><!-- 单元测试 --></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.springframework.boot<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>spring-boot-starter-test<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">scope</span>></span>test<span class="tag"></<span class="name">scope</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependencies</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">build</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">plugins</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">plugin</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.springframework.boot<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>spring-boot-maven-plugin<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">plugin</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">plugins</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">build</span>></span></span><br><span class="line"><span class="tag"></<span class="name">project</span>></span></span><br></pre></td></tr></table></figure><h4 id="weblog-admin"><a href="#weblog-admin" class="headerlink" title="weblog-admin"></a>weblog-admin</h4><figure class="highlight xml"><table><tr><td class="code"><pre><span class="line"><span class="meta"><?xml version=<span class="string">"1.0"</span> encoding=<span class="string">"UTF-8"</span>?></span></span><br><span class="line"><span class="tag"><<span class="name">project</span> <span class="attr">xmlns</span>=<span class="string">"http://maven.apache.org/POM/4.0.0"</span> <span class="attr">xmlns:xsi</span>=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">xsi:schemaLocation</span>=<span class="string">"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">modelVersion</span>></span>4.0.0<span class="tag"></<span class="name">modelVersion</span>></span></span><br><span class="line"> <span class="comment"><!-- 指定父项目为 weblog-springboot --></span></span><br><span class="line"> <span class="tag"><<span class="name">parent</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.sakurasep<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>weblog-springboot<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>${revision}<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">parent</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.sakurasep<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>weblog-admin<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">name</span>></span>weblog-admin<span class="tag"></<span class="name">name</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">description</span>></span>weblog-admin (负责管理后台相关功能)<span class="tag"></<span class="name">description</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">dependencies</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.sakurasep<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>weblog-common<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"> <span class="comment"><!-- 免写冗余的 Java 样板式代码 --></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.projectlombok<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>lombok<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">optional</span>></span>true<span class="tag"></<span class="name">optional</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="comment"><!-- 单元测试 --></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.springframework.boot<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>spring-boot-starter-test<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">scope</span>></span>test<span class="tag"></<span class="name">scope</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependencies</span>></span></span><br><span class="line"></span><br><span class="line"><span class="tag"></<span class="name">project</span>></span></span><br></pre></td></tr></table></figure><h4 id="weblog-common"><a href="#weblog-common" class="headerlink" title="weblog-common"></a>weblog-common</h4><figure class="highlight xml"><table><tr><td class="code"><pre><span class="line"><span class="meta"><?xml version=<span class="string">"1.0"</span> encoding=<span class="string">"UTF-8"</span>?></span></span><br><span class="line"><span class="tag"><<span class="name">project</span> <span class="attr">xmlns</span>=<span class="string">"http://maven.apache.org/POM/4.0.0"</span> <span class="attr">xmlns:xsi</span>=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">xsi:schemaLocation</span>=<span class="string">"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">modelVersion</span>></span>4.0.0<span class="tag"></<span class="name">modelVersion</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">parent</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.sakurasep<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>weblog-springboot<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>${revision}<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">parent</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.sakurasep<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>weblog-common<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">name</span>></span>weblog-common<span class="tag"></<span class="name">name</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">description</span>></span>weblog-module-common (此模块用于存放一些通用的功能)<span class="tag"></<span class="name">description</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">dependencies</span>></span></span><br><span class="line"> <span class="comment"><!-- 免写冗余的 Java 样板式代码 --></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.projectlombok<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>lombok<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">optional</span>></span>true<span class="tag"></<span class="name">optional</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="comment"><!-- 单元测试 --></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.springframework.boot<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>spring-boot-starter-test<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">scope</span>></span>test<span class="tag"></<span class="name">scope</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="comment"><!-- AOP 切面 --></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.springframework.boot<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>spring-boot-starter-aop<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="comment"><!-- Jackson --></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.fasterxml.jackson.core<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>jackson-databind<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependencies</span>></span></span><br><span class="line"></span><br><span class="line"><span class="tag"></<span class="name">project</span>></span></span><br></pre></td></tr></table></figure><h3 id="测试项目"><a href="#测试项目" class="headerlink" title="测试项目"></a>测试项目</h3><p>执行 mvn clean </p><p><img src="/../../img/SpringBoot%E5%90%8E%E7%AB%AF%E5%B7%A5%E7%A8%8B%E6%90%AD%E5%BB%BA/image-20240107141514819.jpg" alt="image-20240107141514819"></p><p>执行 mvn package</p><p><img src="/../../img/SpringBoot%E5%90%8E%E7%AB%AF%E5%B7%A5%E7%A8%8B%E6%90%AD%E5%BB%BA/image-20240107141639434.jpg" alt="image-20240107141639434"></p><p>运行该 Spring Boot 项目,在 weblog-web 找到 WeblogWebApplication 启动类</p><p>运行在 8080 端口</p><p><img src="/../../img/SpringBoot%E5%90%8E%E7%AB%AF%E5%B7%A5%E7%A8%8B%E6%90%AD%E5%BB%BA/image-20240107141844804.jpg" alt="image-20240107141844804"></p><h2 id="Spring-Boot-多环境配置"><a href="#Spring-Boot-多环境配置" class="headerlink" title="Spring Boot 多环境配置"></a>Spring Boot 多环境配置</h2><h3 id="多环境配置文件"><a href="#多环境配置文件" class="headerlink" title="多环境配置文件"></a>多环境配置文件</h3><p>在 weblog-web 添加多环境配置文件</p><div class="tag-plugin colorful checkbox" ><input type="radio" checked="true"/><span>application.yml 用于默认配置</span></div><div class="tag-plugin colorful checkbox" ><input type="radio" checked="true"/><span>application-dev.yml 用于开发环境</span></div><div class="tag-plugin colorful checkbox" ><input type="radio" checked="true"/><span>application-test.yml 用于测试环境</span></div><div class="tag-plugin colorful checkbox" ><input type="radio" checked="true"/><span>application-prod.yml 用于生产环境</span></div><p>相比于 properties 格式的配置文件,yaml 格式的显然可阅读性更好</p><p><img src="/../../img/SpringBoot%E5%90%8E%E7%AB%AF%E5%B7%A5%E7%A8%8B%E6%90%AD%E5%BB%BA/image-20240107143300065.jpg" alt="image-20240107143300065"></p><p>在默认配置文件中激活 dev 环境</p><p><img src="/../../img/SpringBoot%E5%90%8E%E7%AB%AF%E5%B7%A5%E7%A8%8B%E6%90%AD%E5%BB%BA/image-20240107143509797.jpg" alt="image-20240107143509797"></p><p>启动项目测试,出现以下标注语句表示激活成功</p><p><img src="/../../img/SpringBoot%E5%90%8E%E7%AB%AF%E5%B7%A5%E7%A8%8B%E6%90%AD%E5%BB%BA/image-20240107143548478.jpg" alt="image-20240107143548478"></p><h3 id="配置-Lombok"><a href="#配置-Lombok" class="headerlink" title="配置 Lombok"></a>配置 Lombok</h3><h4 id="Lombok-的优点"><a href="#Lombok-的优点" class="headerlink" title="Lombok 的优点"></a>Lombok 的优点</h4><ol><li><strong>简化 Getter 和 Setter 方法:</strong> 在传统的 Java 开发中,你经常需要为每个类的属性手动编写 Getter 和 Setter 方法,但是有了 Lombok,你只需要在属性上加上<code>@Getter</code>和<code>@Setter</code>注解,Lombok 就会为你自动生成这些方法。</li><li><strong>自动生成构造函数:</strong> 通过`@NoArgsConstructor %}、<div class="tag-plugin copy"><input class="copy-area" id="copy_1" value="@RequiredArgsConstructor`或`@AllArgsConstructor`注解,你可以快速生成无参构造函数、带有必需参数的构造函数或者带有全部参数的构造函数。 3. **自动生成 equals 和 hashCode 方法:** 通过`@EqualsAndHashCode`注解,Lombok 会根据类的字段自动生成`equals()`和`hashCode()`方法,让你的类更易于比较和使用在集合中。 4. **日志记录更轻松:** 使用`@Slf4j`注解,你可以直接在类中使用`log`对象,而无需手动创建日志记录器。 5. **简化异常抛出:** 通过`@SneakyThrows`注解,你可以在方法中抛出受检异常,而无需显式地在方法上声明或捕获它们。 6. **数据类简化:** 使用`@Data`注解,Lombok 会为你自动生成所有常用方法,如 Getter、Setter、{% copy toString()`等,让你的数据类更加简洁。 7. **链式调用:** 使用`@Builder`注解,Lombok 可以帮你创建一个更优雅的构建器模式,让你的对象初始化更加流畅 #### 添加 Lombok 依赖 {% note 添加依赖 添加在父项目的 pom.xml 文件中"><button class="copy-btn" onclick="util.copy("copy_1","复制成功")"><svg class="icon copy-btn" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M5.75 1a.75.75 0 00-.75.75v3c0 .414.336.75.75.75h4.5a.75.75 0 00.75-.75v-3a.75.75 0 00-.75-.75h-4.5zm.75 3V2.5h3V4h-3zm-2.874-.467a.75.75 0 00-.752-1.298A1.75 1.75 0 002 3.75v9.5c0 .966.784 1.75 1.75 1.75h8.5A1.75 1.75 0 0014 13.25v-9.5a1.75 1.75 0 00-.874-1.515.75.75 0 10-.752 1.298.25.25 0 01.126.217v9.5a.25.25 0 01-.25.25h-8.5a.25.25 0 01-.25-.25v-9.5a.25.25 0 01.126-.217z"></path></svg></button></div></li></ol><figure class="highlight xml"><table><tr><td class="code"><pre><span class="line"><span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.projectlombok<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>lombok<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>1.18.28<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">scope</span>></span>provided<span class="tag"></<span class="name">scope</span>></span></span><br><span class="line"><span class="tag"></<span class="name">dependency</span>></span></span><br></pre></td></tr></table></figure><h3 id="自定义-logback-配置"><a href="#自定义-logback-配置" class="headerlink" title="自定义 logback 配置"></a>自定义 logback 配置</h3><h4 id="logback的优点"><a href="#logback的优点" class="headerlink" title="logback的优点"></a>logback的优点</h4><ol><li><strong>性能</strong>:Logback 在性能上超越了许多其他的日志实现,尤其是在高并发环境下。</li><li><strong>灵活性</strong>:Logback 提供了高度灵活的日志配置方式,支持从 XML、Groovy 以及编程式的方式进行配置。</li><li><strong>功能丰富</strong>:除了基本的日志功能,Logback 还提供了如日志归档、日志级别动态修改、事件监听等高级功能。</li><li><strong>与 SLF4J 集成</strong>:SLF4J 是一个日志门面(facade),使得应用程序可以在运行时更换日志实现。Logback 作为 SLF4J 的一个原生实现,可以无缝地与其集成。</li><li><strong>与 Spring Boot 的自动配置集成</strong>:Spring Boot 提供了对 Logback 的自动配置,这意味着开发者无需手动配置 Logback,只需提供一个简单的配置文件即可。</li></ol><h4 id="添加logback"><a href="#添加logback" class="headerlink" title="添加logback"></a>添加logback</h4><div class="tag-plugin colorful note" ><div class="title">添加依赖</div><div class="body"><p>spring boot 默认使用 logback 为默认的日志系统,只需要添加 spring-boot-starter-web 依赖就会自动包含 logback 相关依赖</p></div></div><figure class="highlight xml"><table><tr><td class="code"><pre><span class="line"><span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.springframework.boot<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>spring-boot-starter-web<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"><span class="tag"></<span class="name">dependency</span>></span></span><br></pre></td></tr></table></figure><h4 id="配置-logback"><a href="#配置-logback" class="headerlink" title="配置 logback"></a>配置 logback</h4><p>在 weblog-web 的配置文件夹中添加 logback-weblog.xml</p><p><img src="/../../img/SpringBoot%E5%90%8E%E7%AB%AF%E5%B7%A5%E7%A8%8B%E6%90%AD%E5%BB%BA/image-20240107144745067-4610066.jpg" alt="image-20240107144745067"></p><figure class="highlight xml"><table><tr><td class="code"><pre><span class="line"><span class="meta"><?xml version=<span class="string">"1.0"</span> encoding=<span class="string">"UTF-8"</span>?></span></span><br><span class="line"><span class="tag"><<span class="name">configuration</span> ></span></span><br><span class="line"> <span class="tag"><<span class="name">jmxConfigurator</span>/></span></span><br><span class="line"> <span class="tag"><<span class="name">include</span> <span class="attr">resource</span>=<span class="string">"org/springframework/boot/logging/logback/defaults.xml"</span> /></span></span><br><span class="line"></span><br><span class="line"> <span class="comment"><!-- 应用名称 --></span></span><br><span class="line"> <span class="tag"><<span class="name">property</span> <span class="attr">scope</span>=<span class="string">"context"</span> <span class="attr">name</span>=<span class="string">"appName"</span> <span class="attr">value</span>=<span class="string">"weblog"</span> /></span></span><br><span class="line"> <span class="comment"><!-- 自定义日志输出路径,以及日志名称前缀 --></span></span><br><span class="line"> <span class="tag"><<span class="name">property</span> <span class="attr">name</span>=<span class="string">"LOG_FILE"</span> <span class="attr">value</span>=<span class="string">"/app/weblog/logs/${appName}.%d{yyyy-MM-dd}"</span>/></span></span><br><span class="line"> <span class="tag"><<span class="name">property</span> <span class="attr">name</span>=<span class="string">"FILE_LOG_PATTERN"</span> <span class="attr">value</span>=<span class="string">"%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n"</span>/></span></span><br><span class="line"> <span class="comment"><!--<property name="CONSOLE_LOG_PATTERN" value="${FILE_LOG_PATTERN}"/>--></span></span><br><span class="line"></span><br><span class="line"> <span class="comment"><!-- 按照每天生成日志文件 --></span></span><br><span class="line"> <span class="tag"><<span class="name">appender</span> <span class="attr">name</span>=<span class="string">"FILE"</span> <span class="attr">class</span>=<span class="string">"ch.qos.logback.core.rolling.RollingFileAppender"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">rollingPolicy</span> <span class="attr">class</span>=<span class="string">"ch.qos.logback.core.rolling.TimeBasedRollingPolicy"</span>></span></span><br><span class="line"> <span class="comment"><!-- 日志文件输出的文件名 --></span></span><br><span class="line"> <span class="tag"><<span class="name">FileNamePattern</span>></span>${LOG_FILE}-%i.log<span class="tag"></<span class="name">FileNamePattern</span>></span></span><br><span class="line"> <span class="comment"><!-- 日志文件保留天数 --></span></span><br><span class="line"> <span class="tag"><<span class="name">MaxHistory</span>></span>30<span class="tag"></<span class="name">MaxHistory</span>></span></span><br><span class="line"> <span class="comment"><!-- 日志文件最大的大小 --></span></span><br><span class="line"> <span class="tag"><<span class="name">TimeBasedFileNamingAndTriggeringPolicy</span> <span class="attr">class</span>=<span class="string">"ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">maxFileSize</span>></span>10MB<span class="tag"></<span class="name">maxFileSize</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">TimeBasedFileNamingAndTriggeringPolicy</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">rollingPolicy</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">encoder</span> <span class="attr">class</span>=<span class="string">"ch.qos.logback.classic.encoder.PatternLayoutEncoder"</span>></span></span><br><span class="line"> <span class="comment"><!-- 格式化输出:%d 表示日期,%thread 表示线程名,%-5level:级别从左显示 5 个字符宽度 %errorMessage:日志消息,%n 是换行符--></span></span><br><span class="line"> <span class="tag"><<span class="name">pattern</span>></span>${FILE_LOG_PATTERN}<span class="tag"></<span class="name">pattern</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">encoder</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">appender</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="comment"><!-- dev 环境(仅输出到控制台) --></span></span><br><span class="line"> <span class="tag"><<span class="name">springProfile</span> <span class="attr">name</span>=<span class="string">"dev"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">include</span> <span class="attr">resource</span>=<span class="string">"org/springframework/boot/logging/logback/console-appender.xml"</span> /></span></span><br><span class="line"> <span class="tag"><<span class="name">root</span> <span class="attr">level</span>=<span class="string">"info"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">appender-ref</span> <span class="attr">ref</span>=<span class="string">"CONSOLE"</span> /></span></span><br><span class="line"> <span class="tag"></<span class="name">root</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">springProfile</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="comment"><!-- prod 环境(仅输出到文件中) --></span></span><br><span class="line"> <span class="tag"><<span class="name">springProfile</span> <span class="attr">name</span>=<span class="string">"prod"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">include</span> <span class="attr">resource</span>=<span class="string">"org/springframework/boot/logging/logback/console-appender.xml"</span> /></span></span><br><span class="line"> <span class="tag"><<span class="name">root</span> <span class="attr">level</span>=<span class="string">"INFO"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">appender-ref</span> <span class="attr">ref</span>=<span class="string">"FILE"</span> /></span></span><br><span class="line"> <span class="tag"></<span class="name">root</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">springProfile</span>></span></span><br><span class="line"><span class="tag"></<span class="name">configuration</span>></span></span><br></pre></td></tr></table></figure><p>在生产环境的 application-prod.yml 中添加 log 输出</p><p><img src="/../../img/SpringBoot%E5%90%8E%E7%AB%AF%E5%B7%A5%E7%A8%8B%E6%90%AD%E5%BB%BA/image-20240107144834566.jpg" alt="image-20240107144834566"></p><p>在单元测试包下的测试类中加入以下代码</p><p><img src="/../../img/SpringBoot%E5%90%8E%E7%AB%AF%E5%B7%A5%E7%A8%8B%E6%90%AD%E5%BB%BA/image-20240107145235419.jpg" alt="image-20240107145235419"></p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> com.sakurasep.weblogweb;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> lombok.extern.slf4j.Slf4j;</span><br><span class="line"><span class="keyword">import</span> org.junit.jupiter.api.Test;</span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.test.context.SpringBootTest;</span><br><span class="line"></span><br><span class="line"><span class="meta">@SpringBootTest</span></span><br><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">WeblogWebApplicationTests</span> {</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Test</span></span><br><span class="line"> <span class="keyword">void</span> <span class="title function_">contextLoads</span><span class="params">()</span> {</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Test</span></span><br><span class="line"> <span class="keyword">void</span> <span class="title function_">testLog</span><span class="params">()</span> {</span><br><span class="line"> log.info(<span class="string">"这是一行 Info 级别日志"</span>);</span><br><span class="line"> log.warn(<span class="string">"这是一行 Warn 级别日志"</span>);</span><br><span class="line"> log.error(<span class="string">"这是一行 Error 级别日志"</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 占位符</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">author</span> <span class="operator">=</span> <span class="string">"上杉九月"</span>;</span><br><span class="line"> log.info(<span class="string">"这是一行带有占位符日志,作者:{}"</span>, author);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>运行该测试方法</p><p><img src="/../../img/SpringBoot%E5%90%8E%E7%AB%AF%E5%B7%A5%E7%A8%8B%E6%90%AD%E5%BB%BA/image-20240107145339361.jpg" alt="image-20240107145339361"></p><p>激活生产环境看是否输出到文件</p><p><img src="/../../img/SpringBoot%E5%90%8E%E7%AB%AF%E5%B7%A5%E7%A8%8B%E6%90%AD%E5%BB%BA/image-20240107145455726.jpg" alt="image-20240107145455726"></p><p>修改 logback-weblog.xml 中的输出路径</p><p><img src="/../../img/SpringBoot%E5%90%8E%E7%AB%AF%E5%B7%A5%E7%A8%8B%E6%90%AD%E5%BB%BA/image-20240107145647976.jpg" alt="image-20240107145647976"></p><p>测试输出</p><p><img src="/../../img/SpringBoot%E5%90%8E%E7%AB%AF%E5%B7%A5%E7%A8%8B%E6%90%AD%E5%BB%BA/image-20240107145759496.jpg" alt="image-20240107145759496"></p><div class="tag-plugin colorful note" ><div class="title">测试输出结束记得将路径改回原本的路径,并重新改成</div><div class="body"><p>dev 环境</p></div></div><h3 id="自定义注解,实现-API-请求日志切面"><a href="#自定义注解,实现-API-请求日志切面" class="headerlink" title="自定义注解,实现 API 请求日志切面"></a>自定义注解,实现 API 请求日志切面</h3><h4 id="什么是自定义注解-Custom-Annotations-?"><a href="#什么是自定义注解-Custom-Annotations-?" class="headerlink" title="什么是自定义注解 (Custom Annotations)?"></a>什么是自定义注解 (Custom Annotations)?</h4><p>Java 注解是从 Java 5 开始引入的,它为我们提供了一种元编程的方法,允许我们在不改变代码逻辑的情况下为代码添加元数据。这些元数据可以在编译时或运行时通过反射被访问。</p><p>自定义注解就是用户定义的,用于为代码提供元数据的注解。例如,本小节中自定义的<code>@ApiOperationLog</code>注解,它用来表示一个方法在执行时需要被记录日志。</p><h4 id="什么是-AOP-面向切面编程-?"><a href="#什么是-AOP-面向切面编程-?" class="headerlink" title="什么是 AOP (面向切面编程)?"></a>什么是 AOP (面向切面编程)?</h4><p>AOP(Aspect-Oriented Programming,面向切面编程)是一个编程范式,它提供了一种能力,让开发者能够模块化跨多个对象的横切关注点(例如日志、事务管理、安全等)。</p><p>主要概念包括:</p><ul><li><strong>切点 (Pointcuts)</strong>: 定义在哪里应用切面(即在哪里插入横切关注点的代码)。</li><li><strong>通知 (Advices)</strong>: 定义在特定切点上要执行的代码。常见的通知类型有:前置通知、后置通知、环绕通知等。</li><li><strong>切面 (Aspects)</strong>: 切面将切点和通知结合起来,定义了在何处和何时应用特定的逻辑。</li></ul><p>例如,使用AOP,我们可以为所有使用<code>@ApiOperationLog</code>注解的方法自动添加日志逻辑,而不需要在每个方法中手动添加。</p><h4 id="添加依赖"><a href="#添加依赖" class="headerlink" title="添加依赖"></a>添加依赖</h4><p>在父项目的 pom.xml 添加配置</p><figure class="highlight xml"><table><tr><td class="code"><pre><span class="line"><span class="comment"><!-- 版本号统一管理 --></span></span><br><span class="line"><span class="tag"><<span class="name">properties</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">jackson.version</span>></span>2.15.2<span class="tag"></<span class="name">jackson.version</span>></span></span><br><span class="line"><span class="tag"></<span class="name">properties</span>></span></span><br><span class="line"></span><br><span class="line"><span class="comment"><!-- 统一依赖管理 --></span></span><br><span class="line"> <span class="tag"><<span class="name">dependencyManagement</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">dependencies</span>></span></span><br><span class="line"> <span class="comment"><!-- Jackson --></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.fasterxml.jackson.core<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>jackson-databind<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>${jackson.version}<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"></<span class="name">dependencies</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependencyManagement</span>></span></span><br></pre></td></tr></table></figure><p>因为日志切面属于前后端通用的功能,所以在 weblog-common 中也要引用依赖</p><figure class="highlight xml"><table><tr><td class="code"><pre><span class="line"><span class="comment"><!-- AOP 切面 --></span></span><br><span class="line"><span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.springframework.boot<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>spring-boot-starter-aop<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"><span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"></span><br><span class="line"><span class="comment"><!-- Jackson --></span></span><br><span class="line"><span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.fasterxml.jackson.core<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>jackson-databind<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"><span class="tag"></<span class="name">dependency</span>></span></span><br></pre></td></tr></table></figure><h4 id="实现自定义注解"><a href="#实现自定义注解" class="headerlink" title="实现自定义注解"></a>实现自定义注解</h4><p>在 weblog-common 新建一个 aspect 包</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> com.sakurasep.weblogcommon.aspect;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.lang.annotation.*;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//这个元注解用于指定注解的保留策略,即注解在何时生效。RetentionPolicy.RUNTIME 表示该注解将在运行时保留,这意味着它可以通过反射在运行时被访问和解析。</span></span><br><span class="line"><span class="meta">@Retention(RetentionPolicy.RUNTIME)</span></span><br><span class="line"><span class="comment">//这个元注解用于指定注解的目标元素,即可以在哪些地方使用这个注解。ElementType.METHOD 表示该注解只能用于方法上。这意味着您只能在方法上使用这个特定的注解。</span></span><br><span class="line"><span class="meta">@Target({ElementType.METHOD})</span></span><br><span class="line"><span class="comment">//这个元注解用于指定被注解的元素是否会出现在生成的Java文档中。如果一个注解使用了 @Documented,那么在生成文档时,被注解的元素及其注解信息会被包含在文档中。这可以帮助文档生成工具(如 JavaDoc)在生成文档时展示关于注解的信息。</span></span><br><span class="line"><span class="meta">@Documented</span></span><br><span class="line"><span class="keyword">public</span> <span class="meta">@interface</span> ApiOperationLog {</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * API 功能描述</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> String <span class="title function_">description</span><span class="params">()</span> <span class="keyword">default</span> <span class="string">""</span>;</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="创建-JSON-工具类"><a href="#创建-JSON-工具类" class="headerlink" title="创建 JSON 工具类"></a>创建 JSON 工具类</h4><p>在 weblog-common 模块下创建 utils 包,统一放置工具类,新建 JsonUtil 工具类</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> com.sakurasep.weblogcommon.utils;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.core.JsonProcessingException;</span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.databind.ObjectMapper;</span><br><span class="line"><span class="keyword">import</span> lombok.extern.slf4j.Slf4j;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> sakurasep</span></span><br><span class="line"><span class="comment"> * * <span class="doctag">@date</span> 2024/1/7</span></span><br><span class="line"><span class="comment"> * json 工具类 用于将传入的对象打印成 json 字符串</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">JsonUtil</span> {</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">ObjectMapper</span> <span class="variable">INSTANCE</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ObjectMapper</span>();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> String <span class="title function_">toJsonString</span><span class="params">(Object obj)</span> {</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="keyword">return</span> INSTANCE.writeValueAsString(obj);</span><br><span class="line"> } <span class="keyword">catch</span> (JsonProcessingException e) {</span><br><span class="line"> <span class="keyword">return</span> obj.toString();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="定义日志切面类"><a href="#定义日志切面类" class="headerlink" title="定义日志切面类"></a>定义日志切面类</h4><p>在 aspect 包中新建切面类 ApiOperationLogAspect</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> com.sakurasep.weblogcommon.aspect;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.sakurasep.weblogcommon.utils.JsonUtil;</span><br><span class="line"><span class="keyword">import</span> lombok.extern.slf4j.Slf4j;</span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.ProceedingJoinPoint;</span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.annotation.Around;</span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.annotation.Aspect;</span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.annotation.Pointcut;</span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.reflect.MethodSignature;</span><br><span class="line"><span class="keyword">import</span> org.slf4j.MDC;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.Method;</span><br><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"><span class="keyword">import</span> java.util.UUID;</span><br><span class="line"><span class="keyword">import</span> java.util.function.Function;</span><br><span class="line"><span class="keyword">import</span> java.util.stream.Collectors;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> sakurasep</span></span><br><span class="line"><span class="comment"> * * <span class="doctag">@date</span> 2024/1/7</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ApiOperationLogAspect</span> {</span><br><span class="line"></span><br><span class="line"> <span class="comment">/** 以自定义 <span class="doctag">@ApiOperationLog</span> 注解为切点,凡是添加 <span class="doctag">@ApiOperationLog</span> 的方法,都会执行环绕中的代码 */</span></span><br><span class="line"> <span class="meta">@Pointcut("@annotation(com.sakurasep.weblogcommon.aspect.ApiOperationLog)")</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">apiOperationLog</span><span class="params">()</span> {}</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 环绕</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> joinPoint</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> Throwable</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@Around("apiOperationLog()")</span></span><br><span class="line"> <span class="keyword">public</span> Object <span class="title function_">doAround</span><span class="params">(ProceedingJoinPoint joinPoint)</span> <span class="keyword">throws</span> Throwable {</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="comment">// 请求开始时间</span></span><br><span class="line"> <span class="type">long</span> <span class="variable">startTime</span> <span class="operator">=</span> System.currentTimeMillis();</span><br><span class="line"></span><br><span class="line"> <span class="comment">// MDC</span></span><br><span class="line"> MDC.put(<span class="string">"traceId"</span>, UUID.randomUUID().toString());</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 获取被请求的类和方法</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">className</span> <span class="operator">=</span> joinPoint.getTarget().getClass().getSimpleName();</span><br><span class="line"> <span class="type">String</span> <span class="variable">methodName</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 请求入参</span></span><br><span class="line"> Object[] args = joinPoint.getArgs();</span><br><span class="line"> <span class="comment">// 入参转 JSON 字符串</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">argsJsonStr</span> <span class="operator">=</span> Arrays.stream(args).map(toJsonStr()).collect(Collectors.joining(<span class="string">", "</span>));</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 功能描述信息</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">description</span> <span class="operator">=</span> getApiOperationLogDescription(joinPoint);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 打印请求相关参数</span></span><br><span class="line"> log.info(<span class="string">"====== 请求开始: [{}], 入参: {}, 请求类: {}, 请求方法: {} =================================== "</span>,</span><br><span class="line"> description, argsJsonStr, className, methodName);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 执行切点方法</span></span><br><span class="line"> <span class="type">Object</span> <span class="variable">result</span> <span class="operator">=</span> joinPoint.proceed();</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 执行耗时</span></span><br><span class="line"> <span class="type">long</span> <span class="variable">executionTime</span> <span class="operator">=</span> System.currentTimeMillis() - startTime;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 打印出参等相关信息</span></span><br><span class="line"> log.info(<span class="string">"====== 请求结束: [{}], 耗时: {}ms, 出参: {} =================================== "</span>,</span><br><span class="line"> description, executionTime, JsonUtil.toJsonString(result));</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line"> } <span class="keyword">finally</span> {</span><br><span class="line"> MDC.clear();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 获取注解的描述信息</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> joinPoint</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> String <span class="title function_">getApiOperationLogDescription</span><span class="params">(ProceedingJoinPoint joinPoint)</span> {</span><br><span class="line"> <span class="comment">// 1. 从 ProceedingJoinPoint 获取 MethodSignature</span></span><br><span class="line"> <span class="type">MethodSignature</span> <span class="variable">signature</span> <span class="operator">=</span> (MethodSignature) joinPoint.getSignature();</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 2. 使用 MethodSignature 获取当前被注解的 Method</span></span><br><span class="line"> <span class="type">Method</span> <span class="variable">method</span> <span class="operator">=</span> signature.getMethod();</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 3. 从 Method 中提取 LogExecution 注解</span></span><br><span class="line"> <span class="type">ApiOperationLog</span> <span class="variable">apiOperationLog</span> <span class="operator">=</span> method.getAnnotation(ApiOperationLog.class);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 4. 从 LogExecution 注解中获取 description 属性</span></span><br><span class="line"> <span class="keyword">return</span> apiOperationLog.description();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 转 JSON 字符串</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> Function<Object, String> <span class="title function_">toJsonStr</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> arg -> JsonUtil.toJsonString(arg);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="添加包扫描"><a href="#添加包扫描" class="headerlink" title="添加包扫描"></a>添加包扫描</h4><p>在启动类中添加 @ComponentScan,扫描 com.sakurasep 包下的所有类</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> com.sakurasep.weblogweb;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.SpringApplication;</span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.autoconfigure.SpringBootApplication;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.ComponentScan;</span><br><span class="line"></span><br><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="meta">@ComponentScan({"com.sakurasep.*"})</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WeblogWebApplication</span> {</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line"> SpringApplication.run(WeblogWebApplication.class, args);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="新增测试接口"><a href="#新增测试接口" class="headerlink" title="新增测试接口"></a>新增测试接口</h4><p>在 weblog-web 模块中</p><div class="tag-plugin colorful note" ><div class="title">新建接口</div><div class="body"><p>创建 controller 包用于存放统一接口,创建 model 包用于放置 pojo 对象</p></div></div><p>创建 User 类</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> com.sakurasep.weblogweb.model;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> lombok.Data;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> sakurasep</span></span><br><span class="line"><span class="comment"> * * <span class="doctag">@date</span> 2024/3/12</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">User</span> {</span><br><span class="line"> <span class="keyword">private</span> String username;</span><br><span class="line"> <span class="keyword">private</span> Integer sex;</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>创建 TestController 类,路径为 /test</p><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> com.sakurasep.weblogweb.controller;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.sakurasep.weblogcommon.aspect.ApiOperationLog;</span><br><span class="line"><span class="keyword">import</span> com.sakurasep.weblogweb.model.User;</span><br><span class="line"><span class="keyword">import</span> lombok.extern.slf4j.Slf4j;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.PostMapping;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RequestBody;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RestController;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> sakurasep</span></span><br><span class="line"><span class="comment"> * * <span class="doctag">@date</span> 2024/3/12</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TestController</span> {</span><br><span class="line"> <span class="comment">// 路径映射到/test</span></span><br><span class="line"> <span class="meta">@PostMapping("/test")</span></span><br><span class="line"> <span class="comment">// 注解</span></span><br><span class="line"> <span class="meta">@ApiOperationLog(description = "测试接口")</span></span><br><span class="line"> <span class="keyword">public</span> User <span class="title function_">test</span><span class="params">(<span class="meta">@RequestBody</span> User user)</span>{</span><br><span class="line"> <span class="keyword">return</span> user;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="测试-Test-接口"><a href="#测试-Test-接口" class="headerlink" title="测试 Test 接口"></a>测试 Test 接口</h4><p>使用 postman 以 json 的格式请求 /test</p><p><img src="/../../img/SpringBoot%E5%90%8E%E7%AB%AF%E5%B7%A5%E7%A8%8B%E6%90%AD%E5%BB%BA/image-20240312153623018.jpg" alt="image-20240312153623018"></p><p>请求参数</p><p><img src="/../../img/SpringBoot%E5%90%8E%E7%AB%AF%E5%B7%A5%E7%A8%8B%E6%90%AD%E5%BB%BA/image-20240312153647898.jpg" alt="image-20240312153647898"></p><p>出参</p><p><img src="/../../img/SpringBoot%E5%90%8E%E7%AB%AF%E5%B7%A5%E7%A8%8B%E6%90%AD%E5%BB%BA/image-20240312153816881.jpg" alt="image-20240312153816881"></p><p>控制台输出日志</p><p><img src="/../../img/SpringBoot%E5%90%8E%E7%AB%AF%E5%B7%A5%E7%A8%8B%E6%90%AD%E5%BB%BA/image-20240312153755009.jpg" alt="image-20240312153755009"></p><hr><p><img src="/../../assets/user/about_me.jpg" alt="关于我"></p>]]></content>
<summary type="html">后端工程搭建笔记</summary>
<category term="项目开发日记" scheme="https://blog.sakurasep.site/categories/%E9%A1%B9%E7%9B%AE%E5%BC%80%E5%8F%91%E6%97%A5%E8%AE%B0/"/>
<category term="SpringBoot" scheme="https://blog.sakurasep.site/tags/SpringBoot/"/>
<category term="后端" scheme="https://blog.sakurasep.site/tags/%E5%90%8E%E7%AB%AF/"/>
<category term="Java" scheme="https://blog.sakurasep.site/tags/Java/"/>
<category term="Maven" scheme="https://blog.sakurasep.site/tags/Maven/"/>
</entry>
<entry>
<title>准备本地开发环境</title>
<link href="https://blog.sakurasep.site/posts/Xiaoha_Blog_01/"/>
<id>https://blog.sakurasep.site/posts/Xiaoha_Blog_01/</id>
<published>2024-03-12T02:19:06.000Z</published>
<updated>2024-03-11T16:00:00.000Z</updated>
<content type="html"><![CDATA[<div class="tag-plugin quot"><p class="content" type="text"><span class="empty"></span><span class="text">准备本地开发环境</span><span class="empty"></span></p></div><h2 id="环境准备"><a href="#环境准备" class="headerlink" title="环境准备"></a>环境准备</h2><h3 id="基础环境"><a href="#基础环境" class="headerlink" title="基础环境"></a>基础环境</h3><figure class="highlight yml"><table><tr><td class="code"><pre><span class="line"><span class="string">系统:</span> <span class="string">macOS</span> <span class="string">Sonoma</span> <span class="number">14.3</span></span><br><span class="line"><span class="string">包管理器:</span> <span class="string">homebrew</span> <span class="number">4.2</span><span class="number">.2</span></span><br></pre></td></tr></table></figure><p><img src="/../../img/%E5%87%86%E5%A4%87%E6%9C%AC%E5%9C%B0%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83/image-20240107105238544.png" alt="image-20240107105238544"></p><p><img src="/../../img/%E5%87%86%E5%A4%87%E6%9C%AC%E5%9C%B0%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83/image-20240107105213424.png" alt="image-20240107105213424"></p><h3 id="后端开发"><a href="#后端开发" class="headerlink" title="后端开发"></a>后端开发</h3><figure class="highlight yml"><table><tr><td class="code"><pre><span class="line"><span class="attr">IDE:</span> <span class="string">IDEA</span> <span class="number">2023.1</span><span class="number">.3</span></span><br><span class="line"><span class="string">数据库可视化:</span> <span class="string">Navicat</span> <span class="number">16</span></span><br><span class="line"><span class="string">java管理程序:</span> <span class="string">Jenv</span></span><br><span class="line"><span class="attr">JDK:</span> <span class="string">openjdk1.8</span></span><br><span class="line"><span class="attr">mysql:</span> <span class="number">5.7</span></span><br><span class="line"><span class="attr">Maven:</span> <span class="number">3.9</span><span class="number">.6</span></span><br></pre></td></tr></table></figure><p><img src="/../../img/%E5%87%86%E5%A4%87%E6%9C%AC%E5%9C%B0%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83/169398549818727.jpeg" alt="img"></p><p><img src="/../../img/%E5%87%86%E5%A4%87%E6%9C%AC%E5%9C%B0%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83/image-20240107111026707.png" alt="image-20240107111026707"></p><p><img src="/../../img/%E5%87%86%E5%A4%87%E6%9C%AC%E5%9C%B0%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83/image-20240107111117686.png" alt="image-20240107111117686"></p><p><img src="/../../img/%E5%87%86%E5%A4%87%E6%9C%AC%E5%9C%B0%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83/image-20240107110237955.png" alt="image-20240107110237955"></p><p><img src="/../../img/%E5%87%86%E5%A4%87%E6%9C%AC%E5%9C%B0%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83/image-20240107110303130.png" alt="image-20240107110303130"></p><p><img src="/../../img/%E5%87%86%E5%A4%87%E6%9C%AC%E5%9C%B0%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83/image-20240107110631407.png" alt="image-20240107110631407"></p><p><img src="/../../img/%E5%87%86%E5%A4%87%E6%9C%AC%E5%9C%B0%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83/image-20240107110904792.png" alt="image-20240107110904792"></p><h3 id="前端开发"><a href="#前端开发" class="headerlink" title="前端开发"></a>前端开发</h3><figure class="highlight yml"><table><tr><td class="code"><pre><span class="line"><span class="attr">IDE:</span> <span class="string">VsCode</span></span><br><span class="line"><span class="attr">Nodejs:</span> <span class="number">16</span></span><br></pre></td></tr></table></figure><p><img src="/../../img/%E5%87%86%E5%A4%87%E6%9C%AC%E5%9C%B0%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83/image-20240107111248811.png" alt="image-20240107111248811"></p><p><img src="/../../img/%E5%87%86%E5%A4%87%E6%9C%AC%E5%9C%B0%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83/image-20240107111148560.png" alt="image-20240107111148560"></p><hr><p><img src="/../../assets/user/about_me.jpg" alt="关于我"></p>]]></content>
<summary type="html">准备本地开发环境</summary>
<category term="项目开发日记" scheme="https://blog.sakurasep.site/categories/%E9%A1%B9%E7%9B%AE%E5%BC%80%E5%8F%91%E6%97%A5%E8%AE%B0/"/>
<category term="SpringBoot" scheme="https://blog.sakurasep.site/tags/SpringBoot/"/>
<category term="后端" scheme="https://blog.sakurasep.site/tags/%E5%90%8E%E7%AB%AF/"/>
<category term="Java" scheme="https://blog.sakurasep.site/tags/Java/"/>
<category term="Maven" scheme="https://blog.sakurasep.site/tags/Maven/"/>
</entry>
<entry>
<title>适用于 Stellar 的标签转换脚本</title>
<link href="https://blog.sakurasep.site/posts/md-to-stellar/"/>
<id>https://blog.sakurasep.site/posts/md-to-stellar/</id>
<published>2024-03-07T06:53:47.000Z</published>
<updated>2024-03-06T16:00:00.000Z</updated>
<content type="html"><![CDATA[<div class="tag-plugin quot"><p class="content" type="text"><span class="empty"></span><span class="text">一、图片标签测试</span><span class="empty"></span></p></div><h2 id="1-1-image-⇄-图片超链接"><a href="#1-1-image-⇄-图片超链接" class="headerlink" title="1.1 image ⇄ 图片超链接"></a>1.1 image ⇄ 图片超链接</h2><p><img src="https://bu.dusays.com/2024/09/01/66d42682cd240.jpg" alt="@test"></p><h2 id="1-2-galley-标签内不进行修改"><a href="#1-2-galley-标签内不进行修改" class="headerlink" title="1.2 galley 标签内不进行修改"></a>1.2 galley 标签内不进行修改</h2><div class="tag-plugin gallery grid-box" size="xl" ratio="origin"><div class="grid-cell"><img data-fancybox="gallery-1" src="https://bu.dusays.com/2024/09/01/66d42682cd240.jpg" alt="@test"/><div class="image-meta"><span class="image-caption">@test</span></div></div></div><div class="tag-plugin quot"><p class="content" type="text"><span class="empty"></span><span class="text">二、一级标题测试</span><span class="empty"></span></p></div><h2 id="2-1-quot-⇄-一级标题"><a href="#2-1-quot-⇄-一级标题" class="headerlink" title="2.1 quot ⇄ 一级标题"></a>2.1 quot ⇄ 一级标题</h2><div class="tag-plugin quot"><p class="content" type="text"><span class="empty"></span><span class="text">一级标题转换成quot</span><span class="empty"></span></p></div><h2 id="二级标题不转换"><a href="#二级标题不转换" class="headerlink" title="二级标题不转换"></a>二级标题不转换</h2><h3 id="三级标题不转换"><a href="#三级标题不转换" class="headerlink" title="三级标题不转换"></a>三级标题不转换</h3><h4 id="四级标题不转换"><a href="#四级标题不转换" class="headerlink" title="四级标题不转换"></a>四级标题不转换</h4><h5 id="五级标题不转换"><a href="#五级标题不转换" class="headerlink" title="五级标题不转换"></a>五级标题不转换</h5><h6 id="六级标题不转换"><a href="#六级标题不转换" class="headerlink" title="六级标题不转换"></a>六级标题不转换</h6><div class="tag-plugin quot"><p class="content" type="text"><span class="empty"></span><span class="text">三、无序列表测试</span><span class="empty"></span></p></div><h2 id="3-1-radio-⇄-无序列表"><a href="#3-1-radio-⇄-无序列表" class="headerlink" title="3.1 radio ⇄ 无序列表"></a>3.1 radio ⇄ 无序列表</h2><div class="tag-plugin colorful checkbox" ><input type="radio" checked="true"/><span>无序列表1</span></div><div class="tag-plugin colorful checkbox" ><input type="radio" checked="true"/><span>无序列表2</span></div><div class="tag-plugin colorful checkbox" ><input type="radio" checked="true"/><span>无序列表3</span></div><div class="tag-plugin colorful checkbox" ><input type="radio" checked="true"/><span>无序列表4</span></div><div class="tag-plugin colorful checkbox" ><input type="radio" checked="true"/><span>无序列表5</span></div><div class="tag-plugin quot"><p class="content" type="text"><span class="empty"></span><span class="text">四、引用标签测试</span><span class="empty"></span></p></div><h2 id="4-1-note-⇄-引用"><a href="#4-1-note-⇄-引用" class="headerlink" title="4.1 note ⇄ 引用"></a>4.1 note ⇄ 引用</h2><div class="tag-plugin colorful note" ><div class="body"><p>引用标签转换成为note</p></div></div><div class="tag-plugin colorful note" ><div class="body"><p>引用标签转换成为note</p></div></div><div class="tag-plugin quot"><p class="content" type="text"><span class="empty"></span><span class="text">五、超链接测试</span><span class="empty"></span></p></div><h2 id="5-1-link-⇄-超链接"><a href="#5-1-link-⇄-超链接" class="headerlink" title="5.1 link ⇄ 超链接"></a>5.1 link ⇄ 超链接</h2><div class="tag-plugin link dis-select"><a class="link-card rich" title="上杉九月的博客" href="https://blog.sakurasep.site" target="_blank" rel="external nofollow noopener noreferrer" cardlink api="https://site-info-api-git-main-sakurasep.vercel.app/api/v1?url=https://blog.sakurasep.site" autofill="icon,desc"><div class="top"><div class="lazy img" data-bg="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/link/8f277b4ee0ecd.svg"></div><span class="cap link footnote">https://blog.sakurasep.site</span></div><div class="bottom"><span class="title">上杉九月的博客</span><span class="cap desc footnote"></span></div></a></div><div class="tag-plugin quot"><p class="content" type="text"><span class="empty"></span><span class="text">六、单行代码测试</span><span class="empty"></span></p></div><h2 id="6-1-copy-⇄-单行代码"><a href="#6-1-copy-⇄-单行代码" class="headerlink" title="6.1 copy ⇄ 单行代码"></a>6.1 copy ⇄ 单行代码</h2><div class="tag-plugin copy"><input class="copy-area" id="copy_2" value="https://github.com"><button class="copy-btn" onclick="util.copy("copy_2","复制成功")"><svg class="icon copy-btn" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M5.75 1a.75.75 0 00-.75.75v3c0 .414.336.75.75.75h4.5a.75.75 0 00.75-.75v-3a.75.75 0 00-.75-.75h-4.5zm.75 3V2.5h3V4h-3zm-2.874-.467a.75.75 0 00-.752-1.298A1.75 1.75 0 002 3.75v9.5c0 .966.784 1.75 1.75 1.75h8.5A1.75 1.75 0 0014 13.25v-9.5a1.75 1.75 0 00-.874-1.515.75.75 0 10-.752 1.298.25.25 0 01.126.217v9.5a.25.25 0 01-.25.25h-8.5a.25.25 0 01-.25-.25v-9.5a.25.25 0 01.126-.217z"></path></svg></button></div><div class="tag-plugin copy"><input class="copy-area" id="copy_3" value="curl -s https://sh.xaox.cc/install"><button class="copy-btn" onclick="util.copy("copy_3","复制成功")"><svg class="icon copy-btn" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M5.75 1a.75.75 0 00-.75.75v3c0 .414.336.75.75.75h4.5a.75.75 0 00.75-.75v-3a.75.75 0 00-.75-.75h-4.5zm.75 3V2.5h3V4h-3zm-2.874-.467a.75.75 0 00-.752-1.298A1.75 1.75 0 002 3.75v9.5c0 .966.784 1.75 1.75 1.75h8.5A1.75 1.75 0 0014 13.25v-9.5a1.75 1.75 0 00-.874-1.515.75.75 0 10-.752 1.298.25.25 0 01.126.217v9.5a.25.25 0 01-.25.25h-8.5a.25.25 0 01-.25-.25v-9.5a.25.25 0 01.126-.217z"></path></svg></button></div><h2 id="6-2-代码块不转换"><a href="#6-2-代码块不转换" class="headerlink" title="6.2 代码块不转换"></a>6.2 代码块不转换</h2><figure class="highlight cpp"><table><tr><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string"><iostream></span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line">cout << <span class="string">"Hello world"</span>;</span><br><span class="line">}</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br></pre></td></tr></table></figure><hr><p><img src="/../../assets/user/about_me.jpg" alt="欢迎关注我的其他平台"></p>]]></content>
<summary type="html">为了方便在本地编辑时使用 typora 进行预览,到云端时转换成为 Stellar 特有的标签,使用 Python 写了一个转换脚本。</summary>
<category term="零基础教程" scheme="https://blog.sakurasep.site/categories/%E9%9B%B6%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B/"/>
<category term="python" scheme="https://blog.sakurasep.site/tags/python/"/>
<category term="markdown" scheme="https://blog.sakurasep.site/tags/markdown/"/>
<category term="stellar" scheme="https://blog.sakurasep.site/tags/stellar/"/>
<category term="标准化" scheme="https://blog.sakurasep.site/tags/%E6%A0%87%E5%87%86%E5%8C%96/"/>
</entry>
<entry>
<title>媒体库使用指南</title>
<link href="https://blog.sakurasep.site/posts/How-To-Use-MediaServer/"/>
<id>https://blog.sakurasep.site/posts/How-To-Use-MediaServer/</id>
<published>2024-02-21T08:02:42.000Z</published>
<updated>2024-03-18T12:05:37.000Z</updated>
<content type="html"><![CDATA[<h2 id="一、媒体库介绍"><a href="#一、媒体库介绍" class="headerlink" title="一、媒体库介绍"></a>一、媒体库介绍</h2><p>目前在服务器上同时运行着两个媒体库,一个是我自行搭建的,使用 NASTools 和 AutoBangumi 进行媒体管理和追番自动化的本地库(以后简称本地库)。</p><h3 id="1-本地库"><a href="#1-本地库" class="headerlink" title="1. 本地库"></a>1. 本地库</h3><h4 id="1-1-本地库的优点"><a href="#1-1-本地库的优点" class="headerlink" title="1.1 本地库的优点"></a>1.1 本地库的优点</h4><div class="tag-plugin colorful checkbox" ><input type="radio" checked="true"/><span>可以通过微信或者 Telegram 进行交互,一键下载入库你想看的影片</span></div><div class="tag-plugin colorful checkbox" ><input type="radio" checked="true"/><span>使用 AIO 服务器的核显进行解码,理论上支持所有硬件的播放</span></div><div class="tag-plugin colorful checkbox" ><input type="radio" checked="true"/><span>在外观看如果流量不足可以使用转码功能,将高码率的视频转成较低码率以降低流量消耗(因为有些 4K 电影原盘的码率可能平均 30Mb/s ,也就是正常的 5G 网速才能够跑满)</span></div><div class="tag-plugin colorful checkbox" ><input type="radio" checked="true"/><span>支持实时更新蜜柑计划上的新番,基本做到制作组发布后几个小时内获取到新番</span></div><div class="tag-plugin colorful checkbox" ><input type="radio" checked="true"/><span>支持Infuse,iOS & Apple TV & macOS 设备推荐使用 Infuse,价格便宜,效果更好</span></div><h4 id="1-2-本地库的缺点"><a href="#1-2-本地库的缺点" class="headerlink" title="1.2 本地库的缺点"></a>1.2 本地库的缺点</h4><div class="tag-plugin colorful checkbox" ><input type="radio" checked="true"/><span>外网上传带宽取决于我家里宽带的上传带宽,目前是 50Mbps,无法实现多人流畅观看 4K 电影原盘,后续我会将部分影片上传到阿里云盘,以获取直链加速外网播放速度</span></div><div class="tag-plugin colorful checkbox" ><input type="radio" checked="true"/><span>资源较少,目前收录的内容见媒体库收录存档,后续会逐渐增加存量,明年会将硬盘阵列升级到 8x8TB 的机械硬盘阵列,目前存储空间为 14TB</span></div><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240221200510095.jpg" alt="本地媒体库"></p><h3 id="2-网络库"><a href="#2-网络库" class="headerlink" title="2. 网络库"></a>2. 网络库</h3><p>一个是网上最全,更新相对及时的小雅媒体库,它的环境是通过阿里云盘转存小雅保存好的文件,然后导入小雅刮削好的元数据,实现资源以媒体库的形式展示出来(以下简称网络库)。</p><h4 id="2-1-网络库的优点"><a href="#2-1-网络库的优点" class="headerlink" title="2.1 网络库的优点"></a>2.1 网络库的优点</h4><div class="tag-plugin colorful checkbox" ><input type="radio" checked="true"/><span>全网最全的影视资源,基本没有你想不到的</span></div><div class="tag-plugin colorful checkbox" ><input type="radio" checked="true"/><span>访问速度取决于阿里云盘的下载速度,我是阿里云盘的会员,理论上能跑满 500Mbps 的宽带</span></div><div class="tag-plugin colorful checkbox" ><input type="radio" checked="true"/><span>更新速度尚可,小雅媒体库算是一个公益,持续,稳定的媒体库了</span></div><h4 id="2-2-网络库的缺点"><a href="#2-2-网络库的缺点" class="headerlink" title="2.2 网络库的缺点"></a>2.2 网络库的缺点</h4><div class="tag-plugin colorful checkbox" ><input type="radio" checked="true"/><span>Infuse 请不要使用小雅媒体库,因为会出现奇奇怪怪的 bug</span></div><div class="tag-plugin colorful checkbox" ><input type="radio" checked="true"/><span>小雅提供的 Emby 容器我个人并没有配置转码,在某些设备(例如直接使用网页)上可能无法播放</span></div><div class="tag-plugin colorful checkbox" ><input type="radio" checked="true"/><span>新番没有实时更新,目前最新的是 2023 年冬季动漫,还没有更新 2024 年春季动漫</span></div><div class="tag-plugin colorful checkbox" ><input type="radio" checked="true"/><span>有些 bug 我是修不了的,因为同步文件和数据不是由我管理,需要等待脚本更新</span></div><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240221200711623.jpg" alt="image-20240221200711623"></p><h2 id="二、媒体库的使用"><a href="#二、媒体库的使用" class="headerlink" title="二、媒体库的使用"></a>二、媒体库的使用</h2><h3 id="1-如何观看媒体库中的影片"><a href="#1-如何观看媒体库中的影片" class="headerlink" title="1. 如何观看媒体库中的影片"></a>1. 如何观看媒体库中的影片</h3><p>十分不推荐使用网页端,因为网页端无法调用本机进行解码,会导致观看所有资源都会通过服务器进行转码,大大消耗了服务器的资源。</p><div class="tag-plugin colorful note" ><div class="title">0318</div><div class="body"><p>客户端资源仅用于学习交流,所有资源来自于以下Telegram频道。你可以通过源 TG 频道下载,也可以通过我提供的网盘下载</p></div></div><div class="tag-plugin link dis-select"><a class="link-card rich" title="Emby学习小秘" href="https://t.me/EmbyNoisyX" target="_blank" rel="external nofollow noopener noreferrer" cardlink api="https://site-info-api-git-main-sakurasep.vercel.app/api/v1?url=https://t.me/EmbyNoisyX" autofill="icon,desc"><div class="top"><div class="lazy img" data-bg="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/link/8f277b4ee0ecd.svg"></div><span class="cap link footnote">https://t.me/EmbyNoisyX</span></div><div class="bottom"><span class="title">Emby学习小秘</span><span class="cap desc footnote"></span></div></a></div><h4 id="1-1-Windows-用户"><a href="#1-1-Windows-用户" class="headerlink" title="1.1 Windows 用户"></a>1.1 Windows 用户</h4><p>Windows 的使用很方便,下载开心版的客户端即可</p><div class="tag-plugin link dis-select"><a class="link-card rich" title="Windows开心版" href="https://cloud.sakurasep.top/s/jRfM" target="_blank" rel="external nofollow noopener noreferrer" cardlink api="https://site-info-api-git-main-sakurasep.vercel.app/api/v1?url=https://cloud.sakurasep.top/s/jRfM" autofill="icon,desc"><div class="top"><div class="lazy img" data-bg="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/link/8f277b4ee0ecd.svg"></div><span class="cap link footnote">https://cloud.sakurasep.top/s/jRfM</span></div><div class="bottom"><span class="title">Windows开心版</span><span class="cap desc footnote"></span></div></a></div><p>安装结束后有一个配置和卸载工具,可以执行命令针对客户端进行修改,Windows 的玩法是最多的</p><p>安装完成打开客户端,输入服务器地址以及账号密码,即可进行观看</p><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240315112011683.jpg" alt="image-20240315112011683"></p><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240315112028653.jpg" alt="image-20240315112028653"></p><h4 id="1-2-macOS-用户"><a href="#1-2-macOS-用户" class="headerlink" title="1.2 macOS 用户"></a>1.2 macOS 用户</h4><h5 id="使用-Electron-版(次优)"><a href="#使用-Electron-版(次优)" class="headerlink" title="使用 Electron 版(次优)"></a>使用 Electron 版(次优)</h5><div class="tag-plugin link dis-select"><a class="link-card rich" title="macOS Electron Emby" href="https://cloud.sakurasep.top/s/k5h6" target="_blank" rel="external nofollow noopener noreferrer" cardlink api="https://site-info-api-git-main-sakurasep.vercel.app/api/v1?url=https://cloud.sakurasep.top/s/k5h6" autofill="icon,desc"><div class="top"><div class="lazy img" data-bg="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/link/8f277b4ee0ecd.svg"></div><span class="cap link footnote">https://cloud.sakurasep.top/s/k5h6</span></div><div class="bottom"><span class="title">macOS Electron Emby</span><span class="cap desc footnote"></span></div></a></div><h5 id="使用-Emby-官方客户端-(不推荐)"><a href="#使用-Emby-官方客户端-(不推荐)" class="headerlink" title="使用 Emby 官方客户端 (不推荐)"></a>使用 Emby 官方客户端 (不推荐)</h5><div class="tag-plugin colorful note" ><div class="title">注意事项</div><div class="body"><p>使用脚本破解很容易失效,为了 Emby 这官方客户端的效果花 30 一个月买订阅又不值得。故不推荐使用,破解成功的话千万不要升级,因为很难说升级后脚本还能不能适配</p></div></div><p>在 App Store 下载 Emby</p><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240315102103608.jpg" alt="image-20240315102103608"></p><p>在终端输入</p><figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">/bin/bash -c <span class="string">"<span class="subst">$(curl -fsSL https://raw.githubusercontent.com/psychopasss/ss_rule/main/macOS/EmbyUnlock.sh)</span>"</span></span><br></pre></td></tr></table></figure><p>脚本输出</p><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240315102223048.jpg" alt="image-20240315102223048"></p><p>输入服务器地址进入首页,正常播放</p><div class="tag-plugin colorful note" ><div class="body"><p>如果弹出付费订阅验证,请关闭代理以及重新运行脚本</p></div></div><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240315102239995.jpg" alt="image-20240315102239995"></p><h5 id="使用第三方客户端-Infuse-(付费优选)"><a href="#使用第三方客户端-Infuse-(付费优选)" class="headerlink" title="使用第三方客户端 Infuse (付费优选)"></a>使用第三方客户端 Infuse (付费优选)</h5><div class="tag-plugin colorful note" ><div class="title">小雅</div><div class="body"><p>Emby 不要添加到Infuse!!! Infuse 的扫库会使得 小雅请求阿里云盘的 token 过量,从而失效</p></div></div><p>相比于付费给 Emby,Infuse 的会员价格更适合,并且是全平台,你的 iPad iPhone macOS AppleTV 都只需要购买一次订阅就可以全平台享受,价格也不贵,月费 13 元(之前 7 元),年费 88,总之还是挺实惠的。</p><p>我一直在用 Infuse 就是因为 Infuse 界面确实好看,等之后买了 AppleTV 也能顺畅使用。</p><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240315103009176.jpg" alt="image-20240315103009176"></p><p>从 App Store 下载 Infuse</p><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240315105644986.jpg" alt="image-20240315105644986"></p><p>打开后在<code>文件-新增文件来源</code> 添加服务器</p><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240315103253480.jpg" alt="image-20240315103253480"></p><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240315103450782.jpg" alt="image-20240315103450782"></p><p>在 <code>其他 Emby...</code> 这里添加服务器地址,选择媒体库模式</p><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240315103610061.jpg" alt="image-20240315103610061"></p><p>添加后等待 Infuse 扫库刮削媒体信息,刮削完成在首页变便会显示内容</p><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240315105235929.jpg" alt="image-20240315105235929"></p><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240315105247243.jpg" alt="image-20240315105247243"></p><h5 id="使用-VidHub(不推荐)"><a href="#使用-VidHub(不推荐)" class="headerlink" title="使用 VidHub(不推荐)"></a>使用 VidHub(不推荐)</h5><div class="tag-plugin colorful note" ><div class="body"><p>注意,该播放器最近被发现禁止播放无版权内容,作为一个本地播放器使用联网权限来限制保存的视频,严重影响对该软件的信任,所以请不要使用这款软件</p></div></div><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/6f32302ac65c1038b7a856fdf4119313b17e899a.jpg" alt="版权搞到本地播放器了?"></p><div class="tag-plugin colorful note" ><div class="title">VidHub</div><div class="body"><p>连接到媒体服务器貌似不会扫库,是直接获取源服务器的信息,所以说小雅应该是可用的</p></div></div><p>VidHub 是一款免费的国产播放器,最近才听说,试着用了用还是挺不错的,后续更新对更多片源格式的支持后应该会能和 Infuse 刚一刚。</p><p>在 App Store 下载 VidHub</p><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240315105621435.jpg" alt="image-20240315105621435"></p><p>VidHub 也支持两种添加方式</p><p>第一种是针对你没有媒体库管理软件,使用 bt 下载电影或是云盘转存电影,此时可以使用文件源</p><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240315105922765.jpg" alt="image-20240315105922765"></p><p>第二种是针对有媒体库的用户,这里我们就选择第二种方式</p><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240315110628955.jpg" alt="image-20240315110628955"></p><p>连接成功后点击已连接的服务器</p><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240315110825506-0472106.jpg" alt="image-20240315110825506"></p><p>剧集界面</p><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240315110848539.jpg" alt="image-20240315110848539"></p><h4 id="1-3-Android-用户"><a href="#1-3-Android-用户" class="headerlink" title="1.3 Android 用户"></a>1.3 Android 用户</h4><p>目前安卓上有两个版本,一个是常规版,一个是 MIUI 特供版,两者在界面上没有什么区别,特供版改成了小米视频的包名,用于启动视频工具箱里的补帧功能</p><div class="tag-plugin colorful note" ><div class="title">MIUI特供版</div><div class="body"><p>该版本是为了支持MIUI 12.xx / 骁龙8xx平台专属的动态画面补偿(视频补帧)功能而做修改,并添加了开心整合包内容,详细修改见频道记录。</p></div></div><div class="tag-plugin link dis-select"><a class="link-card rich" title="Android 普通版" href="https://cloud.sakurasep.top/s/l5i5" target="_blank" rel="external nofollow noopener noreferrer" cardlink api="https://site-info-api-git-main-sakurasep.vercel.app/api/v1?url=https://cloud.sakurasep.top/s/l5i5" autofill="icon,desc"><div class="top"><div class="lazy img" data-bg="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/link/8f277b4ee0ecd.svg"></div><span class="cap link footnote">https://cloud.sakurasep.top/s/l5i5</span></div><div class="bottom"><span class="title">Android 普通版</span><span class="cap desc footnote"></span></div></a></div><div class="tag-plugin link dis-select"><a class="link-card rich" title="MIUI特供版" href="https://cloud.sakurasep.top/s/l5i5" target="_blank" rel="external nofollow noopener noreferrer" cardlink api="https://site-info-api-git-main-sakurasep.vercel.app/api/v1?url=https://cloud.sakurasep.top/s/l5i5" autofill="icon,desc"><div class="top"><div class="lazy img" data-bg="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/link/8f277b4ee0ecd.svg"></div><span class="cap link footnote">https://cloud.sakurasep.top/s/l5i5</span></div><div class="bottom"><span class="title">MIUI特供版</span><span class="cap desc footnote"></span></div></a></div><h4 id="1-4-IOS-用户"><a href="#1-4-IOS-用户" class="headerlink" title="1.4 IOS 用户"></a>1.4 IOS 用户</h4><div class="tag-plugin colorful note" ><div class="title">注意</div><div class="body"><p>因为官方版的 Emby 破解过于麻烦,需要使用到圈 X,圈 X 还是挺贵的,有这钱还不如去买 Infuse</p></div></div><h5 id="使用-Infuse"><a href="#使用-Infuse" class="headerlink" title="使用 Infuse"></a>使用 Infuse</h5><p>从 App Store 下载 Infuse</p><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/IMG_1370.jpg" alt="IMG_1370"></p><p>如果你在 macOS 已经配置过了,iPad 端会云同步你的连接信息</p><p>如果没有配置,点击主页的设置,和 macOS 端一样的配置方法</p><div class="tag-plugin colorful note" ><div class="title">软件首页</div><div class="body"><p>& 媒体信息页</p></div></div><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/IMG_1376.jpg" alt="IMG_1376"></p><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/IMG_1377.jpg" alt="IMG_1377"></p><h5 id="使用-VidHub"><a href="#使用-VidHub" class="headerlink" title="使用 VidHub"></a>使用 VidHub</h5><p>从 App Store 下载 VidHub</p><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/IMG_1371.jpg" alt="IMG_1371"></p><p>同样的,VidHub 也有云端同步功能,他的配置方法和 macOS 仍然保持相同</p><div class="tag-plugin colorful note" ><div class="title">效果展示</div><div class="body"><p>软件首页和媒体信息页</p></div></div><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/IMG_1372.jpg" alt="IMG_1372"></p><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/IMG_1373.jpg" alt="IMG_1373"></p><h4 id="1-5-Android-TV-用户"><a href="#1-5-Android-TV-用户" class="headerlink" title="1.5 Android TV 用户"></a>1.5 Android TV 用户</h4><p>手里没有,大概介绍一下安装流程。</p><ol><li>下载电视版本的 Emby 客户端</li><li>一般来说将安装包拷贝到 U盘,然后进入电视中安装(有些电视不允许安装第三方应用,这样的话需要打开 adb 调试,然后在同一个局域网内进行 adb 安装,这个我们以后再说)</li><li>打开应用,输入服务器地址和账号密码进行观看</li></ol><div class="tag-plugin link dis-select"><a class="link-card rich" title="Android TV 通用版" href="https://cloud.sakurasep.top/s/nRtq" target="_blank" rel="external nofollow noopener noreferrer" cardlink api="https://site-info-api-git-main-sakurasep.vercel.app/api/v1?url=https://cloud.sakurasep.top/s/nRtq" autofill="icon,desc"><div class="top"><div class="lazy img" data-bg="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/link/8f277b4ee0ecd.svg"></div><span class="cap link footnote">https://cloud.sakurasep.top/s/nRtq</span></div><div class="bottom"><span class="title">Android TV 通用版</span><span class="cap desc footnote"></span></div></a></div><h4 id="1-6-Apple-TV-用户"><a href="#1-6-Apple-TV-用户" class="headerlink" title="1.6 Apple TV 用户"></a>1.6 Apple TV 用户</h4><p>手里没有,大概介绍一下安装流程。</p><ol><li>登录外区 Apple ID 账号,一般来说美区就可以,下载 Infuse 或者 VidHub</li><li>输入服务器地址和账号密码进行观看</li></ol><h3 id="2-如何搜索你想看的内容"><a href="#2-如何搜索你想看的内容" class="headerlink" title="2. 如何搜索你想看的内容"></a>2. 如何搜索你想看的内容</h3><p>因为我使用了 Nastool 作为媒体库管理工具,所以在这里实现了两种交互方式,企业微信和 Telegram。企业微信供内部交流使用,开放给大家的是 Telegram 群组</p><h4 id="添加-Telegram-群组-和-Telegram-Bot"><a href="#添加-Telegram-群组-和-Telegram-Bot" class="headerlink" title="添加 Telegram 群组 和 Telegram Bot"></a>添加 Telegram 群组 和 Telegram Bot</h4><p>Bot <code>@sakurasep_nastool_bot</code></p><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240315181457209.jpg" alt="image-20240315181457209"></p><div class="tag-plugin link dis-select"><a class="link-card rich" title="Channel" href="https://t.me/+IgxEydBNUuZiNzM1" target="_blank" rel="external nofollow noopener noreferrer" cardlink api="https://site-info-api-git-main-sakurasep.vercel.app/api/v1?url=https://t.me/+IgxEydBNUuZiNzM1" autofill="icon,desc"><div class="top"><div class="lazy img" data-bg="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/link/8f277b4ee0ecd.svg"></div><span class="cap link footnote">https://t.me/+IgxEydBNUuZiNzM1</span></div><div class="bottom"><span class="title">Channel</span><span class="cap desc footnote"></span></div></a></div><div class="tag-plugin colorful note" ><div class="title">注意事项</div><div class="body"><p>Bot 是用于发送消息与媒体管理服务进行交互的,Channel 是接受消息通知的。</p></div></div><h4 id="获取-ID-并-添加权限"><a href="#获取-ID-并-添加权限" class="headerlink" title="获取 ID 并 添加权限"></a>获取 ID 并 添加权限</h4><p>如果想使用交互请加我的 TG 进行私聊,发给我你的 ID,以下是 ID 获取方法</p><p>获取 ID 的 bot <code>@getidsbot</code></p><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240315181714464.jpg" alt="image-20240315181714464"></p><p>添加后输入 <code>/start</code> 开始</p><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240315181805232.jpg" alt="image-20240315181805232"></p><h4 id="使用方法"><a href="#使用方法" class="headerlink" title="使用方法"></a>使用方法</h4><p>找到刚才添加的媒体管理 bot</p><p>直接发送你想看的片名,注意,近期上映的院线影片在下线前不会搜到。</p><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240315182516121.jpg" alt="image-20240315182516121"></p><p>点击链接可以查看影片详细的信息,确认无误后发送序号自动开始下载入库,根据下载的大小和做种人数,基本热门的都能在几个小时内完成下载。</p><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240315182655272.jpg" alt="image-20240315182655272"></p><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240315182825811.jpg" alt="image-20240315182825811"></p><h4 id="入库成功"><a href="#入库成功" class="headerlink" title="入库成功"></a>入库成功</h4><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240315192732693.jpg" alt="image-20240315192732693"></p><p>此时 Emby 服务器中便有了<code>水浒传</code></p><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240315192816686.jpg" alt="image-20240315192816686"></p><h2 id="三、动漫归档计划"><a href="#三、动漫归档计划" class="headerlink" title="三、动漫归档计划"></a>三、动漫归档计划</h2><p>相比于非动漫来说,我认为小雅媒体库做的已经很好了,唯独对于动漫这方面来说小雅内容并不是特别优质。</p><p>目前的进度</p><h3 id="1-2024"><a href="#1-2024" class="headerlink" title="1. 2024"></a>1. 2024</h3><h4 id="2024-春季新番"><a href="#2024-春季新番" class="headerlink" title="2024 春季新番"></a>2024 春季新番</h4><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240318162634791.jpg" alt="image-20240318162634791"></p><h3 id="2-2023"><a href="#2-2023" class="headerlink" title="2. 2023"></a>2. 2023</h3><h4 id="2023-冬季未完结"><a href="#2023-冬季未完结" class="headerlink" title="2023 冬季未完结"></a>2023 冬季未完结</h4><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/2023%E5%B9%B4%E5%86%AC%E5%AD%A3%E6%9C%AA%E5%AE%8C%E7%BB%93%E5%8A%A8%E6%BC%AB.jpg" alt="2023年冬季未完结动漫"></p><h4 id="2023-冬季完结"><a href="#2023-冬季完结" class="headerlink" title="2023 冬季完结"></a>2023 冬季完结</h4><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/2023%E5%B9%B4%E5%86%AC%E5%AD%A3%E5%AE%8C%E7%BB%93%E5%8A%A8%E6%BC%AB.jpg" alt="2023年冬季完结动漫"></p><p>目前我想的是把以往年份的有趣的动漫都归档到本地以及云盘中,我个人有阿里云盘12T,Onedrive E5 开发者账号,也就是 25个子账户,每个账户 5T Onedrive</p><p>现在的想法是本地和阿里云盘存一份热门动漫,在Onedrive 中尽量存储能获取的所有内容。</p><p>如果你能够提供容灾的云盘空间或是有时间对媒体库进行整理下载,欢迎在 TG 联系我。</p><h2 id="四、媒体库更新日志"><a href="#四、媒体库更新日志" class="headerlink" title="四、媒体库更新日志"></a>四、媒体库更新日志</h2><p>因为时间原因,更新图片大概一个月一次,请查看下面的索引</p><figure class="highlight markdown"><table><tr><td class="code"><pre><span class="line"><span class="bullet">-</span> 动画电影</span><br><span class="line"><span class="bullet"> -</span> 哪吒闹海 (1979) [TMDB:74037] [IMDB:tt0354770]</span><br><span class="line"><span class="bullet"> -</span> 风之谷 (1984) [TMDB:81] [IMDB:tt0087544]</span><br><span class="line"><span class="bullet"> -</span> 天空之城 (1986) [TMDB:10515] [IMDB:tt0092067]</span><br><span class="line"><span class="bullet"> -</span> 萤火虫之墓 (1988) [TMDB:12477] [IMDB:tt0095327]</span><br><span class="line"><span class="bullet"> -</span> 龙猫 (1988) [TMDB:8392] [IMDB:tt0096283]</span><br><span class="line"><span class="bullet"> -</span> 魔女宅急便 (1989) [TMDB:16859] [IMDB:tt0097814]</span><br><span class="line"><span class="bullet"> -</span> 狮子王 (1994) [TMDB:8587] [IMDB:tt0110357]</span><br><span class="line"><span class="bullet"> -</span> 侧耳倾听 (1995) [TMDB:37797] [IMDB:tt0113824]</span><br><span class="line"><span class="bullet"> -</span> 幽灵公主 (1997) [TMDB:128] [IMDB:tt0119698]</span><br><span class="line"><span class="bullet"> -</span> 未麻的部屋 (1998) [TMDB:10494] [IMDB:tt0156887]</span><br><span class="line"><span class="bullet"> -</span> 千与千寻 (2001) [TMDB:129] [IMDB:tt0245429]</span><br><span class="line"><span class="bullet"> -</span> 怪兽电力公司 (2001) [TMDB:585] [IMDB:tt0198781]</span><br><span class="line"><span class="bullet"> -</span> 冰川时代 (2002) [TMDB:425] [IMDB:tt0268380]</span><br><span class="line"><span class="bullet"> -</span> 东京教父 (2003) [TMDB:13398] [IMDB:tt0388473]</span><br><span class="line"><span class="bullet"> -</span> 哈尔的移动城堡 (2004) [TMDB:4935] [IMDB:tt0347149]</span><br><span class="line"><span class="bullet"> -</span> 穿越时空的少女 (2006) [TMDB:14069] [IMDB:tt0808506]</span><br><span class="line"><span class="bullet"> -</span> 红辣椒 (2006) [TMDB:4977] [IMDB:tt0851578]</span><br><span class="line"><span class="bullet"> -</span> 崖上的波妞 (2008) [TMDB:12429] [IMDB:tt0876563]</span><br><span class="line"><span class="bullet"> -</span> 机器人总动员 (2008) [TMDB:10681] [IMDB:tt0910970]</span><br><span class="line"><span class="bullet"> -</span> 玛丽和马克思 (2009) [TMDB:24238] [IMDB:tt0978762]</span><br><span class="line"><span class="bullet"> -</span> 飞屋环游记 (2009) [TMDB:14160] [IMDB:tt1049413]</span><br><span class="line"><span class="bullet"> -</span> 你看起来好像很好吃 (2010) [TMDB:89825] [IMDB:tt1734113]</span><br><span class="line"><span class="bullet"> -</span> 借东西的小人阿莉埃蒂 (2010) [TMDB:51739] [IMDB:tt1568921]</span><br><span class="line"><span class="bullet"> -</span> 玩具总动员3 (2010) [TMDB:10193] [IMDB:tt0435761]</span><br><span class="line"><span class="bullet"> -</span> 神偷奶爸 (2010) [TMDB:20352] [IMDB:tt1323594]</span><br><span class="line"><span class="bullet"> -</span> 驯龙高手 (2010) [TMDB:10191] [IMDB:tt0892769]</span><br><span class="line"><span class="bullet"> -</span> 萤火之森 (2011) [TMDB:92321] [IMDB:tt2061702]</span><br><span class="line"><span class="bullet"> -</span> 大闹天宫 (2012) [TMDB:145954] [IMDB:tt11941418]</span><br><span class="line"><span class="bullet"> -</span> 疯狂原始人 (2013) [TMDB:49519] [IMDB:tt0481499]</span><br><span class="line"><span class="bullet"> -</span> 超能陆战队 (2014) [TMDB:177572] [IMDB:tt2245084]</span><br><span class="line"><span class="bullet"> -</span> 头脑特工队 (2015) [TMDB:150540] [IMDB:tt2096673]</span><br><span class="line"><span class="bullet"> -</span> 你的名字。 (2016) [TMDB:372058] [IMDB:tt5311514]</span><br><span class="line"><span class="bullet"> -</span> 疯狂动物城 (2016) [TMDB:269149] [IMDB:tt2948356]</span><br><span class="line"><span class="bullet">-</span> 华语电影</span><br><span class="line"><span class="bullet"> -</span> 英雄本色 (1986) [TMDB:11471] [IMDB:tt0092263]</span><br><span class="line"><span class="bullet"> -</span> 倩女幽魂 (1987) [TMDB:30421] [IMDB:tt0093978]</span><br><span class="line"><span class="bullet"> -</span> 阿飞正传 (1990) [TMDB:18311] [IMDB:tt0101258]</span><br><span class="line"><span class="bullet"> -</span> 牯岭街少年杀人事件 (1991) [TMDB:15804] [IMDB:tt0101985]</span><br><span class="line"><span class="bullet"> -</span> 纵横四海 (1991) [TMDB:47423] [IMDB:tt0101020]</span><br><span class="line"><span class="bullet"> -</span> 新龙门客栈 (1992) [TMDB:40213] [IMDB:tt0105859]</span><br><span class="line"><span class="bullet"> -</span> 唐伯虎点秋香 (1993) [TMDB:37703] [IMDB:tt0108289]</span><br><span class="line"><span class="bullet"> -</span> 喜宴 (1993) [TMDB:9261] [IMDB:tt0107156]</span><br><span class="line"><span class="bullet"> -</span> 射雕英雄传之东成西就 (1993) [TMDB:55157] [IMDB:tt0108074]</span><br><span class="line"><span class="bullet"> -</span> 霸王别姬 (1993) [TMDB:10997] [IMDB:tt0106332]</span><br><span class="line"><span class="bullet"> -</span> 青蛇 (1993) [TMDB:39915] [IMDB:tt0106559]</span><br><span class="line"><span class="bullet"> -</span> 九品芝麻官 (1994) [TMDB:55156] [IMDB:tt0110201]</span><br><span class="line"><span class="bullet"> -</span> 活着 (1994) [TMDB:31439] [IMDB:tt0110081]</span><br><span class="line"><span class="bullet"> -</span> 背靠背,脸对脸 (1994) [TMDB:295279] [IMDB:tt0109235]</span><br><span class="line"><span class="bullet"> -</span> 重庆森林 (1994) [TMDB:11104] [IMDB:tt0109424]</span><br><span class="line"><span class="bullet"> -</span> 阳光灿烂的日子 (1994) [TMDB:161285] [IMDB:tt0111786]</span><br><span class="line"><span class="bullet"> -</span> 饮食男女 (1994) [TMDB:10451] [IMDB:tt0111797]</span><br><span class="line"><span class="bullet"> -</span> 大话西游之月光宝盒 (1995) [TMDB:13345] [IMDB:tt0112778]</span><br><span class="line"><span class="bullet"> -</span> 大话西游之月光宝盒 (1995) [TMDB:13345] [IMDB:tt0112778]</span><br><span class="line"><span class="bullet"> -</span> 甜蜜蜜 (1996) [TMDB:37185] [IMDB:tt0117905]</span><br><span class="line"><span class="bullet"> -</span> 春光乍泄 (1997) [TMDB:18329] [IMDB:tt0118845]</span><br><span class="line"><span class="bullet"> -</span> 一一 (2000) [TMDB:25538] [IMDB:tt0244316]</span><br><span class="line"><span class="bullet"> -</span> 花样年华 (2000) [TMDB:843] [IMDB:tt0118694]</span><br><span class="line"><span class="bullet"> -</span> 鬼子来了 (2001) [TMDB:25838] [IMDB:tt0245929]</span><br><span class="line"><span class="bullet"> -</span> 无间道 (2002) [TMDB:10775] [IMDB:tt0338564]</span><br><span class="line"><span class="bullet"> -</span> 无间道2 (2003) [TMDB:11647] [IMDB:tt0369060]</span><br><span class="line"><span class="bullet"> -</span> 功夫 (2004) [TMDB:9470] [IMDB:tt0373074]</span><br><span class="line"><span class="bullet"> -</span> 可可西里 (2004) [TMDB:16074] [IMDB:tt0386651]</span><br><span class="line"><span class="bullet"> -</span> 疯狂的石头 (2006) [TMDB:45380] [IMDB:tt0843270]</span><br><span class="line"><span class="bullet"> -</span> 色·戒 (2007) [TMDB:4588] [IMDB:tt0808357]</span><br><span class="line"><span class="bullet"> -</span> 东邪西毒:终极版 (2009) [TMDB:1241825]</span><br><span class="line"><span class="bullet"> -</span> 岁月神偷 (2010) [TMDB:39693] [IMDB:tt1602572]</span><br><span class="line"><span class="bullet"> -</span> 让子弹飞 (2010) [TMDB:51533] [IMDB:tt1533117]</span><br><span class="line"><span class="bullet"> -</span> 心迷宫 (2014) [TMDB:292362] [IMDB:tt4078856]</span><br><span class="line"><span class="bullet"> -</span> 驴得水 (2016) [TMDB:421742] [IMDB:tt6167014]</span><br><span class="line"><span class="bullet"> -</span> 大佛普拉斯 (2017) [TMDB:475149] [IMDB:tt7010412]</span><br><span class="line"><span class="bullet"> -</span> 我不是药神 (2018) [TMDB:532753] [IMDB:tt7362036]</span><br><span class="line"><span class="bullet"> -</span> 飞驰人生 (2019) [TMDB:575219] [IMDB:tt9597190]</span><br><span class="line"><span class="bullet"> -</span> 三大队 (2023) [TMDB:1109586] [IMDB:tt28212677]</span><br><span class="line"><span class="bullet"> -</span> 年会不能停! (2023) [TMDB:1173076] [IMDB:tt27922369]</span><br><span class="line"><span class="bullet">-</span> 国产剧</span><br><span class="line"><span class="bullet"> -</span> 唐人街探案2 (1) [TMDB:247773] [IMDB:tt22475188]</span><br><span class="line"><span class="bullet"> -</span> 射雕英雄传 (1983) [TMDB:104] [IMDB:tt0274839]</span><br><span class="line"><span class="bullet"> -</span> 红楼梦 (1987) [TMDB:7191] [IMDB:tt1162595]</span><br><span class="line"><span class="bullet"> -</span> 三国演义 (1994) [TMDB:72645] [IMDB:tt0108914]</span><br><span class="line"><span class="bullet"> -</span> 水浒传 (1998) [TMDB:78132] [IMDB:tt1388431]</span><br><span class="line"><span class="bullet"> -</span> 狂飙 (2023) [TMDB:210757] [IMDB:tt26235088]</span><br><span class="line"><span class="bullet"> -</span> 猎冰 (2024) [TMDB:233958]</span><br><span class="line"><span class="bullet">-</span> 外语电影</span><br><span class="line"><span class="bullet"> -</span> 城市之光 (1931) [TMDB:901] [IMDB:tt0021749]</span><br><span class="line"><span class="bullet"> -</span> 摩登时代 (1936) [TMDB:3082] [IMDB:tt0027977]</span><br><span class="line"><span class="bullet"> -</span> 乱世佳人 (1939) [TMDB:770] [IMDB:tt0031381]</span><br><span class="line"><span class="bullet"> -</span> 魂断蓝桥 (1940) [TMDB:43824] [IMDB:tt0033238]</span><br><span class="line"><span class="bullet"> -</span> 罗生门 (1950) [TMDB:548] [IMDB:tt0042876]</span><br><span class="line"><span class="bullet"> -</span> 雨中曲 (1952) [TMDB:872] [IMDB:tt0045152]</span><br><span class="line"><span class="bullet"> -</span> 罗马假日 (1953) [TMDB:804] [IMDB:tt0046250]</span><br><span class="line"><span class="bullet"> -</span> 七武士 (1954) [TMDB:346] [IMDB:tt0047478]</span><br><span class="line"><span class="bullet"> -</span> 十二怒汉 (1957) [TMDB:389] [IMDB:tt0050083]</span><br><span class="line"><span class="bullet"> -</span> 控方证人 (1957) [TMDB:37257] [IMDB:tt0051201]</span><br><span class="line"><span class="bullet"> -</span> 惊魂记 (1960) [TMDB:539] [IMDB:tt0054215]</span><br><span class="line"><span class="bullet"> -</span> 虎口脱险 (1966) [TMDB:8290] [IMDB:tt0060474]</span><br><span class="line"><span class="bullet"> -</span> 2001太空漫游 (1968) [TMDB:62] [IMDB:tt0062622]</span><br><span class="line"><span class="bullet"> -</span> 教父 (1972) [TMDB:238] [IMDB:tt0068646]</span><br><span class="line"><span class="bullet"> -</span> 飞越疯人院 (1975) [TMDB:510] [IMDB:tt0073486]</span><br><span class="line"><span class="bullet"> -</span> 美国往事 (1984) [TMDB:311] [IMDB:tt0087843]</span><br><span class="line"><span class="bullet"> -</span> 忠犬八公物语 (1987) [TMDB:31743] [IMDB:tt0093132]</span><br><span class="line"><span class="bullet"> -</span> 末代皇帝 (1987) [TMDB:746] [IMDB:tt0093389]</span><br><span class="line"><span class="bullet"> -</span> 天堂电影院 (1988) [TMDB:11216] [IMDB:tt0095765]</span><br><span class="line"><span class="bullet"> -</span> 雨人 (1988) [TMDB:380] [IMDB:tt0095953]</span><br><span class="line"><span class="bullet"> -</span> 死亡诗社 (1989) [TMDB:207] [IMDB:tt0097165]</span><br><span class="line"><span class="bullet"> -</span> 沉默的羔羊 (1991) [TMDB:274] [IMDB:tt0102926]</span><br><span class="line"><span class="bullet"> -</span> 终结者2:审判日 (1991) [TMDB:280] [IMDB:tt0103064]</span><br><span class="line"><span class="bullet"> -</span> 闻香识女人 (1992) [TMDB:9475] [IMDB:tt0105323]</span><br><span class="line"><span class="bullet"> -</span> 完美的世界 (1993) [TMDB:9559] [IMDB:tt0107808]</span><br><span class="line"><span class="bullet"> -</span> 辛德勒的名单 (1993) [TMDB:424] [IMDB:tt0108052]</span><br><span class="line"><span class="bullet"> -</span> 低俗小说 (1994) [TMDB:680] [IMDB:tt0110912]</span><br><span class="line"><span class="bullet"> -</span> 燃情岁月 (1994) [TMDB:4476] [IMDB:tt0110322]</span><br><span class="line"><span class="bullet"> -</span> 肖申克的救赎 (1994) [TMDB:278] [IMDB:tt0111161]</span><br><span class="line"><span class="bullet"> -</span> 这个杀手不太冷 (1994) [TMDB:101] [IMDB:tt0110413]</span><br><span class="line"><span class="bullet"> -</span> 阿甘正传 (1994) [TMDB:13] [IMDB:tt0109830]</span><br><span class="line"><span class="bullet"> -</span> 七宗罪 (1995) [TMDB:807] [IMDB:tt0114369]</span><br><span class="line"><span class="bullet"> -</span> 勇敢的心 (1995) [TMDB:197] [IMDB:tt0112573]</span><br><span class="line"><span class="bullet"> -</span> 情书 (1995) [TMDB:47002] [IMDB:tt0113703]</span><br><span class="line"><span class="bullet"> -</span> 爱在黎明破晓前 (1995) [TMDB:76] [IMDB:tt0112471]</span><br><span class="line"><span class="bullet"> -</span> 猜火车 (1996) [TMDB:627] [IMDB:tt0117951]</span><br><span class="line"><span class="bullet"> -</span> 千钧一发 (1997) [TMDB:782] [IMDB:tt0119177]</span><br><span class="line"><span class="bullet"> -</span> 小鞋子 (1997) [TMDB:21334] [IMDB:tt0118849]</span><br><span class="line"><span class="bullet"> -</span> 心灵捕手 (1997) [TMDB:489] [IMDB:tt0119217]</span><br><span class="line"><span class="bullet"> -</span> 泰坦尼克号 (1997) [TMDB:597] [IMDB:tt0120338]</span><br><span class="line"><span class="bullet"> -</span> 美丽人生 (1997) [TMDB:637] [IMDB:tt0118799]</span><br><span class="line"><span class="bullet"> -</span> 拯救大兵瑞恩 (1998) [TMDB:857] [IMDB:tt0120815]</span><br><span class="line"><span class="bullet"> -</span> 搏击俱乐部 (1999) [TMDB:550] [IMDB:tt0137523]</span><br><span class="line"><span class="bullet"> -</span> 第六感 (1999) [TMDB:745] [IMDB:tt0167404]</span><br><span class="line"><span class="bullet"> -</span> 绿里奇迹 (1999) [TMDB:497] [IMDB:tt0120689]</span><br><span class="line"><span class="bullet"> -</span> 菊次郎的夏天 (1999) [TMDB:4291] [IMDB:tt0199683]</span><br><span class="line"><span class="bullet"> -</span> 黑客帝国 (1999) [TMDB:603] [IMDB:tt0133093]</span><br><span class="line"><span class="bullet"> -</span> 西西里的美丽传说 (2000) [TMDB:10867] [IMDB:tt0213847]</span><br><span class="line"><span class="bullet"> -</span> 记忆碎片 (2000) [TMDB:77] [IMDB:tt0209144]</span><br><span class="line"><span class="bullet"> -</span> 人工智能 (2001) [TMDB:644] [IMDB:tt0212720]</span><br><span class="line"><span class="bullet"> -</span> 哈利·波特与魔法石 (2001) [TMDB:671] [IMDB:tt0241527]</span><br><span class="line"><span class="bullet"> -</span> 天使爱美丽 (2001) [TMDB:194] [IMDB:tt0211915]</span><br><span class="line"><span class="bullet"> -</span> 我是山姆 (2001) [TMDB:10950] [IMDB:tt0277027]</span><br><span class="line"><span class="bullet"> -</span> 指环王1:护戒使者 (2001) [TMDB:120] [IMDB:tt0120737]</span><br><span class="line"><span class="bullet"> -</span> 美丽心灵 (2001) [TMDB:453] [IMDB:tt0268978]</span><br><span class="line"><span class="bullet"> -</span> 上帝之城 (2002) [TMDB:598] [IMDB:tt0317248]</span><br><span class="line"><span class="bullet"> -</span> 哈利·波特与密室 (2002) [TMDB:672] [IMDB:tt0295297]</span><br><span class="line"><span class="bullet"> -</span> 指环王2:双塔奇兵 (2002) [TMDB:121] [IMDB:tt0167261]</span><br><span class="line"><span class="bullet"> -</span> 猫鼠游戏 (2002) [TMDB:640] [IMDB:tt0264464]</span><br><span class="line"><span class="bullet"> -</span> 谍影重重 (2002) [TMDB:2501] [IMDB:tt0258463]</span><br><span class="line"><span class="bullet"> -</span> 钢琴家 (2002) [TMDB:423] [IMDB:tt0253474]</span><br><span class="line"><span class="bullet"> -</span> 加勒比海盗1:黑珍珠号的诅咒 (2003) [TMDB:22] [IMDB:tt0325980]</span><br><span class="line"><span class="bullet"> -</span> 大鱼 (2003) [TMDB:587] [IMDB:tt0319061]</span><br><span class="line"><span class="bullet"> -</span> 指环王3:王者无敌 (2003) [TMDB:122] [IMDB:tt0167260]</span><br><span class="line"><span class="bullet"> -</span> 杀人回忆 (2003) [TMDB:11423] [IMDB:tt0353969]</span><br><span class="line"><span class="bullet"> -</span> 真爱至上 (2003) [TMDB:508] [IMDB:tt0314331]</span><br><span class="line"><span class="bullet"> -</span> 致命ID (2003) [TMDB:2832] [IMDB:tt0309698]</span><br><span class="line"><span class="bullet"> -</span> 黑客帝国2:重装上阵 (2003) [TMDB:604] [IMDB:tt0234215]</span><br><span class="line"><span class="bullet"> -</span> 黑客帝国3:矩阵革命 (2003) [TMDB:605] [IMDB:tt0242653]</span><br><span class="line"><span class="bullet"> -</span> 卢旺达饭店 (2004) [TMDB:205] [IMDB:tt0395169]</span><br><span class="line"><span class="bullet"> -</span> 哈利·波特与阿兹卡班的囚徒 (2004) [TMDB:673] [IMDB:tt0304141]</span><br><span class="line"><span class="bullet"> -</span> 幸福终点站 (2004) [TMDB:594] [IMDB:tt0362227]</span><br><span class="line"><span class="bullet"> -</span> 恋恋笔记本 (2004) [TMDB:11036] [IMDB:tt0332280]</span><br><span class="line"><span class="bullet"> -</span> 放牛班的春天 (2004) [TMDB:5528] [IMDB:tt0372824]</span><br><span class="line"><span class="bullet"> -</span> 无人知晓 (2004) [TMDB:2517] [IMDB:tt0408664]</span><br><span class="line"><span class="bullet"> -</span> 爱在日落黄昏时 (2004) [TMDB:80] [IMDB:tt0381681]</span><br><span class="line"><span class="bullet"> -</span> 电锯惊魂 (2004) [TMDB:176] [IMDB:tt0387564]</span><br><span class="line"><span class="bullet"> -</span> 蝴蝶效应 (2004) [TMDB:1954] [IMDB:tt0289879]</span><br><span class="line"><span class="bullet"> -</span> 谍影重重2 (2004) [TMDB:2502] [IMDB:tt0372183]</span><br><span class="line"><span class="bullet"> -</span> 傲慢与偏见 (2005) [TMDB:4348] [IMDB:tt0414387]</span><br><span class="line"><span class="bullet"> -</span> 哈利·波特与火焰杯 (2005) [TMDB:674] [IMDB:tt0330373]</span><br><span class="line"><span class="bullet"> -</span> 战争之王 (2005) [TMDB:1830] [IMDB:tt0399295]</span><br><span class="line"><span class="bullet"> -</span> 断背山 (2005) [TMDB:142] [IMDB:tt0388795]</span><br><span class="line"><span class="bullet"> -</span> 当幸福来敲门 (2006) [TMDB:1402] [IMDB:tt0454921]</span><br><span class="line"><span class="bullet"> -</span> 窃听风暴 (2006) [TMDB:582] [IMDB:tt0405094]</span><br><span class="line"><span class="bullet"> -</span> 致命魔术 (2006) [TMDB:1124] [IMDB:tt0482571]</span><br><span class="line"><span class="bullet"> -</span> 血钻 (2006) [TMDB:1372] [IMDB:tt0450259]</span><br><span class="line"><span class="bullet"> -</span> 香水 (2006) [TMDB:1427] [IMDB:tt0396171]</span><br><span class="line"><span class="bullet"> -</span> 地球上的星星 (2007) [TMDB:7508] [IMDB:tt0986264]</span><br><span class="line"><span class="bullet"> -</span> 谍影重重3 (2007) [TMDB:2503] [IMDB:tt0440963]</span><br><span class="line"><span class="bullet"> -</span> 遗愿清单 (2007) [TMDB:7350] [IMDB:tt0825232]</span><br><span class="line"><span class="bullet"> -</span> 入殓师 (2008) [TMDB:16804] [IMDB:tt1069238]</span><br><span class="line"><span class="bullet"> -</span> 朗读者 (2008) [TMDB:8055] [IMDB:tt0976051]</span><br><span class="line"><span class="bullet"> -</span> 本杰明·巴顿奇事 (2008) [TMDB:4922] [IMDB:tt0421715]</span><br><span class="line"><span class="bullet"> -</span> 步履不停 (2008) [TMDB:25050] [IMDB:tt1087578]</span><br><span class="line"><span class="bullet"> -</span> 浪潮 (2008) [TMDB:7735] [IMDB:tt1063669]</span><br><span class="line"><span class="bullet"> -</span> 穿条纹睡衣的男孩 (2008) [TMDB:14574] [IMDB:tt0914798]</span><br><span class="line"><span class="bullet"> -</span> 蝙蝠侠:黑暗骑士 (2008) [TMDB:155] [IMDB:tt0468569]</span><br><span class="line"><span class="bullet"> -</span> 贫民窟的百万富翁 (2008) [TMDB:12405] [IMDB:tt1010048]</span><br><span class="line"><span class="bullet"> -</span> 三傻大闹宝莱坞 (2009) [TMDB:20453] [IMDB:tt1187043]</span><br><span class="line"><span class="bullet"> -</span> 恐怖游轮 (2009) [TMDB:26466] [IMDB:tt1187064]</span><br><span class="line"><span class="bullet"> -</span> 无耻混蛋 (2009) [TMDB:16869] [IMDB:tt0361748]</span><br><span class="line"><span class="bullet"> -</span> 阿凡达 (2009) [TMDB:19995] [IMDB:tt0499549]</span><br><span class="line"><span class="bullet"> -</span> 告白 (2010) [TMDB:54186] [IMDB:tt1590089]</span><br><span class="line"><span class="bullet"> -</span> 怦然心动 (2010) [TMDB:43949] [IMDB:tt0817177]</span><br><span class="line"><span class="bullet"> -</span> 盗梦空间 (2010) [TMDB:27205] [IMDB:tt1375666]</span><br><span class="line"><span class="bullet"> -</span> 禁闭岛 (2010) [TMDB:11324] [IMDB:tt1130884]</span><br><span class="line"><span class="bullet"> -</span> 黑天鹅 (2010) [TMDB:44214] [IMDB:tt0947798]</span><br><span class="line"><span class="bullet"> -</span> 哈利·波特与死亡圣器(下) (2011) [TMDB:12445] [IMDB:tt1201607]</span><br><span class="line"><span class="bullet"> -</span> 我爱你 (2011) [TMDB:72575] [IMDB:tt1862020]</span><br><span class="line"><span class="bullet"> -</span> 源代码 (2011) [TMDB:45612] [IMDB:tt0945513]</span><br><span class="line"><span class="bullet"> -</span> 熔炉 (2011) [TMDB:81481] [IMDB:tt2070649]</span><br><span class="line"><span class="bullet"> -</span> 触不可及 (2011) [TMDB:77338] [IMDB:tt1675434]</span><br><span class="line"><span class="bullet"> -</span> 超脱 (2011) [TMDB:74308] [IMDB:tt1683526]</span><br><span class="line"><span class="bullet"> -</span> 3 (2012) [TMDB:79660] [IMDB:tt2123129]</span><br><span class="line"><span class="bullet"> -</span> 少年派的奇幻漂流 (2012) [TMDB:87827] [IMDB:tt0454876]</span><br><span class="line"><span class="bullet"> -</span> 蝙蝠侠:黑暗骑士崛起 (2012) [TMDB:49026] [IMDB:tt1345836]</span><br><span class="line"><span class="bullet"> -</span> 被解救的姜戈 (2012) [TMDB:68718] [IMDB:tt1853728]</span><br><span class="line"><span class="bullet"> -</span> 七号房的礼物 (2013) [TMDB:158445] [IMDB:tt2659414]</span><br><span class="line"><span class="bullet"> -</span> 彗星来的那一夜 (2013) [TMDB:220289] [IMDB:tt2866360]</span><br><span class="line"><span class="bullet"> -</span> 恐怖直播 (2013) [TMDB:209764] [IMDB:tt2990738]</span><br><span class="line"><span class="bullet"> -</span> 新世界 (2013) [TMDB:165213] [IMDB:tt2625030]</span><br><span class="line"><span class="bullet"> -</span> 时空恋旅人 (2013) [TMDB:122906] [IMDB:tt2194499]</span><br><span class="line"><span class="bullet"> -</span> 爱在午夜降临前 (2013) [TMDB:132344] [IMDB:tt2209418]</span><br><span class="line"><span class="bullet"> -</span> 素媛 (2013) [TMDB:255709] [IMDB:tt3153634]</span><br><span class="line"><span class="bullet"> -</span> 辩护人 (2013) [TMDB:242452] [IMDB:tt3404140]</span><br><span class="line"><span class="bullet"> -</span> 达拉斯买家俱乐部 (2013) [TMDB:152532] [IMDB:tt0790636]</span><br><span class="line"><span class="bullet"> -</span> 2 (2014) [TMDB:480682] [IMDB:tt3529830]</span><br><span class="line"><span class="bullet"> -</span> 小森林:夏秋篇 (2014) [TMDB:294682] [IMDB:tt3474600]</span><br><span class="line"><span class="bullet"> -</span> 布达佩斯大饭店 (2014) [TMDB:120467] [IMDB:tt2278388]</span><br><span class="line"><span class="bullet"> -</span> 星际穿越 (2014) [TMDB:157336] [IMDB:tt0816692]</span><br><span class="line"><span class="bullet"> -</span> 模仿游戏 (2014) [TMDB:205596] [IMDB:tt2084970]</span><br><span class="line"><span class="bullet"> -</span> 消失的爱人 (2014) [TMDB:210577] [IMDB:tt2267998]</span><br><span class="line"><span class="bullet"> -</span> 荒蛮故事 (2014) [TMDB:265195] [IMDB:tt3011894]</span><br><span class="line"><span class="bullet"> -</span> 一个叫欧维的男人决定去死 (2015) [TMDB:348678] [IMDB:tt4080728]</span><br><span class="line"><span class="bullet"> -</span> 小森林:冬春篇 (2015) [TMDB:336026] [IMDB:tt3474602]</span><br><span class="line"><span class="bullet"> -</span> 小萝莉的猴神大叔 (2015) [TMDB:348892] [IMDB:tt3863552]</span><br><span class="line"><span class="bullet"> -</span> 房间 (2015) [TMDB:264644] [IMDB:tt3170832]</span><br><span class="line"><span class="bullet"> -</span> 海蒂和爷爷 (2015) [TMDB:365045] [IMDB:tt3700392]</span><br><span class="line"><span class="bullet"> -</span> 海街日记 (2015) [TMDB:315846] [IMDB:tt3756788]</span><br><span class="line"><span class="bullet"> -</span> 火星救援 (2015) [TMDB:286217] [IMDB:tt3659388]</span><br><span class="line"><span class="bullet"> -</span> 疯狂的麦克斯4:狂暴之路 (2015) [TMDB:76341] [IMDB:tt1392190]</span><br><span class="line"><span class="bullet"> -</span> 聚焦 (2015) [TMDB:314365] [IMDB:tt1895587]</span><br><span class="line"><span class="bullet"> -</span> 完美陌生人 (2016) [TMDB:381341] [IMDB:tt4901306]</span><br><span class="line"><span class="bullet"> -</span> 摔跤吧!爸爸 (2016) [TMDB:360814] [IMDB:tt5074352]</span><br><span class="line"><span class="bullet"> -</span> 海边的曼彻斯特 (2016) [TMDB:334541] [IMDB:tt4034228]</span><br><span class="line"><span class="bullet"> -</span> 血战钢锯岭 (2016) [TMDB:324786] [IMDB:tt2119532]</span><br><span class="line"><span class="bullet"> -</span> 釜山行 (2016) [TMDB:396535] [IMDB:tt5700672]</span><br><span class="line"><span class="bullet"> -</span> 三块广告牌 (2017) [TMDB:359940] [IMDB:tt5027774]</span><br><span class="line"><span class="bullet"> -</span> 奇迹男孩 (2017) [TMDB:406997] [IMDB:tt2543472]</span><br><span class="line"><span class="bullet"> -</span> 看不见的客人 (2017) [TMDB:411088] [IMDB:tt4857264]</span><br><span class="line"><span class="bullet"> -</span> 请以你的名字呼唤我 (2017) [TMDB:398818] [IMDB:tt5726616]</span><br><span class="line"><span class="bullet"> -</span> 何以为家 (2018) [TMDB:517814] [IMDB:tt8267604]</span><br><span class="line"><span class="bullet"> -</span> 头号玩家 (2018) [TMDB:333339] [IMDB:tt1677720]</span><br><span class="line"><span class="bullet"> -</span> 小偷家族 (2018) [TMDB:505192] [IMDB:tt8075192]</span><br><span class="line"><span class="bullet"> -</span> 绿皮书 (2018) [TMDB:490132] [IMDB:tt6966692]</span><br><span class="line"><span class="bullet"> -</span> 阳光姐妹淘 (2018) [TMDB:517065] [IMDB:tt7493818]</span><br><span class="line"><span class="bullet"> -</span> 小丑 (2019) [TMDB:475557] [IMDB:tt7286456]</span><br><span class="line"><span class="bullet">-</span> 新番</span><br><span class="line"><span class="bullet"> -</span> 小不点 (1983) [TMDB:17400] [IMDB:tt0320055]</span><br><span class="line"><span class="bullet"> -</span> 青之驱魔师 (2011) [TMDB:38464] [IMDB:tt1799631]</span><br><span class="line"><span class="bullet"> -</span> 王者天下 (2012) [TMDB:46437] [IMDB:tt2404499]</span><br><span class="line"><span class="bullet"> -</span> 暗芝居 (2013) [TMDB:56559] [IMDB:tt3111906]</span><br><span class="line"><span class="bullet"> -</span> 欢迎来到实力至上主义的教室 (2017) [TMDB:72517] [IMDB:tt7263328]</span><br><span class="line"><span class="bullet"> -</span> 足球小将 (2018) [TMDB:77240] [IMDB:tt7784442]</span><br><span class="line"><span class="bullet"> -</span> 卡片战斗先导者overDress (2021) [TMDB:106301] [IMDB:tt13872472]</span><br><span class="line"><span class="bullet"> -</span> 弱势角色友崎君 (2021) [TMDB:99083] [IMDB:tt13103028]</span><br><span class="line"><span class="bullet"> -</span> 我被逐出队伍后过上慢生活 (2021) [TMDB:113256] [IMDB:tt13483212]</span><br><span class="line"><span class="bullet"> -</span> 月光下的异世界之旅 (2021) [TMDB:111819] [IMDB:tt13311344]</span><br><span class="line"><span class="bullet"> -</span> 新 福星小子 (2022) [TMDB:154524] [IMDB:tt16764368]</span><br><span class="line"><span class="bullet"> -</span> 不死不幸 (2023) [TMDB:209077] [IMDB:tt21927720]</span><br><span class="line"><span class="bullet"> -</span> 奇异贤伴 黑色天使 (2023) [TMDB:210181] [IMDB:tt24240038]</span><br><span class="line"><span class="bullet"> -</span> 广阔天空!光之美少女 (2023) [TMDB:213883] [IMDB:tt23862502]</span><br><span class="line"><span class="bullet"> -</span> 我心里危险的东西 (2023) [TMDB:207250] [IMDB:tt21423786]</span><br><span class="line"><span class="bullet"> -</span> 烈焰先锋:救国的橘衣消防员 (2023) [TMDB:223780] [IMDB:tt29201691]</span><br><span class="line"><span class="bullet"> -</span> 爱犬指令 (2023) [TMDB:229613]</span><br><span class="line"><span class="bullet"> -</span> 物理魔法使-马修- (2023) [TMDB:204832] [IMDB:tt21209804]</span><br><span class="line"><span class="bullet"> -</span> 狩火之王 (2023) [TMDB:156688] [IMDB:tt21912036]</span><br><span class="line"><span class="bullet"> -</span> 狩龙人拉格纳 (2023) [TMDB:195459] [IMDB:tt28685470]</span><br><span class="line"><span class="bullet"> -</span> 至高之牌 (2023) [TMDB:194665] [IMDB:tt25275610]</span><br><span class="line"><span class="bullet"> -</span> 药屋少女的呢喃 (2023) [TMDB:220542] [IMDB:tt26743760]</span><br><span class="line"><span class="bullet"> -</span> 葬送的芙莉莲 (2023) [TMDB:209867] [IMDB:tt22248376]</span><br><span class="line"><span class="bullet"> -</span> 逃走中 THE GREAT MISSION (2023) [TMDB:217388]</span><br><span class="line"><span class="bullet"> -</span> 香格里拉边境 (2023) [TMDB:205050] [IMDB:tt28776190]</span><br><span class="line"><span class="bullet"> -</span> Wonderful 光之美少女! (2024) [TMDB:243216] [IMDB:tt30608459]</span><br><span class="line"><span class="bullet"> -</span> 为了在异世界也能抚摸毛茸茸而努力。 (2024) [TMDB:205672] [IMDB:tt30689225]</span><br><span class="line"><span class="bullet"> -</span> 事与愿违的不死冒险者 (2024) [TMDB:197848] [IMDB:tt30177477]</span><br><span class="line"><span class="bullet"> -</span> 休假日的坏人先生 (2024) [TMDB:222784] [IMDB:tt29467317]</span><br><span class="line"><span class="bullet"> -</span> 佐佐木与文鸟小哔 (2024) [TMDB:206630] [IMDB:tt27524116]</span><br><span class="line"><span class="bullet"> -</span> 公主殿下“拷问”的时间到了 (2024) [TMDB:229443] [IMDB:tt30643998]</span><br><span class="line"><span class="bullet"> -</span> 到了30岁还是处男,似乎会变成魔法师 (2024) [TMDB:237045] [IMDB:tt28369144]</span><br><span class="line"><span class="bullet"> -</span> 勇气爆发BangBravern (2024) [TMDB:238846] [IMDB:tt30975941]</span><br><span class="line"><span class="bullet"> -</span> 北海道辣妹贼拉可爱 (2024) [TMDB:213181] [IMDB:tt23029874]</span><br><span class="line"><span class="bullet"> -</span> 反派大小姐等级99~我是隐藏BOSS但不是魔王~ (2024) [TMDB:222930] [IMDB:tt30495119]</span><br><span class="line"><span class="bullet"> -</span> 外科医生爱丽丝 (2024) [TMDB:221310] [IMDB:tt28247170]</span><br><span class="line"><span class="bullet"> -</span> 婚戒物语 (2024) [TMDB:218493] [IMDB:tt30488398]</span><br><span class="line"><span class="bullet"> -</span> 异世界温泉开拓记 (2024) [TMDB:241021] [IMDB:tt30644058]</span><br><span class="line"><span class="bullet"> -</span> 异修罗 (2024) [TMDB:220286] [IMDB:tt26713948]</span><br><span class="line"><span class="bullet"> -</span> 愚蠢天使与恶魔共舞 (2024) [TMDB:231357] [IMDB:tt30495098]</span><br><span class="line"><span class="bullet"> -</span> 憧憬成为魔法少女 (2024) [TMDB:236338] [IMDB:tt29605390]</span><br><span class="line"><span class="bullet"> -</span> 我独自升级 (2024) [TMDB:127532] [IMDB:tt21209876]</span><br><span class="line"><span class="bullet"> -</span> 战国妖狐 (2024) [TMDB:234995] [IMDB:tt30325850]</span><br><span class="line"><span class="bullet"> -</span> 指尖相触,恋恋不舍 (2024) [TMDB:230059] [IMDB:tt30024091]</span><br><span class="line"><span class="bullet"> -</span> 挣扎吧,亚当 (2024) [TMDB:241002]</span><br><span class="line"><span class="bullet"> -</span> 无人能敌 (2024) [TMDB:226905] [IMDB:tt28454318]</span><br><span class="line"><span class="bullet"> -</span> 明治击剑-1874- (2024) [TMDB:99787] [IMDB:tt30495035]</span><br><span class="line"><span class="bullet"> -</span> 最弱的驯养师开启的捡垃圾的旅途 (2024) [TMDB:214310] [IMDB:tt30644010]</span><br><span class="line"><span class="bullet"> -</span> 最强肉盾的迷宫攻略~拥有稀少技能体力9999的肉盾,被勇者队伍辞退了~ (2024) [TMDB:236532] [IMDB:tt30643971]</span><br><span class="line"><span class="bullet"> -</span> 月刊妄想科学 (2024) [TMDB:236142] [IMDB:tt30494894]</span><br><span class="line"><span class="bullet"> -</span> 治愈魔法的错误使用方法 (2024) [TMDB:131365] [IMDB:tt15237152]</span><br><span class="line"><span class="bullet"> -</span> 百千家的妖怪王子 (2024) [TMDB:230823] [IMDB:tt30691068]</span><br><span class="line"><span class="bullet"> -</span> 碰之道 (2024) [TMDB:234176] [IMDB:tt31309480]</span><br><span class="line"><span class="bullet"> -</span> 秒杀外挂太强了,异世界的家伙们根本就不是对手。 (2024) [TMDB:236144] [IMDB:tt30146725]</span><br><span class="line"><span class="bullet"> -</span> 轮回七次的恶役千金在前敌国享受随心所欲的新婚生活 (2024) [TMDB:232926] [IMDB:tt28685624]</span><br><span class="line"><span class="bullet"> -</span> 迷宫饭 (2024) [TMDB:207784] [IMDB:tt21621494]</span><br><span class="line"><span class="bullet"> -</span> 金属口红 (2024) [TMDB:222787] [IMDB:tt29510641]</span><br><span class="line"><span class="bullet"> -</span> 零食八江 (2024) [TMDB:236930] [IMDB:tt29474142]</span><br><span class="line"><span class="bullet"> -</span> 魔女与野兽 (2024) [TMDB:208445] [IMDB:tt30089363]</span><br><span class="line"><span class="bullet"> -</span> 魔都精兵的奴隶 (2024) [TMDB:139060] [IMDB:tt16156736]</span><br><span class="line"><span class="bullet">-</span> 演唱会</span><br><span class="line"><span class="bullet"> -</span> 音乐之声 (1965) [TMDB:15121] [IMDB:tt0059742]</span><br><span class="line"><span class="bullet"> -</span> 海上钢琴师 (1998) [TMDB:10376] [IMDB:tt0120731]</span><br><span class="line"><span class="bullet"> -</span> 千年女优:轨迹 (2001) [TMDB:968100]</span><br><span class="line"><span class="bullet"> -</span> 被嫌弃的松子的一生 (2006) [TMDB:31512] [IMDB:tt0768120]</span><br><span class="line"><span class="bullet"> -</span> 海豚湾 (2009) [TMDB:23128] [IMDB:tt1313104]</span><br><span class="line"><span class="bullet"> -</span> 海洋 (2010) [TMDB:36970] [IMDB:tt0765128]</span><br><span class="line"><span class="bullet"> -</span> 再次出发之纽约遇见你 (2013) [TMDB:198277] [IMDB:tt1980929]</span><br><span class="line"><span class="bullet"> -</span> 爆裂鼓手 (2014) [TMDB:244786] [IMDB:tt2582802]</span><br><span class="line"><span class="bullet"> -</span> 爱乐之城 (2016) [TMDB:313369] [IMDB:tt3783958]</span><br><span class="line"><span class="bullet"> -</span> 二十二 (2017) [TMDB:473267] [IMDB:tt3843282]</span><br><span class="line"><span class="bullet"> -</span> 寻梦环游记 (2017) [TMDB:354912] [IMDB:tt2380307]</span><br><span class="line"><span class="bullet"> -</span> 波西米亚狂想曲 (2018) [TMDB:424694] [IMDB:tt1727824]</span><br></pre></td></tr></table></figure><h3 id="1-国产剧"><a href="#1-国产剧" class="headerlink" title="1. 国产剧"></a>1. 国产剧</h3><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240318162248208.jpg" alt="image-20240318162248208"></p><h3 id="2-日韩剧"><a href="#2-日韩剧" class="headerlink" title="2. 日韩剧"></a>2. 日韩剧</h3><p>暂无</p><h3 id="3-外语电影"><a href="#3-外语电影" class="headerlink" title="3. 外语电影"></a>3. 外语电影</h3><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240318162441339.jpg" alt="image-20240318162441339"></p><h3 id="4-华语电影"><a href="#4-华语电影" class="headerlink" title="4. 华语电影"></a>4. 华语电影</h3><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240318162226440.jpg" alt="image-20240318162226440"></p><h3 id="5-动画电影"><a href="#5-动画电影" class="headerlink" title="5. 动画电影"></a>5. 动画电影</h3><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240318161717332.jpg" alt="image-20240318161717332"></p><h3 id="6-演唱会"><a href="#6-演唱会" class="headerlink" title="6. 演唱会"></a>6. 演唱会</h3><p><img src="/../../img/%E5%AA%92%E4%BD%93%E5%BA%93%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/image-20240318162535713.jpg" alt="image-20240318162535713"></p><hr><p><img src="/../../assets/user/about_me.jpg" alt="欢迎关注我的其他平台"></p>]]></content>
<summary type="html">All in one 主机基本搭建完成了,这次媒体库也得到了一次大升级,目前先开放媒体库进行测试,后续会更新媒体库详细的搭建指南。</summary>
<category term="技术分享" scheme="https://blog.sakurasep.site/categories/%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/"/>
<category term="Emby" scheme="https://blog.sakurasep.site/tags/Emby/"/>
<category term="Telegram" scheme="https://blog.sakurasep.site/tags/Telegram/"/>
<category term="媒体库" scheme="https://blog.sakurasep.site/tags/%E5%AA%92%E4%BD%93%E5%BA%93/"/>
<category term="Infuse" scheme="https://blog.sakurasep.site/tags/Infuse/"/>
</entry>
<entry>
<title>TeamSpeak使用指南</title>
<link href="https://blog.sakurasep.site/posts/TeamSpeak/"/>
<id>https://blog.sakurasep.site/posts/TeamSpeak/</id>
<published>2023-12-22T16:30:03.000Z</published>
<updated>2023-12-22T16:00:00.000Z</updated>
<content type="html"><![CDATA[<h2 id="一、为什么我们不再使用KOOK"><a href="#一、为什么我们不再使用KOOK" class="headerlink" title="一、为什么我们不再使用KOOK"></a>一、为什么我们不再使用KOOK</h2><p>KOOK(原开黑啦),这款软件从开始发行就是抄袭国外的社群交流软件Discord,当他起初发行的时候,有高清的屏幕分享,良好的语音通话质量,还有很不错的AI降噪. 此外开黑啦在起初也是没有任何广告和会员特效.</p><p>但是随着免费高质量所积累的用户逐渐扩大,开黑啦担心侵权问题,随即改名KOOK,从此有了会员,语音质量和服务器助力包挂钩,添加了各种花里胡哨的特效,此外它的核心功能AI降噪也变成了每日120分钟体验. 可以说,KOOK将大多数国产软件先引流后狠狠收费的丑恶嘴脸表现到了极致.</p><p>虽然目前市面上还有很多语音软件,如vk老头的语音,黑盒语音,但是我们无法保证这些软件是否会走向KOOK的老路.因此,免费的TeamSpeak成为了我们的首选,它是各大电竞赛事的首选语音交流软件,如CSGO的Major等赛事.它的免费版支持最高7.71KiB/s的音质,此外他的回声消除等功能有效的防止背景嘈杂的声音,它的频道也支持文字交流,相信这样一款专业简洁的语音交流软件可以成为我们今后开黑的神器!</p><h2 id="二、如何使用TeamSpeak"><a href="#二、如何使用TeamSpeak" class="headerlink" title="二、如何使用TeamSpeak"></a>二、如何使用TeamSpeak</h2><h3 id="1-下载与安装"><a href="#1-下载与安装" class="headerlink" title="1. 下载与安装"></a>1. 下载与安装</h3><p>首先,请不要在百度中搜索下载,因为你大概率会进入TeamSpeak中文网,这是盗版网站,和Steam游戏管家是一个道理</p><div class="tag-plugin link dis-select"><a class="link-card rich" title="TeamSpeak官方网站" href="https://teamspeak.com/zh-CN/" target="_blank" rel="external nofollow noopener noreferrer" cardlink api="https://site-info-api-git-main-sakurasep.vercel.app/api/v1?url=https://teamspeak.com/zh-CN/" autofill="icon,desc"><div class="top"><div class="lazy img" data-bg="https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.12/link/8f277b4ee0ecd.svg"></div><span class="cap link footnote">https://teamspeak.com/zh-CN/</span></div><div class="bottom"><span class="title">TeamSpeak官方网站</span><span class="cap desc footnote"></span></div></a></div><p>从这里下载客户端即可.</p><p>点击下载后来到这个界面,选择TS3 Client,因为目前TS5的汉化还没有做好,TS3有完美汉化</p><p>然后就是正常进行安装,中途会问你时候安装overwolf,这个是TeamSpeak的插件,用于在游戏内显示当前频道是谁在讲话</p><h3 id="2-加入我的服务器"><a href="#2-加入我的服务器" class="headerlink" title="2. 加入我的服务器"></a>2. 加入我的服务器</h3><p>根据下图所示填入服务器的名字<div class="tag-plugin copy"><input class="copy-area" id="copy_4" value="没有软蛋"><button class="copy-btn" onclick="util.copy("copy_4","复制成功")"><svg class="icon copy-btn" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M5.75 1a.75.75 0 00-.75.75v3c0 .414.336.75.75.75h4.5a.75.75 0 00.75-.75v-3a.75.75 0 00-.75-.75h-4.5zm.75 3V2.5h3V4h-3zm-2.874-.467a.75.75 0 00-.752-1.298A1.75 1.75 0 002 3.75v9.5c0 .966.784 1.75 1.75 1.75h8.5A1.75 1.75 0 0014 13.25v-9.5a1.75 1.75 0 00-.874-1.515.75.75 0 10-.752 1.298.25.25 0 01.126.217v9.5a.25.25 0 01-.25.25h-8.5a.25.25 0 01-.25-.25v-9.5a.25.25 0 01.126-.217z"></path></svg></button></div>,密码在群里,昵称改成你想显示的昵称,然后就可以连接了!</p><h3 id="3-如何配置TeamSpeak"><a href="#3-如何配置TeamSpeak" class="headerlink" title="3. 如何配置TeamSpeak"></a>3. 如何配置TeamSpeak</h3><p>这是TeamSpeak的简洁UI</p><p>点开偏好设置,最重要的是以下两个设置,首先让我们来看音频输出设置</p><p>然后是音频输入设置,注意这里根据你实际情况调整消除背景噪音的强度以及语音识别的阈值</p><h2 id="三、如何搭建一个TeamSpeak服务器"><a href="#三、如何搭建一个TeamSpeak服务器" class="headerlink" title="三、如何搭建一个TeamSpeak服务器"></a>三、如何搭建一个TeamSpeak服务器</h2><p>如果是仅仅搭建一个稳定可靠的语音服务器,那使用Linux + Docker是最为稳妥的方案</p><h3 id="1-通过Docker安装-Linux"><a href="#1-通过Docker安装-Linux" class="headerlink" title="1. 通过Docker安装(Linux)"></a>1. 通过Docker安装(Linux)</h3><p>零基础教程面向的是普通用户,所以这里建议使用1Panel面板对Linux系统进行简单的可视化管理</p><h2 id="四、结语"><a href="#四、结语" class="headerlink" title="四、结语"></a>四、结语</h2><p>相信到这里你就了解如何使用以及搭建属于你和你朋友自己的语音服务器,希望我的文章能帮助到你,下一篇文章再见!欢迎在评论区和大家交流你对TeamSpeak还有哪些有趣的玩法!</p><hr><p><img src="/../../assets/user/about_me.jpg" alt="欢迎关注我的其他平台"></p>]]></content>
<summary type="html">本篇文章是一篇简单的入门使用教程,后续将会更新部署教程.</summary>
<category term="技术分享" scheme="https://blog.sakurasep.site/categories/%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/"/>
<category term="零基础" scheme="https://blog.sakurasep.site/tags/%E9%9B%B6%E5%9F%BA%E7%A1%80/"/>
<category term="游戏" scheme="https://blog.sakurasep.site/tags/%E6%B8%B8%E6%88%8F/"/>
</entry>
</feed>