-
Notifications
You must be signed in to change notification settings - Fork 0
/
search.xml
2295 lines (1101 loc) · 414 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>[闲谈]-2023</title>
<link href="/2024/02/23/%E9%97%B2%E8%B0%88-2023/"/>
<url>/2024/02/23/%E9%97%B2%E8%B0%88-2023/</url>
<content type="html"><![CDATA[<h3 id="2023总结"><a href="#2023总结" class="headerlink" title="2023总结"></a>2023总结</h3><p>我总会在这个阶段简短说明下去年的想法。这年基本忙于工作,除了本职工作的技术管理之外,还花了一部分时间在摄影摄像剪辑中,因为工作需要。这年是近几年拍摄日落自然较少的一年。另外还包括室友的离别,工作的调整,居住环境的改变,又养了一只猫叫做十一……</p><p>今年独处时总有一个声音在质问我,活着的本身有什么用?既然最终都会离去,为什么要体验如此多的事情?在宏观角度中所做的一文不值。我所做的,之前有人做过,未来也还会有人走向重复的路,当然还包括其他问题。索性我并不讨厌思考,我追问只是因为想明白这些之后依旧做自己。你应该多去了解世界和事物的运作方式,即使每一个抉择都存在人们指指点点,要知道那是他们的事情,这些都不能阻止你做任何你想做的事。</p><p>许多人都自以过来人的身份,希望你活成他们内心的模样,但他们不曾想象世界上存在无数种活法,一但那些事是出乎他们的想象,便七嘴八舌蜂拥而至,我能理解,这其中有许多因素导致的。</p><p>如果我不曾有想法,那或许我只能听从别人的安排。但我有想法和目标后,是身边的人从未走过的路,我应该坚定不移选择它,尽管一路上都是各种不理解。如果把物质财富当成成功的唯一标准,我大抵是永远不会合格的。就像过年期间饭桌上一聊起天来,基本都是谈论车子房子结婚各种邻里邻居的悲惨故事。而我更想听听人们谈论自己有趣的经历,不要只关注别人的人生。</p><p>我认为变化是常态,也许几年后我看这些话,会有新的感受,但是,我知道的,现在此时,我知道做自己不那么轻松,比如留个长发回老家已经无数人可以跟我说道说道,关于结婚同样如此,不会过问你喜欢什么,只要求你选择什么。</p><p>我希望我的一生忠于记录,忠于热爱,忠于自己的内心。</p><p>我觉得我的一生是需要一点精神财富的,那些喜好能支撑我开心的活着。</p><p>“没有谁知道我是谁,没有谁知道我会成为谁,那么我就可以成为任何人。”</p>]]></content>
<categories>
<category> 闲谈 </category>
</categories>
<tags>
<tag> 闲谈 </tag>
</tags>
</entry>
<entry>
<title>[English]-否定句</title>
<link href="/2023/05/05/English-%E5%90%A6%E5%AE%9A%E5%8F%A5/"/>
<url>/2023/05/05/English-%E5%90%A6%E5%AE%9A%E5%8F%A5/</url>
<content type="html"><![CDATA[<h1 id="什么是否定句?"><a href="#什么是否定句?" class="headerlink" title="什么是否定句?"></a>什么是否定句?</h1><ul><li>判断方式<ul><li>表达“不”“否”“没有”等否定意思</li></ul></li></ul><h2 id="主系表句型的否定句"><a href="#主系表句型的否定句" class="headerlink" title="主系表句型的否定句"></a>主系表句型的否定句</h2><p><strong>规则:系动词后面+not (主系表:是很在)</strong></p><ul><li>我是你哥哥<ul><li>I am <strong>(not)</strong> your brother</li></ul></li><li>她很帅<ul><li>She is <strong>(not)</strong> handsome</li></ul></li><li>你很无聊<ul><li>you are <strong>(not)</strong> boring</li></ul></li><li>这件事情很重要<ul><li>This is <strong>(not)</strong> important</li></ul></li><li>他们在那里<ul><li>They are <strong>(not)</strong> there</li></ul></li></ul><h2 id="主谓宾句型的否定句"><a href="#主谓宾句型的否定句" class="headerlink" title="主谓宾句型的否定句"></a>主谓宾句型的否定句</h2><p><strong>规则:主语后+don’t/doesn’t(主语后面动作 动词)</strong></p><ul><li>我爱你<ul><li>I <strong>(don’t)</strong> love you</li></ul></li><li>他说英语<ul><li>He <strong>(doesn’t)</strong> speak English</li></ul></li><li>我知道<ul><li>I <strong>(don’t)</strong> know</li></ul></li><li>我的小狗不喝羊奶<ul><li>My puppy <strong>(doesn’t)</strong> drink goat milk</li></ul></li><li>他们想离开你<ul><li>They <strong>(don’t)</strong> want to leave you</li></ul></li></ul><h2 id="there-be的否定句"><a href="#there-be的否定句" class="headerlink" title="there be的否定句"></a>there be的否定句</h2><p><strong>规则:there is no 没有</strong></p><ul><li>这里没有人<ul><li>there is no + person + here </li></ul></li><li>杯子里没有水<ul><li>there is no + water + in the cup</li></ul></li><li>抽屉里没有钱<ul><li>there is no + money + in the drawer</li></ul></li></ul>]]></content>
<categories>
<category> English </category>
</categories>
<tags>
<tag> English </tag>
</tags>
</entry>
<entry>
<title>[English]-There be句型</title>
<link href="/2023/05/05/English-There%20be%E5%8F%A5%E5%9E%8B/"/>
<url>/2023/05/05/English-There%20be%E5%8F%A5%E5%9E%8B/</url>
<content type="html"><![CDATA[<h1 id="什么是there-be句型?"><a href="#什么是there-be句型?" class="headerlink" title="什么是there be句型?"></a>什么是there be句型?</h1><ul><li>判断方式<ul><li>表达某个地方有…</li></ul></li></ul><h1 id="用there-be句型翻译句子"><a href="#用there-be句型翻译句子" class="headerlink" title="用there be句型翻译句子"></a>用there be句型翻译句子</h1><h2 id="解释"><a href="#解释" class="headerlink" title="解释"></a>解释</h2><table><thead><tr><th align="left">区分</th><th align="left">表达</th></tr></thead><tbody><tr><td align="left">数量=1</td><td align="left">there is</td></tr><tr><td align="left">数量>1</td><td align="left">there are</td></tr></tbody></table><ul><li>桌上 有 一台红色的电脑<ul><li>there be(有) a red computer + on the table</li></ul></li><li>车上 有 很多人<ul><li>there be(有) + many people + on the bus</li></ul></li><li>这里 有 一些书<ul><li>there be(are) + some books + here</li></ul></li><li>那里 有 一个女孩<ul><li>there be(is) + a girl + here</li></ul></li><li>床上 有 一只小狗<ul><li>there be(is) a + puppy + on the bad</li></ul></li></ul>]]></content>
<categories>
<category> English </category>
</categories>
<tags>
<tag> English </tag>
</tags>
</entry>
<entry>
<title>[English]-主系表句型</title>
<link href="/2023/05/03/English-%E4%B8%BB%E7%B3%BB%E8%A1%A8%E5%8F%A5%E5%9E%8B/"/>
<url>/2023/05/03/English-%E4%B8%BB%E7%B3%BB%E8%A1%A8%E5%8F%A5%E5%9E%8B/</url>
<content type="html"><![CDATA[<h1 id="什么是主谓宾句型?"><a href="#什么是主谓宾句型?" class="headerlink" title="什么是主谓宾句型?"></a>什么是主谓宾句型?</h1><ul><li>判断方式<ul><li>是/很/在</li></ul></li></ul><h1 id="用主谓宾句型翻译句子"><a href="#用主谓宾句型翻译句子" class="headerlink" title="用主谓宾句型翻译句子"></a>用主谓宾句型翻译句子</h1><h2 id="解释"><a href="#解释" class="headerlink" title="解释"></a>解释</h2><table><thead><tr><th align="left">主语</th><th align="left">系动词</th></tr></thead><tbody><tr><td align="left">我</td><td align="left">am</td></tr><tr><td align="left">你</td><td align="left">are</td></tr><tr><td align="left">他/她/它</td><td align="left">is</td></tr><tr><td align="left">数量为1</td><td align="left">is</td></tr><tr><td align="left">数量大于1</td><td align="left">are</td></tr></tbody></table><ul><li>他 是 中国人<ul><li>He is Chinese</li></ul></li><li>我 很 累<ul><li>I am tired</li></ul></li><li>我 在 家<ul><li>I am at home</li></ul></li><li>她 在 路上<ul><li>She is on the way</li></ul></li><li>它 很 可爱<ul><li>It is cute</li></ul></li><li>这 是 我的妈妈<ul><li>This is my mon</li></ul></li><li>这 很 有趣<ul><li>This is interesting</li></ul></li><li>英语和数学很简单<ul><li>English and Math are easy</li></ul></li></ul>]]></content>
<categories>
<category> English </category>
</categories>
<tags>
<tag> English </tag>
</tags>
</entry>
<entry>
<title>[English]-主谓宾句型</title>
<link href="/2023/05/03/English-%E4%B8%BB%E8%B0%93%E5%AE%BE%E5%8F%A5%E5%9E%8B/"/>
<url>/2023/05/03/English-%E4%B8%BB%E8%B0%93%E5%AE%BE%E5%8F%A5%E5%9E%8B/</url>
<content type="html"><![CDATA[<h1 id="什么是主谓宾句型?"><a href="#什么是主谓宾句型?" class="headerlink" title="什么是主谓宾句型?"></a>什么是主谓宾句型?</h1><ul><li>主语后面是“动作(动词)”<ul><li>看、跑、吃、喝…</li><li>想、爱、思念、决定…</li></ul></li></ul><h1 id="用主谓宾句型翻译句子"><a href="#用主谓宾句型翻译句子" class="headerlink" title="用主谓宾句型翻译句子"></a>用主谓宾句型翻译句子</h1><h2 id="解释"><a href="#解释" class="headerlink" title="解释"></a>解释</h2><pre><code>- 主语-句子开头的词语 主语后面是动作/动词 主谓宾</code></pre><table><thead><tr><th align="left">主语</th><th align="left">谓语动词</th></tr></thead><tbody><tr><td align="left">我</td><td align="left">不变</td></tr><tr><td align="left">你</td><td align="left">不变</td></tr><tr><td align="left">他/她/它</td><td align="left">变 + s</td></tr><tr><td align="left">数量为1</td><td align="left">变 + s</td></tr><tr><td align="left">数量大于1</td><td align="left">不变</td></tr></tbody></table><ul><li>我爱你<ul><li>I + live + you</li></ul></li><li>他爱你<ul><li>he +lives + you</li></ul></li><li>你吃米饭<ul><li>you + eat + rice</li></ul></li><li>这个人吃面条<ul><li>this + person + eats + noodles </li></ul></li><li>我跑步<ul><li>I + run</li></ul></li><li>他们跑步<ul><li>they + run </li></ul></li><li>她跑步<ul><li>she + runs</li></ul></li><li>我的妈妈吃饭<ul><li>my mom eats rice</li></ul></li><li>Tom吃米饭<ul><li>Tom eat rice</li></ul></li></ul><h1 id="宾语存在动词需变形"><a href="#宾语存在动词需变形" class="headerlink" title="宾语存在动词需变形"></a>宾语存在动词需变形</h1><h2 id="说明"><a href="#说明" class="headerlink" title="说明"></a>说明</h2><pre><code>- 前 to 后 ing</code></pre><ul><li>我爱吃面条<ul><li>I live eating noodles</li></ul></li><li>他爱吃面条<ul><li>he live eating noodles</li></ul></li><li>你喜欢吃米饭<ul><li>you like eating rice</li></ul></li><li>这个人喜欢睡觉<ul><li>this person likes sleeping</li></ul></li><li>我想离开这里<ul><li>I want to leave here</li></ul></li><li>他们决定乘坐大巴<ul><li>they decide to take a bus</li></ul></li><li>她拒绝帮助你<ul><li>she refuses to help you</li></ul></li></ul>]]></content>
<categories>
<category> English </category>
</categories>
<tags>
<tag> English </tag>
</tags>
</entry>
<entry>
<title>[Other]Nginx个人常用命令整理</title>
<link href="/2022/06/24/Other-Nginx%E4%B8%AA%E4%BA%BA%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4%E6%95%B4%E7%90%86/"/>
<url>/2022/06/24/Other-Nginx%E4%B8%AA%E4%BA%BA%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4%E6%95%B4%E7%90%86/</url>
<content type="html"><![CDATA[<p><code>nginx -t 检查配置是否正确</code></p><p><code>nginx -s reload 重新加载配置信息</code></p><pre><code>server { listen 80; server_name www.xxx.com location / { alias /path/;}</code></pre><pre><code>server { listen 80; server_name www.xxx.com location / { proxy_pass http://127.0.0.1:8088}</code></pre><pre><code># HTTPSserver { listen 443 ssl; index index.html index.htm index.php; server_name www.xxx.com; ssl_certificate /xxxxxx.pem; ssl_certificate_key /xxxxxx.key; ssl_session_timeout 5m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; location / { proxy_pass http://127.0.0.1:8088; }}</code></pre><pre><code># ios Swift 通用链接(Universal Links)location / { charset UTF-8; default_type text/html; return 200 '{"applinks":{"apps":[],"details":[{"appID":"xxxxxxxxxx","paths":["*"]}]}}'; }}</code></pre><pre><code>#重定向server { listen 80; server_name www.xxx.com; rewrite ^(.*)$ https://$host$1; #将所有HTTP请求通过rewrite指令重定向到HTTPS。 location / { proxy_pass http://127.0.0.1:8088; }}</code></pre>]]></content>
<categories>
<category> Other </category>
</categories>
<tags>
<tag> nginx </tag>
</tags>
</entry>
<entry>
<title>[JAVA]-中文根据拼音首字母排序</title>
<link href="/2021/03/22/JAVA-%E4%B8%AD%E6%96%87%E6%A0%B9%E6%8D%AE%E6%8B%BC%E9%9F%B3%E9%A6%96%E5%AD%97%E6%AF%8D%E6%8E%92%E5%BA%8F/"/>
<url>/2021/03/22/JAVA-%E4%B8%AD%E6%96%87%E6%A0%B9%E6%8D%AE%E6%8B%BC%E9%9F%B3%E9%A6%96%E5%AD%97%E6%AF%8D%E6%8E%92%E5%BA%8F/</url>
<content type="html"><![CDATA[<p><strong>有些用户列表/品种列表等,常用A,B,C作为名称的搜索条件。</strong></p><p>依赖</p><pre><code><dependency> <groupId>com.belerweb</groupId> <artifactId>pinyin4j</artifactId> <version>2.5.1</version></dependency></code></pre><p>工具类</p><pre><code>public class PinYinUtils { /** * 获取汉字对应的拼音 * * @param chinese 汉字串 * @return */ public static String getFullSpell(String chinese) { StringBuffer bf = new StringBuffer(); char[] arr = chinese.toCharArray(); HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat(); defaultFormat.setCaseType(HanyuPinyinCaseType.UPPERCASE); defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE); for (int i = 0; i < arr.length; i++) { if (arr[i] > 128) { try { bf.append(PinyinHelper.toHanyuPinyinStringArray(arr[i], defaultFormat)[0]); } catch (BadHanyuPinyinOutputFormatCombination e) { e.printStackTrace(); } } else { bf.append(arr[i]); } } return bf.toString(); }}</code></pre><p>将查询的数据,重新进行处理</p><pre><code> /** * 封装根据拼音首字母的数据 * * @param data * @return */ private List<Map<String, Object>> getPinYinData(List<CpPetKind> data) { List<Map<String, Object>> list = new LinkedList<>(); for (int i = 1; i <= 26; i++) { // 大写 String big = String.valueOf((char) (96 + i)).toUpperCase(); // 小写 String little = big.toLowerCase(); List<CpPetKind> initialsList = new LinkedList<>(); for (int j = 0; j < data.size() - 1; j++) { CpPetKind petKind = data.get(j); String initials = PinYinUtils.getFullSpell(petKind.getBreed()).substring(0, 1); if (big.equals(initials) || little.equals(initials)) { initialsList.add(petKind); } } Map<String, Object> tempMap = new HashMap<>(); tempMap.put("initials", big); tempMap.put("kinds", initialsList); list.add(tempMap); } return list; }</code></pre>]]></content>
<categories>
<category> JAVA </category>
</categories>
<tags>
<tag> java </tag>
</tags>
</entry>
<entry>
<title>[JAVA]-视频url获取指定帧数的图片</title>
<link href="/2021/03/17/JAVA-%E8%A7%86%E9%A2%91url%E8%8E%B7%E5%8F%96%E6%8C%87%E5%AE%9A%E5%B8%A7%E6%95%B0%E7%9A%84%E5%9B%BE%E7%89%87/"/>
<url>/2021/03/17/JAVA-%E8%A7%86%E9%A2%91url%E8%8E%B7%E5%8F%96%E6%8C%87%E5%AE%9A%E5%B8%A7%E6%95%B0%E7%9A%84%E5%9B%BE%E7%89%87/</url>
<content type="html"><![CDATA[<p><strong>通过视频地址,获取指定N帧的图片,并且上传到阿里云oss</strong></p><p>参考地址:<a href="http://www.fixbbs.com/p/01439272.html" target="_blank" rel="noopener">http://www.fixbbs.com/p/01439272.html</a></p><h2 id="依赖"><a href="#依赖" class="headerlink" title="依赖"></a>依赖</h2><pre><code><dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv</artifactId> <version>1.4.3</version></dependency><dependency> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>ffmpeg-platform</artifactId> <version>4.0.2-1.4.3</version></dependency><dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>RELEASE</version></dependency></code></pre><h2 id="相关代码"><a href="#相关代码" class="headerlink" title="相关代码"></a>相关代码</h2><pre><code> @Override public Response upload(MultipartFile file) { if (file == null) { return Response.fail().message("缺少必要参数!"); } //获取文件名加后缀 String fileName = file.getOriginalFilename(); if (fileName == null) { return Response.fail().message("上传异常!"); } //获取文件后缀 String suffix = ""; int index = fileName.lastIndexOf("."); if (index > 0) { suffix = file.getOriginalFilename().substring(index, fileName.length()); } String contentType = file.getContentType(); String resources = ALYConstants.OSS_PUBLIC_PICTURE + "other/"; if (contentType != null) { if (contentType.contains("video")) { resources = ALYConstants.OSS_PUBLIC_PICTURE + "video/"; } else if (contentType.contains("image")) { resources = ALYConstants.OSS_PUBLIC_PICTURE + "image/"; if (StringUtils.isBlank(suffix)) { suffix = ".jpg"; } } } //组合新的文件名 String imgName = DateUtils.dateTimeNow() + "-" + IdUtils.fastSimpleUUID() + suffix; resources = resources + DateUtils.dateTime() + "/"; try { boolean state = this.oss(file.getBytes(), resources + imgName); if (!state) { return Response.fail().message("文件上传失败!"); } } catch (IOException e) { log.error("【oss上传资源异常,异常信息:[{}]】", e.getMessage()); } String url = ALYConstants.OSS_STATIC_MAIN_LINK + resources + imgName; this.insert(file, url, imgName, suffix, contentType); return Response.ok().content(new JSONObject() {{ put("url", url); }}); } @Override public String videoToImage(String url) throws Exception { String targetFilePath = ""; FFmpegFrameGrabber grabber = FFmpegFrameGrabber.createDefault(url); grabber.start(); //判断是否是竖屏小视频 String rotate = grabber.getVideoMetadata("rotate"); int lengthInFrames = grabber.getLengthInFrames(); Frame frame; int i = 0; int index = 3;//截取图片第几帧 while (i < lengthInFrames) { frame = grabber.grabImage(); if (i == index) { if (null != rotate && rotate.length() > 1) { targetFilePath = doExecuteFrame(frame, true); //获取缩略图 } else { targetFilePath = doExecuteFrame(frame, false); //获取缩略图 } break; } i++; } grabber.stop(); return targetFilePath; //返回的是视频第N帧 } private void insert(MultipartFile file, String url, String newName, String suffix, String contentType) { String memberId = memberService.infoId(); CpFile cpFile = new CpFile(); cpFile.setId(IdUtils.getSnowFlakeId()); cpFile.setMemberId(memberId); cpFile.setName(file.getOriginalFilename()); cpFile.setNewName(newName); cpFile.setUrl(url); cpFile.setType(contentType); cpFile.setSize(file.getSize()); cpFile.setSuffix(suffix); cpFile.setCreateTime(DateUtils.getNowDate()); this.baseMapper.insert(cpFile); log.info("【文件上传,上传用户:[{}],地址:[{}]】", memberId, url); } private boolean oss(byte[] file, String name) { String oss = ALYConstants.OSS_STATIC_POSITION; String endpoint = ALYConstants.OSS_ENDPOINT; String accessKeyId = ALYConstants.OSS_ACCESS_KEY; String accessKeySecret = ALYConstants.OSS_ACCESS_SECRET; try { //创建OSSClient实例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); //传Byte数组。 ossClient.putObject(oss, name, new ByteArrayInputStream(file)); //关闭OSSClient。 ossClient.shutdown(); return true; } catch (Exception e) { log.error("【文件上传失败,错误信息:[{}]】", e.getMessage()); } return false; } /** * 截取缩略图,存入阿里云OSS(按自己的上传类型自定义转换文件格式) * * @return 图片地址 * @throws Exception */ public String doExecuteFrame(Frame f, boolean direction) throws Exception { if (null == f || null == f.image) { return ""; } Java2DFrameConverter converter = new Java2DFrameConverter(); BufferedImage bi = converter.getBufferedImage(f); if (direction) { Image image = (Image) bi; bi = rotate(image, 90);//图片旋转90度 } ByteArrayOutputStream os = new ByteArrayOutputStream(); ImageIO.write(bi, "png", os); InputStream input = new ByteArrayInputStream(os.toByteArray()); MultipartFile multipartFile = new MockMultipartFile("temp.jpg", "temp.jpg", "temp.jpg", input); Response data = this.upload(multipartFile); Object content = data.getContent(); return JSONObject.parseObject(String.valueOf(content)).getString("url"); } /** * 图片旋转角度 * * @param src 源图片 * @param angel 角度 * @return 目标图片 */ public static BufferedImage rotate(Image src, int angel) { int src_width = src.getWidth(null); int src_height = src.getHeight(null); // calculate the new image size Rectangle rectangle = CalcRotatedSize(new Rectangle(new Dimension( src_width, src_height)), angel); BufferedImage res; res = new BufferedImage(rectangle.width, rectangle.height, BufferedImage.TYPE_INT_RGB); Graphics2D g2 = res.createGraphics(); // transform(这里先平移、再旋转比较方便处理;绘图时会采用这些变化,绘图默认从画布的左上顶点开始绘画,源图片的左上顶点与画布左上顶点对齐,然后开始绘画,修改坐标原点后,绘画对应的画布起始点改变,起到平移的效果;然后旋转图片即可) //平移(原理修改坐标系原点,绘图起点变了,起到了平移的效果,如果作用于旋转,则为旋转中心点) g2.translate((rectangle.width - src_width) / 2, (rectangle.height - src_height) / 2); // 旋转(原理transalte(dx,dy)->rotate(radians)->transalte(-dx,-dy);修改坐标系原点后,旋转90度,然后再还原坐标系原点为(0,0),但是整个坐标系已经旋转了相应的度数 ) g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2); // 先旋转(以目标区域中心点为旋转中心点,源图片左上顶点对准目标区域中心点,然后旋转) // g2.translate(rect_des.width/2,rect_des.height/ 2); // g2.rotate(Math.toRadians(angel)); // 再平移(原点恢复到源图的左上顶点处(现在的右上顶点处),否则只能画出1/4) // g2.translate(-src_width/2,-src_height/2); g2.drawImage(src, null, null); return res; } /** * 计算转换后目标矩形的宽高 * * @param src 源矩形 * @param angel 角度 * @return 目标矩形 */ private static Rectangle CalcRotatedSize(Rectangle src, int angel) { double cos = Math.abs(Math.cos(Math.toRadians(angel))); double sin = Math.abs(Math.sin(Math.toRadians(angel))); int des_width = (int) (src.width * cos) + (int) (src.height * sin); int des_height = (int) (src.height * cos) + (int) (src.width * sin); return new java.awt.Rectangle(new Dimension(des_width, des_height)); }</code></pre>]]></content>
<categories>
<category> JAVA </category>
</categories>
<tags>
<tag> java </tag>
</tags>
</entry>
<entry>
<title>[JAVA]跨域解决方法</title>
<link href="/2020/04/01/JAVA-%E8%B7%A8%E5%9F%9F%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95/"/>
<url>/2020/04/01/JAVA-%E8%B7%A8%E5%9F%9F%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95/</url>
<content type="html"><![CDATA[<p><strong>前后端交互出现跨域错误</strong></p><p>error</p><pre><code>home:1 Access to XMLHttpRequest at 'http://127.0.0.1:8080/article/list?start=1&limit=5' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.</code></pre><h1 id="解决"><a href="#解决" class="headerlink" title="解决"></a>解决</h1><h2 id="一、-CrossOrigin"><a href="#一、-CrossOrigin" class="headerlink" title="一、@CrossOrigin"></a>一、@CrossOrigin</h2><p>该注解可使用在类或者方法上,针对性的解决部分接口的跨域问题。</p><h2 id="二、拦截器(全局)"><a href="#二、拦截器(全局)" class="headerlink" title="二、拦截器(全局)"></a>二、拦截器(全局)</h2><pre><code>@Configurationpublic class WebMvcConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE") .maxAge(3600) .allowCredentials(true); }}</code></pre><h2 id="三、CorsFilter(全局)"><a href="#三、CorsFilter(全局)" class="headerlink" title="三、CorsFilter(全局)"></a>三、CorsFilter(全局)</h2><pre><code>@Configurationpublic class CrossDomainConfig { @Bean public CorsFilter corsFilter() { //1.添加CORS配置信息 CorsConfiguration config = new CorsConfiguration(); //放行哪些原始域 config.addAllowedOrigin("*"); //是否发送Cookie信息 config.setAllowCredentials(true); //放行哪些原始域(请求方式) config.addAllowedMethod("*"); //放行哪些原始域(头部信息) config.addAllowedHeader("*"); //暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息) config.addExposedHeader("content-type"); //2.添加映射路径 UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource(); configSource.registerCorsConfiguration("/**", config); //3.返回新的CorsFilter. return new CorsFilter(configSource); }}</code></pre>]]></content>
<categories>
<category> JAVA </category>
</categories>
<tags>
<tag> java </tag>
</tags>
</entry>
<entry>
<title>[Other]Linux个人常用命令整理</title>
<link href="/2020/03/29/Other-Linux%E4%B8%AA%E4%BA%BA%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4%E6%95%B4%E7%90%86/"/>
<url>/2020/03/29/Other-Linux%E4%B8%AA%E4%BA%BA%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4%E6%95%B4%E7%90%86/</url>
<content type="html"><![CDATA[<h2 id="1、查看整体机器性能"><a href="#1、查看整体机器性能" class="headerlink" title="1、查看整体机器性能"></a>1、查看整体机器性能</h2><p> top</p><pre><code> --1.1 cpu --1.2 mem --1.3 id = idle 空闲率(越大越好) --1.4 load average 系统负载率(后面三个值分别是1分钟5分钟15分钟的平均负载 如果这三个值相加除三乘百分之百高于60说明系统负担重, 高于80说明要gg了)</code></pre><h2 id="2、低配版查看整机性能"><a href="#2、低配版查看整机性能" class="headerlink" title="2、低配版查看整机性能"></a>2、低配版查看整机性能</h2><p>uptime</p><pre><code> --19:21:23 up 17 min, 2 users, load average: 0.00, 0.00, 0.00</code></pre><h2 id="3、内存"><a href="#3、内存" class="headerlink" title="3、内存"></a>3、内存</h2><p>free</p><pre><code> --free -m</code></pre><h2 id="4、硬盘"><a href="#4、硬盘" class="headerlink" title="4、硬盘"></a>4、硬盘</h2><p>df</p><pre><code> --df -h</code></pre><h2 id="5、cpu"><a href="#5、cpu" class="headerlink" title="5、cpu"></a>5、cpu</h2><p>vmstat(包含但不限于)</p><pre><code>--[root@contOS-1 ~]# vmstat -n 2 3procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 0 0 0 904864 27448 39636 0 0 50 4 22 28 0 1 99 0 0 0 0 0 904848 27448 39632 0 0 0 0 14 13 0 0 100 0 0 0 0 0 904848 27448 39632 0 0 0 0 15 13 0 0 100 0 0 </code></pre><h2 id="6、磁盘-io高很大可能写了大sql"><a href="#6、磁盘-io高很大可能写了大sql" class="headerlink" title="6、磁盘(io高很大可能写了大sql)"></a>6、磁盘(io高很大可能写了大sql)</h2><p>iostat</p><pre><code> --iostat -xdk 2 3 --r/s w/s 每s读写</code></pre><p>——————–以上源于周阳哥讲解,我总结的笔记</p><hr><p>其他</p><h2 id="1、获取线程总数"><a href="#1、获取线程总数" class="headerlink" title="1、获取线程总数"></a>1、获取线程总数</h2><pre><code>pstree -p 22704|wc -l</code></pre><h2 id="2、linux相关的参数"><a href="#2、linux相关的参数" class="headerlink" title="2、linux相关的参数"></a>2、linux相关的参数</h2><pre><code>ulimit -a</code></pre><h2 id="3、Logstash"><a href="#3、Logstash" class="headerlink" title="3、Logstash"></a>3、Logstash</h2><pre><code>systemctl start|restart|stop elasticsearch</code></pre><h2 id="4、nginx日志情况"><a href="#4、nginx日志情况" class="headerlink" title="4、nginx日志情况"></a>4、nginx日志情况</h2><pre><code>grep '"responsetime":2.' /usr/local/nginx/logs/access.log</code></pre><h2 id="5、java堆栈分析"><a href="#5、java堆栈分析" class="headerlink" title="5、java堆栈分析"></a>5、java堆栈分析</h2><pre><code>进程十六进制值printf "%x\n" 22414jstack -l PID > jstack.log</code></pre><blockquote><p>dump 文件里,值得关注的线程状态有:</p><p>死锁,Deadlock(重点关注)</p><p>执行中,Runnable </p><p>等待资源,Waiting on condition(重点关注)</p><p>等待获取监视器,Waiting on monitor entry(重点关注)</p><p>暂停,Suspended</p><p>对象等待中,Object.wait() 或 TIMED_WAITING</p><p>阻塞,Blocked(重点关注) </p><p>停止,Parked</p></blockquote>]]></content>
<categories>
<category> Other </category>
</categories>
<tags>
<tag> linux </tag>
</tags>
</entry>
<entry>
<title>[Cloud]Hystrix断路器</title>
<link href="/2020/03/27/Cloud-Hystrix%E6%96%AD%E8%B7%AF%E5%99%A8/"/>
<url>/2020/03/27/Cloud-Hystrix%E6%96%AD%E8%B7%AF%E5%99%A8/</url>
<content type="html"><![CDATA[<h1 id="是什么?"><a href="#是什么?" class="headerlink" title="是什么?"></a>是什么?</h1><blockquote><p>Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,</p><p>Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。</p><p>“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。</p></blockquote><hr><h1 id="Hystrix重要概念"><a href="#Hystrix重要概念" class="headerlink" title="Hystrix重要概念"></a>Hystrix重要概念</h1><p>服务降级:服务器忙,请稍后再试,不让客户端等待并立刻返回一个友好提示,fallback</p><p>服务熔断:类比保险丝达到最大服务访问后,直接拒绝访问,拉闸限电,然后调用服务降级的方法并返回友好提示</p><p>服务限流:秒杀高并发等操作,严禁一窝蜂的过来拥挤,大家排队,一秒钟N个,有序进行</p>]]></content>
<categories>
<category> JAVA </category>
</categories>
<tags>
<tag> SpringCloud </tag>
</tags>
</entry>
<entry>
<title>[Cloud]8-OpenFeign</title>
<link href="/2020/03/22/Cloud-8-OpenFeign/"/>
<url>/2020/03/22/Cloud-8-OpenFeign/</url>
<content type="html"><![CDATA[<h1 id="OpenFeign"><a href="#OpenFeign" class="headerlink" title="OpenFeign"></a>OpenFeign</h1><h2 id="是什么?"><a href="#是什么?" class="headerlink" title="是什么?"></a>是什么?</h2><blockquote><p>Feign是一个声明式WebService客户端。使用Feign能让编写Web Service客户端更加简单。<br>它的使用方法是定义一个服务接口然后在上面添加注解即可。</p></blockquote><p>github: <a href="https://github.com/spring-cloud/spring-cloud-openfeign" target="_blank" rel="noopener">点击访问</a></p><h2 id="能干嘛?"><a href="#能干嘛?" class="headerlink" title="能干嘛?"></a>能干嘛?</h2><blockquote><p>可以在使编写Java Http客户端变得更容易。</p><p>前面在使用Ribbon+RestTemplate时,利用RestTemplate对http请求的封装处理,形成了一套模版化的调用方法。</p></blockquote><h2 id="编码"><a href="#编码" class="headerlink" title="编码"></a>编码</h2><h3 id="新建cloud-comsumer-fegin-order80"><a href="#新建cloud-comsumer-fegin-order80" class="headerlink" title="新建cloud-comsumer-fegin-order80"></a>新建cloud-comsumer-fegin-order80</h3><p>pom新增</p><pre><code><dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId></dependency></code></pre><h3 id="yml"><a href="#yml" class="headerlink" title="yml"></a>yml</h3><pre><code>server: port: 80eureka: client: register-with-eureka: false #是否将自己注册到注册中心,集群必须设置为true配合ribbon service-url: #defaultZone: http://localhost:7001/eureka defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/ #集群版</code></pre><h3 id="主启动类"><a href="#主启动类" class="headerlink" title="主启动类"></a>主启动类</h3><p>@EnableFeignClients</p><pre><code>@SpringBootApplication@EnableFeignClientspublic class OrderFeignMain80 { public static void main(String[] args) { SpringApplication.run(OrderFeignMain80.class, args); }}</code></pre><h3 id="业务类编写"><a href="#业务类编写" class="headerlink" title="业务类编写"></a>业务类编写</h3><p><strong>定义一个feign接口</strong></p><pre><code>@Configuration@FeignClient(value = "CLOUD-PAYMENT-SERVICE")public interface PaymentFeignService { @GetMapping(value = "/payment/get/{id}") CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);}</code></pre><p><strong>controller</strong></p><pre><code>@RestController@Slf4jpublic class OrderFeignController { @Resource private PaymentFeignService paymentFeignService; @GetMapping(value = "/consumer/payment/get/{id}") public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) { return paymentFeignService.getPaymentById(id); }}</code></pre><h3 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h3><p>访问 <a href="http://127.0.0.1/consumer/payment/get/1" target="_blank" rel="noopener">http://127.0.0.1/consumer/payment/get/1</a> 即可发现跟前面写的Ribbon+RestTemplate效果一致。</p><hr><h2 id="OpenFeign超时控制"><a href="#OpenFeign超时控制" class="headerlink" title="OpenFeign超时控制"></a>OpenFeign超时控制</h2><p>cloud-provider-payment8001服务新增接口,同时cloud-comsumer-fegin-order80服务的PaymentFeignService接口和controller同样添加调用。</p><pre><code> @GetMapping("/payment/feign/timeout") public String paymentFeignTimeOut(){ //测试OpenFeign超时 try { TimeUnit.SECONDS.sleep(3); }catch (InterruptedException e){ e.printStackTrace(); } return serverPort; }</code></pre><h2 id="测试-1"><a href="#测试-1" class="headerlink" title="测试"></a>测试</h2><p>访问<a href="http://127.0.0.1:8001/payment/feign/timeout" target="_blank" rel="noopener">http://127.0.0.1:8001/payment/feign/timeout</a> -正常</p><p>访问<a href="http://127.0.0.1/consumer/payment/feign/timeout" target="_blank" rel="noopener">http://127.0.0.1/consumer/payment/feign/timeout</a> -超时</p><pre><code>connect timed out executing GET http://CLOUD-PAYMENT-SERVICE/payment/feign/timeoutfeign.RetryableException: connect timed out executing GET http://CLOUD-PAYMENT-SERVICE/payment/feign/timeout at feign.FeignException.errorExecuting(FeignException.java:213)</code></pre><h3 id="超时解决配置"><a href="#超时解决配置" class="headerlink" title="超时解决配置"></a>超时解决配置</h3><pre><code>#设置feign客户端超时时间ribbon: #指的是建立连接后从服务器读取到可用资源所用的时间 ReadTimeout: 5000 #指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间 ConnectTimeout: 5000</code></pre><hr><h2 id="OpenFeign日志增强"><a href="#OpenFeign日志增强" class="headerlink" title="OpenFeign日志增强"></a>OpenFeign日志增强</h2><h3 id="日志级别"><a href="#日志级别" class="headerlink" title="日志级别"></a>日志级别</h3><blockquote><p>NONE:默认的,不显示任何日志;</p><p>BASIC:仅记录请求方法、URL、响应状态码及执行时间;</p><p>HEADERS:除了BASIC中定义的信息之外,还有请求和响应的头信息;</p><p>FULL:除了HEADERS中定义的信息之外,还有请求和响的正文及元数据。</p></blockquote><h3 id="添加配置类"><a href="#添加配置类" class="headerlink" title="添加配置类"></a>添加配置类</h3><pre><code>@Configurationpublic class FeignConfig { @Bean Logger.Level feignLoggerLevel(){ return Logger.Level.FULL; }}</code></pre><h3 id="yml-1"><a href="#yml-1" class="headerlink" title="yml"></a>yml</h3><pre><code>logging: level: #以什么级别监控哪个接口 xyz.zx21.springcloud.service.PaymentFeignService: debug</code></pre><h3 id="测试-2"><a href="#测试-2" class="headerlink" title="测试"></a>测试</h3><p>访问 <a href="http://127.0.0.1/consumer/payment/get/1" target="_blank" rel="noopener">http://127.0.0.1/consumer/payment/get/1</a></p><p>控制台输出日志</p><pre><code>2020-03-22 19:46:33.369 DEBUG 3496 --- [p-nio-80-exec-2] x.z.s.service.PaymentFeignService : [PaymentFeignService#getPaymentById] ---> GET http://CLOUD-PAYMENT-SERVICE/payment/get/1 HTTP/1.12020-03-22 19:46:33.370 DEBUG 3496 --- [p-nio-80-exec-2] x.z.s.service.PaymentFeignService : [PaymentFeignService#getPaymentById] ---> END HTTP (0-byte body)2020-03-22 19:46:33.376 DEBUG 3496 --- [p-nio-80-exec-2] x.z.s.service.PaymentFeignService : [PaymentFeignService#getPaymentById] <--- HTTP/1.1 200 (6ms)2020-03-22 19:46:33.377 DEBUG 3496 --- [p-nio-80-exec-2] x.z.s.service.PaymentFeignService : [PaymentFeignService#getPaymentById] connection: keep-alive2020-03-22 19:46:33.377 DEBUG 3496 --- [p-nio-80-exec-2] x.z.s.service.PaymentFeignService : [PaymentFeignService#getPaymentById] content-type: application/json2020-03-22 19:46:33.377 DEBUG 3496 --- [p-nio-80-exec-2] x.z.s.service.PaymentFeignService : [PaymentFeignService#getPaymentById] date: Sun, 22 Mar 2020 11:46:33 GMT2020-03-22 19:46:33.377 DEBUG 3496 --- [p-nio-80-exec-2] x.z.s.service.PaymentFeignService : [PaymentFeignService#getPaymentById] keep-alive: timeout=602020-03-22 19:46:33.377 DEBUG 3496 --- [p-nio-80-exec-2] x.z.s.service.PaymentFeignService : [PaymentFeignService#getPaymentById] transfer-encoding: chunked2020-03-22 19:46:33.377 DEBUG 3496 --- [p-nio-80-exec-2] x.z.s.service.PaymentFeignService : [PaymentFeignService#getPaymentById] 2020-03-22 19:46:33.377 DEBUG 3496 --- [p-nio-80-exec-2] x.z.s.service.PaymentFeignService : [PaymentFeignService#getPaymentById] {"code":200,"message":"查询成功,serverPort: 8001","data":{"id":1,"serial":"小信"}}2020-03-22 19:46:33.377 DEBUG 3496 --- [p-nio-80-exec-2] x.z.s.service.PaymentFeignService : [PaymentFeignService#getPaymentById] <--- END HTTP (88-byte body)</code></pre>]]></content>
<categories>
<category> JAVA </category>
</categories>
<tags>
<tag> SpringCloud </tag>
</tags>
</entry>
<entry>
<title>[Cloud]7-Ribbon相关</title>
<link href="/2020/03/22/Cloud-7-Ribbon%E7%9B%B8%E5%85%B3/"/>
<url>/2020/03/22/Cloud-7-Ribbon%E7%9B%B8%E5%85%B3/</url>
<content type="html"><![CDATA[<h1 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h1><h2 id="是什么?"><a href="#是什么?" class="headerlink" title="是什么?"></a>是什么?</h2><blockquote><p>Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。<br>简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法和服务调用。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。我们很容易使用Ribbon实现自定义的负载均衡算法。</p></blockquote><p><strong>负载均衡+ResTemplate调用</strong></p><h2 id="IRule"><a href="#IRule" class="headerlink" title="IRule"></a>IRule</h2><p>特定算法:</p><pre><code>com.netflix.loadbalancer.RoundRobinRule -轮询com.netflix.loadbalancer.RandomRule-随机com.netflix.loadbalance.RetryRule-先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内会进行重试WeightedResponseTimeRule-对RoundRobinRule的扩展,响应速度越快的实例选择权重越大,越容易被选择BestAvailableRule-会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务AvailabilityFilteringRule-先过滤掉故障实例,再选择并发较小的实例ZoneAvoidanceRule-默认规则,复合判断server所在区域的性能和server的可用性选择服务器</code></pre><hr><h1 id="Ribbon负载"><a href="#Ribbon负载" class="headerlink" title="Ribbon负载"></a>Ribbon负载</h1><h2 id="负载规则替换"><a href="#负载规则替换" class="headerlink" title="负载规则替换"></a>负载规则替换</h2><p>注意:这个自定义配置类不能放在@ComponentScan所扫描的当前包下以及子包下,否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,达不到特殊化定制的目的了。</p><h3 id="新建MySelfRule类"><a href="#新建MySelfRule类" class="headerlink" title="新建MySelfRule类"></a>新建MySelfRule类</h3><pre><code>@Configurationpublic class MySelfRule { @Bean public IRule myRule() { //定义为随机 return new RandomRule(); }}</code></pre><h3 id="修改主启动类"><a href="#修改主启动类" class="headerlink" title="修改主启动类"></a>修改主启动类</h3><p>添加注解@RibbonClient</p><pre><code>@SpringBootApplication@EnableEurekaClient@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration = MySelfRule.class)public class OrderMain80 { public static void main(String[] args) { SpringApplication.run(OrderMain80.class, args); }}</code></pre><h3 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h3><p>访问<a href="http://127.0.0.1/consumer/payment/getForEntity/1" target="_blank" rel="noopener">http://127.0.0.1/consumer/payment/getForEntity/1</a> ,这个时候轮询变成了随机。</p><h2 id="负载轮询算法"><a href="#负载轮询算法" class="headerlink" title="负载轮询算法"></a>负载轮询算法</h2><pre><code>负载轮询算法:rest接口第几次请求数%服务器集群总数量=实际调用服务器位置下标,每次服务重启动后rest接口计数从1开始。</code></pre><h3 id="源码"><a href="#源码" class="headerlink" title="源码"></a>源码</h3><p>RoundRobinRule</p><pre><code> public Server choose(ILoadBalancer lb, Object key) { if (lb == null) { log.warn("no load balancer"); return null; } Server server = null; int count = 0; while (server == null && count++ < 10) { List<Server> reachableServers = lb.getReachableServers(); List<Server> allServers = lb.getAllServers(); int upCount = reachableServers.size(); int serverCount = allServers.size(); if ((upCount == 0) || (serverCount == 0)) { log.warn("No up servers available from load balancer: " + lb); return null; } int nextServerIndex = incrementAndGetModulo(serverCount); server = allServers.get(nextServerIndex); if (server == null) { /* Transient. */ Thread.yield(); continue; } if (server.isAlive() && (server.isReadyToServe())) { return (server); } // Next. server = null; } if (count >= 10) { log.warn("No available alive servers after 10 tries from load balancer: " + lb); } return server; }</code></pre><h2 id="手写轮询算法"><a href="#手写轮询算法" class="headerlink" title="手写轮询算法"></a>手写轮询算法</h2><h3 id="8001-8002"><a href="#8001-8002" class="headerlink" title="8001/8002"></a>8001/8002</h3><p>controller添加如下,方便测试。</p><pre><code> @GetMapping(value = "/payment/lb") public String getPaymentLB(){ return serverPort; }</code></pre><h3 id="注释掉消费端的-LoadBalanced"><a href="#注释掉消费端的-LoadBalanced" class="headerlink" title="注释掉消费端的@LoadBalanced"></a>注释掉消费端的@LoadBalanced</h3><p>测试自己写的负载均衡是否生效。</p><h3 id="定义接口LoadBalance"><a href="#定义接口LoadBalance" class="headerlink" title="定义接口LoadBalance"></a>定义接口LoadBalance</h3><pre><code>public interface LoadBalance { ServiceInstance instance(List<ServiceInstance> serviceInstances);}</code></pre><h3 id="接口实现类"><a href="#接口实现类" class="headerlink" title="接口实现类"></a>接口实现类</h3><pre><code>@Componentpublic class MyLB implements LoadBalance { private AtomicInteger atomicInteger = new AtomicInteger(0); public final int getAndIncrement() { int current; int next; do { current = this.atomicInteger.get(); next = current >= 2147483647 ? 0 : current + 1; } while (!this.atomicInteger.compareAndSet(current, next)); //CAS System.out.println("*****第几次访问,次数next: " + next); return next; } @Override public ServiceInstance instance(List<ServiceInstance> serviceInstances) { int index = getAndIncrement() % serviceInstances.size(); return serviceInstances.get(index); }}</code></pre><h3 id="修改controller"><a href="#修改controller" class="headerlink" title="修改controller"></a>修改controller</h3><pre><code> @Resource private RestTemplate restTemplate; @Resource private LoadBalance loadBalance; @Resource private DiscoveryClient discoveryClient; @GetMapping("/consumer/payment/lb") public String getPaymentLB() { List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE"); if (instances == null || instances.size() <= 0) { return null; } ServiceInstance serviceInstance = loadBalance.instance(instances); URI uri = serviceInstance.getUri(); return restTemplate.getForObject(uri + "/payment/lb", String.class); }</code></pre><h3 id="测试-1"><a href="#测试-1" class="headerlink" title="测试"></a>测试</h3><p>访问<a href="http://localhost//consumer/payment/lb" target="_blank" rel="noopener">http://localhost//consumer/payment/lb</a> ,发现每次访问端口都在变化。</p>]]></content>
<categories>
<category> JAVA </category>
</categories>
<tags>
<tag> SringCloud </tag>
</tags>
</entry>
<entry>
<title>[Cloud]6-三个注册中心异同点</title>
<link href="/2020/03/21/Cloud-6-%E4%B8%89%E4%B8%AA%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E5%BC%82%E5%90%8C%E7%82%B9/"/>
<url>/2020/03/21/Cloud-6-%E4%B8%89%E4%B8%AA%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E5%BC%82%E5%90%8C%E7%82%B9/</url>
<content type="html"><![CDATA[<h1 id="异同点"><a href="#异同点" class="headerlink" title="异同点"></a>异同点</h1><p>|组件名|语言|CAP|服务健康检查|对外暴露接口|<br>|:—– |:—–|:—–<br>|Eureka |Java|AP|可配支持|HTTP|<br>|Consul |Go|CP|支持|HTTP/DNS|<br>|ZooKeeper |java|CP|支持|客户端</p><h1 id="CAP"><a href="#CAP" class="headerlink" title="CAP"></a>CAP</h1><p>CAP理论关注粒度是数据,而不是整体系统设计的策略</p><blockquote><p><strong>C:Consistency(强一致性)</strong></p></blockquote><blockquote><p><strong>A:Availability(可用性)</strong></p></blockquote><blockquote><p><strong>P:Partition tolerance(分区容错性)</strong></p></blockquote><p>最多只能同时较好的满足两个。<br>CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,因此,根据 CAP原理将NoSQL数据库分成了满足CA原则、满足CP原则和满足AP原则三大类: </p><p>CA-单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。</p><p>CP-满足一致性,分区容忍性的系统,通常性能不是特别高。</p><p>AP-满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。</p>]]></content>
<categories>
<category> JAVA </category>
</categories>
<tags>
<tag> SpringCloud </tag>
</tags>
</entry>
<entry>
<title>[Cloud]5-集成Consul</title>
<link href="/2020/03/21/Cloud-5-%E9%9B%86%E6%88%90Consul/"/>
<url>/2020/03/21/Cloud-5-%E9%9B%86%E6%88%90Consul/</url>
<content type="html"><![CDATA[<h1 id="Consul"><a href="#Consul" class="headerlink" title="Consul"></a>Consul</h1><h2 id="安装与启动"><a href="#安装与启动" class="headerlink" title="安装与启动"></a>安装与启动</h2><p>下载地址:<a href="https://www.consul.io/downloads.html" target="_blank" rel="noopener">点击</a></p><p>我用windows测试的,解压有一个exe程序, cmd</p><p>启动:<strong>consul agent -dev</strong></p><p>访问:<strong><a href="http://127.0.0.1:8500/ui/dc1/services" target="_blank" rel="noopener">http://127.0.0.1:8500/ui/dc1/services</a></strong></p><hr><h1 id="编码"><a href="#编码" class="headerlink" title="编码"></a>编码</h1><h2 id="服务提供者"><a href="#服务提供者" class="headerlink" title="服务提供者"></a>服务提供者</h2><p>新增cloud-provider-payment8006</p><h3 id="pom"><a href="#pom" class="headerlink" title="pom"></a>pom</h3><pre><code><dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId></dependency></code></pre><h3 id="application-yml"><a href="#application-yml" class="headerlink" title="application.yml"></a>application.yml</h3><pre><code>server: port: 8006# 服务别名---consul注册中心名称spring: application: name: consul-provider-payment cloud: consul: host: localhost port: 8500 discovery: service-name: ${spring.application.name}</code></pre><h3 id="controller"><a href="#controller" class="headerlink" title="controller"></a>controller</h3><pre><code>@RestController@Slf4jpublic class PaymentController { @Value("${server.port}") private String serverPort; @GetMapping(value = "/payment/consul") public String paymentzk() { return "springcloud with consul: " + serverPort + "\t" + UUID.randomUUID().toString(); }}</code></pre><hr><h2 id="服务消费者"><a href="#服务消费者" class="headerlink" title="服务消费者"></a>服务消费者</h2><p>新增cloud-consumerconsul-order80</p><h3 id="pom-1"><a href="#pom-1" class="headerlink" title="pom"></a>pom</h3><p>跟提供者服务一致</p><h3 id="application-yml-1"><a href="#application-yml-1" class="headerlink" title="application.yml"></a>application.yml</h3><pre><code>server: port: 80# 服务别名---consul注册中心名称spring: application: name: consul-consumer-order cloud: consul: host: localhost port: 8500 discovery: service-name: ${spring.application.name}</code></pre><h3 id="controller-1"><a href="#controller-1" class="headerlink" title="controller"></a>controller</h3><pre><code>@RestController@Slf4jpublic class OrderConsulController { private static final String INVOKE_URL = "http://consul-provider-payment"; @Resource private RestTemplate restTemplate; @GetMapping(value = "/consumer/payment/consul") public String paymentInfo(){ String result = restTemplate.getForObject(INVOKE_URL + "/payment/consul", String.class); return result; }}</code></pre><h3 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h3><p>访问<a href="http://127.0.0.1/consumer/payment/consul" target="_blank" rel="noopener">http://127.0.0.1/consumer/payment/consul</a> 可以调用成功!</p>]]></content>
<categories>
<category> JAVA </category>
</categories>
<tags>
<tag> SpringCloud </tag>
</tags>
</entry>
<entry>
<title>[Cloud]4-集成ZooKeeper</title>
<link href="/2020/03/21/Cloud-4-%E9%9B%86%E6%88%90ZooKeeper/"/>
<url>/2020/03/21/Cloud-4-%E9%9B%86%E6%88%90ZooKeeper/</url>
<content type="html"><![CDATA[<p><strong>本机与虚拟机测试,注意:保证本机与虚拟机能互相ping通</strong></p><h1 id="zookeepper命令"><a href="#zookeepper命令" class="headerlink" title="zookeepper命令"></a>zookeepper命令</h1><pre><code>1. 启动ZK服务: zkServer.sh start2. 查看ZK服务状态: zkServer.sh status3. 停止ZK服务: zkServer.sh stop4. 重启ZK服务: zkServer.sh restart5. ZK服务连接: zkCli.sh</code></pre><hr><h1 id="新建服务提供者"><a href="#新建服务提供者" class="headerlink" title="新建服务提供者"></a>新建服务提供者</h1><h2 id="cloud-provider-payment8004"><a href="#cloud-provider-payment8004" class="headerlink" title="cloud-provider-payment8004"></a>cloud-provider-payment8004</h2><p>引入zookeeper相关的依赖</p><pre><code><?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>cloud2020</artifactId> <groupId>xyz.zx21.springcloud</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>cloud-provider-payment8004</artifactId> <dependencies> <dependency> <artifactId>cloud-api-commons</artifactId> <groupId>xyz.zx21.springcloud</groupId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.10</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <!-- 引入zookeeper客户端 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId> <exclusions> <exclusion> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.10</version> </dependency> </dependencies></project></code></pre><h2 id="application-yml"><a href="#application-yml" class="headerlink" title="application.yml"></a>application.yml</h2><pre><code>server: port: 8004# 服务别名---注册zookeeper到注册中心名称spring: application: name: cloud-provider-payment cloud: zookeeper: connect-string: 192.168.8.208:2181 max-retries: 10 datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: org.gjt.mm.mysql.Driver url: jdbc:mysql://127.0.0.1:3306/db2019?useUnicode=true&characterEncoding=utf-8&useSSL=false username: root password: 123456</code></pre><h2 id="controller测试"><a href="#controller测试" class="headerlink" title="controller测试"></a>controller测试</h2><pre><code>@RestController@Slf4jpublic class PaymentController { @Value("${server.port}") private String serverPort; @GetMapping(value = "/payment/zk") public String paymentzk() { return "springcloud with zookeeper: " + serverPort + "\t" + UUID.randomUUID().toString(); }}</code></pre><h2 id="主启动类"><a href="#主启动类" class="headerlink" title="主启动类"></a>主启动类</h2><pre><code>/** * @author Administrator * @date 2020/3/19 14:10 * * //@EnableDiscoveryClient该注解用于向使用consul或 zookeeper作为法册中心时注册服务 */@SpringBootApplication@EnableDiscoveryClientpublic class PaymentMain8004 { public static void main(String[] args) { SpringApplication.run(PaymentMain8004.class, args); }}</code></pre><h2 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h2><p>启动zookeeper,运行微服务。</p><pre><code>[zk: localhost:2181(CONNECTED) 25] ls / [services, zookeeper][zk: localhost:2181(CONNECTED) 26] ls /services [cloud-provider-payment][zk: localhost:2181(CONNECTED) 27] ls /services/cloud-provider-payment[c0ca3c06-7384-42a1-bfa2-63ed8e6f3a1e][zk: localhost:2181(CONNECTED) 28] [zk: localhost:2181(CONNECTED) 28] get /services/cloud-provider-payment/c0ca3c06-7384-42a1-bfa2-63ed8e6f3a1e{"name":"cloud-provider-payment","id":"c0ca3c06-7384-42a1-bfa2-63ed8e6f3a1e","address":"DESKTOP-T08AAHT","port":8004,"sslPort":null,"payload":{"@class":"org.springframework.cloud.zookeeper.discovery.ZookeeperInstance","id":"application-1","name":"cloud-provider-payment","metadata":{}},"registrationTimeUTC":1584766408452,"serviceType":"DYNAMIC","uriSpec":{"parts":[{"value":"scheme","variable":true},{"value":"://","variable":false},{"value":"address","variable":true},{"value":":","variable":false},{"value":"port","variable":true}]}}cZxid = 0x36ctime = Sat Mar 21 20:47:00 CST 2020mZxid = 0x36mtime = Sat Mar 21 20:47:00 CST 2020pZxid = 0x36cversion = 0dataVersion = 0aclVersion = 0ephemeralOwner = 0x170fd2061fe0002dataLength = 536numChildren = 0</code></pre><hr><h1 id="新建消费者cloud-consumerzk-order80"><a href="#新建消费者cloud-consumerzk-order80" class="headerlink" title="新建消费者cloud-consumerzk-order80"></a>新建消费者cloud-consumerzk-order80</h1><h2 id="application-yml-1"><a href="#application-yml-1" class="headerlink" title="application.yml"></a>application.yml</h2><pre><code>server: port: 80spring: application: name: cloud-consumer-order cloud: zookeeper: connect-string: 192.168.8.208:2181 max-retries: 10 datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: org.gjt.mm.mysql.Driver url: jdbc:mysql://127.0.0.1:3306/db2019?useUnicode=true&characterEncoding=utf-8&useSSL=false username: root password: 123456</code></pre><h2 id="业务类"><a href="#业务类" class="headerlink" title="业务类"></a>业务类</h2><pre><code>@Configurationpublic class ApplicationContextConfig { /** * //appLicationcontext.xml <bean id=""class=""> * * 使用@LoapBalanced注解赋于RestTemplate负载均衡的能力 */ @Bean @LoadBalanced public RestTemplate getRestTemplate() { return new RestTemplate(); }}</code></pre><pre><code>@RestController@Slf4jpublic class OrderZKController { private static final String INVOKE_URL = "http://cloud-provider-payment"; @Resource private RestTemplate restTemplate; @GetMapping(value = "/consumer/payment/zk") public String paymentInfo(){ String result = restTemplate.getForObject(INVOKE_URL + "/payment/zk", String.class); return result; }}</code></pre><h2 id="zookeeper查看"><a href="#zookeeper查看" class="headerlink" title="zookeeper查看"></a>zookeeper查看</h2><pre><code>[zk: localhost:2181(CONNECTED) 4] ls /services[cloud-provider-payment, cloud-consumer-order]</code></pre><p>启动后访问<a href="http://127.0.0.1/consumer/payment/zk" target="_blank" rel="noopener">http://127.0.0.1/consumer/payment/zk</a></p>]]></content>
<categories>
<category> JAVA </category>
</categories>
<tags>
<tag> SpringCloud </tag>
</tags>
</entry>
<entry>
<title>[Cloud]3-集成Eureka</title>
<link href="/2020/03/20/Cloud-3-%E9%9B%86%E6%88%90Eureka/"/>
<url>/2020/03/20/Cloud-3-%E9%9B%86%E6%88%90Eureka/</url>
<content type="html"><![CDATA[<h1 id="EurekaServer服务端安装"><a href="#EurekaServer服务端安装" class="headerlink" title="EurekaServer服务端安装"></a>EurekaServer服务端安装</h1><p>新建一个EurekaServer服务,名称:cloud-eureka-server7001 </p><h2 id="主要依赖"><a href="#主要依赖" class="headerlink" title="主要依赖"></a>主要依赖</h2><pre><code><dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency></code></pre><h2 id="application-yml"><a href="#application-yml" class="headerlink" title="application.yml"></a>application.yml</h2><pre><code>server: port: 7001eureka: instance: hostname: localhost #eureka服务端的实例名称 client: register-with-eureka: false #false表示不向注册中心注册自己 fetch-registry: false #false表示自己端就是注册中心 #false表示自己端魔是注册中心,我的钢责就是维护服务实,并不需要去检索服务 service-url: #设置与Eureka Server交互的地址查询服务和注般服务部需要依藏这个她址。 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka</code></pre><h2 id="主启动类"><a href="#主启动类" class="headerlink" title="主启动类"></a>主启动类</h2><pre><code>package xyz.zx21.springcloud;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;/** * @author Administrator * @date 2020/3/20 13:56 */@SpringBootApplication@EnableEurekaServerpublic class EurekaMain7001 { public static void main(String[] args) { SpringApplication.run(EurekaMain7001.class, args); }}</code></pre><h1 id="cloud-provider-payment8001入驻Eureka"><a href="#cloud-provider-payment8001入驻Eureka" class="headerlink" title="cloud-provider-payment8001入驻Eureka"></a>cloud-provider-payment8001入驻Eureka</h1><h2 id="修改pom"><a href="#修改pom" class="headerlink" title="修改pom"></a>修改pom</h2><p>新增依赖</p><pre><code><!-- 引入eureka客户端 --><dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency></code></pre><h2 id="启动类添加注解"><a href="#启动类添加注解" class="headerlink" title="启动类添加注解"></a>启动类添加注解</h2><p><code>@EnableEurekaClient</code></p><h2 id="修改application-yml"><a href="#修改application-yml" class="headerlink" title="修改application.yml"></a>修改application.yml</h2><p>新增</p><pre><code>eureka: client: register-with-eureka: true #是否将自己注册到注册中心,集群必须设置为true配合ribbon fetch-registry: true #是否从服务端抓取已有的注册信息 #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡 service-url: defaultZone: http://localhost:7001/eureka</code></pre><hr><h1 id="cloud-comsumer-order80入驻Euraka"><a href="#cloud-comsumer-order80入驻Euraka" class="headerlink" title="cloud-comsumer-order80入驻Euraka"></a>cloud-comsumer-order80入驻Euraka</h1><p><strong>与上面的同理,添加依赖,改yml和主启动类</strong></p><p>application.yml</p><pre><code>server: port: 80spring: application: name: cloud-order-serviceeureka: client: register-with-eureka: true #是否将自己注册到注册中心,集群必须设置为true配合ribbon fetch-registry: true #是否从服务端抓取已有的注册信息 #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡 service-url: defaultZone: http://localhost:7001/eureka</code></pre><hr><h1 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h1><p>分别启动eureka和80与8001服务,访问<a href="http://localhost:7001/" target="_blank" rel="noopener">http://localhost:7001/</a></p><p>结果如下已经注册进来了</p><pre><code>Application AMIs Availability Zones StatusCLOUD-ORDER-SERVICE n/a (1) (1) UP (1) - DESKTOP-T08AAHT:cloud-order-service:80CLOUD-PAYMENT-SERVICE n/a (1) (1) UP (1) - DESKTOP-T08AAHT:cloud-payment-service:8001</code></pre><hr><h1 id="Eureka集群原理说明"><a href="#Eureka集群原理说明" class="headerlink" title="Eureka集群原理说明"></a>Eureka集群原理说明</h1><p><strong>互相注册,相互守望</strong></p><pre><code>1 先启动eureka注册中心2 启动服务提供者payment支付服务3 支付服务启动后会把自身信息(比如服务地址以别名方式注册进eureka)4 消费者order服务在需要调用接口时,使用服务别名去注册中心获取实际的RPC远程调用地址5 消费者获得调用地址后,底层实际是利用HttpClient技术实现远程调用6 消费者获得服务地址后会统存在本地jvm内存中,默认每间隔30秒更新一次服务调用地址</code></pre><hr><h1 id="Eureka集群环境构建"><a href="#Eureka集群环境构建" class="headerlink" title="Eureka集群环境构建"></a>Eureka集群环境构建</h1><h2 id="新建cloud-eureka-server7002"><a href="#新建cloud-eureka-server7002" class="headerlink" title="新建cloud-eureka-server7002"></a>新建cloud-eureka-server7002</h2><h2 id="修改hosts文件"><a href="#修改hosts文件" class="headerlink" title="修改hosts文件"></a>修改hosts文件</h2><pre><code>127.0.0.1 eureka7001.com127.0.0.1 eureka7002.com</code></pre><p>EurekaServer7001 的yml</p><pre><code>server: port: 7001eureka: instance:# hostname: localhost #eureka服务端的实例名称 hostname: eureka7001.com #eureka服务端的实例名称 client: register-with-eureka: false #false表示不向注册中心注册自己 fetch-registry: false #false表示自己端就是注册中心 #false表示自己端魔是注册中心,我的钢责就是维护服务实,并不需要去检索服务 service-url: #设置与Eureka Server交互的地址查询服务和注册服务部需要依赖这个她址。# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka #单例 defaultZone: http://eureka7002.com:7002/eureka/</code></pre><p>EurekaServer7002 的yml</p><pre><code>server: port: 7002eureka: instance:# hostname: localhost #eureka服务端的实例名称 hostname: eureka7002.com #eureka服务端的实例名称 client: register-with-eureka: false #false表示不向注册中心注册自己 fetch-registry: false #false表示自己端就是注册中心 #false表示自己端魔是注册中心,我的钢责就是维护服务实,并不需要去检索服务 service-url: #设置与Eureka Server交互的地址查询服务和注册服务部需要依赖这个她址。# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka #单例 defaultZone: http://eureka7001.com:7001/eureka/</code></pre><h2 id="测试-1"><a href="#测试-1" class="headerlink" title="测试"></a>测试</h2><p>访问<a href="http://eureka7001.com:7001/" target="_blank" rel="noopener">http://eureka7001.com:7001/</a> 和 <a href="http://eureka7002.com:7002/" target="_blank" rel="noopener">http://eureka7002.com:7002/</a></p><p>能看到7001指向7002,7002指向7001即可。</p><pre><code>DS Replicaseureka7001.com</code></pre><hr><h1 id="其他服务注册到Eureka集群"><a href="#其他服务注册到Eureka集群" class="headerlink" title="其他服务注册到Eureka集群"></a>其他服务注册到Eureka集群</h1><h2 id="修改yml即可"><a href="#修改yml即可" class="headerlink" title="修改yml即可"></a>修改yml即可</h2><pre><code>eureka: client: register-with-eureka: true #是否将自己注册到注册中心,集群必须设置为true配合ribbon fetch-registry: true #是否从服务端抓取已有的注册信息 #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡 service-url: #defaultZone: http://localhost:7001/eureka defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/ #集群版</code></pre><h2 id="测试-2"><a href="#测试-2" class="headerlink" title="测试"></a>测试</h2><h3 id="启动步骤"><a href="#启动步骤" class="headerlink" title="启动步骤"></a>启动步骤</h3><pre><code>1 先要启动EurekaServer,7001/7002服务2 再要启动服务提供者provider,80013 再要启动消费者,804 http://localhost/consumer/payment/get/1</code></pre><hr><h1 id="支付微服务集群配置"><a href="#支付微服务集群配置" class="headerlink" title="支付微服务集群配置"></a>支付微服务集群配置</h1><h2 id="新建cloud-provider-payment8002"><a href="#新建cloud-provider-payment8002" class="headerlink" title="新建cloud-provider-payment8002"></a>新建cloud-provider-payment8002</h2><p>copycloud-provider-payment8001的代码即可,修改端口。</p><p><strong>为了区分方便,修改controller,用于显示端口</strong></p><pre><code>@RestController@Slf4jpublic class PaymentController { @Resource private PaymentService paymentService; @Value("${server.port}") private String serverPort; @PostMapping(value = "/payment/create") public CommonResult create(@RequestBody Payment payment) { int result = paymentService.create(payment); log.info("插入结果:" + result); if (result > 0) { return new CommonResult(200, "插入成功,serverPort: " + serverPort, result); } else { return new CommonResult(444, "插入失败", null); } } @GetMapping(value = "/payment/get/{id}") public CommonResult getPaymentById(@PathVariable("id") Long id) { Payment paymentById = paymentService.getPaymentById(id); log.info("查询结果:" + paymentById); if (paymentById != null) { return new CommonResult(200, "查询成功,serverPort: "+ serverPort, paymentById); } else { return new CommonResult(444, "没有对应记录,查询id:" + id, null); } }}</code></pre><hr><h1 id="cloud-comsumer-order80修改"><a href="#cloud-comsumer-order80修改" class="headerlink" title="cloud-comsumer-order80修改"></a>cloud-comsumer-order80修改</h1><pre><code>@RestController@Slf4jpublic class OrderController {// public static final String PAYMENT_URL = "http://localhost:8001"; public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE"; @Resource private RestTemplate restTemplate; @GetMapping("/consumer/payment/create") public CommonResult<Payment> create(Payment payment) { return restTemplate.postForObject(PAYMENT_URL + "/payment/create", payment, CommonResult.class); } @GetMapping("/consumer/payment/get/{id}") public CommonResult<Payment> getPayment(@PathVariable("id") Long id) { return restTemplate.getForObject(PAYMENT_URL + "/payment/get/" + id, CommonResult.class); }}</code></pre><h2 id="添加-LoadBalanced"><a href="#添加-LoadBalanced" class="headerlink" title="添加@LoadBalanced"></a>添加@LoadBalanced</h2><pre><code>@Configurationpublic class ApplicationContextConfig { /** * //appLicationcontext.xml <bean id=""class=""> * * 使用@LoapBalanced注解赋于RestTemplate负载均衡的能力 */ @Bean @LoadBalanced public RestTemplate getRestTemplate() { return new RestTemplate(); }}</code></pre><hr><h2 id="actuator信息完善"><a href="#actuator信息完善" class="headerlink" title="actuator信息完善"></a>actuator信息完善</h2><h2 id="服务名称修改"><a href="#服务名称修改" class="headerlink" title="服务名称修改"></a>服务名称修改</h2><pre><code> instance: instance-id: payment8001</code></pre><h2 id="ip信息显示"><a href="#ip信息显示" class="headerlink" title="ip信息显示"></a>ip信息显示</h2><pre><code> instance: instance-id: payment8001 prefer-ip-address: true #访问路径可以显示IP地址</code></pre><hr><h1 id="服务发现Discovery"><a href="#服务发现Discovery" class="headerlink" title="服务发现Discovery"></a>服务发现Discovery</h1><p><strong>对于注册进eureka里面的微服务,可以通过服务发现来获得该服务的信息</strong></p><h2 id="修改cloud-provider-payment8001"><a href="#修改cloud-provider-payment8001" class="headerlink" title="修改cloud-provider-payment8001"></a>修改cloud-provider-payment8001</h2><h3 id="controller"><a href="#controller" class="headerlink" title="controller"></a>controller</h3><pre><code> @RestController@Slf4jpublic class PaymentController { @Resource private PaymentService paymentService; @Resource private DiscoveryClient discoveryClient; @Value("${server.port}") private String serverPort; @PostMapping(value = "/payment/create") public CommonResult create(@RequestBody Payment payment) { int result = paymentService.create(payment); log.info("插入结果:" + result); if (result > 0) { return new CommonResult(200, "插入成功,serverPort: " + serverPort, result); } else { return new CommonResult(444, "插入失败", null); } } @GetMapping(value = "/payment/get/{id}") public CommonResult getPaymentById(@PathVariable("id") Long id) { Payment paymentById = paymentService.getPaymentById(id); log.info("查询结果:" + paymentById); if (paymentById != null) { return new CommonResult(200, "查询成功,serverPort: "+ serverPort, paymentById); } else { return new CommonResult(444, "没有对应记录,查询id:" + id, null); } } @GetMapping(value = "/payment/discovery") public Object discovery(){ List<String> services = discoveryClient.getServices(); for (String element : services) { log.info("****element: " +element); } List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE"); for (ServiceInstance instance:instances) { log.info(instance.getServiceId()+"\t"+instance.getHost()+"\t"+instance.getPort()+"\t"+instance.getUri()); } return this.discoveryClient; }}</code></pre><h3 id="主启动类-1"><a href="#主启动类-1" class="headerlink" title="主启动类"></a>主启动类</h3><p> 新增@EnableDiscoveryClient注解</p><h2 id="测试-3"><a href="#测试-3" class="headerlink" title="测试"></a>测试</h2><p> 访问 <a href="http://localhost:8001/payment/discovery" target="_blank" rel="noopener">http://localhost:8001/payment/discovery</a></p><p> 响应</p><pre><code> { "services": [ "cloud-payment-service" ], "order": 0}</code></pre><p> log日志</p><pre><code>2020-03-20 16:24:03.078 INFO 11660 --- [nio-8001-exec-9] x.z.s.controller.PaymentController : ****element: cloud-payment-service2020-03-20 16:24:03.078 INFO 11660 --- [nio-8001-exec-9] x.z.s.controller.PaymentController : CLOUD-PAYMENT-SERVICE 192.168.8.122 8002 http://192.168.8.122:80022020-03-20 16:24:03.078 INFO 11660 --- [nio-8001-exec-9] x.z.s.controller.PaymentController : CLOUD-PAYMENT-SERVICE 192.168.8.122 8001 http://192.168.8.122:8001</code></pre><hr><h1 id="Eureka自我保护机制"><a href="#Eureka自我保护机制" class="headerlink" title="Eureka自我保护机制"></a>Eureka自我保护机制</h1><h2 id="自我保护机制理论知识"><a href="#自我保护机制理论知识" class="headerlink" title="自我保护机制理论知识"></a>自我保护机制理论知识</h2><p> 自我保护机制:默认情况下EurekaClient定时向EurekaServer端发送心跳包如果Eureka在server端在一定时间内(默认90秒)没有收到EurekaClient发送心跳包,便会直接从服务注册列表中剔除该服务,但是在短时间(90秒中)内丢失了大量的服务实例心跳,这时候EurekaServer会开启自我保护机制,不会剔除该服务(该现象可能出现在如果网络不通但是EurekaClient为出现右机,此时如果换做别的注册中心如果一定时间内没有收到心跳会将剔除该服务,这样就出现了严重失误,因为客户端还能正常发送心就,只是网络延迟问题,而保护机制是为了解决此问题而产生的。</p><h2 id="禁用自我保护机制"><a href="#禁用自我保护机制" class="headerlink" title="禁用自我保护机制"></a>禁用自我保护机制</h2><h3 id="修改EurekaServer"><a href="#修改EurekaServer" class="headerlink" title="修改EurekaServer"></a>修改EurekaServer</h3><p> yml</p><pre><code> eureka: instance:# hostname: localhost #eureka服务端的实例名称 hostname: eureka7001.com #eureka服务端的实例名称 client: register-with-eureka: false #false表示不向注册中心注册自己 fetch-registry: false #false表示自己端就是注册中心 #false表示自己端魔是注册中心,我的钢责就是维护服务实,并不需要去检索服务 service-url: #设置与Eureka Server交互的地址查询服务和注册服务部需要依赖这个她址。# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka #单例 #defaultZone: http://eureka7002.com:7002/eureka/ defaultZone: http://eureka7001.com:7001/eureka/ #单机 server: enable-self-preservation: false #禁用自我保护模式,保证不可用服务被及时剔除 eviction-interval-timer-in-ms: 2000 #2秒</code></pre><h3 id="修改Client"><a href="#修改Client" class="headerlink" title="修改Client"></a>修改Client</h3><p> yml</p><pre><code>eureka: client: register-with-eureka: true #是否将自己注册到注册中心,集群必须设置为true配合ribbon fetch-registry: true #是否从服务端抓取已有的注册信息 #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡 service-url: defaultZone: http://localhost:7001/eureka #defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/ #集群版 instance: instance-id: payment8001 prefer-ip-address: true #访问路径可以显示IP地址 lease-renewal-interval-in-seconds: 1 #向服务端发送心跳的时间间隔,单位为秒(默认是30秒) lease-expiration-duration-in-seconds: 2 #收到最后一次心跳后等待时间上限,单位为秒(默认是90秒),超时将剔除</code></pre><h3 id="现象"><a href="#现象" class="headerlink" title="现象"></a>现象</h3><p> 当关闭8001服务时,eureka会很快删除</p>]]></content>
<categories>
<category> JAVA </category>
</categories>
<tags>
<tag> SpringCloud </tag>
</tags>
</entry>
<entry>
<title>[Cloud]2-支付模块与工程重构</title>
<link href="/2020/03/19/Cloud-2-%E6%94%AF%E4%BB%98%E6%A8%A1%E5%9D%97%E4%B8%8E%E5%B7%A5%E7%A8%8B%E9%87%8D%E6%9E%84/"/>
<url>/2020/03/19/Cloud-2-%E6%94%AF%E4%BB%98%E6%A8%A1%E5%9D%97%E4%B8%8E%E5%B7%A5%E7%A8%8B%E9%87%8D%E6%9E%84/</url>
<content type="html"><![CDATA[<p><strong>创建消费者模块cloud-comsumer-order80调用上篇文章的支付模块cloud-provider-payment8001。</strong></p><h1 id="构建步骤"><a href="#构建步骤" class="headerlink" title="构建步骤"></a>构建步骤</h1><pre><code>1、建module2、改pom3、写yml4、主启动5、业务类</code></pre><h1 id="编码"><a href="#编码" class="headerlink" title="编码"></a>编码</h1><h2 id="application-yml"><a href="#application-yml" class="headerlink" title="application.yml"></a>application.yml</h2><pre><code>server: port: 80</code></pre><h2 id="主启动类"><a href="#主启动类" class="headerlink" title="主启动类"></a>主启动类</h2><pre><code>package xyz.zx21.springcloud;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;/** * @author Administrator * @date 2020/3/19 15:53 */@SpringBootApplicationpublic class OrderMain80 { public static void main(String[] args) { SpringApplication.run(OrderMain80.class, args); }}</code></pre><h2 id="业务类"><a href="#业务类" class="headerlink" title="业务类"></a>业务类</h2><p><strong>注入RestTemplate,文档地址</strong>:<a href="https://docs.spring.io/spring-framework/docs/5.2.2.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html" target="_blank" rel="noopener">点击访问</a></p><pre><code>package xyz.zx21.springcloud.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.client.RestTemplate;/** * @author Administrator * @date 2020/3/19 16:39 */@Configurationpublic class ApplicationContextConfig { /** * //appLicationcontext.xml <bean id=""class=""> * */ @Bean public RestTemplate getRestTemplate() { return new RestTemplate(); }}</code></pre><h2 id="controller"><a href="#controller" class="headerlink" title="controller"></a>controller</h2><pre><code>package xyz.zx21.springcloud.controller;import lombok.extern.slf4j.Slf4j;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.client.RestTemplate;import xyz.zx21.springcloud.entities.CommonResult;import xyz.zx21.springcloud.entities.Payment;import javax.annotation.Resource;/** * @author Administrator * @date 2020/3/19 16:37 */@RestController@Slf4jpublic class OrderController { public static final String PAYMENT_URL = "http://localhost:8001"; @Resource private RestTemplate restTemplate; @GetMapping("/consumer/payment/create") public CommonResult<Payment> create(Payment payment) { return restTemplate.postForObject(PAYMENT_URL + "/payment/create", payment, CommonResult.class); } @GetMapping("/consumer/payment/get/{id}") public CommonResult<Payment> getPayment(@PathVariable("id") Long id) { return restTemplate.getForObject(PAYMENT_URL + "/payment/get/" + id, CommonResult.class); }}</code></pre><h1 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h1><p>启动PaymentMain8001和OrderMain80,测试OrderMain80调用PaymentMain8001服务。</p><hr><h1 id="工程重构"><a href="#工程重构" class="headerlink" title="工程重构"></a>工程重构</h1><p><strong>将多余的代码,单独放到一个模块,提供给各个服务,避免冗余,比如实体类</strong></p><h2 id="新建cloud-api-commons模块"><a href="#新建cloud-api-commons模块" class="headerlink" title="新建cloud-api-commons模块"></a>新建cloud-api-commons模块</h2><p>pom.xml</p><pre><code><?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>cloud2020</artifactId> <groupId>xyz.zx21.springcloud</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>cloud-api-commons</artifactId> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <!-- 当optional为true则说明该依赖禁止依赖传递 <optional>true</optional>--> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.1.1</version> </dependency> </dependencies></project></code></pre><h2 id="将其他服务的实体类拷贝"><a href="#将其他服务的实体类拷贝" class="headerlink" title="将其他服务的实体类拷贝"></a>将其他服务的实体类拷贝</h2><h2 id="maven-clean-install-安装"><a href="#maven-clean-install-安装" class="headerlink" title="maven clean install 安装"></a>maven clean install 安装</h2><h2 id="删除其他模块下的实体包"><a href="#删除其他模块下的实体包" class="headerlink" title="删除其他模块下的实体包"></a>删除其他模块下的实体包</h2><h2 id="新增依赖"><a href="#新增依赖" class="headerlink" title="新增依赖"></a>新增依赖</h2><pre><code><dependency> <artifactId>cloud-api-commons</artifactId> <groupId>xyz.zx21.springcloud</groupId> <version>1.0-SNAPSHOT</version></dependency></code></pre><hr><h1 id="TIPS"><a href="#TIPS" class="headerlink" title="TIPS"></a>TIPS</h1><p>关于调用/consumer/payment/create接口,插入数据为null的情况,需要在cloud-provider-payment8001服务对应的controller添加@RequestBody注解</p><pre><code>@PostMapping(value = "/payment/create")public CommonResult create(@RequestBody Payment payment) {...}</code></pre>]]></content>
<categories>
<category> JAVA </category>
</categories>
<tags>
<tag> SpringCloud </tag>
</tags>
</entry>
<entry>
<title>[Cloud]1-父工程创建与支付模块构建</title>
<link href="/2020/03/19/Cloud-1-%E7%88%B6%E5%B7%A5%E7%A8%8B%E5%88%9B%E5%BB%BA%E4%B8%8E%E6%94%AF%E4%BB%98%E6%A8%A1%E5%9D%97%E6%9E%84%E5%BB%BA/"/>
<url>/2020/03/19/Cloud-1-%E7%88%B6%E5%B7%A5%E7%A8%8B%E5%88%9B%E5%BB%BA%E4%B8%8E%E6%94%AF%E4%BB%98%E6%A8%A1%E5%9D%97%E6%9E%84%E5%BB%BA/</url>
<content type="html"><![CDATA[<p><strong>约定 > 配置 > 编码</strong></p><hr><h1 id="工程步骤"><a href="#工程步骤" class="headerlink" title="工程步骤"></a>工程步骤</h1><pre><code>1、New Project2、聚合总父工程名字3、Maven选版本4、工程名字5、字符编码-UTF-86、注解生效激活7、java编译版本选择88、File Type过滤(可选)</code></pre><h1 id="项目创建"><a href="#项目创建" class="headerlink" title="项目创建"></a>项目创建</h1><h2 id="idea创建project工作空间"><a href="#idea创建project工作空间" class="headerlink" title="idea创建project工作空间"></a>idea创建project工作空间</h2><p>新建一个maven工程,工程名:cloud2020,删除src目录,只留下pom。<br>修改pom.xml</p><pre><code><packaging>pom</packaging></code></pre><p>完整的pom</p><pre><code><?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>xyz.zx21.springcloud</groupId> <artifactId>cloud2020</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <junit.version>4.12</junit.version> <log4j.version>1.2.17</log4j.version> <lombok.version>1.16.18</lombok.version> <mysql.version>5.1.47</mysql.version> <druid.version>1.1.16</druid.version> <mybatis.spring.boot.version>1.3.2</mybatis.spring.boot.version> </properties> <!-- 子模块继承之后,提供作用:锁定版本+子模块不用写groupId和version --> <dependencyManagement> <dependencies> <!-- springboot 2.2.2 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.2.2.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <!-- springcloud cloud Hoxton.SR1 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR1</version> <type>pom</type> <scope>import</scope> </dependency> <!-- springcloud cloud alibaba 2.1.0.RELEASE --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.1.0.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>${druid.version}</version> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>${mybatis.spring.boot.version}</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> <optional>true</optional> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <fork>true</fork> <addResources>true</addResources> </configuration> </plugin> </plugins> </build></project></code></pre><hr><h1 id="本章模块"><a href="#本章模块" class="headerlink" title="本章模块"></a>本章模块</h1><p>order(客户端消费者80) -> payment(微服务提供者8001)</p><hr><h2 id="构建步骤"><a href="#构建步骤" class="headerlink" title="构建步骤"></a>构建步骤</h2><pre><code>1、建module2、改pom3、写yml4、主启动5、业务类</code></pre><h3 id="创建-cloud-provider-payment8001-模块"><a href="#创建-cloud-provider-payment8001-模块" class="headerlink" title="创建 cloud-provider-payment8001 模块"></a>创建 cloud-provider-payment8001 模块</h3><p>pom.xml</p><pre><code><?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>cloud2020</artifactId> <groupId>xyz.zx21.springcloud</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>cloud-provider-payment8001</artifactId> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.10</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies></project></code></pre><h2 id="application-yml"><a href="#application-yml" class="headerlink" title="application.yml"></a>application.yml</h2><pre><code>server: port: 8001spring: application: name: cloud-payment-service datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: org.gjt.mm.mysql.Driver url: jdbc:mysql://127.0.0.1:3306/db2019?useUnicode=true&characterEncoding=utf-8&useSSL=false username: root password: 123456mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.com.springcloud.entities</code></pre><h2 id="建数据库"><a href="#建数据库" class="headerlink" title="建数据库"></a>建数据库</h2><p>db2019<br>sql如下</p><pre><code>CREATE TABLE `payment` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID', `serial` varchar(200) DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;</code></pre><hr><h1 id="编码"><a href="#编码" class="headerlink" title="编码"></a>编码</h1><p>实体类Payment</p><pre><code>package xyz.zx21.springcloud.entities;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import java.io.Serializable;/** * @author Administrator * @date 2020/3/19 14:20 */@Data@AllArgsConstructor@NoArgsConstructorpublic class Payment implements Serializable { private Long id; private String serial;}</code></pre><h2 id="数据封装体CommonResult"><a href="#数据封装体CommonResult" class="headerlink" title="数据封装体CommonResult"></a>数据封装体CommonResult</h2><p>用于给前端返回统一格式的数据</p><pre><code>package xyz.zx21.springcloud.entities;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;/** * @author Administrator * @date 2020/3/19 14:24 */@Data@AllArgsConstructor@NoArgsConstructorpublic class CommonResult<T> { private Integer code; private String message; private T data; public CommonResult(Integer code, String message) { this(code, message, null); }}</code></pre><h2 id="contorller"><a href="#contorller" class="headerlink" title="contorller"></a>contorller</h2><pre><code>package xyz.zx21.springcloud.controller;import lombok.extern.slf4j.Slf4j;import org.springframework.web.bind.annotation.*;import xyz.zx21.springcloud.entities.CommonResult;import xyz.zx21.springcloud.entities.Payment;import xyz.zx21.springcloud.service.PaymentService;import javax.annotation.Resource;/** * @author Administrator * @date 2020/3/19 14:28 */@RestController@Slf4jpublic class PaymentController { @Resource private PaymentService paymentService; @PostMapping(value = "/payment/create") public CommonResult create(Payment payment) { int result = paymentService.create(payment); log.info("插入结果:" + result); if (result > 0) { return new CommonResult(200, "插入成功", result); } else { return new CommonResult(444, "插入失败", null); } } @GetMapping(value = "/payment/get/{id}") public CommonResult getPaymentById(@PathVariable("id") Long id) { Payment paymentById = paymentService.getPaymentById(id); log.info("查询结果:" + paymentById); if (paymentById != null) { return new CommonResult(200, "查询成功", paymentById); } else { return new CommonResult(444, "没有对应记录,查询id:" + id, null); } }}</code></pre><h2 id="service"><a href="#service" class="headerlink" title="service"></a>service</h2><pre><code>package xyz.zx21.springcloud.service;import xyz.zx21.springcloud.entities.Payment;/** * @author Administrator * @date 2020/3/19 14:32 */public interface PaymentService { int create(Payment payment); Payment getPaymentById(Long id);}</code></pre><h2 id="impl"><a href="#impl" class="headerlink" title="impl"></a>impl</h2><pre><code>package xyz.zx21.springcloud.service.impl;import org.springframework.stereotype.Service;import xyz.zx21.springcloud.dao.PaymentDao;import xyz.zx21.springcloud.entities.Payment;import xyz.zx21.springcloud.service.PaymentService;import javax.annotation.Resource;/** * @author Administrator * @date 2020/3/19 14:33 */@Servicepublic class PaymentServiceImpl implements PaymentService { @Resource private PaymentDao paymentDao; @Override public int create(Payment payment) { return paymentDao.create(payment); } @Override public Payment getPaymentById(Long id) { return paymentDao.getPaymentById(id); }}</code></pre><h2 id="dao"><a href="#dao" class="headerlink" title="dao"></a>dao</h2><pre><code>package xyz.zx21.springcloud.dao;import org.apache.ibatis.annotations.Mapper;import org.apache.ibatis.annotations.Param;import xyz.zx21.springcloud.entities.Payment;/** * @author Administrator * @date 2020/3/19 14:34 */@Mapperpublic interface PaymentDao { int create(Payment payment); Payment getPaymentById(@Param("id") Long id);}</code></pre><h2 id="dao映射的xml"><a href="#dao映射的xml" class="headerlink" title="dao映射的xml"></a>dao映射的xml</h2><p>在resources下新建mapper文件夹<br>PaymentMapper.xml</p><pre><code><?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="xyz.zx21.springcloud.dao.PaymentDao"> <insert id="create" parameterType="xyz.zx21.springcloud.entities.Payment" useGeneratedKeys="true" keyProperty="id"> insert into payment(serial) values(#{serial}); </insert> <resultMap id="BaseResultMap" type="xyz.zx21.springcloud.entities.Payment"> <id column="id" property="id" jdbcType="BIGINT"></id> <id column="serial" property="serial" jdbcType="VARCHAR"></id> </resultMap> <select id="getPaymentById" parameterType="java.lang.Long" resultMap="BaseResultMap"> select * from payment where id = #{id}; </select></mapper></code></pre><hr><h1 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h1><h2 id="postman接口测试"><a href="#postman接口测试" class="headerlink" title="postman接口测试"></a>postman接口测试</h2><p>get<br>url:<a href="http://127.0.0.1:8001/payment/get/1" target="_blank" rel="noopener">http://127.0.0.1:8001/payment/get/1</a></p><p>返回:</p><pre><code>{ "code": 200, "message": "查询成功", "data": { "id": 1, "serial": "小信" }}</code></pre><p>post<br>url:<a href="http://127.0.0.1:8001/payment/create?serial=测试" target="_blank" rel="noopener">http://127.0.0.1:8001/payment/create?serial=测试</a></p><p>返回:</p><pre><code>{ "code": 200, "message": "插入成功", "data": 1}</code></pre>]]></content>
<categories>
<category> JAVA </category>
</categories>
<tags>
<tag> SpringCloud </tag>
</tags>
</entry>
<entry>
<title>[JAVA]easyexcel导出</title>
<link href="/2020/02/26/JAVA-easyexcel%E5%AF%BC%E5%87%BA/"/>
<url>/2020/02/26/JAVA-easyexcel%E5%AF%BC%E5%87%BA/</url>
<content type="html"><![CDATA[<p>阿里的表格工具,简单了解了一下。</p><h2 id="依赖"><a href="#依赖" class="headerlink" title="依赖"></a>依赖</h2><pre><code><dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.1.2</version></dependency></code></pre><hr><h2 id="新增一个实体类"><a href="#新增一个实体类" class="headerlink" title="新增一个实体类"></a>新增一个实体类</h2><pre><code>@Data@ContentRowHeight()@HeadRowHeight()@ColumnWidth()public class Student { @ExcelProperty("学生姓名") private String name; @ExcelProperty("学生年龄") private int age; @ExcelProperty(value = "性别") private String sex; @DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒") @ExcelProperty(value = "日期",index = 5) private Date date;}</code></pre><p><strong>解释:</strong></p><p>@Data:lombok的注解,可以省略@get/@set等等。</p><p>@ContentRowHeight()/@HeadRowHeight()/@ColumnWidth():可修改列宽、行高。</p><p>@ExcelProperty:定义列名称或者index位置,默认0开始。</p><p>@DateTimeFormat:日期转换</p><hr><h2 id="ExcelTest-java"><a href="#ExcelTest-java" class="headerlink" title="ExcelTest.java"></a>ExcelTest.java</h2><pre><code>@RunWith(SpringRunner.class)@SpringBootTestpublic class ExcelTest { /** * 最简单的导出 */ @Test public void simpleWrite01() throws IOException { // 写法1 String fileName = (new File("").getCanonicalPath()) + "/simpleWrite" + System.currentTimeMillis() + ".xlsx"; // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 // 如果这里想使用03 则 传入excelType参数即可 EasyExcel.write(fileName, Student.class).sheet("模板").doWrite(getData()); // 写法2/* fileName = (new File("").getCanonicalPath()) + "/simpleWrite" + System.currentTimeMillis() + ".xlsx"; // 这里 需要指定写用哪个class去写 ExcelWriter excelWriter = EasyExcel.write(fileName, Student.class).build(); WriteSheet writeSheet = EasyExcel.writerSheet("模板").build(); excelWriter.write(getData(), writeSheet); // 千万别忘记finish 会帮忙关闭流 excelWriter.finish();*/ } /** * 指定列名导出 */ @Test public void simpleWrite02() throws IOException { String fileName = (new File("").getCanonicalPath()) + "/simpleWrite" + System.currentTimeMillis() + ".xlsx"; // 根据用户传入字段 假设我们要忽略 date Set<String> columnFiledNames = new HashSet<String>(); columnFiledNames.add("age"); columnFiledNames.add("sex"); //1、需要忽略的列名// EasyExcel.write(fileName, Student.class).excludeColumnFiledNames(columnFiledNames).sheet("模板").doWrite(getData()); //2、需要保留的列名 EasyExcel.write(fileName, Student.class).includeColumnFiledNames(columnFiledNames).sheet("模板").doWrite(getData()); } private List<Student> getData() { List<Student> list = new ArrayList<>(); for (int i = 0; i < 10; i++) { Student student = new Student(); student.setName("小信" + i); student.setAge(22); student.setSex("男"); student.setDate(new Date()); list.add(student); } return list; }}</code></pre><hr><h2 id="web下载导出"><a href="#web下载导出" class="headerlink" title="web下载导出"></a>web下载导出</h2><pre><code>@RestControllerpublic class WebExcelTest { /** * web中写入 */ @GetMapping("get") public void getExcel(HttpServletResponse response) { try { response.setContentType("application/vnd.ms-excel"); response.setCharacterEncoding("utf-8"); response.setHeader("Content-disposition", "attachment;filename=" + System.currentTimeMillis() + ".xlsx"); // 这里需要设置不关闭流 EasyExcel.write(response.getOutputStream(), Student.class).autoCloseStream(Boolean.FALSE).sheet("模板") .doWrite(getData()); } catch (IOException e) { e.printStackTrace(); } } private List<Student> getData() { List<Student> list = new ArrayList<>(); for (int i = 0; i < 10; i++) { Student student = new Student(); student.setName("小信" + i); student.setAge(22); student.setSex("男"); student.setDate(new Date()); list.add(student); } return list; }</code></pre><hr><p><strong>官方文档:<a href="https://alibaba-easyexcel.github.io/quickstart/write.html" target="_blank" rel="noopener">点击</a></strong></p>]]></content>
<categories>
<category> JAVA </category>
</categories>
<tags>
<tag> java </tag>
</tags>
</entry>
<entry>
<title>[JAVA]抓取淘宝商品信息</title>
<link href="/2020/02/24/JAVA-%E6%8A%93%E5%8F%96%E6%B7%98%E5%AE%9D%E5%95%86%E5%93%81%E4%BF%A1%E6%81%AF/"/>
<url>/2020/02/24/JAVA-%E6%8A%93%E5%8F%96%E6%B7%98%E5%AE%9D%E5%95%86%E5%93%81%E4%BF%A1%E6%81%AF/</url>
<content type="html"><![CDATA[<p>空闲时间写了一个抓取淘宝商品信息的小demo。</p><p>技术:java提供数据,thymeleaf渲染页面,可以一键下载所有图片保存到本地。</p><p><strong>频繁访问的话,淘宝加了限制。</strong></p><p>GitHub:<a href="https://github.com/1579886070/taobaoImage" target="_blank" rel="noopener">点击</a></p>]]></content>
<categories>
<category> JAVA </category>
</categories>
<tags>
<tag> java </tag>
</tags>
</entry>
<entry>
<title>[Other]进制转换</title>
<link href="/2020/02/15/Other-%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2/"/>
<url>/2020/02/15/Other-%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2/</url>
<content type="html"><![CDATA[<h2 id="进制转换"><a href="#进制转换" class="headerlink" title="进制转换"></a>进制转换</h2><h3 id="十进制转二进制"><a href="#十进制转二进制" class="headerlink" title="十进制转二进制"></a>十进制转二进制</h3><p><strong>公式:除二取余,讲要转换的数除以二,计算出商和余数,得到的商不为0时继续除二。最后将余数倒着排序即可</strong><br><img src="http://image.xiaoxinyes.club/2020021501%E5%8D%81%E8%BF%9B%E5%88%B6%E8%BD%AC%E4%BA%8C%E8%BF%9B%E5%88%B6.png" alt="十进制转二进制"></p><hr><h3 id="二进制转十进制"><a href="#二进制转十进制" class="headerlink" title="二进制转十进制"></a>二进制转十进制</h3><p><strong>将二进制从右至左的每个数乘以2的相应次方。</strong></p><p>例如:101转十进制</p><p>1乘2的0次方+0乘2的2次方+1乘2的3次方=5</p><hr><h3 id="二进制与八进制互换"><a href="#二进制与八进制互换" class="headerlink" title="二进制与八进制互换"></a>二进制与八进制互换</h3><p><strong>将二进制从右向左每三位分成一组,然后每段的三位数对应八进制的一位(八进制以0开头)</strong></p><p> <strong>二进制与八进制数值对应表</strong> </p><table><thead><tr><th align="left">二进制</th><th align="left">八进制</th></tr></thead><tbody><tr><td align="left">000</td><td align="left">0</td></tr><tr><td align="left">001</td><td align="left">1</td></tr><tr><td align="left">010</td><td align="left">2</td></tr><tr><td align="left">011</td><td align="left">3</td></tr><tr><td align="left">100</td><td align="left">4</td></tr><tr><td align="left">101</td><td align="left">5</td></tr><tr><td align="left">110</td><td align="left">6</td></tr><tr><td align="left">111</td><td align="left">7</td></tr></tbody></table><hr><h3 id="二进制与十六进制互换"><a href="#二进制与十六进制互换" class="headerlink" title="二进制与十六进制互换"></a>二进制与十六进制互换</h3><p><strong>将二进制从右向左每四位分成一组,然后每段的四位数对应十六进制的一位(十六进制以0x或者0X开头)</strong></p><p> <strong>二进制与八进制数值对应表</strong> </p><table><thead><tr><th align="left">二进制</th><th align="left">八进制</th><th></th><th align="left">二进制</th><th align="left">八进制</th></tr></thead><tbody><tr><td align="left">0000</td><td align="left">0</td><td></td><td align="left">1000</td><td align="left">8</td></tr><tr><td align="left">0001</td><td align="left">1</td><td></td><td align="left">1001</td><td align="left">9</td></tr><tr><td align="left">0010</td><td align="left">2</td><td></td><td align="left">1010</td><td align="left">A</td></tr><tr><td align="left">0011</td><td align="left">3</td><td></td><td align="left">1011</td><td align="left">B</td></tr><tr><td align="left">0100</td><td align="left">4</td><td></td><td align="left">1100</td><td align="left">C</td></tr><tr><td align="left">0101</td><td align="left">5</td><td></td><td align="left">1101</td><td align="left">D</td></tr><tr><td align="left">0110</td><td align="left">6</td><td></td><td align="left">1110</td><td align="left">E</td></tr><tr><td align="left">0111</td><td align="left">7</td><td></td><td align="left">1111</td><td align="left">F</td></tr></tbody></table>]]></content>
<categories>
<category> Other </category>
</categories>
<tags>
<tag> other </tag>
</tags>
</entry>
<entry>
<title>[JAVA]小知识之反斜杠</title>
<link href="/2020/02/14/JAVA-%E5%B0%8F%E7%9F%A5%E8%AF%86%E4%B9%8B%E5%8F%8D%E6%96%9C%E6%9D%A0/"/>
<url>/2020/02/14/JAVA-%E5%B0%8F%E7%9F%A5%E8%AF%86%E4%B9%8B%E5%8F%8D%E6%96%9C%E6%9D%A0/</url>
<content type="html"><![CDATA[<h2 id="解释"><a href="#解释" class="headerlink" title="解释"></a>解释</h2><p>在java中,反斜杠(\)是一个特殊的字符,作用为转义。</p><hr><h2 id="说明"><a href="#说明" class="headerlink" title="说明"></a>说明</h2><table><thead><tr><th align="left">字符</th><th align="left">解释</th></tr></thead><tbody><tr><td align="left">常见的转义字符</td><td align="left"></td></tr><tr><td align="left">\r</td><td align="left">表示回车符号,光标在当前行的开头</td></tr><tr><td align="left">\n</td><td align="left">表示换行符号,到下一行的开头</td></tr><tr><td align="left">\t</td><td align="left">表示制表符号,同tab</td></tr><tr><td align="left">\b</td><td align="left">表示退格符号</td></tr><tr><td align="left">含有特殊意义的转义字符</td><td align="left"></td></tr><tr><td align="left">\‘</td><td align="left">表示单引号</td></tr><tr><td align="left">\“</td><td align="left">表示双引号</td></tr><tr><td align="left">\\</td><td align="left">表示字面意思上的\</td></tr></tbody></table>]]></content>
<categories>
<category> JAVA </category>
</categories>
<tags>
<tag> java </tag>
</tags>
</entry>
<entry>
<title>[Angular]搜索持久化</title>
<link href="/2020/02/13/Angular-%E6%90%9C%E7%B4%A2%E6%8C%81%E4%B9%85%E5%8C%96/"/>
<url>/2020/02/13/Angular-%E6%90%9C%E7%B4%A2%E6%8C%81%E4%B9%85%E5%8C%96/</url>
<content type="html"><![CDATA[<p>类似与淘宝/京东等,搜索关键字,保留搜索历史记录。</p><h2 id="新建search组件"><a href="#新建search组件" class="headerlink" title="新建search组件"></a>新建search组件</h2><pre><code>ng g component components/search</code></pre><h2 id="新建服务"><a href="#新建服务" class="headerlink" title="新建服务"></a>新建服务</h2><p>可以用于公用,我理解为java中的类一样。</p><pre><code>ng g service services/storage</code></pre><h2 id="编写页面"><a href="#编写页面" class="headerlink" title="编写页面"></a>编写页面</h2><p>search.component.html</p><pre><code><div class="search"> <input type="text" [(ngModel)]="keyWord"><button (click)="doSearch()">搜索</button> <hr> 搜索记录 <hr> <ul> <li *ngFor="let item of historyList;let key=index;"> {{item}}--- <button (click)="deleteSearch(key)">X</button> </li> </ul></div></code></pre><p>search.component.css</p><pre><code>.search { width: 400px; margin: 20px auto;}button { height: 32px; width: 80px;}input { margin-bottom: 20px; width: 300px; height: 30px;}ul { list-style-type: none;}</code></pre><h2 id="根模块引入服务"><a href="#根模块引入服务" class="headerlink" title="根模块引入服务"></a>根模块引入服务</h2><pre><code>import { BrowserModule } from '@angular/platform-browser';import { NgModule } from '@angular/core';//引入表单相关模块import { FormsModule } from '@angular/forms';import { AppRoutingModule } from './app-routing.module';import { AppComponent } from './app.component';import { FormComponent } from './components/form/form.component';import { SearchComponent } from './components/search/search.component';//引入服务import { StorageService } from './services/storage.service';@NgModule({ declarations: [ AppComponent, FormComponent, SearchComponent ], imports: [ BrowserModule, AppRoutingModule, FormsModule ], //引入服务 providers: [StorageService], bootstrap: [AppComponent]})export class AppModule { }</code></pre><h2 id="服务模块中的方法"><a href="#服务模块中的方法" class="headerlink" title="服务模块中的方法"></a>服务模块中的方法</h2><p>storage.service.ts</p><pre><code>import { Injectable } from '@angular/core';@Injectable({ providedIn: 'root'})export class StorageService { constructor() { } set(key:string,value:any){ localStorage.setItem(key,JSON.stringify(value)); } get(key:string) { return JSON.parse(localStorage.getItem(key)); } remove(key:string){ localStorage.removeItem(key); }}</code></pre><h2 id="search组件中调用"><a href="#search组件中调用" class="headerlink" title="search组件中调用"></a>search组件中调用</h2><ul><li>注意同样需要引入服务才可以使用</li></ul><pre><code>import { Component, OnInit } from '@angular/core';//引入服务import { StorageService } from '../../services/storage.service';@Component({ selector: 'app-search', templateUrl: './search.component.html', styleUrls: ['./search.component.css']})export class SearchComponent implements OnInit { public keyWord: string; public historyList: any[] = []; //构造函数注入服务 constructor(public storage: StorageService) { } ngOnInit() { //刷新页面持久化 var historyList: any = this.storage.get('historyList'); if (historyList) { this.historyList = this.storage.get('historyList'); } } doSearch() { //避免重复数据 if (this.historyList.indexOf(this.keyWord) == -1) { this.historyList.push(this.keyWord); this.storage.set('historyList', this.historyList); } this.keyWord = ''; } deleteSearch(key: number) { this.historyList.splice(key, 1); this.storage.set('historyList', this.historyList); }}</code></pre>]]></content>
<categories>
<category> Web </category>
</categories>
<tags>
<tag> Angular </tag>
</tags>
</entry>
<entry>
<title>[Angular]表单及双向数据绑定</title>
<link href="/2020/02/12/Angular-%E8%A1%A8%E5%8D%95%E5%8F%8A%E5%8F%8C%E5%90%91%E6%95%B0%E6%8D%AE%E7%BB%91%E5%AE%9A/"/>
<url>/2020/02/12/Angular-%E8%A1%A8%E5%8D%95%E5%8F%8A%E5%8F%8C%E5%90%91%E6%95%B0%E6%8D%AE%E7%BB%91%E5%AE%9A/</url>
<content type="html"><![CDATA[<h2 id="引入表单相关模块"><a href="#引入表单相关模块" class="headerlink" title="引入表单相关模块"></a>引入表单相关模块</h2><p>引入表单相关模块,才可以使用双向数据绑定。</p><p>app.module.ts</p><pre><code>//引入表单相关模块import { FormsModule } from '@angular/forms';</code></pre><h2 id="新建一个form组件"><a href="#新建一个form组件" class="headerlink" title="新建一个form组件"></a>新建一个form组件</h2><pre><code>ng g component components/form</code></pre><h2 id="编写页面"><a href="#编写页面" class="headerlink" title="编写页面"></a>编写页面</h2><p>form.component.html</p><pre><code><h2>表单演示</h2><div class="form"> <ul> <li> 姓名:<input type="text" [(ngModel)]="formInfo.inputValue" /> </li> <li> 性别: <input type="radio" value="1" name="sex" id="sex1" [(ngModel)]="formInfo.sex"><label for="sex1"> 男</label> <input type="radio" value="2" name="sex" id="sex2" [(ngModel)]="formInfo.sex"><label for="sex2"> 女</label> </li> <li> 城市: <select [(ngModel)]="formInfo.defaultCity"> <option *ngFor="let item of formInfo.city" [value]="item">{{item}}</option> </select> </li> <li> 爱好: <span *ngFor="let item of formInfo.hobby;let key=index;"> <input type="checkbox" [id]="'check'+key" [(ngModel)]="item.cheked"/><label [for]="'check'+key"> {{item.title}}</label> </span> </li> <li> <textarea name="mark" id="" cols="30" rows="10" [(ngModel)]="formInfo.mark"></textarea> </li> </ul> <button (click)="dosubmit()">获取内容</button> <br /> <pre> {{formInfo|json}} </pre></div></code></pre><h2 id="css样式"><a href="#css样式" class="headerlink" title="css样式"></a>css样式</h2><p>form.component.css</p><pre><code>h2{ text-align: center;}.form{ width: 400px; margin: auto; border: 2px solid #000;}button{ width: 100px; float: right;}ul{ list-style-type: none;}li{ line-height: 50px;}</code></pre><h2 id="模块代码"><a href="#模块代码" class="headerlink" title="模块代码"></a>模块代码</h2><p>form.component.ts</p><pre><code>import { Component, OnInit } from '@angular/core';@Component({ selector: 'app-form', templateUrl: './form.component.html', styleUrls: ['./form.component.css']})export class FormComponent implements OnInit { public citys: any[] = ['长沙', '杭州', '苏州']; public formInfo: any = { inputValue: '', sex: '1', city: this.citys, defaultCity:this.citys[0], hobby:[{ title:'画画', cheked:false },{ title:'弹吉他', cheked:false },{ title:'运动', cheked:false },], mark:'' } constructor() { } ngOnInit() { } dosubmit() { console.log(this.formInfo); }}</code></pre>]]></content>
<categories>
<category> Web </category>
</categories>
<tags>
<tag> Angular </tag>
</tags>
</entry>
<entry>
<title>[Angular]常用组件与使用</title>
<link href="/2020/02/05/Angular-%E5%B8%B8%E7%94%A8%E7%BB%84%E4%BB%B6%E4%B8%8E%E4%BD%BF%E7%94%A8/"/>
<url>/2020/02/05/Angular-%E5%B8%B8%E7%94%A8%E7%BB%84%E4%BB%B6%E4%B8%8E%E4%BD%BF%E7%94%A8/</url>
<content type="html"><![CDATA[<p>记录一下笔记</p><p>html代码放在xxx.component.html中</p><p>组件代码放在xxx.component.ts中</p><p>css放在xxx.component.css中</p><hr><h2 id="angular绑定数据"><a href="#angular绑定数据" class="headerlink" title="angular绑定数据"></a>angular绑定数据</h2><pre><code><h1>angular模板绑定数据</h1><h3>{{title}}</h3><h3>{{msg}}</h3><h3>{{username}}</h3><h3>{{userage}}</h3><h3>{{userinfo.age}}</h3><h3>{{message}}</h3></code></pre><pre><code> public title='我是一个新闻组件'; msg='我是一个新闻组件的msg'; public username:string = "我是一个姓名"; public userage:any=111; public userinfo:object={ age:11 } public message:string = '这是消息';</code></pre><hr><h2 id="angular绑定属性"><a href="#angular绑定属性" class="headerlink" title="angular绑定属性"></a>angular绑定属性</h2><pre><code><h1>angular模板绑定属性</h1><div title="我是一个属性"> 鼠标瞄上去看一下</div><div [title]="msg"> 鼠标再瞄上去看一下</div></code></pre><pre><code>public msg='我是一个属性';</code></pre><hr><h2 id="angular绑定html"><a href="#angular绑定html" class="headerlink" title="angular绑定html"></a>angular绑定html</h2><pre><code><h1>angular模板绑定html</h1><div> {{content}}</div><br><span [innerHTML]='content' class="red"></span></code></pre><pre><code> public content:string="<h2>我是一个html标签</h2>"</code></pre><pre><code>.red{ color:red;}</code></pre><hr><h2 id="angular做简单的运算、"><a href="#angular做简单的运算、" class="headerlink" title="angular做简单的运算、"></a>angular做简单的运算、</h2><pre><code><h1>angular做简单的运算</h1><h3>1+2={{1+2}}</h3></code></pre><hr><h2 id="angular数据循环"><a href="#angular数据循环" class="headerlink" title="angular数据循环"></a>angular数据循环</h2><pre><code><ul> <li *ngFor="let item of arr"> {{item}} </li></ul><ol> <li *ngFor="let item of list"> {{item}} </li></ol><ul> <li *ngFor="let item of userlist"> {{item.username}}---{{item.userage}} </li></ul><ul> <li *ngFor="let item of cars"> <h3>{{item.brand}}</h3> <ol> <li *ngFor="let car of item.list"> {{car.title}}---{{car.price}} </li> </ol> </li></ul></code></pre><pre><code>//循环 public arr=['abc','123','哈哈']; public list:any=['zxc','321','嘻嘻']; public lists:Array<string>=['qwe','456','呵呵']; public userlist=[{ username:'张三', userage:20 },{ username:'李四', userage:22 },{ username:'王五', userage:25 }]; public cars:any[]=[ { brand:'宝马', list:[ { title:'宝马01', price:'30万' }, { title:'宝马02', price:'40万' } ] }, { brand:'奔驰', list:[ { title:'奔驰01', price:'30万' }, { title:'奔驰02', price:'40万' } ] }]</code></pre><hr><h2 id="angular引入图片"><a href="#angular引入图片" class="headerlink" title="angular引入图片"></a>angular引入图片</h2><pre><code><h1>angular引入图片</h1><img src="assets/images/100.jpg" alt="图片"><br><img [src]="picUrl"></code></pre><pre><code> public picUrl: string = "https://www.baidu.com/img/pc_1c6e30772d5e4103103bd460913332f9.png";</code></pre><hr><h2 id="angular显示数组索引"><a href="#angular显示数组索引" class="headerlink" title="angular显示数组索引"></a>angular显示数组索引</h2><pre><code><h1>angular显示数组索引</h1><ul> <li *ngFor="let item of arr;let key=index" [ngClass]="{'red': key==0,'orange':key==2}"> {{item.name}}---{{key}} </li></ul></code></pre><pre><code> public arr: any[] = [{ name: '张三', }, { name: '王五', }, { name: '赵六' }]</code></pre><hr><h2 id="angular条件判断"><a href="#angular条件判断" class="headerlink" title="angular条件判断"></a>angular条件判断</h2><pre><code><div *ngIf="flag"> 输出true</div><div *ngIf="!flag"> 输出false</div><div *ngIf="false;else other"> 输出false</div><ng-template #other>other content...</ng-template><div [ngSwitch]="404"> <div *ngSwitchCase="200">成功</div> <div *ngSwitchCase="404">找不到</div> <div *ngSwitchCase="500">内部服务错误</div> <div *ngSwitchDefault>其他错误</div></div></code></pre><pre><code> public flag: boolean = true;</code></pre><hr><h2 id="angular-ngStyle"><a href="#angular-ngStyle" class="headerlink" title="angular-ngStyle"></a>angular-ngStyle</h2><pre><code><h1>angular-ngStyle</h1><p style="color: red;">我是一个标签</p><p [ngStyle]="{color: 'blue'}">我也是一个标签</p></code></pre><hr><h2 id="angular-管道"><a href="#angular-管道" class="headerlink" title="angular-管道"></a>angular-管道</h2><pre><code><h1>angular-管道</h1>{{today|date:'yyyy-MM-dd HH:mm:ss'}}</code></pre><pre><code>public today: any = new Date();</code></pre><hr><h2 id="angular-点击事件"><a href="#angular-点击事件" class="headerlink" title="angular-点击事件"></a>angular-点击事件</h2><pre><code><h1>angular-点击事件</h1><button (click)="run()">点击</button></code></pre><pre><code> run(){ alert("触发点击事件") }</code></pre><hr><h2 id="angular-表单事件"><a href="#angular-表单事件" class="headerlink" title="angular-表单事件"></a>angular-表单事件</h2><pre><code><h1>angular-表单事件</h1><input type="text" (keyup)="keyup($event)"/></code></pre><pre><code> keyup(e){ if(e.keyCode==13){ console.log("按了一下回车"); }else{ //e.target 获取dom对象 console.log(e.target.value); } }</code></pre>]]></content>
<categories>
<category> Web </category>
</categories>
<tags>
<tag> Angular </tag>
</tags>
</entry>
<entry>
<title>[Angular]入门之运行项目</title>
<link href="/2020/02/04/Angular-%E5%85%A5%E9%97%A8%E4%B9%8B%E8%BF%90%E8%A1%8C%E9%A1%B9%E7%9B%AE/"/>
<url>/2020/02/04/Angular-%E5%85%A5%E9%97%A8%E4%B9%8B%E8%BF%90%E8%A1%8C%E9%A1%B9%E7%9B%AE/</url>
<content type="html"><![CDATA[<h2 id="1、安装node-js"><a href="#1、安装node-js" class="headerlink" title="1、安装node.js"></a>1、安装node.js</h2><h2 id="2、安装cnpm"><a href="#2、安装cnpm" class="headerlink" title="2、安装cnpm"></a>2、安装cnpm</h2><pre><code>npm install -g cnpm --registry=https://registry.npm.taobao.org</code></pre><h2 id="3、安装angular"><a href="#3、安装angular" class="headerlink" title="3、安装angular"></a>3、安装angular</h2><pre><code>cnpm install -g @angular/cli</code></pre><h3 id="查看是否安装成功"><a href="#查看是否安装成功" class="headerlink" title="查看是否安装成功"></a>查看是否安装成功</h3><pre><code>C:\Users\Administrator>ng v _ _ ____ _ ___ / \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _| / △ \ | '_ \ / _` | | | | |/ _` | '__| | | | | | | / ___ \| | | | (_| | |_| | | (_| | | | |___| |___ | | /_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___| |___/Angular CLI: 8.3.24Node: 10.16.3OS: win32 x64Angular:...Package Version------------------------------------------------------@angular-devkit/architect 0.803.24@angular-devkit/core 8.3.24@angular-devkit/schematics 8.3.24@schematics/angular 8.3.24@schematics/update 0.803.24rxjs 6.5.4</code></pre><h2 id="4、创建安装angular项目"><a href="#4、创建安装angular项目" class="headerlink" title="4、创建安装angular项目"></a>4、创建安装angular项目</h2><p>打开命令提示符窗口</p><pre><code>ng new demo</code></pre><h2 id="5、运行项目"><a href="#5、运行项目" class="headerlink" title="5、运行项目"></a>5、运行项目</h2><p>进入到文件夹下</p><pre><code>cd demo</code></pre><p>运行</p><pre><code>ng serve --open</code></pre><h2 id="6、访问"><a href="#6、访问" class="headerlink" title="6、访问"></a>6、访问</h2><p> <a href="http://localhost:4200/" target="_blank" rel="noopener">http://localhost:4200/</a></p><hr><h2 id="跳过npm安装"><a href="#跳过npm安装" class="headerlink" title="跳过npm安装"></a>跳过npm安装</h2><pre><code>ng new demo2 --skip-install</code></pre><pre><code>cnpm install</code></pre>]]></content>
<categories>
<category> Web </category>
</categories>
<tags>
<tag> Angular </tag>
</tags>
</entry>
<entry>
<title>[JAVA]逻辑分页与物理分页</title>
<link href="/2020/01/05/JAVA-%E9%80%BB%E8%BE%91%E5%88%86%E9%A1%B5%E4%B8%8E%E7%89%A9%E7%90%86%E5%88%86%E9%A1%B5/"/>
<url>/2020/01/05/JAVA-%E9%80%BB%E8%BE%91%E5%88%86%E9%A1%B5%E4%B8%8E%E7%89%A9%E7%90%86%E5%88%86%E9%A1%B5/</url>
<content type="html"><![CDATA[<p>code:mybatis+springboot</p><h2 id="解释"><a href="#解释" class="headerlink" title="解释"></a>解释</h2><h3 id="逻辑分页"><a href="#逻辑分页" class="headerlink" title="逻辑分页"></a>逻辑分页</h3><p><strong>逻辑分页并不是返回分页结果,而是直接返回全部数据,再通过代码获取分页数据。</strong></p><h3 id="物理分页"><a href="#物理分页" class="headerlink" title="物理分页"></a>物理分页</h3><p><strong>使用mysql的limit关键字,直接返回分页结果。</strong></p><hr><h2 id="编码"><a href="#编码" class="headerlink" title="编码"></a>编码</h2><h3 id="sql"><a href="#sql" class="headerlink" title="sql"></a>sql</h3><pre><code>SET NAMES utf8mb4;SET FOREIGN_KEY_CHECKS = 0;-- ------------------------------ Table structure for student-- ----------------------------DROP TABLE IF EXISTS `student`;CREATE TABLE `student` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;-- ------------------------------ Records of student-- ----------------------------INSERT INTO `student` VALUES (1, '测试1', 11);INSERT INTO `student` VALUES (2, '测试2', 22);INSERT INTO `student` VALUES (3, '测试3', 14);INSERT INTO `student` VALUES (4, '测试4', 16);INSERT INTO `student` VALUES (5, '测试5', 32);INSERT INTO `student` VALUES (6, '测试6', 23);SET FOREIGN_KEY_CHECKS = 1;</code></pre><h3 id="对应的实体类"><a href="#对应的实体类" class="headerlink" title="对应的实体类"></a>对应的实体类</h3><pre><code>public class Student { //构造 private int id; private String name; private int age; //get set}</code></pre><h3 id="pom-xml"><a href="#pom-xml" class="headerlink" title="pom.xml"></a>pom.xml</h3><pre><code><?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.2.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>mybatis</artifactId> <version>0.0.1-SNAPSHOT</version> <name>mybatis</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <!--注意:如果xml文件不放到resources下,那么需要配置以下代码,不然target下找不到--> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.*</include> </includes> <filtering>true</filtering> </resource> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> <include>**/*.yml</include> <include>**/*.properties</include> </includes> </resource> </resources> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project></code></pre><h3 id="application-properties"><a href="#application-properties" class="headerlink" title="application.properties"></a>application.properties</h3><pre><code>#jdbc驱动spring.datasource.driverClassName = com.mysql.cj.jdbc.Driverspring.datasource.url = jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghaispring.datasource.username = ****spring.datasource.password = ****#mybatis#xml地址mybatis.mapper-locations=classpath:com/example/mybatis/dao/mapping/**.xml#控制台打印sqlmybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl</code></pre><h2 id="结构"><a href="#结构" class="headerlink" title="结构"></a>结构</h2><blockquote><p>Controller –> service –> dao –>xml</p></blockquote><h3 id="controller"><a href="#controller" class="headerlink" title="controller"></a>controller</h3><pre><code>@RestControllerpublic class StudentController { @Autowired private SutndentServiceImpl studentService; /** * 物理分页 */ @GetMapping("physical-paging") public Object getList1(@RequestParam(value = "start", required = false, defaultValue = "1") int start, @RequestParam(value = "limit", required = false, defaultValue = "3") int limit) { List<Student> list = studentService.physicalPaging(start, limit); return list; } /** * 逻辑分页 */ @GetMapping("logical-paging") public Object getList2(@RequestParam(value = "start", required = false, defaultValue = "1") int start, @RequestParam(value = "limit", required = false, defaultValue = "3") int limit) { List<Student> list = studentService.logicalPaging(start, limit); return list; }}</code></pre><h3 id="service-实现类"><a href="#service-实现类" class="headerlink" title="service+实现类"></a>service+实现类</h3><pre><code>public interface StudentService { /** * 物理分页 * * @param start 起始页 * @param limit 每页条数 * @return */ List<Student> physicalPaging(int start, int limit); /** * 逻辑分页 * * @param start * @param limit * @return */ List<Student> logicalPaging(int start, int limit);}</code></pre><p>注意:实现类的@Service</p><pre><code>@Servicepublic class SutndentServiceImpl implements StudentService { @Autowired private StudentDao studentDao; @Override public List<Student> physicalPaging(int start, int limit) { //这里是分页的关键 if (start < 1) { start = 1; } else { start = (start - 1) * limit; } List<Student> list = studentDao.getList(start, limit); return list; } @Override public List<Student> logicalPaging(int start, int limit) { if (start < 1) { start = 1; } List<Student> list = studentDao.getAllList(); if((start-1)*limit > list.size()){ return Collections.emptyList(); } return list.subList((start - 1) * limit, ((start * limit) > list.size() ? list.size() : (start * limit))); }}</code></pre><h3 id="dao"><a href="#dao" class="headerlink" title="dao"></a>dao</h3><p>注意:类上的@Mapper,文件多时可选择启动类上设置@MapperScan,这样不需要每个mapper加注解。</p><pre><code>@Mapperpublic interface StudentDao { /** * 注意:1、有@Mapper注解 2、一个以上的参数需要加@param * * @param start 起始页 * @param limit 每页多少条 * @return */ List<Student> getList(@Param("start") int start, @Param("limit") int limit); /** * 获取全部数据 * * @return */ List<Student> getAllList();}</code></pre><h3 id="XML映射文件"><a href="#XML映射文件" class="headerlink" title="XML映射文件"></a>XML映射文件</h3><pre><code><?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.example.mybatis.dao.StudentDao"> <!-- 通用查询映射结果 --> <resultMap id="BaseResultMap" type="com.example.mybatis.baen.Student"> <id column="id" property="id"/> <result column="name" property="name"/> <result column="age" property="age"/> </resultMap> <!-- 通用查询结果列 --> <sql id="Base_Column_List"> id, name, age </sql> <select id="getList" resultType="com.example.mybatis.baen.Student"> select <include refid="Base_Column_List"/> from student limit #{start},#{limit} </select> <select id="getAllList" resultType="com.example.mybatis.baen.Student"> select <include refid="Base_Column_List"/> from student </select></mapper></code></pre><h2 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h2><h3 id="逻辑分页接口测试"><a href="#逻辑分页接口测试" class="headerlink" title="逻辑分页接口测试"></a>逻辑分页接口测试</h3><pre><code>http://127.0.0.1:8080/logical-paging?start=1&limit=2---[ { "id": 1, "name": "测试1", "age": 11 }, { "id": 2, "name": "测试2", "age": 22 }]</code></pre><h3 id="物理分页接口测试"><a href="#物理分页接口测试" class="headerlink" title="物理分页接口测试"></a>物理分页接口测试</h3><pre><code>http://127.0.0.1:8080/physical-paging?start=1&limit=2---[ { "id": 1, "name": "测试1", "age": 11 }, { "id": 2, "name": "测试2", "age": 22 }]</code></pre>]]></content>
<categories>
<category> JAVA </category>
</categories>
<tags>
<tag> mybatis </tag>
</tags>
</entry>
<entry>
<title>[JAVA]记一次内存溢出</title>
<link href="/2019/12/21/JAVA-%E8%AE%B0%E4%B8%80%E6%AC%A1%E5%86%85%E5%AD%98%E6%BA%A2%E5%87%BA/"/>
<url>/2019/12/21/JAVA-%E8%AE%B0%E4%B8%80%E6%AC%A1%E5%86%85%E5%AD%98%E6%BA%A2%E5%87%BA/</url>
<content type="html"><![CDATA[<p>项目部署到服务器后,第二天发现异常,记录下排查过程。</p><h2 id="异常发现"><a href="#异常发现" class="headerlink" title="异常发现"></a>异常发现</h2><p>带有权限的账号,突然ssh连接不上服务器了,项目也出现访问不了的情况。后面尝试用root账号,意外的可以登录上。</p><pre><code>topjps</code></pre><p>发现CPU没啥明显的异常,项目进程也没有挂。于是进入项目,查看日志,发现日志中存在异常。</p><pre><code>2019-12-15 11:36:58.200 default [nioEventLoopGroup-4-2] ERROR o.r.client.handler.CommandsQueue - Exception occured. Channel: [id: 0x2f80895c, L:/172.16.149.12:60435 - R:172.16.149.13/172.16.149.13:6379]java.lang.OutOfMemoryError: unable to create new native thread at java.lang.Thread.start0(Native Method) at java.lang.Thread.start(Thread.java:717) at io.netty.util.concurrent.ThreadPerTaskExecutor.execute(ThreadPerTaskExecutor.java:33) at io.netty.util.internal.ThreadExecutorMap$1.execute(ThreadExecutorMap.java:57) at io.netty.util.concurrent.SingleThreadEventExecutor.doStartThread(SingleThreadEventExecutor.java:895) at io.netty.util.concurrent.SingleThreadEventExecutor.startThread(SingleThreadEventExecutor.java:866) at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:759) at io.netty.util.concurrent.AbstractScheduledEventExecutor.schedule(AbstractScheduledEventExecutor.java:232) at io.netty.util.concurrent.AbstractScheduledEventExecutor.schedule(AbstractScheduledEventExecutor.java:155) at io.netty.util.concurrent.AbstractEventExecutorGroup.schedule(AbstractEventExecutorGroup.java:50) at org.redisson.client.RedisConnection.async(RedisConnection.java:205) at org.redisson.client.RedisConnection.async(RedisConnection.java:191) at org.redisson.client.RedisConnection.async(RedisConnection.java:183) at org.redisson.client.handler.BaseConnectionHandler.channelActive(BaseConnectionHandler.java:68)</code></pre><p><strong>竟然内存溢出了</strong>,开始了一段分析过程。</p><hr><p>报错为无法创建线程<code>unable to create new native thread</code>。使用命令查看下是否有问题。</p><pre><code>pstree -a //查看所有进程相关的线程pstree -p PID|wc -l //查看指定进程的线程数</code></pre><p>发现一个项目竟然创建了接近3000线程。能大致推出这是代码有问题,线程未释放导致溢出,但是为什么服务器有权限的账号在发生异常时登录不上了,而root可以呢?</p><h3 id="账号登录不上解决方法"><a href="#账号登录不上解决方法" class="headerlink" title="账号登录不上解决方法"></a>账号登录不上解决方法</h3><p>把服务kill之后,发现用权限的账户可以登录了,原因在于最初时用该账户执行的项目,那么也就是说跟权限配置有关了。用ulimit -a查看下,发现max user processes只有<strong>4096</strong>,这样一算的话启动那些java服务加起来创建的线程数正好就超过这个数了,提高该配置之后,未发现之前出现的权限用户登录不上的情况。</p><pre><code>ulimit -a---core file size (blocks, -c) unlimiteddata seg size (kbytes, -d) unlimitedscheduling priority (-e) 0file size (blocks, -f) unlimitedpending signals (-i) 63459max locked memory (kbytes, -l) 32000max memory size (kbytes, -m) unlimitedopen files (-n) 1000000pipe size (512 bytes, -p) 8POSIX message queues (bytes, -q) 8192000real-time priority (-r) 0stack size (kbytes, -s) 8192cpu time (seconds, -t) unlimitedmax user processes (-u) 4096virtual memory (kbytes, -v) unlimitedfile locks (-x) unlimited</code></pre><hr><h3 id="堆栈分析"><a href="#堆栈分析" class="headerlink" title="堆栈分析"></a>堆栈分析</h3><p>为了排查错误,项目开着,发现线程一直在慢慢累加,最终到了10000多,不再继续,但也没有释放。linux中<strong>jstack</strong>分析下线程堆栈情况。</p><pre><code>jstack -l PID > jstack.log</code></pre><p>日志</p><pre><code>Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.212-b10 mixed mode):"nioEventLoopGroup-1240-13" #13017 prio=10 os_prio=0 tid=0x00007f1278f46000 nid=0x374 runnable [0x00007f1264b4a000] java.lang.Thread.State: RUNNABLE at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method) at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269) at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93) at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86) - locked <0x0000000768f9f6d8> (a io.netty.channel.nio.SelectedSelectionKeySet) - locked <0x0000000768f9f6c8> (a java.util.Collections$UnmodifiableSet) - locked <0x0000000768f9f6f0> (a sun.nio.ch.EPollSelectorImpl) at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97) at io.netty.channel.nio.SelectedSelectionKeySetSelector.select(SelectedSelectionKeySetSelector.java:62) at io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:791) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:439) at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:906) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.lang.Thread.run(Thread.java:748) Locked ownable synchronizers: - None"nioEventLoopGroup-1240-16" #13016 prio=10 os_prio=0 tid=0x00007f15700d4800 nid=0x373 runnable [0x00007f1264c4b000] java.lang.Thread.State: RUNNABLE at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method) at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269) at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93) at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86) - locked <0x0000000768fa15e8> (a io.netty.channel.nio.SelectedSelectionKeySet) - locked <0x0000000768fa15d8> (a java.util.Collections$UnmodifiableSet) - locked <0x0000000768fa1600> (a sun.nio.ch.EPollSelectorImpl) at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97) at io.netty.channel.nio.SelectedSelectionKeySetSelector.select(SelectedSelectionKeySetSelector.java:62) at io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:791) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:439) at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:906) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.lang.Thread.run(Thread.java:748) Locked ownable synchronizers: - None"nioEventLoopGroup-1240-14" #13015 prio=10 os_prio=0 tid=0x00007f1578006800 nid=0x362 runnable [0x00007f1264d4c000] java.lang.Thread.State: RUNNABLE at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method) at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269) at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93) at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86) - locked <0x0000000768f9d840> (a io.netty.channel.nio.SelectedSelectionKeySet) - locked <0x0000000768f9d830> (a java.util.Collections$UnmodifiableSet) - locked <0x0000000768f9d858> (a sun.nio.ch.EPollSelectorImpl) at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97) at io.netty.channel.nio.SelectedSelectionKeySetSelector.select(SelectedSelectionKeySetSelector.java:62) at io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:791) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:439) at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:906) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.lang.Thread.run(Thread.java:748) Locked ownable synchronizers: - None</code></pre><p>以上,能看到nioEventLoopGroup一直处于运行状态,为了更加直观的查看,我本地运行,使用jdk自带的jvm分析工具(在jdk安装目录,bin目录下的jvisualvm.exe),,发现随着时间的推移,nioEventLoopGroup创建数量越来越多。<br><img src="http://image.xiaoxinyes.club/2019122101.png" alt></p><h3 id="代码追踪"><a href="#代码追踪" class="headerlink" title="代码追踪"></a>代码追踪</h3><p>查询代码后,发现有个定时任务中循环创建了redisson,而每次创建琐时都会new NioEventLoopGroup();正是因为这个每次创建后一直处于执行中,JVM垃圾回收并不会处理,所以溢出了。</p><h3 id="解决"><a href="#解决" class="headerlink" title="解决"></a>解决</h3><p>我的处理方法<br>1、初始化之创建一个线程池。</p><pre><code>private static NioEventLoopGroup nioEventLoopGroup;private static NioEventLoopGroup getNioEventLoopGroup() { if (nioEventLoopGroup == null) { nioEventLoopGroup = new NioEventLoopGroup(); } return nioEventLoopGroup; }</code></pre><p>2、或者释放</p><pre><code>nioEventLoopGroup.shutdownGracefully();</code></pre>]]></content>
<categories>
<category> JAVA </category>
</categories>
<tags>
<tag> java </tag>
</tags>
</entry>
<entry>
<title>[ERROR]关于下划线引发的错误</title>
<link href="/2019/12/20/ERROR-%E5%85%B3%E4%BA%8E%E4%B8%8B%E5%88%92%E7%BA%BF%E5%BC%95%E5%8F%91%E7%9A%84%E9%94%99%E8%AF%AF/"/>
<url>/2019/12/20/ERROR-%E5%85%B3%E4%BA%8E%E4%B8%8B%E5%88%92%E7%BA%BF%E5%BC%95%E5%8F%91%E7%9A%84%E9%94%99%E8%AF%AF/</url>
<content type="html"><![CDATA[<p>记录一次关于使用下划线出现的问题。前后端通信,自定义一些请求头参数,但是在调用过程中发现了异常。</p><pre><code>requet.getHeader("XXX_XXX");</code></pre><p>发现后端接收到的参数为空,而其他所有参数都可以获取到,唯独这个不行。联调之后,我们试着修改参数名称,改成XXX-XXX,这个时候可以获取到。</p><p>我们是nginx做负载均衡,经过查询一番相关资料,发现请求头中名称包含下划线时,nginx会被标记成无效。而这个也是可以通过nginx配置修改的。</p><pre><code>underscores_in_headers on</code></pre><hr><p>有些东西是规范,因为不规划引起的问题,有时会需要很长时间去寻找处理,就像之前域名解析包含下划线,nginx有些也无法识别。</p>]]></content>
<categories>
<category> ERROR </category>
</categories>
<tags>
<tag> error </tag>
</tags>
</entry>
<entry>
<title>[Other]重装系统后恢复Hexo博客</title>
<link href="/2019/12/20/Other-%E9%87%8D%E8%A3%85%E7%B3%BB%E7%BB%9F%E5%90%8E%E6%81%A2%E5%A4%8DHexo%E5%8D%9A%E5%AE%A2/"/>
<url>/2019/12/20/Other-%E9%87%8D%E8%A3%85%E7%B3%BB%E7%BB%9F%E5%90%8E%E6%81%A2%E5%A4%8DHexo%E5%8D%9A%E5%AE%A2/</url>
<content type="html"><![CDATA[<p>电脑加了个固态,重装了下,所以有些资料需要迁移一下。</p><h2 id="git和nodo安装"><a href="#git和nodo安装" class="headerlink" title="git和nodo安装"></a>git和nodo安装</h2><p>先安装git和nodo.js,git生成密钥添加到自己的git账户</p><hr><h2 id="处理备份的blog文件"><a href="#处理备份的blog文件" class="headerlink" title="处理备份的blog文件"></a>处理备份的blog文件</h2><p>删除不必要的文件,保留如下:<br><img src="http://image.xiaoxinyes.club/201912202.png" alt></p><hr><h2 id="关联"><a href="#关联" class="headerlink" title="关联"></a>关联</h2><pre><code>git initgit remote add origin git@github.com:XXX/XXX.github.io.git</code></pre><p><img src="http://image.xiaoxinyes.club/201912201.png" alt></p><hr><h2 id="安装hexo"><a href="#安装hexo" class="headerlink" title="安装hexo"></a>安装hexo</h2><pre><code>npm install hexo --save</code></pre><h2 id="安装依赖"><a href="#安装依赖" class="headerlink" title="安装依赖"></a>安装依赖</h2><pre><code>npm install </code></pre><h2 id="其他"><a href="#其他" class="headerlink" title="其他"></a>其他</h2><pre><code>hexo ghexo shexo d</code></pre>]]></content>
<categories>
<category> Other </category>
</categories>
<tags>
<tag> github </tag>
</tags>
</entry>
<entry>
<title>[MySql]关于查询的一次异常排查</title>
<link href="/2019/12/05/MySql-%E5%85%B3%E4%BA%8E%E6%9F%A5%E8%AF%A2%E7%9A%84%E4%B8%80%E6%AC%A1%E5%BC%82%E5%B8%B8%E6%8E%92%E6%9F%A5/"/>
<url>/2019/12/05/MySql-%E5%85%B3%E4%BA%8E%E6%9F%A5%E8%AF%A2%E7%9A%84%E4%B8%80%E6%AC%A1%E5%BC%82%E5%B8%B8%E6%8E%92%E6%9F%A5/</url>
<content type="html"><![CDATA[<p>最近因为一个java项目,其中查询一组数据响应十分慢。后面发现对一张表有40万条左右的数据,单表每次查询速度1S以上。事有蹊跷,开始研究!</p><h2 id="数据40万条"><a href="#数据40万条" class="headerlink" title="数据40万条"></a>数据40万条</h2><pre><code>SELECT count(*) FROM `lz_commodity_info`--条数 350000万左右</code></pre><hr><h2 id="一、SQL查询测试"><a href="#一、SQL查询测试" class="headerlink" title="一、SQL查询测试"></a>一、SQL查询测试</h2><h3 id="执行sql查看执行时间"><a href="#执行sql查看执行时间" class="headerlink" title="执行sql查看执行时间"></a>执行sql查看执行时间</h3><pre><code>SELECT * FROM `lz_commodity_info` where commodity_id=544844787596</code></pre><p>** 响应信息如下,发现竟然查询需要1秒以上。虽然不是主键id,但是也不应该这么慢。**</p><pre><code>SELECT * FROM `lz_commodity_info` where commodity_id=544844787596OK时间: 1.13s</code></pre><hr><h3 id="添加索引"><a href="#添加索引" class="headerlink" title="添加索引"></a>添加索引</h3><p>查看没有添加索引,先加个索引看看。</p><pre><code>alter table `lz_commodity_info` add INDEX(commodity_id)</code></pre><h3 id="再次查询"><a href="#再次查询" class="headerlink" title="再次查询"></a>再次查询</h3><p>** 响应信息如下,竟然还是这么慢,事情没我想得那么简单。**</p><pre><code>SELECT * FROM `lz_commodity_info` where commodity_id=544844787596OK时间: 1.107s</code></pre><hr><h3 id="查看sql"><a href="#查看sql" class="headerlink" title="查看sql"></a>查看sql</h3><p>** 而后查看sql发现,定义的类型是varchar。那么尝试修改下sql语句,加上单引号查询试试。**</p><p><code>`commodity_id` varchar(50)</code></p><pre><code>SELECT * FROM `lz_commodity_info` where commodity_id='544844787596'</code></pre><p>** 响应信息如下,发现从蜗牛直接到火箭了,直接起飞,那么导致慢的原因也浮现出来了。 **</p><pre><code>SELECT * FROM `lz_commodity_info` where commodity_id='544844787596'OK时间: 0.002s</code></pre><hr><h2 id="二、疑问开始"><a href="#二、疑问开始" class="headerlink" title="二、疑问开始"></a>二、疑问开始</h2><h3 id="删除索引再测试"><a href="#删除索引再测试" class="headerlink" title="删除索引再测试"></a>删除索引再测试</h3><pre><code>alter table `lz_commodity_info` drop INDEX `commodity_id`</code></pre><h3 id="再次查看速度"><a href="#再次查看速度" class="headerlink" title="再次查看速度"></a>再次查看速度</h3><p>** 发现速度竟然基本差不多,都长达1s以上了 **</p><pre><code>时间: 1.099s------------时间: 1.077s------------</code></pre><hr><h3 id="explain测试"><a href="#explain测试" class="headerlink" title="explain测试"></a>explain测试</h3><p>sql前+explain 查询sql的执行情况。</p><ul><li>1、没加索引<br>不管是加上单引号还是不加。返回如下:</li></ul><p><img src="http://image.xiaoxinyes.club/20191205000538.png" alt="查询结果"></p><hr><ul><li>2、加上索引<br>不加单引号,返回结果跟上面的一样。</li></ul><p>加单引号,可以看到这才走了索引。返回结果如下:<br><img src="http://image.xiaoxinyes.club/20191205001000.png" alt="查询结果"></p><h2 id="三、总结"><a href="#三、总结" class="headerlink" title="三、总结"></a>三、总结</h2><blockquote><p>1、查询时添加索引可以极大的优化查询速度;</p><p>2、定义的是varchar类型的字段,添加索引,查询切记要加上单引号;</p></blockquote>]]></content>
<categories>
<category> Sql </category>
</categories>
<tags>
<tag> mysql </tag>
</tags>
</entry>
<entry>
<title>[JAVA]缓存之ConcurrentMapCacheManager</title>
<link href="/2019/11/27/JAVA-%E7%BC%93%E5%AD%98%E4%B9%8BConcurrentMapCacheManager/"/>
<url>/2019/11/27/JAVA-%E7%BC%93%E5%AD%98%E4%B9%8BConcurrentMapCacheManager/</url>
<content type="html"><![CDATA[<p>我用mybatis+springboot默认的ConcurrentMapCacheManager缓存演示。maven依赖导入mybatis和web相关即可。</p><h2 id="一、配置文件"><a href="#一、配置文件" class="headerlink" title="一、配置文件"></a>一、配置文件</h2><p>这里显示打印sql,是方便查看调用方法时是不是走缓存拿去数据,如果是的则不会打印sql日志。</p><pre><code>spring: datasource: password: 1579886070 username: root driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=falsemybatis: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印sql</code></pre><hr><h2 id="二、sql"><a href="#二、sql" class="headerlink" title="二、sql"></a>二、sql</h2><pre><code>CREATE TABLE `student` ( `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;</code></pre><hr><h2 id="三、service和实现类"><a href="#三、service和实现类" class="headerlink" title="三、service和实现类"></a>三、service和实现类</h2><h3 id="service"><a href="#service" class="headerlink" title="service"></a>service</h3><pre><code>package xyz.zx21.demo.service;import xyz.zx21.demo.vo.Student;import java.util.List;public interface StudentService { Student add(Student student); boolean deleteById(int id); Student selectById(Student student);}</code></pre><h3 id="Impl"><a href="#Impl" class="headerlink" title="Impl"></a>Impl</h3><p><strong>@CachePut:新增或者将更新的数据存到缓存,名称为student,key为student的id。</strong></p><p><strong>@CacheEvic:删除key为id的缓存</strong></p><p><strong>@Cacheable:将student的id作为Key缓存到student中</strong></p><p>没有指定key的话,方法参数作为key存储到缓存中。</p><pre><code>package xyz.zx21.demo.service.impl;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cache.annotation.CacheEvict;import org.springframework.cache.annotation.CachePut;import org.springframework.cache.annotation.Cacheable;import org.springframework.stereotype.Service;import xyz.zx21.demo.mapper.StudentMapper;import xyz.zx21.demo.service.StudentService;import xyz.zx21.demo.vo.Student;import java.util.List;@Servicepublic class StudentServiceImlp implements StudentService { @Autowired private StudentMapper studentMapper; @Override @CachePut(value = "student", key = "#student.id") public Student add(Student student) { if(studentMapper.insertStudent(student)>0){ return student; } return null; } @Override @CacheEvict(value = "student") public boolean deleteById(int id) { return studentMapper.deleteStudent(id); } @Override @Cacheable(value = "student", key = "#student.id") public Student selectById(Student student) { return studentMapper.selectById(student); }}</code></pre><h2 id="四、controller"><a href="#四、controller" class="headerlink" title="四、controller"></a>四、controller</h2><pre><code>package xyz.zx21.demo.controller;import org.apache.ibatis.annotations.Param;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cache.annotation.CacheEvict;import org.springframework.cache.annotation.CachePut;import org.springframework.cache.annotation.Cacheable;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import xyz.zx21.demo.service.StudentService;import xyz.zx21.demo.vo.Student;import xyz.zx21.demo.vo.StudentVO;@RestController@RequestMappingpublic class StudentController { @Autowired private StudentVO studentVO; @Autowired private StudentService studentService; /** * 添加数据 * * @return */ @GetMapping("addStu") public Object insertStudent(Student student) { return studentService.add(student); } /** * 根据id删除数据 * * @param id * @return */ @GetMapping("delete") public Object delete(@Param("id") int id) { return studentService.deleteById(id); } /** * 根据id查找 * * @param student * @return */ @GetMapping("selectOne") public Object selectOne(Student student) { return studentService.selectById(student); }}</code></pre><h2 id="五、启动类"><a href="#五、启动类" class="headerlink" title="五、启动类"></a>五、启动类</h2><p>注意加上@EnableCaching注解,开启缓存支持。</p><pre><code>package xyz.zx21.demo;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cache.annotation.EnableCaching;@SpringBootApplication@EnableCachingpublic class DemoApplication { public static void main(String[] args) { SpringApplication app = new SpringApplication(DemoApplication.class); app.run(args); }}</code></pre><hr><h2 id="演示"><a href="#演示" class="headerlink" title="演示"></a>演示</h2><h3 id="1、添加数据存入缓存"><a href="#1、添加数据存入缓存" class="headerlink" title="1、添加数据存入缓存"></a>1、添加数据存入缓存</h3><p>请求:<br><code>http://127.0.0.1:8080/addStu?id=3&name=小信&age=23</code></p><p>返回:</p><pre><code>{ "id": 3, "name": "小信", "age": 23}</code></pre><p>idea日志:</p><pre><code>JDBC Connection [HikariProxyConnection@1383776946 wrapping com.mysql.jdbc.JDBC4Connection@59329e8b] will not be managed by Spring==> Preparing: insert into student(id,name,age) values (?,?,?) ==> Parameters: 3(Integer), 小信(String), 23(Integer)<== Updates: 1Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@668ffe2e]</code></pre><h3 id="2、根据id去缓存查数据"><a href="#2、根据id去缓存查数据" class="headerlink" title="2、根据id去缓存查数据"></a>2、根据id去缓存查数据</h3><p>请求:<br><code>http://127.0.0.1:8080/selectOne?id=3</code></p><p>返回:</p><pre><code>{ "id": 3, "name": "小信", "age": 23}</code></pre><p>idea日志:</p><pre><code>2019-11-27 22:45:23.211 DEBUG 10040 --- [nio-8080-exec-8] o.s.web.servlet.DispatcherServlet : GET "/selectOne?id=3", parameters={masked}2019-11-27 22:45:23.211 DEBUG 10040 --- [nio-8080-exec-8] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to xyz.zx21.demo.controller.StudentController#selectOne(Student)2019-11-27 22:45:23.213 DEBUG 10040 --- [nio-8080-exec-8] m.m.a.RequestResponseBodyMethodProcessor : Using 'application/json;q=0.8', given [text/html, application/xhtml+xml, image/webp, image/apng, application/signed-exchange;v=b3, application/xml;q=0.9, */*;q=0.8] and supported [application/json, application/*+json, application/json, application/*+json]2019-11-27 22:45:23.213 DEBUG 10040 --- [nio-8080-exec-8] m.m.a.RequestResponseBodyMethodProcessor : Writing [Student{id=3, name='小信', age=23}]2019-11-27 22:45:23.214 DEBUG 10040 --- [nio-8080-exec-8] o.s.web.servlet.DispatcherServlet : Completed 200 OK</code></pre><blockquote><p>可以看到它并没有去打印sql语句,直接从缓存取的数据</p></blockquote><ul><li>如果查询数据,指定为其他id,第一查询会走数据库,sql会打印到控制台,第二次再同样的请求则直接走缓存。</li></ul>]]></content>
<categories>
<category> JAVA </category>
</categories>
<tags>
<tag> java </tag>
</tags>
</entry>
<entry>
<title>[JAVA]assembly自定义打包</title>
<link href="/2019/11/24/JAVA-assembly%E8%87%AA%E5%AE%9A%E4%B9%89%E6%89%93%E5%8C%85/"/>
<url>/2019/11/24/JAVA-assembly%E8%87%AA%E5%AE%9A%E4%B9%89%E6%89%93%E5%8C%85/</url>
<content type="html"><![CDATA[<p>在很多场景下,会有很多shell脚本或者需要操作一些配置,可以使用maven的assembly插件打出结构清晰的架构。</p><p>官网参考:<a href="http://maven.apache.org/plugins/maven-assembly-plugin/assembly.html" target="_blank" rel="noopener">点击进入</a></p><h2 id="一、去掉springboot打包方式"><a href="#一、去掉springboot打包方式" class="headerlink" title="一、去掉springboot打包方式"></a>一、去掉springboot打包方式</h2><pre><code><build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins></build></code></pre><hr><h2 id="二、添加assembly依赖"><a href="#二、添加assembly依赖" class="headerlink" title="二、添加assembly依赖"></a>二、添加assembly依赖</h2><pre><code> <build> <finalName>zx-demo</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <manifest> <!--运行jar包时运行的主类,要求类全名--> <mainClass>com.example.zxdemo.Application</mainClass> <!-- 是否指定项目classpath下的依赖 --> <addClasspath>true</addClasspath> <!-- 指定依赖的时候声明前缀 --> <classpathPrefix>./</classpathPrefix> </manifest> <manifestEntries> <Class-Path>../conf/ ../resources/</Class-Path> </manifestEntries> </archive> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <configuration> <descriptors> <descriptor>src/main/assembly/assembly.xml</descriptor> </descriptors> </configuration> <executions> <execution><!-- 配置执行器 --> <id>make-assembly</id> <phase>package</phase><!-- 绑定到package生命周期阶段上 --> <goals> <goal>single</goal><!-- 只运行一次 --> </goals> </execution> </executions> </plugin> </plugins> </build></code></pre><ul><li><p>可以看到依赖中写了src/main/assembly/assembly.xml,这是配置文件存放的位置。</p><h2 id="三、assembly-xml"><a href="#三、assembly-xml" class="headerlink" title="三、assembly.xml"></a>三、assembly.xml</h2><pre><code><?xml version="1.0" encoding="UTF-8"?><assembly> <id>zx-demo</id> <formats> <format>tar</format><!--打包的文件格式,也可以有:war zip--> </formats> <!--tar.gz压缩包下是否生成和项目名相同的根目录--> <includeBaseDirectory>false</includeBaseDirectory> <dependencySets> <dependencySet> <!--是否把本项目添加到依赖文件夹下--> <useProjectArtifact>true</useProjectArtifact> <outputDirectory>lib</outputDirectory> <!--将scope为runtime的依赖包打包--> <scope>runtime</scope> </dependencySet> </dependencySets> <fileSets> <fileSet> <directory>src/main/bin</directory> <outputDirectory>./</outputDirectory> </fileSet> <fileSet> <directory>src/main/resources</directory> <outputDirectory>conf</outputDirectory> </fileSet> </fileSets></assembly></code></pre></li><li><p>可以看到 src/main/bin 目录,可以自定义启动脚本。</p><h2 id="四、自定义脚本"><a href="#四、自定义脚本" class="headerlink" title="四、自定义脚本"></a>四、自定义脚本</h2><h3 id="start-sh"><a href="#start-sh" class="headerlink" title="start.sh"></a>start.sh</h3><pre><code>nohup java -jar -Dfile.encoding=UTF-8 -Djava.security.egd=file:/dev/urandom ./lib/zx-demo.jar > /dev/null 2>&1 &</code></pre><h3 id="stop-sh"><a href="#stop-sh" class="headerlink" title="stop.sh"></a>stop.sh</h3><pre><code>PID=`ps -ef | grep zx-demo.jar | grep -v grep | awk '{print $2}'`if [ -z $PID ]; then echo Application is already stoppedelse echo kill $PID kill -s 9 $PIDfi</code></pre></li></ul><p>在assembly.xml中可自定义打包格式,打包后,target下会生成相应的压缩文件。<br><img src="http://" alt="图片"></p><p>conf:resources下的文件</p><p>lib:所有依赖的jar包</p><h2 id="目录结构"><a href="#目录结构" class="headerlink" title="目录结构"></a>目录结构</h2><h3 id="项目结构"><a href="#项目结构" class="headerlink" title="项目结构"></a>项目结构</h3><p><img src="http://image.xiaoxinyes.club/20191124094523.png" alt="项目"></p><h3 id="解压后结构"><a href="#解压后结构" class="headerlink" title="解压后结构"></a>解压后结构</h3><p><img src="http://image.xiaoxinyes.club/20191124094451.png" alt="目录"></p>]]></content>
<categories>
<category> JAVA </category>
</categories>
<tags>
<tag> maven </tag>
</tags>
</entry>
<entry>
<title>[JAVA]Mybatis注解操作表数据</title>
<link href="/2019/11/21/JAVA-Mybatis%E6%B3%A8%E8%A7%A3%E6%93%8D%E4%BD%9C%E8%A1%A8%E6%95%B0%E6%8D%AE/"/>
<url>/2019/11/21/JAVA-Mybatis%E6%B3%A8%E8%A7%A3%E6%93%8D%E4%BD%9C%E8%A1%A8%E6%95%B0%E6%8D%AE/</url>
<content type="html"><![CDATA[<h1 id="springboot-mybatis演示"><a href="#springboot-mybatis演示" class="headerlink" title="springboot+mybatis演示"></a>springboot+mybatis演示</h1><p>@Insert/@Delete/@Select/@Update</p><hr><h2 id="一、依赖"><a href="#一、依赖" class="headerlink" title="一、依赖"></a>一、依赖</h2><pre><code> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.0.0</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.25</version> </dependency></code></pre><h2 id="二、启动类"><a href="#二、启动类" class="headerlink" title="二、启动类"></a>二、启动类</h2><pre><code>@SpringBootApplicationpublic class DemoApplication { public static void main(String[] args) { SpringApplication app = new SpringApplication(DemoApplication.class); app.run(args); }}</code></pre><h2 id="三、application-yml"><a href="#三、application-yml" class="headerlink" title="三、application,yml"></a>三、application,yml</h2><pre><code>spring: datasource: password: 1579886070 username: root driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=falsemybatis: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印sql</code></pre><h2 id="四、student数据表"><a href="#四、student数据表" class="headerlink" title="四、student数据表"></a>四、student数据表</h2><pre><code>CREATE TABLE `student` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8;</code></pre><h2 id="五、来一个实体类"><a href="#五、来一个实体类" class="headerlink" title="五、来一个实体类"></a>五、来一个实体类</h2><pre><code>public class Student { public Student() { } public Student(Integer id, String name, Integer age) { this.id = id; this.name = name; this.age = age; } private Integer id; private String name; private Integer age; //get //set}</code></pre><h2 id="六、service和它的实现类"><a href="#六、service和它的实现类" class="headerlink" title="六、service和它的实现类"></a>六、service和它的实现类</h2><pre><code>public interface StudentService { int add(Student student); boolean deleteById(int id); List<Student> selectAll(); boolean updateStudent(Student s);}</code></pre><pre><code>@Servicepublic class StudentServiceImlp implements StudentService { @Autowired private StudentMapper studentMapper; @Override public int add(Student student) { return studentMapper.insertStudent(student); } @Override public boolean deleteById(int id) { return studentMapper.deleteStudent(id); } @Override public List<Student> selectAll() { return studentMapper.selectStudentAll(); } @Override public boolean updateStudent(Student s) { return studentMapper.update(s); }}</code></pre><h2 id="七、注入mapper"><a href="#七、注入mapper" class="headerlink" title="七、注入mapper"></a>七、注入mapper</h2><p>包含增删改查,类上加了@mapper,则不用再启动类上@MapperScan()</p><pre><code>@Mapperpublic interface StudentMapper { @Insert("insert into student(name,age) values (#{name},#{age})") int insertStudent(Student student); @Delete("delete from student where id = #{id}") boolean deleteStudent(int id); @Select("select * from student") List<Student> selectStudentAll(); @Update("update student set name=#{name},age = #{age} where id = #{id}") boolean update(Student student);}</code></pre><h2 id="八、最后controller"><a href="#八、最后controller" class="headerlink" title="八、最后controller"></a>八、最后controller</h2><pre><code>@RestController@RequestMappingpublic class StudentController { @Autowired private StudentService studentService; /** * 添加数据 * * @param name * @param age * @return */ @GetMapping("addStu") public Object insertStudent(@Param("name") String name, @Param("age") int age) { Student student = new Student(null, name, age); int index = studentService.add(student); return index; } /** * 根据id删除数据 * * @param id * @return */ @GetMapping("delete") public Object delete(@Param("id") int id) { return studentService.deleteById(id); } /** * 查询所有数据 * * @return */ @GetMapping("select") public Object select() { return studentService.selectAll(); } /** * 修改数据 * * @param id * @param name * @param age * @return */ @GetMapping("update") public Object update(int id, String name, int age) { Student s = new Student(id, name, age); return studentService.updateStudent(s); }}</code></pre>]]></content>
<categories>
<category> JAVA </category>
</categories>
<tags>
<tag> mybatis </tag>
</tags>
</entry>
<entry>
<title>[JAVA]MVC请求映射</title>
<link href="/2019/11/10/JAVA-MVC%E8%AF%B7%E6%B1%82%E6%98%A0%E5%B0%84/"/>
<url>/2019/11/10/JAVA-MVC%E8%AF%B7%E6%B1%82%E6%98%A0%E5%B0%84/</url>
<content type="html"><![CDATA[<h2 id="一、-RequestMapping方式"><a href="#一、-RequestMapping方式" class="headerlink" title="一、@RequestMapping方式"></a>一、@RequestMapping方式</h2><p>以前我们controller写请求路劲都是如下格式,指定每个http方法,如get、post等。</p><pre><code>@RequestMapping(value = "v1/get",method = RequestMethod.GET)</code></pre><p>点击方法,进入源代码中查看一下,可以看到方法包含如下多种:<br><img src="http://image.xiaoxinyes.club/2019-11-10_205659.png" alt="源码"></p><hr><h2 id="二、更简洁的方式"><a href="#二、更简洁的方式" class="headerlink" title="二、更简洁的方式"></a>二、更简洁的方式</h2><p>很多以前的老项目的格式都是上面的那种,而现在新增了@GetMapping,@PostMapping,@PutMapping,@DeleteMapping,@PatchMapping。</p><pre><code> @GetMapping("get") public String get(){ return "get请求!"; } @PostMapping("post") public String post(){ return "post请求!"; } @DeleteMapping("delete") public String delete(){ return "delete请求!"; } @PutMapping("put") public String put(){ return "put请求!"; }</code></pre><p>点击任意一个注解进入源码里面,可以看到组合注解。只是简化了,而依旧调用的是RequestMethod。<br><img src="http://image.xiaoxinyes.club/2019-11-10_210259.png" alt="源码"></p><hr><h2 id="三、基于restful接口开发"><a href="#三、基于restful接口开发" class="headerlink" title="三、基于restful接口开发"></a>三、基于restful接口开发</h2><p>Get:对应查询<br>post:对应新增<br>put:对应更新<br>delete:对应删除</p>]]></content>
<categories>
<category> JAVA </category>
</categories>
<tags>
<tag> java </tag>
</tags>
</entry>
<entry>
<title>[JAVA]@Value与@ConfigurationProperties</title>
<link href="/2019/10/29/JAVA-Value%E4%B8%8E-ConfigurationProperties/"/>
<url>/2019/10/29/JAVA-Value%E4%B8%8E-ConfigurationProperties/</url>
<content type="html"><![CDATA[<p>有时重要的信息需要写在配置文件中,如application.yml或是如application.preperties,那么可以通过@Value或是@ConfigurationProperties获取到配置文件中的值。</p><hr><h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><h3 id="一、-Value"><a href="#一、-Value" class="headerlink" title="一、@Value"></a>一、@Value</h3><h4 id="yml配置"><a href="#yml配置" class="headerlink" title="yml配置"></a>yml配置</h4><pre><code>person: name: 小信 age: 20</code></pre><h4 id="controller"><a href="#controller" class="headerlink" title="controller"></a>controller</h4><pre><code>@RestController@RequestMappingpublic class PersonController { @Value("${person.name}") private String name; @Value("${person.age}") private Integer age; @GetMapping("getInfo") public String Info() { return name + ":" + age; }}</code></pre><h4 id="访问地址"><a href="#访问地址" class="headerlink" title="访问地址"></a>访问地址</h4><p><a href="http://127.0.0.1:8080/getInfo" target="_blank" rel="noopener">http://127.0.0.1:8080/getInfo</a></p><p>响应 <code>小信:20</code></p><hr><p><em>使用该方式可以发现,若配置多个,那么都需要使用@Value注入多次,显得较为繁琐</em></p><hr><h3 id="二、-ConfigurationProperties"><a href="#二、-ConfigurationProperties" class="headerlink" title="二、@ConfigurationProperties"></a>二、@ConfigurationProperties</h3><p>将配置文件中得属性与一个Bean相关联,实现类型安全的配置。</p><h4 id="yml配置-1"><a href="#yml配置-1" class="headerlink" title="yml配置"></a>yml配置</h4><pre><code>student: name: 小信 email: xiaoxin1218@qq.com</code></pre><h4 id="Bean实体"><a href="#Bean实体" class="headerlink" title="Bean实体"></a>Bean实体</h4><pre><code>@ConfigurationProperties(prefix = "student")public class StudentVO { private String name; private String email; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; }}</code></pre><p><strong>通过prefix指定配置文件的前缀</strong></p><h4 id="controller-1"><a href="#controller-1" class="headerlink" title="controller"></a>controller</h4><pre><code>@RestController@RequestMappingpublic class StudentController { @Autowired private StudentVO studentVO; @GetMapping("getStu") public String studentInfo() { return studentVO.getName() + "::" + studentVO.getEmail(); }}</code></pre><p><strong>@Autowired可直接注入</strong></p><h4 id="访问地址-1"><a href="#访问地址-1" class="headerlink" title="访问地址"></a>访问地址</h4><p><a href="http://127.0.0.1:8080/getStu" target="_blank" rel="noopener">http://127.0.0.1:8080/getStu</a><br>响应 <code>小信::xiaoxin1218@qq.com</code></p>]]></content>
<categories>
<category> JAVA </category>
</categories>
<tags>
<tag> java </tag>
</tags>
</entry>
<entry>
<title>[JAVA]SpringBoot定制benner</title>
<link href="/2019/10/27/JAVA-SpringBoot%E5%AE%9A%E5%88%B6benner/"/>
<url>/2019/10/27/JAVA-SpringBoot%E5%AE%9A%E5%88%B6benner/</url>
<content type="html"><![CDATA[<p>springboot默认启动banner如下:</p><p><img src="http://image.xiaoxinyes.club/2019-10-27_195347.png" alt="默认banner"></p><p>修改步骤也十分简单</p><hr><h2 id="修改步骤"><a href="#修改步骤" class="headerlink" title="修改步骤"></a>修改步骤</h2><h3 id="一"><a href="#一" class="headerlink" title="一"></a>一</h3><p>在src/main/resources下新建名为banner.txt的文件。</p><h3 id="二"><a href="#二" class="headerlink" title="二"></a>二</h3><p>文本中写入需要的字符,可通过<a href="http://patorjk.com/software/taag" target="_blank" rel="noopener">点击进入</a>该网站生成字符。<br><img src="http://image.xiaoxinyes.club/2019-10-27_200333.png" alt="生成字符网站"></p><h3 id="三"><a href="#三" class="headerlink" title="三"></a>三</h3><p>启动程序即可,可以看到已经发生了变化<br><img src="http://image.xiaoxinyes.club/2019-10-27_200550.png" alt="修改后的benner"></p><h2 id="关闭benner"><a href="#关闭benner" class="headerlink" title="关闭benner"></a>关闭benner</h2><pre><code>@SpringBootApplicationpublic class DemoApplication { public static void main(String[] args) { SpringApplication app = new SpringApplication(DemoApplication.class); app.setBannerMode(Banner.Mode.OFF); app.run(args); }}</code></pre>]]></content>
<categories>
<category> JAVA </category>
</categories>
<tags>
<tag> java </tag>
</tags>
</entry>
<entry>
<title>[JAVA]Mybatis代码生成</title>
<link href="/2019/10/27/JAVA-Mybatis%E4%BB%A3%E7%A0%81%E7%94%9F%E6%88%90/"/>
<url>/2019/10/27/JAVA-Mybatis%E4%BB%A3%E7%A0%81%E7%94%9F%E6%88%90/</url>
<content type="html"><![CDATA[<p>generatorConfig.xml</p><h3 id="首先在pom-xml中添加插件依赖"><a href="#首先在pom-xml中添加插件依赖" class="headerlink" title="首先在pom.xml中添加插件依赖"></a>首先在pom.xml中添加插件依赖</h3><pre><code><build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <!-- mybatis generator 自动生成代码插件 --> <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.1</version> <configuration> <configurationFile>${basedir}/src/main/resources/generator/generatorConfig.xml</configurationFile> <overwrite>true</overwrite> <verbose>true</verbose> </configuration> </plugin> </plugins></build></code></pre><h3 id="新建generatorConfig-xml"><a href="#新建generatorConfig-xml" class="headerlink" title="新建generatorConfig.xml"></a>新建generatorConfig.xml</h3><pre><code><?xml version="1.0" encoding="UTF-8"?><!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"><generatorConfiguration> <!-- 数据库驱动:选择你的本地硬盘上面的数据库驱动包--> <classPathEntry location="E:\SSH_SSM\mysql-connector-java-5.1.44\mysql-connector-java-5.1.44\mysql-connector-java-5.1.44-bin.jar"/> <context id="DB2Tables" targetRuntime="MyBatis3"> <commentGenerator> <property name="suppressDate" value="true"/> <!-- 是否去除自动生成的注释 true:是 : false:否 --> <property name="suppressAllComments" value="false"/> </commentGenerator> <!--数据库连接驱动类,URL,用户名、密码 --> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://127.0.0.1/blogs" userId="root" password="密码"> </jdbcConnection> <javaTypeResolver> <property name="forceBigDecimals" value="false"/> </javaTypeResolver> <!-- 生成(实体)模型的包名和位置--> <javaModelGenerator targetPackage="xyz.xioaxin12.blogs.entity" targetProject="E:\Idea Project\blogs\src\main\java"> <property name="enableSubPackages" value="true"/> <property name="trimStrings" value="true"/> </javaModelGenerator> <!-- 生成XML映射文件的包名和位置--> <sqlMapGenerator targetPackage="resources.mapper" targetProject="E:\Idea Project\blogs\src\main"> <property name="enableSubPackages" value="true"/> </sqlMapGenerator> <!-- 生成DAO接口的包名和位置--> <javaClientGenerator type="XMLMAPPER" targetPackage="xyz.xioaxin12.blogs.dao" targetProject="E:\Idea Project\blogs\src\main\java"> <property name="enableSubPackages" value="true"/> </javaClientGenerator> <!-- 要生成的表 tableName是数据库中的表名或视图名 domainObjectName是实体类名--> <table tableName="t_blog" domainObjectName="Blog" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table> <table tableName="t_blog" domainObjectName="Blog" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table> <table tableName="t_blogger" domainObjectName="Blogger" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table> <table tableName="t_blog" domainObjectName="Blog" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table> <table tableName="t_blogtype" domainObjectName="BlogType" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table> <table tableName="t_blog" domainObjectName="Blog" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table> <table tableName="t_comment" domainObjectName="Comment" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table> <table tableName="t_blog" domainObjectName="Blog" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table> <table tableName="t_link" domainObjectName="Link" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table> <table tableName="t_blog" domainObjectName="Blog" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table> </context></generatorConfiguration></code></pre><p>配置信息,包的所在位置等自行更改。</p><hr><p>idea执行步骤,run–>Edit Configurations–>添加maven–>mybatis-generator:generate -e</p><p><img src="http://image.xiaoxinyes.club/2019-02-13_15-18-24.png" alt></p><p><img src="http://image.xiaoxinyes.club/2019-02-13_15-23-07.png" alt></p><p>最后生成即可<br><img src="http://image.xiaoxinyes.club/Snipaste_2019-02-13_15-25-55.png" alt></p>]]></content>
<categories>
<category> JAVA </category>
</categories>
<tags>
<tag> java </tag>
</tags>
</entry>
<entry>
<title>[ERROR]SpringBoot+Mybatis一个错误</title>
<link href="/2019/10/27/ERROR-SpringBoot-Mybatis%E4%B8%80%E4%B8%AA%E9%94%99%E8%AF%AF/"/>
<url>/2019/10/27/ERROR-SpringBoot-Mybatis%E4%B8%80%E4%B8%AA%E9%94%99%E8%AF%AF/</url>
<content type="html"><![CDATA[<h3 id="异常信息如下"><a href="#异常信息如下" class="headerlink" title="异常信息如下"></a>异常信息如下</h3><pre><code>java.sql.SQLNonTransientConnectionException: CLIENT_PLUGIN_AUTH is required</code></pre><p>image<br><img src="http://image.xiaoxinyes.club/Snipaste_2019-02-13_19-50-35.png" alt></p><hr><h3 id="解决方法"><a href="#解决方法" class="headerlink" title="解决方法"></a>解决方法</h3><p>降低mysql-connector-java的版本即可,我自己试了下5.x的似乎都没问题。</p><h4 id="详细步骤"><a href="#详细步骤" class="headerlink" title="详细步骤"></a>详细步骤</h4><p>将pom.xml中的jdbc数据库驱动修改下。<br>原</p><pre><code> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>provided</scope></dependency></code></pre><p>修改为</p><pre><code> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.25</version></dependency></code></pre><h4 id="关于application-properties配置修改"><a href="#关于application-properties配置修改" class="headerlink" title="关于application.properties配置修改"></a>关于application.properties配置修改</h4><p>原来(mysql6版本以上)</p><pre><code>spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver</code></pre><p>修改为(mysql5)</p><pre><code>spring.datasource.driver-class-name=com.mysql.jdbc.Driver</code></pre>]]></content>
<categories>
<category> ERROR </category>
</categories>
<tags>
<tag> error </tag>
</tags>