-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsearch.xml
3368 lines (1761 loc) · 608 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>微信小程序调研-web-view的使用</title>
<link href="/2018/2018%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E8%B0%83%E7%A0%945/"/>
<url>/2018/2018%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E8%B0%83%E7%A0%945/</url>
<content type="html"><![CDATA[<h3 id="调研内容"><a href="#调研内容" class="headerlink" title="调研内容"></a>调研内容</h3><p>通过小程序和H5网页数据交互,打通小程序和对应公众号的用户关系</p><a id="more"></a><h3 id="调研结果"><a href="#调研结果" class="headerlink" title="调研结果"></a>调研结果</h3><p>可以通过互传openId的方式,通过加密字符串的校验,可以实现数据互通,这个数据并不是百分百准确,但是具有一定的可靠性</p><h4 id="实例"><a href="#实例" class="headerlink" title="实例"></a>实例</h4><p>通过组件web-view来实现,属性src,具体代码如下</p><p>入口页:有一个确认跳转的弹窗</p><p><code>model/index.js</code><br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 生命周期函数--监听页面初次渲染完成</span><br><span class="line"> */</span><br><span class="line">onReady: function() {</span><br><span class="line"> //将小程序用户的openId保存</span><br><span class="line"> wx.setStorageSync('miniOpenId', '12345656777888');</span><br><span class="line"> wx.showModal({</span><br><span class="line"> title: '提示',</span><br><span class="line"> content: '这是一个模态弹窗',</span><br><span class="line"> success(res) {</span><br><span class="line"> if (res.confirm) {</span><br><span class="line"> console.log('用户点击确定')</span><br><span class="line"> var i = 0;</span><br><span class="line"> if (i = 1)</span><br><span class="line"> wx.navigateTo({</span><br><span class="line"> url: '/index/index'</span><br><span class="line"> })</span><br><span class="line"> } else if (res.cancel) {</span><br><span class="line"> console.log('用户点击取消')</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> })</span><br><span class="line">},</span><br></pre></td></tr></table></figure></p><p>web-view加载页面</p><p><code>index/index.js</code><br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">Page({</span><br><span class="line"> /**</span><br><span class="line"> * 页面的初始数据</span><br><span class="line"> */</span><br><span class="line"> data: {</span><br><span class="line"> miniOpenId:'',</span><br><span class="line"> url: ''</span><br><span class="line"> },</span><br><span class="line"> /**</span><br><span class="line"> * 生命周期函数--监听页面加载</span><br><span class="line"> */</span><br><span class="line"> onLoad: function (options) {</span><br><span class="line"> var that = this;</span><br><span class="line"> //获取保存的小程序用户openId</span><br><span class="line"> var miniOpenId = wx.getStorageSync('miniOpenId');</span><br><span class="line"> //设置页面加载需要的参数</span><br><span class="line"> that.setData({ url: 'https://abc.cn/demo/auth2/code' });</span><br><span class="line"> that.setData({ miniOpenId: miniOpenId });</span><br><span class="line"> console.log(miniOpenId);</span><br><span class="line"> </span><br><span class="line"> },</span><br><span class="line"> //接收h5发送的数据</span><br><span class="line"> //需要注意,只有在特定时间点才能触发该方法</span><br><span class="line"> postMessage(e) {</span><br><span class="line"> console.log(1)</span><br><span class="line"> console.log(e.detail.data[0])</span><br><span class="line"> console.log(e.detail.data[0].openId)</span><br><span class="line"> console.log(e.detail.data[0].count)</span><br><span class="line"> }</span><br><span class="line">})</span><br></pre></td></tr></table></figure></p><p><code>index/index.wxml</code>页面<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><view class="page-body"></span><br><span class="line"> <view class="page-section page-section-gap"></span><br><span class="line"> <web-view src="{{url}}?miniOpenId={{miniOpenId}}" bindmessage="postMessage"></span><br><span class="line"> <p >请稍等....</p></span><br><span class="line"> </web-view></span><br><span class="line"> </view></span><br><span class="line"></view></span><br></pre></td></tr></table></figure></p><p>微信授权页面 auth.html,这是在springboot下的thymeleaf页面<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><!DOCTYPE html></span><br><span class="line"><html lang="en" xmlns:th="http://www.w3.org/1999/xhtml"></span><br><span class="line"><head></span><br><span class="line"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" ></meta></span><br><span class="line"> <title>WebView测试</title></span><br><span class="line"> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script></span><br><span class="line"> <!-- jssdk依赖 --></span><br><span class="line"> <script src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js" type="application/javascript"></script></span><br><span class="line"></head></span><br><span class="line"><body></span><br><span class="line"><div></span><br><span class="line"> <h1 align="center">小程序WebView测试</h1></span><br><span class="line"> <div align="center" style="background-color: aquamarine;margin:10px;padding: 10px;width: auto;height: 180px;align-content: center"></span><br><span class="line"> <button style="width: 320px;height: 180px;font-size: xx-large" onclick="comeback1()"><h1>原页面</h1></button></span><br><span class="line"> <button style="width: 320px;height: 180px;font-size: xx-large" onclick="comeback2()"><h1>重定向</h1></button></span><br><span class="line"> </div></span><br><span class="line"></div></span><br><span class="line"><script th:inline="javascript"></span><br><span class="line"> //后端传的openId</span><br><span class="line"> var openId = [[${openId}]];</span><br><span class="line"> console.log(openId);</span><br><span class="line"> var count = 1;</span><br><span class="line"> //发送数据到小程序</span><br><span class="line"> wx.miniProgram.postMessage({ data: {"openId": openId,"count":count} })</span><br><span class="line"> //原路返回</span><br><span class="line"> function comeback1() {</span><br><span class="line"> wx.miniProgram.navigateBack()</span><br><span class="line"> }</span><br><span class="line"> //重定向到新页面</span><br><span class="line"> function comeback2() {</span><br><span class="line"> wx.miniProgram.redirectTo({url: '/m2/index'})</span><br><span class="line"> }</span><br><span class="line"></script></span><br><span class="line"></body></span><br><span class="line"></html></span><br></pre></td></tr></table></figure></p><p>代码放到csdn上了,<a href="https://download.csdn.net/download/defxino/10811121" target="_blank" rel="noopener">https://download.csdn.net/download/defxino/10811121</a><br>如果没积分就给我发邮件吧,主题中说明是干嘛的,我会给你发,mailto:<a href="mailto:[email protected]" target="_blank" rel="noopener">[email protected]</a></p><p>里面有很多坑,需要慢慢踩!</p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> Wechat </tag>
<tag> MiniProgram </tag>
</tags>
</entry>
<entry>
<title>微信小程序调研-支付的支持</title>
<link href="/2018/2018%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E8%B0%83%E7%A0%944/"/>
<url>/2018/2018%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E8%B0%83%E7%A0%944/</url>
<content type="html"><![CDATA[<h3 id="调研内容"><a href="#调研内容" class="headerlink" title="调研内容"></a>调研内容</h3><p>对支付的支持,有哪些功能?有哪些限制?有没有突破的方法?</p><a id="more"></a><h3 id="调研结果"><a href="#调研结果" class="headerlink" title="调研结果"></a>调研结果</h3><h4 id="小程序支付"><a href="#小程序支付" class="headerlink" title="小程序支付"></a>小程序支付</h4><p>小程序的支付可以通过APPID绑定已有微信支付或申请微信支付账号,调用小程序相关支付API,完成支付。</p><h5 id="小程序内网页支付"><a href="#小程序内网页支付" class="headerlink" title="小程序内网页支付"></a>小程序内网页支付</h5><p>由于小程序嵌入的网页中,并不是JSSDK的所有API都支持,只支持部分API,而恰恰JSSDK支付不支持,所以还需要绕回到小程序的微信支付<br>两种方式,一种是直接通过网页与小程序的交互完成交互,后端要完成相关账单对接。另一种是通过网页自己服务自己,自己生成相关的支付码,<br>返回给用户,用户通过扫码完成支付,但是这个方案还需要进一步测试。</p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> Wechat </tag>
<tag> MiniProgram </tag>
</tags>
</entry>
<entry>
<title>Centos7安装Mariadb</title>
<link href="/2018/2018Centos7%E5%AE%89%E8%A3%85Mariadb/"/>
<url>/2018/2018Centos7%E5%AE%89%E8%A3%85Mariadb/</url>
<content type="html"><![CDATA[<h3 id="概要"><a href="#概要" class="headerlink" title="概要"></a>概要</h3><p>简单记录在Centos7.3下安装Mariadb 10.3,及简单配置<br><a id="more"></a></p><h3 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h3><h4 id="Repo设置"><a href="#Repo设置" class="headerlink" title="Repo设置"></a>Repo设置</h4><p><code>vim /etc/yum.repos.d/mariadb.repo</code></p><p>写入内容<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"># MariaDB 10.3 CentOS repository list - created 2018-11-05 02:44 UTC</span><br><span class="line"># http://downloads.mariadb.org/mariadb/repositories/</span><br><span class="line">[mariadb]</span><br><span class="line">name = MariaDB</span><br><span class="line">baseurl = http://yum.mariadb.org/10.3/centos7-amd64</span><br><span class="line">gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB</span><br><span class="line">gpgcheck=1</span><br></pre></td></tr></table></figure></p><p>如果这里的镜像不满足你的系统需求,可以通过<a href="http://downloads.mariadb.org/mariadb/repositories/去选择生成自己系统的" target="_blank" rel="noopener">http://downloads.mariadb.org/mariadb/repositories/去选择生成自己系统的</a><br>镜像配置</p><h4 id="安装命令"><a href="#安装命令" class="headerlink" title="安装命令"></a>安装命令</h4><p>执行命令,等待完成即可</p><p><code>yum -y install MariaDB-server MariaDB-client</code> </p><p>系统不同,命令请自行调整。</p><p>另,官方镜像下载比较慢,如需切换国内镜像请自己手动调整。</p><p>安装完成之后,用 <code>service mysql start</code> 命令进行启动</p><h4 id="设置密码"><a href="#设置密码" class="headerlink" title="设置密码"></a>设置密码</h4><p>执行如下命令并按照步骤设置,初始密码为空,新设置的密码是root的内网访问密码,建议将内网访问密码与<br>外网访问区分开,以防滥用。</p><p><code>mysql_secure_installation</code></p><p>执行完成之后,可以通过 <code>mysql -uroot -p</code> 并输入刚刚设置的密码进行验证密码是否设置成功</p><h3 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h3><h4 id="远程访问"><a href="#远程访问" class="headerlink" title="远程访问"></a>远程访问</h4><p>通过 <code>mysql -uroot -p</code> 进入数据库,创建用户</p><p><code>create user root@'%' identified by '123456';</code> </p><p>授权所有数据远程访问:</p><p><code>grant all privileges on *.* to root@'%' identified by '123456';</code></p><p>授权所有数据访问并具有授权权限:</p><p><code>grant all privileges on *.* to root@'%' identified by '123456' with grant option;</code></p><p>使授权生效:</p><p><code>flush privileges;</code></p><p>做好以上几步,可以通过远程客户端链接数据库了。记得打开服务器对应数据库端口的外网访问权限。</p><h4 id="更改数据存储目录"><a href="#更改数据存储目录" class="headerlink" title="更改数据存储目录"></a>更改数据存储目录</h4><p>更改目录前先停掉mysql服务,<code>service mysql stop</code></p><p>备份配置文件</p><p><code>cp /etc/my.cnf.d/server.cnf /etc/my.cnf.d/server.cnf.bak</code></p><p>增加数据目录</p><p><code>vim /etc/my.cnf.d/server.cnf</code><br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">[mysqld]</span><br><span class="line">datadir=/data/mysql</span><br></pre></td></tr></table></figure></p><p>赋予目录权限</p><p><code>chown -R mysql:mysql /data/mysql</code></p><p>复制数据文件,安装完成后的数据库存储位置是/var/lib/mysql</p><p><code>cp -a /var/lib/mysql/* /data/mysql</code></p><p>重新启动mysql服务,即可访问</p><h4 id="记录慢sql"><a href="#记录慢sql" class="headerlink" title="记录慢sql"></a>记录慢sql</h4><p>增加server配置</p><p><code>vim /etc/my.cnf.d/server.cnf</code><br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">[mysqld]</span><br><span class="line">datadir=/mnt/mysql/data</span><br><span class="line">slow_query_log=on</span><br><span class="line">slow_query_log_file=/data/mysql/logs/slow_query_log.log</span><br><span class="line">long_query_time=2</span><br></pre></td></tr></table></figure></p><p>这里一定要创建logs对应的文件夹,设置完成重启服务即可</p><p><code>service mysql restart</code></p><h4 id="特殊字符问题"><a href="#特殊字符问题" class="headerlink" title="特殊字符问题"></a>特殊字符问题</h4><p>微信昵称、富文本编辑等有特殊字符无法存储的问题,需要数据库支持utf8mb4字符集<br>这里需要注意一下,mysql的utf8字符集并不是我们通常所用的utf8,而是mysql自己定义的<br>一套字符集名字叫utf8,和我们通常所用的utf8字符集对应的是utf8mb4。</p><p>增加server配置</p><p><code>vim /etc/my.cnf.d/server.cnf</code><br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">[mysqld]</span><br><span class="line">datadir=/mnt/mysql/data</span><br><span class="line">slow_query_log=on</span><br><span class="line">slow_query_log_file=/data/mysql/logs/slow_query_log.log</span><br><span class="line">long_query_time=2</span><br><span class="line">character_set_server=utf8mb4</span><br></pre></td></tr></table></figure></p><p>设置完成重启服务即可</p><p><code>service mysql restart</code></p><h4 id="大小写敏感问题"><a href="#大小写敏感问题" class="headerlink" title="大小写敏感问题"></a>大小写敏感问题</h4><p>Linux下大小写敏感,可以统一成小写</p><p>增加server配置</p><p><code>vim /etc/my.cnf.d/server.cnf</code><br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">[mysqld]</span><br><span class="line">datadir=/mnt/mysql/data</span><br><span class="line">slow_query_log=on</span><br><span class="line">slow_query_log_file=/data/mysql/logs/slow_query_log.log</span><br><span class="line">long_query_time=2</span><br><span class="line">character_set_server=utf8mb4</span><br><span class="line">lower_case_table_names = 1</span><br></pre></td></tr></table></figure></p><p>设置完成重启服务即可</p><p>到此,安装和配置都完成了。</p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> Centos7 </tag>
<tag> Mariadb </tag>
<tag> Mysql </tag>
</tags>
</entry>
<entry>
<title>微信小程序调研-打开小程序的支持</title>
<link href="/2018/2018%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E8%B0%83%E7%A0%943/"/>
<url>/2018/2018%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E8%B0%83%E7%A0%943/</url>
<content type="html"><![CDATA[<h3 id="调研内容"><a href="#调研内容" class="headerlink" title="调研内容"></a>调研内容</h3><p>对打开小程序、APP的支持,有哪些功能?有哪些限制?有没有突破的方法?<br><a id="more"></a></p><h3 id="调研结果"><a href="#调研结果" class="headerlink" title="调研结果"></a>调研结果</h3><h4 id="小程序到小程序"><a href="#小程序到小程序" class="headerlink" title="小程序到小程序"></a>小程序到小程序</h4><p>一个小程序要跳转到另一个小程序,两个小程序必须绑定在同一公众号上,也可以跳回来</p><p>同一个小程序最多可以跳转到10个小程序里,这是微信限制,可能后期会逐渐放开</p><p>同一个小程序可关联最多500个公众号。</p><p>公众号可关联同主体的10个小程序及不同主体的3个小程序。</p><h5 id="小程序到APP"><a href="#小程序到APP" class="headerlink" title="小程序到APP"></a>小程序到APP</h5><p>此功能需要用户主动触发才能打开 APP,所以不由 API 来调用,需要用 open-type 的值设置为 launchApp 的 <button> 组件的点击来触发。</button></p><p>虽然可以打开,但是需要做很多工作,而且是特殊场景的使用。APP首先要集成相关SDK,用户通过APP分享消息卡片到微信,然后用户再通过点击消息卡片,进入小程序,通过按钮打开APP.<br>目前看到集成SDK然后进行分享,由原来的分享微信页面改为分享微信小程序,能一定程度上提升用户体验,打开APP的功能还是比较少见。<br>详情参见:<a href="https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/launchApp.html" target="_blank" rel="noopener">https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/launchApp.html</a></p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> Wechat </tag>
<tag> MiniProgram </tag>
</tags>
</entry>
<entry>
<title>微信小程序调研-网页支持</title>
<link href="/2018/2018%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E8%B0%83%E7%A0%942/"/>
<url>/2018/2018%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E8%B0%83%E7%A0%942/</url>
<content type="html"><![CDATA[<h3 id="调研内容"><a href="#调研内容" class="headerlink" title="调研内容"></a>调研内容</h3><p>对网页的支持,有哪些功能?有哪些限制?有没有突破的方法?</p><a id="more"></a><h3 id="调研结果"><a href="#调研结果" class="headerlink" title="调研结果"></a>调研结果</h3><h4 id="小程序必须认证"><a href="#小程序必须认证" class="headerlink" title="小程序必须认证"></a>小程序必须认证</h4><p>创建了两个小程序,通过对比发现,只有已经通过认证的小程序才可以访问外部网页。</p><h4 id="外部网页必须是HTTPS协议"><a href="#外部网页必须是HTTPS协议" class="headerlink" title="外部网页必须是HTTPS协议"></a>外部网页必须是HTTPS协议</h4><p>在认证过的小程序的设置中可以看到设置业务域名的选项,点击启用后可以配置相关业务域名。业务域名需要<br>先下载并配置验证文件的访问,然后再添加域名并提交修改请求。业务域名一年可以更改<br>50次,有一定限制。</p><p>对于老的业务系统可能都是采用http的协议,一种方式,重新部署一份儿,分配一套新的域名,<br>另一种就是做转发,将所有http请求对应的都转发到https上来,一定程度上能解决<br>网址不是https的。</p><p>另外https协议收费也比较可观,前期可以通过阿里云、腾讯云平台获得一个免费的HTTPS证书。我们用的是<br>阿里云的,免费期限是一年,等快过期了可以进行更换,阿里云每个账号可以申请20个免费的。</p><h4 id="业务域名数量受限"><a href="#业务域名数量受限" class="headerlink" title="业务域名数量受限"></a>业务域名数量受限</h4><p>每个认证的小程序可以关联20个业务域名,在更改次数限制之下,可以随意改动,只需要保证<br>是https即可。</p><h4 id="JSSDK被阉割"><a href="#JSSDK被阉割" class="headerlink" title="JSSDK被阉割"></a>JSSDK被阉割</h4><p>通过文档:<a href="https://developers.weixin.qq.com/miniprogram/dev/component/web-view.html" target="_blank" rel="noopener">web-view标签</a> 可以看到一些JSSDK的接口,在小程序打开的网页里是不能使用相关的<br>JSSDK方法的。</p><p>跳转:小程序可以跳转到网页,也可以跳转回小程序。</p><p>微信授权没有问题,已经测过了。</p><h4 id="不支持网页自带支付"><a href="#不支持网页自带支付" class="headerlink" title="不支持网页自带支付"></a>不支持网页自带支付</h4><p>因为JSSDK被阉割的部分包含支付的方法,所以直接通过微信网页的支付功能支付是调不起来对应的微信支付的,具体的解决办法放到支付的调研里进行详细说。</p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> Wechat </tag>
<tag> MiniProgram </tag>
</tags>
</entry>
<entry>
<title>微信小程序调研-公众号的支持</title>
<link href="/2018/2018%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E8%B0%83%E7%A0%941/"/>
<url>/2018/2018%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E8%B0%83%E7%A0%941/</url>
<content type="html"><![CDATA[<h3 id="调研内容"><a href="#调研内容" class="headerlink" title="调研内容"></a>调研内容</h3><p>对公众号的支持,有哪些功能?有哪些限制?有没有突破的方法?<br><a id="more"></a></p><h3 id="调研结果"><a href="#调研结果" class="headerlink" title="调研结果"></a>调研结果</h3><h4 id="导流"><a href="#导流" class="headerlink" title="导流"></a>导流</h4><p>最重要的就是导流功能了!导流分两块,一个是小程序导流给公众号、其他小程序、应用网页等。</p><h5 id="小程序到公众号"><a href="#小程序到公众号" class="headerlink" title="小程序到公众号"></a>小程序到公众号</h5><p>小程序是即用即走,推送内容也必须是用户提交表单之后的七天内,如果超出七天,那就很难到达用户。<br>所以如何唤起小程序,如何让用户沉淀下来是业务开发需要解决的一个重点问题。</p><p>简单的办法就是引导用户关注公众号,可以通过公众号唤起小程序的使用,同时达到对公众号导流的目的。<br>这个功能需要公众号先进行认证,然后在设置页面的选项里打开相关按钮,当用户进入小程序之后,可以加载对应的<br>关注组件,方便用户关注。这个地方需要注意的是,这个关注的必须是小程序同一主体的公众号,不同主体的不行。</p><h5 id="公众号到小程序"><a href="#公众号到小程序" class="headerlink" title="公众号到小程序"></a>公众号到小程序</h5><p>同一个小程序可以绑定到500个公众号上,需要公众号在管理后台申请并作关联操作,填上小程序的APPID<br>,然后小程序的管理员会收到绑定邀请,审核通过后就绑定完成了。这样操作之后,小程序可以配置在微信<br>公众号的菜单上,可以内嵌到公众号的文章里。前提是小程序必须正式上线了。</p><h4 id="用户打通"><a href="#用户打通" class="headerlink" title="用户打通"></a>用户打通</h4><p>用户打通是另外一个重要功能。微信生态里最重要的之一就是用户数据。什么样的用户数据最有效最有用?<br>能根据用户信息多维度判断一个用户,形成用户画像,完成用户认知。<br>如何使用户更丰满更真实?那就是获取足够多的用户信息,通过不同的数据交叉获得用户的真实行为和偏好。</p><h5 id="打通同一主体"><a href="#打通同一主体" class="headerlink" title="打通同一主体"></a>打通同一主体</h5><p>同一主体的比较好说,直接通过开放平台或者虚拟开放平台将两个账号绑定在一起就可以通过微信的unionId进行账号打通了。</p><h5 id="打通不同主体"><a href="#打通不同主体" class="headerlink" title="打通不同主体"></a>打通不同主体</h5><p>不同主体就比较麻烦,只能是曲线救国。通过跳转的时候传参数、用户标识等,可以将两个关联在同一公众号上的小程序数据打通,然后对应的小程序可以和<br>对应的公众号账号打通。可以在打开微信网页的时候传参数说明是哪个公众号、小程序来的,以此来打通用户。还有一种方式就是通过手机号认证、比对,<br>手机号相同的则视为同一自然人,也是一种办法。<br>这种打通账号的方式可以说一定上突破了微信的限制,但同时这个数据也会存在一些垃圾数据,不准确的情况。</p><p>还有其他的内容,今天就先不说了,后面再补充。</p><p>今天是1024程序员节呢,祝大家开心快乐有梦想有奔头!</p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> Wechat </tag>
<tag> MiniProgram </tag>
</tags>
</entry>
<entry>
<title>微信小程序调研-概述</title>
<link href="/2018/2018%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E8%B0%83%E7%A0%940/"/>
<url>/2018/2018%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E8%B0%83%E7%A0%940/</url>
<content type="html"><![CDATA[<h3 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h3><p>最近公司要做的一些产品想用小程序来做前端,所以做了一些调研。</p><a id="more"></a><h3 id="场景"><a href="#场景" class="headerlink" title="场景"></a>场景</h3><p>主要用来连接多个公众号和多个应用及服务,在微信生态里,并且这些公众号很可能不是同一主体,服务有各种各样的形式。<br>通过小程序可以打通多个小程序,以及其他微信网页服务、非微信网页服务,甚至可以打开APP,APP也可以打开小程序</p><p>所以,微信小程序比网页接入微信JSSDK要强大不少,而且在体验方面也会成为一个亮点。</p><h3 id="调研内容"><a href="#调研内容" class="headerlink" title="调研内容"></a>调研内容</h3><ul><li>公众号的支持</li><li>打开微信网页的支持</li><li>打开小程序的支持</li><li>支付的支持</li></ul>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> Wechat </tag>
<tag> MiniProgram </tag>
</tags>
</entry>
<entry>
<title>使用npm小技巧</title>
<link href="/2018/2018%E4%BD%BF%E7%94%A8npm%E5%B0%8F%E6%8A%80%E5%B7%A7/"/>
<url>/2018/2018%E4%BD%BF%E7%94%A8npm%E5%B0%8F%E6%8A%80%E5%B7%A7/</url>
<content type="html"><![CDATA[<h3 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h3><p>使用npm经常会遇到加载某个依赖加载不了,所以需要用国内的淘宝镜像</p><p>然而,将npm改成cnpm是极不习惯的,所以看到nrm就赶紧记下来了,极是好用!<br><a id="more"></a></p><h3 id="安装使用"><a href="#安装使用" class="headerlink" title="安装使用"></a>安装使用</h3><h4 id="安装nrm"><a href="#安装nrm" class="headerlink" title="安装nrm"></a>安装nrm</h4><p><code>npm install nrm -g --registry=https://registry.npm.taobao.org</code></p><h4 id="查看镜像"><a href="#查看镜像" class="headerlink" title="查看镜像"></a>查看镜像</h4><p><code>nrm ls</code></p><p>结果如下<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">* npm ---- https://registry.npmjs.org/</span><br><span class="line"> cnpm --- http://r.cnpmjs.org/</span><br><span class="line"> taobao - https://registry.npm.taobao.org/</span><br><span class="line"> nj ----- https://registry.nodejitsu.com/</span><br><span class="line"> rednpm - http://registry.mirror.cqupt.edu.cn/</span><br><span class="line"> npmMirror https://skimdb.npmjs.com/registry/</span><br><span class="line"> edunpm - http://registry.enpmjs.org/</span><br></pre></td></tr></table></figure></p><h3 id="使用镜像"><a href="#使用镜像" class="headerlink" title="使用镜像"></a>使用镜像</h3><p><code>nrm use taobao</code></p><p>通过命令<code>nrm ls</code>可以看到,镜像已经是taobao了<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"> npm ---- https://registry.npmjs.org/</span><br><span class="line"> cnpm --- http://r.cnpmjs.org/</span><br><span class="line">* taobao - https://registry.npm.taobao.org/</span><br><span class="line"> nj ----- https://registry.nodejitsu.com/</span><br><span class="line"> rednpm - http://registry.mirror.cqupt.edu.cn/</span><br><span class="line"> npmMirror https://skimdb.npmjs.com/registry/</span><br><span class="line"> edunpm - http://registry.enpmjs.org/</span><br></pre></td></tr></table></figure></p><p>接下来就可以正常用npm安装依赖了,都很方便。</p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> NPM </tag>
</tags>
</entry>
<entry>
<title>一图分析小程序-人民社区lite</title>
<link href="/2018/2018%E4%B8%80%E5%9B%BE%E5%88%86%E6%9E%90%E5%B0%8F%E7%A8%8B%E5%BA%8F-%E4%BA%BA%E6%B0%91%E7%A4%BE%E5%8C%BAlite/"/>
<url>/2018/2018%E4%B8%80%E5%9B%BE%E5%88%86%E6%9E%90%E5%B0%8F%E7%A8%8B%E5%BA%8F-%E4%BA%BA%E6%B0%91%E7%A4%BE%E5%8C%BAlite/</url>
<content type="html"><![CDATA[<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>对小程序-人民社区lite的前后端进行了简单的分析<br><a id="more"></a></p><h2 id="思维导图"><a href="#思维导图" class="headerlink" title="思维导图"></a>思维导图</h2><p><img src="/uploads/2018/人民社区.jpg" alt="人民社区"></p>]]></content>
<categories>
<category> 产品 </category>
</categories>
<tags>
<tag> Wechat </tag>
<tag> MiniProgram </tag>
</tags>
</entry>
<entry>
<title>使用阿里云RAM的子账号管理MQ服务</title>
<link href="/2017/152-using-aliyun-mq/"/>
<url>/2017/152-using-aliyun-mq/</url>
<content type="html"><![CDATA[<p>登录Aliyun主账号,进入访问控制页面,点击【用户管理】,选择右上角的【新建用户】</p><p><img src="/uploads/2017/create_1_user.png" alt=""></p><p>创建完成后【管理】用户,找到用户AccessKey那一列,选择创建AccessKey并将相关参数保存,结果如下:<br>这个参数在后面访问MQ服务的时候会用到。</p><p><img src="/uploads/2017/create_access_key.png" alt=""></p><p>授权用户使用mq的权限,如下图:</p><p><img src="/uploads/2017/grant_mq_privilage.png" alt=""></p><p>开启中间件消息队列服务(MQ),创建Topic并申请发布,申请订阅,定义好对应的标识。基本流程如下:</p><p><img src="/uploads/2017/mq_create_new_topic.png" alt=""><br><img src="/uploads/2017/mq_apply_for_producer.png" alt=""><br><img src="/uploads/2017/mq_apply_for_consumer.png" alt=""><br><img src="/uploads/2017/mq_grant_for_sub_account.png" alt=""></p><p>接下来就是按照对应Producer、Consumer集成方式和接入点进行接入,完成基本配置了。<br>如果所有的你都做了,最后一步授权忘了做,这很可能无法接入,会报错。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Exception in thread "main" com.aliyun.openservices.ons.api.exception.ONSClientException: Receive a broker exception, Topi=kaoshi, msgId=null, com.aliyun.openservices.ons.api.impl.authority.exception.AuthenticationException: valid resource owner failed. maybe the resource kaoshi not created, com.alibaba.ons.open.auth.validator.PermissionValidator.check(PermissionValidator.java:66)</span><br><span class="line">See http://docs.aliyun.com/cn#/pub/ons/faq/exceptions&broker_response_exception for further details.</span><br><span class="line">at com.aliyun.openservices.ons.api.impl.rocketmq.ProducerImpl.checkProducerException(ProducerImpl.java:198)</span><br><span class="line">at com.aliyun.openservices.ons.api.impl.rocketmq.ProducerImpl.send(ProducerImpl.java:107)</span><br><span class="line">at com.ksxing.tmp.MqTest.main(MqTest.java:38)</span><br></pre></td></tr></table></figure></p><p>话说回来,要想相对安全的使用阿里云,真的要好好研究一下这个RAM授权机制,所以有时间还得巴拉巴拉文章!<br><a href="https://ram.console.aliyun.com" target="_blank" rel="noopener">https://ram.console.aliyun.com</a></p><hr><p>简单记录,有待深入挖坑!欢迎留言交流!</p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> Aliyun-RAM </tag>
<tag> MQ </tag>
</tags>
</entry>
<entry>
<title>Spring Boot Actuator显示更多信息</title>
<link href="/2017/151-spring-boot-actuator-more-info/"/>
<url>/2017/151-spring-boot-actuator-more-info/</url>
<content type="html"><![CDATA[<p>通过<a href="http://localhost:8100/health" target="_blank" rel="noopener">http://localhost:8100/health</a> 访问监控信息发现只有有限的信息,如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> "description": "Spring Cloud Eureka Discovery Client",</span><br><span class="line"> "status": "UP"</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>只展示了注册中心Eureka的信息。</p><p>经过阅读文档发现,新版本当中,actuator增加了安全机制,需要在配置文件中添加参数:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">management:</span><br><span class="line"> security:</span><br><span class="line"> enabled: false</span><br></pre></td></tr></table></figure><p>默认为true,需要校验权限才能访问/env、/mappings、 /beans,这里关闭后重新启动就可以看到很多health 的信息了。更多配置需要参考:<a href="https://docs.spring.io/spring-boot/docs/1.5.7.RELEASE/reference/htmlsingle/#production-ready" target="_blank" rel="noopener">https://docs.spring.io/spring-boot/docs/1.5.7.RELEASE/reference/htmlsingle/#production-ready</a></p><p>访问<a href="http://localhost:8100/health" target="_blank" rel="noopener">http://localhost:8100/health</a> 获得如下数据:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> "description": "Spring Cloud Eureka Discovery Client",</span><br><span class="line"> "status": "UP",</span><br><span class="line"> "discoveryComposite": {</span><br><span class="line"> "description": "Spring Cloud Eureka Discovery Client",</span><br><span class="line"> "status": "UP",</span><br><span class="line"> "discoveryClient": {</span><br><span class="line"> "description": "Spring Cloud Eureka Discovery Client",</span><br><span class="line"> "status": "UP",</span><br><span class="line"> "services": [</span><br><span class="line"> "itmuch-customer-movie",</span><br><span class="line"> "itmuch-provider-user"</span><br><span class="line"> ]</span><br><span class="line"> },</span><br><span class="line"> "eureka": {</span><br><span class="line"> "description": "Remote status from Eureka server",</span><br><span class="line"> "status": "UP",</span><br><span class="line"> "applications": {</span><br><span class="line"> "ITMUCH-CUSTOMER-MOVIE": 1,</span><br><span class="line"> "ITMUCH-PROVIDER-USER": 1</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> },</span><br><span class="line"> "diskSpace": {</span><br><span class="line"> "status": "UP",</span><br><span class="line"> "total": 164282499072,</span><br><span class="line"> "free": 151694168064,</span><br><span class="line"> "threshold": 10485760</span><br><span class="line"> },</span><br><span class="line"> "refreshScope": {</span><br><span class="line"> "status": "UP"</span><br><span class="line"> },</span><br><span class="line"> "hystrix": {</span><br><span class="line"> "status": "UP"</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>更多参数设置参考:<a href="https://segmentfault.com/a/1190000004318360?_ea=568366" target="_blank" rel="noopener">https://segmentfault.com/a/1190000004318360?_ea=568366</a></p><hr><p>简单记录,有待深入挖坑!欢迎留言交流!</p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> Spring Boot </tag>
<tag> Actuator </tag>
</tags>
</entry>
<entry>
<title>搭建一个Eureka的集群</title>
<link href="/2017/150-simple-eureka-ha/"/>
<url>/2017/150-simple-eureka-ha/</url>
<content type="html"><![CDATA[<p>根据周立的Spring Cloud & Docker那本书学习Eureka集群搭建,含实例代码</p><p>版本如下:</p><p>Spring Boot 1.5.6.RELEASE</p><p>Spring Cloud Camden.SR7</p><p>JDK 1.8</p><h2 id="配置Eureka-Server"><a href="#配置Eureka-Server" class="headerlink" title="配置Eureka Server"></a>配置Eureka Server</h2><h3 id="配置pom-xml"><a href="#配置pom-xml" class="headerlink" title="配置pom.xml"></a>配置pom.xml</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><?xml version="1.0" encoding="UTF-8"?></span><br><span class="line"><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"</span><br><span class="line">xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"></span><br><span class="line"><modelVersion>4.0.0</modelVersion></span><br><span class="line"><groupId>com.sss</groupId></span><br><span class="line"><artifactId>itmuch-discovery-eureka</artifactId></span><br><span class="line"><version>0.0.1-SNAPSHOT</version></span><br><span class="line"><packaging>jar</packaging></span><br><span class="line"><name>itmuch-discovery-eureka</name></span><br><span class="line"><description>Demo project for Spring Boot</description></span><br><span class="line"><parent></span><br><span class="line"><groupId>org.springframework.boot</groupId></span><br><span class="line"><artifactId>spring-boot-starter-parent</artifactId></span><br><span class="line"><version>1.5.6.RELEASE</version></span><br><span class="line"><relativePath/> <!-- lookup parent from repository --></span><br><span class="line"></parent></span><br><span class="line"><properties></span><br><span class="line"><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></span><br><span class="line"><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding></span><br><span class="line"><java.version>1.8</java.version></span><br><span class="line"><spring-cloud.version>Camden.SR7</spring-cloud.version></span><br><span class="line"></properties></span><br><span class="line"></span><br><span class="line"><dependencies></span><br><span class="line"><!--Eureka注册中心--></span><br><span class="line"><dependency></span><br><span class="line"><groupId>org.springframework.cloud</groupId></span><br><span class="line"><artifactId>spring-cloud-starter-eureka-server</artifactId></span><br><span class="line"></dependency></span><br><span class="line"></span><br><span class="line"> <dependency></span><br><span class="line"> <groupId>org.springframework.boot</groupId></span><br><span class="line"> <artifactId>spring-boot-starter-test</artifactId></span><br><span class="line"> </dependency></span><br><span class="line"></dependencies></span><br><span class="line"></span><br><span class="line"><dependencyManagement></span><br><span class="line"><dependencies></span><br><span class="line"><dependency></span><br><span class="line"><groupId>org.springframework.cloud</groupId></span><br><span class="line"><artifactId>spring-cloud-dependencies</artifactId></span><br><span class="line"><version>${spring-cloud.version}</version></span><br><span class="line"><type>pom</type></span><br><span class="line"><scope>import</scope></span><br><span class="line"></dependency></span><br><span class="line"></dependencies></span><br><span class="line"></dependencyManagement></span><br><span class="line"><build></span><br><span class="line"><plugins></span><br><span class="line"><plugin></span><br><span class="line"><groupId>org.springframework.boot</groupId></span><br><span class="line"><artifactId>spring-boot-maven-plugin</artifactId></span><br><span class="line"></plugin></span><br><span class="line"></plugins></span><br><span class="line"></build></span><br><span class="line"></project></span><br></pre></td></tr></table></figure><h3 id="配置application-yml"><a href="#配置application-yml" class="headerlink" title="配置application.yml"></a>配置application.yml</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">spring:</span><br><span class="line"> application:</span><br><span class="line"> name: itmuch-discovery-eureka</span><br><span class="line"> profiles:</span><br><span class="line"> active: peer1 #创建3个项目分别peer2,peer3</span><br><span class="line"></span><br><span class="line">---</span><br><span class="line">server:</span><br><span class="line"> port: 8762</span><br><span class="line">eureka:</span><br><span class="line"> client:</span><br><span class="line"> service-url:</span><br><span class="line"> defaultZone: http://peer1:8761/eureka/,http://peer3:8763/eureka/</span><br><span class="line"> instance:</span><br><span class="line"> hostname: peer2</span><br><span class="line"> server:</span><br><span class="line"> enable-self-preservation: false</span><br><span class="line">spring:</span><br><span class="line"> profiles: peer2</span><br><span class="line"></span><br><span class="line">---</span><br><span class="line">server:</span><br><span class="line"> port: 8761</span><br><span class="line">eureka:</span><br><span class="line"> client:</span><br><span class="line"> service-url:</span><br><span class="line"> defaultZone: http://peer2:8762/eureka/,http://peer3:8763/eureka/</span><br><span class="line"> instance:</span><br><span class="line"> hostname: peer1</span><br><span class="line"> server:</span><br><span class="line"> enable-self-preservation: false</span><br><span class="line">spring:</span><br><span class="line"> profiles: peer1</span><br><span class="line"></span><br><span class="line">---</span><br><span class="line">server:</span><br><span class="line"> port: 8763</span><br><span class="line">eureka:</span><br><span class="line"> client:</span><br><span class="line"> service-url:</span><br><span class="line"> defaultZone: http://peer1:8761/eureka/,http://peer2:8762/eureka/</span><br><span class="line"> instance:</span><br><span class="line"> hostname: peer3</span><br><span class="line"> server:</span><br><span class="line"> enable-self-preservation: false</span><br><span class="line">spring:</span><br><span class="line"> profiles: peer3</span><br></pre></td></tr></table></figure><p>注意这里:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">server:</span><br><span class="line"> enable-self-preservation: false</span><br></pre></td></tr></table></figure><p>增加这个参数后的Eureka Server将关闭自我保护机制,这个机制在线上一般不是这样极端的关闭,而是通过调整阀值,这里为了测试服务是否能正常注销故意关闭的。如果不关闭,Eureka虽然发现服务down掉了,但是因为服务是单点的,所以会保留实例的注册记录在表内,参考我在http:///Spring4all.com 提的问题:<a href="http://spring4all.com/question/446" target="_blank" rel="noopener">http://spring4all.com/question/446</a></p><h3 id="修改HOST"><a href="#修改HOST" class="headerlink" title="修改HOST"></a>修改HOST</h3><p>增加:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">127.0.0.1 peer1 peer2 peer3</span><br></pre></td></tr></table></figure><h3 id="调整Application-java"><a href="#调整Application-java" class="headerlink" title="调整Application.java"></a>调整Application.java</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">import org.springframework.boot.SpringApplication;</span><br><span class="line">import org.springframework.boot.autoconfigure.SpringBootApplication;</span><br><span class="line">import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;</span><br><span class="line"></span><br><span class="line">@SpringBootApplication</span><br><span class="line">@EnableEurekaServer</span><br><span class="line">public class ItmuchDiscoveryEurekaApplication {</span><br><span class="line"></span><br><span class="line">public static void main(String[] args) {</span><br><span class="line">SpringApplication.run(ItmuchDiscoveryEurekaApplication.class, args);</span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>配置完成上边这些,项目名称分别是itmuch-discovery-eureka,itmuch-discovery-eureka-ha,itmuch-discovery-eureka-ha2,然后在IDE里启动即可</p><h2 id="创建服务并注册"><a href="#创建服务并注册" class="headerlink" title="创建服务并注册"></a>创建服务并注册</h2><h3 id="创建Provider-User服务"><a href="#创建Provider-User服务" class="headerlink" title="创建Provider User服务"></a>创建Provider User服务</h3><p>参考项目itmuch-provider-user项目,</p><h4 id="配置pom-xml-1"><a href="#配置pom-xml-1" class="headerlink" title="配置pom.xml"></a>配置pom.xml</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br></pre></td><td class="code"><pre><span class="line"><?xml version="1.0" encoding="UTF-8"?></span><br><span class="line"><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"</span><br><span class="line">xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"></span><br><span class="line"><modelVersion>4.0.0</modelVersion></span><br><span class="line"></span><br><span class="line"><groupId>com.sss</groupId></span><br><span class="line"><artifactId>itmuch-provider-user</artifactId></span><br><span class="line"><version>0.0.1-SNAPSHOT</version></span><br><span class="line"><packaging>jar</packaging></span><br><span class="line"></span><br><span class="line"><name>itmuch-provider-user</name></span><br><span class="line"><description>Demo project for Spring Boot</description></span><br><span class="line"></span><br><span class="line"><parent></span><br><span class="line"><groupId>org.springframework.boot</groupId></span><br><span class="line"><artifactId>spring-boot-starter-parent</artifactId></span><br><span class="line"><version>1.5.6.RELEASE</version></span><br><span class="line"><relativePath/> <!-- lookup parent from repository --></span><br><span class="line"></parent></span><br><span class="line"></span><br><span class="line"><properties></span><br><span class="line"><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></span><br><span class="line"><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding></span><br><span class="line"><java.version>1.8</java.version></span><br><span class="line"></properties></span><br><span class="line"></span><br><span class="line"><dependencies></span><br><span class="line"><dependency></span><br><span class="line"><groupId>org.springframework.boot</groupId></span><br><span class="line"><artifactId>spring-boot-starter-web</artifactId></span><br><span class="line"></dependency></span><br><span class="line"><dependency></span><br><span class="line"><groupId>org.springframework.boot</groupId></span><br><span class="line"><artifactId>spring-boot-starter-data-jpa</artifactId></span><br><span class="line"></dependency></span><br><span class="line"><!-- 健康检查 --></span><br><span class="line"><dependency></span><br><span class="line"><groupId>org.springframework.boot</groupId></span><br><span class="line"><artifactId>spring-boot-starter-actuator</artifactId></span><br><span class="line"></dependency></span><br><span class="line"><!-- 注册服务 --></span><br><span class="line"><dependency></span><br><span class="line"><groupId>org.springframework.cloud</groupId></span><br><span class="line"><artifactId>spring-cloud-starter-eureka</artifactId></span><br><span class="line"></dependency></span><br><span class="line"><dependency></span><br><span class="line"><groupId>com.h2database</groupId></span><br><span class="line"><artifactId>h2</artifactId></span><br><span class="line"></dependency></span><br><span class="line"></span><br><span class="line"><dependency></span><br><span class="line"><groupId>org.projectlombok</groupId></span><br><span class="line"><artifactId>lombok</artifactId></span><br><span class="line"><optional>true</optional></span><br><span class="line"></dependency></span><br><span class="line"><dependency></span><br><span class="line"><groupId>org.springframework.boot</groupId></span><br><span class="line"><artifactId>spring-boot-starter-test</artifactId></span><br><span class="line"><scope>test</scope></span><br><span class="line"></dependency></span><br><span class="line"></dependencies></span><br><span class="line"><dependencyManagement></span><br><span class="line"><dependencies></span><br><span class="line"><dependency></span><br><span class="line"><groupId>org.springframework.cloud</groupId></span><br><span class="line"><artifactId>spring-cloud-dependencies</artifactId></span><br><span class="line"><version>Camden.SR7</version></span><br><span class="line"><type>pom</type></span><br><span class="line"><scope>import</scope></span><br><span class="line"></dependency></span><br><span class="line"></dependencies></span><br><span class="line"></dependencyManagement></span><br><span class="line"><build></span><br><span class="line"><plugins></span><br><span class="line"><plugin></span><br><span class="line"><groupId>org.springframework.boot</groupId></span><br><span class="line"><artifactId>spring-boot-maven-plugin</artifactId></span><br><span class="line"></plugin></span><br><span class="line"></plugins></span><br><span class="line"></build></span><br><span class="line"></project></span><br></pre></td></tr></table></figure><h4 id="配置Application-java"><a href="#配置Application-java" class="headerlink" title="配置Application.java"></a>配置Application.java</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">import org.springframework.boot.SpringApplication;</span><br><span class="line">import org.springframework.boot.autoconfigure.SpringBootApplication;</span><br><span class="line">import org.springframework.cloud.client.discovery.EnableDiscoveryClient;</span><br><span class="line"></span><br><span class="line">@EnableDiscoveryClient</span><br><span class="line">@SpringBootApplication</span><br><span class="line">public class Application {</span><br><span class="line"></span><br><span class="line">public static void main(String[] args) {</span><br><span class="line">SpringApplication.run(Application.class, args);</span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="配置application-yml-1"><a href="#配置application-yml-1" class="headerlink" title="配置application.yml"></a>配置application.yml</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">server:</span><br><span class="line"> port: 8000</span><br><span class="line">spring:</span><br><span class="line"> application:</span><br><span class="line"> name: itmuch-provider-user</span><br><span class="line"> jpa:</span><br><span class="line"> generate-ddl: false</span><br><span class="line"> show-sql: true</span><br><span class="line"> hibernate:</span><br><span class="line"> ddl-auto: none</span><br><span class="line"> datasource: # 指定数据源</span><br><span class="line"> platform: h2 # 指定数据源类型</span><br><span class="line"> schema: classpath:schema.sql # 指定h2数据库的建表脚本</span><br><span class="line"> data: classpath:data.sql # 指定h2数据库的数据脚本</span><br><span class="line">logging: # 配置日志级别,让hibernate打印出执行的SQL</span><br><span class="line"> level:</span><br><span class="line"> root: INFO</span><br><span class="line"> org.hibernate: INFO</span><br><span class="line"> org.hibernate.type.descriptor.sql.BasicBinder: TRACE</span><br><span class="line"> org.hibernate.type.descriptor.sql.BasicExtractor: TRACE</span><br><span class="line"></span><br><span class="line">#监控的信息配置 http://{host}:{port}/info</span><br><span class="line">info:</span><br><span class="line"> app:</span><br><span class="line"> name: @project.artifactId@</span><br><span class="line"> encoding: @project.build.sourceEncoding@</span><br><span class="line"> java:</span><br><span class="line"> source: @java.version@</span><br><span class="line"> target: @java.version@</span><br><span class="line"></span><br><span class="line">#注册服务</span><br><span class="line">eureka:</span><br><span class="line"> client:</span><br><span class="line"> service-url:</span><br><span class="line"> defaultZone: http://peer1:8761/eureka/,http://peer2:8762/eureka/,http://peer3:8763/eureka/</span><br><span class="line"> instance:</span><br><span class="line"> prefer-ip-address: true</span><br></pre></td></tr></table></figure><p>创建配置完成后启动服务,刷新Eureka的页面即可看到对应服务已经存在。</p><h3 id="创建Customer-Movie服务"><a href="#创建Customer-Movie服务" class="headerlink" title="创建Customer Movie服务"></a>创建Customer Movie服务</h3><p>该服务调用Provider User服务,参考项目itmuch-customer-movie.</p><h4 id="配置pom-xml-2"><a href="#配置pom-xml-2" class="headerlink" title="配置pom.xml"></a>配置pom.xml</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br></pre></td><td class="code"><pre><span class="line"><?xml version="1.0" encoding="UTF-8"?></span><br><span class="line"><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"</span><br><span class="line">xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"></span><br><span class="line"><modelVersion>4.0.0</modelVersion></span><br><span class="line"></span><br><span class="line"><groupId>com.sss</groupId></span><br><span class="line"><artifactId>itmuch-consumer-movie</artifactId></span><br><span class="line"><version>0.0.1-SNAPSHOT</version></span><br><span class="line"><packaging>jar</packaging></span><br><span class="line"></span><br><span class="line"><name>itmuch-consumer-movie</name></span><br><span class="line"><description>Demo project for Spring Boot</description></span><br><span class="line"></span><br><span class="line"><parent></span><br><span class="line"><groupId>org.springframework.boot</groupId></span><br><span class="line"><artifactId>spring-boot-starter-parent</artifactId></span><br><span class="line"><version>1.5.6.RELEASE</version></span><br><span class="line"><relativePath/> <!-- lookup parent from repository --></span><br><span class="line"></parent></span><br><span class="line"></span><br><span class="line"><properties></span><br><span class="line"><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></span><br><span class="line"><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding></span><br><span class="line"><java.version>1.8</java.version></span><br><span class="line"><spring.cloud.version>Camden.SR7</spring.cloud.version></span><br><span class="line"></properties></span><br><span class="line"></span><br><span class="line"><dependencies></span><br><span class="line"><dependency></span><br><span class="line"><groupId>org.springframework.boot</groupId></span><br><span class="line"><artifactId>spring-boot-starter-web</artifactId></span><br><span class="line"></dependency></span><br><span class="line"><dependency></span><br><span class="line"><groupId>org.springframework.boot</groupId></span><br><span class="line"><artifactId>spring-boot-starter-actuator</artifactId></span><br><span class="line"></dependency></span><br><span class="line"> <dependency></span><br><span class="line"> <groupId>org.springframework.cloud</groupId></span><br><span class="line"> <artifactId>spring-cloud-starter-eureka</artifactId></span><br><span class="line"> </dependency></span><br><span class="line"><dependency></span><br><span class="line"><groupId>org.projectlombok</groupId></span><br><span class="line"><artifactId>lombok</artifactId></span><br><span class="line"><optional>true</optional></span><br><span class="line"></dependency></span><br><span class="line"><dependency></span><br><span class="line"><groupId>org.springframework.boot</groupId></span><br><span class="line"><artifactId>spring-boot-starter-test</artifactId></span><br><span class="line"><scope>test</scope></span><br><span class="line"></dependency></span><br><span class="line"></dependencies></span><br><span class="line"><dependencyManagement></span><br><span class="line"><dependencies></span><br><span class="line"><dependency></span><br><span class="line"><groupId>org.springframework.cloud</groupId></span><br><span class="line"><artifactId>spring-cloud-dependencies</artifactId></span><br><span class="line"><version>${spring.cloud.version}</version></span><br><span class="line"><type>pom</type></span><br><span class="line"><scope>import</scope></span><br><span class="line"></dependency></span><br><span class="line"></dependencies></span><br><span class="line"></dependencyManagement></span><br><span class="line"><build></span><br><span class="line"><plugins></span><br><span class="line"><plugin></span><br><span class="line"><groupId>org.springframework.boot</groupId></span><br><span class="line"><artifactId>spring-boot-maven-plugin</artifactId></span><br><span class="line"></plugin></span><br><span class="line"></plugins></span><br><span class="line"></build></span><br><span class="line"></project></span><br></pre></td></tr></table></figure><h4 id="配置Application-java-1"><a href="#配置Application-java-1" class="headerlink" title="配置Application.java"></a>配置Application.java</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">import org.springframework.boot.SpringApplication;</span><br><span class="line">import org.springframework.boot.autoconfigure.SpringBootApplication;</span><br><span class="line">import org.springframework.cloud.client.discovery.EnableDiscoveryClient;</span><br><span class="line">import org.springframework.context.annotation.Bean;</span><br><span class="line">import org.springframework.web.client.RestTemplate;</span><br><span class="line"></span><br><span class="line">@EnableDiscoveryClient</span><br><span class="line">@SpringBootApplication</span><br><span class="line">public class Application {</span><br><span class="line"></span><br><span class="line">@Bean</span><br><span class="line">public RestTemplate restTemplate(){</span><br><span class="line">return new RestTemplate();</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">public static void main(String[] args) {</span><br><span class="line">SpringApplication.run(Application.class, args);</span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="配置application-yml-2"><a href="#配置application-yml-2" class="headerlink" title="配置application.yml"></a>配置application.yml</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">server:</span><br><span class="line"> port: 8100</span><br><span class="line">spring:</span><br><span class="line"> application:</span><br><span class="line"> name: itmuch-customer-movie</span><br><span class="line">logging: # 配置日志级别,让hibernate打印出执行的SQL</span><br><span class="line"> level:</span><br><span class="line"> root: INFO</span><br><span class="line"> org.hibernate: INFO</span><br><span class="line"> org.hibernate.type.descriptor.sql.BasicBinder: TRACE</span><br><span class="line"> org.hibernate.type.descriptor.sql.BasicExtractor: TRACE</span><br><span class="line"></span><br><span class="line">#监控的信息配置 http://{host}:{port}/info</span><br><span class="line">info:</span><br><span class="line"> app:</span><br><span class="line"> name: @project.artifactId@</span><br><span class="line"> encoding: @project.build.sourceEncoding@</span><br><span class="line"> java:</span><br><span class="line"> source: @java.version@</span><br><span class="line"> target: @java.version@</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">#注册服务</span><br><span class="line">eureka:</span><br><span class="line"> client:</span><br><span class="line"> service-url:</span><br><span class="line"> defaultZone: http://peer1:8761/eureka/,http://peer2:8762/eureka/,http://peer3:8763/eureka/</span><br><span class="line"> instance:</span><br><span class="line"> prefer-ip-address: true</span><br></pre></td></tr></table></figure><p>创建配置完成后启动服务,刷新Eureka的页面即可看到对应服务已经存在。</p><p>至此:一个简单的Eureka服务已经搭建完成了,下面附送源码,可以直接在github上下载下来运行。</p><h2 id="附件"><a href="#附件" class="headerlink" title="附件"></a>附件</h2><p>传送门:<a href="https://github.com/icnws/eureka-simple-ha-demo" target="_blank" rel="noopener">https://github.com/icnws/eureka-simple-ha-demo</a> </p><hr><p>简单记录,有待深入挖坑!欢迎留言交流!</p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> Spring Cloud </tag>
<tag> Eureka </tag>
</tags>
</entry>
<entry>
<title>在Centos7中安装Nodejs服务</title>
<link href="/2017/149-nodejs-in-centos7/"/>
<url>/2017/149-nodejs-in-centos7/</url>
<content type="html"><![CDATA[<p>博客迁移到github之后,阿里云服务器闲置了,现在折腾一下,把博客同步到阿里云服务器</p><h3 id="集成工具安装"><a href="#集成工具安装" class="headerlink" title="集成工具安装"></a>集成工具安装</h3><p>由于是新的系统,需要执行安装一些常用的软件:</p><p><code>yum -y install gcc make gcc-c++ openssl-devel wget</code></p><h3 id="安装Nodejs"><a href="#安装Nodejs" class="headerlink" title="安装Nodejs"></a>安装Nodejs</h3><p>执行如下命令:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yum install nodejs</span><br></pre></td></tr></table></figure><p>遇到问题:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Error: Package: 1:nodejs-6.11.1-1.el7.x86_64 (epel)</span><br><span class="line"> Requires: libhttp_parser.so.2()(64bit)</span><br><span class="line">Error: Package: 1:nodejs-6.11.1-1.el7.x86_64 (epel)</span><br><span class="line"> Requires: http-parser >= 2.7.0</span><br><span class="line"> You could try using --skip-broken to work around the problem</span><br><span class="line"> You could try running: rpm -Va --nofiles --nodigest</span><br></pre></td></tr></table></figure><p>解决办法参考:<a href="https://github.com/Icinga/icinga-vagrant/issues/87" target="_blank" rel="noopener">https://github.com/Icinga/icinga-vagrant/issues/87</a></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yum -y install https://opensource.enda.eu/packages/http-parser-2.7.1-3.el7.x86_64.rpm</span><br></pre></td></tr></table></figure><p>再次执行<code>yum install nodejs</code>可以正常运行,安装完成,检查node版本</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">[root@xx xx]# node -v</span><br><span class="line">v6.11.1</span><br><span class="line">[root@xx xx]# npm -v</span><br><span class="line">3.10.10</span><br></pre></td></tr></table></figure><p>至此,安装完成,可以正常使用了!</p><hr><p>简单记录,有待深入挖坑!欢迎留言交流!</p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> Centos7 </tag>
<tag> Nodejs </tag>
</tags>
</entry>
<entry>
<title>在docker中安装Mariadb</title>
<link href="/2017/148-mariadb-in-docker/"/>
<url>/2017/148-mariadb-in-docker/</url>
<content type="html"><![CDATA[<p>简单使用Docker下安装Mariadb服务,基于Boot2Docker在windows下实现</p><h3 id="Boot2Docker的安装"><a href="#Boot2Docker的安装" class="headerlink" title="Boot2Docker的安装"></a>Boot2Docker的安装</h3><p>参考上一篇<a href="http://www.icnws.com/2017/147-redis-in-docker/">在docker中安装redis</a> 的前半部分</p><h3 id="下载Mariadb镜像"><a href="#下载Mariadb镜像" class="headerlink" title="下载Mariadb镜像"></a>下载Mariadb镜像</h3><p>用<code>docker pull mariadb</code>下载最新的mariadb镜像</p><p>下载镜像会慢一些,需要等待,完成之后,通过<code>docker images</code>命令就可以看到了。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE</span><br><span class="line">redis latest b77605993f64 6 weeks ago 105.9 MB</span><br><span class="line">mariadb latest b77605991234 9 weeks ago 375.9 MB</span><br></pre></td></tr></table></figure><h3 id="启动服务"><a href="#启动服务" class="headerlink" title="启动服务"></a>启动服务</h3><h4 id="运行容器"><a href="#运行容器" class="headerlink" title="运行容器"></a>运行容器</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run --name test-mariadb -e MYSQL_ROOT_PASSWORD=123456 -d mariadb</span><br></pre></td></tr></table></figure><p>docker命令 run 用–name指定容器的别名,mariadb是指容器的名称<br>MYSQL_ROOT_PASSWORD指定ROOT用户的密码</p><h4 id="端口映射1:"><a href="#端口映射1:" class="headerlink" title="端口映射1:"></a>端口映射1:</h4><p>docker 和虚拟机映射</p><p>将虚拟机的3306端口和docker的3306端口映射,port-mariadb是名称</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run -d -p 3306:3306 --name port-mariadb -e MYSQL_ROOT_PASSWORD=123456 -d mariadb</span><br></pre></td></tr></table></figure><h4 id="端口映射2:"><a href="#端口映射2:" class="headerlink" title="端口映射2:"></a>端口映射2:</h4><p>虚拟机和本机映射</p><p>打开VirtualBox找到boot2docker的虚拟机,打开设置、网络,找到【端口转发】,添加一条规则,宿主机3305和虚拟机的3306映射,如下</p><p><img src="/uploads/2017/docker-vertual-port-bind.jpg" alt=""></p><h4 id="启动服务:"><a href="#启动服务:" class="headerlink" title="启动服务:"></a>启动服务:</h4><p>这里需要启动两个服务,一个是mariadb本身的服务——test-mariadb,一个是docker和虚拟机映射服务——port-mariadb,启动方式如下<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">docker start test-mariadb</span><br><span class="line"></span><br><span class="line">docker start port-mariadb</span><br></pre></td></tr></table></figure></p><p>通过<code>docker ps -a</code>可以看到服务已经运行了<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ docker ps -a</span><br><span class="line">CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES</span><br><span class="line">3190d98286d0 mariadb "docker-entrypoint.sh" 22 minutes ago Up 22 minutes 0.0.0.0:3306->3306/tcp port-mariadb</span><br><span class="line">ce4e5c5cee70 mariadb "docker-entrypoint.sh" 43 minutes ago Up 26 minutes 3306/tcp test-mariadb</span><br></pre></td></tr></table></figure></p><p>至此,就可以通过宿主机本地的Sql客户端工具,配置127.0.0.1的3305端口进行访问了。<br>参考:<a href="https://mariadb.com/kb/en/the-mariadb-library/installing-and-using-mariadb-via-docker/" target="_blank" rel="noopener">https://mariadb.com/kb/en/the-mariadb-library/installing-and-using-mariadb-via-docker/</a></p><h3 id="另外"><a href="#另外" class="headerlink" title="另外"></a>另外</h3><p>附上自己写的docker下启动服务的脚本,每次启动docker后手动启动多麻烦<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"># start services</span><br><span class="line">docker start test-redis</span><br><span class="line">docker start port-redis</span><br><span class="line">docker start test-mariadb</span><br><span class="line">docker start port-mariadb</span><br><span class="line">#end start</span><br></pre></td></tr></table></figure></p><hr><p>简单记录,有待深入挖坑!欢迎留言交流!</p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> Docker </tag>
<tag> Mariadb </tag>
</tags>
</entry>
<entry>
<title>在docker中安装Redis</title>
<link href="/2017/147-redis-in-docker/"/>
<url>/2017/147-redis-in-docker/</url>
<content type="html"><![CDATA[<p>简单使用Docker下安装Redis服务,基于Boot2Docker在windows下实现</p><h3 id="下载软件"><a href="#下载软件" class="headerlink" title="下载软件"></a>下载软件</h3><p>当前环境是Windows 7,所以采用Docker的Windows安装版——Boot2Docker,官网如下:</p><p><a href="http://boot2docker.io/" target="_blank" rel="noopener">http://boot2docker.io/</a></p><p>下载地址(Github)如下:</p><p><a href="https://github.com/boot2docker/windows-installer/releases/download/v1.8.0/docker-install.exe" target="_blank" rel="noopener">https://github.com/boot2docker/windows-installer/releases/download/v1.8.0/docker-install.exe</a></p><h3 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h3><p>一路Next,全选(如果已经安装了Git客户端,这里就不用选择最后一项MSYS-git Unix tools了)、安装驱动,安装完成后会在桌面出现一个virtualBox的标,一个Docker的标,重启即可</p><h3 id="启动"><a href="#启动" class="headerlink" title="启动"></a>启动</h3><p>后双击Docker的图标,发现用sublimeText打开了,实际上是一个.sh文件,只好在git的命令行界面来执行,<code>./start.sh</code> 执行后会显示执行boot2docker的一系列初始化动作,生成密钥,配置,启动VM,分配IP等动作,执行完成后会显示“You can use ‘docker‘ …’’”的字样。这时候,我们在下面键入docker命令,会提示docker的相关命令提示,至此,docker的基本准备工作已经完成,打开VirtualBox会看到一个boot2docker的虚拟机在运行</p><h3 id="下载Redis镜像"><a href="#下载Redis镜像" class="headerlink" title="下载Redis镜像"></a>下载Redis镜像</h3><p>用<code>docker images</code>查看当前所拥有的docker镜像</p><p>用<code>docker search keywords</code>搜索通过关键词指定的镜像</p><p>用<code>docker ps -a</code>查看当前运行的服务</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES</span><br><span class="line">436284456b5a redis "docker-entrypoint.sh" 45 minutes ago Up 45 minutes 6379/tcp test-redis</span><br></pre></td></tr></table></figure><p>用<code>docker pull redis</code>下载最新的redis镜像</p><p>下载镜像会慢一些,需要等待,完成之后,通过<code>docker images</code>命令就可以看到了。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE</span><br><span class="line">redis latest b77605993f64 6 weeks ago 105.9 MB</span><br></pre></td></tr></table></figure><h3 id="启动服务"><a href="#启动服务" class="headerlink" title="启动服务"></a>启动服务</h3><h4 id="运行容器"><a href="#运行容器" class="headerlink" title="运行容器"></a>运行容器</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run --name test-redis redis</span><br></pre></td></tr></table></figure><p>docker命令 run 用–name指定容器的别名,redis是指容器的名称</p><h4 id="端口映射1:"><a href="#端口映射1:" class="headerlink" title="端口映射1:"></a>端口映射1:</h4><p>docker 和虚拟机映射</p><p>将虚拟机的6378端口和docker的6379端口映射,port-redis是名称</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run -d -p 6378:6379 --name port-redis redis</span><br></pre></td></tr></table></figure><h4 id="端口映射2:"><a href="#端口映射2:" class="headerlink" title="端口映射2:"></a>端口映射2:</h4><p>虚拟机和本机映射</p><p>打开VirtualBox找到boot2docker的虚拟机,打开设置、网络,找到【端口转发】,添加一条规则,宿主机6378和虚拟机的6378映射,如下</p><p><img src="/uploads/2017/docker-vertual-port-bind.jpg" alt=""></p><h4 id="启动服务:"><a href="#启动服务:" class="headerlink" title="启动服务:"></a>启动服务:</h4><p>这里需要启动两个服务,一个是redis本身的服务——test-redis,一个是docker和虚拟机映射服务——port-redis,启动方式如下<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">docker start test-redis</span><br><span class="line"></span><br><span class="line">docker start port-redis</span><br></pre></td></tr></table></figure></p><p>通过<code>docker ps -a</code>可以看到服务已经运行了<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ docker ps -a</span><br><span class="line">CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES</span><br><span class="line">e00ff120ecb1 redis "docker-entrypoint.sh" 16 hours ago Up 44 seconds 0.0.0.0:6378->6379/tcp port-redis</span><br><span class="line">436284456b5a redis "docker-entrypoint.sh" 16 hours ago Up About a minute 6379/tcp test-redis</span><br></pre></td></tr></table></figure></p><p>至此,就可以通过宿主机本地的RDM(Redis Desktop Manager)配置127.0.0.1的6378端口进行访问了。</p><hr><p>简单记录,有待深入挖坑!欢迎留言交流!</p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> Redis </tag>
<tag> Docker </tag>
</tags>
</entry>
<entry>
<title>Spring Boot整合Reids</title>
<link href="/2017/146-spring-boot-with-redis/"/>
<url>/2017/146-spring-boot-with-redis/</url>
<content type="html"><![CDATA[<p>终于还是用了Spring Boot,主要跑定时任务。上一次写的那个定时任务就是要用的。这次主要是在定时任务中更新缓存(Redis)数据。</p><h3 id="添加依赖"><a href="#添加依赖" class="headerlink" title="添加依赖"></a>添加依赖</h3><p>当前版本是SpringBoot 1.5.4.RELEASE</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><!-- Redis --></span><br><span class="line"><dependency></span><br><span class="line"> <groupId>org.springframework.boot</groupId></span><br><span class="line"> <artifactId>spring-boot-starter-data-redis</artifactId></span><br><span class="line"></dependency></span><br></pre></td></tr></table></figure><p>这里只需要添加这一个依赖就好了,点进去可以看到相关依赖的信息:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><dependencies></span><br><span class="line"><dependency></span><br><span class="line"><groupId>org.springframework.boot</groupId></span><br><span class="line"><artifactId>spring-boot-starter</artifactId></span><br><span class="line"></dependency></span><br><span class="line"><dependency></span><br><span class="line"><groupId>org.springframework.data</groupId></span><br><span class="line"><artifactId>spring-data-redis</artifactId></span><br><span class="line"></dependency></span><br><span class="line"><dependency></span><br><span class="line"><groupId>redis.clients</groupId></span><br><span class="line"><artifactId>jedis</artifactId></span><br><span class="line"> </dependency></span><br><span class="line"></dependencies></span><br></pre></td></tr></table></figure></p><h3 id="调整配置"><a href="#调整配置" class="headerlink" title="调整配置"></a>调整配置</h3><p> application.properties增加参数</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"># REDIS (RedisProperties)</span><br><span class="line"># Redis数据库索引(默认为0)</span><br><span class="line">spring.redis.database=0</span><br><span class="line"># Redis服务器地址</span><br><span class="line">spring.redis.host=localhost</span><br><span class="line"># Redis服务器连接端口</span><br><span class="line">spring.redis.port=6379</span><br><span class="line"># Redis服务器连接密码(默认为空)</span><br><span class="line">spring.redis.password=m7ua80gbm7cdm</span><br><span class="line"># 连接池最大连接数(使用负值表示没有限制)</span><br><span class="line">spring.redis.pool.max-active=10</span><br><span class="line"># 连接池最大阻塞等待时间(使用负值表示没有限制)</span><br><span class="line">spring.redis.pool.max-wait=10000</span><br><span class="line"># 连接池中的最大空闲连接</span><br><span class="line">spring.redis.pool.max-idle=200</span><br><span class="line"># 连接池中的最小空闲连接</span><br><span class="line">spring.redis.pool.min-idle=3</span><br><span class="line"># 连接超时时间(毫秒)</span><br><span class="line">spring.redis.timeout=6000</span><br></pre></td></tr></table></figure><h3 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">import org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line">import org.springframework.data.redis.core.StringRedisTemplate;</span><br><span class="line"></span><br><span class="line">@Autowired</span><br><span class="line">private StringRedisTemplate stringRedisTemplate;</span><br></pre></td></tr></table></figure><p>然后通过这个类操作Redis,通过阅读源码我们发现,该类是RedisTemplate的子类,具有以下数据操作对象:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"> // cache singleton objects (where possible)</span><br><span class="line">private ValueOperations<K, V> valueOps;//操作String类型的键值</span><br><span class="line">private ListOperations<K, V> listOps;//操作List集合类型的键值</span><br><span class="line">private SetOperations<K, V> setOps;//操作Set集合类型的键值</span><br><span class="line">private ZSetOperations<K, V> zSetOps;//操作有序Set集合类型的键值</span><br><span class="line">private GeoOperations<K, V> geoOps;//操作GEO类型的键值</span><br><span class="line">private HyperLogLogOperations<K, V> hllOps;//这个没有关注</span><br></pre></td></tr></table></figure></p><p>比如<br>操作String类型的键值可以:stringRedisTemplate.opsForValue().set(key,value);<br>操作Zset集合类型的键值可以:stringRedisTemplate.opsForZSet().add(key,value,double);</p><p>这里需要注意,不要使用import org.springframework.data.redis.core.RedisTemplate;这个类,虽然上面的StringRedisTemplate是其子类,但是它操作的redis数据会产生一些额外的二进制数值,如果其他项目读取该数据会略有不便。</p><hr><p>简单记录,有待深入挖坑!欢迎留言交流!</p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> Spring Boot </tag>
<tag> Redis </tag>
</tags>
</entry>
<entry>
<title>Spring Boot整合Quartz实现定时任务表配置</title>
<link href="/2017/145-spring-boot-quartz-editable/"/>
<url>/2017/145-spring-boot-quartz-editable/</url>
<content type="html"><![CDATA[<p> 最近有个小项目要做,spring mvc下的task设置一直不太灵活,因此在Spring Boot上想做到灵活的管理定时任务。需求就是,当项目启动的时候,如果有定时任务则加载进来,生成scheduler,通过后台表配置可以随时更新定时任务状态(启动、更改、删除)。</p><h3 id="添加依赖"><a href="#添加依赖" class="headerlink" title="添加依赖"></a>添加依赖</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><!-- spring's support for quartz --></span><br><span class="line"><dependency></span><br><span class="line"><groupId>org.springframework</groupId></span><br><span class="line"> <artifactId>spring-context-support</artifactId></span><br><span class="line"></dependency></span><br><span class="line"><!--quartz--></span><br><span class="line"><dependency></span><br><span class="line"><groupId>org.quartz-scheduler</groupId></span><br><span class="line"><artifactId>quartz</artifactId></span><br><span class="line"> <version>2.2.3</version></span><br><span class="line"></dependency></span><br></pre></td></tr></table></figure><p>一个是Spring框架的支持,一个是Quartz的依赖,有的博客会加上quartz-jobs,在当前示例中没有用到,这里不做添加。</p><h3 id="调整配置"><a href="#调整配置" class="headerlink" title="调整配置"></a>调整配置</h3><ul><li><p>application.properties增加参数</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">#quartz enabled 设置在当前项目是否运行quartz定时任务</span><br><span class="line">quartz.enabled=true</span><br></pre></td></tr></table></figure></li><li><p>增加quartz配置文件quartz.properties</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># thread-pool</span><br><span class="line">org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool</span><br><span class="line">org.quartz.threadPool.threadCount=2</span><br><span class="line"># job-store</span><br><span class="line">org.quartz.jobStore.class=org.quartz.simpl.RAMJobStore</span><br></pre></td></tr></table></figure><p>这些参数可以不设置,有一些默认值,threadCount的默认值是10,spring mvc下定时任务的默认值是1,所以如果某个定时任务卡住了,肯会影响其后的多个定时任务的执行。</p></li></ul><h3 id="任务表配置"><a href="#任务表配置" class="headerlink" title="任务表配置"></a>任务表配置</h3><ul><li><p>Entity</p><p>实体类,这里是JobConfig,这里没有做过多的设计,只是实现了cron类型的定时任务及任务状态,fullEntity是执行任务的类全名,如我们用的com.example.demo.jobs.MyJob</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">import lombok.AllArgsConstructor;</span><br><span class="line">import lombok.Data;</span><br><span class="line">import lombok.NoArgsConstructor;</span><br><span class="line"></span><br><span class="line">import javax.persistence.Entity;</span><br><span class="line">import javax.persistence.GeneratedValue;</span><br><span class="line">import javax.persistence.GenerationType;</span><br><span class="line">import javax.persistence.Id;</span><br><span class="line">import java.util.Date;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * Created by Administrator on 2017/8/25.</span><br><span class="line"> */</span><br><span class="line">@Entity</span><br><span class="line">@Data</span><br><span class="line">@AllArgsConstructor</span><br><span class="line">@NoArgsConstructor</span><br><span class="line">public class JobConfig {</span><br><span class="line"> @Id</span><br><span class="line"> @GeneratedValue(strategy = GenerationType.AUTO)</span><br><span class="line"> private Integer id;</span><br><span class="line"> private String name;</span><br><span class="line"> private String fullEntity;</span><br><span class="line"> private String groupName;</span><br><span class="line"> private String cronTime;</span><br><span class="line"> private Integer status;</span><br><span class="line"> private Date createAt;</span><br><span class="line"> private Date updateAt;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>代码没有set/get是因为使用了lombok,@Data注解实现set/get/toString等工作</p></li><li><p>Repository</p><p>这里主要是定义了一个根据定时任务状态获取对应的定时任务的方法,JobConfigRepository</p></li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">import com.example.demo.dto.JobConfig;</span><br><span class="line">import org.springframework.data.jpa.repository.JpaRepository;</span><br><span class="line"></span><br><span class="line">import java.util.List;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * Created by Administrator on 2017/8/25.</span><br><span class="line"> */</span><br><span class="line">public interface JobConfigRepository extends JpaRepository<JobConfig, Integer> {</span><br><span class="line"> List<JobConfig> findAllByStatus(int status);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li><p>Service</p><p>调用Repository的方法,提供查询,JobConfigService</p></li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">import com.example.demo.dto.JobConfig;</span><br><span class="line">import com.example.demo.repositories.JobConfigRepository;</span><br><span class="line">import org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line">import org.springframework.stereotype.Service;</span><br><span class="line"></span><br><span class="line">import java.util.List;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * Created by Administrator on 2017/8/25.</span><br><span class="line"> */</span><br><span class="line">@Service</span><br><span class="line">public class JobConfigService {</span><br><span class="line"> @Autowired</span><br><span class="line"> private JobConfigRepository jobConfigRepository;</span><br><span class="line"></span><br><span class="line"> public List<JobConfig> findAllByStatus(Integer status) {</span><br><span class="line"> return jobConfigRepository.findAllByStatus(status);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="添加自动注入支持"><a href="#添加自动注入支持" class="headerlink" title="添加自动注入支持"></a>添加自动注入支持</h3><p>源于<a href="https://gist.github.com/jelies/5085593的解决方案,解决的问题就是在org.quartz.Job的子类里无法直接使用Service等依赖,具体如下:" target="_blank" rel="noopener">https://gist.github.com/jelies/5085593的解决方案,解决的问题就是在org.quartz.Job的子类里无法直接使用Service等依赖,具体如下:</a></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">import org.quartz.spi.TriggerFiredBundle;</span><br><span class="line">import org.springframework.beans.BeansException;</span><br><span class="line">import org.springframework.beans.factory.config.AutowireCapableBeanFactory;</span><br><span class="line">import org.springframework.context.ApplicationContext;</span><br><span class="line">import org.springframework.context.ApplicationContextAware;</span><br><span class="line">import org.springframework.scheduling.quartz.SpringBeanJobFactory;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * Adds auto-wiring support to quartz jobs.</span><br><span class="line"> * @see "https://gist.github.com/jelies/5085593"</span><br><span class="line"> */</span><br><span class="line">public final class AutoWiringSpringBeanJobFactory extends SpringBeanJobFactory </span><br><span class="line"> implements ApplicationContextAware {</span><br><span class="line"></span><br><span class="line"> private transient AutowireCapableBeanFactory beanFactory;</span><br><span class="line"></span><br><span class="line"> public void setApplicationContext(ApplicationContext applicationContext) </span><br><span class="line"> throws BeansException {</span><br><span class="line"> beanFactory = applicationContext.getAutowireCapableBeanFactory();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {</span><br><span class="line"></span><br><span class="line"> final Object job = super.createJobInstance(bundle);</span><br><span class="line"> beanFactory.autowireBean(job);</span><br><span class="line"> return job;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="Scheduler工具类"><a href="#Scheduler工具类" class="headerlink" title="Scheduler工具类"></a>Scheduler工具类</h3><p>实现Scheduler的增删改功能以及JobDetail、CronTrigger的创建,需要注意,这里的数据都是源于JobConfig这个表,name是FullEntity+Id拼接而成的。具体看代码可知:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br></pre></td><td class="code"><pre><span class="line">import com.example.demo.config.AutoWiringSpringBeanJobFactory;</span><br><span class="line">import com.example.demo.dto.JobConfig;</span><br><span class="line">import org.quartz.*;</span><br><span class="line">import org.quartz.impl.StdSchedulerFactory;</span><br><span class="line">import org.springframework.context.ApplicationContext;</span><br><span class="line">import org.springframework.core.io.ClassPathResource;</span><br><span class="line">import org.springframework.scheduling.quartz.CronTriggerFactoryBean;</span><br><span class="line">import org.springframework.scheduling.quartz.JobDetailFactoryBean;</span><br><span class="line">import org.springframework.scheduling.quartz.SchedulerFactoryBean;</span><br><span class="line"></span><br><span class="line">import java.text.ParseException;</span><br><span class="line"></span><br><span class="line">public class SchedulerUtil {</span><br><span class="line"></span><br><span class="line"> //定时任务Scheduler的工厂类,Quartz提供</span><br><span class="line"> private static StdSchedulerFactory schedulerFactory = new StdSchedulerFactory();</span><br><span class="line"> //CronTrigger的工厂类</span><br><span class="line"> private static CronTriggerFactoryBean factoryBean = new CronTriggerFactoryBean();</span><br><span class="line"> //JobDetail的工厂类</span><br><span class="line"> private static JobDetailFactoryBean jobDetailFactory = new JobDetailFactoryBean();</span><br><span class="line"> //自动注入Spring Bean的工厂类</span><br><span class="line"> private static AutoWiringSpringBeanJobFactory jobFactory = </span><br><span class="line"> new AutoWiringSpringBeanJobFactory();</span><br><span class="line"> //定时任务Scheduler的工厂类,Spring Framework提供</span><br><span class="line"> private static SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();</span><br><span class="line"></span><br><span class="line"> static {</span><br><span class="line"> //加载指定路径的配置</span><br><span class="line"> schedulerFactoryBean.setConfigLocation(new ClassPathResource("quartz.properties"));</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> /**</span><br><span class="line"> * 创建定时任务,根据参数,创建对应的定时任务,并使之生效</span><br><span class="line"> * @param config</span><br><span class="line"> * @param context</span><br><span class="line"> * @return</span><br><span class="line"> */</span><br><span class="line"> public static boolean createScheduler(JobConfig config, </span><br><span class="line"> ApplicationContext context) {</span><br><span class="line"> try {</span><br><span class="line"> //创建新的定时任务</span><br><span class="line"> return create(config, context);</span><br><span class="line"> } catch (Exception e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"> return false;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> /**</span><br><span class="line"> * 删除旧的定时任务,创建新的定时任务</span><br><span class="line"> * @param oldConfig</span><br><span class="line"> * @param config</span><br><span class="line"> * @param context</span><br><span class="line"> * @return</span><br><span class="line"> */</span><br><span class="line"> public static Boolean modifyScheduler(JobConfig oldConfig,JobConfig config, </span><br><span class="line"> ApplicationContext context) {</span><br><span class="line"> if (oldConfig == null || config == null || context == null) {</span><br><span class="line"> return false;</span><br><span class="line"> }</span><br><span class="line"> try {</span><br><span class="line"> String oldJobClassStr = oldConfig.getFullEntity();</span><br><span class="line"> String oldName = oldJobClassStr + oldConfig.getId();</span><br><span class="line"> String oldGroupName = oldConfig.getGroupName();</span><br><span class="line"> //1、清除旧的定时任务</span><br><span class="line"> delete(oldName, oldGroupName);</span><br><span class="line"> //2、创建新的定时任务</span><br><span class="line"> return create(config, context);</span><br><span class="line"> } catch (SchedulerException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> } catch (Exception e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"> return false;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> /**</span><br><span class="line"> * 提取的删除任务的方法</span><br><span class="line"> * @param oldName</span><br><span class="line"> * @param oldGroupName</span><br><span class="line"> * @return</span><br><span class="line"> * @throws SchedulerException</span><br><span class="line"> */</span><br><span class="line"> private static Boolean delete(String oldName, String oldGroupName)</span><br><span class="line"> throws SchedulerException {</span><br><span class="line"> TriggerKey key = new TriggerKey(oldName, oldGroupName);</span><br><span class="line"> Scheduler oldScheduler = schedulerFactory.getScheduler();</span><br><span class="line"> //根据TriggerKey获取trigger是否存在,如果存在则根据key进行删除操作</span><br><span class="line"> Trigger keyTrigger = oldScheduler.getTrigger(key);</span><br><span class="line"> if (keyTrigger != null) {</span><br><span class="line"> oldScheduler.unscheduleJob(key);</span><br><span class="line"> }</span><br><span class="line"> return true;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> /**</span><br><span class="line"> * 提取出的创建定时任务的方法</span><br><span class="line"> * @param config</span><br><span class="line"> * @param context</span><br><span class="line"> * @return</span><br><span class="line"> */</span><br><span class="line"> private static Boolean create(JobConfig config, ApplicationContext context) {</span><br><span class="line"> try {</span><br><span class="line"> //创建新的定时任务</span><br><span class="line"> String jobClassStr = config.getFullEntity();</span><br><span class="line"> Class clazz = Class.forName(jobClassStr);</span><br><span class="line"> String name = jobClassStr + config.getId();</span><br><span class="line"> String groupName = config.getGroupName();</span><br><span class="line"> String description = config.toString();</span><br><span class="line"> String time = config.getCronTime();</span><br><span class="line"></span><br><span class="line"> JobDetail jobDetail = createJobDetail(clazz, name, groupName, description);</span><br><span class="line"> if (jobDetail == null) {</span><br><span class="line"> return false;</span><br><span class="line"> }</span><br><span class="line"> Trigger trigger = createCronTrigger(jobDetail, </span><br><span class="line"> time, name, groupName, description);</span><br><span class="line"> if (trigger == null) {</span><br><span class="line"> return false;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> jobFactory.setApplicationContext(context);</span><br><span class="line"></span><br><span class="line"> schedulerFactoryBean.setJobFactory(jobFactory);</span><br><span class="line"> schedulerFactoryBean.setJobDetails(jobDetail);</span><br><span class="line"> schedulerFactoryBean.setTriggers(trigger);</span><br><span class="line"> schedulerFactoryBean.afterPropertiesSet();</span><br><span class="line"> Scheduler scheduler = schedulerFactoryBean.getScheduler();</span><br><span class="line"> if (!scheduler.isShutdown()) {</span><br><span class="line"> scheduler.start();</span><br><span class="line"> }</span><br><span class="line"> return true;</span><br><span class="line"> } catch (ClassNotFoundException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> } catch (SchedulerException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> } catch (Exception e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"> return false;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> /**</span><br><span class="line"> * 根据指定的参数,创建JobDetail</span><br><span class="line"> * @param clazz</span><br><span class="line"> * @param name</span><br><span class="line"> * @param groupName</span><br><span class="line"> * @param description</span><br><span class="line"> * @return</span><br><span class="line"> */</span><br><span class="line"> public static JobDetail createJobDetail(Class clazz, String name, </span><br><span class="line"> String groupName, String description) {</span><br><span class="line"> jobDetailFactory.setJobClass(clazz);</span><br><span class="line"> jobDetailFactory.setName(name);</span><br><span class="line"> jobDetailFactory.setGroup(groupName);</span><br><span class="line"> jobDetailFactory.setDescription(description);</span><br><span class="line"> jobDetailFactory.setDurability(true);</span><br><span class="line"> jobDetailFactory.afterPropertiesSet();</span><br><span class="line"> return jobDetailFactory.getObject();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> /**</span><br><span class="line"> * 根据参数,创建对应的CronTrigger对象</span><br><span class="line"> *</span><br><span class="line"> * @param job</span><br><span class="line"> * @param time</span><br><span class="line"> * @param name</span><br><span class="line"> * @param groupName</span><br><span class="line"> * @param description</span><br><span class="line"> * @return</span><br><span class="line"> */</span><br><span class="line"> public static CronTrigger createCronTrigger(JobDetail job, String time, </span><br><span class="line"> String name, String groupName, String description) {</span><br><span class="line"> factoryBean.setName(name);</span><br><span class="line"> factoryBean.setJobDetail(job);</span><br><span class="line"> factoryBean.setCronExpression(time);</span><br><span class="line"> factoryBean.setDescription(description);</span><br><span class="line"> factoryBean.setGroup(groupName);</span><br><span class="line"> try {</span><br><span class="line"> factoryBean.afterPropertiesSet();</span><br><span class="line"> } catch (ParseException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"> return factoryBean.getObject();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="Scheduler初始化配置"><a href="#Scheduler初始化配置" class="headerlink" title="Scheduler初始化配置"></a>Scheduler初始化配置</h3><p>通过Spring Boot的@Configuration及@ConditionalOnExpression(“‘${quartz.enabled}’==’true’”)实现初始化时是否加载项目的定时任务——SchedulerConfig,这里的参数quartz.enabled的值即是我们上面在配置文件里配置的。代码如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line">package com.example.demo.config;</span><br><span class="line"></span><br><span class="line">import com.example.demo.dto.JobConfig;</span><br><span class="line">import com.example.demo.service.JobConfigService;</span><br><span class="line">import com.example.demo.util.SchedulerUtil;</span><br><span class="line">import org.quartz.impl.StdSchedulerFactory;</span><br><span class="line">import org.slf4j.Logger;</span><br><span class="line">import org.slf4j.LoggerFactory;</span><br><span class="line">import org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line">import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;</span><br><span class="line">import org.springframework.context.ApplicationContext;</span><br><span class="line">import org.springframework.context.annotation.Bean;</span><br><span class="line">import org.springframework.context.annotation.Configuration;</span><br><span class="line"></span><br><span class="line">import java.util.List;</span><br><span class="line"></span><br><span class="line">@Configuration</span><br><span class="line">@ConditionalOnExpression("'${quartz.enabled}'=='true'")</span><br><span class="line">public class SchedulerConfig {</span><br><span class="line"> Logger logger = LoggerFactory.getLogger(getClass());</span><br><span class="line"> @Autowired</span><br><span class="line"> private ApplicationContext applicationContext;</span><br><span class="line"></span><br><span class="line"> @Autowired</span><br><span class="line"> private JobConfigService jobConfigService;</span><br><span class="line"></span><br><span class="line"> @Bean</span><br><span class="line"> public StdSchedulerFactory stdSchedulerFactory() {</span><br><span class="line"> StdSchedulerFactory stdSchedulerFactory = new StdSchedulerFactory();</span><br><span class="line"> //获取JobConfig集合</span><br><span class="line"> List<JobConfig> configs = jobConfigService.findAllByStatus(1);</span><br><span class="line"> logger.debug("Setting the Scheduler up");</span><br><span class="line"> for (JobConfig config : configs) {</span><br><span class="line"> try {</span><br><span class="line"> Boolean flag = SchedulerUtil.createScheduler(</span><br><span class="line"> config, applicationContext);</span><br><span class="line"> System.out.println("执行结果:" + (flag == true ? "成功" : "失败"));</span><br><span class="line"> } catch (Exception e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> return stdSchedulerFactory;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="Job实现"><a href="#Job实现" class="headerlink" title="Job实现"></a>Job实现</h3><p>这里定义了一个简单的Job继承org.quartz.Job,主要是查询当前的定时任务表配置数据,MyJob,具体代码如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">package com.example.demo.jobs;</span><br><span class="line"></span><br><span class="line">import com.example.demo.dto.JobConfig;</span><br><span class="line">import com.example.demo.service.JobConfigService;</span><br><span class="line">import org.quartz.Job;</span><br><span class="line">import org.quartz.JobExecutionContext;</span><br><span class="line">import org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line">import org.springframework.stereotype.Component;</span><br><span class="line"></span><br><span class="line">import java.text.SimpleDateFormat;</span><br><span class="line">import java.util.Date;</span><br><span class="line">import java.util.List;</span><br><span class="line"></span><br><span class="line">@Component</span><br><span class="line">public class MyJob implements Job {</span><br><span class="line"> @Autowired</span><br><span class="line"> private JobConfigService jobConfigService;</span><br><span class="line"></span><br><span class="line"> public void execute(JobExecutionContext context) {</span><br><span class="line"> System.out.println();</span><br><span class="line"> System.out.println();</span><br><span class="line"> //是哪个定时任务配置在执行,可以看到,因为在前面我们将描述设置为了配置类的toString结果</span><br><span class="line"> System.out.println(context.getJobDetail().getDescription());</span><br><span class="line"> SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");</span><br><span class="line"> System.out.println(this.toString() + ":" + f.format(new Date()) + </span><br><span class="line"> "正在执行Job executing...");</span><br><span class="line"> List<JobConfig> configs = jobConfigService.findAllByStatus(1);</span><br><span class="line"> for (JobConfig config : configs) {</span><br><span class="line"> System.out.println(config.toString());</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="数据库表job-config"><a href="#数据库表job-config" class="headerlink" title="数据库表job_config"></a>数据库表job_config</h3><ul><li>表创建</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">CREATE TABLE `job_config` (</span><br><span class="line"> `id` INT(11) NOT NULL AUTO_INCREMENT,</span><br><span class="line"> `create_at` DATETIME DEFAULT NULL,</span><br><span class="line"> `cron_time` VARCHAR(255) DEFAULT NULL,</span><br><span class="line"> `full_entity` VARCHAR(255) DEFAULT NULL,</span><br><span class="line"> `group_name` VARCHAR(255) DEFAULT NULL,</span><br><span class="line"> `name` VARCHAR(255) DEFAULT NULL,</span><br><span class="line"> `status` INT(11) DEFAULT NULL,</span><br><span class="line"> `update_at` DATETIME DEFAULT NULL,</span><br><span class="line"> PRIMARY KEY (`id`)</span><br><span class="line">)</span><br><span class="line"> ENGINE = InnoDB</span><br><span class="line"> AUTO_INCREMENT = 3</span><br><span class="line"> DEFAULT CHARSET = utf8;</span><br></pre></td></tr></table></figure><ul><li>表数据</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">/*Data for the table `job_config` */</span><br><span class="line"></span><br><span class="line">INSERT INTO `job_config` (`id`, `create_at`, `cron_time`, `full_entity`, `group_name`, `name`, `status`, `update_at`)</span><br><span class="line">VALUES (1, '2017-08-25 21:03:35', '0/8 * * * * ?', 'com.example.demo.jobs.MyJob', 'test', 'My test', 1, NULL),</span><br><span class="line"> (2, '2017-08-25 21:12:02', '0/23 * * * * ?', 'com.example.demo.jobs.MyJob', 'test', 'My Job', 1, NULL);</span><br></pre></td></tr></table></figure><h3 id="运行结果"><a href="#运行结果" class="headerlink" title="运行结果"></a>运行结果</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">JobConfig(id=1, name=My test, fullEntity=com.example.demo.jobs.MyJob, groupName=test, cronTime=0/8 * * * * ?, status=1, createAt=2017-08-25 21:03:35.0, updateAt=null)</span><br><span class="line">com.example.demo.jobs.MyJob@7602fe69:2017-08-26 10:43:16正在执行Job executing...</span><br><span class="line">Hibernate: select jobconfig0_.id as id1_1_, jobconfig0_.create_at as create_a2_1_, jobconfig0_.cron_time as cron_tim3_1_, jobconfig0_.full_entity as full_ent4_1_, jobconfig0_.group_name as group_na5_1_, jobconfig0_.name as name6_1_, jobconfig0_.status as status7_1_, jobconfig0_.update_at as update_a8_1_ from job_config jobconfig0_ where jobconfig0_.status=?</span><br><span class="line">JobConfig(id=1, name=My test, fullEntity=com.example.demo.jobs.MyJob, groupName=test, cronTime=0/8 * * * * ?, status=1, createAt=2017-08-25 21:03:35.0, updateAt=null)</span><br><span class="line">JobConfig(id=2, name=My Job, fullEntity=com.example.demo.jobs.MyJob, groupName=test, cronTime=0/23 * * * * ?, status=1, createAt=2017-08-25 21:12:02.0, updateAt=null)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">JobConfig(id=2, name=My Job, fullEntity=com.example.demo.jobs.MyJob, groupName=test, cronTime=0/23 * * * * ?, status=1, createAt=2017-08-25 21:12:02.0, updateAt=null)</span><br><span class="line">com.example.demo.jobs.MyJob@4a49530:2017-08-26 10:43:23正在执行Job executing...</span><br><span class="line">Hibernate: select jobconfig0_.id as id1_1_, jobconfig0_.create_at as create_a2_1_, jobconfig0_.cron_time as cron_tim3_1_, jobconfig0_.full_entity as full_ent4_1_, jobconfig0_.group_name as group_na5_1_, jobconfig0_.name as name6_1_, jobconfig0_.status as status7_1_, jobconfig0_.update_at as update_a8_1_ from job_config jobconfig0_ where jobconfig0_.status=?</span><br><span class="line">JobConfig(id=1, name=My test, fullEntity=com.example.demo.jobs.MyJob, groupName=test, cronTime=0/8 * * * * ?, status=1, createAt=2017-08-25 21:03:35.0, updateAt=null)</span><br><span class="line">JobConfig(id=2, name=My Job, fullEntity=com.example.demo.jobs.MyJob, groupName=test, cronTime=0/23 * * * * ?, status=1, createAt=2017-08-25 21:12:02.0, updateAt=null)</span><br></pre></td></tr></table></figure><p>到这里,Spring Boot与quartz的整合已经完成了,可以通过配置表job_config以及配置quartz.enabled参数来灵活使用定时任务了!</p><p>后续还会继续实践、丰富这个示例,如果上文有什么问题,欢迎留言指正,谢谢!</p><p>源码:<a href="https://github.com/icnws/spring-data-jpa-demo" target="_blank" rel="noopener">https://github.com/icnws/spring-data-jpa-demo</a></p><hr><p>定时任务的路还有很长,想更灵活?可能需要elastic-job等框架吧!欢迎留言交流!</p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> Spring Boot </tag>
<tag> Quartz </tag>
</tags>
</entry>
<entry>
<title>读《非暴力沟通》</title>
<link href="/2017/144-read-nonviolent-communication/"/>
<url>/2017/144-read-nonviolent-communication/</url>
<content type="html"><![CDATA[<p> 最近,比较忙也比较懒,所以读书不太多,只是读了这本鸡汤成分略大的书,《非暴力沟通》,讲的就是如何去避免直接使用暴力去诉诸对抗的行为方法论。有一定的启发,毕竟,我们的文化形态,惯用的是指责、问责,很少关注其他的东西。</p><p><img src="/uploads/2017/fblgt.jpg" alt=""></p><h3 id="书名:非暴力沟通"><a href="#书名:非暴力沟通" class="headerlink" title="书名:非暴力沟通"></a>书名:非暴力沟通</h3><p>看书名就知道,和沟通有关,大多数急于在社交上、生活上沟通有问题的,或者觉得有问题的,一般会寻求这类书籍的帮助。我呢,是因为这本书在微信读书APP里躺了很久,而且不会因为时间不连续导致思路跟不上的问题,所以就看了。</p><p>书中大部分篇幅就是将什么是非暴力沟通,如何体验非暴力沟通,以及怎么持续下去,最终讲了关于一个长辈一辈子践行非暴力沟通的例子,也道出了作者非暴力沟通的榜样。</p><h3 id="事实"><a href="#事实" class="headerlink" title="事实"></a>事实</h3><p>事实就是,这本书用起来需要勇气,大多数时间感觉沟通拖拖拉拉,不能快速的解决问题。然而,从作者的例子我们有一个这样的体验,慢即是快。这是怎么样的体验呢?就是说通过慢的沟通表达抓住主要的问题和症结,对症下药了,然后很多问题和需要就迎刃而解。</p><p>这个很好理解,越来越多的时候,我们发现做事情很容易,将事情表达清楚却很困难。程序员经常遇到产品、美工、领导说的A,实际他们想要的是B,结果是我们做的C,再三沟通才能回到最初的需求,最初的想法,最终的目的,这时候浪费了很多时间。这中间如果出了问题,也大多是指责某一环节的某个人的决策,而很少考虑自己是否真正承担了应该承担的角色以及责任。</p><h3 id="收获"><a href="#收获" class="headerlink" title="收获"></a>收获</h3><p>这本书的最大收获就是,换一个视角,表达和发现需要,而不是指责和狂怒,甚至逃避责任。</p><p>我们在工作的时候,大多数是对结果负责,实际上,大多数结果我们需要由别人替我们承担。这是为什么?</p><p>原因无他,我们只知道最终要实现一个什么东西,不知道这个东西是哪个需求来的,最终目的是什么,只是知道完成系统中的那一环,其他的并不怎么关注。因此,我们把失败归功于上层的决定,推诿给其他人。这是很多人的做法,也是很多人平庸甚至沦为平庸的根源之一。</p><p>换一个角度,从源头去思考我们做的每一件事情,试图去追溯事情的根源,明白发生了什么,需要我们去做什么,怎么才能将我们的工作做的更好更出色,这也是我想告诉你的。</p><p>你的每一次偷懒都会有人给你记着,都会成为未来你成长发展的坎坷,所以春光大好多努力呀!</p><hr><p>你有没有想看这本书?欢迎留言交流!</p>]]></content>
<categories>
<category> 读书 </category>
</categories>
<tags>
<tag> 阅读 </tag>
<tag> 沟通 </tag>
</tags>
</entry>
<entry>
<title>我是怎么阅读新闻的</title>
<link href="/2017/143-how-do-I-read-the-news/"/>
<url>/2017/143-how-do-I-read-the-news/</url>
<content type="html"><![CDATA[<h3 id="1、通常做法:"><a href="#1、通常做法:" class="headerlink" title="1、通常做法:"></a>1、通常做法:</h3><p>大多数人的做法是安装N个客户端,比如网易新闻、今日头条、腾讯新闻等,这些新闻APP的运营会不定时的推送一些新鲜资讯,我们在手机上收到推送之后,点开消息,接着就进入APP,一进去就半个小时过去了,最终可能发现自己只是看了几个搞笑或者故意吸引眼球的各种奇闻疑案,并没有太多的收获。</p><p>特别是像进入头条这种APP,根据用户的“喜好”来匹配内容,判断你喜好的标准可能是自己贴的标签,自己浏览的信息(包括误点操作),我用了几次,感觉都是TM的垃圾信息,很难看到有用的,于是,我就不浪费生命,直接将所有这类新闻APP。</p><h3 id="2、事实"><a href="#2、事实" class="headerlink" title="2、事实"></a>2、事实</h3><p>事实是,每家新闻APP都以各种方式留住你,给你广告,给你垃圾信息,让你长时间的呆在他们的APP里,沉浸下去,为他们的广告用户做背书,然后消磨掉你的时间,为APP公司挣钱。如果你从中得到了益处,那也还好,但是事实是,为了吸引你的眼球,各种性的暗示图文,各种清宫疑案,城市琐事等等,没有什么有营养的东西。</p><p>很多运营人员,为了业绩,为了KPI好看,不择手段,甚至虚假信息,这是我最厌恶的地方。</p><h3 id="3、我的做法"><a href="#3、我的做法" class="headerlink" title="3、我的做法"></a>3、我的做法</h3><p>卸载这些新闻APP,选择通过邮件定义的方式阅读有用的资讯,比如好奇心日报,这样可以少阅读百分之九十的垃圾信息,对一些重要的信息并不怎么遗漏,只是少了一些花边新闻可将而已。话说回来,花边新闻只能让你的逼格降低,并无益处,一时的附和可能是背后的厌恶,说你恶趣味,提升品位也很重要。</p><p>为什么是好奇心日报?</p><p>好奇心日报也不是我的第一选择,像爱范儿、36Kr等我都有试过,事实是很不理想,不能达到我对新闻资讯纯净高效率的要求,好奇心日报可以很好的满足。</p><p>好奇心日报的推送频率不高,手机端自适应排版,信息相对有效性高,热点话题、大公司头条、看图等都是很好看的栏目,一文看尽时鲜,用了有两周吧,很舒爽,所以要些这篇文章推荐给你,提高你的效率,为有限的生命增值。</p><h3 id="4、实现方案"><a href="#4、实现方案" class="headerlink" title="4、实现方案"></a>4、实现方案</h3><p>微信+QQ邮箱+IFTTT服务,即RSS订阅好奇心日报,通过IFTTT推送到QQ邮箱,在微信内打开设置里的QQ邮箱提醒,这样好奇心日报一发布订阅消息,我们很快就能在微信的QQ邮箱提醒里看到邮件了,方便的时候就阅读吧。具体步骤如下:</p><h4 id="4-1、注册IFTTT"><a href="#4-1、注册IFTTT" class="headerlink" title="4.1、注册IFTTT"></a>4.1、注册IFTTT</h4><p>用QQ邮箱在网站<a href="https://ifttt.com/" target="_blank" rel="noopener">https://ifttt.com/</a> 注册一个账号,注意要完整实现有效订阅阅读,这一步很重要。注册成功后登录网站。</p><h4 id="4-2、添加Applet"><a href="#4-2、添加Applet" class="headerlink" title="4.2、添加Applet"></a>4.2、添加Applet</h4><p>找到顶部的“My Applets”并点击,然后找到New Applet,创建一个RSS订阅,点击会出现下图:</p><p><img src="/uploads/2017/if-1.jpg" alt=""></p><p>点击“+this”,然后选择“RSS Feed”,然后选择一个trigger,这里选择第一个“New feed item”,填写Feed URL:<a href="http://www.qdaily.com/feed.xml" target="_blank" rel="noopener">http://www.qdaily.com/feed.xml</a> ,点击create trigger,会出现下图:</p><p><img src="/uploads/2017/if-2.jpg" alt=""></p><p>我们看得“+this”已经被替换成RSS的icon了,然后选择“+that”,在新的页面选择Email,在Choose action页面选择“Send me an email”,然后会出现新的界面,如下所示,会有基本的推送样式,推送邮箱是Base Email,这也是为啥用QQ邮箱注册。</p><p><img src="/uploads/2017/if-3.jpg" alt=""></p><p>在这个页面下,选择“Create Action”即生成对应的订阅,进入最终页面,点击Finish即完成创建:</p><p><img src="/uploads/2017/if-4.jpg" alt=""></p><p>至此,我们就完成了IFTTT订阅RSS的所有操作,等待新的Feed发出后,我们就能收到对应的邮件。</p><p><strong>重要的提醒:IFTTT默认是将所有URL转换成短链接的,因此要手动关闭掉,方法如下:</strong></p><p>在IFTTT的右上角点击用户名,选择Setting,进入新页面后下拉,找到URL shortening,将默认自动转成短链接的复选框点掉即可,然后保存设置,这样收到的邮件才是在国内能正常打开的。</p><p>当然,IFTTT还有很多强大的功能,他其实就是一个搬运工,帮我们做一些需要费时费力的搬运工作,像快递一样,我还会配合IFTTT的Do Note客户端进行发推,这个你可以自己摸索。</p><h4 id="4-3、微信设置"><a href="#4-3、微信设置" class="headerlink" title="4.3、微信设置"></a>4.3、微信设置</h4><p>打开微信的设置,找到通用,选择功能,找到QQ邮箱提醒功能并开启就可以等着新鲜有用的资讯新闻了。</p><hr><p>这就是我阅读新闻资讯的方法,你学到了吗?欢迎留言交流!</p>]]></content>
<categories>
<category> 杂谈 </category>
</categories>
<tags>
<tag> 阅读 </tag>
<tag> Feed </tag>
<tag> RSS </tag>
</tags>
</entry>
<entry>
<title>Thymeleaf强制闭合标签解决方法</title>
<link href="/2017/142-thymeleaf-setting-1st/"/>
<url>/2017/142-thymeleaf-setting-1st/</url>
<content type="html"><![CDATA[<h3 id="错误信息:"><a href="#错误信息:" class="headerlink" title="错误信息:"></a>错误信息:</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">org.xml.sax.SAXParseException: 元素类型 "meta" 必须由匹配的结束标记 "</meta>" 终止。</span><br></pre></td></tr></table></figure><h3 id="解决方案"><a href="#解决方案" class="headerlink" title="解决方案"></a>解决方案</h3><p>增加依赖:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><!-- https://mvnrepository.com/artifact/net.sourceforge.nekohtml/nekohtml --></span><br><span class="line"><!-- 使thymeleaf不强制闭合标签 --></span><br><span class="line"><dependency></span><br><span class="line"><groupId>net.sourceforge.nekohtml</groupId></span><br><span class="line"><artifactId>nekohtml</artifactId></span><br><span class="line"><version>1.9.22</version></span><br><span class="line"></dependency></span><br></pre></td></tr></table></figure><p>参数配置:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">#不强制关闭HTML标签</span><br><span class="line">spring.thymeleaf.mode = LEGACYHTML5</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> Thymeleaf </tag>
</tags>
</entry>
<entry>
<title>IDEA+Github+OSC-Git+Typora才是好搭档</title>
<link href="/2017/135-writing-with-md/"/>
<url>/2017/135-writing-with-md/</url>
<content type="html"><![CDATA[<p> 最近在社区Spring For All( <a href="http://www.spring4all.com" target="_blank" rel="noopener">http://www.spring4all.com</a> )群友的帮助下,完成了Github的网站博客搭建,刚开始我没有意识到md等文件要单独存起来,所以弄了一个乌龙,在家弄的很好,结果去公司电脑就不能很好的玩耍了。</p><p> 所以,做了个方案,既可以在家玩,也可以同步到公司的电脑上,而这些博客的md等文件又不能公开,所以选用了开源中国的git做源文件仓库,编译完成的html文件同步到github上,相当于发布文章了。</p><a id="more"></a><h3 id="1、搭建好Github之后"><a href="#1、搭建好Github之后" class="headerlink" title="1、搭建好Github之后"></a>1、搭建好Github之后</h3><p>需要配置一下脚本,我叫<code>init.sh</code>,主要是用来管理不同机器的环境,因为一旦缺少一些插件,可能会导致最终发布到github的静态页面不一致,因此,要千万注意,这里给出我的是以代码。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"># 在当前目录初始化hexo</span><br><span class="line">npm install hexo-cli -g</span><br><span class="line"># 安装hexo依赖的node模块</span><br><span class="line">npm install</span><br><span class="line"># 安装发布到github的git部署插件</span><br><span class="line">npm install hexo-deployer-git --save</span><br><span class="line"># 创建索引的插件</span><br><span class="line">npm install --save hexo-generator-index</span><br><span class="line"># 创建目录的插件</span><br><span class="line">npm install --save hexo-generator-archive</span><br><span class="line"># 创建Tag的插件</span><br><span class="line">npm install --save hexo-generator-tag</span><br><span class="line"># 搜索插件</span><br><span class="line">npm install hexo-generator-search --save</span><br><span class="line"># 生成搜索库</span><br><span class="line">npm install hexo-generator-searchdb --save</span><br><span class="line"># RSS订阅</span><br><span class="line">npm install hexo-generator-feed --save</span><br><span class="line"># 生成sitemap的插件</span><br><span class="line">npm install hexo-generator-seo-friendly-sitemap --save</span><br></pre></td></tr></table></figure><p>再配置一个编译启动脚本,测试常用,我叫<code>hexo.sh</code>,代码如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"># 清除原有编译代码</span><br><span class="line">hexo clean</span><br><span class="line"># 编译最新代码,生成对应文件</span><br><span class="line">hexo g</span><br><span class="line"># 启动服务,通过localhost:4000访问</span><br><span class="line">hexo s</span><br></pre></td></tr></table></figure><p>每次写完可以即时运行一下,看看效果,如果确定没有问题,那就发布吧,命令是:</p><p><code>hexo d</code></p><h3 id="2、使用开源中国Git托管网站博客源码"><a href="#2、使用开源中国Git托管网站博客源码" class="headerlink" title="2、使用开源中国Git托管网站博客源码"></a>2、使用开源中国Git托管网站博客源码</h3><p>OSC的Git服务有了独立域名,即<a href="http://www.gitee.com" target="_blank" rel="noopener">http://www.gitee.com</a> ,新版3.0也发布了,越来越好用了。如果你还没有账号,不妨注册一个,可以创建私有项目,这样存放博客源码就比较方便,多台机器随意切换。</p><p>用Hexo驱动写博客的好处就是可以让我们随时再部署一套自己的网站出来,不用担心网站数据问题,而开源中国的私有项目服务,可以让这个更无后顾之忧。</p><h3 id="3、IDEA的使用"><a href="#3、IDEA的使用" class="headerlink" title="3、IDEA的使用"></a>3、IDEA的使用</h3><p>IDEA虽然对MD的支持有限,但是对于代码管理还是很方便的,从OSC-Git上检出,同步等非常方便,也可以定义一些写作的模板,方便生成基本文件。</p><h3 id="4、Typora的使用"><a href="#4、Typora的使用" class="headerlink" title="4、Typora的使用"></a>4、Typora的使用</h3><p>Typrora是一款跨平台(Mac、Windows、Linux)的Markdown编辑器,最大的特点就是简洁方便,很多MD工具不能很方便的使用,而这款非常方便。你用一次就会喜欢上,我现在就是用Typora在写这篇文章。</p><p>Typora的网址是:<a href="https://typora.io/" target="_blank" rel="noopener">https://typora.io/</a></p>]]></content>
<categories>
<category> 杂谈 </category>
</categories>
<tags>
<tag> 写作 </tag>
</tags>
</entry>
<entry>
<title>音视频周刊推荐</title>
<link href="/2017/134-audo-and-video-weekly/"/>
<url>/2017/134-audo-and-video-weekly/</url>
<content type="html"><![CDATA[<p>经常会遇到一些人,在学习音视频相关技术的时候资料甚少,也源于很多大牛没时间来分享,音视频领域的技术火了有很长一段时间了,大神们都忙着挣钱呢!有一个喜欢系统分享音视频的大牛雷霄华雷神也不幸离世了,哎,以后的路还是需要靠自己来走。</p><p>今天呢,给大家介绍一个音视频的周刊,这个周刊是以邮件的方式订阅,我虽然最近不怎么搞了,但是还一直订阅着他们的邮件,每周会汇集一些很好的文章,包括前端、架构、后端、活动等等,内容丰富且精彩,如果你在学习音视频,一定不要错过了。</p><a id="more"></a><h3 id="1、示例"><a href="#1、示例" class="headerlink" title="1、示例"></a>1、示例</h3><p><img src="/uploads/2017/audio-and-video-weekly.jpg" alt=""></p><h3 id="2、订阅"><a href="#2、订阅" class="headerlink" title="2、订阅"></a>2、订阅</h3><p>点击<a href="http://livevideostack.us15.list-manage.com/subscribe?u=6bc354bfad4aafd1d8660b97f&id=2137fb31dd" target="_blank" rel="noopener">订阅连接</a><br><img src="/uploads/2017/audio-and-video-weekly-rss.jpg" alt="图片"></p><p>订阅完成之后,你每周都会受到一些关于音视频的精彩内容了。</p><p>话说,现在深耕音视频方面的人才,都是收入狂飙,同样是程序猿,差别也是挺大的。</p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> 推荐 </tag>
<tag> 音视频 </tag>
</tags>
</entry>
<entry>
<title>分析网络资源的DNS解析</title>
<link href="/2017/133-trace-route-dns/"/>
<url>/2017/133-trace-route-dns/</url>
<content type="html"><![CDATA[<h2 id="分析网络资源的DNS解析"><a href="#分析网络资源的DNS解析" class="headerlink" title="分析网络资源的DNS解析"></a>分析网络资源的DNS解析</h2><p>要分析一些资源的来源和信息,所以要通过DNS来追踪,这里做一些简单记录</p><a id="more"></a><h3 id="1、traceroute方式"><a href="#1、traceroute方式" class="headerlink" title="1、traceroute方式"></a>1、traceroute方式</h3><p>这是Linux下的方式,直接用命令</p><p><code>traceroute domain</code></p><p>即可获得对应的解析记录</p><p>更常用的可能是<code>traceroute -m 10 domain</code></p><p>更多信息参考<a href="http://www.cnblogs.com/peida/archive/2013/03/07/2947326.html" target="_blank" rel="noopener">http://www.cnblogs.com/peida/archive/2013/03/07/2947326.html</a></p><p>写的很详细,很有参考价值。</p><h3 id="2、tracert方式"><a href="#2、tracert方式" class="headerlink" title="2、tracert方式"></a>2、tracert方式</h3><p>这是Windows下的方式,直接使用命令</p><p><code>tracert domain</code></p><p>即可获得对应的解析记录,可以参考<a href="http://www.cnblogs.com/godtrue/p/5882541.html这个博文。" target="_blank" rel="noopener">http://www.cnblogs.com/godtrue/p/5882541.html这个博文。</a></p><h3 id="3、IPIP提供的Traceroute工具"><a href="#3、IPIP提供的Traceroute工具" class="headerlink" title="3、IPIP提供的Traceroute工具"></a>3、IPIP提供的Traceroute工具</h3><p>网址:<a href="http://www.ipip.net/traceroute.php" target="_blank" rel="noopener">http://www.ipip.net/traceroute.php</a></p><p>直接将资源地址粘贴进输入框并点击查看,稍等片刻就可以了,很方便</p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> DNS </tag>
<tag> Traceroute </tag>
<tag> Tracert </tag>
</tags>
</entry>
<entry>
<title>密码生成器</title>
<link href="/2017/132-generation-password-desigin-1st/"/>
<url>/2017/132-generation-password-desigin-1st/</url>
<content type="html"><![CDATA[<p>最近让同事帮忙做了个密码生成器,随机字符串,<br>大小写字母(52),0到9(10)再加上!*总共是64个字符,<br>生成8位/12位/16位密码,配合网络笔记使用,手机本地加密使用网络笔记软件!<br>已经用起来了,还挺好用,需要什么密码直接通过笔记查了发到QQ或者微信上就可以了!<br>目前只有安卓版本的,而且比较土,想用的可以留言!</p><p><img src="/uploads/2017/generate-password.png" alt=""></p>]]></content>
<categories>
<category> 杂谈 </category>
</categories>
<tags>
<tag> 高考 </tag>
</tags>
</entry>
<entry>
<title>在github上创建站点</title>
<link href="/2017/create-website-on-github-pages/"/>
<url>/2017/create-website-on-github-pages/</url>
<content type="html"><![CDATA[<p>在群友的帮助下,参考一些博文,最终搞定了在github.com部署博客的实践。</p><h3 id="1、参考博客"><a href="#1、参考博客" class="headerlink" title="1、参考博客"></a>1、参考博客</h3><p><code>http://blog.liuxianan.com/build-blog-website-by-hexo-github.html</code></p><h3 id="2、安装nodejs"><a href="#2、安装nodejs" class="headerlink" title="2、安装nodejs"></a>2、安装nodejs</h3><p>去 <code>https://nodejs.org/en/download/</code> 下载LTS版本,我的是windows7系统x64。下载完成后直接安装即可。</p><h3 id="3、安装git"><a href="#3、安装git" class="headerlink" title="3、安装git"></a>3、安装git</h3><p>去 <a href="https://git-scm.com/downloads" target="_blank" rel="noopener">https://git-scm.com/downloads</a> 下载<br>或者去 <a href="https://git-for-windows.github.io/" target="_blank" rel="noopener">https://git-for-windows.github.io/</a> 下载<br>然后一路next安装即可</p><h3 id="4、创建github账号及项目"><a href="#4、创建github账号及项目" class="headerlink" title="4、创建github账号及项目"></a>4、创建github账号及项目</h3><p>去 <a href="https://github.com" target="_blank" rel="noopener">https://github.com</a> 创建或登录你的账号,然后创建一个项目,项目名称就是 ${username}.github.io<br>比如我的是icnws.github.io,创建完成之后,隔几分钟就可以通过<a href="http://icnws.github.io" target="_blank" rel="noopener">http://icnws.github.io</a> 进行网站访问了,这时候网站除了标题以外基本上都是空的。</p><h3 id="5、配置域名映射"><a href="#5、配置域名映射" class="headerlink" title="5、配置域名映射"></a>5、配置域名映射</h3><p>通过ping icnws.github.io,获得对应项目的IP地址,在域名解析通过A记录配置,然后配置CNAME记录,对www解析到icnws.github.io<br>在github的对应项目根目录创建CNAME文件,注意这里的文件没有后缀,然后将要映射的域名写入即可,比如我这里写了<a href="http://www.icnws.com">http://www.icnws.com</a><br>到这里,映射就配置完成了,稍等片刻就可以直接通过域名<a href="http://www.icnws.com进行访问新生成的博客了。" target="_blank" rel="noopener">www.icnws.com进行访问新生成的博客了。</a></p><h3 id="6、配置github访问的SSH密钥"><a href="#6、配置github访问的SSH密钥" class="headerlink" title="6、配置github访问的SSH密钥"></a>6、配置github访问的SSH密钥</h3><p>在github账号的设置页面可以看到左侧的SSH and GPG keys菜单,选择,然后会看见SSH Key的管理操作按钮。<br>首先在本地,通过git的keygen生成密钥对,然后将公钥内容copy并添加新的SSH Key保存即可<br>配置完成通过 ssh -T <a href="mailto:[email protected]" target="_blank" rel="noopener">[email protected]</a> 来测试是否成功,出现successfully字样就说明成功了。<br>然后配置本地的git全局用户名及邮箱地址,参数为github的用户名和注册邮箱即可。</p><h3 id="7、安装hexo"><a href="#7、安装hexo" class="headerlink" title="7、安装hexo"></a>7、安装hexo</h3><p>Hexo的官网:<a href="https://hexo.io" target="_blank" rel="noopener">https://hexo.io</a><br>中文用户:<a href="https://hexo.io/zh-cn/" target="_blank" rel="noopener">https://hexo.io/zh-cn/</a><br>通过命令:<code>npm install -g hexo-cli</code>进行安装,原有的命令是npm install -g hexo不是安装最新版本。安装完成之后,创建一个hexo的工作目录,比如/d/nodejs/hexo在D盘nodejs目录下创建,然后切换目录至该文件夹执行hexo init,有可能无法生成更新到文件夹node_modules,修改根目录的.gitignore文件并重新执行命令即可。<br>后面的内容可以直接参考官网的手册了,有一点需要注意的就是,在设置deploy的参数时,我在冒号后面少了空格,导致hexo d部署到github的时候反复提交,既不报错也不成功,千万注意,别犯类似的错误了。</p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> hexo </tag>
</tags>
</entry>
<entry>
<title>亚马逊联盟调研</title>
<link href="/2017/survey-for-Amazon-Product-Advertising-API/"/>
<url>/2017/survey-for-Amazon-Product-Advertising-API/</url>
<content type="html"><![CDATA[<p>这几天在看亚马逊联盟的相关服务,从在主界面定义一些链接、页面等方式接入联盟,为网站和APP带来盈利的可能,到通过Product Advertising API来实现相关搜索、查询、购物车操作等,还是有一些收获的。</p><h3 id="1、创建账号:"><a href="#1、创建账号:" class="headerlink" title="1、创建账号:"></a>1、创建账号:</h3><p>通过<a href="https://affiliate-program.amazon.com" target="_blank" rel="noopener">https://affiliate-program.amazon.com</a> 来加入联盟,这里接受你的广告展示可以是网站(website)或者APP(amazon market,google play,apple store),如果都不是,那就无法申请,国内应用市场发布的APP,在这里是不受认可的。<br>账号注册完成后即可以进行操作了。需要注意到,注册这个的同时,如果没有开通AWS服务会开通相关服务,已经开通并关闭了是无法直接使用相关Product Advertising API的</p><h3 id="2、简单使用:"><a href="#2、简单使用:" class="headerlink" title="2、简单使用:"></a>2、简单使用:</h3><p>在<a href="https://affiliate-program.amazon.com/home" target="_blank" rel="noopener">https://affiliate-program.amazon.com/home</a> 页面的导航中找到Product Linking,在其下拉菜单中可以获得单个商品的链接(Product Links),定制各种尺寸的横幅(Banner Links),通过搜索等定制亚马逊提供的广告(Native Shopping Ads),还有就是可以通过在mobile的网页中嵌入弹出广告(Mobile Popover),再就是定制任意亚马逊链接的方式,以文本链接展示( Link To Any Page),以上所有的使用,需要自己查询商品或者设置查询条件以及copy页面链接,然后在操作页面会生成对应的iframe代码或者JavaScript代码。可以将这些代码直接嵌套或者优化后嵌套到我们的网站上,这样别人通过网站的广告点击购买就可以获得收益了。</p><h3 id="3、进阶使用"><a href="#3、进阶使用" class="headerlink" title="3、进阶使用"></a>3、进阶使用</h3><h4 id="3-1、快速加入商品"><a href="#3-1、快速加入商品" class="headerlink" title="3.1、快速加入商品"></a>3.1、快速加入商品</h4><p>在联盟的管理页面操作商品总是略有不便,所以亚马逊提供了一个工具SiteStripe,当你登录联盟账号之后,再在浏览器标签打开亚马逊(<a href="http://www.amazon.com)的时候,顶部会出现这个插件,可以在浏览商品的时候方便快捷的生成文本URL(短链接及长链接),生成商品的图片代码以及图文代码,这些可以快速的作为推广材料" target="_blank" rel="noopener">www.amazon.com)的时候,顶部会出现这个插件,可以在浏览商品的时候方便快捷的生成文本URL(短链接及长链接),生成商品的图片代码以及图文代码,这些可以快速的作为推广材料</a></p><h4 id="3-2、使用Publisher-Studio-Management-插件"><a href="#3-2、使用Publisher-Studio-Management-插件" class="headerlink" title="3.2、使用Publisher Studio Management 插件"></a>3.2、使用Publisher Studio Management 插件</h4><p>然而没有FQ,所以插件安装不方便,没有细细探究。</p><h4 id="3-3、Link-Checker"><a href="#3-3、Link-Checker" class="headerlink" title="3.3、Link Checker"></a>3.3、Link Checker</h4><p>检测推广链接是否失效,商品是亚马逊提供的,难免因产品变动而链接失效,有时间久check一下好了</p><h3 id="4、高级使用"><a href="#4、高级使用" class="headerlink" title="4、高级使用"></a>4、高级使用</h3><p>高级的使用,叫我说就是使用Product Advertising API,这个工具已经很强大了,当然,也非常不错,这里简单介绍一下功能,具体实践还没有进行。使用这个功能需要开通AWS服务,并且生成对应的AccessKey ID 和 Secret Key,否则无法使用。</p><h4 id="4-1、搜索功能(ItemSearch)"><a href="#4-1、搜索功能(ItemSearch)" class="headerlink" title="4.1、搜索功能(ItemSearch)"></a>4.1、搜索功能(ItemSearch)</h4><p>通过API可以直接查询商品列表,返回商品信息,多种查询条件,多种返回数据格式,可以任意定制,总之,功能很强大。</p><h4 id="4-2、查询功能(Lookup)"><a href="#4-2、查询功能(Lookup)" class="headerlink" title="4.2、查询功能(Lookup)"></a>4.2、查询功能(Lookup)</h4><p>可以通过API查询指定节点的浏览节点信息,包括子节点及父节点信息<br>可以通过API查询指定商品的详细信息,详情等,参数比较多,返回格式数据多样<br>可以通过API查询指定商品的相关商品,返回相关商品的标识和名称等,多种返回数据格式</p><h4 id="4-3、购物车功能(Cart)"><a href="#4-3、购物车功能(Cart)" class="headerlink" title="4.3、购物车功能(Cart)"></a>4.3、购物车功能(Cart)</h4><p>这里提供了购物车的初始化及增删改查加清空,以及支付链接,详细信息太多,不能一一言表,还是去看API吧。<br><em>备注:搜索功能的数据都是以XML格式返回的.</em><br>一个简单的说明图示:<br><a href="http://www.processon.com/chart_image/59812599e4b0de2518b32daf.png" title="Product Advertising API" target="_blank" rel="noopener"><img src="http://www.processon.com/chart_image/59812599e4b0de2518b32daf.png" alt="Product Advertising API" title="Product Advertising API"></a><br>参考:<br><a href="https://affiliate-program.amazon.com" target="_blank" rel="noopener">https://affiliate-program.amazon.com</a><br><a href="https://affiliate-program.amazon.com/home" target="_blank" rel="noopener">https://affiliate-program.amazon.com/home</a><br><a href="http://docs.aws.amazon.com/zh_cn/AWSECommerceService/latest/DG/Welcome.html" target="_blank" rel="noopener">http://docs.aws.amazon.com/zh_cn/AWSECommerceService/latest/DG/Welcome.html</a><br><a href="http://webservices.amazon.com/scratchpad/index.html?rw_useCurrentProtocol=1" target="_blank" rel="noopener">http://webservices.amazon.com/scratchpad/index.html?rw_useCurrentProtocol=1</a></p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> Amazon </tag>
</tags>
</entry>
<entry>
<title>Centos配置JAVA环境</title>
<link href="/2017/centos7-setting-the-java-env/"/>
<url>/2017/centos7-setting-the-java-env/</url>
<content type="html"><![CDATA[<p>便利贴记录<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">JAVA_HOME=/usr/jdk8</span><br><span class="line">PATH=$JAVA_HOME/bin:$PATH</span><br><span class="line">CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar</span><br><span class="line">export JAVA_HOME</span><br><span class="line">export PATH</span><br><span class="line">export CLASSPATH</span><br></pre></td></tr></table></figure></p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> Centos7 </tag>
<tag> JAVA </tag>
</tags>
</entry>
<entry>
<title>基于JPA的Specification查询的工具类SpecificationFactory</title>
<link href="/2017/spring-data-jpa-specificationfact-util/"/>
<url>/2017/spring-data-jpa-specificationfact-util/</url>
<content type="html"><![CDATA[<p>一个简单的Specification查询的工具类,可以自行扩展,扩展方法就是将一些手写创建的Specification语句抽象到一个方法内,写到工具类里。</p><h3 id="1、代码如下:"><a href="#1、代码如下:" class="headerlink" title="1、代码如下:"></a>1、代码如下:</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line">import org.springframework.data.jpa.domain.Specification;</span><br><span class="line">import java.util.Collection;</span><br><span class="line">/**</span><br><span class="line"> * Created by Administrator on 2017/7/13 0013.</span><br><span class="line"> */</span><br><span class="line">public final class SpecificationFactory {</span><br><span class="line"> /**</span><br><span class="line"> * 模糊查询,匹配对应字段</span><br><span class="line"> * @param attribute</span><br><span class="line"> * @param value</span><br><span class="line"> * @return</span><br><span class="line"> */</span><br><span class="line"> public static Specification containsLike(String attribute, String value) {</span><br><span class="line"> return (root, query, cb) -&gt; cb.like(root.get(attribute), "%" + value + "%");</span><br><span class="line"> }</span><br><span class="line"> /**</span><br><span class="line"> * 某字段的值等于value的查询条件</span><br><span class="line"> * @param attribute</span><br><span class="line"> * @param value</span><br><span class="line"> * @return</span><br><span class="line"> */</span><br><span class="line"> public static Specification equal(String attribute, Object value) {</span><br><span class="line"> return (root, query, cb) -&gt; cb.equal(root.get(attribute),value);</span><br><span class="line"> }</span><br><span class="line"> /**</span><br><span class="line"> * 获取对应属性的值所在区间</span><br><span class="line"> * @param attribute</span><br><span class="line"> * @param min</span><br><span class="line"> * @param max</span><br><span class="line"> * @return</span><br><span class="line"> */</span><br><span class="line"> public static Specification isBetween(String attribute, int min, int max) {</span><br><span class="line"> return (root, query, cb) -&gt; cb.between(root.get(attribute), min, max);</span><br><span class="line"> }</span><br><span class="line"> public static Specification isBetween(String attribute, double min, double max) {</span><br><span class="line"> return (root, query, cb) -&gt; cb.between(root.get(attribute), min, max);</span><br><span class="line"> }</span><br><span class="line"> /**</span><br><span class="line"> * 通过属性名和集合实现in查询</span><br><span class="line"> * @param attribute</span><br><span class="line"> * @param c</span><br><span class="line"> * @return</span><br><span class="line"> */</span><br><span class="line"> public static Specification in(String attribute, Collection c) {</span><br><span class="line"> return (root, query, cb) -&gt; root.get(attribute).in(c);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="2、用法"><a href="#2、用法" class="headerlink" title="2、用法"></a>2、用法</h3><pre><code>Specification&lt;Customer&gt; spec2 = Specifications .where(SpecificationFactory.containsLike("firstName","bau")) .or(SpecificationFactory.containsLike("lastName","bau"));</code></pre>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> spring-data-jpa </tag>
</tags>
</entry>
<entry>
<title>Spring Boot配置文件中的参数配置参考手册</title>
<link href="/2017/spring-boot-properties-setting-handbook/"/>
<url>/2017/spring-boot-properties-setting-handbook/</url>
<content type="html"><![CDATA[<p>经常会看到群里有人问怎么配置Spring Boot的配置文件及对应参数,这里可以做一个参考。</p><p>参考文档:<a href="http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#common-application-properties" target="_blank" rel="noopener">http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#common-application-properties</a></p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> configure </tag>
<tag> spring boot </tag>
</tags>
</entry>
<entry>
<title>Spring Security 系列:A Starter</title>
<link href="/2017/spring-security-a-starter/"/>
<url>/2017/spring-security-a-starter/</url>
<content type="html"><![CDATA[<p>Spring Security为基于Java的企业软件应用程序提供了一个全面的安全解决方案。正如您将在这个参考指南中发现的那样,我们已经尝试为您提供一个有用的、高度可配置的安全系统。<br>参考文档:(持续更新)<br><a href="https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle" target="_blank" rel="noopener">https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle</a></p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> Spring Security </tag>
</tags>
</entry>
<entry>
<title>基于JPA的分页查询PageRequest的工具类PageUtil</title>
<link href="/2017/spring-data-jpa-pageutil/"/>
<url>/2017/spring-data-jpa-pageutil/</url>
<content type="html"><![CDATA[<p>学习Spring Data JPA有一段时间了,今天开始整理基于JPA的一些东西,比如这篇文章要分享的PageUtil。<br>解决的问题是,通过静态实现快速构造Pageable的实例,在分页查询的时候,写代码也更简单。</p><hr><h3 id="1、代码如下:"><a href="#1、代码如下:" class="headerlink" title="1、代码如下:"></a>1、代码如下:</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">import org.springframework.data.domain.PageRequest;</span><br><span class="line">import org.springframework.data.domain.Sort;</span><br><span class="line"></span><br><span class="line">public class PageUtil {</span><br><span class="line"> public static PageRequest getPageRequest(Integer pageIndex, Integer pageSize, Sort sort){</span><br><span class="line"> //默认页面为0,</span><br><span class="line"> if(pageIndex==null || pageIndex&lt;1){</span><br><span class="line"> pageIndex = 0;</span><br><span class="line"> }else{</span><br><span class="line"> pageIndex = pageIndex-1;</span><br><span class="line"> }</span><br><span class="line"> //默认页面大小20</span><br><span class="line"> if(pageSize==null || pageSize&lt;1){</span><br><span class="line"> pageSize = 20;</span><br><span class="line"> }</span><br><span class="line"> //默认采用ID倒叙排列</span><br><span class="line"> if(sort==null){</span><br><span class="line"> sort = new Sort(Sort.Direction.DESC,"id");</span><br><span class="line"> }</span><br><span class="line"> return new PageRequest(pageIndex,pageSize,sort);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public static PageRequest getPageRequest(){</span><br><span class="line"> return getPageRequest(null,null,null);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public static PageRequest getPageRequest(Integer pageIndex,Integer pageSize){</span><br><span class="line"> return getPageRequest(pageIndex,pageSize,null);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="2、使用方法"><a href="#2、使用方法" class="headerlink" title="2、使用方法"></a>2、使用方法</h3><p><code>Pageable page = PageUtil.getPageRequest(pageIndex,pageSize,null);</code></p><h3 id="3、解说"><a href="#3、解说" class="headerlink" title="3、解说"></a>3、解说</h3><p>通过不同参数的重载,实现方便灵活的构建Pageable的实例,设置一些默认参数:</p><ul><li>默认第一页,pageIndex=0</li><li>默认每页数据二十条,pageSize=20</li><li>默认查询为ID倒序,new Sort(Sort.Direction.DESC,”id”)</li></ul><p>比较简单,如有建议,欢迎留言</p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> spring-data-jpa </tag>
<tag> PageUtil </tag>
</tags>
</entry>
<entry>
<title>Spring Data JPA系列:数据查询(Specification)(二)</title>
<link href="/2017/spring-data-jpa-Specification-2nd/"/>
<url>/2017/spring-data-jpa-Specification-2nd/</url>
<content type="html"><![CDATA[<p>写了一系列入门文章之后,博客也有了一些访问量,按照计划,对数据查询进行深入一些的探究,包括</p><ul><li>inner join查询</li><li>连接对象的属性值查询</li><li>in条件查询</li><li>left join查询<br>还是入门级的示例,更深入的用法需要在实际场景中深化。</li></ul><h3 id="1、更改Customer类"><a href="#1、更改Customer类" class="headerlink" title="1、更改Customer类"></a>1、更改Customer类</h3><p>增加@OneToMany注解的订单对象<br>需要注意的是,这次增加了Lombok依赖,一个简化对象类定义的插件,详见:<a href="https://projectlombok.org/" target="_blank" rel="noopener">https://projectlombok.org/</a><br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line">import lombok.AllArgsConstructor;</span><br><span class="line">import lombok.Data;</span><br><span class="line">import lombok.NoArgsConstructor;</span><br><span class="line">import org.hibernate.annotations.NamedQuery;</span><br><span class="line">import javax.persistence.*;</span><br><span class="line">import java.util.List;</span><br><span class="line">@Entity</span><br><span class="line">@Data</span><br><span class="line">@AllArgsConstructor</span><br><span class="line">@NoArgsConstructor</span><br><span class="line">@NamedQuery(name="Customer.findByFirstName",query = "select c from Customer c where c.firstName = ?1")</span><br><span class="line">public class Customer {</span><br><span class="line"> @Id</span><br><span class="line"> @GeneratedValue(strategy=GenerationType.AUTO)</span><br><span class="line"> private Long id;</span><br><span class="line"> private String firstName;</span><br><span class="line"> private String lastName;</span><br><span class="line"></span><br><span class="line"> //一对多,一个客户对应多个订单,关联的字段是订单里的cId字段</span><br><span class="line"> @OneToMany</span><br><span class="line"> @JoinColumn(name = "cId")</span><br><span class="line"> private List&lt;MyOrder&gt; myOrders;</span><br><span class="line"> public Customer(String firstName, String lastName) {</span><br><span class="line"> this.firstName = firstName;</span><br><span class="line"> this.lastName = lastName;</span><br><span class="line"> }</span><br><span class="line"> @Override</span><br><span class="line"> public String toString() {</span><br><span class="line"> return String.format(</span><br><span class="line"> "Customer[id=%d, firstName='%s', lastName='%s']",</span><br><span class="line"> id, firstName, lastName);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><h3 id="2、增加MyOrder类"><a href="#2、增加MyOrder类" class="headerlink" title="2、增加MyOrder类"></a>2、增加MyOrder类</h3><pre><code>我的订单对象</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line">import lombok.AllArgsConstructor;</span><br><span class="line">import lombok.Data;</span><br><span class="line">import lombok.NoArgsConstructor;</span><br><span class="line">import javax.persistence.*;</span><br><span class="line">import java.math.BigDecimal;</span><br><span class="line">/**</span><br><span class="line"> * Created by Administrator on 2017/7/17 0017.</span><br><span class="line"> */</span><br><span class="line">@Entity</span><br><span class="line">@Data</span><br><span class="line">@AllArgsConstructor</span><br><span class="line">@NoArgsConstructor</span><br><span class="line">public class MyOrder {</span><br><span class="line"> @Id</span><br><span class="line"> @GeneratedValue(strategy = GenerationType.AUTO)</span><br><span class="line"> private Long id;</span><br><span class="line"> private String code;</span><br><span class="line"> private Long cId;</span><br><span class="line"> private BigDecimal total;</span><br><span class="line"> //实体映射重复列必须设置:insertable = false,updatable = false</span><br><span class="line"> @OneToOne</span><br><span class="line"> @JoinColumn(name = "cId",insertable = false,updatable = false)</span><br><span class="line"> private Customer customer;</span><br><span class="line"> @Override</span><br><span class="line"> public String toString() {</span><br><span class="line"> return "MyOrder{" +</span><br><span class="line"> "id=" + id +</span><br><span class="line"> ", code='" + code + '\'' +</span><br><span class="line"> ", cId=" + cId +</span><br><span class="line"> ", total=" + total +</span><br><span class="line"> ", customer=" + customer +</span><br><span class="line"> '}';</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="3、新增MyOrderRepository类"><a href="#3、新增MyOrderRepository类" class="headerlink" title="3、新增MyOrderRepository类"></a>3、新增MyOrderRepository类</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">这里主要是继承JpaSpecificationExecutor接口,进行Specification查询</span><br><span class="line"></span><br><span class="line">import com.example.demo.dto.MyOrder;</span><br><span class="line">import org.springframework.data.jpa.repository.JpaSpecificationExecutor;</span><br><span class="line">import org.springframework.data.repository.CrudRepository;</span><br><span class="line">/**</span><br><span class="line"> * Created by Administrator on 2017/7/17 0017.</span><br><span class="line"> */</span><br><span class="line">public interface MyOrderRepository extends JpaSpecificationExecutor&lt;MyOrder&gt;,CrudRepository&lt;MyOrder,Long&gt; {</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="4、新增ShoppingController类"><a href="#4、新增ShoppingController类" class="headerlink" title="4、新增ShoppingController类"></a>4、新增ShoppingController类</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br></pre></td><td class="code"><pre><span class="line">import com.example.demo.dto.Customer;</span><br><span class="line">import com.example.demo.dto.MyOrder;</span><br><span class="line">import com.example.demo.repositories.MyOrderRepository;</span><br><span class="line">import org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line">import org.springframework.data.domain.Page;</span><br><span class="line">import org.springframework.data.domain.PageRequest;</span><br><span class="line">import org.springframework.data.domain.Pageable;</span><br><span class="line">import org.springframework.data.domain.Sort;</span><br><span class="line">import org.springframework.data.jpa.domain.Specification;</span><br><span class="line">import org.springframework.stereotype.Controller;</span><br><span class="line">import org.springframework.web.bind.annotation.RequestMapping;</span><br><span class="line">import javax.persistence.criteria.*;</span><br><span class="line">@Controller</span><br><span class="line">@RequestMapping("/shop")</span><br><span class="line">public class ShoppingController {</span><br><span class="line"> @Autowired</span><br><span class="line"> private MyOrderRepository myOrderRepository;</span><br><span class="line"> /**</span><br><span class="line"> * 内连接查询</span><br><span class="line"> */</span><br><span class="line"> @RequestMapping("/q1")</span><br><span class="line"> public void specification1(){</span><br><span class="line"> //根据查询结果,声明返回值对象,这里要查询用户的订单列表,所以声明返回对象为MyOrder</span><br><span class="line"> Specification&lt;MyOrder&gt; spec = new Specification&lt;MyOrder&gt;() {</span><br><span class="line"> //Root&lt;X&gt; 根查询,默认与声明相同</span><br><span class="line"> @Override</span><br><span class="line"> public Predicate toPredicate(Root&lt;MyOrder&gt; root, CriteriaQuery&lt;?&gt; query, CriteriaBuilder cb) {</span><br><span class="line"> //声明并创建MyOrder的CriteriaQuery对象</span><br><span class="line"> CriteriaQuery&lt;MyOrder&gt; q1 = cb.createQuery(MyOrder.class);</span><br><span class="line"> //连接的时候,要以声明的根查询对象(这里是root,也可以自己创建)进行join</span><br><span class="line"> //Join&lt;Z,X&gt;是Join生成的对象,这里的Z是被连接的对象,X是目标对象,</span><br><span class="line"> // 连接的属性字段是被连接的对象在目标对象的属性,这里是我们在MyOrder内声明的customer</span><br><span class="line"> //join的第二个参数是可选的,默认是JoinType.INNER(内连接 inner join),也可以是JoinType.LEFT(左外连接 left join)</span><br><span class="line"> Join&lt;Customer,MyOrder&gt; myOrderJoin = root.join("customer",JoinType.INNER);</span><br><span class="line"> //用CriteriaQuery对象拼接查询条件,这里只增加了一个查询条件,cId=1</span><br><span class="line"> q1.select(myOrderJoin).where(cb.equal(root.get("cId"),1));</span><br><span class="line"> //通过getRestriction获得Predicate对象</span><br><span class="line"> Predicate p1= q1.getRestriction();</span><br><span class="line"> //返回对象</span><br><span class="line"> return p1;</span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line"> resultPrint(spec);</span><br><span class="line"> }</span><br><span class="line"> /**</span><br><span class="line"> * 增加查询条件,关联的对象Customer的对象值</span><br><span class="line"> */</span><br><span class="line"> @RequestMapping("/q2")</span><br><span class="line"> public void specification2(){</span><br><span class="line"> Specification&lt;MyOrder&gt; spec = new Specification&lt;MyOrder&gt;() {</span><br><span class="line"> @Override</span><br><span class="line"> public Predicate toPredicate(Root&lt;MyOrder&gt; root, CriteriaQuery&lt;?&gt; query, CriteriaBuilder cb) {</span><br><span class="line"> CriteriaQuery&lt;MyOrder&gt; q1 = cb.createQuery(MyOrder.class);</span><br><span class="line"> Join&lt;Customer,MyOrder&gt; myOrderJoin = root.join("customer");</span><br><span class="line"> q1.select(myOrderJoin)</span><br><span class="line"> .where(</span><br><span class="line"> cb.equal(root.get("cId"),1),//cId=1</span><br><span class="line"> cb.equal(root.get("customer").get("firstName"),"Jack")//对象customer的firstName=Jack</span><br><span class="line"> );</span><br><span class="line"> Predicate p1= q1.getRestriction();</span><br><span class="line"> return p1;</span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line"> resultPrint(spec);</span><br><span class="line"> }</span><br><span class="line"> /**</span><br><span class="line"> * in的条件查询</span><br><span class="line"> * 需要将对应的结果集以root.get("attributeName").in(Object.. values)的方式传入</span><br><span class="line"> * values支持多个参数,支持对象(Object),表达式Expression&lt;?&gt;,集合Collection以及Expression&lt;Collection&lt;?&gt;&gt;</span><br><span class="line"> */</span><br><span class="line"> @RequestMapping("/q3")</span><br><span class="line"> public void specification3(){</span><br><span class="line"> Specification&lt;MyOrder&gt; spec = new Specification&lt;MyOrder&gt;() {</span><br><span class="line"> @Override</span><br><span class="line"> public Predicate toPredicate(Root&lt;MyOrder&gt; root, CriteriaQuery&lt;?&gt; query, CriteriaBuilder cb) {</span><br><span class="line"> CriteriaQuery&lt;MyOrder&gt; q1 = cb.createQuery(MyOrder.class);</span><br><span class="line"> Join&lt;Customer,MyOrder&gt; myOrderJoin = root.join("customer");</span><br><span class="line"> q1.select(myOrderJoin)</span><br><span class="line"> .where(</span><br><span class="line"> cb.equal(root.get("cId"),1)</span><br><span class="line"> ,root.get("id").in(1,2,4)</span><br><span class="line"> );</span><br><span class="line"></span><br><span class="line"> Predicate p1= q1.getRestriction();</span><br><span class="line"> return p1;</span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line"> resultPrint(spec);</span><br><span class="line"> }</span><br><span class="line"> /**</span><br><span class="line"> * 左外链接查询,对比inner join,</span><br><span class="line"> * 这里只是改了一个参数,将JoinType.INNER改成JoinType.LEFT</span><br><span class="line"> *</span><br><span class="line"> * 注意,当前示例不支持JoinType.RIGHT,用的比较少,没有探究</span><br><span class="line"> */</span><br><span class="line"> @RequestMapping("/q4")</span><br><span class="line"> public void specification4(){</span><br><span class="line"> Specification&lt;MyOrder&gt; spec = new Specification&lt;MyOrder&gt;() {</span><br><span class="line"> @Override</span><br><span class="line"> public Predicate toPredicate(Root&lt;MyOrder&gt; root, CriteriaQuery&lt;?&gt; query, CriteriaBuilder cb) {</span><br><span class="line"> CriteriaQuery&lt;MyOrder&gt; q1 = cb.createQuery(MyOrder.class);</span><br><span class="line"> Join&lt;Customer,MyOrder&gt; myOrderJoin = root.join("customer",JoinType.LEFT);</span><br><span class="line"> q1.select(myOrderJoin).where(cb.equal(root.get("cId"),1));</span><br><span class="line"> Predicate p1= q1.getRestriction();</span><br><span class="line"> return p1;</span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line"> resultPrint(spec);</span><br><span class="line"> }</span><br><span class="line"> /***</span><br><span class="line"> *输出分页信息</span><br><span class="line"> **/</span><br><span class="line"> private void resultPrint(Specification&lt;MyOrder&gt; spec) {</span><br><span class="line"> //分页查询</span><br><span class="line"> Pageable pageable = new PageRequest(0,10, Sort.Direction.DESC,"id");</span><br><span class="line"> //查询的分页结果</span><br><span class="line"> Page&lt;MyOrder&gt; page =myOrderRepository.findAll(spec,pageable);</span><br><span class="line"> System.out.println(page);</span><br><span class="line"> System.out.println(page.getTotalElements());</span><br><span class="line"> System.out.println(page.getTotalPages());</span><br><span class="line"> for (MyOrder c:page.getContent()){</span><br><span class="line"> System.out.println(c.toString());</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><pre><code>内容已经写进注释了,请读源码,有问题请留言。</code></pre><h3 id="5、测试"><a href="#5、测试" class="headerlink" title="5、测试"></a>5、测试</h3><h4 id="1)、内连接查询及结果:"><a href="#1)、内连接查询及结果:" class="headerlink" title="1)、内连接查询及结果:"></a>1)、内连接查询及结果:</h4><ul><li>URL:<a href="http://localhost:8080/shop/q1" target="_blank" rel="noopener">http://localhost:8080/shop/q1</a></li><li>结果:<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">Hibernate: select myorder0_.id as id1_1_, myorder0_.c_id as c_id2_1_, myorder0_.code as code3_1_, myorder0_.total as total4_1_ from my_order myorder0_ inner join customer customer1_ on myorder0_.c_id=customer1_.id where myorder0_.c_id=1 order by myorder0_.id desc limit ?</span><br><span class="line">Hibernate: select customer0_.id as id1_0_0_, customer0_.first_name as first_na2_0_0_, customer0_.last_name as last_nam3_0_0_ from customer customer0_ where customer0_.id=?</span><br><span class="line">Page 1 of 1 containing com.example.demo.dto.MyOrder instances</span><br><span class="line">5</span><br><span class="line">1</span><br><span class="line">MyOrder{id=5, code='123455', cId=1, total=55.23, customer=Customer[id=1, firstName='Jack', lastName='Bauer']}</span><br><span class="line">MyOrder{id=4, code='123459', cId=1, total=9.99, customer=Customer[id=1, firstName='Jack', lastName='Bauer']}</span><br><span class="line">MyOrder{id=3, code='123458', cId=1, total=11.90, customer=Customer[id=1, firstName='Jack', lastName='Bauer']}</span><br><span class="line">MyOrder{id=2, code='123457', cId=1, total=20.90, customer=Customer[id=1, firstName='Jack', lastName='Bauer']}</span><br><span class="line">MyOrder{id=1, code='123456', cId=1, total=11.10, customer=Customer[id=1, firstName='Jack', lastName='Bauer']}</span><br></pre></td></tr></table></figure></li></ul><h4 id="2)、关联对象条件查询及结果:"><a href="#2)、关联对象条件查询及结果:" class="headerlink" title="2)、关联对象条件查询及结果:"></a>2)、关联对象条件查询及结果:</h4><ul><li>URL:<a href="http://localhost:8080/shop/q2" target="_blank" rel="noopener">http://localhost:8080/shop/q2</a></li><li>结果:<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">Hibernate: select myorder0_.id as id1_1_, myorder0_.c_id as c_id2_1_, myorder0_.code as code3_1_, myorder0_.total as total4_1_ from my_order myorder0_ inner join customer customer1_ on myorder0_.c_id=customer1_.id where myorder0_.c_id=1 and customer1_.first_name=? order by myorder0_.id desc limit ?</span><br><span class="line">Hibernate: select customer0_.id as id1_0_0_, customer0_.first_name as first_na2_0_0_, customer0_.last_name as last_nam3_0_0_ from customer customer0_ where customer0_.id=?</span><br><span class="line">Page 1 of 1 containing com.example.demo.dto.MyOrder instances</span><br><span class="line">5</span><br><span class="line">1</span><br><span class="line">MyOrder{id=5, code='123455', cId=1, total=55.23, customer=Customer[id=1, firstName='Jack', lastName='Bauer']}</span><br><span class="line">MyOrder{id=4, code='123459', cId=1, total=9.99, customer=Customer[id=1, firstName='Jack', lastName='Bauer']}</span><br><span class="line">MyOrder{id=3, code='123458', cId=1, total=11.90, customer=Customer[id=1, firstName='Jack', lastName='Bauer']}</span><br><span class="line">MyOrder{id=2, code='123457', cId=1, total=20.90, customer=Customer[id=1, firstName='Jack', lastName='Bauer']}</span><br><span class="line">MyOrder{id=1, code='123456', cId=1, total=11.10, customer=Customer[id=1, firstName='Jack', lastName='Bauer']}</span><br></pre></td></tr></table></figure></li></ul><h4 id="3)、in条件查询测试及结果:"><a href="#3)、in条件查询测试及结果:" class="headerlink" title="3)、in条件查询测试及结果:"></a>3)、in条件查询测试及结果:</h4><ul><li>URL:<a href="http://localhost:8080/shop/q3" target="_blank" rel="noopener">http://localhost:8080/shop/q3</a></li><li>结果:<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Hibernate: select myorder0_.id as id1_1_, myorder0_.c_id as c_id2_1_, myorder0_.code as code3_1_, myorder0_.total as total4_1_ from my_order myorder0_ inner join customer customer1_ on myorder0_.c_id=customer1_.id where myorder0_.c_id=1 and (myorder0_.id in (1 , 2 , 4)) order by myorder0_.id desc limit ?</span><br><span class="line">Hibernate: select customer0_.id as id1_0_0_, customer0_.first_name as first_na2_0_0_, customer0_.last_name as last_nam3_0_0_ from customer customer0_ where customer0_.id=?</span><br><span class="line">Page 1 of 1 containing com.example.demo.dto.MyOrder instances</span><br><span class="line">3</span><br><span class="line">1</span><br><span class="line">MyOrder{id=4, code='123459', cId=1, total=9.99, customer=Customer[id=1, firstName='Jack', lastName='Bauer']}</span><br><span class="line">MyOrder{id=2, code='123457', cId=1, total=20.90, customer=Customer[id=1, firstName='Jack', lastName='Bauer']}</span><br><span class="line">MyOrder{id=1, code='123456', cId=1, total=11.10, customer=Customer[id=1, firstName='Jack', lastName='Bauer']}</span><br></pre></td></tr></table></figure></li></ul><h4 id="4)、左外连接测试及结果:"><a href="#4)、左外连接测试及结果:" class="headerlink" title="4)、左外连接测试及结果:"></a>4)、左外连接测试及结果:</h4><ul><li>URL:<a href="http://localhost:8080/shop/q4" target="_blank" rel="noopener">http://localhost:8080/shop/q4</a></li><li>结果:<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">Hibernate: select myorder0_.id as id1_1_, myorder0_.c_id as c_id2_1_, myorder0_.code as code3_1_, myorder0_.total as total4_1_ from my_order myorder0_ left outer join customer customer1_ on myorder0_.c_id=customer1_.id where myorder0_.c_id=1 order by myorder0_.id desc limit ?</span><br><span class="line">Hibernate: select customer0_.id as id1_0_0_, customer0_.first_name as first_na2_0_0_, customer0_.last_name as last_nam3_0_0_ from customer customer0_ where customer0_.id=?</span><br><span class="line">Page 1 of 1 containing com.example.demo.dto.MyOrder instances</span><br><span class="line">5</span><br><span class="line">1</span><br><span class="line">MyOrder{id=5, code='123455', cId=1, total=55.23, customer=Customer[id=1, firstName='Jack', lastName='Bauer']}</span><br><span class="line">MyOrder{id=4, code='123459', cId=1, total=9.99, customer=Customer[id=1, firstName='Jack', lastName='Bauer']}</span><br><span class="line">MyOrder{id=3, code='123458', cId=1, total=11.90, customer=Customer[id=1, firstName='Jack', lastName='Bauer']}</span><br><span class="line">MyOrder{id=2, code='123457', cId=1, total=20.90, customer=Customer[id=1, firstName='Jack', lastName='Bauer']}</span><br><span class="line">MyOrder{id=1, code='123456', cId=1, total=11.10, customer=Customer[id=1, firstName='Jack', lastName='Bauer']}</span><br></pre></td></tr></table></figure></li></ul><p>参考:<br>官方文档:<a href="https://docs.spring.io/spring-data/jpa/docs/current/reference/html" target="_blank" rel="noopener">https://docs.spring.io/spring-data/jpa/docs/current/reference/html</a><br>API官方文档:<a href="http://docs.spring.io/spring-data/data-jpa/docs/current/api/" target="_blank" rel="noopener">http://docs.spring.io/spring-data/data-jpa/docs/current/api/</a><br>JPQL文档:<a href="http://www.blogjava.net/calmJava/archive/2011/04/01/347450.html" target="_blank" rel="noopener">http://www.blogjava.net/calmJava/archive/2011/04/01/347450.html</a></p><p>DEMO示例:<a href="https://github.com/icnws/spring-data-jpa-demo" target="_blank" rel="noopener">https://github.com/icnws/spring-data-jpa-demo</a></p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> spring-data-jpa </tag>
<tag> specification </tag>
</tags>
</entry>
<entry>
<title>Redis: OOM command not allowed when used memory > ‘maxmemory’</title>
<link href="/2017/redis-oom-memory/"/>
<url>/2017/redis-oom-memory/</url>
<content type="html"><![CDATA[<h3 id="1、事故:"><a href="#1、事故:" class="headerlink" title="1、事故:"></a>1、事故:</h3><p>检查服务器,发现redis无法正常写入,大多数时候写入失败,打开redis的日志信息发现:<br><code>Redis: OOM command not allowed when used memory &gt; ‘maxmemory’</code><br>意思是Redis内存不足,可以在命令行中,通过 <code>info memory</code>查看当前redis 的内存设置信息,如下:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"># Memory</span><br><span class="line">used_memory:2365344</span><br><span class="line">used_memory_human:2.26M</span><br><span class="line">used_memory_rss:9953280</span><br><span class="line">used_memory_rss_human:9.49M</span><br><span class="line">used_memory_peak:2483552</span><br><span class="line">used_memory_peak_human:2.37M</span><br><span class="line">total_system_memory:16725504000</span><br><span class="line">total_system_memory_human:15.58G</span><br><span class="line">used_memory_lua:37888</span><br><span class="line">used_memory_lua_human:37.00K</span><br><span class="line">maxmemory:4194304</span><br><span class="line">maxmemory_human:4.00M</span><br><span class="line">maxmemory_policy:noeviction</span><br><span class="line">mem_fragmentation_ratio:4.21</span><br><span class="line">mem_allocator:jemalloc-4.0.3</span><br></pre></td></tr></table></figure></p><p>可以看到已用的和当前的设置,我这里是调整之后的数据,单位是byte</p><h3 id="2、方案:"><a href="#2、方案:" class="headerlink" title="2、方案:"></a>2、方案:</h3><p>通过whereis redis.conf找到redis的配置文件<br>打开文件并找到memory配置项,设置你需要的大小,比如:4194304,这是4GB的大小,注意memory的说明信息,这里的单位是byte</p><p>修改完成之后,reload当前redis服务,可能用到<br><code>service redis-server reload</code><br>或者<br><code>service redis-server force-reload</code><br>这样基本上就能解决上述问题了,如有其他问题还需一一对应解决之。</p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> redis </tag>
<tag> redis OOM </tag>
</tags>
</entry>
<entry>
<title>Spring Data JPA系列:数据查询(Specification)(一)</title>
<link href="/2017/spring-data-jpa-Specification-1st/"/>
<url>/2017/spring-data-jpa-Specification-1st/</url>
<content type="html"><![CDATA[<p>在JPA中,如果用@Query查询有诸多不便,因此JPA提供了基于Criteria API的查询,比@Query查询更灵活方便,这篇文章就简单说说Specification的简单使用。<br>这篇文章是参考:<a href="https://jverhoelen.github.io/spring-data-queries-jpa-criteria-api" title="Useing JPA Criteria API" target="_blank" rel="noopener">Useing JPA Criteria API</a> ,相关代码如下所示:</p><h3 id="1、定义一个继承JpaSpecificationExecutor的接口:"><a href="#1、定义一个继承JpaSpecificationExecutor的接口:" class="headerlink" title="1、定义一个继承JpaSpecificationExecutor的接口:"></a>1、定义一个继承<code>JpaSpecificationExecutor</code>的接口:</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">import com.example.demo.dto.Customer;</span><br><span class="line">import org.springframework.data.jpa.repository.JpaRepository;</span><br><span class="line">import org.springframework.data.jpa.repository.JpaSpecificationExecutor;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * Created by Administrator on 2017/7/12 0012.</span><br><span class="line"> */</span><br><span class="line">public interface CustomerSpecificationRepository extends JpaRepository&lt;Customer,Long&gt;,</span><br><span class="line"> JpaSpecificationExecutor&lt;Customer&gt; {</span><br><span class="line">}</span><br></pre></td></tr></table></figure><pre><code>这里只是继承接口声明的方法,比如</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">T findOne(Specification<T> spec);</span><br><span class="line">List<T> findAll(Specification<T> spec);</span><br><span class="line">Page<T> findAll(Specification<T> spec, Pageable pageable);</span><br><span class="line">List<T> findAll(Specification<T> spec, Sort sort);</span><br><span class="line">long count(Specification<T> spec);</span><br></pre></td></tr></table></figure><pre><code>包含了常用的查询单个对象,查询数据集合,查询分页数据集合,查询带排序参数的数据集合,查询数据的大小,这些都是常用的数据结果集,因此可以不用做其他定义即可直接使用。</code></pre><h3 id="2、创建SpecificationFactory工具类"><a href="#2、创建SpecificationFactory工具类" class="headerlink" title="2、创建SpecificationFactory工具类"></a>2、创建SpecificationFactory工具类</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">import org.springframework.data.jpa.domain.Specification;</span><br><span class="line">import javax.persistence.criteria.Path;</span><br><span class="line">/**</span><br><span class="line"> * Created by Administrator on 2017/7/13 0013.</span><br><span class="line"> */</span><br><span class="line">public final class SpecificationFactory {</span><br><span class="line"> public static Specification containsLike(String attribute, String value) {</span><br><span class="line"> return (root, query, cb) -&gt; cb.like(root.get(attribute), "%" + value + "%");</span><br><span class="line"> }</span><br><span class="line"> public static Specification isBetween(String attribute, int min, int max) {</span><br><span class="line"> return (root, query, cb) -&gt; cb.between(root.get(attribute), min, max);</span><br><span class="line"> }</span><br><span class="line"> public static Specification isBetween(String attribute, double min, double max) {</span><br><span class="line"> return (root, query, cb) -&gt; cb.between(root.get(attribute), min, max);</span><br><span class="line"> }</span><br><span class="line"> public static &lt;T extends Enum&lt;T&gt;&gt; Specification enumMatcher(String attribute, T queriedValue) {</span><br><span class="line"> return (root, query, cb) -&gt; {</span><br><span class="line"> Path&lt;T&gt; actualValue = root.get(attribute);</span><br><span class="line"> if (queriedValue == null) {</span><br><span class="line"> return null;</span><br><span class="line"> }</span><br><span class="line"> return cb.equal(actualValue, queriedValue);</span><br><span class="line"> };</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><pre><code>这个工具类定义了一些基本的查询,包括模糊匹配(containsLike),数值区间(isBetween)以及枚举类参数匹配(enumMatcher),这些也是在查询中常用的方法,在查询的时候,通过Specifications进行调用组织参数,即可获得接口Specification的实例,然后用于查询。</code></pre><h3 id="3、在CustomerController中添加测试方法"><a href="#3、在CustomerController中添加测试方法" class="headerlink" title="3、在CustomerController中添加测试方法"></a>3、在CustomerController中添加测试方法</h3><ul><li><p>初始化</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">@Autowired</span><br><span class="line">private CustomerSpecificationRepository csr;</span><br></pre></td></tr></table></figure></li><li><p>单一条件查询</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">@RequestMapping("/spec")</span><br><span class="line">public void specificationQuery(){</span><br><span class="line"> Specification&lt;Customer&gt; spec = SpecificationFactory.containsLike("lastName","bau");</span><br><span class="line"> Pageable pageable = new PageRequest(0,5, Sort.Direction.DESC,"id");</span><br><span class="line"> Page&lt;Customer&gt; page = csr.findAll(spec,pageable);</span><br><span class="line"> System.out.println(page);</span><br><span class="line"> System.out.println(page.getTotalElements());</span><br><span class="line"> System.out.println(page.getTotalPages());</span><br><span class="line"> for (Customer c:page.getContent()){</span><br><span class="line"> System.out.println(c.toString());</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><p>复合条件查询</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">@RequestMapping("/spec2")</span><br><span class="line">public void specificationQuery2(){</span><br><span class="line"> Specification&lt;Customer&gt; spec2 = Specifications</span><br><span class="line"> .where(SpecificationFactory.containsLike("firstName","bau"))</span><br><span class="line"> .or(SpecificationFactory.containsLike("lastName","bau"));</span><br><span class="line"> Pageable pageable = new PageRequest(0,5, Sort.Direction.DESC,"id");</span><br><span class="line"> Page&lt;Customer&gt; page = csr.findAll(spec2,pageable);</span><br><span class="line"> System.out.println(page);</span><br><span class="line"> System.out.println(page.getTotalElements());</span><br><span class="line"> System.out.println(page.getTotalPages());</span><br><span class="line"> for (Customer c:page.getContent()){</span><br><span class="line"> System.out.println(c.toString());</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ul><p>至此,使用Specification通过Criteria API进行查询,获得查询的结果集。相较于@Query方式的查询定义,更人性化和方便操作,后面在对Criteria API的使用进一步深入,会继续给出相关实践,敬请期待。</p><p>参考:<br>官方文档:<a href="https://docs.spring.io/spring-data/jpa/docs/current/reference/html" target="_blank" rel="noopener">https://docs.spring.io/spring-data/jpa/docs/current/reference/html</a><br>API官方文档:<a href="http://docs.spring.io/spring-data/data-jpa/docs/current/api/" target="_blank" rel="noopener">http://docs.spring.io/spring-data/data-jpa/docs/current/api/</a><br>JPQL文档:<a href="http://www.blogjava.net/calmJava/archive/2011/04/01/347450.html" target="_blank" rel="noopener">http://www.blogjava.net/calmJava/archive/2011/04/01/347450.html</a></p><p>DEMO示例:<a href="https://github.com/icnws/spring-data-jpa-demo" target="_blank" rel="noopener">https://github.com/icnws/spring-data-jpa-demo</a></p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> spring-data-jpa </tag>
<tag> specification </tag>
</tags>
</entry>
<entry>
<title>Java看源码如何方便看注释文档?</title>
<link href="/2017/how-to-read-original-code-convenient/"/>
<url>/2017/how-to-read-original-code-convenient/</url>
<content type="html"><![CDATA[<p>现在的JAVA项目大多用maven管理依赖,在maven的导入选项旁边有下载源码和文档,执行这个操作可以在看相关项目依赖的时候直接看对应的源码及文档注释很方便。<br>很多人对于问题都是求之于搜索引擎给出的答案,这样不是说不行,只是很浪费时间。<br>开始的时候我们没有入门可以借助文档和搜索引擎来达到快速入门的目的,在入门之后,很多问题应该求之于源码上,这个阶段,看源码是必经之路,如果你没有经过,那总有一天死都不知道怎么死的,就是这样。<br>继续说看源码,在IDEA内,按住Ctrl然后点击引用的类名即可进入对应的源码,然后在源码内有方法的定义和文档的说明,比如:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * The &lt;code&gt;CriteriaQuery&lt;/code&gt; interface defines functionality that is specific</span><br><span class="line"> * to top-level queries.</span><br><span class="line"> *</span><br><span class="line"> * @param &lt;T&gt; the type of the defined result</span><br><span class="line"> * @since Java Persistence 2.0</span><br><span class="line"> */</span><br><span class="line">public interface CriteriaQuery&lt;T&gt; extends AbstractQuery&lt;T&gt; {</span><br><span class="line"></span><br><span class="line"> /**</span><br><span class="line"> * Specify the item that is to be returned in the query result.</span><br><span class="line"> * Replaces the previously specified selection(s), if any.</span><br><span class="line"> *</span><br><span class="line"> * &lt;p&gt; Note: Applications using the string-based API may need to</span><br><span class="line"> * specify the type of the select item when it results from</span><br><span class="line"> * a get or join operation and the query result type is</span><br><span class="line"> * specified.</span><br><span class="line"> *</span><br><span class="line"> * &lt;pre&gt;</span><br><span class="line"> * For example:</span><br><span class="line"> *</span><br><span class="line"> * CriteriaQuery&lt;String&gt; q = cb.createQuery(String.class);</span><br><span class="line"> * Root&lt;Order&gt; order = q.from(Order.class);</span><br><span class="line"> * q.select(order.get("shippingAddress").&lt;String&gt;get("state"));</span><br><span class="line"> *</span><br><span class="line"> * CriteriaQuery&lt;Product&gt; q2 = cb.createQuery(Product.class);</span><br><span class="line"> * q2.select(q2.from(Order.class)</span><br><span class="line"> * .join("items")</span><br><span class="line"> * .&lt;Item,Product&gt;join("product"));</span><br><span class="line"> *</span><br><span class="line"> * &lt;/pre&gt;</span><br><span class="line"> *</span><br><span class="line"> * @param selection selection specifying the item that</span><br><span class="line"> * is to be returned in the query result</span><br><span class="line"> *</span><br><span class="line"> * @return the modified query</span><br><span class="line"> *</span><br><span class="line"> * @throws IllegalArgumentException if the selection is</span><br><span class="line"> * a compound selection and more than one selection</span><br><span class="line"> * item has the same assigned alias</span><br><span class="line"> */</span><br><span class="line"> CriteriaQuery&lt;T&gt; select(Selection&lt;? extends T&gt; selection);</span><br></pre></td></tr></table></figure></p><p>这里会遇到一个问题,一些example的代码并不好读,这个时候可以在对应的方法上,按Ctr+q即可看到该方法的文档如下:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">javax.persistence.criteria.CriteriaQuery</span><br><span class="line">CriteriaQuery&lt;T&gt; select(Selection&lt;? extends T&gt; selection)</span><br><span class="line">Specify the item that is to be returned in the query result. Replaces the previously specified selection(s), if any.</span><br><span class="line">Note: Applications using the string-based API may need to specify the type of the select item when it results from a get or join operation and the query result type is specified.</span><br><span class="line"> For example:</span><br><span class="line"></span><br><span class="line"> CriteriaQuery&lt;String&gt; q = cb.createQuery(String.class);</span><br><span class="line"> Root&lt;Order&gt; order = q.from(Order.class);</span><br><span class="line"> q.select(order.get("shippingAddress").&lt;String&gt;get("state"));</span><br><span class="line"></span><br><span class="line"> CriteriaQuery&lt;Product&gt; q2 = cb.createQuery(Product.class);</span><br><span class="line"> q2.select(q2.from(Order.class)</span><br><span class="line"> .join("items")</span><br><span class="line"> .&lt;Item,Product&gt;join("product"));</span><br></pre></td></tr></table></figure></p><p>同时在这个弹框里可以看到一个向上的箭头,点击这个箭头可以进入浏览器像阅读JAVA API一样阅读当前对象的API文档</p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> 读源码 </tag>
</tags>
</entry>
<entry>
<title>Spring Data JPA系列:数据更新(Update)</title>
<link href="/2017/spring-data-jpa-update/"/>
<url>/2017/spring-data-jpa-update/</url>
<content type="html"><![CDATA[<p>上次通过《Spring Data JPA系列:使用@Modifying修改(Modifying queries)》介绍了数据更新的方式,这种更新方式会很不方便,写的时候也比较麻烦,可以为更新密码、更新用户名等一些特殊的更新单独定义,但是对大多数数据操作是不方便的,比如我要更新一条有一百个字段的数据,这时候如果要通过Modifying方式就非常的不方便,因此,我们需要一种新的方式来解救。<br>通过阅读Spring-Data-JPA相关的文档和博客,找到了对应的解决方案,就是使用<code>save()</code>方法,经过测试,可用。<br>我们平时对<code>save()</code>方法的理解,大多是等同于<code>insert()</code>,主要是指新增一条数据,而JPA的<code>save()</code>方法包含了<code>merge()</code>的概念,就是说,如果save的对象不存在primary key或者primary key值在database内不存在的时候会新添加一条数据,如果primary key 存在并且primary key已经在database中存在,那就会依据primary key对该条数据进行更新,这是我们乐意见到的。</p><p>参考的文章:<a href="https://stackoverflow.com/questions/11881479/how-do-i-update-an-entity-using-spring-data-jpa" target="_blank" rel="noopener">https://stackoverflow.com/questions/11881479/how-do-i-update-an-entity-using-spring-data-jpa</a></p><p>相关描述如下:</p><p>Identity of entities is defined by their primary keys. Since firstname and lastname are not parts of the primary key, you cannot tell JPA to treat Users with the same firstnames and lastnames as equal if they have different userIds.</p><p>So, if you want to update a User identified by its firstname and lastname, you need to find that User by a query, and then change appropriate fields of the object your found. These changes will be flushed to the database automatically at the end of transaction, so that you don’t need to do anything to save these changes explicitly.</p><h5 id="EDIT"><a href="#EDIT" class="headerlink" title="EDIT:"></a>EDIT:</h5><p>Perhaps I should elaborate on overall semantics of JPA. There are two main approaches to design of persistence APIs:</p><ul><li>insert/update approach. When you need to modify the database you should call methods of persistence API explicitly: you call insert to insert an object, or update to save new state of the object to the database.</li><li>Unit of Work approach. In this case you have a set of objects managed by persistence library. All changes you make to these objects will be flushed to the database automatically at the end of Unit of Work (i.e. at the end of the current transaction in typical case). When you need to insert new record to the database, you make the corresponding object managed. Managed objects are identified by their primary keys, so that if you make an object with predefined primary key managed, it will be associated with the database record of the same id, and state of this object will be propagated to that record automatically.</li></ul><p>JPA follows the later approach. save() in Spring Data JPA is backed by merge() in plain JPA, therefore it makes your entity managed as described above. It means that calling save() on an object with predefined id will update the corresponding database record rather than insert a new one, and also explains why save() is not called create().</p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> spring-data-jpa </tag>
<tag> Update </tag>
</tags>
</entry>
<entry>
<title>Spring Boot:@RestController中.(点号)导致截断的问题</title>
<link href="/2017/spring-boot-restcontroller-with-dot-soulutions/"/>
<url>/2017/spring-boot-restcontroller-with-dot-soulutions/</url>
<content type="html"><![CDATA[<p>在测试<code>/api/v1/user/info/email/{email}</code>这个方法的时候@PathVariable无法正常接收参数,邮件地址中(.)后的值会被截断,在社区<a href="http://www.spring4all.com" target="_blank" rel="noopener">http://www.spring4all.com</a> 中通过小马哥和@杨小强的帮助下解决了这个问题,记录一下。</p><h3 id="1、局部修改"><a href="#1、局部修改" class="headerlink" title="1、局部修改"></a>1、局部修改</h3><p>比如当前的这个path中就确定一定会包含(.)这样的符号,可以通过配置路径为<code>/api/v1/user/info/email/{email:.*}</code>来解决</p><h3 id="2、全局配置"><a href="#2、全局配置" class="headerlink" title="2、全局配置"></a>2、全局配置</h3><p>全局配置是指在项目的Config文件里配置,代码如下:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">import org.springframework.context.annotation.Configuration;</span><br><span class="line">import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;</span><br><span class="line">import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * Created by Administrator on 2017/7/10 0010.</span><br><span class="line"> */</span><br><span class="line">@Configuration</span><br><span class="line">public class WebConfig extends WebMvcConfigurerAdapter {</span><br><span class="line"> @Override</span><br><span class="line"> public void configurePathMatch(PathMatchConfigurer configurer) {</span><br><span class="line"> configurer.setUseSuffixPatternMatch(false);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>通过这个,我发现,对WebMvcConfigurerAdapter不太熟悉,后面需要加深一下。</p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> spring boot </tag>
<tag> PathVariable </tag>
</tags>
</entry>
<entry>
<title>OKHTTP3简单工具类分享</title>
<link href="/2017/okhttp3-util-share/"/>
<url>/2017/okhttp3-util-share/</url>
<content type="html"><![CDATA[<h3 id="1、官网:"><a href="#1、官网:" class="headerlink" title="1、官网:"></a>1、官网:</h3><p><a href="https://square.github.io/okhttp/" target="_blank" rel="noopener">https://square.github.io/okhttp/</a></p><h3 id="2、工具类"><a href="#2、工具类" class="headerlink" title="2、工具类"></a>2、工具类</h3><p>代码如下:</p><pre><code>import okhttp3.*;import org.apache.commons.lang.StringUtils;import java.io.IOException;import java.util.Map;public class OkHttpUtil { private static final OkHttpClient mOkHttpClient = new OkHttpClient(); private static RequestBody staticRequestBoday = new FormBody.Builder().build(); private static String reqMethod="GET"; /** * 不会开启异步线程。 * @param request * @return * @throws IOException */ public static Response execute(Request request) throws IOException{ return mOkHttpClient.newCall(request).execute(); } /** * 开启异步线程访问网络 * @param request * @param responseCallback */ public static void enqueue(Request request, Callback responseCallback){ mOkHttpClient.newCall(request).enqueue(responseCallback); } public static String getStringFromServer(String url) throws IOException{ Request request = new Request.Builder().url(url).build(); Response response = execute(request); if (response.isSuccessful()) { String responseUrl = response.body().string(); return responseUrl; } else { throw new IOException("Unexpected code " + response); } } private static final String CHARSET_NAME = "UTF-8"; /*** * 返回Client对象 * @return */ public static OkHttpClient getClient() { return mOkHttpClient; } public static RequestBody staticRequestBoday(){ if(staticRequestBoday==null){ staticRequestBoday = new FormBody.Builder().build(); } return staticRequestBoday; } /** * 根据给定的值,创建Request对象 * 默认方法是GET,默认requestBody为空 * @param method * @param kvs * @param requestBody * @return */ public static Request buildRequest(String method, Map&lt;String,String&gt; kvs,RequestBody requestBody){ if(StringUtils.isBlank(method)){ method = reqMethod; } if(requestBody==null){ requestBody=staticRequestBoday; } String url =""; if(kvs!=null){ url=formatMap(kvs); }else{ return null; } Request request = new Request.Builder().method(method,requestBody) .url(url) .build(); return request; } /** * * @param kvs * @return */ public static Request buildRequest(Map&lt;String,String&gt; kvs){ return buildRequest(null,kvs,null); } /** * * @param method * @param kvs * @return */ public static Request buildRequest(String method,Map&lt;String,String&gt; kvs){ return buildRequest(method,kvs,null); } /** * * @param kvs * @param requestBody * @return */ public static Request buildRequest(Map&lt;String,String&gt; kvs,RequestBody requestBody){ return buildRequest(null,kvs,requestBody); } private static String formatMap(Map&lt;String, String&gt; map) { StringBuffer sb = new StringBuffer(""); for(String key:map.keySet()){ if(key.equals("url")){ continue; } sb.append(key+"="+map.get(key)+"&amp;"); } System.out.println(sb.toString()); String url = map.get("url")+"?"+sb.toString(); return url; }}</code></pre>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> JAVA </tag>
<tag> OKHTTP3 </tag>
</tags>
</entry>
<entry>
<title>Spring Data JPA系列:投影(Projection)的用法</title>
<link href="/2017/spring-data-jpa-Projection/"/>
<url>/2017/spring-data-jpa-Projection/</url>
<content type="html"><![CDATA[<p>在JPA的查询中,有一个不方便的地方,@Query注解,如果查询直接是<code>Select C from Customer c</code>,这时候,查询的返回对象就是Customer这个完整的对象,包含所有字段,对于我们的示例并没有什么问题,但是对于比较庞大的domain类,这个查询时就比较要命,并不是所有的字段都能用到,比较头疼。另外,如果定义<code>select c.firstName as firstName,c.lastName as lastName from Customer c</code>这个查询结果,返回的对象是Object类型,而且无法直接转换成Customer对象,这样用起来就不是很方便。<br>对于这种情况,JPA提供了一种声明方式来解决,即声明一个接口类,然后直接使用这个接口类接受返回的数据即可。下面奉上代码:</p><h3 id="1、增加CustomerProjection接口类"><a href="#1、增加CustomerProjection接口类" class="headerlink" title="1、增加CustomerProjection接口类"></a>1、增加CustomerProjection接口类</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">package com.example.demo.dto;</span><br><span class="line">import org.springframework.beans.factory.annotation.Value;</span><br><span class="line">/**</span><br><span class="line"> * Created by Administrator on 2017/7/9 0009.</span><br><span class="line"> */</span><br><span class="line">public interface CustomerProjection {</span><br><span class="line"> @Value("#{target.firstName + ' ' + target.lastName}")</span><br><span class="line"> String getFullName();</span><br><span class="line"></span><br><span class="line"> String getFirstName();</span><br><span class="line"></span><br><span class="line"> String getLastName();</span><br><span class="line">}</span><br></pre></td></tr></table></figure><pre><code>这里声明的方式是可以直接通过get+属性名,这是普通的,另外也可以通过@Value注解来实现指定字段,除了指定字段也可以做聚合展示,比如有些地方需要展示客户的全名,这里定义的getFullName()方法及注解@Value即完成这一操作。需要注意这里的@Value中的target表达式写法及拼接方法。</code></pre><h3 id="2、增加CustomerRepository方法"><a href="#2、增加CustomerRepository方法" class="headerlink" title="2、增加CustomerRepository方法"></a>2、增加CustomerRepository方法</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">@Query("SELECT c.firstName as firstName,c.lastName as lastName from Customer c")</span><br><span class="line">Collection&lt;CustomerProjection&gt; findAllProjectedBy();</span><br></pre></td></tr></table></figure><h3 id="3、增加CustomerController方法"><a href="#3、增加CustomerController方法" class="headerlink" title="3、增加CustomerController方法"></a>3、增加CustomerController方法</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * find by projections</span><br><span class="line"> */</span><br><span class="line">@RequestMapping("/findAllProjections")</span><br><span class="line">public void findAllProjections(){</span><br><span class="line"> Collection&lt;CustomerProjection&gt; projections = repository.findAllProjectedBy();</span><br><span class="line"> System.out.println(projections);</span><br><span class="line"> System.out.println(projections.size());</span><br><span class="line"> for (CustomerProjection projection:projections){</span><br><span class="line"> System.out.println("FullName:"+projection.getFullName());</span><br><span class="line"> System.out.println("FirstName:"+projection.getFirstName());</span><br><span class="line"> System.out.println("LastName:"+projection.getLastName());</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>这里只是做了简单示意,深入的内容需要自己去挖掘探索。不过关于Projection的资料比较少,我也是扒了不少资料才理解的差不多了,还需要多多实践。</p><p>另外spring-data-examples项目中有一些JPA的例子,可以用来学习,梳理思路。<a href="https://github.com/spring-projects/spring-data-examples/tree/master/jpa" title="https://github.com/spring-projects/spring-data-examples/tree/master/jpa" target="_blank" rel="noopener">https://github.com/spring-projects/spring-data-examples/tree/master/jpa</a></p><p>参考:<br>官方文档:<a href="https://docs.spring.io/spring-data/jpa/docs/current/reference/html" target="_blank" rel="noopener">https://docs.spring.io/spring-data/jpa/docs/current/reference/html</a><br>API官方文档:<a href="http://docs.spring.io/spring-data/data-jpa/docs/current/api/" target="_blank" rel="noopener">http://docs.spring.io/spring-data/data-jpa/docs/current/api/</a><br>JPQL文档:<a href="http://www.blogjava.net/calmJava/archive/2011/04/01/347450.html" target="_blank" rel="noopener">http://www.blogjava.net/calmJava/archive/2011/04/01/347450.html</a></p><p>DEMO示例:<a href="https://github.com/icnws/spring-data-jpa-demo" target="_blank" rel="noopener">https://github.com/icnws/spring-data-jpa-demo</a></p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> Projection </tag>
<tag> spring-data-jpa </tag>
</tags>
</entry>
<entry>
<title>Spring Data JPA系列:分页(Pageable)</title>
<link href="/2017/spring-data-jpa-pageable/"/>
<url>/2017/spring-data-jpa-pageable/</url>
<content type="html"><![CDATA[<p>在JPA中提供了很方便的分页功能,那就是Pageable(org.springframework.data.domain.Pageable)以及它的实现类PageRequest(org.springframework.data.domain.PageRequest),详细的可以见示例代码:</p><h3 id="1、改变CustomerRepository方法"><a href="#1、改变CustomerRepository方法" class="headerlink" title="1、改变CustomerRepository方法"></a>1、改变CustomerRepository方法</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 一个参数,匹配两个字段</span><br><span class="line"> * @param name2</span><br><span class="line"> * @Param pageable 分页参数</span><br><span class="line"> * @return</span><br><span class="line"> * 这里Param的值和=:后面的参数匹配,但不需要和方法名对应的参数值对应</span><br><span class="line"> * 这里增加了@QueryHints注解,是给查询添加一些额外的提示</span><br><span class="line"> * 比如当前的name值为HINT_COMMENT是在查询的时候带上一些备注信息</span><br><span class="line"> */</span><br><span class="line">@QueryHints(value = { @QueryHint(name = HINT_COMMENT, value = "a query for pageable")})</span><br><span class="line">@Query("select c from Customer c where c.firstName=:name or c.lastName=:name")</span><br><span class="line">Page&lt;Customer&gt; findByName(@Param("name") String name2,Pageable pageable);</span><br></pre></td></tr></table></figure><h3 id="2、增加CustomerController方法pageable"><a href="#2、增加CustomerController方法pageable" class="headerlink" title="2、增加CustomerController方法pageable"></a>2、增加CustomerController方法pageable</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 分页</span><br><span class="line"> * 应用查询提示@QueryHints,这里是在查询的适合增加了一个comment</span><br><span class="line"> * 查询结果是lastName和firstName都是bauer这个值的数据</span><br><span class="line"> */</span><br><span class="line">@RequestMapping("/pageable")</span><br><span class="line">public void pageable(){</span><br><span class="line"> //Pageable是接口,PageRequest是接口实现</span><br><span class="line"> //PageRequest的对象构造函数有多个,page是页数,初始值是0,size是查询结果的条数,后两个参数参考Sort对象的构造方法</span><br><span class="line"> Pageable pageable = new PageRequest(0,3, Sort.Direction.DESC,"id");</span><br><span class="line"> Page&lt;Customer&gt; page = repository.findByName("bauer",pageable);</span><br><span class="line"> //查询结果总行数</span><br><span class="line"> System.out.println(page.getTotalElements());</span><br><span class="line"> //按照当前分页大小,总页数</span><br><span class="line"> System.out.println(page.getTotalPages());</span><br><span class="line"> //按照当前页数、分页大小,查出的分页结果集合</span><br><span class="line"> for (Customer customer: page.getContent()) {</span><br><span class="line"> System.out.println(customer.toString());</span><br><span class="line"> }</span><br><span class="line"> System.out.println("-------------------------------------------");</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>从示例代码的注释当中可以看到Page对象的相关参数及值的说明,更详细的用法,参考PageRequest源码。</p><p><strong>小结:怎么样,是不是很简单很方便?!<br>另:PageRequest.java源码在上一篇文章已经有了。</strong></p><p>参考:<br>官方文档:<a href="https://docs.spring.io/spring-data/jpa/docs/current/reference/html" target="_blank" rel="noopener">https://docs.spring.io/spring-data/jpa/docs/current/reference/html</a><br>API官方文档:<a href="http://docs.spring.io/spring-data/data-jpa/docs/current/api/" target="_blank" rel="noopener">http://docs.spring.io/spring-data/data-jpa/docs/current/api/</a><br>JPQL文档:<a href="http://www.blogjava.net/calmJava/archive/2011/04/01/347450.html" target="_blank" rel="noopener">http://www.blogjava.net/calmJava/archive/2011/04/01/347450.html</a></p><p>DEMO示例:<a href="https://github.com/icnws/spring-data-jpa-demo" target="_blank" rel="noopener">https://github.com/icnws/spring-data-jpa-demo</a></p>]]></content>
<categories>
<category> 技术 </category>
</categories>
<tags>
<tag> spring-data-jpa </tag>
<tag> Pageable </tag>
<tag> 分页 </tag>
</tags>
</entry>
<entry>
<title>Centos7:系统用户</title>
<link href="/2017/centos7-setting-the-system-users/"/>
<url>/2017/centos7-setting-the-system-users/</url>
<content type="html"><![CDATA[<h4 id="1、用户创建"><a href="#1、用户创建" class="headerlink" title="1、用户创建"></a>1、用户创建</h4><p><code>useradd username</code></p><h4 id="2、更改密码"><a href="#2、更改密码" class="headerlink" title="2、更改密码"></a>2、更改密码</h4><p><code>passwd username</code><br>然后输入密码即可,两次</p>]]></content>