-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsearch.xml
475 lines (228 loc) · 581 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>面试题-Spring篇</title>
<link href="/posts/828907ec.html"/>
<url>/posts/828907ec.html</url>
<content type="html"><![CDATA[<h1>Spring篇</h1><h2 id="1-什么是Spring?">1. 什么是Spring?</h2><p>Spring 是个java企业级应用的开源开发框架。Spring主要用来开发Java应用,但是有些扩展是针对构建J2EE平台的web应用。Spring 框架目标是简化Java企业级应用开发,并通过POJO为基础的编程模型促进良好的编程习惯。</p><h2 id="2-项目中为什么使用Spring框架?">2. 项目中为什么使用Spring框架?</h2><ul><li><strong>轻量</strong>:Spring 是轻量的,基本的版本大约2MB。</li><li><strong>控制反转</strong>:Spring通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是创建或查找依赖的对象们。</li><li><strong>面向切面的编程(AOP)</strong>:Spring支持面向切面的编程,并且把应用业务逻辑和系统服务分开。</li><li><strong>IOC容器</strong>:Spring 包含并管理应用中对象的生命周期和配置。</li><li><strong>MVC框架</strong>:Spring的WEB框架是个精心设计的框架,是Web框架的一个很好的替代品。</li><li><strong>事务管理</strong>:Spring 提供一个持续的事务管理接口,可以扩展到上至本地事务下至全局事务(JTA)。</li><li><strong>异常处理</strong>:Spring 提供方便的API把具体技术相关的异常(比如由JDBC,Hibernate or JDO抛出的)转化为一致的unchecked异常</li></ul><h2 id="3-依赖注入的方式有几种,各是什么">3. 依赖注入的方式有几种,各是什么?</h2><ol><li><strong>构造器注入</strong>将被依赖对象通过构造函数的参数注入给依赖对象,并且在初始化对象的时候注入。<ul><li>优点: 对象初始化完成后便可获得可使用的对象。</li><li>缺点: 当需要注入的对象很多时,构造器参数列表将会很长; 不够灵活。若有多种注入方式,每种方式只需注入指定几个依赖,那么就需要提供多个重载的构造函数,麻烦。</li></ul></li><li><strong>setter方法注入</strong>IoC Service Provider通过调用成员变量提供的setter函数将被依赖对象注入给依赖类。<ul><li>优点: 灵活。可以选择性地注入需要的对象。</li><li>缺点: 依赖对象初始化完成后由于尚未注入被依赖对象,因此还不能使用。</li></ul></li><li><strong>接口注入</strong>依赖类必须要实现指定的接口,然后实现该接口中的一个函数,该函数就是用于依赖注入。该函数的参数就是要注入的对象。<ul><li>优点 接口注入中,接口的名字、函数的名字都不重要,只要保证函数的参数是要注入的对象类型即可。</li><li>缺点: 侵入行太强,不建议使用。</li></ul></li></ol><p>PS:什么是侵入行? 如果类A要使用别人提供的一个功能,若为了使用这功能,需要在自己的类中<br>增加额外的代码,这就是侵入性。</p><h2 id="4-说说你对Spring-MVC的理解">4. 说说你对Spring MVC的理解</h2><p>MVC:MVC是一种设计模式</p><ul><li><p>工作原理:</p><ol><li>用户发送请求至前端控制器DispatcherServlet。</li><li>DispatcherServlet收到请求调用HandlerMapping处理器映射器。</li><li>处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。</li><li>DispatcherServlet调用HandlerAdapter处理器适配器。</li><li>HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。</li><li>Controller执行完成返回ModelAndView。</li><li>HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。</li><li>DispatcherServlet将ModelAndView传给ViewReslover视图解析器。</li><li>ViewReslover解析后返回具体View。</li><li>DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。</li><li>DispatcherServlet响应用户。</li></ol></li><li><p>常用的注解:</p><ul><li>@RequestMapping:用于处理请求 url 映射的注解,可用于类或方法上。用于类上,则表示类中的所有响应请求的方法都是以该地址作为父路径。</li><li>@RequestBody:注解实现接收http请求的json数据,将json转换为java对象。</li><li>@ResponseBody:注解实现将conreoller方法返回对象转化为json对象响应给客户</li></ul></li></ul><h2 id="5-Spring-框架中的单例-Bean-是线程安全的么?">5. Spring 框架中的单例 Bean 是线程安全的么?</h2><p>Spring 框架并没有对单例 Bean 进行任何多线程的封装处理。</p><ul><li>关于单例 Bean 的线程安全和并发问题,需要开发者自行去搞定。</li><li>单例的线程安全问题,并不是 Spring 应该去关心的。Spring 应该做的是,提供根据配置,创建单例 Bean 或多例 Bean 的功能。当然,但实际上,大部分的 Spring Bean 并没有可变的状态,所以在某种程度上说 Spring 的单例Bean 是线程安全的。如果你的 Bean 有多种状态的话,就需要自行保证线程安全。最浅显的解决办法,就是将多态 Bean 的作用域(Scope)由 Singleton 变更为 Prototype。</li></ul>]]></content>
<categories>
<category> 面试题 </category>
</categories>
<tags>
<tag> Spring </tag>
<tag> 面试 </tag>
</tags>
</entry>
<entry>
<title>面试题-MySQL篇</title>
<link href="/posts/c98a0f2b.html"/>
<url>/posts/c98a0f2b.html</url>
<content type="html"><![CDATA[<h1>MySQL篇</h1><h2 id="1-MySQL-有哪些存储引擎?">1. MySQL 有哪些存储引擎?</h2><p>mysql常用引擎包括:MYISAM、Innodb、Memory、MERGE</p><ul><li>MYISAM:全表锁,拥有较高的执行速度,不支持事务,不支持外键,并发性能差,占用空间相对较小,对事务完整性没有要求,以select、insert为主的应用基本上可以使用这引擎</li><li>Innodb:行级锁,提供了具有提交、回滚和崩溃回复能力的事务安全,支持自动增长列,支持外键约束,并发能力强,占用空间是MYISAM的2.5倍,处理效率相对会差一些</li><li>Memory:全表锁,存储在内存中,速度快,但会占用和数据量成正比的内存空间且数据在mysql重启时会丢失,默认使用HASH索引,检索效率非常高,但不适用于精确查找,主要用于那些内容变化不频繁的代码表</li><li>MERGE:是一组MYISAM表的组合</li></ul><h2 id="2-InnoDB和MyISAM的区别有哪些?">2. InnoDB和MyISAM的区别有哪些?</h2><ol><li>InnoDB支持事务,MyISAM不支持,对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务;</li><li>InnoDB支持外键,而MyISAM不支持。对一个包含外键的InnoDB表转为MYISAM会失败;</li><li>InnoDB是聚集索引,数据文件是和索引绑在一起的,必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。而MyISAM是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。</li><li>InnoDB不保存表的具体行数,执行select count(*) from table时需要全表扫描。而MyISAM用<br>一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快;</li><li>Innodb不支持全文索引,而MyISAM支持全文索引,查询效率上MyISAM要高;</li></ol><h2 id="3-数据库的三范式是什么?">3. 数据库的三范式是什么?</h2><ul><li><p>第一范式:列不可再分</p></li><li><p>第二范式:行可以唯一区分,(主键约束)</p></li><li><p>第三范式:表的非主属性不能依赖与其他表的非主属性(外键约束)且三大范式是一级一级依赖的,第二范式建立在第一范式上,第三范式建立第一第二范式上</p></li></ul><h2 id="4-数据库事务">4. 数据库事务</h2><ol><li><p><strong>什么是事务?</strong>:多条sql语句,要么全部成功,要么全部失败</p></li><li><p><strong>事务的特征?</strong>:原子性(Atomic)、一致性(Consistency)、隔离性(Isolation)、持久性(Durabiliy)。简称ACID。</p></li><li><p><strong>事务的隔离级别有哪些?</strong>:读未提交、读提交、可重复读、串行化。</p><ul><li>READ-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。</li><li>READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。</li><li>REPEATABLE-READ(可重复读): 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。</li><li>SERIALIZABLE(可串行化): 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。</li></ul></li><li><p><strong>MySQL的默认隔离级别是哪个?</strong>:可重复读</p></li><li><p><strong>事务的并发问题有哪些?</strong>:脏读、不可重复读、幻读。<strong>如何解决?</strong>:通过设置隔离级别、使用悲观锁、使用乐观锁。</p><ul><li><strong>脏读(Dirty read)</strong>: 当一个事务正在访问数据并且对数据进行了修改,而这种修改还没有提交到数据库中,这时另外一个事务也访问了这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是“脏数据”,依据“脏数据”所做的操作可能是不正确的。</li><li><strong>丢失修改(Lost to modify)</strong>: 指在一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失修改。 例如:事务1读取某表中的数据A=20,事务2也读取A=20,事务1修改A=A-1,事务2也修改A=A-1,最终结果A=19,事务1的修改被丢失。</li><li><strong>不可重复读(Unrepeatableread)</strong>: 指在一个事务内多次读同一数据。在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情况,因此称为不可重复读。</li><li><strong>幻读(Phantom read)</strong>: 幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。</li></ul></li></ol><h2 id="5-索引">5. 索引</h2><ol><li><p><strong>索引是什么</strong></p><ul><li>官方介绍索引是帮助MySQL高效获取数据的数据结构。更通俗的说,数据库索引好比是一本书前面的目录,能加快数据库的查询速度。</li><li>一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往是存储在磁盘上的文件中的(可能存储在单独的索引文件中,也可能和数据一起存储在数据文件中)。</li><li>我们通常所说的索引,包括聚集索引、覆盖索引、组合索引、前缀索引、唯一索引等,没有特别说明,默认都是使用B+树结构组织(多路搜索树,并不一定是二叉的)的索引。</li></ul></li><li><p><strong>索引优缺点</strong></p><ul><li>优点:<ol><li>降低数据排序的成本,降低CPU消耗: 索引之所以查的快是因为先将数据排好序,若该字段正好需要排序,则正好降低了排序的成本</li><li>提高数据的检案速度,降低数据库IO成本: 使用案引的意义就是通过缩小表中需要查询的记录的数目从而加快搜案的速度</li></ol></li><li>缺点:<ol><li>降低更新表的速度: 表的数据发生了变化,对应的索引也需要一起变更从而减低的更新速度,否则索引指向的物理数据可能不对,这也是索引失效的原因之一</li><li>占用存储空间:索引实际上也是一张表,记录了主键与素引字段股以素引文件的形式存储在磁盘上</li></ol></li></ul></li><li><p><strong>什么时候不要使用索引?</strong></p><ul><li>经常增删改的列不要建立索引;</li><li>有大量重复的列不建立索引;</li><li>表记录太少不要建立索引。</li></ul></li></ol><h2 id="6-Sql优化手段">6. Sql优化手段</h2><ol><li>查询语句中不要使用select * 会进行全表扫描,占用大量资源</li><li>尽量减少子查询,使用关联查询(left join,right join,inner join)替代</li><li>减少使用IN或者NOT IN ,使用exists,not exists或者关联查询语句替代</li><li>or 的查询尽量用 union或者union all 代替(在确认没有重复数据或者不用剔除重复数据时,union all会更好)</li><li>应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。</li><li>应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num is null 可以在num上设置默认值0,确保表中num列没有null值,然后这样查询: select id from t where num=0</li></ol><h2 id="7-什么是内连接、外连接、右外连接、左外连接?">7. 什么是内连接、外连接、右外连接、左外连接?</h2><ul><li>内联接(Inner Join):匹配2张表中相关联的记录。</li><li>左外联接(Left Outer Join):除了匹配2张表中相关联的记录外,还会匹配左表中剩余的记录,右表中未匹配到的字段用NULL表示。</li><li>右外联接(Right Outer Join):除了匹配2张表中相关联的记录外,还会匹配右表中剩余的记录,左表中未匹配到的字段用NULL表示。在判定左表和右表时,要根据表名出现在Outer Join的左右位置关系。</li></ul><h2 id="8-说说在-MySQL-中一条查询-SQL-是如何执行的?">8. 说说在 MySQL 中一条查询 SQL 是如何执行的?</h2><p>例如:</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> id <span class="operator">=</span> <span class="number">1</span>;</span><br></pre></td></tr></table></figure><ol><li><strong>取得链接</strong>,使用使用到 MySQL 中的连接器。</li><li><strong>查询缓存</strong>,key 为 SQL 语句,value 为查询结果,如果查到就直接返回。不建议使用次缓存,在 MySQL 8.0 版本已经将查询缓存删除,也就是说MySQL 8.0 版本后不存在此功能。</li><li><strong>分析器</strong>,分为词法分析和语法分析。此阶段只是做一些 SQL 解析,语法校验。所以一般语法错误在此阶段。</li><li><strong>优化器</strong>,是在表里有多个索引的时候,决定使用哪个索引;或者一个语句中存在多表关联的时候(join),决定各个表的连接顺序。</li><li><strong>执行器</strong>,通过分析器让 SQL 知道你要干啥,通过优化器知道该怎么做,于是开始执行语句。执行语句的时候还要判断是否具备此权限,没有权限就直接返回提示没有权限的错误;有权限则打开表,根据表的引擎定义,去使用这个引擎提供的接口,获取这个表的第一行,判断 id 是都等于 1。如果是,直接返回;如果不是继续调用引擎接口去下一行,重复相同的判断,直到取到这个表的最后一行,最后返回。</li></ol><h2 id="9-MySQL-中-varchar-与-char-的区别?varchar-30-中的-30代表的涵义?">9. MySQL 中 varchar 与 char 的区别?varchar(30) 中的 30代表的涵义?</h2><ul><li>varchar 与 char 的区别,char 是一种固定长度的类型,varchar 则是一种可变长度的类型。</li><li>varchar(30) 中 30 的涵义最多存放 30 个字符。varchar(30) 和 (130) 存储 hello 所占空间一样,但后者在排序时会消耗更多内存,因为 ORDER BY col 采用 fixed_length 计算 col 长度(memory 引擎也一样)。</li><li>对效率要求高用 char,对空间使用要求高用 varchar。</li></ul><h2 id="10-int-11-中的-11-代表什么涵义?">10. int(11) 中的 11 代表什么涵义?</h2><ul><li>int(11) 中的 11,不影响字段存储的范围,只影响展示效果。</li><li>int(11)是一种数据类型定义。其中int表示整数类型,而括号里的11并不代表存储数字的大小范围。</li><li>它主要用于在显示宽度上的格式化。例如,当使用ZEROFILL属性时,int(11)表示如果存储的数字位数不足 11 位,会在数字前面填充 0 来达到 11 位的显示宽度。</li><li>举例来说,如果定义了一个字段为int(11) ZEROFILL,存储数字1时,在查询结果中可能会显示为00000000001。但从存储角度讲,int类型在 MySQL 中有固定的存储范围(通常是-2147483648到2147483647),这个范围与int(11)中的11无关。</li></ul><h2 id="11-为什么-SELECT-COUNT-FROM-table-在-InnoDB-比MyISAM-慢?">11. 为什么 SELECT COUNT(*) FROM table 在 InnoDB 比MyISAM 慢?</h2><p>对于 SELECT COUNT(*) FROM table 语句,在没有 WHERE 条件的情况下,InnoDB 比 MyISAM 可能会慢很多,尤其在大表的情况下。因为,InnoDB 是去实时统计结果,会全表扫描;而 MyISAM内部维持了一个计数器,预存了结果,所以直接返回即可。</p><h2 id="12-说说-InnoDB-与-MyISAM-有什么区别?">12. 说说 InnoDB 与 MyISAM 有什么区别?</h2><ul><li>在 MySQL 5.1 及之前的版本中,MyISAM 是默认的存储引擎,而在 MySQL 5.5 版本以后,默认使用 InnoDB 存储引擎。</li><li>MyISAM 不支持行级锁,换句话说,MyISAM 会对整张表加锁,而不是针对行。同时,</li><li>MyISAM 不支持事务和外键。MyISAM 可被压缩,存储空间较小,而且 MyISAM 在筛选大量数据时非常快。</li><li>InnoDB 是事务型引擎,当事务异常提交时,会被回滚。同时,InnoDB 支持行锁。此外,</li><li>InnoDB 需要更多存储空间,会在内存中建立其专用的缓冲池用于高速缓冲数据和索引。</li><li>InnoDB 支持自动奔溃恢复特性。<br>建议:一般情况下,个人建议优先选择 InnoDB 存储引擎,并且尽量不要将 InnoDB 与 MyISAM 混合使用。</li></ul><h2 id="13-MySQL-索引类型有哪些?">13. MySQL 索引类型有哪些?</h2><ul><li><strong>主键索引</strong>:索引列中的值必须是唯一的,不允许有空值。</li><li><strong>唯一索引</strong>:索引列中的值必须是唯一的,但是允许为空值。</li><li><strong>全文索引</strong>:只能在文本类型CHAR,VARCHAR,TEXT类型字段上创建全文索引。字段长度比较大时,如果创建普通索引,在进行like模糊查询时效率比较低,这时可以创建全文索引。MyISAM和InnoDB中都可以使用全文索引。</li><li><strong>空间索引</strong>:MySQL在5.7之后的版本支持了空间索引,而且支持OpenGIS几何数据模型。MySQL在空间索引这方面遵循OpenGIS几何数据模型规则。</li><li><strong>前缀索引</strong>:在文本类型如CHAR,VARCHAR,TEXT类列上创建索引时,可以指定索引列的长度,但是数值类型不能指定。</li></ul><h2 id="14-MVCC">14. MVCC</h2><ol><li><strong>说说什么是 MVCC?</strong><ul><li>多版本并发控制(MVCC=Multi-Version Concurrency Control),是一种用来解决读 - 写冲突的无锁并发控制。也就是为事务分配单向增长的时间戳,为每个修改保存一个版本。版本与事务时间戳关联,读操作只读该事务开始前的数据库的快照(复制了一份数据)。这样在读操作不用阻塞写操作,写操作不用阻塞读操作的同时,避免了脏读和不可重复读。</li></ul></li><li>MVCC 可以为数据库解决什么问题?<ul><li>在并发读写数据库时,可以做到在读操作时不用阻塞写操作,写操作也不用阻塞读操作,提高了数据库并发读写的性能。同时还可以解决脏读、幻读、不可重复读等事务隔离问题,但不能解决更新丢失问题。</li></ul></li><li>说说 MVCC 的<strong>实现原理</strong><ul><li>MVCC 的目的就是多版本并发控制,在数据库中的实现,就是为了解决读写冲突,它的实现原理主要是依赖记录中的 3 个隐式字段、undo 日志、Read View 来实现的。</li></ul></li></ol><h2 id="15-请说说-MySQL-数据库的锁?">15. 请说说 MySQL 数据库的锁?</h2><p>MySQL 中有共享锁和排它锁,也就是读锁和写锁。</p><ol><li>共享锁:不堵塞,多个用户可以同一时刻读取同一个资源,相互之间没有影响。</li><li>排它锁:一个写操作阻塞其他的读锁和写锁,这样可以只允许一个用户进行写入,防止其他用<br>户读取正在写入的资源。</li><li>表锁:系统开销最小,会锁定整张表,MyISAM 使用表锁。</li><li>行锁:容易出现死锁,发生冲突概率低,并发高,InnoDB 支持行锁(必须有索引才能实现,否则会自动锁全表,那么就不是行锁了)。</li></ol><h2 id="16-说说悲观锁和乐观锁">16. 说说悲观锁和乐观锁</h2><ol><li><strong>悲观锁:</strong><ul><li>说的是数据库被外界(包括本系统当前的其他事物以及来自外部系统的事务处理)修改保持着保守态度,因此在整个数据修改过程中,将数据处于锁状态。悲观的实现往往是依靠数据库提供的锁机制,也只有数据库层面提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统汇总实现了加锁机制,也是没有办法保证系统不会修改数据。在悲观锁的情况下,为了保证事务的隔离性,就需要一致性锁定读。读取数据时给加锁,其它事务无法修改这些数据。修改删除数据时也要加锁,其它事务无法读取这些数据。</li></ul></li><li><strong>乐观锁:</strong><ul><li>相对悲观锁而言,乐观锁机制采取了更加宽松的加锁机制。悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销往往无法承受而乐观锁机制在一定程度上解决了这个问题。乐观锁,大多是基于数据版本(Version)记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个“version”字段来实现。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据</li></ul></li></ol><h2 id="17-怎样尽量避免死锁的出现?">17. 怎样尽量避免死锁的出现?</h2><ol><li>设置获取锁的超时时间,至少能保证最差情况下,可以退出程序,不至于一直等待导致死锁;</li><li>设置按照同一顺序访问资源,类似于串行执行;</li><li>避免事务中的用户交叉;</li><li>保持事务简短并在一个批处理中;</li><li>使用低隔离级别;</li><li>使用绑定链接</li></ol><h2 id="18-SQL优化经验">18. SQL优化经验</h2><ol><li>表的设计优化,数据类型的选择,参考阿里开发手册</li><li>索引优化,索引创建原则</li><li>sql语句优化,避免索引失效,避免使用select*</li><li>主从复制、读写分离,不让数据的写入,影响读操作</li><li>分库分表</li></ol><h2 id="19-MySQL中什么时候索引会失效?">19. MySQL中什么时候索引会失效?</h2><ol><li>违反最左前缀法则</li><li>范围查询右边的列,不能使用索引</li><li>不要在索引列上进行运算操作,索引将失效</li><li>字符串不加单引号,造成索引失效。(类型转换)</li></ol>]]></content>
<categories>
<category> 面试题 </category>
</categories>
<tags>
<tag> 面试 </tag>
<tag> mysql </tag>
</tags>
</entry>
<entry>
<title>ApI网关</title>
<link href="/posts/f7c5ffd.html"/>
<url>/posts/f7c5ffd.html</url>
<content type="html"><![CDATA[<p>什么是网关?理解成火车站的检票口,<strong>统一</strong> 检票</p><p><strong>网关优点</strong>: 统一进行操作,去处理一些问题</p><h2 id="1、网关作用">1、网关作用</h2><ol><li>路由</li><li>负载均衡</li><li>统一鉴权</li><li>统一处理跨域</li><li>统一业务处理(缓存)</li><li>访问控制</li><li>发布控制</li><li>流量染色</li><li>统一接口保护<ol><li>限制请求</li><li>信息脱敏</li><li>降级(熔断)</li><li>限流 学习令牌桶算法,学习露桶算法,学习一下RedislimitHandler</li><li>超时时间</li><li>重试(业务保护)</li></ol></li><li>统一日志</li><li>统一文档</li></ol><h2 id="2、具体作用">2、具体作用</h2><ul><li><p><strong>路由</strong><br>起到转发的作用,比如有接口A和接口B,网关会记录这些信息,根据用户访问的地址和参数,转发请求到对应的接口(服务器/集群)<br>用户a调用接口A<br>/a => 接口A<br>/b => 接口B<br><a href="https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories">https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories</a></p></li><li><p><strong>负载均衡</strong><br>在路由的基础上可以转发到某一个服务器<br>/c => 服务A/ 集群A(随机转发到其中的某一个机器)<br>uri从固定地址改成b:xx</p></li><li><p><strong>统一鉴权</strong><br>判断用户是否有权限进行操作,无论访问什么接口,我都统一去判断权限,不用重复写</p></li><li><p><strong>统一处理跨域</strong><br>网关统一处理跨域,不用在每个项目单独处理<br><a href="https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#cors-configuration">https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#cors-configuration</a></p></li><li><p><strong>统一业务处理</strong><br>把每个项目中都要做的通用逻辑放到上层(网关),统一处理,比如本项目的次数统计</p></li><li><p><strong>访问控制</strong><br>黑白名单,比如限制DDOS IP</p></li><li><p><strong>发布控制</strong></p><p>灰度发布,比如上线新接口,先给新接口分配 20%流量,老接口80% ,再慢慢调整比例<br><a href="https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-weight-route-predicate-factory">https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-weight-route-predicate-factory</a></p></li><li><p><strong>流量染色</strong><br>区分用户来源:<br>给请求(流量)添加一些标识,一般是设置请求头中,添加新的请求头<br><a href="https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-addrequestheader-gatewayfilter-factory">https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-addrequestheader-gatewayfilter-factory</a></p></li><li><p><strong>全局染色</strong><br><a href="https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#default-filters">https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#default-filters</a></p></li><li><p><strong>接口保护</strong></p><ol><li><p>限制请求<br><a href="https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#requestheadersiz-gatewayfilter-factory">https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#requestheadersiz-gatewayfilter-factory</a></p></li><li><p>信息脱敏</p><p><a href="https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-removerequestheader-gatewayfilter-factory">https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-removerequestheader-gatewayfilter-factory</a></p></li><li><p>降级(熔断) 进行兜底</p><p><a href="https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#fallback-headers">https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#fallback-headers</a></p></li><li><p>限流</p><p><a href="https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-requestratelimiter-gatewayfilter-factory">https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-requestratelimiter-gatewayfilter-factory</a></p></li><li><p>超时时间 超时就中断</p><p><a href="https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#http-timeouts-configuration">https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#http-timeouts-configuration</a></p></li><li><p>重试(业务保护):</p><p><a href="https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-retry-gatewayfilter-factory">https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-retry-gatewayfilter-factory</a></p></li></ol></li><li><p><strong>统一日志</strong><br>统一的请求,响应信息记录</p></li><li><p><strong>统一文档</strong><br>将下游项目的文档进行聚合,在一个页面统一查看<br>建议用:<a href="https://doc.xiaominfo.com/docs/middleware-sources/aggregation-introduction">https://doc.xiaominfo.com/docs/middleware-sources/aggregation-introduction</a></p></li><li><p><strong>网关的分类</strong></p><ol><li><strong>全局网关</strong>(接入层网关)作用:是负载均衡、请求日志等,不和业务逻辑绑定</li><li><strong>业务网关</strong>(微服务网关)会有一些业务逻辑,作用是将请求转发到不同的业务/项目/接口/服务<br>参考文章:<a href="https://blog.csdn.net/qq_21040559/article/details/122961395">https://blog.csdn.net/qq_21040559/article/details/122961395</a></li></ol></li><li><p><strong>实现</strong></p><ol><li><strong>Nginx</strong>(全局网关),<strong>Kong网关</strong>(API网关), <strong>编程成本相对较高</strong></li><li><strong>Spring Cloud Gateway</strong>(取代了Zuul)性能高 可以用java代码来写逻辑 适于学习<br>网关技术选型:<a href="https://zhuanlan.zhihu.com/p/500587132">https://zhuanlan.zhihu.com/p/500587132</a></li></ol></li></ul>]]></content>
<categories>
<category> 学习笔记 </category>
</categories>
<tags>
<tag> gateway </tag>
</tags>
</entry>
<entry>
<title>加密</title>
<link href="/posts/c31b0edc.html"/>
<url>/posts/c31b0edc.html</url>
<content type="html"><![CDATA[<h2 id="1、加密方式">1、加密方式</h2><p>将accessKey、secretKey放在Header里明文传递安全吗</p><p>答案是否定的,因为我们的<strong>请求可能被人拦截</strong>,而我们把密码放进请求头里面,可能会被别人获取</p><blockquote><p>一般是根据密钥,生成<strong>签名sign</strong></p></blockquote><p><strong>加密方式</strong></p><ol><li><p>对称加密</p></li><li><p>非对称加密</p></li><li><p>md5 签名(不可解密)</p></li></ol><p><strong>签名的做法</strong></p><p>假如 ,我们有用户参数,我们用密钥与他拼接,用签名算法得到一个不可解密的值</p><p><strong>用户参数 +密钥=>签名生成算法(MD5,HMac,Sha1) =>不可解密的值</strong></p><p>例子:xuan +abc=>7e7b9583aa0bc3e834fe8bcaebda38b5(这里是我随便输的,得到的值是随机的)</p><p>怎么知道签名对不对?</p><p>服务端用一模一样的参数和算法去生成签名,只要和用户传的一致,就表示密钥一致</p><p><strong>怎么防重放?</strong></p><p>加nonce随机数只能用一次</p><p>服务端要保存用过的随机数</p><p>加timestamp 时间戳,校验它的有效期</p><p>综上所属</p><p><strong>传递的参数</strong></p><ol><li>accessKey</li><li>sign (由accessKey(或者使用用户请求参数body等)、secretKey加密而来)</li><li>nonce随机数</li><li>timestamp</li><li>body(用户请求参数 可要可不要)</li></ol><p><strong>API签名认证是一个很灵活的设计,具体要有哪些参数,尽量服务端调用,参数名如何要根据场景来。</strong></p>]]></content>
<categories>
<category> 学习笔记 </category>
</categories>
<tags>
<tag> ApI </tag>
</tags>
</entry>
<entry>
<title>关于Markdown格式以及外挂标签的用法</title>
<link href="/posts/5c2fafc7.html"/>
<url>/posts/5c2fafc7.html</url>
<content type="html"><</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><p>本地图片:<br><img src="/assets/pusheencode.webp" alt="示例图片" style="zoom:50%;" /><br>在线图片:<br><img src="https://cdn.jsdelivr.net/gh/fomalhaut1998/markdown_pic/img/code.png" alt="code"></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="1-8-表格">1.8 表格</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-2">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">| 项目标号 | 资金 | 备注 |</span><br><span class="line">| -------- | -------- | ---- |</span><br><span class="line">| 1 | 100,000 | 无 |</span><br><span class="line">| 2 | 200,000 | 无 |</span><br><span class="line">| 3 | 300,600 | 重要 |</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><table><thead><tr><th>项目标号</th><th>资金</th><th>备注</th></tr></thead><tbody><tr><td>1</td><td>100,000</td><td>无</td></tr><tr><td>2</td><td>200,000</td><td>无</td></tr><tr><td>3</td><td>300,600</td><td>重要</td></tr></tbody></table><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="1-9-公式">1.9 公式</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-2">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$$</span><br><span class="line">\Gamma(z)=\int<span class="emphasis">_0^\infty t^{z-1}e^{-t}dt.</span></span><br><span class="line"><span class="emphasis">$$</span></span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><p>$$<br>\Gamma(z)=\int_0^\infty t^{z-1}e^{-t}dt.<br>$$</p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h1>2.Butterfly外挂标签</h1><div class="note info flat"><p>这部分参考安知鱼:<a href="https://anzhiy.cn/posts/7d58.html">基于Butterfly的外挂标签引入</a></p></div><h2 id="2-1-行内文本样式-text">2.1 行内文本样式 text</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-2">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-3">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">{% u 文本内容 %}</span><br><span class="line">{% emp 文本内容 %}</span><br><span class="line">{% wavy 文本内容 %}</span><br><span class="line">{% del 文本内容 %}</span><br><span class="line">{% kbd 文本内容 %}</span><br><span class="line">{% psw 文本内容 %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="bullet">1.</span> 带 {% u 下划线 %} 的文本</span><br><span class="line"><span class="bullet">2.</span> 带 {% emp 着重号 %} 的文本</span><br><span class="line"><span class="bullet">3.</span> 带 {% wavy 波浪线 %} 的文本</span><br><span class="line"><span class="bullet">4.</span> 带 {% del 删除线 %} 的文本</span><br><span class="line"><span class="bullet">5.</span> 键盘样式的文本 {% kbd command %} + {% kbd D %}</span><br><span class="line"><span class="bullet">6.</span> 密码样式的文本:{% psw 这里没有验证码 %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><ol><li>带 <u>下划线</u> 的文本</li><li>带 <emp>着重号</emp> 的文本</li><li>带 <wavy>波浪线</wavy> 的文本</li><li>带 <del>删除线</del> 的文本</li><li>键盘样式的文本 <kbd>command</kbd> + <kbd>D</kbd></li><li>密码样式的文本:<psw>这里没有验证码</psw></li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-2-行内文本-span">2.2 行内文本 span</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-2">配置参数</button></li><li class="tab"><button type="button" data-href="#分栏-3">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% span 样式参数(参数以空格划分), 文本内容 %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><ol><li><code>字体</code>: logo, code</li><li><code>颜色</code>: red,yellow,green,cyan,blue,gray</li><li><code>大小</code>: small, h4, h3, h2, h1, large, huge, ultra</li><li><code>对齐方向</code>: left, center, right</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="bullet">-</span> 彩色文字</span><br><span class="line">在一段话中方便插入各种颜色的标签,包括:{% span red, 红色 %}、{% span yellow, 黄色 %}、{% span green, 绿色 %}、{% span cyan, 青色 %}、{% span blue, 蓝色 %}、{% span gray, 灰色 %}。</span><br><span class="line"><span class="bullet">-</span> 超大号文字</span><br><span class="line">文档「开始」页面中的标题部分就是超大号文字。</span><br><span class="line">{% span center logo large, Volantis %}</span><br><span class="line">{% span center small, A Wonderful Theme for Hexo %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-4"><ul><li>彩色文字<br>在一段话中方便插入各种颜色的标签,包括:<span class='p red'>红色</span>、<span class='p yellow'>黄色</span>、<span class='p green'>绿色</span>、<span class='p cyan'>青色</span>、<span class='p blue'>蓝色</span>、<span class='p gray'>灰色</span>。</li><li>超大号文字<br>文档「开始」页面中的标题部分就是超大号文字。<br><span class='p center logo large'>Volantis</span><br><span class='p center small'>A Wonderful Theme for Hexo</span></li></ul><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-3-段落文本-p">2.3 段落文本 p</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-2">配置参数</button></li><li class="tab"><button type="button" data-href="#分栏-3">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% p 样式参数(参数以空格划分), 文本内容 %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><ol><li><code>字体</code>: logo, code</li><li><code>颜色</code>: red,yellow,green,cyan,blue,gray</li><li><code>大小</code>: small, h4, h3, h2, h1, large, huge, ultra</li><li><code>对齐方向</code>: left, center, right</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="bullet">-</span> 彩色文字</span><br><span class="line">在一段话中方便插入各种颜色的标签,包括:{% p red, 红色 %}、{% p yellow, 黄色 %}、{% p green, 绿色 %}、{% p cyan, 青色 %}、{% p blue, 蓝色 %}、{% p gray, 灰色 %}。</span><br><span class="line"><span class="bullet">-</span> 超大号文字</span><br><span class="line">文档「开始」页面中的标题部分就是超大号文字。</span><br><span class="line">{% p center logo large, Volantis %}</span><br><span class="line">{% p center small, A Wonderful Theme for Hexo %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-4"><ul><li>彩色文字<br>在一段话中方便插入各种颜色的标签,包括:<p class='p red'>红色</p>、<p class='p yellow'>黄色</p>、<p class='p green'>绿色</p>、<p class='p cyan'>青色</p>、<p class='p blue'>蓝色</p>、<p class='p gray'>灰色</p>。</li><li>超大号文字<br>文档「开始」页面中的标题部分就是超大号文字。</li></ul><p class='p center logo large'>Volantis</p><p class='p center small'>A Wonderful Theme for Hexo</p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-4-引用note">2.4 引用note</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">通用配置</button></li><li class="tab"><button type="button" data-href="#分栏-2">语法格式</button></li><li class="tab"><button type="button" data-href="#分栏-3">参数配置</button></li><li class="tab"><button type="button" data-href="#分栏-4">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-5">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">note:</span><br><span class="line"> # Note tag style values:</span><br><span class="line"> # - simple bs-callout old alert style. Default.</span><br><span class="line"> # - modern bs-callout new (v2-v3) alert style.</span><br><span class="line"> # - flat flat callout style with background, like on Mozilla or StackOverflow.</span><br><span class="line"> # - disabled disable all CSS styles import of note tag.</span><br><span class="line"> style: simple</span><br><span class="line"> icons: false</span><br><span class="line"> border<span class="emphasis">_radius: 3</span></span><br><span class="line"><span class="emphasis"> # Offset lighter of background in % for modern and flat styles (modern: -12 | 12; flat: -18 | 6).</span></span><br><span class="line"><span class="emphasis"> # Offset also applied to label tag variables. This option can work with disabled note tag.</span></span><br><span class="line"><span class="emphasis"> light_</span>bg<span class="emphasis">_offset: 0</span></span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="section"># 自带icon</span></span><br><span class="line">{% note [class] [no-icon] [style] %}</span><br><span class="line">Any content (support inline tags too.io).</span><br><span class="line">{% endnote %}</span><br><span class="line"><span class="section"># 外部icon</span></span><br><span class="line">{% note [color] [icon] [style] %}</span><br><span class="line">Any content (support inline tags too.io).</span><br><span class="line">{% endnote %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><p>1.自带icon</p><table><thead><tr><th>参数</th><th style="text-align:center">用法</th></tr></thead><tbody><tr><td>class</td><td style="text-align:center">【可选】标识,不同的标识有不同的配色 ( default / primary / success / info / warning / danger )</td></tr><tr><td>no-icon</td><td style="text-align:center">【可选】不显示 icon</td></tr><tr><td>style</td><td style="text-align:center">【可选】可以覆盖配置中的 style (simple/modern/flat/disabled)</td></tr></tbody></table><p>2.外部icon</p><table><thead><tr><th>参数</th><th style="text-align:center">用法</th></tr></thead><tbody><tr><td>class</td><td style="text-align:center">【可选】标识,不同的标识有不同的配色 ( default / blue / pink / red / purple / orange / green )</td></tr><tr><td>no-icon</td><td style="text-align:center">【可选】可配置自定义 icon (只支持 fontawesome 图标, 也可以配置 no-icon )</td></tr><tr><td>style</td><td style="text-align:center">【可选】可以覆盖配置中的 style (simple/modern/flat/disabled)</td></tr></tbody></table><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-4"><details class="folding-tag" blue><summary> 1.自带icon </summary> <div class='content'> <p>1.<code>simple</code>样式</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">{% note simple %}默认 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note default simple %}default 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note primary simple %}primary 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note success simple %}success 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note info simple %}info 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note warning simple %}warning 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note danger simple %}danger 提示块标签{% endnote %}</span><br></pre></td></tr></table></figure><p>2.<code>modern</code>样式</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">{% note modern %}默认 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note default modern %}default 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note primary modern %}primary 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note success modern %}success 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note info modern %}info 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note warning modern %}warning 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note danger modern %}danger 提示块标签{% endnote %}</span><br></pre></td></tr></table></figure><p>3.<code>flat</code>样式</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">{% note flat %}默认 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note default flat %}default 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note primary flat %}primary 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note success flat %}success 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note info flat %}info 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note warning flat %}warning 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note danger flat %}danger 提示块标签{% endnote %}</span><br></pre></td></tr></table></figure><p>4.<code>disabled</code>样式</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">{% note disabled %}默认 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note default disabled %}default 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note primary disabled %}primary 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note success disabled %}success 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note info disabled %}info 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note warning disabled %}warning 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note danger disabled %}danger 提示块标签{% endnote %}</span><br></pre></td></tr></table></figure><p>5.<code>no-icon</code>样式</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">{% note no-icon %}默认 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note default no-icon %}default 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note primary no-icon %}primary 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note success no-icon %}success 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note info no-icon %}info 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note warning no-icon %}warning 提示块标签{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note danger no-icon %}danger 提示块标签{% endnote %}</span><br></pre></td></tr></table></figure> </div> </details><details class="folding-tag" blue><summary> 2.外部icon </summary> <div class='content'> <p>1.<code>simple</code>样式</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">{% note 'fab fa-cc-visa' simple %}你是刷 Visa 还是 UnionPay{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note blue 'fas fa-bullhorn' simple %}2021年快到了....{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note pink 'fas fa-car-crash' simple %}小心开车 安全至上{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note red 'fas fa-fan' simple%}这是三片呢?还是四片?{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note orange 'fas fa-battery-half' simple %}你是刷 Visa 还是 UnionPay{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note purple 'far fa-hand-scissors' simple %}剪刀石头布{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note green 'fab fa-internet-explorer' simple %}前端最讨厌的浏览器{% endnote %}</span><br></pre></td></tr></table></figure><p>2.<code>modern</code>样式</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">{% note 'fab fa-cc-visa' modern %}你是刷 Visa 还是 UnionPay{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note blue 'fas fa-bullhorn' modern %}2021年快到了....{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note pink 'fas fa-car-crash' modern %}小心开车 安全至上{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note red 'fas fa-fan' modern%}这是三片呢?还是四片?{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note orange 'fas fa-battery-half' modern %}你是刷 Visa 还是 UnionPay{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note purple 'far fa-hand-scissors' modern %}剪刀石头布{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note green 'fab fa-internet-explorer' modern %}前端最讨厌的浏览器{% endnote %}</span><br></pre></td></tr></table></figure><p>3.<code>flat</code>样式</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">{% note 'fab fa-cc-visa' flat %}你是刷 Visa 还是 UnionPay{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note blue 'fas fa-bullhorn' flat %}2021年快到了....{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note pink 'fas fa-car-crash' flat %}小心开车 安全至上{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note red 'fas fa-fan' flat%}这是三片呢?还是四片?{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note orange 'fas fa-battery-half' flat %}你是刷 Visa 还是 UnionPay{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note purple 'far fa-hand-scissors' flat %}剪刀石头布{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note green 'fab fa-internet-explorer' flat %}前端最讨厌的浏览器{% endnote %}</span><br></pre></td></tr></table></figure><p>4.<code>disabled</code>样式</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">{% note 'fab fa-cc-visa' disabled %}你是刷 Visa 还是 UnionPay{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note blue 'fas fa-bullhorn' disabled %}2021年快到了....{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note pink 'fas fa-car-crash' disabled %}小心开车 安全至上{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note red 'fas fa-fan' disabled %}这是三片呢?还是四片?{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note orange 'fas fa-battery-half' disabled %}你是刷 Visa 还是 UnionPay{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note purple 'far fa-hand-scissors' disabled %}剪刀石头布{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note green 'fab fa-internet-explorer' disabled %}前端最讨厌的浏览器{% endnote %}</span><br></pre></td></tr></table></figure><p>5.<code>no-icon</code>样式</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">{% note no-icon %}你是刷 Visa 还是 UnionPay{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note blue no-icon %}2021年快到了....{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note pink no-icon %}小心开车 安全至上{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note red no-icon %}这是三片呢?还是四片?{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note orange no-icon %}你是刷 Visa 还是 UnionPay{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note purple no-icon %}剪刀石头布{% endnote %}</span><br><span class="line"></span><br><span class="line">{% note green no-icon %}前端最讨厌的浏览器{% endnote %}</span><br></pre></td></tr></table></figure> </div> </details><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-5"><details class="folding-tag" blue><summary> 1.自带icon </summary> <div class='content'> <p>1.<code>simple</code>样式</p><div class="note simple"><p>默认 提示块标签</p></div><div class="note default simple"><p>default 提示块标签</p></div><div class="note primary simple"><p>primary 提示块标签</p></div><div class="note success simple"><p>success 提示块标签</p></div><div class="note info simple"><p>info 提示块标签</p></div><div class="note warning simple"><p>warning 提示块标签</p></div><div class="note danger simple"><p>danger 提示块标签</p></div>2.`modern`样式<div class="note modern"><p>默认 提示块标签</p></div><div class="note default modern"><p>default 提示块标签</p></div><div class="note primary modern"><p>primary 提示块标签</p></div><div class="note success modern"><p>success 提示块标签</p></div><div class="note info modern"><p>info 提示块标签</p></div><div class="note warning modern"><p>warning 提示块标签</p></div><div class="note danger modern"><p>danger 提示块标签</p></div><p>3.<code>flat</code>样式</p><div class="note flat"><p>默认 提示块标签</p></div><div class="note default flat"><p>default 提示块标签</p></div><div class="note primary flat"><p>primary 提示块标签</p></div><div class="note success flat"><p>success 提示块标签</p></div><div class="note info flat"><p>info 提示块标签</p></div><div class="note warning flat"><p>warning 提示块标签</p></div><div class="note danger flat"><p>danger 提示块标签</p></div><p>4.<code>disabled</code>样式</p><div class="note disabled"><p>默认 提示块标签</p></div><div class="note default disabled"><p>default 提示块标签</p></div><div class="note primary disabled"><p>primary 提示块标签</p></div><div class="note success disabled"><p>success 提示块标签</p></div><div class="note info disabled"><p>info 提示块标签</p></div><div class="note warning disabled"><p>warning 提示块标签</p></div><div class="note danger disabled"><p>danger 提示块标签</p></div><p>5.<code>no-icon</code>样式</p><div class="note no-icon flat"><p>默认 提示块标签</p></div><div class="note default no-icon flat"><p>default 提示块标签</p></div><div class="note primary no-icon flat"><p>primary 提示块标签</p></div><div class="note success no-icon flat"><p>success 提示块标签</p></div><div class="note info no-icon flat"><p>info 提示块标签</p></div><div class="note warning no-icon flat"><p>warning 提示块标签</p></div><div class="note danger no-icon flat"><p>danger 提示块标签</p></div> </div> </details><details class="folding-tag" blue><summary> 2.外部icon </summary> <div class='content'> <p>1.<code>simple</code>样式</p><div class="note icon-padding simple"><i class="note-icon fab fa-cc-visa"></i><p>你是刷 Visa 还是 UnionPay</p></div><div class="note blue icon-padding simple"><i class="note-icon fas fa-bullhorn"></i><p>2021年快到了…</p></div><div class="note pink icon-padding simple"><i class="note-icon fas fa-car-crash"></i><p>小心开车 安全至上</p></div><div class="note red icon-padding simple"><i class="note-icon fas fa-fan"></i><p>这是三片呢?还是四片?</p></div><div class="note orange icon-padding simple"><i class="note-icon fas fa-battery-half"></i><p>你是刷 Visa 还是 UnionPay</p></div><div class="note purple icon-padding simple"><i class="note-icon far fa-hand-scissors"></i><p>剪刀石头布</p></div><div class="note green icon-padding simple"><i class="note-icon fab fa-internet-explorer"></i><p>前端最讨厌的浏览器</p></div><p>2.<code>modern</code>样式</p><div class="note icon-padding modern"><i class="note-icon fab fa-cc-visa"></i><p>你是刷 Visa 还是 UnionPay</p></div><div class="note blue icon-padding modern"><i class="note-icon fas fa-bullhorn"></i><p>2021年快到了…</p></div><div class="note pink icon-padding modern"><i class="note-icon fas fa-car-crash"></i><p>小心开车 安全至上</p></div><div class="note red icon-padding modern"><i class="note-icon fas fa-fan"></i><p>这是三片呢?还是四片?</p></div><div class="note orange icon-padding modern"><i class="note-icon fas fa-battery-half"></i><p>你是刷 Visa 还是 UnionPay</p></div><div class="note purple icon-padding modern"><i class="note-icon far fa-hand-scissors"></i><p>剪刀石头布</p></div><div class="note green icon-padding modern"><i class="note-icon fab fa-internet-explorer"></i><p>前端最讨厌的浏览器</p></div><p>3.<code>flat</code>样式</p><div class="note icon-padding flat"><i class="note-icon fab fa-cc-visa"></i><p>你是刷 Visa 还是 UnionPay</p></div><div class="note blue icon-padding flat"><i class="note-icon fas fa-bullhorn"></i><p>2021年快到了…</p></div><div class="note pink icon-padding flat"><i class="note-icon fas fa-car-crash"></i><p>小心开车 安全至上</p></div><div class="note red icon-padding flat"><i class="note-icon fas fa-fan"></i><p>这是三片呢?还是四片?</p></div><div class="note orange icon-padding flat"><i class="note-icon fas fa-battery-half"></i><p>你是刷 Visa 还是 UnionPay</p></div><div class="note purple icon-padding flat"><i class="note-icon far fa-hand-scissors"></i><p>剪刀石头布</p></div><div class="note green icon-padding flat"><i class="note-icon fab fa-internet-explorer"></i><p>前端最讨厌的浏览器</p></div><p>4.<code>disabled</code>样式</p><div class="note icon-padding disabled"><i class="note-icon fab fa-cc-visa"></i><p>你是刷 Visa 还是 UnionPay</p></div><div class="note blue icon-padding disabled"><i class="note-icon fas fa-bullhorn"></i><p>2021年快到了…</p></div><div class="note pink icon-padding disabled"><i class="note-icon fas fa-car-crash"></i><p>小心开车 安全至上</p></div><div class="note red icon-padding disabled"><i class="note-icon fas fa-fan"></i><p>这是三片呢?还是四片?</p></div><div class="note orange icon-padding disabled"><i class="note-icon fas fa-battery-half"></i><p>你是刷 Visa 还是 UnionPay</p></div><div class="note purple icon-padding disabled"><i class="note-icon far fa-hand-scissors"></i><p>剪刀石头布</p></div><div class="note green icon-padding disabled"><i class="note-icon fab fa-internet-explorer"></i><p>前端最讨厌的浏览器</p></div><p>5.<code>no-icon</code>样式</p><div class="note no-icon flat"><p>你是刷 Visa 还是 UnionPay</p></div><div class="note blue no-icon flat"><p>2021年快到了…</p></div><div class="note pink no-icon flat"><p>小心开车 安全至上</p></div><div class="note red no-icon flat"><p>这是三片呢?还是四片?</p></div><div class="note orange no-icon flat"><p>你是刷 Visa 还是 UnionPay</p></div><div class="note purple no-icon flat"><p>剪刀石头布</p></div><div class="note green no-icon flat"><p>前端最讨厌的浏览器</p></div> </div> </details><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-5-上标标签-tip">2.5 上标标签 tip</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-2">配置参数</button></li><li class="tab"><button type="button" data-href="#分栏-3">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% tip [参数,可选] %}文本内容{% endtip %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><ol><li><code>样式</code>: success,error,warning,bolt,ban,home,sync,cogs,key,bell</li><li><code>自定义图标</code>: 支持fontawesome。</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">{% tip %}default{% endtip %}</span><br><span class="line">{% tip info %}info{% endtip %}</span><br><span class="line">{% tip success %}success{% endtip %}</span><br><span class="line">{% tip error %}error{% endtip %}</span><br><span class="line">{% tip warning %}warning{% endtip %}</span><br><span class="line">{% tip bolt %}bolt{% endtip %}</span><br><span class="line">{% tip ban %}ban{% endtip %}</span><br><span class="line">{% tip home %}home{% endtip %}</span><br><span class="line">{% tip sync %}sync{% endtip %}</span><br><span class="line">{% tip cogs %}cogs{% endtip %}</span><br><span class="line">{% tip key %}key{% endtip %}</span><br><span class="line">{% tip bell %}bell{% endtip %}</span><br><span class="line">{% tip fa-atom %}自定义font awesome图标{% endtip %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-4"><div class="tip "><p>default</p></div><div class="tip info"><p>info</p></div><div class="tip success"><p>success</p></div><div class="tip error"><p>error</p></div><div class="tip warning"><p>warning</p></div><div class="tip bolt"><p>bolt</p></div><div class="tip ban"><p>ban</p></div><div class="tip home"><p>home</p></div><div class="tip sync"><p>sync</p></div><div class="tip cogs"><p>cogs</p></div><div class="tip key"><p>key</p></div><div class="tip bell"><p>bell</p></div><div class="tip fa-atom"><p>自定义font awesome图标</p></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-6-动态标签-anima">2.6 动态标签 anima</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-2">配置参数</button></li><li class="tab"><button type="button" data-href="#分栏-3">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% tip [参数,可选] %}文本内容{% endtip %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><div class="note info flat"><ol><li>将所需的CSS类添加到图标(或DOM中的任何元素)。</li><li>对于父级悬停样式,需要给目标元素添加指定CSS类,同时还要给目标元素的父级元素添加CSS类<code>faa-parent animated-hover</code>。(详情见示例及示例源码)<br>You can regulate the speed of the animation by adding the CSS class or . faa-fastfaa-slow</li><li>可以通过给目标元素添加CSS类<code>faa-fast</code>或<code>faa-slow</code>来控制动画快慢。</li></ol></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><p>1.On DOM load(当页面加载时显示动画)</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">{% tip warning faa-horizontal animated %}warning{% endtip %}</span><br><span class="line">{% tip ban faa-flash animated %}ban{% endtip %}</span><br></pre></td></tr></table></figure><p>2.调整动画速度</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">{% tip warning faa-horizontal animated faa-fast %}warning{% endtip %}</span><br><span class="line">{% tip ban faa-flash animated faa-slow %}ban{% endtip %}</span><br></pre></td></tr></table></figure><p>3.On hover(当鼠标悬停时显示动画)</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">{% tip warning faa-horizontal animated-hover %}warning{% endtip %}</span><br><span class="line">{% tip ban faa-flash animated-hover %}ban{% endtip %}</span><br></pre></td></tr></table></figure><p>4.On parent hover(当鼠标悬停在父级元素时显示动画)</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">{% tip warning faa-parent animated-hover %}<span class="language-xml"><span class="tag"><<span class="name">p</span> <span class="attr">class</span>=<span class="string">"faa-horizontal"</span>></span></span>warning<span class="language-xml"><span class="tag"></<span class="name">p</span>></span></span>{% endtip %}</span><br><span class="line">{% tip ban faa-parent animated-hover %}<span class="language-xml"><span class="tag"><<span class="name">p</span> <span class="attr">class</span>=<span class="string">"faa-flash"</span>></span></span>ban<span class="language-xml"><span class="tag"></<span class="name">p</span>></span></span>{% endtip %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-4"><p>1.On DOM load(当页面加载时显示动画)</p><div class="tip warning faa-horizontal animated"><p>warning</p></div><div class="tip ban faa-flash animated"><p>ban</p></div>2.调整动画速度<div class="tip warning faa-horizontal animated faa-fast"><p>warning</p></div><div class="tip ban faa-flash animated faa-slow"><p>ban</p></div>3.On hover(当鼠标悬停时显示动画)<div class="tip warning faa-horizontal animated-hover"><p>warning</p></div><div class="tip ban faa-flash animated-hover"><p>ban</p></div>4.On parent hover(当鼠标悬停在父级元素时显示动画)<div class="tip warning faa-parent animated-hover"><p class="faa-horizontal">warning</p></div><div class="tip ban faa-parent animated-hover"><p class="faa-flash">ban</p></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-7-复选列表-checkbox">2.7 复选列表 checkbox</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-2">配置参数</button></li><li class="tab"><button type="button" data-href="#分栏-3">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% checkbox 样式参数(可选), 文本(支持简单md) %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><ol><li><code>样式</code>: plus, minus, times</li><li><code>颜色</code>: red,yellow,green,cyan,blue,gray</li><li><code>选中状态</code>: checked</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">{% checkbox 纯文本测试 %}</span><br><span class="line">{% checkbox checked, 支持简单的 [<span class="string">markdown</span>](<span class="link">https://guides.github.com/features/mastering-markdown/</span>) 语法 %}</span><br><span class="line">{% checkbox red, 支持自定义颜色 %}</span><br><span class="line">{% checkbox green checked, 绿色 + 默认选中 %}</span><br><span class="line">{% checkbox yellow checked, 黄色 + 默认选中 %}</span><br><span class="line">{% checkbox cyan checked, 青色 + 默认选中 %}</span><br><span class="line">{% checkbox blue checked, 蓝色 + 默认选中 %}</span><br><span class="line">{% checkbox plus green checked, 增加 %}</span><br><span class="line">{% checkbox minus yellow checked, 减少 %}</span><br><span class="line">{% checkbox times red checked, 叉 %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-4"><div class='checkbox'><input type="checkbox" /> <p>纯文本测试</p> </div><div class='checkbox checked'><input type="checkbox" checked="checked"/> <p>支持简单的 <a href="https://guides.github.com/features/mastering-markdown/">markdown</a> 语法</p> </div><div class='checkbox red'><input type="checkbox" /> <p>支持自定义颜色</p> </div><div class='checkbox green checked'><input type="checkbox" checked="checked"/> <p>绿色 + 默认选中</p> </div><div class='checkbox yellow checked'><input type="checkbox" checked="checked"/> <p>黄色 + 默认选中</p> </div><div class='checkbox cyan checked'><input type="checkbox" checked="checked"/> <p>青色 + 默认选中</p> </div><div class='checkbox blue checked'><input type="checkbox" checked="checked"/> <p>蓝色 + 默认选中</p> </div><div class='checkbox plus green checked'><input type="checkbox" checked="checked"/> <p>增加</p> </div><div class='checkbox minus yellow checked'><input type="checkbox" checked="checked"/> <p>减少</p> </div><div class='checkbox times red checked'><input type="checkbox" checked="checked"/> <p>叉</p> </div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-8-单选列表-radio">2.8 单选列表 radio</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-2">配置参数</button></li><li class="tab"><button type="button" data-href="#分栏-3">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% radio 样式参数(可选), 文本(支持简单md) %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><ol><li><code>颜色</code>: red,yellow,green,cyan,blue,gray</li><li><code>选中状态</code>: checked</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">{% radio 纯文本测试 %}</span><br><span class="line">{% radio checked, 支持简单的 [<span class="string">markdown</span>](<span class="link">https://guides.github.com/features/mastering-markdown/</span>) 语法 %}</span><br><span class="line">{% radio red, 支持自定义颜色 %}</span><br><span class="line">{% radio green, 绿色 %}</span><br><span class="line">{% radio yellow, 黄色 %}</span><br><span class="line">{% radio cyan, 青色 %}</span><br><span class="line">{% radio blue, 蓝色 %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-4"><div class='checkbox'><input type="radio" /> <p>纯文本测试</p> </div><div class='checkbox checked'><input type="radio" checked="checked"/> <p>支持简单的 <a href="https://guides.github.com/features/mastering-markdown/">markdown</a> 语法</p> </div><div class='checkbox red'><input type="radio" /> <p>支持自定义颜色</p> </div><div class='checkbox green'><input type="radio" /> <p>绿色</p> </div><div class='checkbox yellow'><input type="radio" /> <p>黄色</p> </div><div class='checkbox cyan'><input type="radio" /> <p>青色</p> </div><div class='checkbox blue'><input type="radio" /> <p>蓝色</p> </div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-9-时间轴-timeline">2.9 时间轴 timeline</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-2">配置参数</button></li><li class="tab"><button type="button" data-href="#分栏-3">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">{% timeline 时间线标题(可选)[,color] %}</span><br><span class="line"><!-- timeline 时间节点(标题) --></span><br><span class="line">正文内容</span><br><span class="line"><!-- endtimeline --></span><br><span class="line"><!-- timeline 时间节点(标题) --></span><br><span class="line">正文内容</span><br><span class="line"><!-- endtimeline --></span><br><span class="line">{% endtimeline %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><ol><li><code>title</code>:标题/时间线</li><li><code>color</code>:<code>timeline</code>颜色:default(留空) / blue / pink / red / purple / orange / green</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">{% timeline 时间轴样式,blue %}</span><br><span class="line"></span><br><span class="line"><!-- timeline 2020-07-24 [<span class="string">2.6.6 -> 3.0</span>](<span class="link">https://github.com/volantis-x/hexo-theme-volantis/releases</span>) --></span><br><span class="line"></span><br><span class="line"><span class="bullet">1.</span> 如果有 <span class="code">`hexo-lazyload-image`</span> 插件,需要删除并重新安装最新版本,设置 <span class="code">`lazyload.isSPA: true`</span>。</span><br><span class="line"><span class="bullet">2.</span> 2.x 版本的 css 和 js 不适用于 3.x 版本,如果使用了 <span class="code">`use_cdn: true`</span> 则需要删除。</span><br><span class="line"><span class="bullet">3.</span> 2.x 版本的 fancybox 标签在 3.x 版本中被重命名为 gallery 。</span><br><span class="line"><span class="bullet">4.</span> 2.x 版本的置顶 <span class="code">`top: true`</span> 改为了 <span class="code">`pin: true`</span>,并且同样适用于 <span class="code">`layout: page`</span> 的页面。</span><br><span class="line"><span class="bullet">5.</span> 如果使用了 <span class="code">`hexo-offline`</span> 插件,建议卸载,3.0 版本默认开启了 pjax 服务。</span><br><span class="line"></span><br><span class="line"><!-- endtimeline --></span><br><span class="line"></span><br><span class="line"><!-- timeline 2020-05-15 [<span class="string">2.6.3 -> 2.6.6</span>](<span class="link">https://github.com/volantis-x/hexo-theme-volantis/releases/tag/2.6.6</span>) --></span><br><span class="line"></span><br><span class="line">不需要额外处理。</span><br><span class="line"></span><br><span class="line"><!-- endtimeline --></span><br><span class="line"></span><br><span class="line"><!-- timeline 2020-04-20 [<span class="string">2.6.2 -> 2.6.3</span>](<span class="link">https://github.com/volantis-x/hexo-theme-volantis/releases/tag/2.6.3</span>) --></span><br><span class="line"></span><br><span class="line"><span class="bullet">1.</span> 全局搜索 <span class="code">`seotitle`</span> 并替换为 <span class="code">`seo_title`</span>。</span><br><span class="line"><span class="bullet">2.</span> group 组件的索引规则有变,使用 group 组件的文章内,<span class="code">`group: group_name`</span> 对应的组件名必须是 <span class="code">`group_name`</span>。</span><br><span class="line"><span class="bullet">2.</span> group 组件的列表名优先显示文章的 <span class="code">`short_title`</span> 其次是 <span class="code">`title`</span>。</span><br><span class="line"></span><br><span class="line"><!-- endtimeline --></span><br><span class="line"></span><br><span class="line">{% endtimeline %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-4"><div class="timeline blue"><div class='timeline-item headline'><div class='timeline-item-title'><div class='item-circle'><p>时间轴样式</p></div></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>2020-07-24 <a href="https://github.com/volantis-x/hexo-theme-volantis/releases">2.6.6 -> 3.0</a></p></div></div><div class='timeline-item-content'><ol><li>如果有 <code>hexo-lazyload-image</code> 插件,需要删除并重新安装最新版本,设置 <code>lazyload.isSPA: true</code>。</li><li>2.x 版本的 css 和 js 不适用于 3.x 版本,如果使用了 <code>use_cdn: true</code> 则需要删除。</li><li>2.x 版本的 fancybox 标签在 3.x 版本中被重命名为 gallery 。</li><li>2.x 版本的置顶 <code>top: true</code> 改为了 <code>pin: true</code>,并且同样适用于 <code>layout: page</code> 的页面。</li><li>如果使用了 <code>hexo-offline</code> 插件,建议卸载,3.0 版本默认开启了 pjax 服务。</li></ol></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>2020-05-15 <a href="https://github.com/volantis-x/hexo-theme-volantis/releases/tag/2.6.6">2.6.3 -> 2.6.6</a></p></div></div><div class='timeline-item-content'><p>不需要额外处理。</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>2020-04-20 <a href="https://github.com/volantis-x/hexo-theme-volantis/releases/tag/2.6.3">2.6.2 -> 2.6.3</a></p></div></div><div class='timeline-item-content'><ol><li>全局搜索 <code>seotitle</code> 并替换为 <code>seo_title</code>。</li><li>group 组件的索引规则有变,使用 group 组件的文章内,<code>group: group_name</code> 对应的组件名必须是 <code>group_name</code>。</li><li>group 组件的列表名优先显示文章的 <code>short_title</code> 其次是 <code>title</code>。</li></ol></div></div></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-10-链接卡片-link">2.10 链接卡片 link</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-2">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-3">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% link 标题, 链接, 图片链接(可选) %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% link 糖果屋教程贴, https://akilar.top/posts/615e2dec/, https://cdn.cbd.int/[email protected]/image/siteicon/favicon.ico %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><div class="tag link"><a class="link-card" title="糖果屋教程贴" href="https://akilar.top/posts/615e2dec/"><div class="left"><img src="https://cdn.cbd.int/[email protected]/image/siteicon/favicon.ico"/></div><div class="right"><p class="text">糖果屋教程贴</p><p class="url">https://akilar.top/posts/615e2dec/</p></div></a></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-11-按钮-btns">2.11 按钮 btns</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-2">参数配置</button></li><li class="tab"><button type="button" data-href="#分栏-3">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">{% btns 样式参数 %}</span><br><span class="line">{% cell 标题, 链接, 图片或者图标 %}</span><br><span class="line">{% cell 标题, 链接, 图片或者图标 %}</span><br><span class="line">{% endbtns %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><ol><li>圆角样式:rounded, circle</li><li>增加文字样式:可以在容器内增加 <code><b></code>标题<code></b></code>和<code><p></code>描述文字<code></p></code></li><li>布局方式:<br>默认为自动宽度,适合视野内只有一两个的情况。</li></ol><table><thead><tr><th>参数</th><th>含义</th></tr></thead><tbody><tr><td>wide</td><td>宽一点的按钮</td></tr><tr><td>fill</td><td>填充布局,自动铺满至少一行,多了会换行</td></tr><tr><td>center</td><td>居中,按钮之间是固定间距</td></tr><tr><td>around</td><td>居中分散</td></tr><tr><td>grid2</td><td>等宽最多2列,屏幕变窄会适当减少列数</td></tr><tr><td>grid3</td><td>等宽最多3列,屏幕变窄会适当减少列数</td></tr><tr><td>grid4</td><td>等宽最多4列,屏幕变窄会适当减少列数</td></tr><tr><td>grid5</td><td>等宽最多5列,屏幕变窄会适当减少列数</td></tr></tbody></table><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><p>1.如果需要显示类似「团队成员」之类的一组含有头像的链接</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">{% btns circle grid5 %}</span><br><span class="line">{% cell xaoxuu, https://xaoxuu.com, https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/avatar/avatar.png %}</span><br><span class="line">{% cell xaoxuu, https://xaoxuu.com, https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/avatar/avatar.png %}</span><br><span class="line">{% cell xaoxuu, https://xaoxuu.com, https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/avatar/avatar.png %}</span><br><span class="line">{% cell xaoxuu, https://xaoxuu.com, https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/avatar/avatar.png %}</span><br><span class="line">{% cell xaoxuu, https://xaoxuu.com, https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/avatar/avatar.png %}</span><br><span class="line">{% endbtns %}</span><br></pre></td></tr></table></figure><p>2.或者含有图标的按钮</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">{% btns rounded grid5 %}</span><br><span class="line">{% cell 下载源码, /, fas fa-download %}</span><br><span class="line">{% cell 查看文档, /, fas fa-book-open %}</span><br><span class="line">{% endbtns %}</span><br></pre></td></tr></table></figure><p>3.圆形图标 + 标题 + 描述 + 图片 + 网格5列 + 居中</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">{% btns circle center grid5 %}</span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">'https://apps.apple.com/cn/app/heart-mate-pro-hrm-utility/id1463348922?ls=1'</span>></span></span></span><br><span class="line"> <span class="language-xml"><span class="tag"><<span class="name">i</span> <span class="attr">class</span>=<span class="string">'fab fa-apple'</span>></span></span><span class="language-xml"><span class="tag"></<span class="name">i</span>></span></span></span><br><span class="line"> <span class="language-xml"><span class="tag"><<span class="name">b</span>></span></span>心率管家<span class="language-xml"><span class="tag"></<span class="name">b</span>></span></span></span><br><span class="line"> {% p red, 专业版 %}</span><br><span class="line"> <span class="language-xml"><span class="tag"><<span class="name">img</span> <span class="attr">src</span>=<span class="string">'https://cdn.jsdelivr.net/gh/fomalhaut1998/cdn-assets/qrcode/heartmate_pro.png'</span>></span></span></span><br><span class="line"><span class="language-xml"><span class="tag"></<span class="name">a</span>></span></span></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">'https://apps.apple.com/cn/app/heart-mate-lite-hrm-utility/id1475747930?ls=1'</span>></span></span></span><br><span class="line"> <span class="language-xml"><span class="tag"><<span class="name">i</span> <span class="attr">class</span>=<span class="string">'fab fa-apple'</span>></span></span><span class="language-xml"><span class="tag"></<span class="name">i</span>></span></span></span><br><span class="line"> <span class="language-xml"><span class="tag"><<span class="name">b</span>></span></span>心率管家<span class="language-xml"><span class="tag"></<span class="name">b</span>></span></span></span><br><span class="line"> {% p green, 免费版 %}</span><br><span class="line"> <span class="language-xml"><span class="tag"><<span class="name">img</span> <span class="attr">src</span>=<span class="string">'https://cdn.jsdelivr.net/gh/fomalhaut1998/cdn-assets/qrcode/heartmate_lite.png'</span>></span></span></span><br><span class="line"><span class="language-xml"><span class="tag"></<span class="name">a</span>></span></span></span><br><span class="line">{% endbtns %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-4"><p>1.如果需要显示类似「团队成员」之类的一组含有头像的链接</p><div class="btns circle grid5"> <a class="button" href='https://xaoxuu.com' title='xaoxuu'><img src='https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/avatar/avatar.png'>xaoxuu</a><a class="button" href='https://xaoxuu.com' title='xaoxuu'><img src='https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/avatar/avatar.png'>xaoxuu</a><a class="button" href='https://xaoxuu.com' title='xaoxuu'><img src='https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/avatar/avatar.png'>xaoxuu</a><a class="button" href='https://xaoxuu.com' title='xaoxuu'><img src='https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/avatar/avatar.png'>xaoxuu</a><a class="button" href='https://xaoxuu.com' title='xaoxuu'><img src='https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/avatar/avatar.png'>xaoxuu</a> </div>2.或者含有图标的按钮<div class="btns rounded grid5"> <a class="button" href='/' title='下载源码'><i class='fas fa-download'></i>下载源码</a><a class="button" href='/' title='查看文档'><i class='fas fa-book-open'></i>查看文档</a> </div>3.圆形图标 + 标题 + 描述 + 图片 + 网格5列 + 居中<div class="btns circle center grid5"> <a href='https://apps.apple.com/cn/app/heart-mate-pro-hrm-utility/id1463348922?ls=1'> <i class='fab fa-apple'></i> <b>心率管家</b> <p class='p red'>专业版</p> <img src='https://cdn.jsdelivr.net/gh/fomalhaut1998/cdn-assets/qrcode/heartmate_pro.png'></a><a href='https://apps.apple.com/cn/app/heart-mate-lite-hrm-utility/id1475747930?ls=1'> <i class='fab fa-apple'></i> <b>心率管家</b> <p class='p green'>免费版</p> <img src='https://cdn.jsdelivr.net/gh/fomalhaut1998/cdn-assets/qrcode/heartmate_lite.png'></a> </div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-12-github卡片-ghcard">2.12 github卡片 ghcard</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-2">参数配置</button></li><li class="tab"><button type="button" data-href="#分栏-3">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">{% ghcard 用户名, 其它参数(可选) %}</span><br><span class="line">{% ghcard 用户名/仓库, 其它参数(可选) %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><p>使用<code>,</code>分割各个参数。写法为:<code>参数名=参数值</code><br>以下只写几个常用参数值。</p><table><thead><tr><th><strong>参数名</strong></th><th>取值</th><th>释义</th></tr></thead><tbody><tr><td>hide</td><td>stars,commits,prs,issues,contribs</td><td>隐藏指定统计</td></tr><tr><td>count_private</td><td>true</td><td>将私人项目贡献添加到总提交计数中</td></tr><tr><td>show_icons</td><td>true</td><td>显示图标</td></tr><tr><td>theme</td><td>查阅:<a href="https://github.com/anuraghazra/github-readme-stats/blob/master/themes/README.md">Available Themes</a></td><td>主题</td></tr></tbody></table><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><p>1.用户信息卡片</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">| {% ghcard fomalhaut1998 %} | {% ghcard fomalhaut1998, theme=vue %} |</span><br><span class="line">| -- | -- |</span><br><span class="line">| {% ghcard fomalhaut1998, theme=buefy %} | {% ghcard fomalhaut1998, theme=solarized-light %} |</span><br><span class="line">| {% ghcard fomalhaut1998, theme=onedark %} | {% ghcard fomalhaut1998, theme=solarized-dark %} |</span><br><span class="line">| {% ghcard fomalhaut1998, theme=algolia %} | {% ghcard fomalhaut1998, theme=calm %} |</span><br></pre></td></tr></table></figure><p>2.仓库信息卡片</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">| {% ghcard volantis-x/hexo-theme-volantis %} | {% ghcard volantis-x/hexo-theme-volantis, theme=vue %} |</span><br><span class="line">| -- | -- |</span><br><span class="line">| {% ghcard volantis-x/hexo-theme-volantis, theme=buefy %} | {% ghcard volantis-x/hexo-theme-volantis, theme=solarized-light %} |</span><br><span class="line">| {% ghcard volantis-x/hexo-theme-volantis, theme=onedark %} | {% ghcard volantis-x/hexo-theme-volantis, theme=solarized-dark %} |</span><br><span class="line">| {% ghcard volantis-x/hexo-theme-volantis, theme=algolia %} | {% ghcard volantis-x/hexo-theme-volantis, theme=calm %} |</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-4"><p>1.用户信息卡片</p><table><thead><tr><th><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/fomalhaut1998"><img src="https://github-readme-stats.vercel.app/api/?username=fomalhaut1998&show_owner=true"/></a></th><th><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/fomalhaut1998"><img src="https://github-readme-stats.vercel.app/api/?username=fomalhaut1998&theme=vue&show_owner=true"/></a></th></tr></thead><tbody><tr><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/fomalhaut1998"><img src="https://github-readme-stats.vercel.app/api/?username=fomalhaut1998&theme=buefy&show_owner=true"/></a></td><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/fomalhaut1998"><img src="https://github-readme-stats.vercel.app/api/?username=fomalhaut1998&theme=solarized-light&show_owner=true"/></a></td></tr><tr><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/fomalhaut1998"><img src="https://github-readme-stats.vercel.app/api/?username=fomalhaut1998&theme=onedark&show_owner=true"/></a></td><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/fomalhaut1998"><img src="https://github-readme-stats.vercel.app/api/?username=fomalhaut1998&theme=solarized-dark&show_owner=true"/></a></td></tr><tr><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/fomalhaut1998"><img src="https://github-readme-stats.vercel.app/api/?username=fomalhaut1998&theme=algolia&show_owner=true"/></a></td><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/fomalhaut1998"><img src="https://github-readme-stats.vercel.app/api/?username=fomalhaut1998&theme=calm&show_owner=true"/></a></td></tr></tbody></table><p>2.仓库信息卡片</p><table><thead><tr><th><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/volantis-x/hexo-theme-volantis"><img src="https://github-readme-stats.vercel.app/api/pin/?username=volantis-x&repo=hexo-theme-volantis&show_owner=true"/></a></th><th><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/volantis-x/hexo-theme-volantis"><img src="https://github-readme-stats.vercel.app/api/pin/?username=volantis-x&repo=hexo-theme-volantis&theme=vue&show_owner=true"/></a></th></tr></thead><tbody><tr><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/volantis-x/hexo-theme-volantis"><img src="https://github-readme-stats.vercel.app/api/pin/?username=volantis-x&repo=hexo-theme-volantis&theme=buefy&show_owner=true"/></a></td><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/volantis-x/hexo-theme-volantis"><img src="https://github-readme-stats.vercel.app/api/pin/?username=volantis-x&repo=hexo-theme-volantis&theme=solarized-light&show_owner=true"/></a></td></tr><tr><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/volantis-x/hexo-theme-volantis"><img src="https://github-readme-stats.vercel.app/api/pin/?username=volantis-x&repo=hexo-theme-volantis&theme=onedark&show_owner=true"/></a></td><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/volantis-x/hexo-theme-volantis"><img src="https://github-readme-stats.vercel.app/api/pin/?username=volantis-x&repo=hexo-theme-volantis&theme=solarized-dark&show_owner=true"/></a></td></tr><tr><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/volantis-x/hexo-theme-volantis"><img src="https://github-readme-stats.vercel.app/api/pin/?username=volantis-x&repo=hexo-theme-volantis&theme=algolia&show_owner=true"/></a></td><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/volantis-x/hexo-theme-volantis"><img src="https://github-readme-stats.vercel.app/api/pin/?username=volantis-x&repo=hexo-theme-volantis&theme=calm&show_owner=true"/></a></td></tr></tbody></table><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-13-github徽标-ghbdage">2.13 github徽标 ghbdage</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-2">配置参数</button></li><li class="tab"><button type="button" data-href="#分栏-3">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% bdage [right],[left],[logo]||[color],[link],[title]||[option] %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><ol><li><code>left</code>:徽标左边的信息,必选参数。</li><li><code>right</code>: 徽标右边的信息,必选参数,</li><li><code>logo</code>:徽标图标,图标名称详见<a href="https://simpleicons.org/">simpleicons</a>,可选参数。</li><li><code>color</code>:徽标右边的颜色,可选参数。</li><li><code>link</code>:指向的链接,可选参数。</li><li><code>title</code>:徽标的额外信息,可选参数。主要用于优化SEO,但<code>object</code>标签不会像<code>a</code>标签一样在鼠标悬停显示<code>title</code>信息。</li><li><code>option</code>:自定义参数,支持<a href="https://shields.io/">shields.io</a>的全部API参数支持,具体参数可以参看上文中的拓展写法示例。形式为<code>name1=value2&name2=value2</code>。</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><p>1.基本参数,定义徽标左右文字和图标</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">{% bdage Theme,Butterfly %}</span><br><span class="line">{% bdage Frame,Hexo,hexo %}</span><br></pre></td></tr></table></figure><p>2.信息参数,定义徽标右侧内容背景色,指向链接</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">{% bdage CDN,JsDelivr,jsDelivr||abcdef,https://metroui.org.ua/index.html,本站使用JsDelivr为静态资源提供CDN加速 %}</span><br><span class="line">//如果是跨顺序省略可选参数,仍然需要写个逗号,用作分割</span><br><span class="line">{% bdage Source,GitHub,GitHub||,https://github.com/ %}</span><br></pre></td></tr></table></figure><p>3.拓展参数,支持shields的API的全部参数内容</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">{% bdage Hosted,Vercel,Vercel||brightgreen,https://vercel.com/,本站采用双线部署,默认线路托管于Vercel||style=social&logoWidth=20 %}</span><br><span class="line">//如果是跨顺序省略可选参数组,仍然需要写双竖线||用作分割</span><br><span class="line">{% bdage Hosted,Vercel,Vercel||||style=social&logoWidth=20&logoColor=violet %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-4"><p>1.基本参数,定义徽标左右文字和图标</p><p><object class="ghbdage" style="margin-inline:5px" title="" standby="loading..." data="https://img.shields.io/badge/Butterfly-Theme-orange?logo=&color=orange&link=&"></object><br><object class="ghbdage" style="margin-inline:5px" title="" standby="loading..." data="https://img.shields.io/badge/Hexo-Frame-orange?logo=hexo&color=orange&link=&"></object></p><p>2.信息参数,定义徽标右侧内容背景色,指向链接</p><p><object class="ghbdage" style="margin-inline:5px" title="本站使用JsDelivr为静态资源提供CDN加速" standby="loading..." data="https://img.shields.io/badge/JsDelivr-CDN-orange?logo=jsDelivr&color=abcdef&link=https://metroui.org.ua/index.html&"></object><br>//如果是跨顺序省略可选参数,仍然需要写个逗号,用作分割<br><object class="ghbdage" style="margin-inline:5px" title="" standby="loading..." data="https://img.shields.io/badge/GitHub-Source-orange?logo=GitHub&color=orange&link=https://github.com/&"></object></p><p>3.拓展参数,支持shields的API的全部参数内容</p><p><object class="ghbdage" style="margin-inline:5px" title="本站采用双线部署,默认线路托管于Vercel" standby="loading..." data="https://img.shields.io/badge/Vercel-Hosted-orange?logo=Vercel&color=brightgreen&link=https://vercel.com/&style=social&logoWidth=20"></object><br>//如果是跨顺序省略可选参数组,仍然需要写双竖线||用作分割<br><object class="ghbdage" style="margin-inline:5px" title="" standby="loading..." data="https://img.shields.io/badge/Vercel-Hosted-orange?logo=Vercel&color=orange&link=&style=social&logoWidth=20&logoColor=violet"></object></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-14-网站卡片-sites">2.14 网站卡片 sites</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-2">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-3">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">{% sitegroup %}</span><br><span class="line">{% site 标题, url=链接, screenshot=截图链接, avatar=头像链接(可选), description=描述(可选) %}</span><br><span class="line">{% site 标题, url=链接, screenshot=截图链接, avatar=头像链接(可选), description=描述(可选) %}</span><br><span class="line">{% endsitegroup %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">{% sitegroup %}</span><br><span class="line">{% site xaoxuu, url=https://xaoxuu.com, screenshot=https://i.loli.net/2020/08/21/VuSwWZ1xAeUHEBC.jpg, avatar=https://cdn.jsdelivr.net/gh/fomalhaut1998/cdn-assets/avatar/avatar.png, description=简约风格 %}</span><br><span class="line">{% site inkss, url=https://inkss.cn, screenshot=https://i.loli.net/2020/08/21/Vzbu3i8fXs6Nh5Y.jpg, avatar=https://cdn.jsdelivr.net/gh/inkss/common@master/static/web/avatar.jpg, description=这是一段关于这个网站的描述文字 %}</span><br><span class="line">{% site MHuiG, url=https://blog.mhuig.top, screenshot=https://i.loli.net/2020/08/22/d24zpPlhLYWX6D1.png, avatar=https://cdn.jsdelivr.net/gh/MHuiG/imgbed@master/data/p.png, description=这是一段关于这个网站的描述文字 %}</span><br><span class="line">{% site Colsrch, url=https://colsrch.top, screenshot=https://i.loli.net/2020/08/22/dFRWXm52OVu8qfK.png, avatar=https://cdn.jsdelivr.net/gh/Colsrch/images/Colsrch/avatar.jpg, description=这是一段关于这个网站的描述文字 %}</span><br><span class="line">{% site Linhk1606, url=https://linhk1606.github.io, screenshot=https://i.loli.net/2020/08/21/3PmGLCKicnfow1x.png, avatar=https://i.loli.net/2020/02/09/PN7I5RJfFtA93r2.png, description=这是一段关于这个网站的描述文字 %}</span><br><span class="line">{% endsitegroup %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><div class="site-card-group"><a class="site-card" href="https://fomalhaut1998.com"><div class="img"><img src="https://i.loli.net/2020/08/21/VuSwWZ1xAeUHEBC.jpg"/></div><div class="info"><img src="https://cdn.jsdelivr.net/gh/fomalhaut1998/cdn-assets/avatar/avatar.png"/><span class="title">fomalhaut1998</span><span class="desc">简约风格</span></div></a><a class="site-card" href="https://inkss.cn"><div class="img"><img src="https://i.loli.net/2020/08/21/Vzbu3i8fXs6Nh5Y.jpg"/></div><div class="info"><img src="https://cdn.jsdelivr.net/gh/inkss/common@master/static/web/avatar.jpg"/><span class="title">inkss</span><span class="desc">这是一段关于这个网站的描述文字</span></div></a><a class="site-card" href="https://blog.mhuig.top"><div class="img"><img src="https://i.loli.net/2020/08/22/d24zpPlhLYWX6D1.png"/></div><div class="info"><img src="https://cdn.jsdelivr.net/gh/MHuiG/imgbed@master/data/p.png"/><span class="title">MHuiG</span><span class="desc">这是一段关于这个网站的描述文字</span></div></a><a class="site-card" href="https://colsrch.top"><div class="img"><img src="https://i.loli.net/2020/08/22/dFRWXm52OVu8qfK.png"/></div><div class="info"><img src="https://cdn.jsdelivr.net/gh/Colsrch/images/Colsrch/avatar.jpg"/><span class="title">Colsrch</span><span class="desc">这是一段关于这个网站的描述文字</span></div></a><a class="site-card" href="https://linhk1606.github.io"><div class="img"><img src="https://i.loli.net/2020/08/21/3PmGLCKicnfow1x.png"/></div><div class="info"><img src="https://i.loli.net/2020/02/09/PN7I5RJfFtA93r2.png"/><span class="title">Linhk1606</span><span class="desc">这是一段关于这个网站的描述文字</span></div></a></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-15-行内图片-inlineimage">2.15 行内图片 inlineimage</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-2">参数配置</button></li><li class="tab"><button type="button" data-href="#分栏-3">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% inlineimage 图片链接, height=高度(可选) %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><ol><li><code>高度</code>:height=20px</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">这是 {% inlineimage https://cdn.jsdelivr.net/gh/volantis-x/cdn-emoji/aru-l/0000.gif %} 一段话。</span><br><span class="line"></span><br><span class="line">这又是 {% inlineimage https://cdn.jsdelivr.net/gh/volantis-x/cdn-emoji/aru-l/5150.gif, height=40px %} 一段话。</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-4"><p>这是 <img no-lazy class="inline" src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-emoji/aru-l/0000.gif" style="height:1.5em"/> 一段话。</p><p>这又是 <img no-lazy class="inline" src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-emoji/aru-l/5150.gif" style="height:40px;"/> 一段话。</p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-16-单张图片-image">2.16 单张图片 image</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-2">参数配置</button></li><li class="tab"><button type="button" data-href="#分栏-3">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% image 链接, width=宽度(可选), height=高度(可选), alt=描述(可选), bg=占位颜色(可选) %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><ol><li>图片宽度高度:width=300px, height=32px</li><li>图片描述:alt=图片描述(butterfly需要在主题配置文件中开启图片描述)</li><li>占位背景色:bg=#f2f2f2</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><p>1.添加描述:</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% image https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/025.jpg, alt=每天下课回宿舍的路,没有什么故事。 %}</span><br></pre></td></tr></table></figure><p>2.指定宽度</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% image https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/025.jpg, width=400px %}</span><br></pre></td></tr></table></figure><p>3.指定宽度并添加描述:</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% image https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/025.jpg, width=400px, alt=每天下课回宿舍的路,没有什么故事。 %}</span><br></pre></td></tr></table></figure><p>4.设置占位背景色:</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% image https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/025.jpg, width=400px, bg=#1D0C04, alt=优化不同宽度浏览的观感 %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-4"><p>1.添加描述:</p><div class="img-wrap"><div class="img-bg"><img class="img" src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/025.jpg" alt="每天下课回宿舍的路,没有什么故事。"/></div><span class="image-caption">每天下课回宿舍的路,没有什么故事。</span></div>2..指定宽度<div class="img-wrap"><div class="img-bg"><img class="img" src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/025.jpg" style="width:400px;"/></div></div>3.指定宽度并添加描述:<div class="img-wrap"><div class="img-bg"><img class="img" src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/025.jpg" alt="每天下课回宿舍的路,没有什么故事。" style="width:400px;"/></div><span class="image-caption">每天下课回宿舍的路,没有什么故事。</span></div>4.设置占位背景色:<div class="img-wrap"><div class="img-bg" style="background:#1D0C04"><img class="img" src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/025.jpg" alt="优化不同宽度浏览的观感" style="width:400px;"/></div><span class="image-caption">优化不同宽度浏览的观感</span></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-17-音频-audio">2.17 音频 audio</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-2">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-3">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% audio 音频链接 %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% audio https://github.com/volantis-x/volantis-docs/releases/download/assets/Lumia1020.mp3 %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><div class="audio"><audio controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/Lumia1020.mp3' type='audio/mp3'>Your browser does not support the audio tag.</audio></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-18-视频-video">2.18 视频 video</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-2">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-3">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% video 视频链接 %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><ol><li><code>对齐方向</code>:left, center, right</li><li><code>列数</code>:逗号后面直接写列数,支持 1 ~ 4 列。</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><p>1.100%宽度</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG<span class="emphasis">_0341.mov %}</span></span><br></pre></td></tr></table></figure><p>2.50%宽度</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">{% videos, 2 %}</span><br><span class="line">{% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG<span class="emphasis">_0341.mov %}</span></span><br><span class="line"><span class="emphasis">{% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_</span>0341.mov %}</span><br><span class="line">{% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG<span class="emphasis">_0341.mov %}</span></span><br><span class="line"><span class="emphasis">{% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_</span>0341.mov %}</span><br><span class="line">{% endvideos %}</span><br></pre></td></tr></table></figure><p>3.25%宽度</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">{% videos, 4 %}</span><br><span class="line">{% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG<span class="emphasis">_0341.mov %}</span></span><br><span class="line"><span class="emphasis">{% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_</span>0341.mov %}</span><br><span class="line">{% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG<span class="emphasis">_0341.mov %}</span></span><br><span class="line"><span class="emphasis">{% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_</span>0341.mov %}</span><br><span class="line">{% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG<span class="emphasis">_0341.mov %}</span></span><br><span class="line"><span class="emphasis">{% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_</span>0341.mov %}</span><br><span class="line">{% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG<span class="emphasis">_0341.mov %}</span></span><br><span class="line"><span class="emphasis">{% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_</span>0341.mov %}</span><br><span class="line">{% endvideos %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-4"><p>1.100%宽度</p><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div>2.50%宽度<div class="videos" col='2'><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div></div>3.25%宽度<div class="videos" col='4'><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-19-相册-gallery">2.19 相册 gallery</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-2">参数配置</button></li><li class="tab"><button type="button" data-href="#分栏-3">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><p>1.gallerygroup 相册图库</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="language-xml"><span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"gallery-group-main"</span>></span></span></span><br><span class="line">{% galleryGroup name description link img-url %}</span><br><span class="line">{% galleryGroup name description link img-url %}</span><br><span class="line">{% galleryGroup name description link img-url %}</span><br><span class="line"><span class="language-xml"><span class="tag"></<span class="name">div</span>></span></span></span><br></pre></td></tr></table></figure><p>2.gallery 相册</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">{% gallery %}</span><br><span class="line">markdown 圖片格式</span><br><span class="line">{% endgallery %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><ul><li>gallerygroup 相册图库</li></ul><table><thead><tr><th>参数名</th><th>释义</th></tr></thead><tbody><tr><td>name</td><td>图库名字</td></tr><tr><td>description</td><td>图库描述</td></tr><tr><td>link</td><td>链接到对应相册的地址</td></tr><tr><td>img-url</td><td>图库封面</td></tr></tbody></table><ul><li><p>gallery 相册</p><p>区别于旧版的Gallery相册,新的Gallery相册会自动根据图片长度进行排版,书写也更加方便,与markdown格式一样。可根据需要插入到相应的md。无需再自己配置长宽。<strong>建议在粘贴时故意使用长短、大小、横竖不一的图片</strong>,会有更好的效果。(尺寸完全相同的图片只会平铺输出,效果很糟糕)</p></li></ul><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><p>1.gallerygroup 相册图库</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="language-xml"><span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"gallery-group-main"</span>></span></span></span><br><span class="line">{% galleryGroup MC 在Rikkaの六花服务器里留下的足迹 '/gallery/MC/' https://cdn.cbd.int/[email protected]/image/1.jpg %}</span><br><span class="line">{% galleryGroup Gundam 哦咧哇gundam哒! '/gallery/Gundam/' https://cdn.cbd.int/[email protected]/image/20200907110508327.png %}</span><br><span class="line">{% galleryGroup I-am-Akilar 某种意义上也算自拍吧 '/gallery/I-am-Akilar/' https://cdn.cbd.int/[email protected]/image/20200907113116651.png %}</span><br><span class="line"><span class="language-xml"><span class="tag"></<span class="name">div</span>></span></span></span><br></pre></td></tr></table></figure><p>2.gallery 相册</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">{% gallery %}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">{% endgallery %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-4"><p>1.gallerygroup 相册图库</p><div class="gallery-group-main"> <figure class="gallery-group"> <img class="gallery-group-img no-lightbox" src='https://cdn.cbd.int/[email protected]/image/1.jpg' alt="Group Image Gallery"> <figcaption> <div class="gallery-group-name">MC</div> <p>在Rikkaの六花服务器里留下的足迹</p> <a href='/gallery/MC/'></a> </figcaption> </figure> <figure class="gallery-group"> <img class="gallery-group-img no-lightbox" src='https://cdn.cbd.int/[email protected]/image/20200907110508327.png' alt="Group Image Gallery"> <figcaption> <div class="gallery-group-name">Gundam</div> <p>哦咧哇gundam哒!</p> <a href='/gallery/Gundam/'></a> </figcaption> </figure> <figure class="gallery-group"> <img class="gallery-group-img no-lightbox" src='https://cdn.cbd.int/[email protected]/image/20200907113116651.png' alt="Group Image Gallery"> <figcaption> <div class="gallery-group-name">I-am-Akilar</div> <p>某种意义上也算自拍吧</p> <a href='/gallery/I-am-Akilar/'></a> </figcaption> </figure></div>2.gallery 相册<div class="fj-gallery"><p><img src="https://i.loli.net/2019/12/25/Fze9jchtnyJXMHN.jpg" alt=""><br><img src="https://i.loli.net/2019/12/25/ryLVePaqkYm4TEK.jpg" alt=""></p> </div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-20-折叠框-folding">2.20 折叠框 folding</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-2">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-3">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><p>1.gallerygroup 相册图库</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">{% folding 参数(可选), 标题 %}</span><br><span class="line"></span><br><span class="line">{% endfolding %}</span><br></pre></td></tr></table></figure><!-- tab 参数配置 --><ol><li><p><code>颜色</code>:blue, cyan, green, yellow, red</p></li><li><p><code>状态</code>:状态填写 open 代表默认打开。</p></li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">{% folding 查看图片测试 %}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">{% endfolding %}</span><br><span class="line"></span><br><span class="line">{% folding cyan open, 查看默认打开的折叠框 %}</span><br><span class="line"></span><br><span class="line">这是一个默认打开的折叠框。</span><br><span class="line"></span><br><span class="line">{% endfolding %}</span><br><span class="line"></span><br><span class="line">{% folding green, 查看代码测试 %}</span><br><span class="line">假装这里有代码块(代码块没法嵌套代码块)</span><br><span class="line">{% endfolding %}</span><br><span class="line"></span><br><span class="line">{% folding yellow, 查看列表测试 %}</span><br><span class="line"></span><br><span class="line"><span class="bullet">-</span> haha</span><br><span class="line"><span class="bullet">-</span> hehe</span><br><span class="line"></span><br><span class="line">{% endfolding %}</span><br><span class="line"></span><br><span class="line">{% folding red, 查看嵌套测试 %}</span><br><span class="line"></span><br><span class="line">{% folding blue, 查看嵌套测试2 %}</span><br><span class="line"></span><br><span class="line">{% folding 查看嵌套测试3 %}</span><br><span class="line"></span><br><span class="line">hahaha <span class="language-xml"><span class="tag"><<span class="name">span</span>></span></span><span class="language-xml"><span class="tag"><<span class="name">img</span> <span class="attr">src</span>=<span class="string">'https://cdn.jsdelivr.net/gh/volantis-x/cdn-emoji/tieba/%E6%BB%91%E7%A8%BD.png'</span> <span class="attr">style</span>=<span class="string">'height:24px'</span>></span></span><span class="language-xml"><span class="tag"></<span class="name">span</span>></span></span></span><br><span class="line"></span><br><span class="line">{% endfolding %}</span><br><span class="line"></span><br><span class="line">{% endfolding %}</span><br><span class="line"></span><br><span class="line">{% endfolding %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><details class="folding-tag" ><summary> 查看图片测试 </summary> <div class='content'> <p><img src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper/abstract/41F215B9-261F-48B4-80B5-4E86E165259E.jpeg" alt=""></p> </div> </details><details class="folding-tag" cyan open><summary> 查看默认打开的折叠框 </summary> <div class='content'> <p>这是一个默认打开的折叠框。</p> </div> </details><details class="folding-tag" green><summary> 查看代码测试 </summary> <div class='content'> <p>假装这里有代码块(代码块没法嵌套代码块)</p> </div> </details><details class="folding-tag" yellow><summary> 查看列表测试 </summary> <div class='content'> <ul><li>haha</li><li>hehe</li></ul> </div> </details><details class="folding-tag" red><summary> 查看嵌套测试 </summary> <div class='content'> <details class="folding-tag" blue><summary> 查看嵌套测试2 </summary> <div class='content'> <details class="folding-tag" ><summary> 查看嵌套测试3 </summary> <div class='content'> <p>hahaha <span><img src='https://cdn.jsdelivr.net/gh/volantis-x/cdn-emoji/tieba/%E6%BB%91%E7%A8%BD.png' style='height:24px'></span></p> </div> </details> </div> </details> </div> </details><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-21-分栏-tab">2.21 分栏 tab</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-2">配置参数</button></li><li class="tab"><button type="button" data-href="#分栏-3">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">{% tabs Unique name, [index] %}</span><br><span class="line"><!-- tab [Tab caption] [@icon] --></span><br><span class="line">Any content (support inline tags too).</span><br><span class="line"><!-- endtab --></span><br><span class="line">{% endtabs %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><ol><li><p>Unique name :</p><ul><li><p>选项卡块标签的唯一名称,不带逗号。</p></li><li><p>将在#id中用作每个标签及其索引号的前缀。</p></li><li><p>如果名称中包含空格,则对于生成#id,所有空格将由破折号代替。</p></li><li><p>仅当前帖子/页面的URL必须是唯一的!</p></li></ul></li><li><p>[index]:</p><ul><li><p>活动选项卡的索引号。</p></li><li><p>如果未指定,将选择第一个标签(1)。</p></li><li><p>如果index为-1,则不会选择任何选项卡。</p></li><li><p>可选参数。</p></li></ul></li><li><p>[Tab caption]:</p><ul><li><p>当前选项卡的标题。</p></li><li><p>如果未指定标题,则带有制表符索引后缀的唯一名称将用作制表符的标题。</p></li><li><p>如果未指定标题,但指定了图标,则标题将为空。</p></li><li><p>可选参数。</p></li></ul></li><li><p>[@icon]:</p><ul><li><p>FontAwesome图标名称(全名,看起来像“ fas fa-font”)</p></li><li><p>可以指定带空格或不带空格;</p></li><li><p>例如’Tab caption @icon’ 和 ‘Tab caption@icon’.</p></li><li><p>可选参数。</p></li></ul></li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><p>1.Demo 1 - 预设选择第一个【默认】</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">{% tabs test1 %}</span><br><span class="line"><!-- tab --></span><br><span class="line"><span class="strong">**This is Tab 1.**</span></span><br><span class="line"><!-- endtab --></span><br><span class="line"></span><br><span class="line"><!-- tab --></span><br><span class="line"><span class="strong">**This is Tab 2.**</span></span><br><span class="line"><!-- endtab --></span><br><span class="line"></span><br><span class="line"><!-- tab --></span><br><span class="line"><span class="strong">**This is Tab 3.**</span></span><br><span class="line"><!-- endtab --></span><br><span class="line">{% endtabs %}</span><br></pre></td></tr></table></figure><p>2.Demo 2 - 预设选择tabs</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">{% tabs test2, 3 %}</span><br><span class="line"><!-- tab --></span><br><span class="line"><span class="strong">**This is Tab 1.**</span></span><br><span class="line"><!-- endtab --></span><br><span class="line"></span><br><span class="line"><!-- tab --></span><br><span class="line"><span class="strong">**This is Tab 2.**</span></span><br><span class="line"><!-- endtab --></span><br><span class="line"></span><br><span class="line"><!-- tab --></span><br><span class="line"><span class="strong">**This is Tab 3.**</span></span><br><span class="line"><!-- endtab --></span><br><span class="line">{% endtabs %}</span><br></pre></td></tr></table></figure><p>3.Demo 3 - 没有预设值</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">{% tabs test3, -1 %}</span><br><span class="line"><!-- tab --></span><br><span class="line"><span class="strong">**This is Tab 1.**</span></span><br><span class="line"><!-- endtab --></span><br><span class="line"></span><br><span class="line"><!-- tab --></span><br><span class="line"><span class="strong">**This is Tab 2.**</span></span><br><span class="line"><!-- endtab --></span><br><span class="line"></span><br><span class="line"><!-- tab --></span><br><span class="line"><span class="strong">**This is Tab 3.**</span></span><br><span class="line"><!-- endtab --></span><br><span class="line">{% endtabs %}</span><br></pre></td></tr></table></figure><p>4.Demo 4 - 自定义Tab名 + 只有icon + icon和Tab名</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">{% tabs test4 %}</span><br><span class="line"><!-- tab 第一个Tab --></span><br><span class="line"><span class="strong">**tab名字为第一个Tab**</span></span><br><span class="line"><!-- endtab --></span><br><span class="line"></span><br><span class="line"><!-- tab @fab fa-apple-pay --></span><br><span class="line"><span class="strong">**只有图标 没有Tab名字**</span></span><br><span class="line"><!-- endtab --></span><br><span class="line"></span><br><span class="line"><!-- tab 炸弹@fas fa-bomb --></span><br><span class="line"><span class="strong">**名字+icon**</span></span><br><span class="line"><!-- endtab --></span><br><span class="line">{% endtabs %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-4"><p>1.Demo 1 - 预设选择第一个【默认】</p><div class="tabs" id="test1"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#test1-1">test1 1</button></li><li class="tab"><button type="button" data-href="#test1-2">test1 2</button></li><li class="tab"><button type="button" data-href="#test1-3">test1 3</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="test1-1"><p><strong>This is Tab 1.</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="test1-2"><p><strong>This is Tab 2.</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="test1-3"><p><strong>This is Tab 3.</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><p>2.Demo 2 - 预设选择tabs</p><div class="tabs" id="test2"><ul class="nav-tabs"><li class="tab"><button type="button" data-href="#test2-1">test2 1</button></li><li class="tab"><button type="button" data-href="#test2-2">test2 2</button></li><li class="tab active"><button type="button" data-href="#test2-3">test2 3</button></li></ul><div class="tab-contents"><div class="tab-item-content" id="test2-1"><p><strong>This is Tab 1.</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="test2-2"><p><strong>This is Tab 2.</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content active" id="test2-3"><p><strong>This is Tab 3.</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><p>3.Demo 3 - 没有预设值</p><div class="tabs" id="test3"><ul class="nav-tabs"><li class="tab"><button type="button" data-href="#test3-1">test3 1</button></li><li class="tab"><button type="button" data-href="#test3-2">test3 2</button></li><li class="tab"><button type="button" data-href="#test3-3">test3 3</button></li></ul><div class="tab-contents"><div class="tab-item-content" id="test3-1"><p><strong>This is Tab 1.</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="test3-2"><p><strong>This is Tab 2.</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="test3-3"><p><strong>This is Tab 3.</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><p>4.Demo 4 - 自定义Tab名 + 只有icon + icon和Tab名</p><div class="tabs" id="test4"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#test4-1">第一个Tab</button></li><li class="tab"><button type="button" data-href="#test4-2"><i class="fab fa-apple-pay" style="text-align: center;"></i></button></li><li class="tab"><button type="button" data-href="#test4-3"><i class="fas fa-bomb"></i>炸弹</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="test4-1"><p><strong>tab名字为第一个Tab</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="test4-2"><p><strong>只有图标 没有Tab名字</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="test4-3"><p><strong>名字+icon</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-22-诗词标签-poem">2.22 诗词标签 poem</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">参数配置</button></li><li class="tab"><button type="button" data-href="#分栏-2">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-3">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><ol><li><code>title</code>:诗词标题</li><li><code>author</code>:作者,可以不写</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">{% poem 水调歌头,苏轼 %}</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><br><span class="line">转朱阁,低绮户,照无眠。</span><br><span class="line">不应有恨,何事长向别时圆?</span><br><span class="line">人有悲欢离合,月有阴晴圆缺,此事古难全。</span><br><span class="line">但愿人长久,千里共婵娟。</span><br><span class="line">{% endpoem %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><div class='poem'><div class='poem-title'>水调歌头</div><div class='poem-author'>苏轼</div><p>丙辰中秋,欢饮达旦,大醉,作此篇,兼怀子由。<br>明月几时有?把酒问青天。<br>不知天上宫阙,今夕是何年?<br>我欲乘风归去,又恐琼楼玉宇,高处不胜寒。<br>起舞弄清影,何似在人间?</p><p>转朱阁,低绮户,照无眠。<br>不应有恨,何事长向别时圆?<br>人有悲欢离合,月有阴晴圆缺,此事古难全。<br>但愿人长久,千里共婵娟。</p></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-23-阿里图标-icon">2.23 阿里图标 icon</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-2">参数配置</button></li><li class="tab"><button type="button" data-href="#分栏-3">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% icon [icon-xxxx],[font-size] %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><ol><li><code>icon-xxxx</code>:表示图标<code>font-class</code>,可以在自己的阿里矢量图标库项目的<code>font-class</code>引用方案内查询并复制。</li><li><code>font-size</code>:表示图标大小,直接填写数字即可,单位为<code>em</code>。图标大小默认值为<code>1em</code>。</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">{% icon icon-rat<span class="emphasis">_zi %}{% icon icon-rat,2 %}</span></span><br><span class="line"><span class="emphasis"></span></span><br><span class="line"><span class="emphasis">{% icon icon-ox_</span>chou,3 %}{% icon icon-ox,4 %}</span><br><span class="line"></span><br><span class="line">{% icon icon-tiger<span class="emphasis">_yin,5 %}{% icon icon-tiger,6 %}</span></span><br><span class="line"><span class="emphasis"></span></span><br><span class="line"><span class="emphasis">{% icon icon-rabbit_</span>mao,1 %}{% icon icon-rabbit,2 %}</span><br><span class="line"></span><br><span class="line">{% icon icon-dragon<span class="emphasis">_chen,3 %}{% icon icon-dragon,4 %}</span></span><br><span class="line"><span class="emphasis"></span></span><br><span class="line"><span class="emphasis">{% icon icon-snake_</span>si,5 %}{% icon icon-snake,6 %}</span><br><span class="line"></span><br><span class="line">{% icon icon-horse<span class="emphasis">_wu %}{% icon icon-horse,2 %}</span></span><br><span class="line"><span class="emphasis"></span></span><br><span class="line"><span class="emphasis">{% icon icon-goat_</span>wei,3 %}{% icon icon-goat,4 %}</span><br><span class="line"></span><br><span class="line">{% icon icon-monkey<span class="emphasis">_shen,5 %}{% icon icon-monkey,6 %}</span></span><br><span class="line"><span class="emphasis"></span></span><br><span class="line"><span class="emphasis">{% icon icon-rooster_</span>you %}{% icon icon-rooster,2 %}</span><br><span class="line"></span><br><span class="line">{% icon icon-dog<span class="emphasis">_xu,3 %}{% icon icon-dog,4 %}</span></span><br><span class="line"><span class="emphasis"></span></span><br><span class="line"><span class="emphasis">{% icon icon-boar_</span>hai,5 %}{% icon icon-boar,6 %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-4"><p><svg class="icon" style="width:1em; height:1em" aria-hidden="true"><use xlink:href="#icon-rat_zi"></use></svg><svg class="icon" style="width:2em; height:2em" aria-hidden="true"><use xlink:href="#icon-rat"></use></svg></p><p><svg class="icon" style="width:3em; height:3em" aria-hidden="true"><use xlink:href="#icon-ox_chou"></use></svg><svg class="icon" style="width:4em; height:4em" aria-hidden="true"><use xlink:href="#icon-ox"></use></svg></p><p><svg class="icon" style="width:5em; height:5em" aria-hidden="true"><use xlink:href="#icon-tiger_yin"></use></svg><svg class="icon" style="width:6em; height:6em" aria-hidden="true"><use xlink:href="#icon-tiger"></use></svg></p><p><svg class="icon" style="width:1em; height:1em" aria-hidden="true"><use xlink:href="#icon-rabbit_mao"></use></svg><svg class="icon" style="width:2em; height:2em" aria-hidden="true"><use xlink:href="#icon-rabbit"></use></svg></p><p><svg class="icon" style="width:3em; height:3em" aria-hidden="true"><use xlink:href="#icon-dragon_chen"></use></svg><svg class="icon" style="width:4em; height:4em" aria-hidden="true"><use xlink:href="#icon-dragon"></use></svg></p><p><svg class="icon" style="width:5em; height:5em" aria-hidden="true"><use xlink:href="#icon-snake_si"></use></svg><svg class="icon" style="width:6em; height:6em" aria-hidden="true"><use xlink:href="#icon-snake"></use></svg></p><p><svg class="icon" style="width:1em; height:1em" aria-hidden="true"><use xlink:href="#icon-horse_wu"></use></svg><svg class="icon" style="width:2em; height:2em" aria-hidden="true"><use xlink:href="#icon-horse"></use></svg></p><p><svg class="icon" style="width:3em; height:3em" aria-hidden="true"><use xlink:href="#icon-goat_wei"></use></svg><svg class="icon" style="width:4em; height:4em" aria-hidden="true"><use xlink:href="#icon-goat"></use></svg></p><p><svg class="icon" style="width:5em; height:5em" aria-hidden="true"><use xlink:href="#icon-monkey_shen"></use></svg><svg class="icon" style="width:6em; height:6em" aria-hidden="true"><use xlink:href="#icon-monkey"></use></svg></p><p><svg class="icon" style="width:1em; height:1em" aria-hidden="true"><use xlink:href="#icon-rooster_you"></use></svg><svg class="icon" style="width:2em; height:2em" aria-hidden="true"><use xlink:href="#icon-rooster"></use></svg></p><p><svg class="icon" style="width:3em; height:3em" aria-hidden="true"><use xlink:href="#icon-dog_xu"></use></svg><svg class="icon" style="width:4em; height:4em" aria-hidden="true"><use xlink:href="#icon-dog"></use></svg></p><p><svg class="icon" style="width:5em; height:5em" aria-hidden="true"><use xlink:href="#icon-boar_hai"></use></svg><svg class="icon" style="width:6em; height:6em" aria-hidden="true"><use xlink:href="#icon-boar"></use></svg></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-24-特效标签wow">2.24 特效标签wow</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-2">渲染演示</button></li><li class="tab"><button type="button" data-href="#分栏-3">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">{% wow [animete],[duration],[delay],[offset],[iteration] %}</span><br><span class="line">内容</span><br><span class="line">{% endwow %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><ol><li><code>animate</code>: 动画样式,效果详见<a href="https://animate.style/">animate.css参考文档</a></li><li><code>duration</code>: 选填项,动画持续时间,单位可以是<code>ms</code>也可以是<code>s</code>。例如<code>3s</code>,<code>700ms</code>。</li><li><code>delay</code>: 选填项,动画开始的延迟时间,单位可以是<code>ms</code>也可以是<code>s</code>。例如<code>3s</code>,<code>700ms</code>。</li><li><code>offset</code>: 选填项,开始动画的距离(相对浏览器底部)</li><li><code>iteration</code>: 选填项,动画重复的次数</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><p>1.flip动画效果。</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">{% wow animate<span class="strong">__zoomIn,5s,5s,100,10 %}</span></span><br><span class="line"><span class="strong">{% note blue 'fas fa-bullhorn' modern%}</span></span><br><span class="line"><span class="strong">`zoomIn`动画效果,持续`5s`,延时`5s`,离底部`100`距离时启动,重复`10`次</span></span><br><span class="line"><span class="strong">{% endnote %}</span></span><br><span class="line"><span class="strong">{% endwow %}</span></span><br></pre></td></tr></table></figure><p>2.zoomIn动画效果,持续5s,延时5s,离底部100距离时启动,重复10次</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">{% wow animate<span class="strong">__zoomIn,5s,5s,100,10 %}</span></span><br><span class="line"><span class="strong">{% note blue 'fas fa-bullhorn' modern%}</span></span><br><span class="line"><span class="strong">`zoomIn`动画效果,持续`5s`,延时`5s`,离底部`100`距离时启动,重复`10`次</span></span><br><span class="line"><span class="strong">{% endnote %}</span></span><br><span class="line"><span class="strong">{% endwow %}</span></span><br></pre></td></tr></table></figure><p>3.slideInRight动画效果,持续5s,延时5s</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">{% wow animate<span class="strong">__slideInRight,5s,5s %}</span></span><br><span class="line"><span class="strong">{% note orange 'fas fa-car' modern%}</span></span><br><span class="line"><span class="strong">`slideInRight`动画效果,持续`5s`,延时`5s`。</span></span><br><span class="line"><span class="strong">{% endnote %}</span></span><br><span class="line"><span class="strong">{% endwow %}</span></span><br></pre></td></tr></table></figure><p>4.heartBeat动画效果,延时5s,重复10次。此处注意不用的参数位置要留空,用逗号间隔。</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">{% wow animate<span class="strong">__heartBeat,,5s,,10 %}</span></span><br><span class="line"><span class="strong">{% note red 'fas fa-battery-half' modern%}</span></span><br><span class="line"><span class="strong">`heartBeat`动画效果,延时`5s`,重复`10`次。</span></span><br><span class="line"><span class="strong">{% endnote %}</span></span><br><span class="line"><span class="strong">{% endwow %}</span></span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-4"><p>1.flip动画效果。</p><div class='wow animate__zoomIn' data-wow-duration='5s' data-wow-delay='5s' data-wow-offset='100' data-wow-iteration='10' ><div class="note blue icon-padding modern"><i class="note-icon fas fa-bullhorn"></i><p><code>zoomIn</code>动画效果,持续<code>5s</code>,延时<code>5s</code>,离底部<code>100</code>距离时启动,重复<code>10</code>次</p></div></div><p>2.zoomIn动画效果,持续5s,延时5s,离底部100距离时启动,重复10次</p><div class='wow animate__zoomIn' data-wow-duration='5s' data-wow-delay='5s' data-wow-offset='100' data-wow-iteration='10' ><div class="note blue icon-padding modern"><i class="note-icon fas fa-bullhorn"></i><p><code>zoomIn</code>动画效果,持续<code>5s</code>,延时<code>5s</code>,离底部<code>100</code>距离时启动,重复<code>10</code>次</p></div></div><p>3.slideInRight动画效果,持续5s,延时5s</p><div class='wow animate__slideInRight' data-wow-duration='5s' data-wow-delay='5s' data-wow-offset='' data-wow-iteration='' ><div class="note orange icon-padding modern"><i class="note-icon fas fa-car"></i><p><code>slideInRight</code>动画效果,持续<code>5s</code>,延时<code>5s</code>。</p></div></div><p>4.heartBeat动画效果,延时5s,重复10次。此处注意不用的参数位置要留空,用逗号间隔。</p><div class='wow animate__heartBeat' data-wow-duration='' data-wow-delay='5s' data-wow-offset='' data-wow-iteration='10' ><div class="note red icon-padding modern"><i class="note-icon fas fa-battery-half"></i><p><code>heartBeat</code>动画效果,延时<code>5s</code>,重复<code>10</code>次。</p></div></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-25-进度条-progress">2.25 进度条 progress</h2><div class="note info flat"><p>进度条标签参考<a href="https://rongbuqiu.com/jdt.html">沂佰孜猫-给HEXO文章添加彩色进度条</a>。<br>源样式提取自<a href="https://zwying0814.gitbook.io/cuteen/">Cuteen</a>主题。</p></div><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">参数配置</button></li><li class="tab"><button type="button" data-href="#分栏-2">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-3">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% progress [width] [color] [text] %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><ol><li><code>width</code>: 0到100的阿拉伯数字</li><li><code>color</code>: 颜色,取值有red,yellow,green,cyan,blue,gray</li><li><code>text</code>:进度条上的文字内容</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">{% progress 10 red 进度条样式预览 %}</span><br><span class="line">{% progress 30 yellow 进度条样式预览 %}</span><br><span class="line">{% progress 50 green 进度条样式预览 %}</span><br><span class="line">{% progress 70 cyan 进度条样式预览 %}</span><br><span class="line">{% progress 90 blue 进度条样式预览 %}</span><br><span class="line">{% progress 100 gray 进度条样式预览 %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-4"><div class="progress"><div class="progress-bar-animated progress-bar progress-bar-striped bg-red" style="width: 10%" aria-valuenow="10" aria-valuemin="0" aria-valuemax="100"><p>进度条样式预览</p></div></div><div class="progress"><div class="progress-bar-animated progress-bar progress-bar-striped bg-yellow" style="width: 30%" aria-valuenow="30" aria-valuemin="0" aria-valuemax="100"><p>进度条样式预览</p></div></div><div class="progress"><div class="progress-bar-animated progress-bar progress-bar-striped bg-green" style="width: 50%" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100"><p>进度条样式预览</p></div></div><div class="progress"><div class="progress-bar-animated progress-bar progress-bar-striped bg-cyan" style="width: 70%" aria-valuenow="70" aria-valuemin="0" aria-valuemax="100"><p>进度条样式预览</p></div></div><div class="progress"><div class="progress-bar-animated progress-bar progress-bar-striped bg-blue" style="width: 90%" aria-valuenow="90" aria-valuemin="0" aria-valuemax="100"><p>进度条样式预览</p></div></div><div class="progress"><div class="progress-bar-animated progress-bar progress-bar-striped bg-gray" style="width: 100%" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"><p>进度条样式预览</p></div></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-26-注释-notation">2.26 注释 notation</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-2">参数配置</button></li><li class="tab"><button type="button" data-href="#分栏-3">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% nota [label] , [text] %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><ol><li><p><code>label</code>: 注释词汇</p></li><li><p><code>text</code>: 悬停显示的注解内容</p></li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% nota 把鼠标移动到我上面试试 ,可以看到注解内容出现在顶栏 %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-4"><p><span class='nota' data-nota='可以看到注解内容出现在顶栏'>把鼠标移动到我上面试试</span></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-27-气泡注释-bubble">2.27 气泡注释 bubble</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-2">参数配置</button></li><li class="tab"><button type="button" data-href="#分栏-3">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% bubble [content] , [notation] ,[background-color] %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><ol><li><code>content</code>: 注释词汇</li><li><code>notation</code>: 悬停显示的注解内容</li><li><code>background-color</code>: 可选,气泡背景色。默认为“#71a4e3”</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">最近我学到了不少新玩意儿(虽然对很多大佬来说这些已经是旧技术了),比如CSS的{% bubble 兄弟相邻选择器,"例如 h1 + p {margin-top:50px;}" %},{% bubble flex布局,"Flex 是 Flexible Box 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性","#ec5830" %},{% bubble transform变换,"transform 属性向元素应用 2D 或 3D 转换。该属性允许我们对元素进行旋转、缩放、移动或倾斜。","#1db675" %},animation的{% bubble 贝塞尔速度曲线,"贝塞尔曲线(Bézier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线。一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋","#de4489" %}写法,还有今天刚看到的{% bubble clip-path,"clip-path属性使用裁剪方式创建元素的可显示区域。区域内的部分显示,区域外的隐藏。","#868fd7" %}属性。这些对我来说很新颖的概念狠狠的冲击着我以前积累起来的设计思路。</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-4"><p>最近我学到了不少新玩意儿(虽然对很多大佬来说这些已经是旧技术了),比如CSS的<span class="bubble-content">兄弟相邻选择器</span><span class="bubble-notation"><span class="bubble-item" style="background-color:#71a4e3;">例如 h1 + p {margin-top:50px;}</span></span>,<span class="bubble-content">flex布局</span><span class="bubble-notation"><span class="bubble-item" style="background-color:#ec5830;">Flex 是 Flexible Box 的缩写,意为弹性布局",用来为盒状模型提供最大的灵活性"</span></span>,<span class="bubble-content">transform变换</span><span class="bubble-notation"><span class="bubble-item" style="background-color:#1db675;">transform 属性向元素应用 2D 或 3D 转换。该属性允许我们对元素进行旋转、缩放、移动或倾斜。</span></span>,animation的<span class="bubble-content">贝塞尔速度曲线</span><span class="bubble-notation"><span class="bubble-item" style="background-color:#de4489;">贝塞尔曲线(Bézier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线。一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋</span></span>写法,还有今天刚看到的<span class="bubble-content">clip-path</span><span class="bubble-notation"><span class="bubble-item" style="background-color:#868fd7;">clip-path属性使用裁剪方式创建元素的可显示区域。区域内的部分显示,区域外的隐藏。</span></span>属性。这些对我来说很新颖的概念狠狠的冲击着我以前积累起来的设计思路。</p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-28-引用文献-reference">2.28 引用文献 reference</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-2">参数配置</button></li><li class="tab"><button type="button" data-href="#分栏-3">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">{% referto [id] , [literature] %}</span><br><span class="line">{% referfrom [id] , [literature] , [url] %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><ol><li><p>referto 引用上标</p><ul><li><p><code>id</code>: 上标序号内容,需与referfrom标签的id对应才能实现跳转</p></li><li><p><code>literature</code>: 引用的参考文献名称</p></li></ul></li><li><p>referfrom 引用出处</p><ul><li><p><code>id</code>: 序号内容,需与referto标签的id对应才能实现 跳转</p></li><li><p><code>literature</code>: 引用的参考文献名称</p></li><li><p><code>url</code>: 引用的参考文献链接,可省略</p></li></ul></li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">Akilarの糖果屋(akilar.top)是一个私人性质的博客{% referto '[1]','Akilarの糖果屋群聊简介' %},从各类教程至生活点滴,无话不谈。建群的目的是提供一个闲聊的场所。博客采用Hexo框架{% referto '[2]','Hexo中文文档' %},Butterfly主题{% referto '[3]','Butterfly 安装文档(一) 快速开始' %}</span><br><span class="line"></span><br><span class="line">本项目参考了Volantis{% referto '[4]','hexo-theme-volantis 标签插件' %}的标签样式。引入<span class="code">`[tag].js`</span>,并针对<span class="code">`butterfly`</span>主题修改了相应的<span class="code">`[tag].styl`</span>。在此鸣谢<span class="code">`Volantis`</span>主题众开发者。</span><br><span class="line">主要参考内容包括各个volantis的内置标签插件文档{% referto '[5]','Volantis文档:内置标签插件' %}</span><br><span class="line">Butterfly主题的各个衍生魔改{% referto '[6]','Butterfly 安装文档:标签外挂(Tag Plugins' %}{% referto '[7]','小弋の生活馆全样式预览' %}{% referto '[8]','l-lin-font-awesome-animation' %}{% referto '[9]','小康的butterfly主题使用文档' %}</span><br><span class="line"></span><br><span class="line">{% referfrom '[1]','Akilarの糖果屋群聊简介','https://jq.qq.com/?<span class="emphasis">_wv=1027&k=pGLB2C0N' %}</span></span><br><span class="line"><span class="emphasis">{% referfrom '[2]','Hexo中文文档','https://hexo.io/zh-cn/docs/' %}</span></span><br><span class="line"><span class="emphasis">{% referfrom '[3]','Butterfly 安装文档(一) 快速开始','https://butterfly.js.org/posts/21cfbf15/' %}</span></span><br><span class="line"><span class="emphasis">{% referfrom '[4]','hexo-theme-volantis 标签插件','https://volantis.js.org/v5/tag-plugins/' %}</span></span><br><span class="line"><span class="emphasis">{% referfrom '[5]','Volantis文档:内置标签插件','https://volantis.js.org/tag-plugins/' %}</span></span><br><span class="line"><span class="emphasis">{% referfrom '[6]','Butterfly 安装文档:标签外挂(Tag Plugins','https://butterfly.js.org/posts/4aa8abbe/#%E6%A8%99%E7%B1%A4%E5%A4%96%E6%8E%9B%EF%BC%88Tag-Plugins%EF%BC%89' %}</span></span><br><span class="line"><span class="emphasis">{% referfrom '[7]','小弋の生活馆全样式预览','https://lovelijunyi.gitee.io/posts/c898.html' %}</span></span><br><span class="line"><span class="emphasis">{% referfrom '[8]','l-lin-font-awesome-animation','https://github.com/l-lin/font-awesome-animation' %}</span></span><br><span class="line"><span class="emphasis">{% referfrom '[9]','小康的butterfly主题使用文档','https://www.antmoe.com/posts/3b43914f/' %}</span></span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-4"><p>Akilarの糖果屋(akilar.top)是一个私人性质的博客<span class="hidden-anchor" id="referto_[1]"></span><sup class="reference"><a href="#referfrom_[1]">[1]</a></sup><span class="reference-bubble"><span class="reference-item"><span class="reference-literature">Akilarの糖果屋群聊简介</span><span class="reference-title">参考资料</span></span></span>,从各类教程至生活点滴,无话不谈。建群的目的是提供一个闲聊的场所。博客采用Hexo框架<span class="hidden-anchor" id="referto_[2]"></span><sup class="reference"><a href="#referfrom_[2]">[2]</a></sup><span class="reference-bubble"><span class="reference-item"><span class="reference-literature">Hexo中文文档</span><span class="reference-title">参考资料</span></span></span>,Butterfly主题<span class="hidden-anchor" id="referto_[3]"></span><sup class="reference"><a href="#referfrom_[3]">[3]</a></sup><span class="reference-bubble"><span class="reference-item"><span class="reference-literature">Butterfly 安装文档(一) 快速开始</span><span class="reference-title">参考资料</span></span></span></p><p>本项目参考了Volantis<span class="hidden-anchor" id="referto_[4]"></span><sup class="reference"><a href="#referfrom_[4]">[4]</a></sup><span class="reference-bubble"><span class="reference-item"><span class="reference-literature">hexo-theme-volantis 标签插件</span><span class="reference-title">参考资料</span></span></span>的标签样式。引入<code>[tag].js</code>,并针对<code>butterfly</code>主题修改了相应的<code>[tag].styl</code>。在此鸣谢<code>Volantis</code>主题众开发者。<br>主要参考内容包括各个volantis的内置标签插件文档<span class="hidden-anchor" id="referto_[5]"></span><sup class="reference"><a href="#referfrom_[5]">[5]</a></sup><span class="reference-bubble"><span class="reference-item"><span class="reference-literature">Volantis文档:内置标签插件</span><span class="reference-title">参考资料</span></span></span><br>Butterfly主题的各个衍生魔改<span class="hidden-anchor" id="referto_[6]"></span><sup class="reference"><a href="#referfrom_[6]">[6]</a></sup><span class="reference-bubble"><span class="reference-item"><span class="reference-literature">Butterfly 安装文档:标签外挂(Tag Plugins</span><span class="reference-title">参考资料</span></span></span><span class="hidden-anchor" id="referto_[7]"></span><sup class="reference"><a href="#referfrom_[7]">[7]</a></sup><span class="reference-bubble"><span class="reference-item"><span class="reference-literature">小弋の生活馆全样式预览</span><span class="reference-title">参考资料</span></span></span><span class="hidden-anchor" id="referto_[8]"></span><sup class="reference"><a href="#referfrom_[8]">[8]</a></sup><span class="reference-bubble"><span class="reference-item"><span class="reference-literature">l-lin-font-awesome-animation</span><span class="reference-title">参考资料</span></span></span><span class="hidden-anchor" id="referto_[9]"></span><sup class="reference"><a href="#referfrom_[9]">[9]</a></sup><span class="reference-bubble"><span class="reference-item"><span class="reference-literature">小康的butterfly主题使用文档</span><span class="reference-title">参考资料</span></span></span></p><div class="reference-source"><span class="hidden-anchor" id="referfrom_[1]"></span><a class="reference-anchor" href="#referto_[1]">[1]<div class="reference-anchor-up fa-solid fa-angles-up"></div></a><a class="reference-link" href="https://jq.qq.com/?_wv=1027&k=pGLB2C0N">Akilarの糖果屋群聊简介</a></div><div class="reference-source"><span class="hidden-anchor" id="referfrom_[2]"></span><a class="reference-anchor" href="#referto_[2]">[2]<div class="reference-anchor-up fa-solid fa-angles-up"></div></a><a class="reference-link" href="https://hexo.io/zh-cn/docs/">Hexo中文文档</a></div><div class="reference-source"><span class="hidden-anchor" id="referfrom_[3]"></span><a class="reference-anchor" href="#referto_[3]">[3]<div class="reference-anchor-up fa-solid fa-angles-up"></div></a><a class="reference-link" href="https://butterfly.js.org/posts/21cfbf15/">Butterfly 安装文档(一) 快速开始</a></div><div class="reference-source"><span class="hidden-anchor" id="referfrom_[4]"></span><a class="reference-anchor" href="#referto_[4]">[4]<div class="reference-anchor-up fa-solid fa-angles-up"></div></a><a class="reference-link" href="https://volantis.js.org/v5/tag-plugins/">hexo-theme-volantis 标签插件</a></div><div class="reference-source"><span class="hidden-anchor" id="referfrom_[5]"></span><a class="reference-anchor" href="#referto_[5]">[5]<div class="reference-anchor-up fa-solid fa-angles-up"></div></a><a class="reference-link" href="https://volantis.js.org/tag-plugins/">Volantis文档:内置标签插件</a></div><div class="reference-source"><span class="hidden-anchor" id="referfrom_[6]"></span><a class="reference-anchor" href="#referto_[6]">[6]<div class="reference-anchor-up fa-solid fa-angles-up"></div></a><a class="reference-link" href="https://butterfly.js.org/posts/4aa8abbe/#%E6%A8%99%E7%B1%A4%E5%A4%96%E6%8E%9B%EF%BC%88Tag-Plugins%EF%BC%89">Butterfly 安装文档:标签外挂(Tag Plugins</a></div><div class="reference-source"><span class="hidden-anchor" id="referfrom_[7]"></span><a class="reference-anchor" href="#referto_[7]">[7]<div class="reference-anchor-up fa-solid fa-angles-up"></div></a><a class="reference-link" href="https://lovelijunyi.gitee.io/posts/c898.html">小弋の生活馆全样式预览</a></div><div class="reference-source"><span class="hidden-anchor" id="referfrom_[8]"></span><a class="reference-anchor" href="#referto_[8]">[8]<div class="reference-anchor-up fa-solid fa-angles-up"></div></a><a class="reference-link" href="https://github.com/l-lin/font-awesome-animation">l-lin-font-awesome-animation</a></div><div class="reference-source"><span class="hidden-anchor" id="referfrom_[9]"></span><a class="reference-anchor" href="#referto_[9]">[9]<div class="reference-anchor-up fa-solid fa-angles-up"></div></a><a class="reference-link" href="https://www.antmoe.com/posts/3b43914f/">小康的butterfly主题使用文档</a></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-29-PDF展示">2.29 PDF展示</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-2">参数配置</button></li><li class="tab"><button type="button" data-href="#分栏-3">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% pdf 文件路径 %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><ol><li><code>文件路径</code>: 可以是相对路径或者是在线链接</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="section"># 1.本地文件:在md文件路径下创建一个同名文件夹,其内放pdf文件名为xxx.pdf的文件</span></span><br><span class="line">{% pdf xxx.pdf %}</span><br><span class="line"><span class="section"># 2.在线链接</span></span><br><span class="line">{% pdf https://cdn.jsdelivr.net/gh/Justlovesmile/CDN/pdf/小作文讲义.pdf %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-4"><p>2.在线链接(要放到最外层才能起作用)</p><pre><code><div class="row"><embed src="https://cdn.jsdelivr.net/gh/Justlovesmile/CDN/pdf/小作文讲义.pdf" width="100%" height="550" type="application/pdf"></div></code></pre><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-30-Hexo-tag-map-插件">2.30 Hexo-tag-map 插件</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-2">参数配置</button></li><li class="tab"><button type="button" data-href="#分栏-3">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% + 标签值 + 经度 + 纬度 + 文本 + 缩放等级 + 宽 + 高 + 默认图层 + %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><table><thead><tr><th style="text-align:center">地图名</th><th style="text-align:center">标签值 <必填></th><th style="text-align:center">宽 (默认 100%) / 高 (默认 360px)</th><th style="text-align:center">缩放等级 (默认 14)</th><th style="text-align:center">宽 (默认 100%) / 高 (默认 360px)</th><th style="text-align:center">默认图层 (默认 1)</th></tr></thead><tbody><tr><td style="text-align:center">混合地图</td><td style="text-align:center">map</td><td style="text-align:center">百分数或具体值 (100% 或 360px)</td><td style="text-align:center">取值 3~18</td><td style="text-align:center">百分数或具体值 (100% 或 360px)</td><td style="text-align:center">取值 1~7</td></tr><tr><td style="text-align:center">谷歌地图</td><td style="text-align:center">googleMap</td><td style="text-align:center">百分数或具体值 (100% 或 360px)</td><td style="text-align:center">取值 1~20</td><td style="text-align:center">百分数或具体值 (100% 或 360px)</td><td style="text-align:center">取值 1~3</td></tr><tr><td style="text-align:center">高德地图</td><td style="text-align:center">gaodeMap</td><td style="text-align:center">百分数或具体值 (100% 或 360px)</td><td style="text-align:center">取值 3~18</td><td style="text-align:center">百分数或具体值 (100% 或 360px)</td><td style="text-align:center">取值 1~3</td></tr><tr><td style="text-align:center">百度地图</td><td style="text-align:center">baiduMap</td><td style="text-align:center">百分数或具体值 (100% 或 360px)</td><td style="text-align:center">取值 4~18</td><td style="text-align:center">百分数或具体值 (100% 或 360px)</td><td style="text-align:center">取值 1~2</td></tr><tr><td style="text-align:center">Geoq 地图</td><td style="text-align:center">geoqMap</td><td style="text-align:center">百分数或具体值 (100% 或 360px)</td><td style="text-align:center">取值 1~18</td><td style="text-align:center">百分数或具体值 (100% 或 360px)</td><td style="text-align:center">取值 1~5</td></tr><tr><td style="text-align:center">openstreet 地图</td><td style="text-align:center">openstreetMap</td><td style="text-align:center">百分数或具体值 (100% 或 360px)</td><td style="text-align:center">取值 1~18</td><td style="text-align:center">百分数或具体值 (100% 或 360px)</td><td style="text-align:center">不支持此参数</td></tr></tbody></table><ol><li>参数之间,用英文逗号相隔</li><li>参数必须按上述事例顺序输入,不得为空</li><li>同一个页面,同一组经纬度值,只能插入一个相同标签值的地图 (若有需要,可以将第二个地图上,经度或纬度末尾删除一两个数)</li><li>参数取值必须在上述范围内</li><li>默认图层:即地图叠加层的值,默认常规地图还是卫星地图,可按地图显示顺序取值</li><li>缩放等级,数字越大,地图比例尺越小,显示的越精细</li><li>除标签值外,其他参数选填,但 每个参数的左边的参数必填</li><li>谷歌地图需要外网才能加载查看</li></ol><p>坐标获取:<a href="https://lbs.amap.com/tools/picker">高德地图坐标拾取系统</a> 、<a href="https://api.map.baidu.com/lbsapi/getpoint/index.html">百度地图坐标拾取系统</a></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">{% map 120.101101,30.239119 %}</span><br><span class="line">{% googleMap 120.101101,30.239119, 这里是西湖灵隐寺,据说求姻缘很灵验哦! %}</span><br><span class="line">{% geoqMap 120.101101,30.239119, 这里是西湖灵隐寺,据说求姻缘很灵验哦!, 13, 90%, 320px, 3 %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-4"><link rel="stylesheet" href="//unpkg.com/hexo-tag-map/lib/[email protected]"><script data-pjax src="//unpkg.com/hexo-tag-map/lib/[email protected]"></script><script data-pjax src="//unpkg.com/hexo-tag-map/lib/[email protected]"></script><div class="map-box" style="margin: 0.8rem 0 1.6rem 0;"><div id="map-120.101101-30.239119" style="max-width:100%; height:360px;display: block;margin:0 auto;z-index:1;border-radius: 5px;"></div></div><script type="text/javascript">var normalm=L.tileLayer.chinaProvider('GaoDe.Normal.Map',{maxZoom:20,minZoom:1,attribution:'高德地图'});var imgm=L.tileLayer.chinaProvider('GaoDe.Satellite.Map',{maxZoom:20,minZoom:1,attribution:'高德地图'});var imga=L.tileLayer.chinaProvider('GaoDe.Satellite.Annotion',{maxZoom:20,minZoom:1,attribution:'高德地图'});var normalMap=L.tileLayer.chinaProvider('Google.Normal.Map',{maxZoom:20,minZoom:1,attribution:'Google Maps'}),satelliteMap=L.tileLayer.chinaProvider('Google.Satellite.Map',{maxZoom:21,minZoom:1,attribution:'Google Maps'});routeMap=L.tileLayer.chinaProvider('Google.Satellite.Annotion',{maxZoom:21,minZoom:1});var normalMap=L.tileLayer.chinaProvider('Google.Normal.Map',{maxZoom:21,minZoom:1,attribution:'Google Maps'}),satelliteMap=L.tileLayer.chinaProvider('Google.Satellite.Map',{maxZoom:21,minZoom:1,attribution:'Google Maps'}),routeMap=L.tileLayer.chinaProvider('Google.Satellite.Annotion',{maxZoom:21,minZoom:1,attribution:'Google Maps'});var normalm1=L.tileLayer.chinaProvider('Geoq.Normal.Map',{maxZoom:21,minZoom:1,attribution:'GeoQ'});var normal=L.layerGroup([normalm]),image=L.layerGroup([imgm,imga]);var baseLayers={"高德地图":normal,"智图地图":normalm1,"谷歌地图":normalMap,"高德卫星地图":imgm,"谷歌卫星地图":satelliteMap,"高德卫星标注":image,"谷歌卫星标注":routeMap};var mymap=L.map('map-120.101101-30.239119',{center:[30.239119,120.101101],zoom:14,layers:[normal],zoomControl:false});L.control.layers(baseLayers,null).addTo(mymap);L.control.zoom({zoomInTitle:'放大',zoomOutTitle:'缩小'}).addTo(mymap);</script><br><link rel="stylesheet" href="//unpkg.com/hexo-tag-map/lib/[email protected]"><script data-pjax src="//unpkg.com/hexo-tag-map/lib/[email protected]"></script><script data-pjax src="//unpkg.com/hexo-tag-map/lib/[email protected]"></script><div id="googleMap-120.101101-30.239119" style="max-width:100%; height:360px;display: block;margin:0 auto;z-index:1;border-radius: 5px;"></div><script type="text/javascript">var normalMap=L.tileLayer.chinaProvider('Google.Normal.Map',{maxZoom:22,minZoom:1,attribution:'Google Maps'}),satelliteMap=L.tileLayer.chinaProvider('Google.Satellite.Map',{maxZoom:22,minZoom:1,attribution:'Google Maps'}),routeMap=L.tileLayer.chinaProvider('Google.Satellite.Annotion',{maxZoom:22,minZoom:1,attribution:'Google Maps'});var baseLayers={"谷歌地图":normalMap,"谷歌卫星图":satelliteMap,"谷歌卫星标注": routeMap};var overlayLayers={};var mymap=L.map("googleMap-120.101101-30.239119",{center:[30.239119,120.101101],zoom:14,layers:[normalMap],zoomControl:false});L.control.layers(baseLayers,null).addTo(mymap);L.control.zoom({zoomInTitle:'放大',zoomOutTitle:'缩小'}).addTo(mymap);var marker = L.marker(['30.239119','120.101101']).addTo(mymap);marker.bindPopup("这里是西湖灵隐寺,据说求姻缘很灵验哦!").openPopup();</script><br><link rel="stylesheet" href="//unpkg.com/hexo-tag-map/lib/[email protected]"><script data-pjax src="//unpkg.com/hexo-tag-map/lib/[email protected]"></script><script data-pjax src="//unpkg.com/hexo-tag-map/lib/[email protected]"></script><div id="geoqMap-120.101101-30.239119" style="max-width:90%; height:320px;display: block;margin:0 auto;z-index:1;border-radius: 5px;"></div><script type="text/javascript">var normalm1=L.tileLayer.chinaProvider('Geoq.Normal.Map',{maxZoom:20,minZoom:1,attribution:'GeoQ'});var normalm2=L.tileLayer.chinaProvider('Geoq.Normal.PurplishBlue',{maxZoom:20,minZoom:1,attribution:'GeoQ'});var normalm3=L.tileLayer.chinaProvider('Geoq.Normal.Gray',{maxZoom:20,minZoom:1,attribution:'GeoQ'});var normalm4=L.tileLayer.chinaProvider('Geoq.Normal.Warm',{maxZoom:20,minZoom:1,attribution:'GeoQ'});var normalm5=L.tileLayer.chinaProvider('Geoq.Theme.Hydro',{maxZoom:20,minZoom:1,attribution:'GeoQ'});var normal=L.layerGroup([normalm1,normalm2,normalm3,normalm4,normalm5]);var baseLayers={"智图地图":normalm1,"午夜蓝":normalm2,"灰色":normalm3,"暖色":normalm4,"水系":normalm5};var mymap=L.map("geoqMap-120.101101-30.239119",{center:[30.239119,120.101101],zoom:13,layers:[normalm3],zoomControl:false});L.control.layers(baseLayers,null).addTo(mymap);L.control.zoom({zoomInTitle:'放大',zoomOutTitle:'缩小'}).addTo(mymap);var marker = L.marker(['30.239119','120.101101']).addTo(mymap);marker.bindPopup("这里是西湖灵隐寺,据说求姻缘很灵验哦!").openPopup();</script><br><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-31-隐藏块">2.31 隐藏块</h2><div class="tabs" id="分栏"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#分栏-1">标签语法</button></li><li class="tab"><button type="button" data-href="#分栏-2">参数配置</button></li><li class="tab"><button type="button" data-href="#分栏-3">示例源码</button></li><li class="tab"><button type="button" data-href="#分栏-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="分栏-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">{% hideBlock display,bg,color %}</span><br><span class="line">content</span><br><span class="line">{% endhideBlock %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-2"><ol><li>content:要隐藏的内容</li><li>display:展示前按钮显示的文字(可选)</li><li>bg:按钮的背景颜色(可选)</li><li>color:按钮显示的文字的颜色(可选)</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">{% hideBlock 点我预览, blue %}</span><br><span class="line">这里有张图片:</span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">img</span> <span class="attr">src</span>=<span class="string">"https://s1.vika.cn/space/2022/10/30/b35fce448bc9404a8d65c3ce1e6e46eb"</span> <span class="attr">alt</span>=<span class="string">"image (1)"</span> <span class="attr">style</span>=<span class="string">"zoom:67%;"</span> /></span></span></span><br><span class="line">{% endhideBlock %}</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="分栏-4"><div class="hide-block"><button type="button" class="hide-button" style="background-color: blue;">点我预览 </button><div class="hide-content"><p>这里有张图片:<br><img src="https://s1.vika.cn/space/2022/10/30/b35fce448bc9404a8d65c3ce1e6e46eb" alt="image (1)" style="zoom:67%;" /></p></div></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div>]]></content>
<categories>
<category> 学习笔记 </category>
</categories>
<tags>
<tag> Markdown </tag>
</tags>
</entry>
<entry>
<title>谈谈Redis</title>
<link href="/posts/2a063794.html"/>
<url>/posts/2a063794.html</url>
<content type="html"><![CDATA[]]></content>
<categories>
<category> 数据库 </category>
</categories>
<tags>
<tag> Redis </tag>
</tags>
</entry>
<entry>
<title>算法</title>
<link href="/posts/b7e144d1.html"/>
<url>/posts/b7e144d1.html</url>
<content type="html"><![CDATA[<h1>算法思维培养</h1><h2 id="算法题收集">算法题收集</h2><p>1.给你一个数组 <code>nums</code> 和一个值 <code>val</code>,你需要 <strong><a href="https://baike.baidu.com/item/%E5%8E%9F%E5%9C%B0%E7%AE%97%E6%B3%95">原地</a></strong> 移除所有数值等于 <code>val</code> 的元素,并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用 <code>O(1)</code> 额外空间并 <strong><a href="https://baike.baidu.com/item/%E5%8E%9F%E5%9C%B0%E7%AE%97%E6%B3%95">原地 </a>修改输入数组</strong>。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//双指针模型</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"> <span class="comment">//private int[] nums = {3,2,2,3};</span></span><br><span class="line"> <span class="comment">//private int val = 3;</span></span><br><span class="line"> <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">removeElement</span><span class="params">(<span class="type">int</span>[] nums, <span class="type">int</span> val)</span> {</span><br><span class="line"> <span class="type">int</span> <span class="variable">left</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"> <span class="type">int</span> <span class="variable">right</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span> (right < nums.length){</span><br><span class="line"> <span class="keyword">if</span> (nums[right] == val) {</span><br><span class="line"> right++;</span><br><span class="line"> <span class="keyword">continue</span>; </span><br><span class="line"> }<span class="keyword">else</span> {</span><br><span class="line"> nums[left] = nums[right];</span><br><span class="line"> left++;</span><br><span class="line"> }</span><br><span class="line"> right++; </span><br><span class="line"> } </span><br><span class="line"> <span class="keyword">return</span> left; </span><br><span class="line"> } </span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> 算法之路 </category>
</categories>
<tags>
<tag> 算法 </tag>
</tags>
</entry>
<entry>
<title>Centos7安装Docker教程</title>
<link href="/posts/d17f223a.html"/>
<url>/posts/d17f223a.html</url>
<content type="html"><![CDATA[<h1>安装Docker</h1><p>Docker 分为 CE 和 EE 两大版本。CE 即社区版(免费,支持周期 7 个月),EE 即企业版,强调安全,付费使用,支持周期 24 个月。</p><p>Docker CE 分为 <code>stable</code> <code>test</code> 和 <code>nightly</code> 三个更新频道。</p><p>官方网站上有各种环境下的 <a href="https://docs.docker.com/install/">安装指南</a>,这里主要介绍 Docker CE 在 CentOS上的安装。</p><h1>1.CentOS安装Docker</h1><p>Docker CE 支持 64 位版本 CentOS 7,并且要求内核版本不低于 3.10, CentOS 7 满足最低内核的要求,所以我们在CentOS 7安装Docker。</p><h2 id="1-1-卸载(可选)">1.1.卸载(可选)</h2><p>如果之前安装过旧版本的Docker,可以使用下面命令卸载:</p><figure class="highlight livescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">yum remove docker <span class="string">\</span></span><br><span class="line"> docker-client <span class="string">\</span></span><br><span class="line"> docker-client-latest <span class="string">\</span></span><br><span class="line"> docker-common <span class="string">\</span></span><br><span class="line"> docker-latest <span class="string">\</span></span><br><span class="line"> docker-latest-logrotate <span class="string">\</span></span><br><span class="line"> docker-logrotate <span class="string">\</span></span><br><span class="line"> docker-selinux <span class="string">\</span></span><br><span class="line"> docker-engine-selinux <span class="string">\</span></span><br><span class="line"> docker-engine <span class="string">\</span></span><br><span class="line"> docker-ce</span><br></pre></td></tr></table></figure><h2 id="1-2-安装docker">1.2.安装docker</h2><p>首先需要大家虚拟机联网,安装yum工具</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">yum install -y yum-utils \</span><br><span class="line"> device-mapper-persistent-data \</span><br><span class="line"> lvm2 --skip-broken</span><br></pre></td></tr></table></figure><p>然后更新本地镜像源:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">设置docker镜像源</span></span><br><span class="line">yum-config-manager \</span><br><span class="line"> --add-repo \</span><br><span class="line"> https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo</span><br><span class="line"> </span><br><span class="line">sed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' /etc/yum.repos.d/docker-ce.repo</span><br><span class="line"></span><br><span class="line">yum makecache fast</span><br></pre></td></tr></table></figure><p>然后输入命令:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yum install -y docker-ce</span><br></pre></td></tr></table></figure><p>docker-ce为社区免费版本。稍等片刻,docker即可安装成功。</p><h2 id="1-3-启动docker">1.3.启动docker</h2><p>Docker应用需要用到各种端口,逐一去修改防火墙设置。非常麻烦,因此建议大家直接关闭防火墙!</p><p>启动docker前,一定要关闭防火墙后!!</p><p>启动docker前,一定要关闭防火墙后!!</p><p>启动docker前,一定要关闭防火墙后!!</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 关闭</span></span><br><span class="line">systemctl stop firewalld</span><br><span class="line"><span class="comment"># 禁止开机启动防火墙</span></span><br><span class="line">systemctl <span class="built_in">disable</span> firewalld</span><br></pre></td></tr></table></figure><p>通过命令启动docker:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">systemctl start docker <span class="comment"># 启动docker服务</span></span><br><span class="line"></span><br><span class="line">systemctl stop docker <span class="comment"># 停止docker服务</span></span><br><span class="line"></span><br><span class="line">systemctl restart docker <span class="comment"># 重启docker服务</span></span><br></pre></td></tr></table></figure><p>然后输入命令,可以查看docker版本:</p><figure class="highlight ebnf"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">docker -v</span></span><br></pre></td></tr></table></figure><p>如图:</p><p><img src="assets/image-20210418154704436.png" alt="image-20210418154704436"></p><h2 id="1-4-配置镜像加速">1.4.配置镜像加速</h2><p>docker官方镜像仓库网速较差,我们需要设置国内镜像服务:</p><p>参考阿里云的镜像加速文档:<a href="https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors">https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors</a></p><h1>2.CentOS7安装DockerCompose</h1><h2 id="2-1-下载">2.1.下载</h2><p>Linux下需要通过命令下载:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 安装</span></span><br><span class="line">curl -L https://github.com/docker/compose/releases/download/1.23.1/docker-compose-`<span class="built_in">uname</span> -s`-`<span class="built_in">uname</span> -m` > /usr/local/bin/docker-compose</span><br></pre></td></tr></table></figure><p>如果下载速度较慢,或者下载失败,可以使用课前资料提供的docker-compose文件:</p><p><img src="assets/image-20210417133020614.png" alt="image-20210417133020614"></p><p>上传到<code>/usr/local/bin/</code>目录也可以。</p><h2 id="2-2-修改文件权限">2.2.修改文件权限</h2><p>修改文件权限:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 修改权限</span></span><br><span class="line"><span class="built_in">chmod</span> +x /usr/local/bin/docker-compose</span><br></pre></td></tr></table></figure><h2 id="2-3-Base自动补全命令:">2.3.Base自动补全命令:</h2><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 补全命令</span></span><br><span class="line">curl -L https://raw.githubusercontent.com/docker/compose/1.29.1/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose</span><br></pre></td></tr></table></figure><p>如果这里出现错误,需要修改自己的hosts文件:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">"199.232.68.133 raw.githubusercontent.com"</span> >> /etc/hosts</span><br></pre></td></tr></table></figure><h1>3.Docker镜像仓库</h1><p>搭建镜像仓库可以基于Docker官方提供的DockerRegistry来实现。</p><p>官网地址:<a href="https://hub.docker.com/_/registry">https://hub.docker.com/_/registry</a></p><h2 id="3-1-简化版镜像仓库">3.1.简化版镜像仓库</h2><p>Docker官方的Docker Registry是一个基础版本的Docker镜像仓库,具备仓库管理的完整功能,但是没有图形化界面。</p><p>搭建方式比较简单,命令如下:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">docker run -d \</span><br><span class="line"> --restart=always \</span><br><span class="line"> --name registry\</span><br><span class="line"> -p 5000:5000 \</span><br><span class="line"> -v registry-data:/var/lib/registry \</span><br><span class="line"> registry</span><br></pre></td></tr></table></figure><p>命令中挂载了一个数据卷registry-data到容器内的/var/lib/registry 目录,这是私有镜像库存放数据的目录。</p><p>访问http://YourIp:5000/v2/_catalog 可以查看当前私有镜像服务中包含的镜像</p><h2 id="3-2-带有图形化界面版本">3.2.带有图形化界面版本</h2><p>使用DockerCompose部署带有图象界面的DockerRegistry,命令如下:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">version:</span> <span class="string">'3.0'</span></span><br><span class="line"><span class="attr">services:</span></span><br><span class="line"> <span class="attr">registry:</span></span><br><span class="line"> <span class="attr">image:</span> <span class="string">registry</span></span><br><span class="line"> <span class="attr">volumes:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">./registry-data:/var/lib/registry</span></span><br><span class="line"> <span class="attr">ui:</span></span><br><span class="line"> <span class="attr">image:</span> <span class="string">joxit/docker-registry-ui:static</span></span><br><span class="line"> <span class="attr">ports:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="number">8080</span><span class="string">:80</span></span><br><span class="line"> <span class="attr">environment:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">REGISTRY_TITLE=传智教育私有仓库</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">REGISTRY_URL=http://registry:5000</span></span><br><span class="line"> <span class="attr">depends_on:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">registry</span></span><br></pre></td></tr></table></figure><h2 id="3-3-配置Docker信任地址">3.3.配置Docker信任地址</h2><p>我们的私服采用的是http协议,默认不被Docker信任,所以需要做一个配置:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 打开要修改的文件</span></span><br><span class="line">vi /etc/docker/daemon.json</span><br><span class="line"><span class="comment"># 添加内容:</span></span><br><span class="line"><span class="string">"insecure-registries"</span>:[<span class="string">"http://192.168.150.101:8080"</span>]</span><br><span class="line"><span class="comment"># 重加载</span></span><br><span class="line">systemctl daemon-reload</span><br><span class="line"><span class="comment"># 重启docker</span></span><br><span class="line">systemctl restart docker</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> 微服务 </category>
</categories>
<tags>
<tag> 微服务 </tag>
<tag> Docker </tag>
</tags>
</entry>
<entry>
<title>Centos7安装Nacos教程</title>
<link href="/posts/4eb76220.html"/>
<url>/posts/4eb76220.html</url>
<content type="html"><![CDATA[<h1>Nacos安装指南</h1><h1>1.Windows安装</h1><p>开发阶段采用单机安装即可。</p><h2 id="1-1-下载安装包">1.1.下载安装包</h2><p>在Nacos的GitHub页面,提供有下载链接,可以下载编译好的Nacos服务端或者源代码:</p><p>GitHub主页:<a href="https://github.com/alibaba/nacos">https://github.com/alibaba/nacos</a></p><p>GitHub的Release下载页:<a href="https://github.com/alibaba/nacos/releases">https://github.com/alibaba/nacos/releases</a></p><p>本课程采用1.4.1.版本的Nacos,课前资料已经准备了安装包:</p><p>windows版本使用<code>nacos-server-1.4.1.zip</code>包即可。</p><h2 id="1-2-解压">1.2.解压</h2><p>将这个包解压到任意非中文目录下,如图:</p><p>目录说明:</p><ul><li>bin:启动脚本</li><li>conf:配置文件</li></ul><h2 id="1-3-端口配置">1.3.端口配置</h2><p>Nacos的默认端口是8848,如果你电脑上的其它进程占用了8848端口,请先尝试关闭该进程。</p><p><strong>如果无法关闭占用8848端口的进程</strong>,也可以进入nacos的conf目录,修改配置文件中的端口:</p><p>记事本打开application.properties文件</p><p>修改其中的内容:</p><p>server.port=8848</p><h2 id="1-4-启动">1.4.启动</h2><p>启动非常简单,进入bin目录</p><p>然后执行命令即可:</p><ul><li><p>windows命令:</p><figure class="highlight dos"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">startup.<span class="built_in">cmd</span> -m standalone</span><br></pre></td></tr></table></figure></li></ul><p>执行后的效果如图:</p><p>出现一大串字符图案</p><h2 id="1-5-访问">1.5.访问</h2><p>在浏览器输入地址:<a href="http://127.0.0.1:8848/nacos%E5%8D%B3%E5%8F%AF%EF%BC%9A">http://127.0.0.1:8848/nacos即可:</a></p><p>默认的账号和密码都是nacos,进入后:</p><h1>2.Linux安装</h1><p>Linux或者Mac安装方式与Windows类似。</p><h2 id="2-1-安装JDK">2.1.安装JDK</h2><p>Nacos依赖于JDK运行,索引Linux上也需要安装JDK才行。</p><p>上传jdk安装包:</p><p>上传到某个目录,例如:<code>/usr/local/</code></p><p>然后解压缩:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tar -xvf jdk-8u144-linux-x64.tar.gz</span><br></pre></td></tr></table></figure><p>然后重命名为java</p><p>配置环境变量:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">export</span> JAVA_HOME=/usr/local/java</span><br><span class="line"><span class="built_in">export</span> PATH=<span class="variable">$PATH</span>:<span class="variable">$JAVA_HOME</span>/bin</span><br></pre></td></tr></table></figure><p>设置环境变量:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">source</span> /etc/profile</span><br></pre></td></tr></table></figure><h2 id="2-2-上传安装包">2.2.上传安装包</h2><p>也可以直接使用课前资料中的tar.gz:</p><p>上传到Linux服务器的某个目录,例如<code>/usr/local/src</code>目录下:</p><h2 id="2-3-解压">2.3.解压</h2><p>命令解压缩安装包:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tar -xvf nacos-server-1.4.1.tar.gz</span><br></pre></td></tr></table></figure><p>然后删除安装包:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">rm</span> -rf nacos-server-1.4.1.tar.gz</span><br></pre></td></tr></table></figure><h2 id="2-4-端口配置">2.4.端口配置</h2><p>与windows中类似</p><h2 id="2-5-启动">2.5.启动</h2><p>在nacos/bin目录中,输入命令启动Nacos:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sh startup.sh -m standalone</span><br></pre></td></tr></table></figure><h1>3.Nacos的依赖</h1><p>父工程:</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><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>com.alibaba.cloud<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>spring-cloud-alibaba-dependencies<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>2.2.5.RELEASE<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">type</span>></span>pom<span class="tag"></<span class="name">type</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">scope</span>></span>import<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><p>客户端:</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"><!-- nacos客户端依赖包 --></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.alibaba.cloud<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>spring-cloud-starter-alibaba-nacos-discovery<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></pre></td></tr></table></figure>]]></content>
<categories>
<category> 微服务 </category>
</categories>
<tags>
<tag> 微服务 </tag>
<tag> Nacos </tag>
</tags>
</entry>
<entry>
<title>CentOS部署RabbitMQ</title>
<link href="/posts/17ff1682.html"/>
<url>/posts/17ff1682.html</url>
<content type="html"><![CDATA[<h1>RabbitMQ部署指南</h1><h1>1.单机部署</h1><p>我们在Centos7虚拟机中使用Docker来安装。</p><h2 id="1-1-下载镜像">1.1.下载镜像</h2><p>方式一:在线拉取</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker pull rabbitmq:3-management</span><br></pre></td></tr></table></figure><p>方式二:从本地加载</p><p>在课前资料已经提供了镜像包:</p><p><img src="assets/image-20210423191210349.png" alt="image-20210423191210349"></p><p>上传到虚拟机中后,使用命令加载镜像即可:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker load -i mq.tar</span><br></pre></td></tr></table></figure><h2 id="1-2-安装MQ">1.2.安装MQ</h2><p>执行下面的命令来运行MQ容器:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">docker run \</span><br><span class="line"> -e RABBITMQ_DEFAULT_USER=iTddey \</span><br><span class="line"> -e RABBITMQ_DEFAULT_PASS=123321 \</span><br><span class="line"> --name mq \</span><br><span class="line"> --hostname mq1 \</span><br><span class="line"> -p 15672:15672 \</span><br><span class="line"> -p 5672:5672 \</span><br><span class="line"> -d \</span><br><span class="line"> rabbitmq:latest</span><br></pre></td></tr></table></figure><h1>2.集群部署</h1><p>接下来,我们看看如何安装RabbitMQ的集群。</p><h2 id="2-1-集群分类">2.1.集群分类</h2><p>在RabbitMQ的官方文档中,讲述了两种集群的配置方式:</p><ul><li>普通模式:普通模式集群不进行数据同步,每个MQ都有自己的队列、数据信息(其它元数据信息如交换机等会同步)。例如我们有2个MQ:mq1,和mq2,如果你的消息在mq1,而你连接到了mq2,那么mq2会去mq1拉取消息,然后返回给你。如果mq1宕机,消息就会丢失。</li><li>镜像模式:与普通模式不同,队列会在各个mq的镜像节点之间同步,因此你连接到任何一个镜像节点,均可获取到消息。而且如果一个节点宕机,并不会导致数据丢失。不过,这种方式增加了数据同步的带宽消耗。</li></ul><p>我们先来看普通模式集群。</p><h2 id="2-2-设置网络">2.2.设置网络</h2><p>首先,我们需要让3台MQ互相知道对方的存在。</p><p>分别在3台机器中,设置 /etc/hosts文件,添加如下内容:</p><figure class="highlight accesslog"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">192.168.150.101</span> mq1</span><br><span class="line"><span class="number">192.168.150.102</span> mq2</span><br><span class="line"><span class="number">192.168.150.103</span> mq3</span><br></pre></td></tr></table></figure><p>并在每台机器上测试,是否可以ping通对方:</p>]]></content>
<categories>
<category> 微服务 </category>
</categories>
<tags>
<tag> 微服务 </tag>
<tag> RabbitMQ </tag>
</tags>
</entry>
<entry>
<title>部署elasticsearch</title>
<link href="/posts/5b9a0ff1.html"/>
<url>/posts/5b9a0ff1.html</url>
<content type="html"><![CDATA[<h1>安装elasticsearch</h1><h1>1.部署单点es</h1><h2 id="1-1-创建网络">1.1.创建网络</h2><p>因为我们还需要部署kibana容器,因此需要让es和kibana容器互联。这里先创建一个网络:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker network create es-net</span><br></pre></td></tr></table></figure><h2 id="1-2-加载镜像">1.2.加载镜像</h2><p>这里我们采用elasticsearch的7.12.1版本的镜像,这个镜像体积非常大,接近1G。不建议大家自己pull。</p><p>课前资料提供了镜像的tar包:</p><p><img src="assets/image-20210510165308064.png" alt="image-20210510165308064"></p><p>大家将其上传到虚拟机中,然后运行命令加载即可:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 导入数据</span></span><br><span class="line">docker load -i es.tar</span><br></pre></td></tr></table></figure><p>同理还有<code>kibana</code>的tar包也需要这样做。</p><h2 id="1-3-运行">1.3.运行</h2><p>运行docker命令,部署单点es:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">docker run -d \</span><br><span class="line">--name es \</span><br><span class="line"> -e <span class="string">"ES_JAVA_OPTS=-Xms512m -Xmx512m"</span> \</span><br><span class="line"> -e <span class="string">"discovery.type=single-node"</span> \</span><br><span class="line"> -v es-data:/usr/share/elasticsearch/data \</span><br><span class="line"> -v es-plugins:/usr/share/elasticsearch/plugins \</span><br><span class="line"> --privileged \</span><br><span class="line"> --network es-net \</span><br><span class="line"> -p 9200:9200 \</span><br><span class="line"> -p 9300:9300 \</span><br><span class="line">elasticsearch:7.12.1</span><br></pre></td></tr></table></figure><p>命令解释:</p><ul><li><code>-e "cluster.name=es-docker-cluster"</code>:设置集群名称</li><li><code>-e "http.host=0.0.0.0"</code>:监听的地址,可以外网访问</li><li><code>-e "ES_JAVA_OPTS=-Xms512m -Xmx512m"</code>:内存大小</li><li><code>-e "discovery.type=single-node"</code>:非集群模式</li><li><code>-v es-data:/usr/share/elasticsearch/data</code>:挂载逻辑卷,绑定es的数据目录</li><li><code>-v es-logs:/usr/share/elasticsearch/logs</code>:挂载逻辑卷,绑定es的日志目录</li><li><code>-v es-plugins:/usr/share/elasticsearch/plugins</code>:挂载逻辑卷,绑定es的插件目录</li><li><code>--privileged</code>:授予逻辑卷访问权</li><li><code>--network es-net</code> :加入一个名为es-net的网络中</li><li><code>-p 9200:9200</code>:端口映射配置</li></ul><p>在浏览器中输入:<a href="http://192.168.150.101:9200">http://192.168.150.101:9200</a> 即可看到elasticsearch的响应结果:</p><p><img src="assets/image-20210506101053676.png" alt="image-20210506101053676"></p><h1>2.部署kibana</h1><p>kibana可以给我们提供一个elasticsearch的可视化界面,便于我们学习。</p><h2 id="2-1-部署">2.1.部署</h2><p>运行docker命令,部署kibana</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">docker run -d \</span><br><span class="line">--name kibana \</span><br><span class="line">-e ELASTICSEARCH_HOSTS=http://es:9200 \</span><br><span class="line">--network=es-net \</span><br><span class="line">-p 5601:5601 \</span><br><span class="line">kibana:7.12.1</span><br></pre></td></tr></table></figure><ul><li><code>--network es-net</code> :加入一个名为es-net的网络中,与elasticsearch在同一个网络中</li><li><code>-e ELASTICSEARCH_HOSTS=http://es:9200"</code>:设置elasticsearch的地址,因为kibana已经与elasticsearch在一个网络,因此可以用容器名直接访问elasticsearch</li><li><code>-p 5601:5601</code>:端口映射配置</li></ul><p>kibana启动一般比较慢,需要多等待一会,可以通过命令:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker logs -f kibana</span><br></pre></td></tr></table></figure><p>查看运行日志,当查看到下面的日志,说明成功:</p><p><img src="assets/image-20210109105135812.png" alt="image-20210109105135812"></p><p>此时,在浏览器输入地址访问:<a href="http://192.168.150.101:5601">http://192.168.150.101:5601</a>,即可看到结果</p><h2 id="2-2-DevTools">2.2.DevTools</h2><p>kibana中提供了一个DevTools界面:</p><p><img src="assets/image-20210506102630393.png" alt="image-20210506102630393"></p><p>这个界面中可以编写DSL来操作elasticsearch。并且对DSL语句有自动补全功能。</p><h1>3.安装IK分词器</h1><h2 id="3-1-在线安装ik插件(较慢)">3.1.在线安装ik插件(较慢)</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">进入容器内部</span></span><br><span class="line">docker exec -it elasticsearch /bin/bash</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">在线下载并安装</span></span><br><span class="line">./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.12.1/elasticsearch-analysis-ik-7.12.1.zip</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">退出</span></span><br><span class="line">exit</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">重启容器</span></span><br><span class="line">docker restart elasticsearch</span><br></pre></td></tr></table></figure><h2 id="3-2-离线安装ik插件(推荐)">3.2.离线安装ik插件(推荐)</h2><h3 id="1)查看数据卷目录">1)查看数据卷目录</h3><p>安装插件需要知道elasticsearch的plugins目录位置,而我们用了数据卷挂载,因此需要查看elasticsearch的数据卷目录,通过下面命令查看:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker volume inspect es-plugins</span><br></pre></td></tr></table></figure><p>显示结果:</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">[</span></span><br><span class="line"> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"CreatedAt"</span><span class="punctuation">:</span> <span class="string">"2022-05-06T10:06:34+08:00"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"Driver"</span><span class="punctuation">:</span> <span class="string">"local"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"Labels"</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">null</span></span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"Mountpoint"</span><span class="punctuation">:</span> <span class="string">"/var/lib/docker/volumes/es-plugins/_data"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"Name"</span><span class="punctuation">:</span> <span class="string">"es-plugins"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"Options"</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">null</span></span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"Scope"</span><span class="punctuation">:</span> <span class="string">"local"</span></span><br><span class="line"> <span class="punctuation">}</span></span><br><span class="line"><span class="punctuation">]</span></span><br></pre></td></tr></table></figure><p>说明plugins目录被挂载到了:<code>/var/lib/docker/volumes/es-plugins/_data </code>这个目录中。</p><h3 id="2)解压缩分词器安装包">2)解压缩分词器安装包</h3><p>下面我们需要把课前资料中的ik分词器解压缩,重命名为ik</p><p><img src="assets/image-20210506110249144.png" alt="image-20210506110249144"></p><h3 id="3)上传到es容器的插件数据卷中">3)上传到es容器的插件数据卷中</h3><p>也就是<code>/var/lib/docker/volumes/es-plugins/_data </code>:</p><p><img src="assets/image-20210506110704293.png" alt="image-20210506110704293"></p><h3 id="4)重启容器">4)重启容器</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">4、重启容器</span></span><br><span class="line">docker restart es</span><br></pre></td></tr></table></figure><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 查看es日志</span></span><br><span class="line">docker logs -f es</span><br></pre></td></tr></table></figure><h3 id="5)测试:">5)测试:</h3><p>IK分词器包含两种模式:</p><ul><li><p><code>ik_smart</code>:最少切分</p></li><li><p><code>ik_max_word</code>:最细切分</p></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">GET /_analyze</span><br><span class="line"><span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"analyzer"</span><span class="punctuation">:</span> <span class="string">"ik_max_word"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"text"</span><span class="punctuation">:</span> <span class="string">"黑马程序员学习java太棒了"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><p>结果:</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"tokens"</span> <span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line"> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"token"</span> <span class="punctuation">:</span> <span class="string">"黑马"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"start_offset"</span> <span class="punctuation">:</span> <span class="number">0</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"end_offset"</span> <span class="punctuation">:</span> <span class="number">2</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"type"</span> <span class="punctuation">:</span> <span class="string">"CN_WORD"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"position"</span> <span class="punctuation">:</span> <span class="number">0</span></span><br><span class="line"> <span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line"> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"token"</span> <span class="punctuation">:</span> <span class="string">"程序员"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"start_offset"</span> <span class="punctuation">:</span> <span class="number">2</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"end_offset"</span> <span class="punctuation">:</span> <span class="number">5</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"type"</span> <span class="punctuation">:</span> <span class="string">"CN_WORD"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"position"</span> <span class="punctuation">:</span> <span class="number">1</span></span><br><span class="line"> <span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line"> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"token"</span> <span class="punctuation">:</span> <span class="string">"程序"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"start_offset"</span> <span class="punctuation">:</span> <span class="number">2</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"end_offset"</span> <span class="punctuation">:</span> <span class="number">4</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"type"</span> <span class="punctuation">:</span> <span class="string">"CN_WORD"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"position"</span> <span class="punctuation">:</span> <span class="number">2</span></span><br><span class="line"> <span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line"> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"token"</span> <span class="punctuation">:</span> <span class="string">"员"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"start_offset"</span> <span class="punctuation">:</span> <span class="number">4</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"end_offset"</span> <span class="punctuation">:</span> <span class="number">5</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"type"</span> <span class="punctuation">:</span> <span class="string">"CN_CHAR"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"position"</span> <span class="punctuation">:</span> <span class="number">3</span></span><br><span class="line"> <span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line"> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"token"</span> <span class="punctuation">:</span> <span class="string">"学习"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"start_offset"</span> <span class="punctuation">:</span> <span class="number">5</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"end_offset"</span> <span class="punctuation">:</span> <span class="number">7</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"type"</span> <span class="punctuation">:</span> <span class="string">"CN_WORD"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"position"</span> <span class="punctuation">:</span> <span class="number">4</span></span><br><span class="line"> <span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line"> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"token"</span> <span class="punctuation">:</span> <span class="string">"java"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"start_offset"</span> <span class="punctuation">:</span> <span class="number">7</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"end_offset"</span> <span class="punctuation">:</span> <span class="number">11</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"type"</span> <span class="punctuation">:</span> <span class="string">"ENGLISH"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"position"</span> <span class="punctuation">:</span> <span class="number">5</span></span><br><span class="line"> <span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line"> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"token"</span> <span class="punctuation">:</span> <span class="string">"太棒了"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"start_offset"</span> <span class="punctuation">:</span> <span class="number">11</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"end_offset"</span> <span class="punctuation">:</span> <span class="number">14</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"type"</span> <span class="punctuation">:</span> <span class="string">"CN_WORD"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"position"</span> <span class="punctuation">:</span> <span class="number">6</span></span><br><span class="line"> <span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line"> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"token"</span> <span class="punctuation">:</span> <span class="string">"太棒"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"start_offset"</span> <span class="punctuation">:</span> <span class="number">11</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"end_offset"</span> <span class="punctuation">:</span> <span class="number">13</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"type"</span> <span class="punctuation">:</span> <span class="string">"CN_WORD"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"position"</span> <span class="punctuation">:</span> <span class="number">7</span></span><br><span class="line"> <span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line"> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"token"</span> <span class="punctuation">:</span> <span class="string">"了"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"start_offset"</span> <span class="punctuation">:</span> <span class="number">13</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"end_offset"</span> <span class="punctuation">:</span> <span class="number">14</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"type"</span> <span class="punctuation">:</span> <span class="string">"CN_CHAR"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"position"</span> <span class="punctuation">:</span> <span class="number">8</span></span><br><span class="line"> <span class="punctuation">}</span></span><br><span class="line"> <span class="punctuation">]</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><h2 id="3-3-扩展词词典">3.3 扩展词词典</h2><p>随着互联网的发展,“造词运动”也越发的频繁。出现了很多新的词语,在原有的词汇列表中并不存在。比如:“奥力给”,“传智播客” 等。</p><p>所以我们的词汇也需要不断的更新,IK分词器提供了扩展词汇的功能。</p><p>1)打开IK分词器config目录:</p><p><img src="assets/image-20210506112225508.png" alt="image-20210506112225508"></p><p>2)在IKAnalyzer.cfg.xml配置文件内容添加:</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><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="meta"><!DOCTYPE <span class="keyword">properties</span> <span class="keyword">SYSTEM</span> <span class="string">"http://java.sun.com/dtd/properties.dtd"</span>></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">comment</span>></span>IK Analyzer 扩展配置<span class="tag"></<span class="name">comment</span>></span></span><br><span class="line"> <span class="comment"><!--用户可以在这里配置自己的扩展字典 *** 添加扩展词典--></span></span><br><span class="line"> <span class="tag"><<span class="name">entry</span> <span class="attr">key</span>=<span class="string">"ext_dict"</span>></span>ext.dic<span class="tag"></<span class="name">entry</span>></span></span><br><span class="line"><span class="tag"></<span class="name">properties</span>></span></span><br></pre></td></tr></table></figure><p>3)新建一个 ext.dic,可以参考config目录下复制一个配置文件进行修改</p><figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">传智播客</span></span><br><span class="line"><span class="attr">奥力给</span></span><br></pre></td></tr></table></figure><p>4)重启elasticsearch</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">docker restart es</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看 日志</span></span><br><span class="line">docker logs -f elasticsearch</span><br></pre></td></tr></table></figure><p><img src="assets/image-20201115230900504.png" alt="image-20201115230900504"></p><p>日志中已经成功加载ext.dic配置文件</p><p>5)测试效果:</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">GET /_analyze</span><br><span class="line"><span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"analyzer"</span><span class="punctuation">:</span> <span class="string">"ik_max_word"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"text"</span><span class="punctuation">:</span> <span class="string">"传智播客Java就业超过90%,奥力给!"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><blockquote><p>注意当前文件的编码必须是 UTF-8 格式,严禁使用Windows记事本编辑</p></blockquote><h2 id="3-4-停用词词典">3.4 停用词词典</h2><p>在互联网项目中,在网络间传输的速度很快,所以很多语言是不允许在网络上传递的,如:关于宗教、政治等敏感词语,那么我们在搜索时也应该忽略当前词汇。</p><p>IK分词器也提供了强大的停用词功能,让我们在索引时就直接忽略当前的停用词汇表中的内容。</p><p>1)IKAnalyzer.cfg.xml配置文件内容添加:</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><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="meta"><!DOCTYPE <span class="keyword">properties</span> <span class="keyword">SYSTEM</span> <span class="string">"http://java.sun.com/dtd/properties.dtd"</span>></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">comment</span>></span>IK Analyzer 扩展配置<span class="tag"></<span class="name">comment</span>></span></span><br><span class="line"> <span class="comment"><!--用户可以在这里配置自己的扩展字典--></span></span><br><span class="line"> <span class="tag"><<span class="name">entry</span> <span class="attr">key</span>=<span class="string">"ext_dict"</span>></span>ext.dic<span class="tag"></<span class="name">entry</span>></span></span><br><span class="line"> <span class="comment"><!--用户可以在这里配置自己的扩展停止词字典 *** 添加停用词词典--></span></span><br><span class="line"> <span class="tag"><<span class="name">entry</span> <span class="attr">key</span>=<span class="string">"ext_stopwords"</span>></span>stopword.dic<span class="tag"></<span class="name">entry</span>></span></span><br><span class="line"><span class="tag"></<span class="name">properties</span>></span></span><br></pre></td></tr></table></figure><p>3)在 stopword.dic 添加停用词</p><figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">习大大</span></span><br></pre></td></tr></table></figure><p>4)重启elasticsearch</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 重启服务</span></span><br><span class="line">docker restart elasticsearch</span><br><span class="line">docker restart kibana</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看 日志</span></span><br><span class="line">docker logs -f elasticsearch</span><br></pre></td></tr></table></figure><p>日志中已经成功加载stopword.dic配置文件</p><p>5)测试效果:</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">GET /_analyze</span><br><span class="line"><span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"analyzer"</span><span class="punctuation">:</span> <span class="string">"ik_max_word"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"text"</span><span class="punctuation">:</span> <span class="string">"传智播客Java就业率超过95%,习大大都点赞,奥力给!"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><blockquote><p>注意当前文件的编码必须是 UTF-8 格式,严禁使用Windows记事本编辑</p></blockquote><h1>4.部署es集群</h1><p>部署es集群可以直接使用docker-compose来完成,不过要求你的Linux虚拟机至少有<strong>4G</strong>的内存空间</p><p>首先编写一个docker-compose文件,内容如下:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br></pre></td><td class="code"><pre><span class="line">version: <span class="string">'2.2'</span></span><br><span class="line">services:</span><br><span class="line"> es01:</span><br><span class="line"> image: docker.elastic.co/elasticsearch/elasticsearch:7.12.1</span><br><span class="line"> container_name: es01</span><br><span class="line"> environment:</span><br><span class="line"> - node.name=es01</span><br><span class="line"> - cluster.name=es-docker-cluster</span><br><span class="line"> - discovery.seed_hosts=es02,es03</span><br><span class="line"> - cluster.initial_master_nodes=es01,es02,es03</span><br><span class="line"> - bootstrap.memory_lock=<span class="literal">true</span></span><br><span class="line"> - <span class="string">"ES_JAVA_OPTS=-Xms512m -Xmx512m"</span></span><br><span class="line"> ulimits:</span><br><span class="line"> memlock:</span><br><span class="line"> soft: -1</span><br><span class="line"> hard: -1</span><br><span class="line"> volumes:</span><br><span class="line"> - data01:/usr/share/elasticsearch/data</span><br><span class="line"> ports:</span><br><span class="line"> - 9200:9200</span><br><span class="line"> networks:</span><br><span class="line"> - elastic</span><br><span class="line"> es02:</span><br><span class="line"> image: docker.elastic.co/elasticsearch/elasticsearch:7.12.1</span><br><span class="line"> container_name: es02</span><br><span class="line"> environment:</span><br><span class="line"> - node.name=es02</span><br><span class="line"> - cluster.name=es-docker-cluster</span><br><span class="line"> - discovery.seed_hosts=es01,es03</span><br><span class="line"> - cluster.initial_master_nodes=es01,es02,es03</span><br><span class="line"> - bootstrap.memory_lock=<span class="literal">true</span></span><br><span class="line"> - <span class="string">"ES_JAVA_OPTS=-Xms512m -Xmx512m"</span></span><br><span class="line"> ulimits:</span><br><span class="line"> memlock:</span><br><span class="line"> soft: -1</span><br><span class="line"> hard: -1</span><br><span class="line"> volumes:</span><br><span class="line"> - data02:/usr/share/elasticsearch/data</span><br><span class="line"> networks:</span><br><span class="line"> - elastic</span><br><span class="line"> es03:</span><br><span class="line"> image: docker.elastic.co/elasticsearch/elasticsearch:7.12.1</span><br><span class="line"> container_name: es03</span><br><span class="line"> environment:</span><br><span class="line"> - node.name=es03</span><br><span class="line"> - cluster.name=es-docker-cluster</span><br><span class="line"> - discovery.seed_hosts=es01,es02</span><br><span class="line"> - cluster.initial_master_nodes=es01,es02,es03</span><br><span class="line"> - bootstrap.memory_lock=<span class="literal">true</span></span><br><span class="line"> - <span class="string">"ES_JAVA_OPTS=-Xms512m -Xmx512m"</span></span><br><span class="line"> ulimits:</span><br><span class="line"> memlock:</span><br><span class="line"> soft: -1</span><br><span class="line"> hard: -1</span><br><span class="line"> volumes:</span><br><span class="line"> - data03:/usr/share/elasticsearch/data</span><br><span class="line"> networks:</span><br><span class="line"> - elastic</span><br><span class="line"></span><br><span class="line">volumes:</span><br><span class="line"> data01:</span><br><span class="line"> driver: <span class="built_in">local</span></span><br><span class="line"> data02:</span><br><span class="line"> driver: <span class="built_in">local</span></span><br><span class="line"> data03:</span><br><span class="line"> driver: <span class="built_in">local</span></span><br><span class="line"></span><br><span class="line">networks:</span><br><span class="line"> elastic:</span><br><span class="line"> driver: bridge</span><br></pre></td></tr></table></figure><p>Run <code>docker-compose</code> to bring up the cluster:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker-compose up</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> 微服务 </category>
</categories>
<tags>
<tag> 微服务 </tag>
<tag> elasticsearch </tag>
</tags>
</entry>
<entry>
<title>微服务</title>
<link href="/posts/460c1130.html"/>
<url>/posts/460c1130.html</url>
<content type="html"><![CDATA[<h1>微服务</h1><h2 id="1-认识微服务">1.认识微服务</h2><p>微服务是一种经过良好架构设计的分布式架构方案,微服务架构特征:</p><ul><li>单一职责:微服务拆分粒度更小,每一个服务都对应唯一的业务能力,做到单一职责,避免重复业务开发</li><li>面向服务:微服务对外暴露业务接口</li><li>自治:团队独立、技术独立、数据独立、部署独立</li><li>隔离性强:服务调用做好隔离、容错、降级,避免出现级联问题</li></ul><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/1.png" alt="1"></p><p>单体架构特点?</p><ul><li>简单方便,高度耦合,扩展性差,适合小型项目。例如:学生管理系统</li></ul><p>分布式架构特点?</p><ul><li>松耦合,扩展性好,但架构复杂,难度大。适合大型互联网项目,例如:京东、淘宝</li></ul><p>微服务:一种良好的分布式架构方案</p><ul><li>优点:拆分粒度更小、服务更独立、耦合度更低</li><li>缺点:架构非常复杂,运维、监控、部署难度提高</li></ul><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/2.png" alt="2"></p><h2 id="2-服务远程调用">2.服务远程调用</h2><p>基于java通过RestTemplate发送Http请求<br>1、注册restTemplate到Spring容器</p><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/3.png" alt="3"></p><p>2、使用restTemplate发送Http请求</p><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/4.png" alt="4"></p><h2 id="3-Eureka(注册中心)">3.Eureka(注册中心)</h2><h3 id="提供者与消费者">提供者与消费者</h3><ul><li>服务提供者:一次业务中,被其它微服务调用的服务。(提供接口给其它微服务)</li><li>服务消费者:一次业务中,调用其它微服务的服务。(调用其它微服务提供的接口)</li></ul><p>一个服务既可以是服务消费者也可以是服务消费者,两者是相对的。</p><h3 id="eureka的作用">eureka的作用</h3><p>1、消费者该如何获取服务提供者具体信息?</p><ul><li>服务提供者启动时向eureka注册自己的信息</li><li>eureka保存这些信息</li><li>消费者根据服务名称向eureka拉取提供者信息</li></ul><p>2、如果有多个服务提供者,消费者该如何选择?</p><ul><li>服务消费者利用负载均衡算法,从服务列表中挑选一个</li></ul><p>3、消费者如何感知服务提供者健康状态?</p><ul><li>服务提供者会每隔30秒向EurekaServer发送心跳请求,报告健康状态</li><li>eureka会更新记录服务列表信息,心跳不正常会被剔除</li><li>消费者就可以拉取到最新的信息</li></ul><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/5.png" alt="5"></p><p>4、在Eureka架构中,微服务角色有两类:</p><ol><li>EurekaServer:服务端,注册中心</li></ol><ul><li>记录服务信息</li><li>心跳监控</li></ul><ol start="2"><li>EurekaClient:客户端</li><li>Provider:服务提供者,例如案例中的user-service<br>- 注册自己的信息到EurekaServer<br>- 每隔30秒向EurekaServer发送心跳</li><li>consumer:服务消费者,例如案例中的order-service<br>- 根据服务名称从EurekaServer拉取服务列表<br>- 基于服务列表做负载均衡,选中一个微服务后发起远程调用</li></ol><h2 id="4-服务注册">4.服务注册</h2><h3 id="引入依赖">引入依赖</h3><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><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.cloud<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>spring-cloud-starter-netflix-eureka-server<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><h3 id="配置yml">配置yml</h3><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/6.png" alt="6"></p><h3 id="拉取服务">拉取服务</h3><p>服务拉取是基于服务名称获取服务列表,然后在对服务列表做负载均衡<br>1、修改OrderService的代码,修改访问的url路径,用服务名代替ip、端口:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">String</span> <span class="variable">url</span> <span class="operator">=</span> <span class="string">"http://userservice/user/"</span>+ order.getUserId();</span><br></pre></td></tr></table></figure><p>2、在order-service项目的启动类OrderApplication中的RestTemplate添加负载均衡注解:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="meta">@LoadBalanced</span></span><br><span class="line"><span class="keyword">public</span> RestTemplate <span class="title function_">restTemplate</span><span class="params">()</span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">RestTemplate</span>();</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><h3 id="总过程">总过程</h3><p>1、搭建EurekaSerer</p><ul><li>引入eureka-server依赖</li><li>添加@EnableEurekaServer注解</li><li>在application.yml中配置eureka地址</li></ul><p>2、服务注册</p><ul><li>引入eureka-client依赖</li><li>在application.yml中配置eureka地址</li></ul><p>3、服务发现</p><ul><li>引入eureka-client依赖</li><li>在application.yml中配置eureka地址</li><li>给RestTemplate添加@LoadBalanced注解</li><li>用服务提供者的服务名称远程调用</li></ul><div class="note orange icon-padding flat"><i class="note-icon fas fa-battery-half"></i><p>问题:Springcloud使用eureka客户端报错:<br>com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException:<br>解决方案:yml文件层级出错,改正即可</p></div><h2 id="6-Ribbon负载均衡">6.Ribbon负载均衡</h2><h3 id="负载均衡流程">负载均衡流程</h3><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/7.png" alt="7"></p><h3 id="负载均衡策略">负载均衡策略</h3><p>通过定义IRule实现可以修改负载均衡规则,有两种方式:<br>1、代码方式:在order-service中的OrderApplication类中,定义一个新的IRule:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="keyword">public</span> IRule <span class="title function_">myRule</span><span class="params">()</span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">RandomRule</span>();<span class="comment">//定义为随机</span></span><br><span class="line"> }</span><br></pre></td></tr></table></figure><p>2、配置文件方式:在order-service的application.yml文件中,添加新的配置也可以修改规则:</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">userservice:</span></span><br><span class="line"> <span class="attr">ribbon:</span></span><br><span class="line"> <span class="attr">NFLoadBalancerRuleClassName:</span> <span class="string">com.netflix.loadbalancer.RandomRule</span> <span class="comment"># 负载均衡规则 </span></span><br></pre></td></tr></table></figure><h3 id="总结">总结</h3><ol><li>Ribbon负载均衡规则</li></ol><ul><li>规则接口是IRule</li><li>默认实现是ZoneAvoidanceRule,根据zone选择服务列表,然后轮询</li></ul><ol start="2"><li>负载均衡自定义方式</li></ol><ul><li>代码方式:配置灵活,但修改时需要重新打包发布</li><li>配置方式:直观、方便,无需重新打包发布但是无法做全局配置</li></ul><ol start="3"><li>饥饿加载</li></ol><ul><li>开启饥饿加载</li><li>指定饥饿加载的微服务名称</li></ul><h2 id="7-Nacos注册中心">7.Nacos注册中心</h2><h3 id="启动服务">启动服务</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">startup.cmd -m standalone</span><br></pre></td></tr></table></figure><h3 id="访问">访问</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">在浏览器输入地址:http:<span class="comment">//127.0.0.1:8848/nacos 即可:</span></span><br></pre></td></tr></table></figure><h3 id="导入依赖包">导入依赖包</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><-- 父工程 --></span><br><span class="line"><dependency></span><br><span class="line"> <groupId>com.alibaba.cloud</groupId></span><br><span class="line"> <artifactId>spring-cloud-alibaba-dependencies</artifactId></span><br><span class="line"> <version><span class="number">2.2</span><span class="number">.5</span>.RELEASE</version></span><br><span class="line"> <type>pom</type></span><br><span class="line"> <scope><span class="keyword">import</span></scope></span><br><span class="line"></dependency></span><br><span class="line"><!--nacos客户端依赖包 --></span><br><span class="line"><dependency></span><br><span class="line"> <groupId>com.alibaba.cloud</groupId></span><br><span class="line"> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></span><br><span class="line"></dependency></span><br></pre></td></tr></table></figure><h3 id="配置yml文件">配置yml文件</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//客户端</span></span><br><span class="line">cloud:</span><br><span class="line"> nacos:</span><br><span class="line"> server-addr: localhost:<span class="number">8848</span> #nacos的注册中心地址</span><br></pre></td></tr></table></figure><h3 id="集群分级存储服务">集群分级存储服务</h3><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/8.png" alt="8"></p><h3 id="优先同集群负载均衡访问策略">优先同集群负载均衡访问策略</h3><ul><li>NacosRute负载均衡策略<ol><li>优先选择同集群服务实例列表</li><li>本地集群找不到提供者,才去其它集群寻找,并且会报警告</li><li>确定了可用实例列表后,再采用随机负载均衡挑选实例</li></ol></li><li>实例的权重控制<ol><li>Nacos控制台可以设置实例的权重值,</li><li>0~1之间同集群内的多个实例,</li><li>权重越高被访问的频率越高权重设置为0则完全不会被访问</li></ol></li><li>Nacos环境隔离<ol><li>namespace用来做环境隔离</li><li>每个namespace都有唯一id不同</li><li>namespace下的服务不可见</li></ol></li></ul><h2 id="8-Nacos配置中心">8.Nacos配置中心</h2><h3 id="统一配置管理">统一配置管理</h3><ul><li>配置获取步骤:<br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/9.png" alt="9"></li></ul><ol><li>pom文件中引入配置依赖</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><!--nacos配置管理客户端依赖 --></span><br><span class="line"> <dependency></span><br><span class="line"> <groupId>com.alibaba.cloud</groupId></span><br><span class="line"> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></span><br><span class="line"> </dependency></span><br></pre></td></tr></table></figure><ol start="2"><li>对应微服务模块导入配置文件</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">bootstrap.yml文件</span><br><span class="line">spring:</span><br><span class="line"> application:</span><br><span class="line"> name: userService #服务名称</span><br><span class="line"> profiles:</span><br><span class="line"> active: dev #开发环境,这里是dev</span><br><span class="line"> cloud:</span><br><span class="line"> nacos:</span><br><span class="line"> server-addr: localhost:<span class="number">8848</span> #Nacos地址</span><br><span class="line"> config:</span><br><span class="line"> file-extension: yaml #文件后缀名</span><br></pre></td></tr></table></figure><ol start="3"><li>读取配置文件</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1</span>、Controller中加入<span class="meta">@RefreshScope</span>注解 <span class="comment">//动态刷新配置,配置热更新、</span></span><br><span class="line"><span class="meta">@RefreshScope</span> </span><br><span class="line"><span class="meta">@RequestMapping("/user")</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> UserService userService;</span><br><span class="line"> <span class="meta">@Value("${pattern.dateformat}")</span></span><br><span class="line"> <span class="keyword">private</span> String dateformat;</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> PatternConfig patternConfig;</span><br><span class="line"> <span class="meta">@GetMapping("/now")</span></span><br><span class="line"> <span class="keyword">public</span> String <span class="title function_">now</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> LocalDateTime.now().format(DateTimeFormatter.ofPattern(patternConfig.getDateformat()));</span><br><span class="line"> }</span><br><span class="line"><span class="number">2</span>、注入PatternConfig配置类对象,届时自动热加载</span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@ConfigurationProperties(prefix = "pattern")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">PatternConfig</span> {</span><br><span class="line"> <span class="keyword">private</span> String dateformat;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ol start="4"><li>Nacos配置更改后,微服务可以实现热更新,方式:</li></ol><ul><li>通过@Value注解注入,结合@RefreshScope来刷新</li><li>通过@ConfigurationProperties注入,自动刷新</li></ul><ol start="5"><li>注意事项:</li></ol><ul><li>不是所有的配置都适合放到配置中心,维护起来比较麻烦</li><li>建议将一些关键参数,需要运行时调整的参数放到nacos配置中心,一般都是自定义配置</li></ul><ol start="6"><li>微服务会从nacos读取的配置文件:</li></ol><ul><li>[服务名]-[spring.profile.active].yaml,环境配置</li><li>[服务名].yaml,默认配置,多环境共享</li></ul><ol start="7"><li>优先级:<br>[服务名]-[环境].yaml>[服务名].yaml>本地配置</li></ol><h3 id="Nacos集群搭建步骤">Nacos集群搭建步骤:</h3><ol><li>搭建MySQL集群并初始化数据库表</li><li>下载解压nacos</li><li>修改集群配置(节点信息)、数据库配置</li><li>分别启动多个nacos节点</li><li>nginx反向代理</li></ol><h2 id="9-Feign-Http客户端,用于发送Http请求">9.Feign (Http客户端,用于发送Http请求)</h2><p>1、 引入依赖</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><!--feign依赖包--></span><br><span class="line"> <dependency></span><br><span class="line"> <groupId>org.springframework.cloud</groupId></span><br><span class="line"> <artifactId>spring-cloud-starter-openfeign</artifactId></span><br><span class="line"> </dependency></span><br></pre></td></tr></table></figure><p>2、 启动类上加@EnableFeignClients注解</p><p>3、 编写Feign客户端</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@FeignClient("userService")</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">UserClient</span> {</span><br><span class="line"> <span class="meta">@GetMapping("/user/{id}")</span></span><br><span class="line"> User <span class="title function_">findById</span><span class="params">(<span class="meta">@PathVariable("id")</span> Long id)</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>4、 编写FeignClient接口</p><p>5、 使用FeignClient中定义的方法代替RestTemplate</p><h3 id="自定义feign配置">自定义feign配置</h3><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/10.png" alt="10"></p><ol><li>方式一:在配置文件中配置</li></ol><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">feign:</span></span><br><span class="line"> <span class="attr">client:</span></span><br><span class="line"> <span class="attr">config:</span></span><br><span class="line"> <span class="attr">default:</span></span><br><span class="line"> <span class="attr">loggerLevel:</span> <span class="string">FULL</span></span><br></pre></td></tr></table></figure><ol start="2"><li>方式二:java代码方式,需要先声明一个Bean</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">FeignClientConfiguration</span>{</span><br><span class="line"> <span class="meta">@Bean</span></span><br><span class="line"> <span class="keyword">public</span> Logger.Level <span class="title function_">feignLogLevel</span><span class="params">()</span>{</span><br><span class="line"> <span class="keyword">return</span> Logger.Level.BASIC;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>而后如果是全局配置,则把它放到@EnableFeignClients这个注解中:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@EnableFeignClients(defaultConfiguration = FeignClientConfiguration.class)</span></span><br></pre></td></tr></table></figure><ul><li>如果是局部配置,则把它放到@FeignClient这个注解中:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@FeignClient(value ="userservice",configuration = FeignClientConfiguration.class)</span></span><br></pre></td></tr></table></figure><h3 id="Feign的日志级别">Feign的日志级别</h3><ul><li>级别从低到高分为:<ol><li>NONE:默认的,不记录任何日志</li><li>BASIC:仅记录请求方法、URL、响应状态码及执行时间</li><li>HEADERS:在BASIC的基础上,额外记录请求和响应的header</li><li>FULL:在HEADERS的基础上,额外记录请求和响应的body</li></ol></li></ul><h3 id="Feign的日志配置">Feign的日志配置:</h3><ol><li>方式一是配置文件,feign.client.config.xxx.loggerLevel</li></ol><ul><li>如果xxx是default则代表全局</li><li>如果xxx是服务名称,例如userservice则代表某服务</li></ul><ol start="2"><li>方式二是java代码配置Logger.Level这个Bean</li></ol><ul><li>如果在@EnableFeignClients注解声明则代表全局</li><li>如果在@FeignClient注解中声明则代表某服务</li></ul><h3 id="feign性能调优">feign性能调优</h3><p>Feign底层的客户端实现:</p><ul><li>URLConnection:默认实现,不支持连接池</li><li>Apache HttpClient:支持连接池</li><li>OKHttp:支持连接池<br>因此优化Feign的性能主要包括:<br>使用连接池代替默认的URLConnection日志级别,最好用basic或none</li></ul><ol><li>引入依赖</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><!--httpClient的依赖--></span><br><span class="line"> <dependency></span><br><span class="line"> <groupId>io.github.openfeign</groupId></span><br><span class="line"> <artifactId>feign-httpclient</artifactId></span><br><span class="line"> </dependency></span><br></pre></td></tr></table></figure><ol start="2"><li>设置配置</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">feign:</span><br><span class="line"> client:</span><br><span class="line"> config:</span><br><span class="line"> <span class="keyword">default</span>:</span><br><span class="line"> loggerLevel: FULL</span><br><span class="line"> httpclient: #配置连接池</span><br><span class="line"> enabled: <span class="literal">true</span> #开启feign对HttpClient的支持</span><br><span class="line"> max-connections: <span class="number">200</span> #最大连接数</span><br><span class="line"> max-connections-per-route: <span class="number">50</span> #每一个路经的最大连接数</span><br></pre></td></tr></table></figure><blockquote><p>Feign的优化:<br>1.日志级别尽量用basic<br>2.使用HttpClient或OKHttp代替URLConnection引入feign-httpClient依赖,配置文件开启httpClient功能,设置连接池参数</p></blockquote><ol start="3"><li>Feign的最佳实践:</li></ol><ul><li>让controller和FeignClient继承同一接口</li><li>将FeignClient、POJO、Feign的默认配置都定义到一个项目中,供所有消费者使用</li></ul><ol start="4"><li>当定义的FeignClient不在SpringBootApplication的扫描包范围时,这些FeignClient无法使用。有两种方式解决:</li></ol><ul><li>方式一:指定FeignClient所在包</li></ul> <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@EnableFeignClients(basePackages ="cn.itcast.feign.clients")</span></span><br></pre></td></tr></table></figure><ul><li>方式二:指定FeignClient字节码</li></ul> <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GEnableFeignClients(clients={UserClient.class})</span><br></pre></td></tr></table></figure><h2 id="10-Gateway网关">10.Gateway网关</h2><ul><li><p>网关的作用:<br>1,对用户请求做身份认证、权限校验<br>2,将用户请求路由到微服务,并实现负载均衡<br>3,对用户请求做限流</p></li><li><p>搭建网关服务:<br>网关本身也属于一个微服务,因此需要注册到Nacos服务发现中</p></li></ul><p>1、新建一个微服务,引入依赖</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><!--网关依赖--></span><br><span class="line"><dependency></span><br><span class="line"> <groupId>org.springframework.cloud</groupId></span><br><span class="line"> <artifactId>spring-cloud-starter-gateway</artifactId></span><br><span class="line"> </dependency></span><br><span class="line"><!--nacos服务发现依赖--></span><br><span class="line"><dependency></span><br><span class="line"> <groupId>com.alibaba.cloud</groupId></span><br><span class="line"> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></span><br><span class="line"></dependency></span><br></pre></td></tr></table></figure><p>2、配置路由,和nacos地址</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">server:</span><br><span class="line"> port: <span class="number">10010</span></span><br><span class="line">spring:</span><br><span class="line"> application:</span><br><span class="line"> name: gateway</span><br><span class="line"> cloud:</span><br><span class="line"> nacos:</span><br><span class="line"> server-addr: localhost:<span class="number">8848</span> #nacos地址</span><br><span class="line"> gateway:</span><br><span class="line"> routes:</span><br><span class="line"> - id: user-service #路由标识,必须唯一</span><br><span class="line"> uri: lb:<span class="comment">//userService #路由的目标地址</span></span><br><span class="line"> predicates: #路由断言,判断请求是否符合规则</span><br><span class="line"> - Path=/user<span class="comment">/** #路径断言,判断路径是否是以/user开头,如果是则符合</span></span><br><span class="line"><span class="comment"> - id: order-service</span></span><br><span class="line"><span class="comment"> uri: lb://orderService</span></span><br><span class="line"><span class="comment"> predicates:</span></span><br><span class="line"><span class="comment"> - Path=/order/**</span></span><br></pre></td></tr></table></figure><p>3、流程:<br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/11.png" alt="11"></p><h3 id="路由断言工厂">路由断言工厂</h3><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/12.png" alt="12"></p><h3 id="过滤器">过滤器</h3><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/13.png" alt="13"></p><ol><li>全局过滤器 GlobalFilter<br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/14.png" alt="14"></li></ol><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/15.png" alt="15"></p><blockquote><p>全局过滤器的作用是什么?<br>1,对所有路由都生效的过滤器,并且可以自定义处理逻辑<br>实现全局过滤器的步骤?<br>1,实现GlobalFilter接口<br>2,添加@Order注解或实现Ordered接口<br>3,编写处理逻辑</p></blockquote><p>4、过滤器执行顺序</p><blockquote><p>路由过滤器、defaultFilter、全局过滤器的执行顺序?<br>1,order值越小,优先级越高<br>2,当order值一样时,顺序是defaultFilter最先,然后是局部的路由过滤器,最后是全局过滤器</p></blockquote><p>5、网关的CORS跨域配置</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">globalcors:</span> <span class="comment"># 全局的跨域处理</span></span><br><span class="line"> <span class="attr">add-to-simple-url-handler-mapping:</span> <span class="literal">true</span> <span class="comment"># 解决options请求被拦截问题</span></span><br><span class="line"> <span class="attr">corsConfigurations:</span></span><br><span class="line"> <span class="string">'[/**]'</span><span class="string">:</span></span><br><span class="line"> <span class="attr">allowedOrigins:</span> <span class="comment"># 允许哪些网站的跨域请求</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">"http://localhost:8090"</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">"http://www.leyou.com"</span></span><br><span class="line"> <span class="attr">allowedMethods:</span> <span class="comment"># 允许的跨域ajax的请求方式</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">"GET"</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">"POST"</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">"DELETE"</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">"PUT"</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">"OPTIONS"</span></span><br><span class="line"> <span class="attr">allowedHeaders:</span> <span class="string">"*"</span> <span class="comment"># 允许在请求中携带的头信息</span></span><br><span class="line"> <span class="attr">allowCredentials:</span> <span class="literal">true</span> <span class="comment"># 是否允许携带cookie</span></span><br><span class="line"> <span class="attr">maxAge:</span> <span class="number">360000</span> <span class="comment"># 这次跨域检测的有效期</span></span><br></pre></td></tr></table></figure><h2 id="11-Docker">11.Docker</h2><h3 id="原理">原理</h3><p>1、Docker是一个快速交付应用、运行应用的技术:</p><ol><li>可以将程序及其依赖、运行环境一起打包为一个镜像可以迁移到任意Linux操作系统</li><li>运行时利用沙箱机制形成隔离容器,各个应用互不干扰</li><li>启动、移除都可以通过一行命令完成,方便快捷<br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/16.png" alt="16"></li></ol><h3 id="镜像与容器">镜像与容器</h3><p><em>镜像(Image)</em>: Docker将应用程序及其所需的依赖、函数库、环境、配置等文件打包在一起,称为镜像。<br><em>容器(Container)</em>: 镜像中的应用程序运行后形成的进程就是<em>容器</em>,只是Docker会给容器做隔离,对外不可见。<br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/17.png" alt="17"></p><h3 id="Docker架构">Docker架构</h3><p>Docker是一个CS架构的程序,由两部分组成:</p><ul><li>服务端(server):Docker守护进程,负责处理Docker指令,管理镜像、容器等</li><li>客户端(client):通过命令或RestAPI向Docker服务端发送指令。可以在本地或远程向服务端发送指令<br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/18.png" alt="18"></li></ul><blockquote><p>1,镜像:<br>将应用程序及其依赖、环境、配置打包在一起</p><p>2,容器<br>镜像运行起来就是容器,一个镜像可以运行多个容器</p><p>3,Docker结构:<br>服务端:接收命令或远程请求,操作镜像或容器客户端:发送命令或者请求到Docker服务端</p><p>4,DockerHub :<br>一个镜像托管的服务器,类似的还有阿里云镜像服务,统称为DockerRegistry</p></blockquote><h3 id="Docker镜像命令">Docker镜像命令</h3><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/19.png" alt="19"></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">systemctl start docker <span class="comment">//启动Docker</span></span><br><span class="line">docker pull 服务名 <span class="comment">//拉取镜像</span></span><br><span class="line">docker images <span class="comment">//查看镜像</span></span><br><span class="line">docker rmi <span class="comment">//删除</span></span><br><span class="line">docker push <span class="comment">//推送</span></span><br><span class="line">docker save <span class="comment">//保存镜像到本地</span></span><br><span class="line">docker load <span class="comment">//读取本地镜像文件</span></span><br></pre></td></tr></table></figure><h3 id="Docker容器命令">Docker容器命令</h3><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/20.png" alt="20"></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">docker run <span class="comment">//创建并启动容器</span></span><br><span class="line">docker ps <span class="comment">//查看运行中的容器</span></span><br><span class="line">docker stop <span class="comment">//停止容器</span></span><br><span class="line">docker start <span class="comment">//启动容器</span></span><br><span class="line">docker restart <span class="comment">//重启容器</span></span><br><span class="line">docker rm <span class="comment">//删除容器</span></span><br><span class="line">docker exec <span class="comment">//进入容器</span></span><br><span class="line">docker attach <span class="comment">//进入容器</span></span><br><span class="line">docker logs <span class="comment">//查看日志</span></span><br><span class="line">docker top <span class="comment">//查看容器中运行的进程</span></span><br><span class="line">docker inspect <span class="comment">//查看容器内部细节</span></span><br></pre></td></tr></table></figure><p><em>docker run --name containerName -p 80:80 -d nginx</em><br>命令解读:</p><ul><li>docker run:创建并运行一个容器</li><li>–name:给容器起一个名字,比如叫做mn</li><li>-p:将宿主机端口与容器端口映射,冒号左侧是宿主机端口,右侧是容器端口</li><li>-d:后台运行容器</li><li>nginx:镜像名称,例如nginx</li></ul><p><em>docker exec -it mn bash</em><br>命令解读:</p><ul><li>docker exec:进入容器内部,执行一个命令</li><li>-it:给当前进入的容器创建一个标准输入、输出终端,允许我们与容器交互</li><li>mn:要进入的容器的名称</li><li>bash:进入容器后执行的命令,bash是一个linux终端交互命令</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">docker logs -f 镜像名 <span class="comment">//持续跟踪日志</span></span><br><span class="line"><span class="comment">//进入容器并进行交互 </span></span><br><span class="line">docker exec -it mn bash</span><br><span class="line"><span class="comment">//进入nginx主页文件夹 </span></span><br><span class="line">cd /usr/share/nginx/html</span><br><span class="line"><span class="comment">//容器内安装Vim编辑器</span></span><br><span class="line">apt get update && apt get install vim</span><br><span class="line"><span class="comment">//查看容器状态:</span></span><br><span class="line">docker ps -a <span class="comment">//添加-a参数查看所有状态的容器删除容器:</span></span><br><span class="line">docker rm -f <span class="comment">//不能删除运行中的容器,除非添加-f参数进入容器:</span></span><br><span class="line">docker exec-t[容器名][要执行的命令]exec命令可以进入容器修改文件,但是在容器内修改文件是不推荐的</span><br><span class="line"><span class="comment">//创建redis容器</span></span><br><span class="line">docker run --name mr -p <span class="number">6379</span>:<span class="number">6379</span> -d redis redis-server --appendonly yes</span><br><span class="line"><span class="comment">//进入容器并进行交互 </span></span><br><span class="line">docker exec -it mr bash/redis-cli </span><br></pre></td></tr></table></figure><h3 id="Docket数据卷命令">Docket数据卷命令</h3><p>数据卷:是一个虚拟目录,指向宿主机文件系统中的某个目录<br>作用:将容器与数据分离,解耦合,方便操作容器内数据,保证数据安全<br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/21.png" alt="21"></p><p>1、常见数据卷命令</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//创建数据卷</span></span><br><span class="line"> docker volume creat [数据卷名称]</span><br><span class="line"><span class="comment">//显示一个或多个volume的信息</span></span><br><span class="line"> docker volume inspect</span><br><span class="line"><span class="comment">//列出所有的volume</span></span><br><span class="line"> docker volume ls</span><br><span class="line"><span class="comment">//删除未使用的volume</span></span><br><span class="line"> docker volume prune</span><br><span class="line"><span class="comment">//删除一个或多个指定的volume</span></span><br><span class="line"> docker volume rm [数据卷名称]</span><br></pre></td></tr></table></figure><p>2、挂载数据卷并与容器相连接</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">docker run: 就是创建并运行容器</span><br><span class="line">--name mn: 给容器起个名字叫mn</span><br><span class="line">-v html:/root/htm: 把html数据卷挂载到容器内的/root/html这个目录中</span><br><span class="line">-p <span class="number">8080</span>:<span class="number">80</span>: 把宿主机的<span class="number">8080</span>端口映射到容器内的<span class="number">80</span>端口</span><br><span class="line">nginx: 镜像名称</span><br><span class="line">docker run --name mn -p <span class="number">80</span>:<span class="number">80</span> -v html:/usr/share/nginx/html -d nginx</span><br><span class="line"><span class="comment">//如果数据卷不存在,docker会自动创建数据卷,不用刻意去创建数据卷</span></span><br><span class="line"> </span><br><span class="line"><span class="comment">//创建并运行mysql容器</span></span><br><span class="line">docker run \</span><br><span class="line"> --name mysql \</span><br><span class="line"> -e MYSQL_ROOT_PASSWORD=<span class="number">123</span> \</span><br><span class="line"> -p <span class="number">3306</span>:<span class="number">3306</span> \</span><br><span class="line"> -v /tmp/mysql/conf/hmy.cnf:/etc/mysql/conf.d/hmy.cnf \</span><br><span class="line"> -v /tmp/mysql/data:/<span class="keyword">var</span>/lib/mysql \</span><br><span class="line"> -d \</span><br><span class="line"> mysql:<span class="number">5.7</span><span class="number">.25</span></span><br></pre></td></tr></table></figure><p>数据卷挂载方式对比<br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/22.png" alt="22"></p><ol><li>docker run的命令中通过-v参数挂载文件或目录到容器中:<br>-v volume名称:容器内目录<br>-v宿主机文件:容器内文件<br>-v宿主机目录:容器内目录</li><li>数据卷挂载与目录直接挂载的</li></ol><ul><li>数据卷挂载耦合度低,由docker来管理目录,但是目录较深,不好找</li><li>目录挂载耦合度高,需要我们自己管理目录,不过目录容易寻找查看</li></ul><h3 id="镜像结构">镜像结构</h3><p>镜像是分层结构,每一层称为一个Layer</p><ol><li>Baselmage层:包含基本的系统函数库、环境变量、文件系统</li><li>Entrypoint:入口,是镜像中应用启动的命令</li><li>其它:在Baselmage基础上添加依赖、安装程序、完成整个应用的安装和配置</li></ol><h3 id="自定义镜像">自定义镜像</h3><p>Dockerfile就是一个文本文件,其中包含一个个的指令(Instruction),用指令来说明要执行什么操作来构建镜像。每<br>-个指令都会形成一层Layer。<br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/23.png" alt="23"></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span>Dockerfile的本质是一个文件,通过指令描述镜像的构建过程</span><br><span class="line"><span class="number">2.</span>Dockerfile的第一行必须是FROM,从一个基础镜像来构建</span><br><span class="line"><span class="number">3.</span>基础镜像可以是基本操作系统,如Ubuntu。也可以是其他人制作好的镜像,例如:java:<span class="number">8</span>-alpine</span><br><span class="line">update user set authentication string=password(<span class="string">'123'</span>) where user=<span class="string">'985211'</span></span><br></pre></td></tr></table></figure><h3 id="DockerCompose">DockerCompose</h3><ol><li>Docker Compose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器</li><li>Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">systemctl start docker <span class="comment">//启动Docker</span></span><br><span class="line">docker-compose up -d nacos <span class="comment">//优先启动nacos注册中心</span></span><br></pre></td></tr></table></figure><h3 id="Docker镜像仓库">Docker镜像仓库</h3><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/24.png" alt="24"></p><ol><li>推送本地镜像到仓库前都必须重命名(docker tag)镜像,以镜像仓库地址为前缀</li><li>镜像仓库推送前需要把仓库地址配置到docker服多的daemon.json文件中,被docker信任</li><li>推送使用docker push命令</li><li>拉取使用docker pull命令</li></ol><h2 id="12-异步通信">12.异步通信</h2><p>基于Feign同步调用:<br>同步调用的优点:</p><ul><li>时效性较强,可以立即得到结果</li></ul><p>同步调用的问题:</p><ul><li>耦合度高</li><li>性能和吞吐能力下降有额外的资源消耗</li><li>有级联失败问题</li></ul><p>异部调用:</p><ul><li>也就是说只有支付成功后请求才会被发送到这个服务,如果支付失败,在第一步调用接口时就会返回失败</li><li>这里要表示的就是,用户只关心支付成功没有,也就是说只关心第一步成功没有</li><li>至于后面的订单或者是短信通知相对来说不重要了,因为用户知道钱已经给了,如果有问题就再说<br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/25.png" alt="25"></li></ul><p>异步通信的优点:</p><ol><li>耦合度低</li><li>吞吐量提升</li><li>故障隔离</li><li>流量削峰<br>异步通信的缺点:</li><li>依赖于Broker的可靠性、安全性、吞吐能力</li><li>架构复杂了,业务没有明显的流程线,不好追踪管理</li></ol><p>大多数情况下用的是同步通讯</p><h2 id="13-消息队列(MQ)">13.消息队列(MQ)</h2><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/26.png" alt="26"></p><h3 id="RabbitMQ">RabbitMQ</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//安装</span></span><br><span class="line"><span class="number">1</span>,docker pull rabbitmq</span><br><span class="line"><span class="comment">//运行mq</span></span><br><span class="line">docker run \</span><br><span class="line"> -e RABBITMQ_DEFAULT_USER=iTddey \</span><br><span class="line"> -e RABBITMQ_DEFAULT_PASS=<span class="number">123321</span> \</span><br><span class="line"> --name mq \</span><br><span class="line"> --hostname mq1 \</span><br><span class="line"> -p <span class="number">15672</span>:<span class="number">15672</span> \</span><br><span class="line"> -p <span class="number">5672</span>:<span class="number">5672</span> \</span><br><span class="line"> -d \</span><br><span class="line"> rabbitmq:latest</span><br><span class="line"> <span class="comment">//进入容器内部</span></span><br><span class="line"> docker exec -it mq /bin/bash</span><br><span class="line"> <span class="comment">//步骤二:开启web界面管理插件 </span></span><br><span class="line"> rabbitmq-plugins enable rabbitmq_management</span><br></pre></td></tr></table></figure><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/27.png" alt="27"></p><h3 id="常见消息模型">常见消息模型</h3><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/28.png" alt="28"></p><p>基本消息队列的消息发送流程:</p><ol><li>建立connection</li><li>创建channel</li><li>利用channel声明队列</li><li>利用channel向队列发送消息</li></ol><p>基本消息队列的消息接收流程:</p><ol><li>建立connection</li><li>创建channel</li><li>利用channel声明队列</li><li>定义consumer的消费行为handleDelivery()</li><li>利用channel将消费者与队列绑定</li></ol><h3 id="SpringAMQP">SpringAMQP</h3><ol><li>基本队列BasicQueue</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//1,父类中引依赖</span></span><br><span class="line"><!--AMQP依赖,包含RabbitMQ--></span><br><span class="line"> <dependency></span><br><span class="line"> <groupId>org.springframework.boot</groupId></span><br><span class="line"> <artifactId>spring-boot-starter-amqp</artifactId></span><br><span class="line"> </dependency></span><br><span class="line"><span class="comment">//2,导入配置</span></span><br><span class="line">spring:</span><br><span class="line"> rabbitmq:</span><br><span class="line"> host: <span class="number">192.168</span><span class="number">.50</span><span class="number">.80</span></span><br><span class="line"> port: <span class="number">5672</span></span><br><span class="line"> username: iTddey</span><br><span class="line"> password: <span class="number">123321</span></span><br><span class="line"> virtual-host: /</span><br><span class="line"><span class="comment">//3,编写消息发送测试类</span></span><br><span class="line"><span class="meta">@RunWith(SpringRunner.class)</span></span><br><span class="line"><span class="meta">@SpringBootTest</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SpringAMQPTest</span> {</span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> RabbitTemplate rabbitTemplate;</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_">testSimpleQueue</span><span class="params">()</span>{</span><br><span class="line"> <span class="type">String</span> <span class="variable">queueName</span> <span class="operator">=</span> <span class="string">"simple.queue"</span>;</span><br><span class="line"> <span class="type">String</span> <span class="variable">message</span> <span class="operator">=</span> <span class="string">"hello,spring amqp"</span>;</span><br><span class="line"> rabbitTemplate.convertAndSend(queueName,message);</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="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SpringRabbitListener</span> {</span><br><span class="line"> <span class="meta">@RabbitListener(queues = "simple.queue")</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">listenSimpleQueueMessage</span><span class="params">(String msg)</span> <span class="keyword">throws</span> InterruptedException {</span><br><span class="line"> System.out.println(<span class="string">"spring消费者接收到消息︰【"</span> + msg + <span class="string">"】 "</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>SpringAMQP如何接收消息?</p><ul><li>引入amqp的starter依赖</li><li>配置RabbitMQ地址</li><li>定义类,添加@Component注解</li><li>类中声明方法,添加@RabbitListener注解,方法参数接收消息</li><li>注意:消息一旦消费就会从队列删除,RabbitMQ没有消息回溯功能</li></ul><ol start="2"><li>工作队列WorkQueue</li></ol><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/29.png" alt="29"></p><p>消息预取机制:修改消费者服务yml配置文件中的preFetch的值,可以设置预取消息的上限</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">spring:</span><br><span class="line"> rabbitmq:</span><br><span class="line"> host: <span class="number">192.168</span><span class="number">.50</span><span class="number">.80</span> #主机名</span><br><span class="line"> port: <span class="number">5672</span> #端口</span><br><span class="line"> username: iTddey #用户名</span><br><span class="line"> password: <span class="number">123321</span> #密码</span><br><span class="line"> virtual-host: / #虚拟主机</span><br><span class="line"> listener:</span><br><span class="line"> direct:</span><br><span class="line"> prefetch: <span class="number">1</span> #每次只能获取一条消息,处理完成才能获取下一个消息</span><br></pre></td></tr></table></figure><h4 id="Publish,Subscribe-发布,订阅模型">Publish,Subscribe(发布,订阅模型)</h4><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/30.png" alt="30"></p><h5 id="Fanou-Exchange-广播">Fanou Exchange 广播</h5><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/31.png" alt="31"><br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/32.png" alt="32"><br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/33.png" alt="33"></p><blockquote><p>交换机的作用是什么?</p><ol><li>接收publisher发送的消息</li><li>将消息按照规则路由到与之绑定的队列</li><li>不能缓存消息,路由失败,消息丢失</li><li>FanoutExchange的会将消息路由到每个绑定的队列</li></ol><p>声明队列、交换机、绑定关系的Bean是什么?</p><ol><li>Queue</li><li>FanoutExchange</li><li>Binding</li></ol></blockquote><h5 id="Direct-Exchange-路由">Direct Exchange 路由</h5><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/34.png" alt="34"><br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/35.png" alt="35"></p><blockquote><p>描述下Direct交换机与Fanout交换机的差异?</p><ol><li>Fanout交换机将消息路由给每一个与之绑定的队列</li><li>Direct交换机根据RoutingKey判断路由给哪个队列</li><li>如果多个队列具有相同的RoutingKey,则与Fanout功能类似</li></ol><p>基于@RabbitListener注解声明队列和交换机有哪些常见注解?</p><ol><li>@Queue</li><li>@Exchange</li></ol></blockquote><h5 id="Topic-Exchange-话题">Topic Exchange 话题</h5><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/SpringCloud/36.png" alt="36"></p><h4 id="消息转换器">消息转换器</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//父工程引入依赖</span></span><br><span class="line"><!--Json转换器--></span><br><span class="line"> <dependency></span><br><span class="line"> <groupId>com.fasterxml.jackson.core</groupId></span><br><span class="line"> <artifactId>jackson-databind</artifactId></span><br><span class="line"> </dependency></span><br></pre></td></tr></table></figure><blockquote><p>SpringAMQP中消息的序列化和反序列化是怎么实现的?</p><p>利用MessageConverter实现的,默认是JDK的序列化</p><p>注意发送方与接收方必须使用相同的Messageconverter</p></blockquote>]]></content>
<categories>
<category> 微服务 </category>
</categories>
<tags>
<tag> 微服务 </tag>
</tags>
</entry>
<entry>
<title>Spring全家桶总揽</title>
<link href="/posts/1e7ff688.html"/>
<url>/posts/1e7ff688.html</url>
<content type="html"><![CDATA[<h1>区别</h1><h2 id="Spring">Spring</h2><h2 id="Spring-Boot">Spring Boot</h2><h2 id="Spring-MVC">Spring MVC</h2>]]></content>
<categories>
<category> Spring全家桶 </category>
</categories>
<tags>
<tag> Spring </tag>
<tag> Spring Boot </tag>
<tag> Spring MVC </tag>
</tags>
</entry>
<entry>
<title>Java基础</title>
<link href="/posts/a03a840d.html"/>
<url>/posts/a03a840d.html</url>
<content type="html"><![CDATA[<h1>Java基础</h1><h2 id="面向对象">面向对象</h2><ul><li>所谓的面向对象,其实就是分析问题时,以问题所涉及到的事或物为中心的分析方式<br>类和对象:</li><li>类表示归纳和整理</li><li>对象就表示具体的事物</li></ul><h3 id="类与对象">类与对象</h3><ol><li>类是抽象的,对象是具体的</li><li>类是模子,对象是具体的实例</li><li>类是静态的,对象是动态的</li><li>类的创建过程<ul><li>先声明类</li><li>创建对象</li><li>声明网性,所说的属性其实就是类中的变最变航类型变航名称 =变值属性类型性名称 = 属性値</li><li>声明方法</li><li>void 方法名(参数){ 功能代码 }</li><li>执行方法<ul><li>对象.属性</li><li>对象.方法名()<br>总结:</li></ul></li></ul></li><li>static修饰的成员方法叫什么?如何使用?<ul><li>类方法(静态方法)</li><li>属于类,可以直接用类名访问,也可以用对象访问<br>使用:类名.类方法</li></ul></li><li>无static修饰的成员方法叫什么?如何使用?<ul><li>实例方法(对象的方法)</li><li>属于对象,只能用对象访问<br>使用方法:对象.实例方法</li></ul></li></ol><blockquote><p>注意事项</p><ul><li>类方法中可以直接访问类的成员,不可以直接访问实例成员。</li><li>实例方法中既可以直接访问类成员,也可以直接访问实例成员。</li><li>实例方法中可以出现this关键字,类方法中不可以出现this关键字的。</li></ul></blockquote><h3 id="代码块">代码块</h3><p>代码块是类的5大成分之一(成员变量、构造器、方法、代码块、内部类)<br>代码块分为两种:</p><ol><li>静态代码块:<br>格式:static{}<br>特点:类加载时自动执行,由于类只会加载一次,所以静态代码块也只会执行一次。<br>作用:完成类的初始化,例如:对类变量的初始化赋值。</li><li>实例代码块:<br>格式:{}<br>特点:每次创建对象时,执行实例代码块,并在构造器前执行。<br>作用:和构造器一样,都是用来完成对象的初始化的,例如:对实例变量进行初始化赋值。</li></ol><h3 id="构造器">构造器</h3><p>构造器是类的5大成分之一(成员变量、构造器、方法、代码块、内部类)<br>构造器的作用:</p><ol><li>创建对象</li><li>完成对象的初始化</li><li>构造器没有返回值,连void都不写</li><li>构造器的名称必须和类名完全一样</li><li>构造器可以有参数,因此可以发生重载</li><li>一旦定义了构造器,有默认的构造器,如果没有显示定义,则系统会自动创建一个无参的构造器。</li><li>构造器内不能使用return返回数据。</li><li>一旦显示定义了构造器,系统就不再提供默认的无参构造器。</li></ol><h3 id="构造器与代码块的区别">构造器与代码块的区别</h3><ol><li>执行顺序:<ul><li>代码块在构造器之前执行</li><li>构造器在代码块之后执行</li></ul></li><li>作用:<ul><li>代码块可以完成对象的初始化,例如:对实例变量进行初始化赋值</li><li>构造器可以完成对象的初始化,例如:对类变量的初始化赋值</li></ul></li></ol><h3 id="内存模型">内存模型</h3><ol><li>栈(stack):存放局部变量,方法参数,对象的引用</li><li>堆(heap):存放new出来的对象</li><li>方法区(method area):存放类的信息,常量,静态变量</li><li>程序计数器(program counter):记录当前线程执行到哪一行代码<br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/1.png" alt="1"></li></ol><h3 id="StringAPI">StringAPI</h3><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/2.png" alt="2"></p><h3 id="继承">继承</h3><ol><li>继承是面向对象三大特征之一</li><li>继承是类与类之间的关系</li><li>继承的特点:<ul><li>子类拥有父类的所有成员(成员变量和方法)</li><li>子类可以拥有自己的成员</li><li>子类可以对父类继承的成员进行扩展,重写</li><li>子类可以继承父类的属性和行为,但是子类不能继承父类的构造器,</li><li>Java是单继承模式:一个类只能继承一个直接父类。</li><li>Java不支持多继承、但是支持多层继承</li></ul></li><li>继承的语法:<ul><li>子类继承父类,使用extends关键字</li></ul></li></ol><blockquote><ol><li><p>在子类方法中访问成员(成员变量、成员方法)满足:</p><ul><li>就近原则,子类没有找子类、子类没有找父类、父类没有就报错!</li></ul></li><li><p>如果子父类中出现了重名的成员,此时如果一定要在子类中使用父类的怎么办?</p><ul><li>格式: super.父类成员变量/父类成员方法</li></ul></li><li><p>this关键字是什么?</p><ul><li>出现在构造器和成员方法中,代表当前对象的地址</li></ul></li><li><p>this关键字在构造器中、成员方法中可以做什么?</p><ul><li>可以用于指定访问当前对象的成员。</li></ul></li><li><p>子类继承父类后构造器的特点:</p><ul><li>子类中所有的构造器默认都会先访问父类中无参的构造器,再执行自己。</li></ul></li><li><p>为什么?</p><ul><li>子类在初始化的时候,有可能会使用到父类中的数据,如果父类没有完成初始化,子类将无法使用父类的数据。</li><li>子类初始化之前,一定要调用父类构造器先完成父类数据空间的初始化。</li></ul></li><li><p>怎么调用父类构造器的?</p><ul><li>子类构造器的第一行语句默认都是:super(),不写也存在。</li></ul></li><li><p>this(…)和super(…)使用注意点:</p><ul><li>子类通过 this (.)去调用本类的其他构造器,本类其他构造器会通过 super 去手动调用父类的构造器,最终还是会调用父类构造器的。</li><li>注意:this(…)super(…)都只能放在构造器的第一行,所以二者不能共存在同一个构造器中。<br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/3.png" alt="3"></li></ul></li></ol></blockquote><h3 id="方法重写">方法重写</h3><ol><li>什么是方法重写?<br>在继承体系中,子类出现了和父类中一模一样的方法声明,我们就称子类这个方法是重写的方法。</li><li>方法重写的应用场景<br>当子类需要父类的功能,但父类的该功能不完全满足自己的需求时<br>子类可以重写父类中的方法。</li><li>案例演示:<br>旧手机的功能只能是基本的打电话,发信息<br>新手机的功能需要能够:基本的打电话下支持视频通话。基本的发信息下支持发送语音和图片。</li></ol><blockquote><p>@Override重写注解</p><ul><li>@Override是放在重写后的方法上,作为重写是否正确的校验注解。</li><li>加上该注解后如果重写错误,编译阶段会出现错误提示。</li><li>建议重写方法都加@Override注解,代码安全,优雅!</li></ul><p>方法重写注意事项和要求</p><ul><li>重写方法的名称、形参列表必须与被重写方法的名称和参数列表一致。</li><li>私有方法不能被重写。<br>子类重写父类方法时,访问权限必须大于或者等于父类<br>暂时了解:缺省 < protected < public子类不能重写父类的静态方法,如果重写会报错的。</li></ul></blockquote><ol start="5"><li>方法重写是什么样的?<ul><li>子类写一个与父类申明一样的方法覆盖父类的方法。</li></ul></li><li>方法重写建议加上哪个注解,有什么好处?<ul><li>@Override注解可以校验重写是否正确,同时可读性好</li></ul></li><li>重写方法有哪些基本要求?<ul><li>重写方法的名称和形参列表应该与被重写方法一致。</li><li>私有方法不能被重写。</li><li>子类重写父类方法时,访问权限必须大于或者等于父类被重写的方法的权限</li></ul></li></ol><h3 id="封装">封装</h3><ol><li>如何进行封装更好?<br>一般建议对成员变量使用private(私有、隐藏)关键字修饰进(private修饰的成员只能在当前类中访问)为每个成员变量提供配套public修饰的的getter、setter方法暴露<br>其取值和赋值</li></ol><h3 id="ArrList集合">ArrList集合</h3><ul><li>ArrayList是集合中的一种,它支持索引</li><li>ArrayList集合中存放的是对象的地址</li></ul><ol><li>ArrayList集合的对象获取</li></ol><table><thead><tr><th>构造器</th><th>说明</th></tr></thead><tbody><tr><td>public ArrayList()</td><td>创建一个新的ArrList集合</td></tr></tbody></table><ol start="2"><li>ArrayList集合的常用方法</li></ol><table><thead><tr><th>方法名</th><th>说明</th></tr></thead><tbody><tr><td>public boolean add(E e)</td><td>向集合中添加元素</td></tr><tr><td>public E remove(int index)</td><td>删除指定索引位置的元素</td></tr><tr><td>public E get(int index)</td><td>获取指定索引位置的元素</td></tr><tr><td>public int size()</td><td>获取集合中元素的个数</td></tr><tr><td>public boolean contains(E e)</td><td>判断集合中是否包含指定元素</td></tr><tr><td>public void clear()</td><td>清空集合中所有的元素</td></tr><tr><td>public boolean isEmpty()</td><td>判断集合是否为空</td></tr><tr><td>public int indexOf(E e)</td><td>获取指定元素在集合中第一次出现的索引位置</td></tr><tr><td>public int lastIndexOf(E e)</td><td>获取指定元素在集合中最后一次出现的索引位置</td></tr><tr><td>public E set(int index, E e)</td><td>修改指定索引位置的元素</td></tr><tr><td>public E[] toArray()</td><td>将集合转换为数组</td></tr></tbody></table><ol start="3"><li>ArrayList集合的遍历</li></ol><table><thead><tr><th>方法名</th><th>说明</th></tr></thead><tbody><tr><td>public Iterator<E> iterator()</td><td>获取集合的迭代器</td></tr></tbody></table><ol start="4"><li>ArrayList集合的常用遍历方式<ul><li>迭代器遍历</li><li>增强for循环遍历</li></ul></li></ol><h3 id="final">final</h3><ol><li>final 修饰类,不能被继承,例如工具类</li><li>final 修饰方法,方法不能被继重写</li><li>final 修饰变量,变量有且只能被赋值一次</li></ol><blockquote><p>注意:<br>final修饰的变量是基本类型:那么变量存储的数据值不能发生改变。<br>final修饰的变量是引用类型:那么变量存储的地址值不能发生改变,但是地址指向的对象内容是可以发生变化的</p></blockquote><h3 id="常量">常量</h3><ol><li>常量是使用了public static final修饰的变量,必须有初始值,而且执行过程中其值不发生改变</li><li>作用以及好处:<ul><li>可以提高程序的可读性</li><li>提高程序的安全性</li><li>方便维护</li></ul></li><li>命名规范:英文单词全部大写,多个单词下划线进行连接</li><li>执行过程:<ul><li>编译阶段:常量名会存入到class文件中,编译阶段常量名会替换成常量值</li><li>运行阶段:常量值会存入到内存中,运行阶段常量值不会发生改变</li></ul></li></ol><h3 id="枚举">枚举</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//修饰符 enum 枚举名{}</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">enum</span> <span class="title class_">Season</span>{</span><br><span class="line"> <span class="comment">//罗列枚举的实例名称</span></span><br><span class="line"> SPRING,SUMMER,AUTUMN,WINTER;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>枚举类都是继承了枚举类型:java.lang.Enum</li><li>枚举都是最终类,不可以被继承。</li><li>构造器的构造器都是私有的,枚举对外不能创建对象。</li><li>枚举类的第一行默认都是罗列枚举对象的名称的。</li><li>枚举类相当于是多例模式</li></ul><h3 id="抽象类">抽象类</h3><ol><li>抽象类是使用abstract修饰的类,抽象类中可以包含抽象方法</li><li>抽象类不能被实例化,抽象类可以包含非抽象方法</li><li>抽象类可以包含抽象方法,也可以包含非抽象方法</li><li>抽象类可以包含构造器,抽象类的构造器是用来初始化成员变量</li><li>抽象类不能使用final修饰,因为抽象类是要被继承的</li><li>抽象类中可以包含静态方法,静态方法可以被继承</li></ol><blockquote><p>注意事项</p><ul><li>抽象方法只能有方法签名不能有方法体</li><li>一个类中如果包含抽象方法,那么该类必须是抽象类</li><li>类有的成员(成员变量、方法、构造器)抽象类都具备</li><li>抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类</li><li>一个类继承了抽象类必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类</li><li>不能用abstract修饰变量、代码块、构造器。</li></ul></blockquote><ol><li>抽象类、抽象方法是什么样的?<ul><li>都是用abstract修饰的;抽象方法只有方法签名,不能写方法体。</li><li>一个类中定义了抽象方法,这个类必须声明成抽象类</li></ul></li><li>抽象类基本作用是啥?<ul><li>作为父类,用来被继承的。</li></ul></li><li>继承抽象类有哪些要注意?<ul><li>一个类如果继承了抽象类,那么这个类必须重写完抽象类的全部抽象方法否则这个类也必须定义成抽象类。</li></ul></li><li>final和abstract是什么关系?<ul><li>互斥关系</li><li>abstract定义的抽象类作为模板让子类继承,final定义的类不能被继承</li><li>抽象方法定义通用功能让子类重写,final定义的方法子类不能重写</li></ul></li></ol><h3 id="模板方法模式">模板方法模式</h3><ol><li>模板方法模式解决了什么问题?<ul><li>提高了代码的复用性</li><li>模板方法已经定义了通用结构,模板方法不能确定的部分定义成抽象方法,交给子类实现,因此,使用者只需要关心自己需要实现的功能即可。</li></ul></li></ol><h3 id="接口">接口</h3><ol><li>接口的命名格式:</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> interface 接口名 {</span><br><span class="line"> <span class="comment">// 常量</span></span><br><span class="line"> <span class="comment">// 抽象方法</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><ol start="2"><li><p>接口的用法</p><ul><li>接口是用来被类实现(implements)的,实现接口的类称为实现类。实现类可以理解成所谓的子类</li><li>接口可以被类单实现,也可以被多实现</li><li>一个类实现接口,必须重写完全部接口的全部抽象方法,否则这个类需要定义成抽象类</li></ul></li><li><p>小结</p><ul><li>类和类的关系:单继承,</li><li>类和接口的关系:多实现。</li><li>接口和接口的关系:多继承,一个接口可以同时继承多个接口</li></ul></li><li><p>接口多继承的作用</p><ul><li>规范合并,整合多个接口为同一个接口,便于子类实现。</li></ul></li></ol><h3 id="泛型">泛型</h3><ul><li>定义类、接口、方法时,同时声明了一个或者多个类型变量(如:<E>),称为泛型类、泛型接口,泛型方法、它们统称为泛型。</li><li>作用:泛型提供了在编译阶段约束所能操作的数据类型,并自动进行检查的能力!这样可以避免强制类型转换,及其可能出现的异常。</li><li>泛型的本质:把具体的数据类型作为参数传给类型变量。</li><li>泛型不支持基本数据类型,只能支持对象类型</li></ul><h3 id="API">API</h3><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/4.png" alt="4"></p><h4 id="Object">Object</h4><p>所有类都是Object类的子孙类,都可以使用Object类的方法</p><table><thead><tr><th>方法名</th><th>说明</th></tr></thead><tbody><tr><td>public boolean equals(Object obj)</td><td>判断当前对象与指定对象是否相等</td></tr><tr><td>public String toString()</td><td>返回当前对象的字符串表示</td></tr><tr><td>public Object clone()</td><td>对象克隆</td></tr></tbody></table><p>tostring存在的意义: toString()方法存在的意义就是为了被子类重写,以便返回对象具体的内容。<br>equals存在的意义: 直接比较两个对象的地址是否相同完全可以用“==”替代equals,equals存在的意义就是为了被子类重写,以便子类自己来定制比较规则(比如比较对象内容)</p><ol><li>Object中toString方法的作用是什么?存在的意义是什么?<ul><li>基本作用:返回对象的字符串形式,</li><li>存在的意义:让子类重写,以便返回子类对象的内容。</li></ul></li><li>Object中equals方法的作用是什么?存在的意义是什么?<ul><li>基本作用:默认是比较两个对象的地址是否相等,</li><li>存在的意义:让子类重写,以便用于比较对象的内容是否相同。</li></ul></li></ol><blockquote><p>浅克隆: 拷贝出的新对象,与原对象中的数据一模一样(引用类型拷贝的只是地址)<br>深克隆:对象中基本类型的数据直接拷贝,对象中的字符串数据拷贝的还是地址。对象中还包含的其他对象,不会拷贝地址,会创建新对象。</p></blockquote><h4 id="Objects">Objects</h4><p>Objects类是java.util包下的一个工具类,里面提供了很多静态方法,用来操作对象。</p><table><thead><tr><th>方法名</th><th>说明</th></tr></thead><tbody><tr><td>public static boolean equals(Object a, Object b)</td><td>判断两个对象是否相等</td></tr><tr><td>public static <T> T requireNonNull(T obj)</td><td>判断指定对象是否为null,如果为null,抛出异常</td></tr><tr><td>public static String toString(Object obj)</td><td>返回对象的字符串表示</td></tr><tr><td>public static boolean isNull(Object obj)</td><td>判断指定对象是否为null</td></tr><tr><td>public static boolean nonNull(Object obj)</td><td>判断指定对象是否不为null</td></tr><tr><td>public static int hashCode(Object obj)</td><td>返回指定对象的哈希值</td></tr></tbody></table><h4 id="包装类">包装类</h4><p>包装类就是把基本类型的数据包装成对象。</p><table><thead><tr><th>基本数据类型</th><th>对应的包装类</th></tr></thead><tbody><tr><td>byte</td><td>Byte</td></tr><tr><td>short</td><td>Short</td></tr><tr><td>int</td><td>Integer</td></tr><tr><td>long</td><td>Long</td></tr><tr><td>float</td><td>Float</td></tr><tr><td>double</td><td>Double</td></tr><tr><td>char</td><td>Character</td></tr><tr><td>boolean</td><td>Boolean</td></tr></tbody></table><p>自动拆箱: 基本类型的数据自动转换成包装类对象<br>自动装箱: 包装类对象自动转换成基本类型的数据</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">Integer</span> <span class="variable">a</span> <span class="operator">=</span> Interger.valueof(<span class="number">21</span>) </span><br><span class="line"><span class="comment">//自动装箱:把基本数据类型转换成数据对象</span></span><br><span class="line"> <span class="type">Integer</span> <span class="variable">a</span> <span class="operator">=</span> <span class="number">21</span> ; </span><br><span class="line"><span class="comment">//自动拆箱:把数据对象转换成基本数据类型</span></span><br><span class="line"> <span class="type">int</span> <span class="variable">a1</span> <span class="operator">=</span> a ;</span><br></pre></td></tr></table></figure><ol><li>包装类的其他操作<ul><li>可以把基本类型的数据转换成字符串类型</li><li>可以把字符串类型的数值转换成数值本身对应的数据类型</li></ul></li></ol><h4 id="Stringbuilder">Stringbuilder</h4><p>StringBuilder是一个可变的字符序列,可以对字符串进行拼接、插入、删除等操作。</p><table><thead><tr><th>方法名</th><th>说明</th></tr></thead><tbody><tr><td>public StringBuilder append(String str)</td><td>拼接字符串</td></tr><tr><td>public StringBuilder insert(int offset, String str)</td><td>在指定位置插入字符串</td></tr><tr><td>public StringBuilder delete(int start, int end)</td><td>删除指定位置的字符串</td></tr><tr><td>public StringBuilder reverse()</td><td>反转字符串</td></tr></tbody></table><table><thead><tr><th>构造器</th><th>说明</th></tr></thead><tbody><tr><td>public StringBuilder()</td><td>创建一个空的字符串构建器</td></tr><tr><td>public StringBuilder(String str)</td><td>创建一个指定字符串初始化的字符串构建器</td></tr></tbody></table><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">StringBulider</span> <span class="variable">sb</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">StringBulider</span>(<span class="string">"liujiale"</span>);</span><br><span class="line"><span class="comment">//拼接内容</span></span><br><span class="line">sb.append(<span class="number">21</span>);</span><br><span class="line">sb.append(<span class="string">"刘佳乐"</span>);</span><br><span class="line"><span class="comment">//链式拼接编程</span></span><br><span class="line">sb.append(<span class="number">21</span>).append(<span class="string">"刘佳乐"</span>);</span><br><span class="line"><span class="comment">//反转</span></span><br><span class="line">sb.reverse();</span><br><span class="line"><span class="comment">//返回字符串的长度</span></span><br><span class="line">sb.length();</span><br><span class="line"><span class="comment">//把StringBulider对象转为String对象</span></span><br><span class="line">sb.toString();</span><br></pre></td></tr></table></figure><ul><li>对于字符串相关的操作,如频繁的拼接、修改等,建议用StringBuidler,效率更高!</li><li>注意:如果操作字符串较少,或者不需要操作,以及定义字符串变量,还是建议用String。</li></ul><h4 id="StringBuffer">StringBuffer</h4><p>StringBuffer是一个可变的字符序列,可以对字符串进行拼接、插入、删除等操作。</p><table><thead><tr><th>方法名</th><th>说明</th></tr></thead><tbody><tr><td>public StringBuffer append(String str)</td><td>拼接字符串</td></tr><tr><td>public StringBuffer insert(int offset, String str)</td><td>在指定位置插入字符串</td></tr><tr><td>public StringBuffer delete(int start, int end)</td><td>删除指定位置的字符串</td></tr><tr><td>public StringBuffer reverse()</td><td>反转字符串</td></tr></tbody></table><blockquote><ul><li>StringBuffer的用法与StringBuilder是一模一样的</li><li>但 StringBuilder是线程不安全的 StringBuffer是线程安全的</li></ul></blockquote><h4 id="Math">Math</h4><p>Math类是java.lang包下的一个工具类,里面提供了很多静态方法,用来操作数学相关的数据。</p><table><thead><tr><th>方法名</th><th>说明</th></tr></thead><tbody><tr><td>public static int abs(int a)</td><td>返回指定整数的绝对值</td></tr><tr><td>public static double ceil(double a)</td><td>返回大于或等于指定双精度型数值的最小整数</td></tr><tr><td>public static double floor(double a)</td><td>返回小于或等于指定双精度型数值的最大整数</td></tr><tr><td>public static int max(int a, int b)</td><td>返回两个整数中较大的值</td></tr><tr><td>public static int min(int a, int b)</td><td>返回两个整数中较小的值</td></tr><tr><td>public static double pow(double a, double b)</td><td>返回第一个参数的第二个参数次幂</td></tr><tr><td>public static double random()</td><td>返回一个随机的小数,该随机数大于等于0.0,小于1.0</td></tr><tr><td>public static int round(float a)</td><td>返回最接近指定浮点型数值的整数</td></tr><tr><td>public static long round(double a)</td><td>返回最接近指定双精度型数值的整数</td></tr><tr><td>public static double sqrt(double a)</td><td>返回指定双精度型数值的平方根</td></tr></tbody></table><h4 id="Random">Random</h4><p>Random类是java.util包下的一个工具类,里面提供了很多静态方法,用来生成随机数。</p><table><thead><tr><th>方法名</th><th>说明</th></tr></thead><tbody><tr><td>public static int nextInt()</td><td>返回一个随机整数,该随机数介于int类型的最小值和最大值之间</td></tr><tr><td>public static int nextInt(int n)</td><td>返回一个随机整数,该随机数介于0(包含)和指定值(不包含)之间</td></tr><tr><td>public static double nextDouble()</td><td>返回一个随机小数,该随机数介于0.0和1.0之间</td></tr><tr><td>public static boolean nextBoolean()</td><td>返回一个随机布尔值,该随机值是true或false</td></tr><tr><td>public static void setSeed(long seed)</td><td>设置随机数种子</td></tr></tbody></table><h4 id="System">System</h4><p>System类是java.lang包下的一个工具类,里面提供了很多静态方法,用来获取与系统相关的信息。</p><table><thead><tr><th>方法名</th><th>说明</th></tr></thead><tbody><tr><td>public static long currentTimeMillis()</td><td>返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差</td></tr><tr><td>public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)</td><td>将数组中指定的数据复制到另一个数组中</td></tr><tr><td>public static void exit(int status)</td><td>终止当前正在运行的Java虚拟机</td></tr><tr><td>public static void gc()</td><td>运行垃圾回收器</td></tr></tbody></table><h4 id="Runtime">Runtime</h4><p>Runtime类是java.lang包下的一个工具类,里面提供了很多静态方法,用来获取与运行环境相关的信息。</p><table><thead><tr><th>方法名</th><th>说明</th></tr></thead><tbody><tr><td>public static Runtime getRuntime()</td><td>返回与当前Java程序关联的Runtime对象</td></tr><tr><td>public static long totalMemory()</td><td>返回Java虚拟机中的内存总量</td></tr><tr><td>public static long freeMemory()</td><td>返回Java虚拟机中的空闲内存量</td></tr><tr><td>public static void gc()</td><td>运行垃圾回收器</td></tr></tbody></table><h4 id="BigDecimal">BigDecimal</h4><p>用来表示一个任意精度的小数。</p><table><thead><tr><th>方法名</th><th>说明</th></tr></thead><tbody><tr><td>public BigDecimal(String val)</td><td>创建一个指定字符串表示的BigDecimal对象</td></tr><tr><td>public BigDecimal add(BigDecimal augend)</td><td>将两个BigDecimal对象相加</td></tr><tr><td>public BigDecimal subtract(BigDecimal subtrahend)</td><td>将两个BigDecimal对象相减</td></tr><tr><td>public BigDecimal multiply(BigDecimal multiplicand)</td><td>将两个BigDecimal对象相乘</td></tr><tr><td>public BigDecimal divide(BigDecimal divisor)</td><td>将两个BigDecimal对象相除</td></tr><tr><td>public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)</td><td>将两个BigDecimal对象相除,并保留指定的小数位数,可以使用指定的舍入模式</td></tr></tbody></table><h3 id="日期时间">日期时间</h3><h4 id="Date">Date</h4><p>代表日期时间</p><table><thead><tr><th>方法名</th><th>说明</th></tr></thead><tbody><tr><td>public long getTime()</td><td>返回从1970年1月1日00:00:00走到此刻的总的毫秒数</td></tr><tr><td>public void setTime(long time)</td><td>设置日期对象的时间为当前时间毫秒值对应的时间</td></tr></tbody></table><h4 id="SimpleDateFormat">SimpleDateFormat</h4><p>SimpleDateFormat是一个日期时间格式化类,用来格式化和解析日期时间字符串。</p><table><thead><tr><th>方法名</th><th>说明</th></tr></thead><tbody><tr><td>public SimpleDateFormat(String pattern)</td><td>创建一个指定模式的字符串格式化器</td></tr><tr><td>public String format(Date date)</td><td>将日期对象格式化为日期时间字符串</td></tr><tr><td>public Date parse(String source)</td><td>将日期时间字符串解析为日期对象</td></tr></tbody></table><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">String</span> <span class="variable">s1</span> <span class="operator">=</span> <span class="string">"2023-11-11 12:12:11"</span>;</span><br><span class="line"> <span class="type">SimpleDateFormat</span> <span class="variable">sdf1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SimpleDateFormat</span>(<span class="string">"yyyy-MM-dd HH:mm:ss"</span>);</span><br><span class="line"> <span class="type">Date</span> <span class="variable">d1</span> <span class="operator">=</span> sdf1.parse(s1);</span><br><span class="line"> System.out.println(d1);</span><br></pre></td></tr></table></figure><h4 id="Calendar">Calendar</h4><ul><li>代表的是系统此刻时间对应的日历。</li><li>通过它可以单独获取、修改时间中的年、月、日、时、分、秒等</li></ul><table><thead><tr><th>方法名</th><th>说明</th></tr></thead><tbody><tr><td>public static Calendar getInstance()</td><td>获取一个代表系统此刻时间的日历对象</td></tr><tr><td>public int get(int field)</td><td>获取指定日历字段的值</td></tr><tr><td>public void set(int field, int value)</td><td>设置指定日历字段的值</td></tr><tr><td>public abstract void add(int field, int amount)</td><td>根据日历的规则,为指定日历字段添加或减去指定的时间量</td></tr></tbody></table><h4 id="Java8新日期时间">Java8新日期时间</h4><ul><li>LocalDate:代表本地日期(年、月、日、星期)</li><li>LocalTime:代表本地时间(时、分、秒、纳秒)</li><li>LocalDateTime:代表本地日期、时间(年、月、日、星期、时、分、秒、纳秒)<br>| 方法名 | 说明 |<br>| -------- | --------- |<br>| public static LocalDate now() | 获取当前日期 |<br>| public static LocalTime now(Clock clock) | 获取当前时间 |<br>| public static LocalDateTime now(Clock clock) | 获取当前日期和时间 |<br>| public static LocalDateTime now(ZoneId zone) | 获取当前日期和时间 |<br>| public static LocalDateTime now(ZoneId zone, Clock clock) | 获取当前日期和时间 |<br>| public static LocalDateTime of(int year, int month, int dayOfMonth, int hour, int minute, int second) | 获取指定日期和时间的日期时间对象 |<br>| public static LocalDateTime of(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond) | 获取指定日期和时间的日期时间对象 |<br>| public static LocalDateTime of(LocalDate date, LocalTime time) | 获取指定日期和时间的日期时间对象 |</li></ul><h3 id="Arrays">Arrays</h3><p>Arrays类用来操作数组。</p><table><thead><tr><th>方法名</th><th>说明</th></tr></thead><tbody><tr><td>public static String toString(int[] a)</td><td>将数组转换为字符串</td></tr><tr><td>public static void sort(int[] a)</td><td>对数组进行排序</td></tr></tbody></table><p>如果数组中存储的是对象,如何排序?</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Test1</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"> Student[] students = <span class="keyword">new</span> <span class="title class_">Student</span>[<span class="number">3</span>];</span><br><span class="line"> students[<span class="number">0</span>] = <span class="keyword">new</span> <span class="title class_">Student</span>(<span class="string">"张三"</span>, <span class="number">180</span>, <span class="number">20</span>);</span><br><span class="line"> students[<span class="number">1</span>] = <span class="keyword">new</span> <span class="title class_">Student</span>(<span class="string">"李四"</span>, <span class="number">170</span>, <span class="number">21</span>);</span><br><span class="line"> students[<span class="number">2</span>] = <span class="keyword">new</span> <span class="title class_">Student</span>(<span class="string">"王五"</span>, <span class="number">160</span>, <span class="number">22</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//public static void sort(类型[] arr),对数组进行排序,默认升序</span></span><br><span class="line"> Arrays.sort(students);</span><br><span class="line"> System.out.println(Arrays.toString(students));</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">//public static <T> void sort(T[] arr, Comparator<? super T> c)</span></span><br><span class="line"> <span class="comment">//对数组进行排序,使用自定义的比较器进行排序</span></span><br><span class="line"> Arrays.sort(students , <span class="keyword">new</span> <span class="title class_">Comparator</span><Student>() {</span><br><span class="line"> <span class="meta">@Override</span> <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">compare</span><span class="params">(Student o1, Student o2)</span> {</span><br><span class="line"><span class="comment">// if (o1.getHeight() > o2.getHeight()) {</span></span><br><span class="line"><span class="comment">// return 1;</span></span><br><span class="line"><span class="comment">// } else if (o1.getHeight() < o2.getHeight()) {</span></span><br><span class="line"><span class="comment">// return -1;</span></span><br><span class="line"><span class="comment">// }</span></span><br><span class="line"><span class="comment">// return 0;//升序</span></span><br><span class="line"> <span class="keyword">return</span> Double.compare(o1.getHeight(), o2.getHeight());<span class="comment">//按照身高升序</span></span><br><span class="line"> <span class="comment">//return Double.compare(o2.getHeight(), o1.getHeight());//按照身高降序</span></span><br><span class="line"> <span class="comment">//return Integer.compare(o1.getAge(), o2.getAge());//按照年龄升序</span></span><br><span class="line"> <span class="comment">//return Integer.compare(o2.getAge(), o1.getAge());//按照年龄降序</span></span><br><span class="line"> }</span><br><span class="line"> });</span><br><span class="line"> <span class="comment">//Lambda简化写法</span></span><br><span class="line"> Arrays.sort(students ,(Student o1, Student o2) -> {</span><br><span class="line"> <span class="keyword">return</span> Double.compare(o1.getHeight(), o2.getHeight());<span class="comment">//按照身高升序</span></span><br><span class="line"> });</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><p>学生类</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Student</span> <span class="keyword">implements</span> <span class="title class_">Comparable</span><Student>{</span><br><span class="line"> <span class="keyword">private</span> String name;</span><br><span class="line"> <span class="keyword">private</span> <span class="type">double</span> height;</span><br><span class="line"> <span class="keyword">private</span> <span class="type">int</span> age;</span><br><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">"Student{"</span> +</span><br><span class="line"> <span class="string">"name='"</span> + name + <span class="string">'\''</span> +</span><br><span class="line"> <span class="string">", height="</span> + height +</span><br><span class="line"> <span class="string">", age="</span> + age +</span><br><span class="line"> <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="comment">//this 表示当前对象, o 表示参数对象</span></span><br><span class="line"> <span class="comment">//返回值 1 表示当前对象大于参数对象, -1 表示当前对象小于参数对象, 0 表示相等</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_">compareTo</span><span class="params">(Student o)</span> {</span><br><span class="line"> <span class="comment">//年龄升序排列</span></span><br><span class="line"><span class="comment">// if (this.age > o.age) {</span></span><br><span class="line"><span class="comment">// return 1;</span></span><br><span class="line"><span class="comment">// } else if (this.age < o.age) {</span></span><br><span class="line"><span class="comment">// return -1;</span></span><br><span class="line"><span class="comment">// } else {</span></span><br><span class="line"><span class="comment">// return 0;</span></span><br><span class="line"><span class="comment">// }</span></span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">this</span>.age - o.age;<span class="comment">// 升序排列</span></span><br><span class="line"> <span class="comment">//return o.age - this.age;//降序排列</span></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">Student</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_">Student</span><span class="params">(String name, <span class="type">double</span> height, <span class="type">int</span> age)</span> {</span><br><span class="line"> <span class="built_in">this</span>.name = name;</span><br><span class="line"> <span class="built_in">this</span>.height = height;</span><br><span class="line"> <span class="built_in">this</span>.age = age;</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> <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="keyword">public</span> <span class="type">int</span> <span class="title function_">getAge</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> age;</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_">setAge</span><span class="params">(<span class="type">int</span> age)</span> {</span><br><span class="line"> <span class="built_in">this</span>.age = age;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="JDK8新特性">JDK8新特性</h3><h4 id="Lambda">Lambda</h4><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/lambda.png" alt="lambda"></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Test</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">Animal</span> <span class="variable">a</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Animal</span>() {</span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</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"> a.run();</span><br><span class="line"> System.out.println(<span class="string">"----------------"</span>);</span><br><span class="line"><span class="comment">// Swing S = new Swing(){</span></span><br><span class="line"><span class="comment">// public void swing() {</span></span><br><span class="line"><span class="comment">// System.out.println("人在游泳");</span></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">// S.swing();</span></span><br><span class="line"> <span class="comment">//lambda简化</span></span><br><span class="line"> <span class="type">Swing</span> <span class="variable">S</span> <span class="operator">=</span> () -> {</span><br><span class="line"> System.out.println(<span class="string">"人在游泳"</span>);</span><br><span class="line"> };</span><br><span class="line"> S.swing();</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">interface</span> <span class="title class_">Swing</span> {</span><br><span class="line"> <span class="keyword">void</span> <span class="title function_">swing</span><span class="params">()</span>;</span><br><span class="line">}</span><br><span class="line"><span class="keyword">abstract</span> <span class="keyword">class</span> <span class="title class_">Animal</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>Lambda省略规则</p><ul><li>参数类型可以省略不写。</li><li>如果只有一个参数,参数类型可以省略,同时()也可以省略。</li><li>如果Lambda表达式中的方法体代码只有一行代码,可以省略大括号不写,同时要省略分号!此时,如果这行代码是return语句,也必须去掉return不写.</li></ul><p>方法引用</p><ol><li>静态方法引用<br>用法:类名::静态方法。<br>使用场景:<br>如果某个Lambda表达式里只是调用一个静态方法,并且前后参数的形式一致,就可以使用静态方法引用。</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">Arrays.sort(students , <span class="keyword">new</span> <span class="title class_">Comparator</span><Student>() {</span><br><span class="line"> <span class="meta">@Override</span> <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">compare</span><span class="params">(Student o1, Student o2)</span> { </span><br><span class="line"> <span class="keyword">return</span> Double.compare(o1.getHeight(), o2.getHeight());<span class="comment">//按照身高升序</span></span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//Lambda简化写法</span></span><br><span class="line"> Arrays.sort(students ,(Student o1, Student o2) -> {</span><br><span class="line"> <span class="keyword">return</span> Double.compare(o1.getHeight(), o2.getHeight());<span class="comment">//按照身高升序</span></span><br><span class="line"> });</span><br><span class="line"> <span class="comment">//再次简化</span></span><br><span class="line"> Arrays.sort(students , (o1,o2) ->o1.getAge - o2.getAge);</span><br><span class="line"> <span class="comment">//再次简化</span></span><br><span class="line"> Arrays.sort(students , (o1,o2) ->CompareBydata.compareByAge(o1,o2));</span><br><span class="line"> <span class="comment">//再次简化:静态方法引用</span></span><br><span class="line"> Arrays.sort(students ,CompareBydata::compareByAge);</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CompareBydata</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_">compareByAge</span><span class="params">(atudent o1,student o2)</span>{</span><br><span class="line"> <span class="keyword">return</span> o1.getAge - o2.getAge;<span class="comment">//自定义升序规则</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ol start="2"><li>实例方法的引用<br>用法:对象名::实例方法。<br>使用场景:<br>如果某个Lambda表达式里只是调用一个实例方法,并且前后参数的形式一致,就可以使用实例方法引用。</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">CompareBydata</span> <span class="variable">compare</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">CompareBydata</span>();</span><br><span class="line"><span class="comment">//实例方法引用</span></span><br><span class="line">Arrays.sort(students ,Compare::compareByAge);</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CompareBydata</span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">compareByAge</span><span class="params">(atudent o1,student o2)</span>{</span><br><span class="line"> <span class="keyword">return</span> o1.getAge - o2.getAge;<span class="comment">//自定义升序规则</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ol start="3"><li>特定类型的方法引用<br>用法:类型::方法。<br>使用场景:<br>如果某个Lambda表达式里只是调用一个实例方法,并且前面参数列表中的第一个参数是作为方法的主调后面的所有参数都是作为该实例方法的入参的,则此时就可以使用特定类型的方法引用。</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Test1</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"> String [] names = {<span class="string">"Ailin"</span>, <span class="string">"Bai"</span>, <span class="string">"CaoZhi"</span>, <span class="string">"alin"</span>, <span class="string">"bobi"</span>, <span class="string">"caoZhan"</span>};</span><br><span class="line"> <span class="comment">//默认按照首字母排序</span></span><br><span class="line"> <span class="comment">//Arrays.sort(names);</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"> Arrays.sort(names,<span class="keyword">new</span> <span class="title class_">Comparator</span><String>() {</span><br><span class="line"> <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">compare</span><span class="params">(String o1, String o2)</span> {</span><br><span class="line"> <span class="keyword">return</span> o1.compareToIgnoreCase(o2);</span><br><span class="line"> }</span><br><span class="line"> });</span><br><span class="line"> <span class="comment">//简化</span></span><br><span class="line"> Arrays.sort(names, ( o1, o2) -> o1.compareToIgnoreCase(o2));</span><br><span class="line"> <span class="comment">//特定方法引用</span></span><br><span class="line"> Arrays.sort(names, String::compareToIgnoreCase);</span><br><span class="line"> </span><br><span class="line"> System.out.println(Arrays.toString(names));</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ol start="4"><li>构造方法的引用<br>用法:类名::new<br>使用场景:<br>如果某个Lambda表达式里只是创建一个对象,并且前面参数列表中的第一个参数是作为构造方法的主调后面的所有参数都是作为该构造方法的入参的,则此时就可以使用构造方法的引用。</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Test1</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="comment">//构造方法的引用</span></span><br><span class="line"> List<String> list = <span class="keyword">new</span> <span class="title class_">ArrayList</span><>() {</span><br><span class="line"> {</span><br><span class="line"> add(<span class="string">"Ailin"</span>);</span><br><span class="line"> add(<span class="string">"Bai"</span>);</span><br><span class="line"> add(<span class="string">"CaoZhi"</span>);</span><br><span class="line"> }</span><br><span class="line"> };</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><h3 id="正则表达式">正则表达式</h3><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/5.png" alt="5"><br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/6.png" alt="6"><br>正则表达式用于搜索替换,切割内容</p><table><thead><tr><th>方法名</th><th>说明</th></tr></thead><tbody><tr><td>public String replaceAll(String regex,String replacement)</td><td>替换所有匹配的字符串</td></tr><tr><td>public String replaceFirst(String regex,String replacement)</td><td>替换第一个匹配的字符串</td></tr><tr><td>public String[] split(String regex)</td><td>切割字符串</td></tr><tr><td>public boolean matches(String regex)</td><td>判断是否匹配正则表达式</td></tr><tr><td>public String[] split(String regex,int limit)</td><td>切割字符串,limit限制切割次数</td></tr></tbody></table><h3 id="异常">异常</h3><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/7.png" alt="7"></p><p>自定义异常</p><ul><li>Java无法为这个世界上全部的问题都提供异常类来代表,如果企业自己的某种问题,想通过异常来表示<br>以便用异常来管理该问题,那就需要自己来定义异常类了</li></ul><ol><li><p>运行时异常</p><ul><li>定义一个异常类继承RuntimeException,</li><li>重写构造器。</li><li>通过throw new 异常类(xxx)来创建异常对象并抛出。编译阶段不报错,提醒不强烈,运行时才可能出现!!</li></ul></li><li><p>编译时异常</p><ul><li>定义一个异常类继承Exception.</li><li>重写构造器。</li><li>通过throw new 异常类(xxx)来创建异常对象并抛出编译阶段就报错,提醒更加强烈!</li></ul></li><li><p>处理方式</p><ul><li>捕获异常,记录异常并响应合适的信息给用户</li><li>捕获异常,尝试重新修复</li></ul></li></ol><p>抛出异常</p><ul><li>在方法上使用throws关键字,可以将方法内部出现的异常抛出去给调用者处理</li><li>直接捕获程序出现的异常(try-catch捕获)</li></ul><h3 id="集合框架">集合框架</h3><p>Collection集合</p><ul><li>Collection代表单列集合,每个元素(数据)只包含一个值</li><li>Map代表双列集合,每个元素包含两个值(键值对)</li><li>Collection是单列集合的祖宗,它规定的方法(功能)是全部单列集合都会继承的</li></ul><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/8.png" alt="8"></p><ol><li>Collection常见方法</li></ol><table><thead><tr><th>方法名</th><th>说明</th></tr></thead><tbody><tr><td>public boolean add(E e)</td><td>添加元素</td></tr><tr><td>public void clear()</td><td>清空集合</td></tr><tr><td>public boolean remove(E e)</td><td>删除元素</td></tr><tr><td>public boolean contains(E e)</td><td>判断集合中是否包含某个元素</td></tr><tr><td>public boolean isEmpty()</td><td>判断集合是否为空</td></tr><tr><td>public int size()</td><td>获取集合中元素的个数</td></tr><tr><td>public Object[] toArray()</td><td>将集合转换为数组</td></tr></tbody></table><ol start="2"><li>Collections<br>是用来操作集合的工具类</li></ol><table><thead><tr><th>方法名</th><th>说明</th></tr></thead><tbody><tr><td>public static void reverse(List<?> list)</td><td>反转集合中元素的顺序</td></tr><tr><td>public static void shuffle(List<?> list)</td><td>随机排序集合中元素</td></tr><tr><td>public static <T> void sort(List<T> list)</td><td>升序排序集合中元素</td></tr><tr><td>public static <T> addAll(Collection<? super T> c,T… elements)</td><td>将多个元素添加到集合中</td></tr></tbody></table><blockquote><p>注意:Collections中的sort方法,只能对List集合进行排序,不能对Set集合进行排序。</p></blockquote><p>排序方式一:</p><table><thead><tr><th>方法名</th><th>说明</th></tr></thead><tbody><tr><td>public static <T> void sort(List<T> list)</td><td>升序排序集合中元素</td></tr></tbody></table><ul><li>本方法可以直接对自定义类型的List集合排序,但自定义类型必须实现了Comparable接口,指定了比较规则才可以。</li></ul><p>排序方式二:</p><table><thead><tr><th>方法名</th><th>说明</th></tr></thead><tbody><tr><td>public static <T> void sort(List<T> list,Comparator<? super T> c)</td><td>升序排序集合中元素</td></tr></tbody></table><h4 id="遍历集合">遍历集合</h4><ol><li>增强for循环</li></ol><ul><li>增强for循环,也称为for each循环,用来遍历数组和集合。</li><li>增强for循环的语法格式:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span>(元素的数据类型 变量名:数组或者集合){</span><br><span class="line"> <span class="comment">//使用变量名来访问数组或者集合中的元素</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><ol start="2"><li>迭代器</li></ol><ul><li>迭代器是用来遍历集合的专用方式(数组没有迭代器),在Java中迭代器的代表是Iterator,用来遍历集合。<br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/9.png" alt="9"></li></ul><ol start="3"><li>Lambda表达式<br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/10.png" alt="10"></li></ol><h4 id="List集合">List集合</h4><p>List系列集合特点:有序,可重复,有索引</p><ul><li>ArrayList:有序,可重复,有索引。</li><li>LinkedList:有序,可重复,有索引。<br>二者底层实现不同!适合的场景不同</li></ul><table><thead><tr><th>方法名</th><th>说明</th></tr></thead><tbody><tr><td>public boolean add(E e)</td><td>添加元素</td></tr><tr><td>public void clear()</td><td>清空集合</td></tr><tr><td>public boolean remove(E e)</td><td>删除元素</td></tr><tr><td>public boolean contains(E e)</td><td>判断集合中是否包含某个元素</td></tr><tr><td>public boolean isEmpty()</td><td>判断集合是否为空</td></tr><tr><td>public int size()</td><td>获取集合中元素的个数</td></tr><tr><td>public Object[] toArray()</td><td>将集合转换为数组</td></tr></tbody></table><blockquote><p>indexof()方法根据集合中的数值来找到对应索引的位置<br>contains()方法判断集合中是否存在重复数值,有返回true,没有返回forse</p></blockquote><ol><li>ArrayList</li></ol><ul><li>ArrayList底层是数组,查询快,增删慢</li><li>数组默认长度为10,当添加元素时,会自动扩容,默认扩容为原来的1.5倍</li></ul><p>应用场景:<br>1、ArrayList适合:根据索引查询数据比如根据随机索引取数据(高效)!或者数据量不是很大时!<br>2、ArrayList不适合:数据量大的同时又要频繁的进行增删操作!</p><blockquote><ol><li>查询速度快(注意:是根据索引查询数据快):查询数据通过地址值和索引定位,查询任意数据耗时相同</li><li>删除效率低:可能需要把后面很多的数据进行前移。</li><li>添加效率极低:可能需要把后面很多的数据后移,再添加元素;或者也可能需要进行数组的扩容。</li></ol></blockquote><ol start="2"><li>LinkedList</li></ol><ul><li>LinkedList底层是链表,查询慢,增删快,但对首尾元素进行增删改查的速度是极快的</li><li>链表的每个元素都包含有数据和指针,指针指向下一个元素</li><li>LinkedList新增了:很多首尾操作的特有方法。</li></ul><table><thead><tr><th>方法名</th><th>说明</th></tr></thead><tbody><tr><td>public void addFirst(E e)</td><td>在链表的首部添加元素</td></tr><tr><td>public void addLast(E e)</td><td>在链表的尾部添加元素</td></tr><tr><td>public E getFirst()</td><td>获取链表的首部元素</td></tr><tr><td>public E getLast()</td><td>获取链表的尾部元素</td></tr><tr><td>public E removeFirst()</td><td>删除链表的首部元素</td></tr><tr><td>public E removeLast()</td><td>删除链表的尾部元素</td></tr></tbody></table><p>应用场景:队列(先进先出),栈(先进后出)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><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="comment">//创建一个队列</span></span><br><span class="line"> LinkedList<String> lk = <span class="keyword">new</span> <span class="title class_">LinkedList</span><>();</span><br><span class="line"> <span class="comment">//入队</span></span><br><span class="line"> lk.addLast(<span class="string">"1"</span>);</span><br><span class="line"> lk.addLast(<span class="string">"2"</span>);</span><br><span class="line"> lk.addLast(<span class="string">"3"</span>);</span><br><span class="line"> lk.addLast(<span class="string">"4"</span>);</span><br><span class="line"> <span class="comment">//出队</span></span><br><span class="line"> System.out.println(lk.removeFirst());</span><br><span class="line"> System.out.println(lk.removeFirst());</span><br><span class="line"> System.out.println(lk.removeFirst());</span><br><span class="line"> System.out.println(lk.removeFirst());</span><br><span class="line"> <span class="comment">//创建一个栈</span></span><br><span class="line"> LinkedList<String> stack = <span class="keyword">new</span> <span class="title class_">LinkedList</span><>();</span><br><span class="line"> <span class="comment">//压栈(push)</span></span><br><span class="line"> stack.addFirst(<span class="string">"子弹1"</span>);</span><br><span class="line"> stack.addFirst(<span class="string">"子弹2"</span>);</span><br><span class="line"> stack.addFirst(<span class="string">"子弹3"</span>);</span><br><span class="line"> stack.addFirst(<span class="string">"子弹4"</span>);</span><br><span class="line"> <span class="comment">//出栈(pop)</span></span><br><span class="line"> System.out.println(stack);</span><br><span class="line"> System.out.println(stack.removeFirst());</span><br><span class="line"> System.out.println(stack.removeFirst());</span><br><span class="line"> System.out.println(stack.removeFirst());</span><br><span class="line"> System.out.println(stack.removeFirst());</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><h4 id="Set集合">Set集合</h4><p>Set系列集合特点: 无序;添加数据的顺序和获取出的数据顺序不一致;不重复;无索引;</p><ul><li>Hashset: 无序、不重复、无索引。</li><li>LinkedHashset: 有序、不重复、无索引。</li><li>TreeSet:排序、不重复、无索引</li></ul><blockquote><p>哈希值</p><ul><li>就是一个int类型的数值,Java中每个对象都有一个哈希值。</li><li>Java中的所有对象,都可以调用obejct类提供的hashCode方法,返回该对象自己的哈希值<br>public int hashcode():返回对象的哈希码值。</li></ul><p>对象哈希值的特点:</p><ul><li>同一个对象多次调用hashCode()方法返回的哈希值是相同的。</li><li>不同的对象,它们的哈希值一般不相同,但也有可能会相同(哈希碰撞)</li></ul></blockquote><ol><li>HashSet底层原理<ul><li>基于哈希表实现。</li><li>哈希表是一种增删改查数据,性能都较好的数据结构。</li></ul></li><li>哈希表<ul><li>JDK8之前,哈希表=数组+链表</li><li>JDK8开始,哈希表=数组+链表+红黑树</li></ul></li></ol><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/11.png" alt="11"><br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/12.png" alt="12"></p><ol start="3"><li>平衡二叉树<ul><li>平衡二叉树是二叉搜索树,又被称为AVL树。</li><li>它是一颗空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一颗平衡二叉树。</li><li>平衡二叉树的常用实现方法有红黑树、AVL、替罪羊树、Treap、伸展树等。</li><li>在满足查找二叉树的大小规则下,让树尽可能矮小,以此提高查数据的性能</li></ul></li></ol><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/13.png" alt="13"></p><ol start="4"><li>红黑树<ul><li>它是一颗空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一颗红黑树。</li><li>它是一种特殊的二叉树,树中的每个节点都只能是红色或者黑色。</li><li>树中根节点是黑色。</li><li>每个叶子节点(NIL)是黑色。</li><li>不能有相邻接的两个红色节点。</li><li>从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。</li><li>红黑树,就是可以自平衡的二叉树</li><li>红黑树是一种增删改查数据性能相对都较好的结构</li></ul></li></ol><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/14.png" alt="14"></p><ol start="5"><li><p>哈希表和红黑树的区别</p><ul><li>哈希表查询速度快,增删速度慢。</li><li>红黑树查询速度慢,增删速度快。</li><li>哈希表适用于查询多,增删少的情况。</li><li>红黑树适用于查询少,增删多的情况。</li></ul></li><li><p>HashSet去重复<br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/15.png" alt="15"></p></li><li><p>LinkedHashSet底层原理</p><ul><li>依然是基于哈希表(数组、链表、红黑树)实现的。</li><li>但是,它的每个元素都额外的多了一个双链表的机制记录它前后元素的位置。<br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/16.png" alt="16"></li></ul></li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><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="comment">//创建HashSet集合对象:无序,不重复,无索引</span></span><br><span class="line"> Set<Integer> set = <span class="keyword">new</span> <span class="title class_">HashSet</span><>();</span><br><span class="line"> <span class="comment">//创建LinkedHashSet集合对象:有序,不重复,无索引</span></span><br><span class="line"> Set<Integer> set1 = <span class="keyword">new</span> <span class="title class_">LinkedHashSet</span><>();</span><br><span class="line"> <span class="comment">//创建TreeSet集合对象:有序(默认是从小到大升序),不重复,无索引</span></span><br><span class="line"> Set<Integer> set2 = <span class="keyword">new</span> <span class="title class_">TreeSet</span><>();</span><br><span class="line"> set.add(<span class="number">2</span>);</span><br><span class="line"> set.add(<span class="number">2</span>);</span><br><span class="line"> set.add(<span class="number">1</span>);</span><br><span class="line"> set.add(<span class="number">3</span>);</span><br><span class="line"> set.add(<span class="number">3</span>);</span><br><span class="line"> set.add(<span class="number">4</span>);</span><br><span class="line"> set.add(<span class="number">4</span>);</span><br><span class="line"> System.out.println(set);</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><ol start="8"><li>TreeSet<ul><li>特点:不重复、无索引、可排序(默认升序排序,按照元素的大小,由小到大排序)</li><li>底层是基于红黑树实现的排序</li></ul></li></ol><blockquote><p>注意</p><ul><li>对于数值类型:Integer,Double,默认按照数值本身的大小进行升序排序</li><li>对于字符串类型:默认按照首字符的编号升序排序。</li><li>对于自定义类型如Student对象,Treeset默认是无法直接排序的</li></ul></blockquote><ul><li>自定义排序规则<br>TreeSet集合存储自定义类型的对象时,必须指定排序规则,支持如下两种方式来指定比较规则。</li><li>方式一<br>让自定义的类(如学生类)实现Comparable接口,重写里面的compareTo方法来指定比较规则</li><li>方式二<br>通过调用Treeset集合有参数构造器,可以设置Comparator对象(比较器对象,用于指定比较规则<br>public TreeSet(Comparator<?super E>comparator)</li></ul><p>两种方式中,关于返回值的规则:</p><ul><li>如果认为第一个元素>第二个元素 返回正整数即可</li><li>如果认为第一个元系<第二个元表返回负整数即可。</li><li>如果认为第一个元素=第二个元索返回0即可,此时Treeset集合只会保留一个元素,认为两者重复。</li></ul><blockquote><p>注意:如果类本身有实现Comparable接口,TreeSet集合同时也自带比较器,默认使用集合自带的比较器排序<br>各种集合的应用场景</p><ol><li>如果希望记住元素的添加顺序,需要存储重复的元素,又要频繁的根据索引查询数据?<ul><li>用ArrayList集合(有序、可重复、有索引),底层基于数组的。(常用)</li></ul></li><li>如果希望记住元素的添加顺序,且增删首尾数据的情况较多?<ul><li>用LinkedList集合(有序、可重复、有索引),底层基于双链表实现的,</li></ul></li><li>如果不在意元索顺序,也没有重复元素需要存储,只希望增删改查都快?<ul><li>用Hashset集合(无序,不重复,无索引),底层基于哈希表实现的。(常用)</li></ul></li><li>如果希望记住元素的添加顺序,也没有重复元索需要存储,且希望增删改查都快?<ul><li>用LinkedHashset集合(有序,不重复,无索引),底层基于哈希表和双链表。</li></ul></li><li>如果要对元素进行排序,也没有重复元素需要存储?且希望增删改查都快?<ul><li>用TreeSet集合,基于红黑树实现</li></ul></li></ol></blockquote><ul><li>集合的并发修改异常<ol><li>使用迭代器遍历集合时,又同时在删除集合中的数据,程序就会出现并发修改异常的错误。</li><li>由于增强for循环遍历集合就是迭代器遍历集合的简化写法,因此,使用增强for循环遍历集合,又在同时删除集合中的数据时,程序也会出现并发修改异常的错误</li></ol></li><li>怎么保证遍历集合同时删除数据时不出bug?<ol><li>使用迭代器遍历集合,但用迭代器自己的删除方法删除数据即可。</li><li>如果能用for循环遍历时:可以倒着遍历并删除;或者从前往后遍历,但删除元素后做i–操作。</li></ol></li></ul><h4 id="Map集合">Map集合</h4><ul><li>Map集合称为双列集合,格式:{key1=value1,key2=value2,key3=value3,…},一次需要存一对数据做为一个元素</li><li>Map集合的每个元素"key=value"称为一个键值对/键值对对象/一个Entry对象,Map集合也被叫做"键值对集合"</li><li>Map集合的所有键是不允许重复的,但值可以重复,键和值是一一对应的,每一个键只能找到自己对应的值<br>Map集合体系</li></ul><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/17.png" alt="17"></p><blockquote><p>Map系列集合的特点都是由键决定的,值只是一个附属品,值是不做要求的</p></blockquote><ul><li>HashMap(由键决定特点):无序、不重复、无索引;(用的最多)</li><li>LinkedHashMap (由键决定特点):由键决定的特点:有序、不重复、无索引</li><li>TreeMap (由键决定特点):按照大小默认升序排序、不重复、无索引。</li><li>Map是双列集合的祖宗,它的功能是全部双列集合都可以继承过来使用的,</li></ul><table><thead><tr><th>方法名</th><th>说明</th></tr></thead><tbody><tr><td>void clear()</td><td>清除集合中的所有元素</td></tr><tr><td>boolean containsKey(Object key)</td><td>判断集合中是否包含指定的键</td></tr><tr><td>boolean containsValue(Object value)</td><td>判断集合中是否包含指定的值</td></tr><tr><td>Set<Map.Entry<K,V>> entrySet()</td><td>返回所有键值对对象的集合</td></tr><tr><td>V get(Object key)</td><td>根据键获取值</td></tr><tr><td>boolean isEmpty()</td><td>判断集合是否为空</td></tr><tr><td>V put(K key,V value)</td><td>存储键值对</td></tr><tr><td>V remove(Object key)</td><td>根据键删除键值对</td></tr><tr><td>int size()</td><td>获取集合中键值对的数量</td></tr><tr><td>Collection<V> values()</td><td>获取所有值</td></tr></tbody></table><p>Map集合的遍历</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><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="comment">//创建Map集合对象</span></span><br><span class="line"> Map<String, Integer> map = <span class="keyword">new</span> <span class="title class_">HashMap</span><>();</span><br><span class="line"> <span class="comment">//存储键值对</span></span><br><span class="line"> map.put(<span class="string">"语文"</span>, <span class="number">100</span>);</span><br><span class="line"> map.put(<span class="string">"数学"</span>, <span class="number">90</span>);</span><br><span class="line"> map.put(<span class="string">"英语"</span>, <span class="number">80</span>);</span><br><span class="line"> map.put(<span class="string">"物理"</span>, <span class="number">70</span>);</span><br><span class="line"> map.put(<span class="string">"化学"</span>, <span class="number">60</span>);</span><br><span class="line"> <span class="comment">//获取所有键值对对象的集合</span></span><br><span class="line"> Set<Map.Entry<String, Integer>> entrySet = map.entrySet();</span><br><span class="line"> <span class="comment">//遍历entrySet集合,得到每一个键值对对象</span></span><br><span class="line"> <span class="keyword">for</span> (Map.Entry<String, Integer> me : entrySet) {</span><br><span class="line"> <span class="comment">//根据键值对对象获取键和值</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">key</span> <span class="operator">=</span> me.getKey();</span><br><span class="line"> <span class="type">Integer</span> <span class="variable">value</span> <span class="operator">=</span> me.getValue();</span><br><span class="line"> System.out.println(key + <span class="string">"="</span> + value);</span><br><span class="line"> }</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/18.png" alt="18"></p><p>案例:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Test2</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"> List<String> data = <span class="keyword">new</span> <span class="title class_">ArrayList</span><>();</span><br><span class="line"> String[] arr = {<span class="string">"A"</span>, <span class="string">"B"</span>, <span class="string">"C"</span>, <span class="string">"D"</span>};</span><br><span class="line"> <span class="type">Random</span> <span class="variable">r</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Random</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">80</span>; i++) {</span><br><span class="line"> <span class="comment">//模拟学生选择一个景点,并将其放入集合中</span></span><br><span class="line"> <span class="type">int</span> <span class="variable">index</span> <span class="operator">=</span> r.nextInt(<span class="number">4</span>);</span><br><span class="line"> data.add(arr[index]);</span><br><span class="line"> }</span><br><span class="line"> System.out.println(data);</span><br><span class="line"> <span class="comment">//统计每个景点的选择次数</span></span><br><span class="line"> Map<String, Integer> Jg = <span class="keyword">new</span> <span class="title class_">HashMap</span><>();</span><br><span class="line"> <span class="comment">//遍历集合,统计每个景点的选择次数</span></span><br><span class="line"> <span class="keyword">for</span> (String s : data) {</span><br><span class="line"> <span class="comment">//判断集合中是否有该景点</span></span><br><span class="line"> <span class="keyword">if</span> (Jg.containsKey(s)) {</span><br><span class="line"> <span class="comment">//有该景点,则将该景点的选择次数加1</span></span><br><span class="line"> Jg.put(s, Jg.get(s) + <span class="number">1</span>);</span><br><span class="line"> }<span class="keyword">else</span> {</span><br><span class="line"> <span class="comment">//没有该景点,则将该景点的选择次数设置为1</span></span><br><span class="line"> Jg.put(s, <span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> System.out.println(Jg);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>LinkedHashMap<br>底层数据结构依然是基于哈希表实现的,只是每个键值对元素又额外的多了一个双链表的机制记录元素顺序(保证有序)。</p><blockquote><p>LinkedHashMap集合的特点:有序、不重复、无索引</p></blockquote><ul><li>LinkedHashMap集合底层是链表和哈希表结合组成的,底层哈希表的键和值都是Entry对象</li><li>LinkedHashMap集合的Entry对象,重写了hashCode()和equals()方法,保证键不重复,且按照添加的顺序保存</li></ul><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/19.png" alt="19"></p><p>TreeMap<br>底层数据结构是基于红黑树实现的,保证按照键的大小顺序保存键值对</p><blockquote><p>TreeMap集合的特点:按照键的大小默认升序排序、不重复、无索引(只能对键排序)</p></blockquote><ul><li>TreeMap集合的底层是红黑树,红黑树是一颗自平衡的二叉树,保证按照键的大小顺序保存键值对</li><li>TreeMap集合的键和值都不能为null<br>TreeMap集合同样也支持两种方式来指定排序规则</li><li>让类实现Comparable接口,重写比较规则。</li><li>TreeMap集合有一个有参数构造器,支持创建Comparator比较器对象,以便用来指定比较规则。</li></ul><p>集合的嵌套</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><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"> Map<String, List<String>> map = <span class="keyword">new</span> <span class="title class_">HashMap</span><>();</span><br><span class="line"> List<String> cities1 = <span class="keyword">new</span> <span class="title class_">ArrayList</span><>();</span><br><span class="line"> Collections.addAll(cities1, <span class="string">"北京"</span>, <span class="string">"上海"</span>, <span class="string">"广州"</span>, <span class="string">"深圳"</span>);</span><br><span class="line"> map.put(<span class="string">"中国"</span>, cities1);</span><br><span class="line"></span><br><span class="line"> List<String> cities2 = <span class="keyword">new</span> <span class="title class_">ArrayList</span><>();</span><br><span class="line"> Collections.addAll(cities2, <span class="string">"成都"</span>, <span class="string">"重庆"</span>, <span class="string">"西安"</span>, <span class="string">"杭州"</span>);</span><br><span class="line"> map.put(<span class="string">"中国"</span>, cities2);</span><br><span class="line"> System.out.println(map);</span><br><span class="line"> List<String> cities = map.get(<span class="string">"中国"</span>);</span><br><span class="line"> <span class="keyword">for</span> (String city : cities) {</span><br><span class="line"> System.out.println(city);</span><br><span class="line"> }</span><br><span class="line"> map.forEach((k, v) -> {</span><br><span class="line"> System.out.println(k + <span class="string">" : "</span> + v);</span><br><span class="line"> });</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><h3 id="Stream">Stream</h3><ul><li>也叫Stream流,是Jdk8开始新增的一套API (java.util.stream.*),可以用于操作集合或者数组的数据。</li><li>优势: Stream流大量的结合了Lambda的语法风格来编程,提供了一种更加强大,更加简单的方式操作集合或者数组中的数据,代码更简洁,可读性更好</li></ul><ol><li><p>Stream流的使用步骤<br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/20.png" alt="20"></p></li><li><p>Stream流中的常用方法<br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/21.png" alt="21"><br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/22.png" alt="22"></p></li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><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="comment">//获取List集合的Stream流</span></span><br><span class="line"> List<String> names = <span class="keyword">new</span> <span class="title class_">ArrayList</span><>();</span><br><span class="line"> Collections.addAll(names, <span class="string">"张三"</span>, <span class="string">"李四"</span>, <span class="string">"王五"</span>, <span class="string">"赵六"</span>);</span><br><span class="line"> Stream<String> stream = names.stream();</span><br><span class="line"></span><br><span class="line"> <span class="comment">//获取set集合的Stream流</span></span><br><span class="line"> Set<String> set = <span class="keyword">new</span> <span class="title class_">HashSet</span><>();</span><br><span class="line"> Collections.addAll(set, <span class="string">"张三"</span>, <span class="string">"李四"</span>, <span class="string">"王五"</span>, <span class="string">"赵六"</span>);</span><br><span class="line"> Stream<String> stream1 = set.stream();</span><br><span class="line"> stream1.filter(s->s.startsWith(<span class="string">"王"</span>)).forEach(s->System.out.println(s));</span><br><span class="line"></span><br><span class="line"> <span class="comment">//获取map集合的Stream流</span></span><br><span class="line"> Map<String, Double> map = <span class="keyword">new</span> <span class="title class_">HashMap</span><>();</span><br><span class="line"> map.put(<span class="string">"张三"</span>, <span class="number">187.4</span>);</span><br><span class="line"> map.put(<span class="string">"李四"</span>, <span class="number">156.8</span>);</span><br><span class="line"> map.put(<span class="string">"王五"</span>, <span class="number">177.4</span>);</span><br><span class="line"> map.put(<span class="string">"赵六"</span>, <span class="number">188.5</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//获取key集合的Stream流</span></span><br><span class="line"> Set<String> ks = map.keySet();</span><br><span class="line"> Stream<String> vs = ks.stream();</span><br><span class="line"></span><br><span class="line"> <span class="comment">//获取value集合的Stream流</span></span><br><span class="line"> Collection<Double> ks1 = map.values();</span><br><span class="line"> Stream<Double> vs1 = ks1.stream();</span><br><span class="line"></span><br><span class="line"> <span class="comment">//获取entry键值对集合的Stream流</span></span><br><span class="line"> Set<Map.Entry<String, Double>> entrySet = map.entrySet();</span><br><span class="line"> Stream<Map.Entry<String, Double>> es = entrySet.stream();</span><br><span class="line"> es.filter(e->e.getKey().contains(<span class="string">"王"</span>))</span><br><span class="line"> .forEach(e->System.out.println(e.getKey()+<span class="string">"---"</span>+e.getValue()));</span><br><span class="line"></span><br><span class="line"> <span class="comment">//获取数组的Stream流</span></span><br><span class="line"> String[] arr = {<span class="string">"张三"</span>, <span class="string">"李四"</span>, <span class="string">"王五"</span>, <span class="string">"赵六"</span>};</span><br><span class="line"> Stream<String> s1 = Arrays.stream(arr);</span><br><span class="line"> Stream<String> s2 = Stream.of(arr);</span><br><span class="line"> s1.filter(s->s.startsWith(<span class="string">"王"</span>)).forEach(s->System.out.println(s));</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><p>中间方法:</p><table><thead><tr><th>Stream流常用中间方法</th><th>说明</th></tr></thead><tbody><tr><td>Stream<T> filter(Predicate<? super T> predicate)</td><td>接收一个Predicate接口参数,用于对数据进行过滤</td></tr><tr><td>Stream<T> distinct()</td><td>用于去重,通过流中元素的hashCode和equals方法判断是否为重复元素</td></tr><tr><td>Stream<T> sorted()</td><td>产生一个新流,其中按自然顺序排序</td></tr><tr><td>Stream<T> sorted(Comparator<? super T> comparator)</td><td>产生一个新流,其中按比较器顺序排序</td></tr><tr><td>Stream<T> peek(Consumer<? super T> action)</td><td>接收一个Consumer接口参数,用于对数据进行操作</td></tr><tr><td>Stream<T> limit(long maxSize)</td><td>截断流,使其元素不超过给定数量</td></tr><tr><td>Stream<T> skip(long n)</td><td>跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与limit(n)互补</td></tr></tbody></table><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><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"> List<Double> score = <span class="keyword">new</span> <span class="title class_">ArrayList</span><>();</span><br><span class="line"> Collections.addAll(score, <span class="number">90.0</span>, <span class="number">80.0</span>, <span class="number">95.0</span>, <span class="number">85.0</span>, <span class="number">90.0</span>, <span class="number">85.0</span>, <span class="number">95.0</span>, <span class="number">90.0</span>, <span class="number">80.0</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 1. 找出大于85分的学生,并按年龄升序排序,打印输出</span></span><br><span class="line"> score.stream().filter(x -> x > <span class="number">85</span>).sorted().forEach(System.out::println);</span><br><span class="line"></span><br><span class="line"> List<Student> students = <span class="keyword">new</span> <span class="title class_">ArrayList</span><>();</span><br><span class="line"> <span class="type">Student</span> <span class="variable">s1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Student</span>(<span class="string">"张三"</span>, <span class="number">20</span>, <span class="number">170.3</span>);</span><br><span class="line"> <span class="type">Student</span> <span class="variable">s2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Student</span>(<span class="string">"李四"</span>, <span class="number">21</span>, <span class="number">160.3</span>);</span><br><span class="line"> <span class="type">Student</span> <span class="variable">s3</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Student</span>(<span class="string">"王五"</span>, <span class="number">22</span>, <span class="number">180.5</span>);</span><br><span class="line"> <span class="type">Student</span> <span class="variable">s4</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Student</span>(<span class="string">"赵六"</span>, <span class="number">23</span>, <span class="number">165.2</span>);</span><br><span class="line"> <span class="type">Student</span> <span class="variable">s5</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Student</span>(<span class="string">"孙七"</span>, <span class="number">24</span>, <span class="number">175.8</span>);</span><br><span class="line"> <span class="type">Student</span> <span class="variable">s6</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Student</span>(<span class="string">"周八"</span>, <span class="number">25</span>, <span class="number">160.9</span>);</span><br><span class="line"> <span class="type">Student</span> <span class="variable">s7</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Student</span>(<span class="string">"周八"</span>, <span class="number">25</span>, <span class="number">160.2</span>);</span><br><span class="line"> Collections.addAll(students, s1, s2, s3, s4, s5, s6, s7);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 2. 找出所有年龄大于23岁,且小于30的学生,并按年龄降序输出</span></span><br><span class="line"> students.stream()</span><br><span class="line"> .filter(s -> s.getAge() > <span class="number">23</span> && s.getAge() <= <span class="number">30</span>)</span><br><span class="line"> .sorted((o1, o2) -> o2.getAge() - o1.getAge())</span><br><span class="line"> .forEach(System.out::println);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 3.取身高最高的前三名同学</span></span><br><span class="line"> students.stream()</span><br><span class="line"> .sorted((o1, o2) ->Double.compare(o2.getHeight(),o1.getHeight()))</span><br><span class="line"> .limit(<span class="number">3</span>)</span><br><span class="line"> .forEach(System.out::println);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 4.取出身高倒数的2名同学</span></span><br><span class="line"> students.stream()</span><br><span class="line"> .sorted((o1, o2) ->Double.compare(o2.getHeight(),o1.getHeight()))</span><br><span class="line"> .skip(students.size()-<span class="number">2</span>)</span><br><span class="line"> .forEach(System.out::println);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 5.找出身高超过165的同学,并按身高降序输出,并去除重复的学生</span></span><br><span class="line"> students.stream()</span><br><span class="line"> .filter(s -> s.getHeight() > <span class="number">165</span>)</span><br><span class="line"> .sorted((o1, o2) ->Double.compare(o2.getHeight(),o1.getHeight()))</span><br><span class="line"> .map(Student::getName)</span><br><span class="line"> .forEach(System.out::println);</span><br><span class="line"> </span><br><span class="line"> <span class="comment">//distinct()去重复,认为两个内容一样就认为是重复的(重写equals方法和hashcode方法)</span></span><br><span class="line"> students.stream()</span><br><span class="line"> .filter(s -> s.getHeight() > <span class="number">165</span>)</span><br><span class="line"> .sorted((o1, o2) ->Double.compare(o2.getHeight(),o1.getHeight()))</span><br><span class="line"> .distinct()</span><br><span class="line"> .forEach(System.out::println);</span><br><span class="line"> </span><br><span class="line"> <span class="comment">//合并两个Stream流</span></span><br><span class="line"> Stream<String> stream1 = Stream.of(<span class="string">"a"</span>, <span class="string">"b"</span>, <span class="string">"c"</span>);</span><br><span class="line"> Stream<String> stream2 = Stream.of(<span class="string">"d"</span>, <span class="string">"e"</span>, <span class="string">"f"</span>);</span><br><span class="line"> Stream<String> stream3 = Stream.concat(stream1, stream2);</span><br><span class="line"> stream3.forEach(System.out::println);</span><br><span class="line"></span><br><span class="line"> }</span><br></pre></td></tr></table></figure><p>终结方法</p><table><thead><tr><th>Stream流常用终结方法</th><th>说明</th></tr></thead><tbody><tr><td>void forEach(Consumer<? super T> action)</td><td>遍历数据</td></tr><tr><td>long count()</td><td>返回流中元素总数</td></tr><tr><td>Optional<T> findFirst()</td><td>返回流中第一个元素</td></tr><tr><td>Optional<T> findAny()</td><td>返回流中任意元素</td></tr><tr><td>Optional<T> max(Comparator<? super T> comparator)</td><td>返回流中最大值</td></tr><tr><td>Optional<T> min(Comparator<? super T> comparator)</td><td>返回流中最小值</td></tr><tr><td>void close()</td><td>关闭流,释放资源</td></tr></tbody></table><h3 id="IO流">IO流</h3><p>用于读写数据,或网络中的数据。</p><ul><li>字节输入流:以内存为基准,来自磁盘文件/网络中的数据以字节的形式读入到内存中去的流</li><li>字节输出流:以内存为基准,把内存中的数据以字节写出到磁盘文件或者网络中去的流</li><li>字符输入流:以内存为基准,来自磁盘文件/网络中的数据以字符的形式读入到内存中去的流</li><li>字符输出流:以内存为基准,把内存中的数据以字符写出到磁盘文件或者网络介质中去的流。<br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/23.png" alt="23"></li></ul><h4 id="字节流">字节流</h4><ol><li>FileInputStream(文件字节输入流)</li></ol><table><thead><tr><th>构造器</th><th>说明</th></tr></thead><tbody><tr><td>FileInputStream(File file)</td><td>创建一个文件字节输入流,用于读取文件</td></tr><tr><td>FileInputStream(String name)</td><td>创建一个文件字节输入流,用于读取文件</td></tr></tbody></table><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>int read()</td><td>读取一个字节,并返回该字节所对应的ASCII码值</td></tr><tr><td>int read(byte[] b)</td><td>读取一个字节数组,并返回该字节数组的长度</td></tr><tr><td>int read(byte[] b, int off, int len)</td><td>读取一个字节数组,并返回该字节数组的长度</td></tr></tbody></table><ol start="2"><li>FileOutputStream(文件字节输出流)</li></ol><table><thead><tr><th>构造器</th><th>说明</th></tr></thead><tbody><tr><td>FileOutputStream(File file)</td><td>创建一个文件字节输出流,用于写入文件</td></tr><tr><td>FileOutputStream(String name)</td><td>创建一个文件字节输出流,用于写入文件</td></tr><tr><td>FileOutputStream(File file, boolean append)</td><td>创建一个文件字节输出流,用于写入文件,可追加数据</td></tr><tr><td>FileOutputStream(String name, boolean append)</td><td>创建一个文件字节输出流,用于写入文件,可追加数据</td></tr></tbody></table><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>void write(int b)</td><td>写入一个字节</td></tr><tr><td>void write(byte[] b)</td><td>写入一个字节数组</td></tr><tr><td>void write(byte[] b, int off, int len)</td><td>写入一个字节数组</td></tr><tr><td>void close() throws IOException</td><td>关闭流,释放资源</td></tr></tbody></table><p>文件复制案例</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><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></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 class="keyword">throws</span> Exception {</span><br><span class="line"> <span class="comment">// 1.创建输入流对象</span></span><br><span class="line"> <span class="type">InputStream</span> <span class="variable">is</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">FileInputStream</span>((<span class="string">"E:\\JAVA Project\\JavaCode\\src\\com\\abc.txt"</span>));</span><br><span class="line"> <span class="comment">// 2.创建输出流对象</span></span><br><span class="line"> <span class="type">OutputStream</span> <span class="variable">os</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">FileOutputStream</span>((<span class="string">"E:\\JAVA Project\\JavaCode\\src\\com\\abc1.txt"</span>));</span><br><span class="line"> <span class="comment">// 3.创建字节数组用来转移数据</span></span><br><span class="line"> <span class="type">byte</span>[] data = <span class="keyword">new</span> <span class="title class_">byte</span>[<span class="number">1024</span>];</span><br><span class="line"> <span class="comment">// 4.循环读取输入流中的数据,并写入到输出流中</span></span><br><span class="line"> <span class="type">int</span> len ;</span><br><span class="line"> <span class="keyword">while</span> ((len = is.read(data))!= -<span class="number">1</span>) {</span><br><span class="line"> os.write(data, <span class="number">0</span>, len);</span><br><span class="line"> }</span><br><span class="line"> os.close();</span><br><span class="line"> is.close();</span><br><span class="line"> System.out.println(<span class="string">"文件复制成功"</span>);</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><h4 id="字符流">字符流</h4><p>适合读写文本文件内容</p><ul><li>字符输入流:以内存为基准,来自磁盘文件/网络中的数据以字符的形式读入到内存中去的流</li><li>字符输出流:以内存为基准,把内存中的数据以字符写出到磁盘文件或者网络介质中去的流。</li></ul><ol><li>FileReader(文件字符输入流)</li></ol><table><thead><tr><th>构造器</th><th>说明</th></tr></thead><tbody><tr><td>FileReader(File file)</td><td>创建一个文件字符输入流,用于读取文件</td></tr><tr><td>FileReader(String name)</td><td>创建一个文件字符输入流,用于读取文件</td></tr></tbody></table><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>int read()</td><td>读取一个字符,并返回该字符所对应的ASCII码值</td></tr><tr><td>int read(char[] cbuf)</td><td>读取一个字符数组,并返回该字符数组的长度</td></tr><tr><td>int read(char[] cbuf, int off, int len)</td><td>读取一个字符数组,并返回该字符数组的长度</td></tr></tbody></table><ol start="2"><li>FileWriter(文件字符输出流)</li></ol><blockquote><p>字符输出流写出数据后,必须刷新流(调用flush()方法进行刷新该字符流通道还能继续使用)<br>或者关闭流(调用close()方法,默认先进行刷新操作),写出去的数据才能生效</p></blockquote><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>public static void flush() throws IOException</td><td>刷新流,将内存中的数据写出到文件中</td></tr><tr><td>public void close() throws IOException</td><td>关闭流,释放资源,包含刷新</td></tr></tbody></table><table><thead><tr><th>构造器</th><th>说明</th></tr></thead><tbody><tr><td>FileWriter(File file)</td><td>创建一个文件字符输出流,用于写入文件</td></tr><tr><td>FileWriter(String name)</td><td>创建一个文件字符输出流,用于写入文件</td></tr><tr><td>FileWriter(File file, boolean append)</td><td>创建一个文件字符输出流,用于写入文件,可追加数据</td></tr><tr><td>FileWriter(String name, boolean append)</td><td>创建一个文件字符输出流,用于写入文件,可追加数据</td></tr></tbody></table><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>void write(int c)</td><td>写入一个字符</td></tr><tr><td>void write(char[] cbuf)</td><td>写入一个字符数组</td></tr><tr><td>void write(char[] cbuf, int off, int len)</td><td>写入一个字符数组</td></tr><tr><td>void close() throws IOException</td><td>关闭流,释放资源</td></tr></tbody></table><blockquote><p>字节流、字符流的使用场景小结</p><ul><li>字节流适合做一切文件数据的拷贝(音视频,文本);</li><li>字节流不适合读取中文内容输出</li><li>字符流适合做文本文件的操作(读,写)。</li></ul></blockquote><h4 id="缓冲流">缓冲流</h4><ul><li>缓冲流:在流的基础上,添加缓冲功能,提高流的读写效率。</li><li>原理:字节缓冲输入流自带了8KB缓冲池;字节缓冲输出流也自带了8KB缓冲池<br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/24.png" alt="24"></li></ul><ol><li>BufferedReader(字符缓冲输入流)</li></ol><table><thead><tr><th>构造器</th><th>说明</th></tr></thead><tbody><tr><td>BufferedReader(Reader in)</td><td>创建一个字符缓冲输入流,用于读取文件</td></tr></tbody></table><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>String readLine()</td><td>读取一行字符串,并返回该字符串</td></tr><tr><td>void close() throws IOException</td><td>关闭流,释放资源</td></tr></tbody></table><ol start="2"><li>BufferedWriter(字符缓冲输出流)</li></ol><table><thead><tr><th>构造器</th><th>说明</th></tr></thead><tbody><tr><td>BufferedWriter(Writer out)</td><td>创建一个字符缓冲输出流,用于写入文件</td></tr></tbody></table><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>void write(String s)</td><td>写入一个字符串</td></tr><tr><td>void newLine()</td><td>写入一个换行符</td></tr><tr><td>void close() throws IOException</td><td>关闭流,释放资源</td></tr></tbody></table><blockquote><ul><li>低级字节流通过改变字节数组的大小可以提高性能</li><li>缓冲流通过改变字节数组大小同时改变缓冲池大小也可以提高性能</li><li>以一个字节一个字节的方式适合小文件,大文件被淘汰。性能差</li></ul></blockquote><h4 id="转换流">转换流</h4><ol><li>InputStreamReader(字符输入转换流)<ul><li>解决不同编码时,字符流读取文本内容乱码的问题。</li><li>解决思路:先获取文件的原始字节流,再将其按真实的字符集编码转成字符输入流,这样字符输入流中的字符就不乱码了</li></ul></li></ol><table><thead><tr><th>构造器</th><th>说明</th></tr></thead><tbody><tr><td>InputStreamReader(InputStream in)</td><td>创建一个字符输入转换流,用于读取文件</td></tr><tr><td>InputStreamReader(InputStream in, String charsetName)</td><td>创建一个字符输入转换流,用于读取文件</td></tr></tbody></table><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>int read()</td><td>读取一个字符,并返回该字符所对应的ASCII码值</td></tr><tr><td>int read(char[] cbuf)</td><td>读取一个字符数组,并返回该字符数组的长度</td></tr><tr><td>int read(char[] cbuf, int off, int len)</td><td>读取一个字符数组,并返回该字符数组的长度</td></tr><tr><td>void close() throws IOException</td><td>关闭流,释放资源</td></tr></tbody></table><ol start="2"><li>OutputStreamWriter(字符输出转换流)<ul><li>作用:可以控制写出去的字符使用什么字符集编码。</li><li>解决思路:获取字节输出流,再按照指定的字符集编码将其转换成字符输出流,以后写出去的字符就会用该字符集编码了</li></ul></li></ol><table><thead><tr><th>构造器</th><th>说明</th></tr></thead><tbody><tr><td>OutputStreamWriter(OutputStream out)</td><td>创建一个字符输出转换流,用于写入文件</td></tr><tr><td>OutputStreamWriter(OutputStream out, String charsetName)</td><td>创建一个字符输出转换流,用于写入文件</td></tr></tbody></table><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>void write(int c)</td><td>写入一个字符</td></tr><tr><td>void write(char[] cbuf)</td><td>写入一个字符数组</td></tr><tr><td>void write(char[] cbuf, int off, int len)</td><td>写入一个字符数组</td></tr><tr><td>void close() throws IOException</td><td>关闭流,释放资源</td></tr></tbody></table><h4 id="打印流">打印流</h4><ul><li>作用:打印流可以实现更方便、更高效的打印数据出去,能实现打印啥出去就是啥出去</li></ul><ol><li>PrintStream</li></ol><table><thead><tr><th>构造器</th><th>说明</th></tr></thead><tbody><tr><td>PrintStream(String fileName)</td><td>创建一个打印流,用于写入文件</td></tr><tr><td>PrintStream(File file)</td><td>创建一个打印流,用于写入文件</td></tr><tr><td>PrintStream(OutputStream out,boolean autoFlush)</td><td>实现自动刷新,创建一个打印流,用于写入文件</td></tr><tr><td>PrintStream(OutputStream out,boolean autoFlush,String encodingName)</td><td>实现自动刷新,指定编码方式</td></tr><tr><td>PrintStream(String fileName, String charsetName)</td><td>创建一个打印流,用于写入文件</td></tr></tbody></table><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>void print(xxx xx)</td><td>打印任意类型的数据</td></tr><tr><td>void write(int/byte[]/byte[]一部分)</td><td>可以支持写字节数据</td></tr></tbody></table><ol start="2"><li>PrintWriter</li></ol><table><thead><tr><th>构造器</th><th>说明</th></tr></thead><tbody><tr><td>public PrintWriter(OutputStream/Writer/File/String)</td><td>打印流直接通向字节输出流/文件/文件路径</td></tr><tr><td>public PrintWriter(string fileName, Charset charset)</td><td>可以指定写出去的字符编码</td></tr><tr><td>public PrintWriter(OutputStream out/Writer,boolean autoFlush)</td><td>实现自动刷新</td></tr><tr><td>public PrintWriter(OutputStream out,boolean autoFlush, String encoding)</td><td>实现自动刷新,指定编码方式</td></tr></tbody></table><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>void print(xxx xx)</td><td>打印任意类型的数据</td></tr><tr><td>void write(int/char[]/string/…)</td><td>可以支持写字符数据</td></tr></tbody></table><h4 id="数据流">数据流</h4><ol><li>DataOutputStream(数据输出流)<ul><li>作用:可以将基本数据类型的数据写出去,并且可以控制写出去的字符使用什么字符集编码。</li></ul></li></ol><table><thead><tr><th>构造器</th><th>说明</th></tr></thead><tbody><tr><td>DataOutputStream(OutputStream out)</td><td>创建一个数据输出流,用于写入文件</td></tr></tbody></table><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>void writeInt(int v)</td><td>写入一个int类型的数据</td></tr><tr><td>void writeByte(byte v)</td><td>写入一个byte类型的数据</td></tr><tr><td>void writeDouble(double v)</td><td>写入一个double类型的数据</td></tr><tr><td>void writeUTF(String str)</td><td>写入一个字符串</td></tr><tr><td>void close() throws IOException</td><td>关闭流,释放资源</td></tr></tbody></table><ol start="2"><li>DataInputStream(数据输入流)<ul><li>作用:可以将基本数据类型的数据读进来,并且可以控制读进来的字符使用什么字符集编码。</li></ul></li></ol><table><thead><tr><th>构造器</th><th>说明</th></tr></thead><tbody><tr><td>DataInputStream(InputStream in)</td><td>创建一个数据输入流,用于读取文件</td></tr></tbody></table><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>int readInt()</td><td>读取一个int类型的数据</td></tr><tr><td>byte readByte()</td><td>读取一个byte类型的数据</td></tr><tr><td>double readDouble()</td><td>读取一个double类型的数据</td></tr><tr><td>String readUTF()</td><td>读取一个字符串</td></tr><tr><td>void close() throws IOException</td><td>关闭流,释放资源</td></tr></tbody></table><blockquote><ul><li>读取和写入顺序要一致,否则会报错,及输入输出要对应</li></ul></blockquote><h4 id="序列化流">序列化流</h4><blockquote><p>对象序列化:把Java对象写入到文件中去<br>对象反序列化:把文件的Java对象读出来<br>对象如果要实现序列化必须要实现序列化接口(Serializable)</p></blockquote><ol><li>ObjectOutputStream(对象输出流)<ul><li>作用:可以将Java对象序列化,并且把Java对象存在文件中。</li></ul></li></ol><table><thead><tr><th>构造器</th><th>说明</th></tr></thead><tbody><tr><td>ObjectOutputStream(OutputStream out)</td><td>创建一个对象输出流,用于写入文件</td></tr></tbody></table><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>void writeObject(Object obj)</td><td>写入一个Java对象</td></tr><tr><td>void close() throws IOException</td><td>关闭流,释放资源</td></tr></tbody></table><ol start="2"><li>ObjectInputStream(对象输入流)<ul><li>作用:可以将Java对象反序列化,并且把存在文件中的Java对象读入内存中。</li></ul></li></ol><table><thead><tr><th>构造器</th><th>说明</th></tr></thead><tbody><tr><td>ObjectInputStream(InputStream in)</td><td>创建一个对象输入流,用于读取文件</td></tr></tbody></table><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>Object readObject()</td><td>读取一个Java对象</td></tr><tr><td>void close() throws IOException</td><td>关闭流,释放资源</td></tr></tbody></table><blockquote><p>transient 代表该属性不参与序列化,即不被序列化<br>如果一次性序列化多个对象,可以用ArrayList集合存储对象,然后直接对集合进行序列化即可<br>ArrayList集合已经实现了序列化接口</p></blockquote><h4 id="IO框架">IO框架</h4><p>Commons-IO</p><ul><li>作用:对IO流进行高级封装,简化IO流编程</li><li>下载地址:<a href="https://commons.apache.org/proper/commons-io/download_io.cgi">https://commons.apache.org/proper/commons-io/download_io.cgi</a></li><li>使用步骤:<ol><li>导入commons-io-1.3.2.jar</li><li>使用IOUtils类中的方法</li></ol></li></ul><p>常用方法:</p><table><thead><tr><th>FileUtils类提供的部分方法</th><th>说明</th></tr></thead><tbody><tr><td>void copyFile(File srcFile, File destFile)</td><td>复制文件</td></tr><tr><td>void copyDirectory(File srcDir, File destDir)</td><td>复制目录</td></tr><tr><td>void deleteDirectory(File dir)</td><td>删除目录</td></tr><tr><td>void deleteFile(File file)</td><td>删除文件</td></tr><tr><td>boolean isDirectory(File file)</td><td>判断是否是目录</td></tr><tr><td>boolean isFile(File file)</td><td>判断是否是文件</td></tr><tr><td>boolean isHidden(File file)</td><td>判断是否是隐藏文件</td></tr><tr><td>boolean exists(File file)</td><td>判断文件是否存在</td></tr></tbody></table><table><thead><tr><th>IOUtils类提供的部分方法</th><th>说明</th></tr></thead><tbody><tr><td>long copy(InputStream in, OutputStream out)</td><td>复制流中的数据</td></tr><tr><td>String readFileToString(File file, Charset charset)</td><td>读取文件中的数据</td></tr><tr><td>void writeStringToFile(File file, String data, Charset charset)</td><td>写数据到文件中</td></tr><tr><td>void write(byte[] data, OutputStream out)</td><td>写字节数组到输出流中</td></tr><tr><td>void copy(Reader in, Writer out)</td><td>复制文件</td></tr></tbody></table><h3 id="特殊文件,日志">特殊文件,日志</h3><ol><li><p>.properties属性文件</p><ul><li>作用:用于存储配置信息</li><li>只能存储键值对信息</li><li>键不能重复</li><li>文件后缀一般是.properties</li></ul></li><li><p>xml文件</p><ul><li>XML( 全称EXtensible Markup Language,可扩展标记语言 )本质是一种数据的格式,可以用来存储复杂的数据结构,和数据关系。</li><li>XML的特点</li><li>XML中的“<标签名>” 称为一个标签或一个元素,一般是成对出现的XML中的标签名可以自己定义 (可扩展),但必须要正确的嵌套</li><li>XML中只能有一个根标签。</li><li>XML中的标签可以有属性。</li><li>如果一个文件中放置的是XML格式的数据,这个文件就是XML文件,后缀一般为.xml</li></ul></li></ol><blockquote><p>XML文件语法规则:</p><ul><li>< : 代表小于号</li><li>> : 代表大于号</li><li>& : 代表和号</li><li>" : 代表引号</li><li>' : 代表单引号</li><li> : 代表空格</li></ul></blockquote><ol start="3"><li>日志技术<br>可以将系统执行的信息,方便的记录到指定的位置(控制台、文件中、数据库中)可以随时以开关的形式控制日志的启停,无需侵入到源代码中去进行修改普遍使用slf4j日志框架,进行日志的记录</li></ol><table><thead><tr><th>属性</th><th>说明</th></tr></thead><tbody><tr><td>trace</td><td>最详细的日志信息,一般不会使用</td></tr><tr><td>debug</td><td>调试信息</td></tr><tr><td>info</td><td>运行信息</td></tr><tr><td>warn</td><td>警告信息</td></tr><tr><td>error</td><td>错误信息</td></tr><tr><td>fatal</td><td>致命错误信息</td></tr></tbody></table><h3 id="线程">线程</h3><h4 id="多线程">多线程</h4><p>多线程是指从软硬件上实现的多条执行流程的技术(多条线程由CPU负责调度执行)</p><ol><li>多线程的创建方式一:继承Thread类<ul><li>定义一个子类MyThread继承线程类java.lang.Thread,重写run()方法</li><li>创建MyThread类的对象</li><li>调用线程对象的start()方法启动线程(启动后还是执行run方法的)</li></ul></li></ol><p><strong>多线程的注意事项</strong></p><blockquote><p>1、启动线程必须是调用start方法,不是调用run方法</p><ul><li> 直接调用run方法会当成普通方法执行,此时相当于还是单线程执行</li><li> 只有调用start方法才是启动一个新的线程执行</li></ul><p>2、不要把主线程任务放在启动子线程之前</p><ul><li>这样主线程一直是先跑完的,相当于是一个单线程的效果了</li></ul></blockquote><ol start="2"><li>多线程的创建方式二:实现Runnable接口<ul><li>定义一个线程任务类MyRunnable实现Runnable接口,重写run方法</li><li>创建MyRunnable任务对象</li><li>把MyRunnable任务对象交给Thread处理</li><li>调用线程对象的start()方法启动线程</li></ul></li></ol><blockquote><p>方式二的优缺点</p><ul><li>优点:任务类只是实现接口,可以继续继承其他类、实现其他接口,扩展性强</li><li>缺点:需要多一个Runnable对象</li></ul></blockquote><ol start="3"><li>多线程的第三种创建方式:利用Callable接口、FutureTask类来实现<ul><li>创建任务对象</li><li>定义一个类实现Callable接口,重写call方法,封装要做的事情,和要返回的数据把Callable类型的对象封装成FutureTask (线程任务对象)</li><li>把线程任务对象交给Thread对象</li><li>调用Thread对象的start方法启动线程</li><li>线程执行完毕后、通过FutureTask对象的的get方法去获取线程任务执行的结果</li></ul></li></ol><blockquote><p>注意:如果线程没有执行完毕,或有多个线程则(FutureTask对象的的get方法)会等待线程执行完毕,才会通过此方法进行输出结果</p></blockquote><table><thead><tr><th>构造器</th><th>说明</th></tr></thead><tbody><tr><td>public FutureTask(Callable<V> callable)</td><td>创建一个Callable类型的任务对象</td></tr></tbody></table><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>V get()</td><td>获取线程执行完毕后的结果</td></tr></tbody></table><ol start="4"><li>线程创建方式三的优缺点</li></ol><blockquote><p>优点:线程任务类只是实现接口,可以继续继承类和实现接口,扩展性强,可以在 线程执行完毕后 去获取线程执行的结果.</p><p>缺点:编码复杂一点。</p></blockquote><table><thead><tr><th>Thread提供的构造器</th><th>说明</th></tr></thead><tbody><tr><td>public Thread()</td><td>创建一个新线程</td></tr><tr><td>public Thread(Runnable target)</td><td>创建一个新线程</td></tr><tr><td>public Thread(Runnable target, String name)</td><td>创建一个新线程并指定线程名</td></tr></tbody></table><table><thead><tr><th>Thread提供方法</th><th>说明</th></tr></thead><tbody><tr><td>public void start()</td><td>启动线程,线程进入就绪状态,等待CPU调度</td></tr><tr><td>public void run()</td><td>线程执行体,线程启动后会自动调用run方法</td></tr><tr><td>public String getName()</td><td>获取线程的名称</td></tr><tr><td>public void setName(String name)</td><td>设置线程的名称</td></tr><tr><td>public static Thread currentThread()</td><td>获取当前线程对象</td></tr><tr><td>public static void sleep(long time)</td><td>让当前线程休眠指定的毫秒数</td></tr><tr><td>public void join()</td><td>等待线程执行完毕</td></tr></tbody></table><h4 id="线程安全">线程安全</h4><blockquote><p>多个线程,同时操作同一个共享资源的时候,可能会出现业务安全问题</p><p>出现原因:</p><ol><li>存在多个线程在同时执行</li><li>同时访问一个共享资源</li><li>存在修改该共享资源</li></ol></blockquote><h4 id="线程同步">线程同步</h4><blockquote><p>目的: 解决线程安全问题的方案<br>思想:让多个线程实现先后依次访问共享资源,这样就解决了安全问题<br>解决方案:<br>加锁: 每次只允许一个线程加锁,加锁后才能进入访问,访问完毕后自动解锁,然后其他线程才能再加锁进来</p></blockquote><p>方案一:同步代码块</p><blockquote><ol><li><p>作用: 把访问共享资源的核心代码给上锁,以此保证线程安全</p></li><li><p>原理: 每次只允许一个线程加锁后进入,:执行完毕后自动解锁,其他线程才可以进来执行</p></li><li><p>同步锁的注意事项:<br>对于当前同时执行的线程来说,同步锁必须是同一把(同一个对象),否则会出bug。</p></li><li><p>锁对象随便选择一个唯一的对象好不好呢?<br>不好,会影响其他无关线程的执行</p></li><li><p>锁对象的使用规范<br>建议使用共享资源作为锁对象,对于实例方法建议使用this作为锁对象<br>对于静态方法建议使用字节码 (类名.class)对象作为锁对象</p></li></ol></blockquote><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* synchronized ("佳得乐"){}//在其代码块中要有一个同步锁,当线程进来时要确保是同一个对象,这样其他线 程才会进不来,之所以用字符串对象作为锁,因为字符串有且只有一个,并存在于字符串常量池中</span></span><br><span class="line"><span class="comment">* 静态方法用 类名.class 作为锁</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">synchronized(同步锁){</span></span><br><span class="line"><span class="comment">访问共享资源的核心代码</span></span><br><span class="line"><span class="comment">}</span></span><br></pre></td></tr></table></figure><p>方案二:同步方法</p><blockquote><ol><li>作用:把访问共享资源的核心方法给上锁,以此保证线程安全。</li><li>原理:每次只能一个线程进入,执行完毕以后自动解锁,其他线程才可以进来执行</li><li>内部隐含一种锁,以(this)作为锁对象,如果方法是静态方法:同步方法默认用类名.class作为的锁对象。</li></ol></blockquote><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">修饰符 <span class="keyword">synchronized</span> 返回值类型 方法名称(形参列表){</span><br><span class="line">操作共享资源的代码</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>方案三:Lock锁</p><ol><li>Lock锁是DK5开始提供的一个新的锁定操作,通过它可以创建出锁对象进行加锁和解锁,更灵活、更方便、更强大</li><li>Lock是接口,不能直接实例化,可以采用它的实现类ReentrantLock来构建Lock锁对象。<ul><li>防止实例方法出现异常,并跳出方法体,不执行解锁操作,而造成资源的占用,其他线程无法访问,通常使用try-finally把方法体放在try{}块中,解锁操作放在finally{}块中,即使出现异常,也会执行解锁操作。</li><li>每个类的实例都会有一个锁对象,用来锁住自己,锁住共享资源,锁对象是唯一的,通常用final 来修饰锁对象,保证唯一性,不能被二次赋值。</li></ul></li></ol><table><thead><tr><th>构造器</th><th>说明</th></tr></thead><tbody><tr><td>public ReentrantLock()</td><td>创建一个ReentrantLock对象</td></tr></tbody></table><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>public void lock()</td><td>获取锁</td></tr><tr><td>public void unlock()</td><td>释放锁</td></tr></tbody></table><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Account</span> {</span><br><span class="line"><span class="comment">//方式三:设置lock锁,创建锁对象</span></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">final</span> <span class="type">Lock</span> <span class="variable">lk</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ReentrantLock</span>();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">Account</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">//public synchronized void drawMoney(double money) {</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">drawMoney</span><span class="params">(<span class="type">double</span> money)</span> {</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> Thread.currentThread().getName();</span><br><span class="line"> <span class="comment">//方式一:设置同步代码块,即上锁</span></span><br><span class="line"> <span class="comment">//synchronized ("佳得乐") {</span></span><br><span class="line"> lk.lock();<span class="comment">//上锁</span></span><br><span class="line"> <span class="keyword">if</span>(<span class="built_in">this</span>.money>=money){</span><br><span class="line"> System.out.println(name + <span class="string">"成功取款"</span> + money);</span><br><span class="line"> <span class="built_in">this</span>.money -= money;</span><br><span class="line"> System.out.println(<span class="built_in">this</span>.accountId + <span class="string">"余额为:"</span> + <span class="built_in">this</span>.money);</span><br><span class="line"> }<span class="keyword">else</span> {</span><br><span class="line"> System.out.println(name + <span class="string">"取款失败"</span>);</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">finally</span> {</span><br><span class="line"> lk.unlock();<span class="comment">//解锁</span></span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//}</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="线程通信">线程通信</h4><ol><li><p>什么是线程通信?<br>当多个线程共同操作共享的资源时,线程间通过某种方式互相告知自己的状态,以相互协调,并避免无效的资源争夺</p></li><li><p>线程通信的常见模型(生产者与消费者模型)</p><ul><li>生产者线程负责生产数据</li><li>消费者线程负责消费生产者生产的数据</li><li>注意: 生产者生产完数据应该等待自己,通知消费者消费;消费者消费完数据也应该等待自己,再通知生产者生产!</li></ul></li><li><p>线程通信的常用方法,Object类的等待唤醒和等待方法</p></li></ol><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>void wait()</td><td>等待,线程进入等待状态,直到被唤醒</td></tr><tr><td>void notify()</td><td>唤醒一个等待的线程</td></tr><tr><td>void notifyAll()</td><td>唤醒所有等待的线程</td></tr></tbody></table><ol start="4"><li>线程通信的注意事项<ul><li>等待和唤醒方法必须由同一个锁对象调用,否则会报错</li><li>等待和唤醒方法必须由同步代码块或者同步方法调用,否则会报错</li></ul></li></ol><h4 id="线程池">线程池</h4><ol><li><p>什么是线程池?</p><ul><li>线程池是管理线程的一个容器,可以管理多个线程,提高线程的复用率,减少线程的创建和销毁带来的开销,提高程序的性能</li><li>线程池是JDK1.5开始提供的一个新的线程管理工具,可以方便的创建线程池,并执行线程任务</li></ul></li><li><p>线程池的创建方式</p><ul><li>通过Executors工具类创建线程池</li></ul></li></ol><blockquote><p>作用:复用线程</p><ol><li>谁代表线程池?<br>JDK 5.0起提供了代表线程池的接口: <code>ExecutorService</code></li><li>如何得到线程池对象?<br>方式一:使用<code>ExecutorService</code>的实现类<code>ThreadPoolExecutor</code>自创建一个线程池对象。<br>方式二:使用<code>Executors</code>(线程池的工具类)调用方法返回不同特点的线程池对象</li></ol></blockquote><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/25.png" alt="25"></p><blockquote><p>参数一: corePoolsize: 指定线程池的核心线程的数量<br>参数二: maximumPoolSize: 指定线程池的最大线程数量<br>参数三: keepAliveTime: 指定临时线程的存活时间<br>参数四: unit:指定临时线程存活的时间单位(秒、分、时、天)<br>参数五: workQueue: 指定线程池的任务队列。<br>参数六: threadFactory: 指定线程池的线程工厂<br>参数七: handler:指定线程池的任务拒绝策略(线程都在忙,任务队列也满了的时候,新任务来了该怎么处理</p></blockquote><p>线程池的注意事项:<br>1、临时线程什么时候创建?<br>新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建临时线程<br>2、什么时候会开始拒绝新任务?<br>核心线程和临时线程都在忙,任务队列也满了,新的任务过来的时候才会开始拒绝任务<br>ExecutorService常用方法:</p><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>void execute(Runnable command)</td><td>执行任务</td></tr><tr><td>Future<?> submit(Runnable task)</td><td>执行任务,并返回一个Future对象</td></tr><tr><td>void shutdown()</td><td>等待线程池中的任务执行完毕,再关闭线程池</td></tr><tr><td>void shutdownNow()</td><td>立即关闭线程池,不执行任务</td></tr></tbody></table><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 1.创建线程池</span></span><br><span class="line"> <span class="type">ExecutorService</span> <span class="variable">p</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ThreadPoolExecutor</span>(<span class="number">3</span>,<span class="number">5</span>,<span class="number">8</span>,TimeUnit.SECONDS,</span><br><span class="line"> <span class="keyword">new</span> <span class="title class_">ArrayBlockingQueue</span><>(<span class="number">4</span>),</span><br><span class="line"> Executors.defaultThreadFactory(),</span><br><span class="line"> <span class="keyword">new</span> <span class="title class_">ThreadPoolExecutor</span>.AbortPolicy());</span><br><span class="line"> <span class="type">Runnable</span> <span class="variable">r</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyRunnable1</span>();</span><br><span class="line"> p.execute(r);<span class="comment">//自动创建线程,并自动执行任务</span></span><br><span class="line"> p.execute(r);<span class="comment">//自动创建线程,并自动执行任务</span></span><br><span class="line"> p.execute(r);<span class="comment">//自动创建线程,并自动执行任务</span></span><br><span class="line"></span><br><span class="line"> p.execute(r);<span class="comment">//复用前面的线程</span></span><br><span class="line"> p.execute(r);<span class="comment">//复用前面的线程</span></span><br><span class="line"> p.execute(r);</span><br><span class="line"> p.execute(r);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//p.shutdown();//等线程任务完成,再关闭线程池</span></span><br><span class="line"> <span class="comment">//p.shutdownNow();//立即关闭线程池</span></span><br><span class="line"> <span class="comment">//临时线程开始创建</span></span><br><span class="line"> p.execute(r);</span><br><span class="line"> p.execute(r);</span><br><span class="line"> <span class="comment">//开始拒绝新任务</span></span><br><span class="line"> p.execute(r);</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><p>新任务拒绝策略:</p><table><thead><tr><th>策略</th><th>说明</th></tr></thead><tbody><tr><td>ThreadPoolExecutor.AbortPolicy()</td><td>丢弃任务并抛出RejectedExecutionException异常</td></tr><tr><td>ThreadPoolExecutor.CallerRunsPolicy()</td><td>由调用线程处理该任务</td></tr><tr><td>ThreadPoolExecutor.DiscardOldestPolicy()</td><td>丢弃队列最前面的任务,然后重新尝试执行任务</td></tr><tr><td>ThreadPoolExecutor.DiscardPolicy()</td><td>直接丢弃任务,不予任何处理也不抛出异常</td></tr></tbody></table><h4 id="并发,并行">并发,并行</h4><ol><li>并发:(一个核心不断切换不同线程执行)<br>进程中的线程是由CPU负责调度执行的,但CPU能同时处理线程的数量有限,为了保证全部线程都能往前执行,CPU会轮询为系统的每个线程服务,由于CPU切换的速度很快,给我们的感觉这些线程在同时执行,这就是并发。</li><li>并行:(多个核心同时执行多个线程)在同一个时刻上,同时有多个线程在被CPU调度执行</li><li>多线程:并发,并行同时进行。</li><li>关于线程<ul><li>正在运行的程序(软件)就是一个独立的进程。</li><li>线程是属于进程的,一个进程中可以同时运行很多个线程。</li><li>进程中的多个线程其实是并发和并行执行的。</li></ul></li></ol><h4 id="线程的生命周期">线程的生命周期</h4><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/26.png" alt="26"></p><p>线程的六种状态:</p><table><thead><tr><th>线程状态</th><th>说明</th></tr></thead><tbody><tr><td>new(新建)</td><td>线程刚被创建,但是并未启动。</td></tr><tr><td>RUNNABLE(可运行)</td><td>线程已经调用了start(),等待CPU调度</td></tr><tr><td>BLOCKED(锁阻塞)</td><td>线程在执行的时候未竞争到锁对象,则该线程进入Blocked状态</td></tr><tr><td>WAITING(无限等待)</td><td>一个线程进入Waiting状态,另一个线程调用notify或者notifyAll方法才能够唤醒</td></tr><tr><td>TIME_WAITING(计时等待)</td><td>同waiting状态,有几个方法(sleep,wait)有超时参数,调用他们将进入Timed Waiting状态</td></tr><tr><td>TERMINATED(被终止)</td><td>因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡</td></tr></tbody></table><h3 id="网络通信">网络通信</h3><p><code>网络编程三要素</code></p><blockquote><p>网络通信的关键三要素<br>IP: 设备在网络中的地址,是唯一的标识。<br>端口: 应用程序在设备中唯一的标识<br>协议: 连接和数据在网络中传输的规则。</p></blockquote><p>IP地址:</p><ul><li>IP (Internet Protocol): 全称”互联网协议地址”,是分配给上网设备的唯一标志。</li><li>IP地址有两种形式:IPv4、IPv6</li><li>IPv4:(32bit 4字节)点分十进制表示法</li><li>IPv6:(128bit 16字节)分成8段表示,每段每四位编码成一个十六进制位表示,数之间用冒号 (:)分开。</li></ul><p>公网IP,内网IP</p><ul><li>公网IP:是可以连接互联网的IP地址;内网IP:也叫局域网P,只能组织机构内部使用</li><li>192.168开头的就是常见的局域网地址,范用即为192.168.0.0–192.168.255.255,专门为组织机构内部使用</li></ul><p>特殊IP地址</p><ul><li>127.0.0.1、localhost: 代表本机IP,只会寻找当前所在的主机。</li></ul><p>IP常用命令:</p><ul><li>ipconfig: 查看本机IP地址</li><li>pingIP地址:检查网络是否连通</li></ul><p><code>InterAddress</code>:代表IP地址</p><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>InetAddress(String host)</td><td>根据主机名创建InetAddress对象</td></tr><tr><td>InetAddress(String host, int port)</td><td>根据主机名和端口号创建InetAddress对象</td></tr><tr><td>InetAddress getLocalHost()</td><td>获取本机InetAddress对象</td></tr><tr><td>InetAddress getByName(String host)</td><td>根据主机名获取InetAddress对象</td></tr><tr><td>String getHostAddress()</td><td>获取IP地址</td></tr><tr><td>String getHostName()</td><td>获取主机名</td></tr></tbody></table><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><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 class="keyword">throws</span> Exception {</span><br><span class="line"> <span class="type">InetAddress</span> <span class="variable">ip1</span> <span class="operator">=</span> InetAddress.getLocalHost();</span><br><span class="line"> System.out.println(ip1.getHostName());</span><br><span class="line"> System.out.println(ip1.getHostAddress());</span><br><span class="line"> </span><br><span class="line"> <span class="type">InetAddress</span> <span class="variable">ip2</span> <span class="operator">=</span> InetAddress.getByName(<span class="string">"www.baidu.com"</span>);</span><br><span class="line"> System.out.println(ip2.getHostName());</span><br><span class="line"> System.out.println(ip2.getHostAddress());</span><br><span class="line"> System.out.println(ip2.isReachable(<span class="number">1000</span>));</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><blockquote><p><strong>端口</strong></p><ul><li>标记正在计算机设备上运行的应用程序的,被规定为一个 16 位的二进制,范围是0~65535。</li></ul><p>分类</p><ul><li><p>周知端口:0~1023,被预先定义的知名应用占用(如: HTTP占用80,FTP占用21)</p></li><li><p>注册端口:1024~49151,分配给用户进程或某些应用程序</p></li><li><p>动态端口:49152到65535,之所以称为动态端口,是因为它一般不固定分配某种进程,而是动态分配</p></li><li><p>注意:我们自己开发的程序一般选择使用注册端口,且一个设备中不能出现两个程序的端口号一样,否则出错</p></li></ul></blockquote><p><strong>传输协议</strong><br>OSI网络参考模型:全球网络互联标准<br>TCP/IP网络模型:事实上的国际标准。</p><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/27.png" alt="27"></p><p>一、UDP协议<br>特点: 无连接、不可靠通信、传输效率高</p><p>不事先建立连接,数据按照包发,一包数据包含:自己的IP、程序端口,目的地IP、程序端口和数据(限制在64KB内)等发送方不管对方是否在线,数据在中间丢失也不管,如果接收方收到数据也不返回确认,故是不可靠的。</p><p>业务场景:语音通话,视频直播。</p><p>二、TCP协议</p><blockquote><p>可靠通信特点: 面向连接、可靠通信、传输效率相对不高<br>TCP的最终目的:要保证在不可靠的信道上实现可靠的传输<br>TCP主要有三个步骤实现可靠传输:</p><ol><li><p>三次握手建立连接</p><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/28.png" alt="28"></p><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/29.png" alt="29"></p></li><li><p>传输数据进行确认</p></li><li><p>四次挥手断开连接</p><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/30.png" alt="30"></p><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/31.png" alt="31"></p></li></ol></blockquote><h3 id="Java高级">Java高级</h3><h4 id="单元测试">单元测试</h4><p>就是针对最小的功能单元(方法),编写测试代码对其进行正确性测试</p><h4 id="反射">反射</h4><p>反射就是:加载类,并允许以编程的方式解剖类中的各种成分(成员变量、方法、构造器等)</p><p>1、反射第一步:加载类,获取类的字节码: Class对象<br>2、获取类的构造器: Constructor对象<br>3、获取类的成员变量: Field对象<br>5、获取类的成员方法: Method对象</p><blockquote><p>获取Class对象的三种方式<br>1、Class c1=类名.class<br>2、调用Class提供方法: public static Class forName(String package);<br>3、Object提供的方法: public Class getClass(); Class c3 = 对象.getClass();</p></blockquote><ol><li>获取构造器</li></ol><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>Constructor getConstructor(Class<?>… parameterTypes)</td><td>根据参数类型获取构造器</td></tr><tr><td>Constructor[] getConstructors()</td><td>获取所有公共构造器</td></tr><tr><td>Constructor getDeclaredConstructor(Class<?>… parameterTypes)</td><td>根据参数类型获取构造器</td></tr><tr><td>Constructor[] getDeclaredConstructors()</td><td>获取所有构造器</td></tr></tbody></table><ol start="2"><li>获取成员变量</li></ol><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>Field getField(String name)</td><td>根据成员变量名获取公共成员变量</td></tr><tr><td>Field[] getFields()</td><td>获取所有公共成员变量</td></tr><tr><td>Field getDeclaredField(String name)</td><td>根据成员变量名获取成员变量</td></tr><tr><td>Field[] getDeclaredFields()</td><td>获取所有成员变量</td></tr></tbody></table><ol start="3"><li>获取成员方法</li></ol><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>Method getMethod(String name, Class<?>… parameterTypes)</td><td>根据方法名和参数类型获取公共方法</td></tr><tr><td>Method[] getMethods()</td><td>获取所有公共方法</td></tr><tr><td>Method getDeclaredMethod(String name, Class<?>… parameterTypes)</td><td>根据方法名和参数类型获取方法</td></tr><tr><td>Method[] getDeclaredMethods()</td><td>获取所有方法</td></tr></tbody></table><ol start="4"><li>作用,应用场景<br>存任意对象的字段和其数据到文件中去</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Student</span> {</span><br><span class="line"> <span class="keyword">private</span> String name;</span><br><span class="line"> <span class="keyword">private</span> <span class="type">int</span> age;</span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">Student</span><span class="params">()</span> {</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">Student</span><span class="params">(String name, <span class="type">int</span> age)</span> {</span><br><span class="line"> <span class="built_in">this</span>.name = name;</span><br><span class="line"> <span class="built_in">this</span>.age = age;</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> <span class="type">int</span> <span class="title function_">getAge</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> age;</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_">setAge</span><span class="params">(<span class="type">int</span> age)</span> {</span><br><span class="line"> <span class="built_in">this</span>.age = age;</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="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Test1</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_">save</span><span class="params">()</span> <span class="keyword">throws</span> Exception {</span><br><span class="line"> <span class="type">Student</span> <span class="variable">s</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Student</span>(<span class="string">"刘佳乐"</span>,<span class="number">20</span>);</span><br><span class="line"> ObjectFrame.saveObject(s);</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="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ObjectFrame</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_">saveObject</span><span class="params">(Object obj)</span> <span class="keyword">throws</span> Exception {</span><br><span class="line"> <span class="comment">//创建打印流</span></span><br><span class="line"> <span class="type">PrintStream</span> <span class="variable">ps</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">PrintStream</span>(<span class="keyword">new</span> <span class="title class_">FileOutputStream</span>(<span class="string">"E:\\JAVA Project\\JavaCode\\src\\com\\FS\\abc.txt"</span>), <span class="literal">true</span>);</span><br><span class="line"> <span class="comment">//获取类的class对象,obj是任意对象,到底有多少个字段要保存。</span></span><br><span class="line"> <span class="type">Class</span> <span class="variable">c</span> <span class="operator">=</span> obj.getClass();</span><br><span class="line"> <span class="comment">//得到类的简写,也就是类名</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">str</span> <span class="operator">=</span> c.getSimpleName();</span><br><span class="line"> ps.println(<span class="string">"---------"</span> + str + <span class="string">"-------------"</span>);</span><br><span class="line"> <span class="comment">//从这个类中提取它的全部成员变量</span></span><br><span class="line"> Field[] fields = c.getDeclaredFields();</span><br><span class="line"> <span class="comment">//遍历每个成员变量</span></span><br><span class="line"> <span class="keyword">for</span> (Field f : fields) {</span><br><span class="line"> <span class="comment">//拿到这个成员变量在对象中的数据。</span></span><br><span class="line"> f.setAccessible(<span class="literal">true</span>);<span class="comment">//禁止检查访问权限</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> f.getName();</span><br><span class="line"> <span class="type">String</span> <span class="variable">value</span> <span class="operator">=</span> f.get(obj) + <span class="string">""</span>;</span><br><span class="line"> ps.println(name + <span class="string">":"</span> + value);</span><br><span class="line"> }</span><br><span class="line"> ps.close();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="注解">注解</h4><blockquote><p>Java代码里的特殊标记,比如: @Override、@Test等<br>作用:让其他程序根据注解信息来决定怎么执行该程序<br>注意:注解可以用在类上、构造器上、方法上、成员变量上、参数上、等位置处。</p></blockquote><ol><li>自定义注解<br>就是自己定义注解。</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="meta">@interface</span> 注解名称{</span><br><span class="line"> <span class="keyword">public</span> 属性类型 属性名() defult 默认值;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>特殊属性名: value<br>如果注解中只有一个value属性,使用注解时,value名称可以不写!!<br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/32.png" alt="32"></p><ol start="2"><li><p>元注解<br>元注解是用于修饰注解的注解,比如: @Target、@Retention<br>@Target:指定注解可以修饰哪些位置<br>@Retention:指定注解的生命周期<br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/33.png" alt="33"></p></li><li><p>注解解析<br>就是判断类上、方法上、成员变量上是否存在注解,并把注解里的内容给解析出来。</p></li></ol><blockquote><p>如何解析注解?</p><ol><li>要解析谁上面的注解,就应该先拿到谁</li><li>比如要解析类上面的注解,则应该先获取该类的CLass对象,再通过Clas5对象解析其上面的注解</li><li>比如要解析成员方法上的注解,则应该获取到该成员方法的Method对象,再通过Method对象解析其上面的注解。</li><li>Class、Method、Field,nstructor、都实现了AnnotatedElement接口,它们都拥有解析注解的能力</li></ol></blockquote><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Test1</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_">test</span><span class="params">()</span> <span class="keyword">throws</span> Exception {</span><br><span class="line"> <span class="comment">//获取类上的注解</span></span><br><span class="line"> <span class="type">Class</span> <span class="variable">c</span> <span class="operator">=</span> Student.class;</span><br><span class="line"> Annotation[] anns = c.getAnnotations();</span><br><span class="line"> <span class="keyword">for</span> (Annotation a : anns) {</span><br><span class="line"> <span class="keyword">if</span> (a <span class="keyword">instanceof</span> MyAnnotation) {</span><br><span class="line"> <span class="type">MyAnnotation</span> <span class="variable">ma</span> <span class="operator">=</span> (MyAnnotation) a;</span><br><span class="line"> System.out.println(ma.value());</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="动态代理">动态代理</h4><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Java/34.png" alt="34"></p>]]></content>
<categories>
<category> Java </category>
</categories>
<tags>
<tag> Java </tag>
</tags>
</entry>
<entry>
<title>面试题总结</title>
<link href="/posts/a80ea308.html"/>
<url>/posts/a80ea308.html</url>
<content type="html"><![CDATA[<h1>面试之道</h1><h2 id="1-项目相关">1. 项目相关</h2><h3 id="1-1-详细说明你的项目">1.1 详细说明你的项目</h3><blockquote><p>从以下几个方面进行项目介绍<br>1、项目的背景,包括:是自研还是外包、什么业务、服务的客户群是谁、谁去运营等问题<br>2、项目的业务流程<br>3、项目的功能模块<br>4、项目的技术架构<br>5、个人工作职责<br>6、个人负责模块的详细说明,包括模块的设计,所用到的技术,技术的实现方案等</p></blockquote><p>案例:</p><p>我最近参与的项目是我们公司自研的专门针对成人职业技能教育的网络课堂系统,网站提供了成人职业技能培训的相关课程,如:软件开发培训、职业资格证书培训、成人学历教育培训等课程。项目基于B2B2C的业务模式,培训机构可以在平台入驻、发布课程,我们公司作为运营方由专门的人员对发布的课程进行审核,审核通过后课程才可以发布成功,课程包括免费和收费两种形式,对于免费课程普通用户可以直接选课学习,对于收课程在选课后需要支付成功才可以继续学习。<br>本项目包括三个端:用户端(学生端)、机构端、运营端。<br>核心模块包括:内容管理、媒资管理、课程搜索、订单支付、选课管理、认证授权等。<br>本项目采用前后端分离架构,后端采用SpringBoot、springCloud技术栈开发,数据库使用了MySQL,还使用的Redis、消息队列、分布式文件系统、Elasticsearch等中间件系统。<br>划分的微服务包括:内容管理服务、媒资管理服务、搜索服务、订单支付服务、学习中心服务、系统管理服务认证授权服务、网关服务、注册中心服务、配置中心服务等。<br>我在这个项目中负责了内容管理、媒资管理、订单支付模块的设计与开发。</p><p>内容管理模块,是对平台上的课程进行管理,课程的相关信息比较多这里在数据库设计了课程基本信息表、课程营销表、课程计划、课程师资表进行存储,培训机构要发布一门课程需要填写课程基本信息、课程营销信息、课程计划信息、课程师资信息,填写完毕后需要提交审核,由运营人员进行课程信息的审核,整个审核过程是程序自动审核加人工确认的方式,通常24小时审核完成。课程审核通过即可发布课程,课程的相关信息会聚合到课程发布表中,这里不仅要将课程信息写到课程发布表还要将课程信息写到索引库、分布式文件系统中,所以这里存在分布式事务的问题,项目使用本地消息表加任务调度的方式去解决这里的分布式事务,保存数据的最终一致性。</p><h3 id="1-2-你的项目流程是什么">1.2 你的项目流程是什么</h3><ol><li>产品人员设计产品原型。</li><li>讨论需求。</li><li>分模块设计接口。</li><li>出接口文档。</li><li>将接口文档给到前端人员,前后端分离开发。</li><li>开发完毕进行测试。</li><li>测试完毕发布项目,由运维人员进行部署安装。</li></ol><h3 id="1-3-系统如何处理异常">1.3 系统如何处理异常?</h3><p>我们自定义一个统一的异常处理器去捕获并处理异常。使用控制器增加注解@ControllerAdvice和异常处理注<br>解@ExceptionHandler来实现。</p><ul><li>处理自定义异常<br>程序在编写代码时根据校验结果主动抛出自定义异常类对象,抛出异常时指定详细的异常信息,异常处理器<br>捕获异常信息记录异常日志并响应给用户。</li><li>处理未知异常<br>接口执行过程中的一些运行时异常也会由异常处理器统一捕获,记录异常日志,统一应给用户500错误。<br>在异常处理器中还可以针对某个异常类型进行单独处理。</li></ul><h2 id="2-Git">2. Git</h2><h3 id="2-1-Git代码冲突怎么处理">2.1 Git代码冲突怎么处理</h3><p>我们在使用Git时难免会出现代码冲突的问题,出现冲突的原因是因为当本地文件的版本与目标分支中文件的版本不一致时当存在同一行的内容不同时在进行合并时会出现冲突。<br>代码冲突一般发生在以下情况:<br>1、多个分支向主分支合并时<br>2、同一个分支下pull或push操作时。</p><p>不使用图形化界面工具,我们要手动合并文件的内容,确定最终的版本</p><h3 id="2-2-你是在哪个开发分支">2.2 你是在哪个开发分支</h3><p>我们不是直接在主分支开发,由技术经理创建独立的开发分支,我们是在独立的开发分支中进行开发,最后由技术经理将开发分支合并到主分支。</p><h2 id="3-maven">3. maven</h2><h3 id="3-1-maven常用命令">3.1 maven常用命令</h3><ul><li>mvn clean //清除target目录中的生成结果</li><li>mvn compile //编译源代码</li><li>mvn test //执行单元测试</li><li>mvn package //打包</li><li>mvn install //打包并把打好的包上传到本地仓库</li><li>mvn deploy //打包并把打好的包上传到远程仓库</li></ul><h3 id="3-2maven依赖版本冲突如何处理">3.2maven依赖版本冲突如何处理</h3><p>maven依赖版本冲突一般是由于间接依赖导致一个jar包即有多个不同的版本,比如:A依赖了B的1.0版本,C依赖了B的2.0版本,项目依赖A和C从而间接依赖了B的1.0和2.0版本,此时B有两个版本引入到了项目中,当存在版本冲突时可能会出现ClassNotFoundException、NoSuchMethodError等错误。<br>处理版本冲突可以使用以下方法:<br>1、使用exclusions 排除依赖<br>比如:我们只依赖B的1.0版本,此时可以在依赖C时排除对B的依赖。<br>2、使用dependencyManagement锁定版本号。<br>通常在父工程对依赖的版本统一管理。<br>比如:我们只依赖B的1.0版本,此时可以在父工程中限定B的版本为1.0。</p><h2 id="4-Mysql">4. Mysql</h2><h3 id="4-1-mysql常见的存储引擎以及区别">4.1 mysql常见的存储引擎以及区别</h3><p>一、InnoDB</p><ol><li>支持事务。</li><li>使用的锁粒度默认为行级锁,可以支持更高的并发;也支持表锁。</li><li>支持外键约束;外键约束其实降低了表的查询速度,增加了表之间的耦合度。</li></ol><p>二、MyISAM</p><ol><li>不提供事务支持</li><li>只支持表级锁</li><li>不支持外键</li></ol><p>三、memory</p><ol><li>数据存储在内存中</li></ol><p>总结:</p><ul><li><p>MyISAM管理非事务表,提供高速存储和检索以及全文搜索能力,如果在应用中执行大量select操作,应该选择MyISAMM</p></li><li><p>InnoDB用于事务处理,具有ACID事务支持等特性,如果在应用中执行大量insert和update操作,应该选择InnoDB</p></li></ul><h3 id="4-2-mysql建表时要注意哪些">4.2 mysql建表时要注意哪些</h3><p>MySQL建表的经验有很多,下边列举一些:</p><ol><li>注意选择存储引擎,如果要支持事务需要选择InnoDB。</li><li>注意字段类型的选择,对于日期类型如果要记录时分秒建议使用datetime,只记录年月日使用date类型,对于字符类型的选择,固定长度字段选择char,不固定长度的字段选择varchar,varchar比char节省空间但速度没有char快;对于内容介绍类的长广文本字段使用text或longtext类型;如果存储图片等二进制数据使用blob或longblob类型;对金额字段建议使用DECIMAL;对于数值类型的字段在确保取值范围足够的前提下尽量使用占用空间较小的类型,</li><li>主键字段建议使用自然主键,不要有业务意义,建议使用int unsigned类型,特殊场景使用bigint类型。</li><li>如果要存储text、blob字段建议单独建一张表,使用外键关联。</li><li>尽量不要定义外键,保证表的独立性,可以存在外键意义的字段。</li><li>设置字段默认值,比如:状态、创建时间等。</li><li>每个字段写清楚注释。</li><li>注意字段的约束,比如:非空、唯一、主键等</li></ol><h3 id="4-3-树型表的标记字段是什么-如何查询MySQL树型表">4.3 树型表的标记字段是什么?如何查询MySQL树型表?</h3><p>树型表的标记字段是parentid即父结点的id。<br>查询一个树型表的方法:</p><ol><li><p>当层级固定时可以用表的自链接进行查询。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">select</span><br><span class="line"> one.id one_id,</span><br><span class="line"> one.name one_name,</span><br><span class="line"> one.parentid one_parentid,</span><br><span class="line"> one.orderby one_orderby,</span><br><span class="line"> one.label one_label,</span><br><span class="line"> two.id two_id,</span><br><span class="line"> two.name two_name,</span><br><span class="line"> two.parentid two_parentid,</span><br><span class="line"> two.orderby two_orderby,</span><br><span class="line"> two.label two_label</span><br><span class="line"> from course_category one</span><br><span class="line"> inner join course_category two on one.id = two.parentid</span><br><span class="line"> where one.parentid = 1</span><br><span class="line"> and one.is_show = 1</span><br><span class="line"> and two.is_show = 1</span><br><span class="line"> order by one.orderby,</span><br><span class="line"> two.orderby</span><br></pre></td></tr></table></figure></li><li><p>如果想灵活查询每个层级可以使用mysgl递归方法,使用withRECURSIVE 实现。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">with RECURSIVE t1 AS</span><br><span class="line">(</span><br><span class="line"> SELECT 1 as n</span><br><span class="line"> UNION ALL</span><br><span class="line"> SELECT n + 1 FROM t1 WHERE n < 5</span><br><span class="line">)</span><br><span class="line">SELECT * FROM t1;</span><br></pre></td></tr></table></figure></li></ol><h2 id="5-Spring-boot">5. Spring boot</h2><h3 id="5-1-springBoot接口开发的常用注解有哪些">5.1 springBoot接口开发的常用注解有哪些?</h3><ul><li>@Controller 标记此类是一个控制器,可以返回视图解析器指定的html页面,通过@ResponseBody可以将结果返回json、xml数据。</li><li>@RestController相当于@ResponseBody加 @Controler,实现rest接口开发,返回json数据,不能返回html页面。</li><li>@RequestMapping定义接口地址,可以标记在类上也可以标记在方法上,支持http的post、put、get等方法。</li><li>@PostMapping定义post接口,只能标记在方法上,用于添加记录,复杂条件的查询接口。</li><li>@GetMapping定义get接口,只能标记在方法上,用于查询接口的定义。</li><li>@PutMapping定义put接口,只能标记在方法上,用于修改接口的定义。</li><li>@DeleteMapping定义delete接口,只能标记在方法上,用于除接口的定义。</li><li>@RequestBody定义在方法上,用于将json串转成java对象。</li><li>@PathVarible 接收请求路径中占位符的值.</li><li>@ApiOperation swagger注解,对接口方法进行说明。</li><li>@Api wagger注解,对接口类进行说明。</li><li>@Autowired 基于类型注入。</li><li>@Resourc基于名称注入,如果基于名称注入失败转为基于类型注入。</li></ul><h2 id="6-MyBatis">6. MyBatis</h2><h3 id="6-1-MyBatis分页插件原理">6.1 MyBatis分页插件原理</h3><p>首先分页参数放到ThreadLocal中,拦截执行的sql,根据数据库类型添加对应的分页语句重写sql,例如:(select* from table where a) 转换为 (select count(*) from table where a)和(select * from table where a limit ,),计算出了total总条数、pageNum当前第几页、pagesize每页大小和当前页的数据,是否为首页,是否为尾页,总页数等。</p><h3 id="6-2-MyBatis的ResultType和ResultMap的区别">6.2 MyBatis的ResultType和ResultMap的区别?</h3><ul><li><p>ResultType:指定映射类型,只要查询的字段名和类型的属性名匹配可以自动映射。</p></li><li><p>ResuitMap:自定义映射规则,当查询的字段名和映射类型的属性不匹配时可以通过ResultMap自定义映射规则也可以实现一对多、一对一映射。</p></li></ul><h3 id="6-3-和-有什么区别">6.3 #{ } 和 ${ }有什么区别?</h3><ul><li>#{ }是标记一个占位符,可以防止sql注入。</li><li>${ }用于在动态 sql中拼接字符串,可能导致sql!注入。</li></ul><h2 id="7-spring">7. spring</h2><h3 id="7-1-什么情况Spring事务会失效">7.1 什么情况Spring事务会失效</h3><ol><li>在方法中捕获异常没有抛出去</li><li>非事务方法调用事务方法</li><li>事务方法内部调用事务方法</li><li>@Transactional标记的方法不是public,或者不是接口重写方法也不会抛异常<ul><li>因为CGLIB代理的代理对象 要继承被代理对象,重写里面的方法。如果是private方法 无法继承</li></ul></li><li>抛出的异常与rollbackFor指定的异常不匹配,默认rollbackFor指定的异常为RuntimeException</li><li>数据库表不支持事务,比如MySQL的MyISAM</li><li>Spring的传播行为导致事务失效,比如:PROPAGATION NEVER、PROPAGATION NOT SUPPORTED</li></ol><h2 id="8-Minio分布式文件系统">8. Minio分布式文件系统</h2><h3 id="8-1-断点续传是怎么做的">8.1 断点续传是怎么做的?</h3><p>我们是基于分块上传的模式实现断点续传的需求,当文件上传一部分断网后前边已经上传过的不再上传。</p><ol><li>前端对文件分块。</li><li>前端使用多线程一块一块上传,上传前给服务端发一个消息校验该分块是否上传,如果已上传则不再上传。</li><li>等所有分块上传完毕,服务端合并所有分块,校验文件的完整性。因为分块全部上传到了服务器,服务器将所有分块按顺序进行合并,就是写每个分块文件内容按顺序依次写入一个文件中。使用字节流去读写文件。</li><li>前端给服务传了一个md5值,服务端合并文件后计算合并后文件的md5是否和前端传的一样,如果一样则说文件完整,如果不一样说明可能由于网络丢包导致文件不完整,这时上传失败需要重新上传。</li></ol><h3 id="8-2-分块文件清理问题">8.2 分块文件清理问题</h3><p>上传一个文件进行分块上传,上传一半不传了,之前上传到minio的分块文件要清理吗?怎么做的?</p><ol><li>在数据库中有一张文件表记录minio中存储的文件信息。</li><li>文件开始上传时会写入文件表,状态为上传中,上传完成会更新状态为上传完成。</li><li>当一个文件传了一半不再上传了说明该文件没有上传完成,会有定时任务去查询文件表中的记录,如果文件未上传完成则删除minio中没有上传成功的文件目录。</li></ol><h2 id="9-xxl-job">9. xxl-job</h2><h3 id="9-1-描述">9.1 描述</h3><p>xxl-job的工作原理是什么?<br>xxl-job是什么怎么工作?<br>XXL-J0B分布式任务调度服务由调用中心和执行器组成,调用中心负责按任务调度策略向执行器下发任务,执行器负责接收任务执行任务。</p><ol><li>首先部署并启动xx1-job调度中心。(一个java工程)</li><li>首先在微服务添加xx1-job依赖,在微服务中配置执行器</li><li>启动微服务,执行器向调度中心上报自己。</li><li>在微服务中写一个任务方法并用xx1-job的注解去标记执行任务的方法名称。</li><li>在调度中心配置任务调度策略,调度策略就是每隔多长时间执行还是在每天或每月的固定时间去执行,比如每天0点执行,或每隔1小时执行一次等。</li><li>在调度中心启动任务。</li><li>调度中心根据任务调度策略,到达时间就开始下发任务给执行器。</li><li>执行器收到任务就开始执行任务。</li></ol><h3 id="9-2-如何保证任务不重复执行">9.2 如何保证任务不重复执行?</h3><ol><li>调度中心按分片广播的方式去下发任务</li><li>执行器收到作业分片广播的参数:分片总数和分片序号,计算 任务id 除以 分片总数得到一个余数,如果余数等于分片序号这时就去执行这个任务,这里保证了不同的执行器执行不同的任务</li><li>配置调度过期策略为“忽略”,避免同一个执行器多次重复执行同一个任务</li><li>配置任务阻塞处理策略为“丢弃后续调度”,注意:丢弃也没事下一次调度就又可以执行了</li><li>另外还要保证任务处理的幂等性,执行过的任务可以打一个状态标记已完成,下次再调度执行该任务判断该任务已完成就不再执行</li></ol><h3 id="9-3-任务幂等性如何保证">9.3 任务幂等性如何保证?</h3><p>它描述了一次和多次请求某一个资源对于资源本身应该具有同样的结果。幂等性是为了解决重复提交问题,比如:恶意刷单,重复支付等。解决幂等性常用的方案:</p><ol><li>数据库约束,比如:唯一索引,主键。同一个主键不可能两次都插入成功。</li><li>乐观锁,常用于数据库,更新数据时根据乐观锁状态去更新。</li><li>唯一序列号,请求前生成唯一的序列号,携带序列号去请求,执行时在redis记录该序列号表示以该序列号的请求执行过了,如果相同的序列号再次来执行说明是重复执行。这里我们在数据库视频处理表中添加处理状态字段,视频处理完成更新状态为完成,执行视频处理前判断状态是否完成,如果完成则不再处理。</li></ol><h1>鱼友之面</h1><ol><li><p>抽象类和接口的异同点:</p><ul><li>相同点:都不能实例化成对象,只能被其他类继承或实现。都包含抽象方法,这些方法只有声明没有实现。</li><li>不同点:抽象类可以包含非抽象方法(具体方法),而接口中的所有方法都是抽象的。一个类可以实现多个接口,但只能继承一个抽象类。接口支持默认方法和静态方法,抽象类不支持。</li></ul></li><li><p>线程的状态:</p><ul><li>新建(New)</li><li>可运行(Runnable)</li><li>阻塞(Blocked)</li><li>等待(Waiting)</li><li>超时等待(Timed Waiting)</li><li>终止(Terminated)</li><li>sleep和wait的异同点:<ul><li>sleep是Thread类的静态方法,使当前线程暂停执行指定的时间,不释放锁资源。</li><li>wait是Object类的方法,使当前线程等待,直到其他线程调用此对象的notify()或notifyAll()方法,会释放锁资源。</li></ul></li></ul></li><li><p>序列化是将对象的状态信息转换为字节流的过程,便于在网络上传输或存储到文件系统。序列化的目的是实现对象的持久化和远程方法调用(RMI)。</p></li><li><p>finally和return的执行关系:</p><ul><li>无论try块中是否执行了return语句,finally块中的代码都会被执行。</li><li>如果finally块中也包含return语句,那么它会覆盖try或catch块中的return值。</li></ul></li><li><p>Spring框架中的IoC(Inversion of Control,控制反转)和AOP(Aspect-Oriented Programming,面向切面编程):</p><ul><li>IoC:通过依赖注入(DI)将对象的创建和依赖关系的管理交给Spring容器,降低了组件之间的耦合度。</li><li>AOP:允许开发者定义横切关注点,这些关注点独立于应用程序的主要业务逻辑,可以在不修改源代码的情况下对程序进行功能扩展,如日志记录、事务管理、安全检查等。</li></ul></li><li><p>什么是SQL注入攻击?预防方法?</p><ul><li>SQL注入攻击是通过在SQL查询中插入恶意代码来破坏、篡改或窃取数据库数据的行为。</li><li>在JDBC编程中,应使用PreparedStatement代替Statement来避免SQL注入攻击,因为PreparedStatement将参数与SQL语句分开处理,不允许参数中包含SQL代码。</li></ul></li><li><p>JDBC事务概念? spring声明事务在编码中涉及哪些要点</p><ul><li>JDBC事务是一系列对数据库的操作序列,要么全部成功执行,要么全部失败回滚,以保持数据的完整性和一致性。</li><li>Spring声明式事务管理通过注解(如@Transactional)或XML配置来简化事务管理,开发者只需关注业务逻辑,无需编写繁琐的事务控制代码。</li></ul></li><li><p>线程死锁的原因:</p><ul><li>互斥条件:资源至少有一个是不可共享的。</li><li>请求与保持条件:一个线程因请求资源而阻塞时,对已获得的资源保持不放。</li><li>不剥夺条件:线程已获得的资源,在未使用完之前,不能被其他线程强行剥夺。</li><li>循环等待条件:若干线程之间形成一种头尾相接的循环等待资源关系。</li><li>规避方法:<ul><li>按顺序加锁,避免循环等待。</li><li>设置锁的超时时间。</li><li>使用tryLock()方法尝试获取锁。</li><li>使用死锁检测算法。</li></ul></li></ul></li><li><p>对于一个常规的interface接口,是否可以通过反射机制创建其对象实例</p><ul><li>对于一个常规的interface接口,不能通过反射机制直接创建其对象实例,因为接口本身不能被实例化。</li><li>但是,可以通过反射机制创建实现了该接口的具体类的对象实例。</li></ul></li><li><p>Mysql的数据库引擎有哪些?</p><ul><li>MySQL数据库引擎主要有InnoDB、MyISAM、Memory等。</li></ul></li><li><p>new String(“abc”)创建了多少个对象?</p><ul><li>new String(“abc”)创建了两个对象:一个是字符串字面量"abc"(存储在字符串常量池中),另一个是通过new关键字创建的String对象(存储在堆内存中)。</li></ul></li><li><p>为什么重写了equals方法还要重写hashcode方法?</p><ul><li>重写equals方法后,如果两个对象相等(根据equals方法的定义),它们的hashcode也应该相等,以保证它们在哈希表中的行为一致。</li><li>如果不重写hashcode方法,那么即使两个对象相等,它们的hashcode也可能不同,这会导致在使用哈希表时出现问题。</li></ul></li><li><p>Redis和MySQL如何保持数据一致性?</p><ul><li>写入时更新(Write-Through):应用程序在更新MySQL数据库后立即更新Redis。</li><li>写入后更新(Write-Behind):应用程序在更新MySQL数据库后稍后再更新Redis,可以批量操作以提高性能。</li><li>事务提交时更新(Write-On-Commit):应用程序在MySQL事务提交后更新Redis,确保数据的一致性。</li></ul></li><li><p>Java中有哪些常见的异常类?</p><ul><li>Java中常见的异常类包括:NullPointerException、IndexOutOfBoundsException、ClassCastException、ArrayStoreException、IllegalArgumentException、IOException等。</li></ul></li><li><p>重写(Override)和重载(Overload)的使用场景:</p><ul><li>重写:子类提供特定于其自身实现的方法版本,用于覆盖父类中的同名方法。通常用于改变方法的行为。</li><li>重载:在同一类中定义多个同名方法,但参数列表不同。通常用于提供多种输入参数组合的处理方式。</li></ul></li><li><p>Redis和MySQL有安全线程吗?<br>Redis和MySQL本身不提供安全线程。为了确保安全性,需要采取以下措施:</p></li></ol><ul><li>使用连接池来管理数据库连接,避免频繁创建和关闭连接。</li><li>对用户输入进行验证和过滤,防止SQL注入攻击。</li><li>使用SSL/TLS加密通信。</li><li>设置合适的权限和访问控制。</li></ul>]]></content>
<categories>
<category> 面试题 </category>
</categories>
<tags>
<tag> 面试 </tag>
</tags>
</entry>
<entry>
<title>八股文总结</title>
<link href="/posts/4ff17a5f.html"/>
<url>/posts/4ff17a5f.html</url>
<content type="html"><![CDATA[<h1>头悬梁,锥刺股</h1>]]></content>
<categories>
<category> 八股文 </category>
</categories>
<tags>
<tag> Java </tag>
<tag> 八股文 </tag>
</tags>
</entry>
<entry>
<title>Mysql知识点</title>
<link href="/posts/7ba7061.html"/>
<url>/posts/7ba7061.html</url>
<content type="html"><![CDATA[<p>访问远程服务器上的数据库</p><ul><li>mysql -u用户名 -p密码[-h数据库服务器IP地址 -P端口号]</li></ul><p>SQL:一门操作关系型数据库的编程语言,定义操作所有关系型数据库的统一标准。</p><h2 id="通用语法">通用语法</h2><ul><li><p>SQL语句可以单行或多行书写,以分号结尾。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">show</span> databases;</span><br></pre></td></tr></table></figure></li><li><p>SOL语句可以使用空格/缩进来增强语句的可读性。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">show</span> databases;</span><br></pre></td></tr></table></figure></li><li><p>MySQL数据库的SQL语句不区分大小写。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SHOW</span> DATABASES;</span><br></pre></td></tr></table></figure></li><li><p>注释</p><ol><li><p>单行注释:–注释内容 或#注释内容(MySQL特有)</p> <figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- show databases;</span></span><br></pre></td></tr></table></figure></li><li><p>多行注释: /* 注释内容 */</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* show databases; */</span></span><br></pre></td></tr></table></figure></li></ol></li></ul><h2 id="DDL">DDL</h2><p>数据定义语言,用来定义数据库对象(数据库,表,字段)</p> <figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="operator">/</span><span class="operator">/</span>创建数据库</span><br><span class="line">creat database <span class="string">'数据库名'</span></span><br><span class="line"><span class="operator">/</span><span class="operator">/</span>展示数据库</span><br><span class="line"><span class="keyword">show</span> database</span><br><span class="line"><span class="operator">/</span><span class="operator">/</span>删除数据库</span><br><span class="line"><span class="keyword">drop</span> database <span class="string">'数据库名'</span></span><br></pre></td></tr></table></figure><ol><li><p>查询</p><ul><li>查询当前数据库所有表: show tables;</li><li>查询表结构: desc 表名;</li><li>查询建表语句: show create table 表名</li></ul></li><li><p>修改</p><ul><li>添加字段: alter table 表名 add 字段名 类型(长度)[comment 注释] [约束];</li><li>修改字段类型: alter table 表名 modify 字段名 新数据类型(长度);</li><li>修改字段名和字段类型: alter table 表名 change 旧字段名 新字段名 类型(长度)[comment 注释][约束</li><li>删除字段: alter table 表名 drop column 字段名;</li><li>修改表名: rename table 表名 to 新表名</li></ul></li><li><p>删除</p><ul><li>删除表: drop table [if exists]表名</li></ul></li></ol><h2 id="DML">DML</h2><p>数据操作语言,用来对数据库表中的数据进行增删改</p><ol><li><p>插入数据</p><ul><li>指定字段添加数据: insert into 表名(字段名1,字段名2) values (值1,值2);</li><li>全部字段添加数据: insert into 表名 values (值1,值2,…);</li><li>批量添加数据(指定字段): insert into 表名(字段名1,字段名2) values (值1,值2),(值1,值2);</li><li>批量添加数据(全部字段) : insert into 表名 values (值1,值2,…),(值1, 值2,…);</li></ul></li><li><p>更新数据</p><ul><li>修改数据: update 表名 set 字段名1= 值1,字段名2 = 值2,…[ where 条件];</li></ul></li><li><p>删除数据</p><ul><li>删除数据: delete from 表名 [where 条件];</li></ul></li></ol><h2 id="DQL">DQL</h2><p>数据查询语言,用来查询数据库中表的记录</p><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Mysql/1.png" alt="1"></p><ol><li><p>基本查询:</p><ul><li>查询多个字段: select 字段1,字段2, 字段3 from 表名</li><li>查询所有字段(通配符): select * from 表名;</li><li>设置别名: select 字段1[as 别名1],字段2[as 别名2] from 表名 as关键词可省略</li><li>去除重复记录: select distinct 字段列表 from 表名;</li></ul></li><li><p>条件查询:</p><ul><li>select 字段列表 from 表名 where 条件列表;</li><li>Where条件运算符<br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Mysql/2.png" alt="2"></li></ul></li><li><p>聚合函数:<br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Mysql/3.png" alt="3"></p><ul><li>null值不参与所有聚合函数运算。</li><li>统计数量可以使用:count( *) count(字段) count(常量),推荐使用count( * )。</li><li>//流程控制函数:if(条件表达式,true取值,false取值),</li><li>//case 表达式 when 值1 then 结果1 when 值2 then 结果2 …else …end</li></ul></li><li><p>分组查询:</p><ul><li>(where之后不能使用聚合函数)</li><li>select 字段列表 from 表名[where 条件] group by 分组字段名 [having 分组后过滤条件];</li><li>执行顺序:where>聚合函数>having,where不能对聚合函数进行判断,having可以</li></ul></li><li><p>排序查询:</p><ul><li>select 字段列表 from 表名 [where 条件列表] [group by 分组字段]order by 字段1 排序方式1,字段2 排序方式2…</li><li>ASC: 升序(默认值) DESC:降序</li><li>如果是多字段排序,当第一个字段值相同时,才会根据第二个字段进行排序</li></ul></li><li><p>分页查询</p><ul><li>select 字段列表 from 表名 limit 起始索引,查询记录数</li><li>起始索引 = (页码 - 1) * 每页展示记录数</li></ul></li><li><p>注意:</p><ul><li>起始索引从0开始,起始索引= (查询页码-)*每页显示记录数</li><li>分页查询是数据库的方言,不同的数据库有不同的实现,MySQL中是LIMIT如果查询的是第一页数据,起始索引可以省略,直接简写为 limit 10.</li></ul></li></ol><h2 id="多表设计">多表设计</h2><p>对表进行外键约束,保证数据的完整性,一致性,有效性。<br><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Mysql/4.png" alt="4"></p><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Mysql/5.png" alt="5"></p><p>实体之间的关系:</p><ol><li>一对一:人和身份证</li><li>一对多:部门和员工</li><li>多对多:学生选课,一个学生可以选多门课程,一门课程也可以被多个学生选择</li></ol><h2 id="多表查询">多表查询</h2><p>多表查询:指从多张表中查询数据<br>笛卡尔积:笛卡尔乘积是指在数学中,两个集合(A集合 和 B集合)的所有组合情况。(在多表查询时,需要消除无效的笛卡尔积)</p><ol><li><p>连接查询</p><ul><li>内连接查询:查询A和B交集部分数据<ul><li>隐式内连接:使用where条件消除无用数据</li><li>显示内连接:使用inner join …on 消除无用数据</li></ul></li><li>外连接查询:查询A和B所有数据,如果数据不存在,则为null<ul><li>左外连接:查询A表所有数据,以及A和B交集部分数据</li><li>右外连接:查询B表所有数据,以及A和B交集部分数据</li></ul></li><li>自连接查询:当前表与自身连接查询,自连接必须使用表别名</li></ul></li><li><p>子查询</p><ul><li>子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询。</li><li>子查询一般作为其他语句的条件使用,子查询可以放在where后面,也可以放在having后面,还可以放在select后面。子查询语句可以放在小括号中。</li><li>根据子查询出现的位置分类<ul><li>select后面:标量子查询</li><li>from后面:表子查询</li><li>where后面:标量子查询、列子查询、行子查询</li><li>having后面:标量子查询、列子查询、行子查询</li></ul></li><li>根据子查询的结果分类<ul><li>标量子查询(结果集只有一行一列,操作符: > < >= <= = <>)</li><li>列子查询(结果集只有一列多行,操作符: in、not in、any/some、all)</li><li>行子查询(结果集有一行多列,操作符: =、<>)</li><li>表子查询(结果集一般为多行多列,操作符: in)</li></ul></li></ul></li></ol><h2 id="事务">事务</h2><p>概念:一组操作的集合,这组操作要么全部成功,要么全部失败</p><p>开启事务: start transaction; / begin ;<br>提交事务: commit;<br>回滚事务: rollback;</p><p>四大特性:</p><ol><li>原子性:事务是一个不可分割的工作单位,事务中的操作要么全部完成,要么全部不完成。</li><li>一致性:事务开始和完成时,数据必须保持一致状态。</li><li>隔离性:多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。</li><li>持久性:一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。</li></ol><h2 id="索引">索引</h2><p>索引 (index)是帮助数据 高效获取数据的 数据结构(二叉树)</p><p>优点:</p><ul><li>提高数据查询的效率,降低数据库的IO成本。</li><li>通过索引列对数据进行排序,降低数据排序的成本,降低CPU消耗</li></ul><p>缺点:</p><ul><li>索引会占用存储空间。</li><li>索引大大提高了查询效率,同时却也降低了insert、update、delete的效率</li></ul><p><img src="https://web-talis-a.oss-cn-beijing.aliyuncs.com/Mysql/6.png" alt="6"></p><p>结构:B+Tree<br>特点:</p><ul><li>每一个节点,可以存储多个key (有n个key,就有n个指针)。</li><li>所有的数据都存储在叶子节点,非叶子节点仅用于索引数据。</li><li>叶子节点形成了一颗双向链表,便于数据的排序及区间范围查询。</li></ul><p>语法:</p><blockquote><p>创建索引:create [unique] index 索引名 on 表名(字段名,…);<br>查看索引:show index from 表名;<br>删除索引:drop index 索引名 on 表名;</p><p>注意:<br>主键字段,在建表时,会自动创建主键索引。(性能最高)<br>添加唯一约束时,数据库实际上会添加唯一索引。</p></blockquote>]]></content>
<categories>
<category> 数据库 </category>
</categories>
<tags>
<tag> Mysql </tag>
</tags>
</entry>
<entry>
<title>谈天说地</title>
<link href="/posts/93c91d94.html"/>
<url>/posts/93c91d94.html</url>
<content type="html"><![CDATA[<div class='wow animate__heartBeat' data-wow-duration='' data-wow-delay='5s' data-wow-offset='' data-wow-iteration='10' ><div class="note red icon-padding modern"><i class="note-icon fas fa-battery-half"></i><p>此时此刻我想吟诗一首</p></div></div><div class='poem'><div class='poem-title'>水调歌头</div><div class='poem-author'>苏轼</div><p>丙辰中秋,欢饮达旦,大醉,作此篇,兼怀子由。<br>明月几时有?把酒问青天。<br>不知天上宫阙,今夕是何年?<br>我欲乘风归去,又恐琼楼玉宇,高处不胜寒。<br>起舞弄清影,何似在人间?</p><p>转朱阁,低绮户,照无眠。<br>不应有恨,何事长向别时圆?<br>人有悲欢离合,月有阴晴圆缺,此事古难全。<br>但愿人长久,千里共婵娟。</p></div>]]></content>
<categories>
<category> 谈天说地 </category>
</categories>
<tags>
<tag> 谈天说地 </tag>
</tags>
</entry>
</search>