-
Notifications
You must be signed in to change notification settings - Fork 0
/
atom.xml
573 lines (303 loc) · 124 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>周信的博客</title>
<subtitle>静心也</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="http://zx21.xyz/"/>
<updated>2024-02-23T07:47:42.464Z</updated>
<id>http://zx21.xyz/</id>
<author>
<name>周信</name>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>[闲谈]-2023</title>
<link href="http://zx21.xyz/2024/02/23/%E9%97%B2%E8%B0%88-2023/"/>
<id>http://zx21.xyz/2024/02/23/%E9%97%B2%E8%B0%88-2023/</id>
<published>2024-02-23T06:51:23.000Z</published>
<updated>2024-02-23T07:47:42.464Z</updated>
<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>
<summary type="html">
<h3 id="2023总结"><a href="#2023总结" class="headerlink" title="2023总结"></a>2023总结</h3><p>我总会在这个阶段简短说明下去年的想法。这年基本忙于工作,除了本职工作的技术管理之外,还花了一部分时间在摄影摄
</summary>
<category term="闲谈" scheme="http://zx21.xyz/categories/%E9%97%B2%E8%B0%88/"/>
<category term="闲谈" scheme="http://zx21.xyz/tags/%E9%97%B2%E8%B0%88/"/>
</entry>
<entry>
<title>[English]-否定句</title>
<link href="http://zx21.xyz/2023/05/05/English-%E5%90%A6%E5%AE%9A%E5%8F%A5/"/>
<id>http://zx21.xyz/2023/05/05/English-%E5%90%A6%E5%AE%9A%E5%8F%A5/</id>
<published>2023-05-05T12:40:38.000Z</published>
<updated>2023-05-05T13:22:39.039Z</updated>
<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>
<summary type="html">
<h1 id="什么是否定句?"><a href="#什么是否定句?" class="headerlink" title="什么是否定句?"></a>什么是否定句?</h1><ul>
<li>判断方式<ul>
<li>表达“不”“否”“没有”等否定意思</li>
</ul>
</
</summary>
<category term="English" scheme="http://zx21.xyz/categories/English/"/>
<category term="English" scheme="http://zx21.xyz/tags/English/"/>
</entry>
<entry>
<title>[English]-There be句型</title>
<link href="http://zx21.xyz/2023/05/05/English-There%20be%E5%8F%A5%E5%9E%8B/"/>
<id>http://zx21.xyz/2023/05/05/English-There%20be%E5%8F%A5%E5%9E%8B/</id>
<published>2023-05-05T12:36:38.000Z</published>
<updated>2023-05-05T12:56:09.522Z</updated>
<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>
<summary type="html">
<h1 id="什么是there-be句型?"><a href="#什么是there-be句型?" class="headerlink" title="什么是there be句型?"></a>什么是there be句型?</h1><ul>
<li>判断方式<ul>
<li>表达某
</summary>
<category term="English" scheme="http://zx21.xyz/categories/English/"/>
<category term="English" scheme="http://zx21.xyz/tags/English/"/>
</entry>
<entry>
<title>[English]-主系表句型</title>
<link href="http://zx21.xyz/2023/05/03/English-%E4%B8%BB%E7%B3%BB%E8%A1%A8%E5%8F%A5%E5%9E%8B/"/>
<id>http://zx21.xyz/2023/05/03/English-%E4%B8%BB%E7%B3%BB%E8%A1%A8%E5%8F%A5%E5%9E%8B/</id>
<published>2023-05-03T04:36:38.000Z</published>
<updated>2023-05-03T04:36:47.012Z</updated>
<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>
<summary type="html">
<h1 id="什么是主谓宾句型?"><a href="#什么是主谓宾句型?" class="headerlink" title="什么是主谓宾句型?"></a>什么是主谓宾句型?</h1><ul>
<li>判断方式<ul>
<li>是/很/在</li>
</ul>
</li>
</summary>
<category term="English" scheme="http://zx21.xyz/categories/English/"/>
<category term="English" scheme="http://zx21.xyz/tags/English/"/>
</entry>
<entry>
<title>[English]-主谓宾句型</title>
<link href="http://zx21.xyz/2023/05/03/English-%E4%B8%BB%E8%B0%93%E5%AE%BE%E5%8F%A5%E5%9E%8B/"/>
<id>http://zx21.xyz/2023/05/03/English-%E4%B8%BB%E8%B0%93%E5%AE%BE%E5%8F%A5%E5%9E%8B/</id>
<published>2023-05-03T03:36:38.000Z</published>
<updated>2023-05-03T03:34:00.254Z</updated>
<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>
<summary type="html">
<h1 id="什么是主谓宾句型?"><a href="#什么是主谓宾句型?" class="headerlink" title="什么是主谓宾句型?"></a>什么是主谓宾句型?</h1><ul>
<li>主语后面是“动作(动词)”<ul>
<li>看、跑、吃、喝…</li>
</summary>
<category term="English" scheme="http://zx21.xyz/categories/English/"/>
<category term="English" scheme="http://zx21.xyz/tags/English/"/>
</entry>
<entry>
<title>[Other]Nginx个人常用命令整理</title>
<link href="http://zx21.xyz/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/"/>
<id>http://zx21.xyz/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/</id>
<published>2022-06-24T03:36:38.000Z</published>
<updated>2023-05-03T02:25:35.015Z</updated>
<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>
<summary type="html">
<p><code>nginx -t 检查配置是否正确</code></p>
<p><code>nginx -s reload 重新加载配置信息</code></p>
<pre><code>server {
listen 80;
server_name www.x
</summary>
<category term="Other" scheme="http://zx21.xyz/categories/Other/"/>
<category term="nginx" scheme="http://zx21.xyz/tags/nginx/"/>
</entry>
<entry>
<title>[JAVA]-中文根据拼音首字母排序</title>
<link href="http://zx21.xyz/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/"/>
<id>http://zx21.xyz/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/</id>
<published>2021-03-22T09:05:14.000Z</published>
<updated>2023-05-03T02:25:35.010Z</updated>
<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>
<summary type="html">
<p><strong>有些用户列表/品种列表等,常用A,B,C作为名称的搜索条件。</strong></p>
<p>依赖</p>
<pre><code>&lt;dependency&gt;
&lt;groupId&gt;com.belerweb&lt;/groupId&g
</summary>
<category term="JAVA" scheme="http://zx21.xyz/categories/JAVA/"/>
<category term="java" scheme="http://zx21.xyz/tags/java/"/>
</entry>
<entry>
<title>[JAVA]-视频url获取指定帧数的图片</title>
<link href="http://zx21.xyz/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/"/>
<id>http://zx21.xyz/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/</id>
<published>2021-03-17T08:00:25.000Z</published>
<updated>2023-05-03T02:25:35.012Z</updated>
<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>
<summary type="html">
<p><strong>通过视频地址,获取指定N帧的图片,并且上传到阿里云oss</strong></p>
<p>参考地址:<a href="http://www.fixbbs.com/p/01439272.html" target="_blank" rel="noopener">
</summary>
<category term="JAVA" scheme="http://zx21.xyz/categories/JAVA/"/>
<category term="java" scheme="http://zx21.xyz/tags/java/"/>
</entry>
<entry>
<title>[JAVA]跨域解决方法</title>
<link href="http://zx21.xyz/2020/04/01/JAVA-%E8%B7%A8%E5%9F%9F%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95/"/>
<id>http://zx21.xyz/2020/04/01/JAVA-%E8%B7%A8%E5%9F%9F%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95/</id>
<published>2020-04-01T08:43:05.000Z</published>
<updated>2023-05-03T02:25:35.013Z</updated>
<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>
<summary type="html">
<p><strong>前后端交互出现跨域错误</strong></p>
<p>error</p>
<pre><code>home:1 Access to XMLHttpRequest at &#39;http://127.0.0.1:8080/article/list?start
</summary>
<category term="JAVA" scheme="http://zx21.xyz/categories/JAVA/"/>
<category term="java" scheme="http://zx21.xyz/tags/java/"/>
</entry>
<entry>
<title>[Other]Linux个人常用命令整理</title>
<link href="http://zx21.xyz/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/"/>
<id>http://zx21.xyz/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/</id>
<published>2020-03-29T05:04:27.000Z</published>
<updated>2023-05-03T02:25:35.015Z</updated>
<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>
<summary type="html">
<h2 id="1、查看整体机器性能"><a href="#1、查看整体机器性能" class="headerlink" title="1、查看整体机器性能"></a>1、查看整体机器性能</h2><p> top</p>
<pre><code> --1.1 cpu
</summary>
<category term="Other" scheme="http://zx21.xyz/categories/Other/"/>
<category term="linux" scheme="http://zx21.xyz/tags/linux/"/>
</entry>
<entry>
<title>[Cloud]Hystrix断路器</title>
<link href="http://zx21.xyz/2020/03/27/Cloud-Hystrix%E6%96%AD%E8%B7%AF%E5%99%A8/"/>
<id>http://zx21.xyz/2020/03/27/Cloud-Hystrix%E6%96%AD%E8%B7%AF%E5%99%A8/</id>
<published>2020-03-27T08:32:06.000Z</published>
<updated>2023-05-03T02:25:35.000Z</updated>
<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>
<summary type="html">
<h1 id="是什么?"><a href="#是什么?" class="headerlink" title="是什么?"></a>是什么?</h1><blockquote>
<p>Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调
</summary>
<category term="JAVA" scheme="http://zx21.xyz/categories/JAVA/"/>
<category term="SpringCloud" scheme="http://zx21.xyz/tags/SpringCloud/"/>
</entry>
<entry>
<title>[Cloud]8-OpenFeign</title>
<link href="http://zx21.xyz/2020/03/22/Cloud-8-OpenFeign/"/>
<id>http://zx21.xyz/2020/03/22/Cloud-8-OpenFeign/</id>
<published>2020-03-22T11:01:51.000Z</published>
<updated>2023-05-03T02:25:35.000Z</updated>
<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>
<summary type="html">
<h1 id="OpenFeign"><a href="#OpenFeign" class="headerlink" title="OpenFeign"></a>OpenFeign</h1><h2 id="是什么?"><a href="#是什么?" class="headerli
</summary>
<category term="JAVA" scheme="http://zx21.xyz/categories/JAVA/"/>
<category term="SpringCloud" scheme="http://zx21.xyz/tags/SpringCloud/"/>
</entry>
<entry>
<title>[Cloud]7-Ribbon相关</title>
<link href="http://zx21.xyz/2020/03/22/Cloud-7-Ribbon%E7%9B%B8%E5%85%B3/"/>
<id>http://zx21.xyz/2020/03/22/Cloud-7-Ribbon%E7%9B%B8%E5%85%B3/</id>
<published>2020-03-22T05:02:23.000Z</published>
<updated>2023-05-03T02:25:35.000Z</updated>
<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>
<summary type="html">
<h1 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h1><h2 id="是什么?"><a href="#是什么?" class="headerlink" title="是什么?"></a>是什么?</h
</summary>
<category term="JAVA" scheme="http://zx21.xyz/categories/JAVA/"/>
<category term="SringCloud" scheme="http://zx21.xyz/tags/SringCloud/"/>
</entry>
<entry>
<title>[Cloud]6-三个注册中心异同点</title>
<link href="http://zx21.xyz/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/"/>
<id>http://zx21.xyz/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/</id>
<published>2020-03-21T14:37:12.000Z</published>
<updated>2023-05-03T02:25:35.000Z</updated>
<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>
<summary type="html">
<h1 id="异同点"><a href="#异同点" class="headerlink" title="异同点"></a>异同点</h1><p>|组件名|语言|CAP|服务健康检查|对外暴露接口|<br>|:—– |:—–|:—–<br>|Eureka |Java|AP|可
</summary>
<category term="JAVA" scheme="http://zx21.xyz/categories/JAVA/"/>
<category term="SpringCloud" scheme="http://zx21.xyz/tags/SpringCloud/"/>
</entry>
<entry>
<title>[Cloud]5-集成Consul</title>
<link href="http://zx21.xyz/2020/03/21/Cloud-5-%E9%9B%86%E6%88%90Consul/"/>
<id>http://zx21.xyz/2020/03/21/Cloud-5-%E9%9B%86%E6%88%90Consul/</id>
<published>2020-03-21T09:53:36.000Z</published>
<updated>2023-05-03T02:25:34.999Z</updated>
<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>
<summary type="html">
<h1 id="Consul"><a href="#Consul" class="headerlink" title="Consul"></a>Consul</h1><h2 id="安装与启动"><a href="#安装与启动" class="headerlink" title=
</summary>
<category term="JAVA" scheme="http://zx21.xyz/categories/JAVA/"/>
<category term="SpringCloud" scheme="http://zx21.xyz/tags/SpringCloud/"/>
</entry>
<entry>
<title>[Cloud]4-集成ZooKeeper</title>
<link href="http://zx21.xyz/2020/03/21/Cloud-4-%E9%9B%86%E6%88%90ZooKeeper/"/>
<id>http://zx21.xyz/2020/03/21/Cloud-4-%E9%9B%86%E6%88%90ZooKeeper/</id>
<published>2020-03-21T03:08:48.000Z</published>
<updated>2023-05-03T02:25:34.999Z</updated>
<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>
<summary type="html">
<p><strong>本机与虚拟机测试,注意:保证本机与虚拟机能互相ping通</strong></p>
<h1 id="zookeepper命令"><a href="#zookeepper命令" class="headerlink" title="zookeepper命令"><
</summary>
<category term="JAVA" scheme="http://zx21.xyz/categories/JAVA/"/>
<category term="SpringCloud" scheme="http://zx21.xyz/tags/SpringCloud/"/>
</entry>
<entry>
<title>[Cloud]3-集成Eureka</title>
<link href="http://zx21.xyz/2020/03/20/Cloud-3-%E9%9B%86%E6%88%90Eureka/"/>
<id>http://zx21.xyz/2020/03/20/Cloud-3-%E9%9B%86%E6%88%90Eureka/</id>
<published>2020-03-20T05:46:09.000Z</published>
<updated>2023-05-03T02:25:34.999Z</updated>
<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>
<summary type="html">
<h1 id="EurekaServer服务端安装"><a href="#EurekaServer服务端安装" class="headerlink" title="EurekaServer服务端安装"></a>EurekaServer服务端安装</h1><p>新建一个Eureka
</summary>
<category term="JAVA" scheme="http://zx21.xyz/categories/JAVA/"/>
<category term="SpringCloud" scheme="http://zx21.xyz/tags/SpringCloud/"/>
</entry>
<entry>
<title>[Cloud]2-支付模块与工程重构</title>
<link href="http://zx21.xyz/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/"/>
<id>http://zx21.xyz/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/</id>
<published>2020-03-19T08:29:40.000Z</published>
<updated>2023-05-03T02:25:34.999Z</updated>
<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>
<summary type="html">
<p><strong>创建消费者模块cloud-comsumer-order80调用上篇文章的支付模块cloud-provider-payment8001。</strong></p>
<h1 id="构建步骤"><a href="#构建步骤" class="headerlink"
</summary>
<category term="JAVA" scheme="http://zx21.xyz/categories/JAVA/"/>
<category term="SpringCloud" scheme="http://zx21.xyz/tags/SpringCloud/"/>
</entry>
<entry>
<title>[Cloud]1-父工程创建与支付模块构建</title>
<link href="http://zx21.xyz/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/"/>
<id>http://zx21.xyz/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/</id>
<published>2020-03-19T05:28:06.000Z</published>
<updated>2023-05-03T02:25:34.991Z</updated>
<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>
<summary type="html">
<p><strong>约定 &gt; 配置 &gt; 编码</strong></p>
<hr>
<h1 id="工程步骤"><a href="#工程步骤" class="headerlink" title="工程步骤"></a>工程步骤</h1><pre><code>1、New
</summary>
<category term="JAVA" scheme="http://zx21.xyz/categories/JAVA/"/>
<category term="SpringCloud" scheme="http://zx21.xyz/tags/SpringCloud/"/>
</entry>
<entry>
<title>[JAVA]easyexcel导出</title>
<link href="http://zx21.xyz/2020/02/26/JAVA-easyexcel%E5%AF%BC%E5%87%BA/"/>
<id>http://zx21.xyz/2020/02/26/JAVA-easyexcel%E5%AF%BC%E5%87%BA/</id>
<published>2020-02-26T13:29:59.000Z</published>
<updated>2023-05-03T02:25:35.008Z</updated>
<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>
<summary type="html">
<p>阿里的表格工具,简单了解了一下。</p>
<h2 id="依赖"><a href="#依赖" class="headerlink" title="依赖"></a>依赖</h2><pre><code>&lt;dependency&gt;
&lt;groupId&gt;
</summary>
<category term="JAVA" scheme="http://zx21.xyz/categories/JAVA/"/>
<category term="java" scheme="http://zx21.xyz/tags/java/"/>
</entry>
</feed>