-
Notifications
You must be signed in to change notification settings - Fork 0
/
atom.xml
378 lines (206 loc) · 331 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>熊峰的博客 - Seifon's Blog</title>
<icon>https://www.gravatar.com/avatar/7ac49c33c147e472add17a2c25693e10</icon>
<subtitle>不定期分享一些个人开发经验</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="http://www.seifon.cn/"/>
<updated>2019-08-04T04:37:09.607Z</updated>
<id>http://www.seifon.cn/</id>
<author>
<name>Seifon</name>
<email>[email protected]</email>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>JVM调优之探索CMS和G1的物理内存归还机制</title>
<link href="http://www.seifon.cn/2019/08/04/JVM%E8%B0%83%E4%BC%98%E4%B9%8B%E6%8E%A2%E7%B4%A2CMS%E5%92%8CG1%E7%9A%84%E7%89%A9%E7%90%86%E5%86%85%E5%AD%98%E5%BD%92%E8%BF%98%E6%9C%BA%E5%88%B6/"/>
<id>http://www.seifon.cn/2019/08/04/JVM调优之探索CMS和G1的物理内存归还机制/</id>
<published>2019-08-04T04:37:01.000Z</published>
<updated>2019-08-04T04:37:09.607Z</updated>
<content type="html"><![CDATA[<h3 id="前言:"><a href="#前言:" class="headerlink" title="前言:"></a>前言:</h3><p>公司有一个资产统计系统,使用频率很低,但是要求在使用时查询速度快,因此想到做一些缓存放在内存中,在长时间没有使用,就持久化到磁盘中,并对垃圾进行回收,归还物理内存给操作系统,从而节省宝贵资源给其它业务系统。当我做好缓存时,却发现了一个棘手的问题,通过程序释放资源并通知GC回收资源后,堆内存的已用内存减少了,空闲内存增加了,可是进程占用系统内存却没有减少。查阅了很多资料,也尝试过很多次,都没有完美解决问题。直到后来看到一段评论谈及G1垃圾回收器,才恍然大悟。</p><p>接下来,通过一个小demo给大家演示一下两种垃圾回收器对物理内存归还的区别。如果有什么不对的地方,希望大家能够在评论里面指正。</p><ul><li>堆大小配置:</li></ul><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">-Xms128M -Xmx2048M</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><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></pre></td><td class="code"><pre><span class="line">import org.junit.Test;</span><br><span class="line"></span><br><span class="line">import java.util.ArrayList;</span><br><span class="line">import java.util.List;</span><br><span class="line"></span><br><span class="line">public class MemoryRecycleTest {</span><br><span class="line"></span><br><span class="line"> @Test</span><br><span class="line"> public void testMemoryRecycle() throws InterruptedException {</span><br><span class="line"></span><br><span class="line"> List list = new ArrayList();</span><br><span class="line"></span><br><span class="line"> //指定要生产的对象大小为512m</span><br><span class="line"> int count = 512;</span><br><span class="line"></span><br><span class="line"> //新建一条线程,负责生产对象</span><br><span class="line"> new Thread(() -> {</span><br><span class="line"> try {</span><br><span class="line"> for (int i = 1; i <= 10; i++) {</span><br><span class="line"> System.out.println(String.format("第%s次生产%s大小的对象", i, count));</span><br><span class="line"> addObject(list, count);</span><br><span class="line"> //休眠40秒</span><br><span class="line"> Thread.sleep(i * 10000);</span><br><span class="line"> }</span><br><span class="line"> } catch (InterruptedException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"> }).start();</span><br><span class="line"></span><br><span class="line"> //新建一条线程,负责清理list,回收jvm内存</span><br><span class="line"> new Thread(() -> {</span><br><span class="line"> for (;;) {</span><br><span class="line"> //当list内存到达512m,就通知gc回收堆</span><br><span class="line"> if (list.size() >= count) {</span><br><span class="line"> System.out.println("清理list.... 回收jvm内存....");</span><br><span class="line"> list.clear();</span><br><span class="line"> //通知gc回收</span><br><span class="line"> System.gc();</span><br><span class="line"> //打印堆内存信息</span><br><span class="line"> printJvmMemoryInfo();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }).start();</span><br><span class="line"></span><br><span class="line"> //阻止程序退出</span><br><span class="line"> Thread.currentThread().join();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public void addObject(List list, int count) {</span><br><span class="line"> for (int i = 0; i < count; i++) {</span><br><span class="line"> OOMobject ooMobject = new OOMobject();</span><br><span class="line"> //向list添加一个1m的对象</span><br><span class="line"> list.add(ooMobject);</span><br><span class="line"> try {</span><br><span class="line"> //休眠100毫秒</span><br><span class="line"> Thread.sleep(100);</span><br><span class="line"> } catch (InterruptedException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public static class OOMobject{</span><br><span class="line"> //生成1m的对象</span><br><span class="line"> private byte[] bytes=new byte[1024*1024];</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public static void printJvmMemoryInfo() {</span><br><span class="line"> // 虚拟机级内存情况查询</span><br><span class="line"> long vmFree = 0;</span><br><span class="line"> long vmUse = 0;</span><br><span class="line"> long vmTotal = 0;</span><br><span class="line"> long vmMax = 0;</span><br><span class="line"> int byteToMb = 1024 * 1024;</span><br><span class="line"> Runtime rt = Runtime.getRuntime();</span><br><span class="line"> vmTotal = rt.totalMemory() / byteToMb;</span><br><span class="line"> vmFree = rt.freeMemory() / byteToMb;</span><br><span class="line"> vmMax = rt.maxMemory() / byteToMb;</span><br><span class="line"> vmUse = vmTotal - vmFree;</span><br><span class="line"> System.out.println("");</span><br><span class="line"> System.out.println("JVM内存已用的空间为:" + vmUse + " MB");</span><br><span class="line"> System.out.println("JVM内存的空闲空间为:" + vmFree + " MB");</span><br><span class="line"> System.out.println("JVM总内存空间为:" + vmTotal + " MB");</span><br><span class="line"> System.out.println("JVM总内存最大堆空间为:" + vmMax + " MB");</span><br><span class="line"> System.out.println("");</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="首先使用CMS垃圾回收器:"><a href="#首先使用CMS垃圾回收器:" class="headerlink" title="首先使用CMS垃圾回收器:"></a>首先使用CMS垃圾回收器:</h3><ul><li>将jvm运行参数设置为如下:</li></ul><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">-Xms128M -Xmx2048M -XX:+UseConcMarkSweepGC</span><br></pre></td></tr></table></figure><p><img src="http://img.seifon.cn/343f1dd4c397964981a5cb088dbd6c09.png" alt="image"></p><ul><li>运行程序后,使用JProfiler查看堆内存情况:</li></ul><p><img src="http://img.seifon.cn/cebbdfbf474b62ac70995487f58a2a58.png" alt="image"></p><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><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">第1次生产512大小的对象</span><br><span class="line">清理list.... 回收jvm内存....</span><br><span class="line"></span><br><span class="line">JVM内存已用的空间为:6 MB</span><br><span class="line">JVM内存的空闲空间为:936 MB</span><br><span class="line">JVM总内存空间为:942 MB</span><br><span class="line">JVM总内存最大堆空间为:1990 MB</span><br><span class="line"></span><br><span class="line">第2次生产512大小的对象</span><br><span class="line">清理list.... 回收jvm内存....</span><br><span class="line"></span><br><span class="line">JVM内存已用的空间为:4 MB</span><br><span class="line">JVM内存的空闲空间为:1025 MB</span><br><span class="line">JVM总内存空间为:1029 MB</span><br><span class="line">JVM总内存最大堆空间为:1990 MB</span><br><span class="line"></span><br><span class="line">第3次生产512大小的对象</span><br><span class="line">清理list.... 回收jvm内存....</span><br><span class="line"></span><br><span class="line">JVM内存已用的空间为:4 MB</span><br><span class="line">JVM内存的空闲空间为:680 MB</span><br><span class="line">JVM总内存空间为:684 MB</span><br><span class="line">JVM总内存最大堆空间为:1990 MB</span><br><span class="line"></span><br><span class="line">第4次生产512大小的对象</span><br><span class="line">清理list.... 回收jvm内存....</span><br><span class="line"></span><br><span class="line">JVM内存已用的空间为:4 MB</span><br><span class="line">JVM内存的空闲空间为:119 MB</span><br><span class="line">JVM总内存空间为:123 MB</span><br><span class="line">JVM总内存最大堆空间为:1990 MB</span><br><span class="line"></span><br><span class="line">第5次生产512大小的对象</span><br><span class="line">清理list.... 回收jvm内存....</span><br><span class="line"></span><br><span class="line">JVM内存已用的空间为:4 MB</span><br><span class="line">JVM内存的空闲空间为:119 MB</span><br><span class="line">JVM总内存空间为:123 MB</span><br><span class="line">JVM总内存最大堆空间为:1990 MB</span><br><span class="line"></span><br><span class="line">第6次生产512大小的对象</span><br><span class="line">清理list.... 回收jvm内存....</span><br><span class="line"></span><br><span class="line">JVM内存已用的空间为:4 MB</span><br><span class="line">JVM内存的空闲空间为:119 MB</span><br><span class="line">JVM总内存空间为:123 MB</span><br><span class="line">JVM总内存最大堆空间为:1990 MB</span><br><span class="line"></span><br><span class="line">第7次生产512大小的对象</span><br><span class="line">清理list.... 回收jvm内存....</span><br><span class="line"></span><br><span class="line">JVM内存已用的空间为:4 MB</span><br><span class="line">JVM内存的空闲空间为:119 MB</span><br><span class="line">JVM总内存空间为:123 MB</span><br><span class="line">JVM总内存最大堆空间为:1990 MB</span><br><span class="line"></span><br><span class="line">第8次生产512大小的对象</span><br><span class="line">清理list.... 回收jvm内存....</span><br><span class="line"></span><br><span class="line">JVM内存已用的空间为:4 MB</span><br><span class="line">JVM内存的空闲空间为:119 MB</span><br><span class="line">JVM总内存空间为:123 MB</span><br><span class="line">JVM总内存最大堆空间为:1990 MB</span><br><span class="line"></span><br><span class="line">第9次生产512大小的对象</span><br><span class="line">清理list.... 回收jvm内存....</span><br><span class="line"></span><br><span class="line">JVM内存已用的空间为:4 MB</span><br><span class="line">JVM内存的空闲空间为:119 MB</span><br><span class="line">JVM总内存空间为:123 MB</span><br><span class="line">JVM总内存最大堆空间为:1990 MB</span><br></pre></td></tr></table></figure><ul><li>查看jmap heap 信息:</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><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></pre></td><td class="code"><pre><span class="line">C:\Users>jmap -heap 4716</span><br><span class="line">Attaching to process ID 4716, please wait...</span><br><span class="line">Debugger attached successfully.</span><br><span class="line">Server compiler detected.</span><br><span class="line">JVM version is 25.161-b12</span><br><span class="line"></span><br><span class="line">using parallel threads in the new generation.</span><br><span class="line">using thread-local object allocation.</span><br><span class="line">Concurrent Mark-Sweep GC</span><br><span class="line"></span><br><span class="line">Heap Configuration:</span><br><span class="line"> MinHeapFreeRatio = 40</span><br><span class="line"> MaxHeapFreeRatio = 70</span><br><span class="line"> MaxHeapSize = 2122317824 (2024.0MB)</span><br><span class="line"> NewSize = 44695552 (42.625MB)</span><br><span class="line"> MaxNewSize = 348913664 (332.75MB)</span><br><span class="line"> OldSize = 89522176 (85.375MB)</span><br><span class="line"> NewRatio = 2</span><br><span class="line"> SurvivorRatio = 8</span><br><span class="line"> MetaspaceSize = 21807104 (20.796875MB)</span><br><span class="line"> CompressedClassSpaceSize = 1073741824 (1024.0MB)</span><br><span class="line"> MaxMetaspaceSize = 17592186044415 MB</span><br><span class="line"> G1HeapRegionSize = 0 (0.0MB)</span><br><span class="line"></span><br><span class="line">Heap Usage:</span><br><span class="line">New Generation (Eden + 1 Survivor Space):</span><br><span class="line"> capacity = 280887296 (267.875MB)</span><br><span class="line"> used = 1629392 (1.5539093017578125MB)</span><br><span class="line"> free = 279257904 (266.3210906982422MB)</span><br><span class="line"> 0.5800874668251284% used</span><br><span class="line">Eden Space:</span><br><span class="line"> capacity = 249692160 (238.125MB)</span><br><span class="line"> used = 1629392 (1.5539093017578125MB)</span><br><span class="line"> free = 248062768 (236.5710906982422MB)</span><br><span class="line"> 0.6525603366961942% used</span><br><span class="line">From Space:</span><br><span class="line"> capacity = 31195136 (29.75MB)</span><br><span class="line"> used = 0 (0.0MB)</span><br><span class="line"> free = 31195136 (29.75MB)</span><br><span class="line"> 0.0% used</span><br><span class="line">To Space:</span><br><span class="line"> capacity = 31195136 (29.75MB)</span><br><span class="line"> used = 0 (0.0MB)</span><br><span class="line"> free = 31195136 (29.75MB)</span><br><span class="line"> 0.0% used</span><br><span class="line">concurrent mark-sweep generation:</span><br><span class="line"> capacity = 624041984 (595.1328125MB)</span><br><span class="line"> used = 4169296 (3.9761505126953125MB)</span><br><span class="line"> free = 619872688 (591.1566619873047MB)</span><br><span class="line"> 0.6681114583470076% used</span><br><span class="line"></span><br><span class="line">6718 interned Strings occupying 574968 bytes.</span><br></pre></td></tr></table></figure><p>通过统计图和控制台日志,可以看到在运行43秒左右前,使用内存呈直线平滑上升,开辟的内存呈阶梯状上升。当使用内存到达525m时,程序发起了System.gc(),此时垃圾被回收了,因此使用内存回到了10m,可是jvm开辟出来的内存空间却没有归还给操作系统,导致程序一直霸占着960m左右的内存资源。第二次生产对象时,可以看到在运行53秒至1分44秒时,不再开辟新空间,而是重复利用已开辟的内存继续创建对象,当执行第二次System.gc()时,jvm又开辟了一小部分内存,这一次程序霸占了1050m内存资源。第三次生产对象时,可以看到在运行2分05秒至2分55秒时,不再开辟新空间,而是重复利用已开辟的内存继续创建对象,当执行到第三次System.gc()时,jvm归还了一部分内存给操作系统,此时依然霸占着700m内存。……..循环执行10次……从总的情况,可以看出,随着System.gc()次数逐渐增加和时间间隔逐渐拉大,从继续开辟内存变成了慢慢归还内存给了操作系统,直到后面将物理内存全部归还给操作系统。</p><h3 id="接下来使用G1垃圾回收器:"><a href="#接下来使用G1垃圾回收器:" class="headerlink" title="接下来使用G1垃圾回收器:"></a>接下来使用G1垃圾回收器:</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">-Xms128M -Xmx2048M -XX:+UseG1GC</span><br></pre></td></tr></table></figure><p><img src="http://img.seifon.cn/8c6ac8d8a33bdf42f6511ce3cb2d59ba.png" alt="image"></p><ul><li>运行程序后,使用JProfiler查看堆内存情况:</li></ul><p><img src="http://img.seifon.cn/cc51dc7f2f0260d88ca84c25ffee1dfa.png" alt="image"></p><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><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">第1次生产512大小的对象</span><br><span class="line">清理list.... 回收jvm内存....</span><br><span class="line"></span><br><span class="line">JVM内存已用的空间为:5 MB</span><br><span class="line">JVM内存的空闲空间为:123 MB</span><br><span class="line">JVM总内存空间为:128 MB</span><br><span class="line">JVM总内存最大堆空间为:2024 MB</span><br><span class="line"></span><br><span class="line">第2次生产512大小的对象</span><br><span class="line">清理list.... 回收jvm内存....</span><br><span class="line"></span><br><span class="line">JVM内存已用的空间为:4 MB</span><br><span class="line">JVM内存的空闲空间为:124 MB</span><br><span class="line">JVM总内存空间为:128 MB</span><br><span class="line">JVM总内存最大堆空间为:2024 MB</span><br><span class="line"></span><br><span class="line">第3次生产512大小的对象</span><br><span class="line">清理list.... 回收jvm内存....</span><br><span class="line"></span><br><span class="line">JVM内存已用的空间为:4 MB</span><br><span class="line">JVM内存的空闲空间为:124 MB</span><br><span class="line">JVM总内存空间为:128 MB</span><br><span class="line">JVM总内存最大堆空间为:2024 MB</span><br><span class="line"></span><br><span class="line">第4次生产512大小的对象</span><br><span class="line">清理list.... 回收jvm内存....</span><br><span class="line"></span><br><span class="line">JVM内存已用的空间为:4 MB</span><br><span class="line">JVM内存的空闲空间为:124 MB</span><br><span class="line">JVM总内存空间为:128 MB</span><br><span class="line">JVM总内存最大堆空间为:2024 MB</span><br><span class="line"></span><br><span class="line">第5次生产512大小的对象</span><br><span class="line">清理list.... 回收jvm内存....</span><br><span class="line"></span><br><span class="line">JVM内存已用的空间为:4 MB</span><br><span class="line">JVM内存的空闲空间为:124 MB</span><br><span class="line">JVM总内存空间为:128 MB</span><br><span class="line">JVM总内存最大堆空间为:2024 MB</span><br><span class="line"></span><br><span class="line">第6次生产512大小的对象</span><br><span class="line">清理list.... 回收jvm内存....</span><br><span class="line"></span><br><span class="line">JVM内存已用的空间为:4 MB</span><br><span class="line">JVM内存的空闲空间为:124 MB</span><br><span class="line">JVM总内存空间为:128 MB</span><br><span class="line">JVM总内存最大堆空间为:2024 MB</span><br><span class="line"></span><br><span class="line">第7次生产512大小的对象</span><br><span class="line">清理list.... 回收jvm内存....</span><br><span class="line"></span><br><span class="line">JVM内存已用的空间为:4 MB</span><br><span class="line">JVM内存的空闲空间为:124 MB</span><br><span class="line">JVM总内存空间为:128 MB</span><br><span class="line">JVM总内存最大堆空间为:2024 MB</span><br><span class="line"></span><br><span class="line">第8次生产512大小的对象</span><br><span class="line">清理list.... 回收jvm内存....</span><br><span class="line"></span><br><span class="line">JVM内存已用的空间为:4 MB</span><br><span class="line">JVM内存的空闲空间为:124 MB</span><br><span class="line">JVM总内存空间为:128 MB</span><br><span class="line">JVM总内存最大堆空间为:2024 MB</span><br><span class="line"></span><br><span class="line">第9次生产512大小的对象</span><br><span class="line">清理list.... 回收jvm内存....</span><br><span class="line"></span><br><span class="line">JVM内存已用的空间为:4 MB</span><br><span class="line">JVM内存的空闲空间为:124 MB</span><br><span class="line">JVM总内存空间为:128 MB</span><br><span class="line">JVM总内存最大堆空间为:2024 MB</span><br></pre></td></tr></table></figure><ul><li>查看jmap heap 信息:</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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line">C:\Users>jmap -heap 18112</span><br><span class="line">Attaching to process ID 18112, please wait...</span><br><span class="line">Debugger attached successfully.</span><br><span class="line">Server compiler detected.</span><br><span class="line">JVM version is 25.161-b12</span><br><span class="line"></span><br><span class="line">using thread-local object allocation.</span><br><span class="line">Garbage-First (G1) GC with 4 thread(s)</span><br><span class="line"></span><br><span class="line">Heap Configuration:</span><br><span class="line"> MinHeapFreeRatio = 40</span><br><span class="line"> MaxHeapFreeRatio = 70</span><br><span class="line"> MaxHeapSize = 2122317824 (2024.0MB)</span><br><span class="line"> NewSize = 1363144 (1.2999954223632812MB)</span><br><span class="line"> MaxNewSize = 1272971264 (1214.0MB)</span><br><span class="line"> OldSize = 5452592 (5.1999969482421875MB)</span><br><span class="line"> NewRatio = 2</span><br><span class="line"> SurvivorRatio = 8</span><br><span class="line"> MetaspaceSize = 21807104 (20.796875MB)</span><br><span class="line"> CompressedClassSpaceSize = 1073741824 (1024.0MB)</span><br><span class="line"> MaxMetaspaceSize = 17592186044415 MB</span><br><span class="line"> G1HeapRegionSize = 1048576 (1.0MB)</span><br><span class="line"></span><br><span class="line">Heap Usage:</span><br><span class="line">G1 Heap:</span><br><span class="line"> regions = 2024</span><br><span class="line"> capacity = 2122317824 (2024.0MB)</span><br><span class="line"> used = 8336616 (7.950416564941406MB)</span><br><span class="line"> free = 2113981208 (2016.0495834350586MB)</span><br><span class="line"> 0.39280714253663074% used</span><br><span class="line">G1 Young Generation:</span><br><span class="line">Eden Space:</span><br><span class="line"> regions = 2</span><br><span class="line"> capacity = 83886080 (80.0MB)</span><br><span class="line"> used = 2097152 (2.0MB)</span><br><span class="line"> free = 81788928 (78.0MB)</span><br><span class="line"> 2.5% used</span><br><span class="line">Survivor Space:</span><br><span class="line"> regions = 0</span><br><span class="line"> capacity = 0 (0.0MB)</span><br><span class="line"> used = 0 (0.0MB)</span><br><span class="line"> free = 0 (0.0MB)</span><br><span class="line"> 0.0% used</span><br><span class="line">G1 Old Generation:</span><br><span class="line"> regions = 11</span><br><span class="line"> capacity = 50331648 (48.0MB)</span><br><span class="line"> used = 6239464 (5.950416564941406MB)</span><br><span class="line"> free = 44092184 (42.049583435058594MB)</span><br><span class="line"> 12.396701176961264% used</span><br><span class="line"></span><br><span class="line">6706 interned Strings occupying 573840 bytes.</span><br></pre></td></tr></table></figure><p>通过统计图和控制台日志,可以看到在运行41秒左右前,使用内存呈直线平滑上升,开辟的内存也是呈直线平滑上升。当使用内存到达530m时,程序发起了System.gc(),垃圾被回收,因此使用内存回到了10m。此时会发现神奇的现象出来了,jvm之前开辟出来的剩余内存空间全部归还给了操作系统,内存回到了我们指定的初始jvm堆大小128m。通过多次执行生产对象对比发现,jvm都是在每一次调用System.gc()后全部归还物理内存,不做任何保留。达到了我期望的效果!</p><h3 id="总结:"><a href="#总结:" class="headerlink" title="总结:"></a>总结:</h3><p>CMS垃圾回收器,在内存开辟后,会随着System.gc()执行次数逐渐增多和回收频率逐渐拉长,从继续开辟内存到慢慢归还物理内存给操作系统,直到出现一次全部归还,就会在每次调用System.gc()都归还所有剩余的物理内存给操作系统;G1恰恰相反,G1是在JVM每次回收垃圾后,主动归还物理内存给操作系统,不做任何保留,大大降低了内存占用。</p><p>另外,查看java堆栈实时情况,推荐使用JProfiler和VisualVM。如果是本地推荐JProfiler,因为功能强大,不过远程配置麻烦;如果是连远程java进程,推荐VisualVM,功能够用,连接远程只需配置一些jvm参数。</p><h3 id="其它说明"><a href="#其它说明" class="headerlink" title="其它说明"></a>其它说明</h3><p>JDK 12将有G1收集器,将内存返回到操作系统(不调用System.gc)“应用程序空闲时”</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></pre></td><td class="code"><pre><span class="line">jdk9 增加了这个jvm参数:</span><br><span class="line"></span><br><span class="line">-XX:+ShrinkHeapInSteps</span><br><span class="line">使Java堆渐进地缩小到目标大小,该选项默认开启,经过多次GC后堆缩小到目标大小;如果关闭该选项,那么GC后Java堆将立即缩小到目标大小。如果希望最小化Java堆大小,可以关闭改选项,并配合以下选项:</span><br><span class="line"></span><br><span class="line">-XX:MaxHeapFreeRatio=10 -XX:MinHeapFreeRatio=5</span><br><span class="line"></span><br><span class="line">这样将保持Java堆空间较小,并减少程序的动态占用空间,这对嵌入式应用非常有用,但对于一般应用,可能降低性能。</span><br></pre></td></tr></table></figure><h3 id="参考资料:"><a href="#参考资料:" class="headerlink" title="参考资料:"></a>参考资料:</h3><p><a href="http://www.imooc.com/wenda/detail/574044" target="_blank" rel="noopener">http://www.imooc.com/wenda/detail/574044</a><br><a href="https://developer.ibm.com/cn/blog/2017/still-paying-unused-memory-java-app-idle/" target="_blank" rel="noopener">https://developer.ibm.com/cn/blog/2017/still-paying-unused-memory-java-app-idle/</a><br><a href="https://gameinstitute.qq.com/community/detail/118528" target="_blank" rel="noopener">https://gameinstitute.qq.com/community/detail/118528</a><br><a href="https://www.zhihu.com/question/30813753" target="_blank" rel="noopener">https://www.zhihu.com/question/30813753</a><br><a href="https://www.zhihu.com/question/29161424" target="_blank" rel="noopener">https://www.zhihu.com/question/29161424</a></p>]]></content>
<summary type="html">
<h3 id="前言:"><a href="#前言:" class="headerlink" title="前言:"></a>前言:</h3><p>公司有一个资产统计系统,使用频率很低,但是要求在使用时查询速度快,因此想到做一些缓存放在内存中,在长时间没有使用,就持久化到磁盘中,
</summary>
</entry>
<entry>
<title>Feign Stub挡板和Mock</title>
<link href="http://www.seifon.cn/2019/01/28/Feign-Stub%E6%8C%A1%E6%9D%BF%E5%92%8CMock/"/>
<id>http://www.seifon.cn/2019/01/28/Feign-Stub挡板和Mock/</id>
<published>2019-01-28T14:20:58.000Z</published>
<updated>2019-01-28T14:21:07.023Z</updated>
<content type="html"><![CDATA[<h4 id="背景:"><a href="#背景:" class="headerlink" title="背景:"></a>背景:</h4><p>在项目开发中,会有调用第三方接口的场景。当开发时,对方不愿意提供测试服务器给我们调用,或者有的接口会按调用次数进行计费。当联调时,第三方的测试服务器也可能会出现不稳定,如果他们的服务挂了,我们就一直等着服务恢复,那么这就相当影响效率了。如果我们在开发时,就定义一个挡板或者mock服务,在发起调用时,不直接调到第三方接口,而是调到我们自己的挡板代码或者mock服务,这样就可以避免这些问题了。</p><blockquote><p>优势:</p></blockquote><ul><li>挡板代码,不需要侵入业务代码,可以根据入参做一些动态结果返回</li><li>不需要专门开发一个挡板服务,并且在每次启动客户端都先启动挡板服务</li><li>可以自由选择使用挡板还是Mock数据</li></ul><blockquote><p>详细Demo代码,已经提交到Github,欢迎star</p></blockquote><p>Demo地址: <a href="https://github.com/Seifon/FeignStubMock" target="_blank" rel="noopener">https://github.com/Seifon/FeignStubMock</a></p><hr><h4 id="一、下面我就以一个第三方SMS短信接口来做演示:"><a href="#一、下面我就以一个第三方SMS短信接口来做演示:" class="headerlink" title="一、下面我就以一个第三方SMS短信接口来做演示:"></a>一、下面我就以一个第三方SMS短信接口来做演示:</h4><p>首先,我们写一个Feign客户端接口,正常调用第三方接口:</p><h5 id="1-定义一个SMS短信的Feign客户端接口:"><a href="#1-定义一个SMS短信的Feign客户端接口:" class="headerlink" title="1.定义一个SMS短信的Feign客户端接口:"></a>1.定义一个SMS短信的Feign客户端接口:</h5><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">import cn.seifon.example.feignstubmock.dto.YunxunSmsReqDto;</span><br><span class="line">import cn.seifon.example.feignstubmock.dto.YunxunSmsRespDto;</span><br><span class="line">import org.springframework.cloud.openfeign.FeignClient;</span><br><span class="line">import org.springframework.web.bind.annotation.PostMapping;</span><br><span class="line">import org.springframework.web.bind.annotation.RequestBody;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * @Author: Seifon</span><br><span class="line"> * @Description:</span><br><span class="line"> * @Date: Created in 10:24 2019/1/7</span><br><span class="line"> */</span><br><span class="line">@FeignClient(name = "smsclient", url = "${sms.url}", primary = false)</span><br><span class="line">public interface YunxunSmsFeign {</span><br><span class="line"></span><br><span class="line"> /**</span><br><span class="line"> *</span><br><span class="line"> * @param request</span><br><span class="line"> * @return {"code":"0","failNum":"0","successNum":"1","msgId":"19012516213625881","time":"20190125162136","errorMsg":""}</span><br><span class="line"> * @return {"code":"107","msgId":"","time":"20190125162358","errorMsg":"手机号码格式错误"}</span><br><span class="line"> */</span><br><span class="line"> @PostMapping("/msg/variable/json")</span><br><span class="line"> YunxunSmsRespDto send(@RequestBody YunxunSmsReqDto request);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><blockquote><p>注意:@FeignClient注解里面的primary属性一定要设置为false,这是为了防止在开启Feign挡板时,出现多个Feign客户端导致启动报错。</p></blockquote><h5 id="2-写一个单元测试:"><a href="#2-写一个单元测试:" class="headerlink" title="2.写一个单元测试:"></a>2.写一个单元测试:</h5><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">import cn.seifon.example.feignstubmock.dto.YunxunSmsReqDto;</span><br><span class="line">import cn.seifon.example.feignstubmock.dto.YunxunSmsRespDto;</span><br><span class="line">import cn.seifon.example.feignstubmock.feign.YunxunSmsFeign;</span><br><span class="line">import com.alibaba.fastjson.JSON;</span><br><span class="line">import org.junit.Test;</span><br><span class="line">import org.junit.runner.RunWith;</span><br><span class="line">import org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line">import org.springframework.boot.test.context.SpringBootTest;</span><br><span class="line">import org.springframework.test.context.junit4.SpringRunner;</span><br><span class="line"></span><br><span class="line">@RunWith(SpringRunner.class)</span><br><span class="line">@SpringBootTest</span><br><span class="line">public class FeignStubMockApplicationTests {</span><br><span class="line"> @Autowired</span><br><span class="line"> private YunxunSmsFeign yunxunSmsFeign;</span><br><span class="line"></span><br><span class="line"> @Test</span><br><span class="line"> public void feignStubMockTest() {</span><br><span class="line"> YunxunSmsReqDto yunxunSmsReqDto=new YunxunSmsReqDto();</span><br><span class="line"> yunxunSmsReqDto.setAccount("XXXXXXX");</span><br><span class="line"> yunxunSmsReqDto.setPassword("XXXXXXX");</span><br><span class="line"> yunxunSmsReqDto.setMsg("登录验证码:{$var},请不要对非本人透露。");</span><br><span class="line"> yunxunSmsReqDto.setParams("13011112222,123456");</span><br><span class="line"> yunxunSmsReqDto.setReport("true");</span><br><span class="line"></span><br><span class="line"> YunxunSmsRespDto send = yunxunSmsFeign.send(yunxunSmsReqDto);</span><br><span class="line"> </span><br><span class="line"> //打印结果</span><br><span class="line"> System.out.println(JSON.toJSON(send));</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h6 id="3-1-我们输入一个正确的手机号,拿一个成功的结果:"><a href="#3-1-我们输入一个正确的手机号,拿一个成功的结果:" class="headerlink" title="3.1.我们输入一个正确的手机号,拿一个成功的结果:"></a>3.1.我们输入一个正确的手机号,拿一个成功的结果:</h6><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></pre></td><td class="code"><pre><span class="line">2019-01-28 11:17:56.718 DEBUG 6920 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] ---> POST http://smssh1.253.com/msg/variable/json HTTP/1.1</span><br><span class="line">2019-01-28 11:17:56.719 DEBUG 6920 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] Content-Type: application/json;charset=UTF-8</span><br><span class="line">2019-01-28 11:17:56.720 DEBUG 6920 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] Content-Length: 160</span><br><span class="line">2019-01-28 11:17:56.720 DEBUG 6920 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] </span><br><span class="line">2019-01-28 11:17:56.721 DEBUG 6920 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] {"account":"XXXXXX","password":"XXXXXXX","msg":"登录验证码:{$var},请不要对非本人透露。","params":"17311112222,123456","report":"true"}</span><br><span class="line">2019-01-28 11:17:56.721 DEBUG 6920 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] ---> END HTTP (160-byte body)</span><br><span class="line">2019-01-28 11:17:56.958 DEBUG 6920 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] <--- HTTP/1.1 200 OK (236ms)</span><br><span class="line">2019-01-28 11:17:56.960 DEBUG 6920 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] connection: keep-alive</span><br><span class="line">2019-01-28 11:17:56.962 DEBUG 6920 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] content-length: 109</span><br><span class="line">2019-01-28 11:17:56.963 DEBUG 6920 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] content-type: application/json;charset=UTF-8</span><br><span class="line">2019-01-28 11:17:56.965 DEBUG 6920 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] date: Mon, 28 Jan 2019 03:17:56 GMT</span><br><span class="line">2019-01-28 11:17:56.966 DEBUG 6920 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] </span><br><span class="line">2019-01-28 11:17:56.971 DEBUG 6920 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] {"code":"0","failNum":"0","successNum":"1","msgId":"19012811175621982","time":"20190128111756","errorMsg":""}</span><br><span class="line">2019-01-28 11:17:56.972 DEBUG 6920 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] <--- END HTTP (109-byte body)</span><br><span class="line">{"code":"0","failNum":"0","successNum":"1","msgId":"19012811175621982","time":"20190128111756","errorMsg":""}</span><br></pre></td></tr></table></figure><p>此时,我们可以根据日志,看到请求的地址也是第三方的url</p><h6 id="3-2-我们输入一个错误的手机号,拿一个失败的结果:"><a href="#3-2-我们输入一个错误的手机号,拿一个失败的结果:" class="headerlink" title="3.2.我们输入一个错误的手机号,拿一个失败的结果:"></a>3.2.我们输入一个错误的手机号,拿一个失败的结果:</h6><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></pre></td><td class="code"><pre><span class="line">2019-01-28 11:21:15.300 DEBUG 5288 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] ---> POST http://smssh1.253.com/msg/variable/json HTTP/1.1</span><br><span class="line">2019-01-28 11:21:15.301 DEBUG 5288 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] Content-Type: application/json;charset=UTF-8</span><br><span class="line">2019-01-28 11:21:15.302 DEBUG 5288 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] Content-Length: 152</span><br><span class="line">2019-01-28 11:21:15.302 DEBUG 5288 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] </span><br><span class="line">2019-01-28 11:21:15.303 DEBUG 5288 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] {"account":"XXXXX","password":"XXXXXXX","msg":"登录验证码:{$var},请不要对非本人透露。","params":"173,123456","report":"true"}</span><br><span class="line">2019-01-28 11:21:15.303 DEBUG 5288 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] ---> END HTTP (152-byte body)</span><br><span class="line">2019-01-28 11:21:15.470 DEBUG 5288 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] <--- HTTP/1.1 200 OK (165ms)</span><br><span class="line">2019-01-28 11:21:15.471 DEBUG 5288 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] connection: keep-alive</span><br><span class="line">2019-01-28 11:21:15.473 DEBUG 5288 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] content-length: 87</span><br><span class="line">2019-01-28 11:21:15.474 DEBUG 5288 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] content-type: application/json;charset=UTF-8</span><br><span class="line">2019-01-28 11:21:15.476 DEBUG 5288 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] date: Mon, 28 Jan 2019 03:21:15 GMT</span><br><span class="line">2019-01-28 11:21:15.477 DEBUG 5288 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] </span><br><span class="line">2019-01-28 11:21:15.483 DEBUG 5288 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] {"code":"107","msgId":"","time":"20190128112115","errorMsg":"手机号码格式错误"}</span><br><span class="line">2019-01-28 11:21:15.484 DEBUG 5288 --- [ main] c.s.e.f.feign.YunxunSmsFeign : [YunxunSmsFeign#send] <--- END HTTP (87-byte body)</span><br><span class="line">{"code":"107","msgId":"","time":"20190128112115","errorMsg":"手机号码格式错误"}</span><br></pre></td></tr></table></figure><p>当我们知道了两种情况下出现的结果,那么我们就可以模拟响应结果啦。小技巧:我们可以先跟对方调接口,把各种响应报文保存下来,方便后面直接mock数据</p><hr><h4 id="二、接下来进入挡板编写环节:"><a href="#二、接下来进入挡板编写环节:" class="headerlink" title="二、接下来进入挡板编写环节:"></a>二、接下来进入挡板编写环节:</h4><h5 id="1-编写一个YunxunSmsFeignStub类,并实现YunxunSmsFeign接口:"><a href="#1-编写一个YunxunSmsFeignStub类,并实现YunxunSmsFeign接口:" class="headerlink" title="1.编写一个YunxunSmsFeignStub类,并实现YunxunSmsFeign接口:"></a>1.编写一个YunxunSmsFeignStub类,并实现YunxunSmsFeign接口:</h5><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">import cn.seifon.example.feignstubmock.dto.YunxunSmsReqDto;</span><br><span class="line">import cn.seifon.example.feignstubmock.dto.YunxunSmsRespDto;</span><br><span class="line">import cn.seifon.example.feignstubmock.feign.YunxunSmsFeign;</span><br><span class="line">import org.apache.commons.lang3.RandomUtils;</span><br><span class="line">import org.apache.commons.lang3.StringUtils;</span><br><span class="line">import org.apache.commons.lang3.time.DateFormatUtils;</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.boot.autoconfigure.condition.ConditionalOnProperty;</span><br><span class="line">import org.springframework.context.annotation.Primary;</span><br><span class="line">import org.springframework.stereotype.Component;</span><br><span class="line"></span><br><span class="line">import java.util.Date;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * @Author: Seifon</span><br><span class="line"> * @Description:</span><br><span class="line"> * @Date: Created in 10:24 2019/1/7</span><br><span class="line"> */</span><br><span class="line">@Primary //注意:需要在原Feign接口@FeignClient注解加入primary = false 属性</span><br><span class="line">@Component</span><br><span class="line">@ConditionalOnProperty(name = "feign-stub.yunxun.sms.mode", havingValue = "stub")</span><br><span class="line">public class YunxunSmsFeignStub implements YunxunSmsFeign {</span><br><span class="line"> private static final Logger LOG = LoggerFactory.getLogger(YunxunSmsFeignStub.class);</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public YunxunSmsRespDto send(YunxunSmsReqDto request) {</span><br><span class="line"> YunxunSmsRespDto yunxunSmsRespDto = new YunxunSmsRespDto();</span><br><span class="line"></span><br><span class="line"> //模拟正常响应结果</span><br><span class="line"> yunxunSmsRespDto.setCode("0");</span><br><span class="line"> yunxunSmsRespDto.setFailNum("0");</span><br><span class="line"> yunxunSmsRespDto.setSuccessNum("1");</span><br><span class="line"> yunxunSmsRespDto.setMsgId(String.valueOf(RandomUtils.nextLong(19000000000000000L, 19999999999999999L)));</span><br><span class="line"> yunxunSmsRespDto.setTime(DateFormatUtils.format(new Date(), "yyyyMMddHHmmss"));</span><br><span class="line"> yunxunSmsRespDto.setErrorMsg("");</span><br><span class="line"></span><br><span class="line"> String params = request.getParams();</span><br><span class="line"> String[] paramSplit = StringUtils.split(params, ",");</span><br><span class="line"> if (paramSplit[0].length() != 11) {</span><br><span class="line"> //模拟错误响应结果</span><br><span class="line"> yunxunSmsRespDto.setCode("107");</span><br><span class="line"> yunxunSmsRespDto.setMsgId("");</span><br><span class="line"> yunxunSmsRespDto.setErrorMsg("手机号码格式错误");</span><br><span class="line"> }</span><br><span class="line"> return yunxunSmsRespDto;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><blockquote><p>注意:必须标注@Primary注解,否则启动会报错。@ConditionalOnProperty的作用就是根据application.yaml配置的相关属性,判断是否注入Spring容器</p></blockquote><h5 id="2-application-yaml文件,加入下面的配置:"><a href="#2-application-yaml文件,加入下面的配置:" class="headerlink" title="2.application.yaml文件,加入下面的配置:"></a>2.application.yaml文件,加入下面的配置:</h5><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">sms:</span><br><span class="line"> url: 'http://smssh1.253.com'</span><br><span class="line"></span><br><span class="line">#yunxun:代表第三方系统名称,sms:代表业务名称,mode:代表Stub模式,url:代表mock服务地址</span><br><span class="line">feign-stub:</span><br><span class="line"> yunxun:</span><br><span class="line"> sms:</span><br><span class="line"> mode: 'stub'</span><br></pre></td></tr></table></figure><h5 id="3-为了区分返回的内容是挡板结果,我们可以写一个AOP切面打印日志:"><a href="#3-为了区分返回的内容是挡板结果,我们可以写一个AOP切面打印日志:" class="headerlink" title="3.为了区分返回的内容是挡板结果,我们可以写一个AOP切面打印日志:"></a>3.为了区分返回的内容是挡板结果,我们可以写一个AOP切面打印日志:</h5><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></pre></td><td class="code"><pre><span class="line">import com.alibaba.fastjson.JSON;</span><br><span class="line">import org.apache.commons.lang3.StringUtils;</span><br><span class="line">import org.aspectj.lang.ProceedingJoinPoint;</span><br><span class="line">import org.aspectj.lang.annotation.Around;</span><br><span class="line">import org.aspectj.lang.annotation.Aspect;</span><br><span class="line">import org.aspectj.lang.annotation.Pointcut;</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.stereotype.Component;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * @Author: Seifon</span><br><span class="line"> * @Description:</span><br><span class="line"> * @Date: Created in 10:24 2019/1/7</span><br><span class="line"> */</span><br><span class="line">@Aspect</span><br><span class="line">@Component</span><br><span class="line">public class FeignStubAspect {</span><br><span class="line"></span><br><span class="line"> private static final Logger LOG = LoggerFactory.getLogger(FeignStubAspect.class);</span><br><span class="line"></span><br><span class="line"> @Pointcut("execution(* cn.seifon.example.feignstubmock..stub.*.*(..))")</span><br><span class="line"> public void pointCut(){}</span><br><span class="line"></span><br><span class="line"> @Around("pointCut()")</span><br><span class="line"> public Object around(ProceedingJoinPoint pjp){</span><br><span class="line"> String name = StringUtils.join(pjp.getTarget().getClass().getName(), ".", pjp.getSignature().getName());</span><br><span class="line"> LOG.info("-----【{}】---- 进入挡板模式... request: 【{}】", name, JSON.toJSON(pjp.getArgs()));</span><br><span class="line"> try {</span><br><span class="line"> Object proceed = pjp.proceed();</span><br><span class="line"> LOG.info("-----【{}】---- 退出挡板模式... request: 【{}】, response: 【{}】", name, JSON.toJSON(pjp.getArgs()), JSON.toJSON(proceed));</span><br><span class="line"> return proceed;</span><br><span class="line"> } catch (Throwable e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> return null;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h6 id="4-1-运行之前写的单元测试代码(输入一个正确的手机号):"><a href="#4-1-运行之前写的单元测试代码(输入一个正确的手机号):" class="headerlink" title="4.1.运行之前写的单元测试代码(输入一个正确的手机号):"></a>4.1.运行之前写的单元测试代码(输入一个正确的手机号):</h6><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">2019-01-28 11:32:51.255 INFO 7488 --- [ main] c.s.e.f.aspect.FeignStubAspect : -----【cn.seifon.example.feignstubmock.feign.stub.YunxunSmsFeignStub.send】---- 进入挡板模式... request: 【[{"msg":"登录验证码:{$var},请不要对非本人透露。","password":"XXXXXXX","report":"true","params":"13011112222,123456","account":"XXXXXXX"}]】</span><br><span class="line">2019-01-28 11:32:51.975 INFO 7488 --- [ main] c.s.e.f.aspect.FeignStubAspect : -----【cn.seifon.example.feignstubmock.feign.stub.YunxunSmsFeignStub.send】---- 退出挡板模式... request: 【[{"msg":"登录验证码:{$var},请不要对非本人透露。","password":"XXXXXXX","report":"true","params":"13011112222,123456","account":"XXXXXXX"}]】, response: 【{"code":"0","failNum":"0","successNum":"1","msgId":"19148964234899564","time":"20190128113251","errorMsg":""}】</span><br><span class="line">{"code":"0","failNum":"0","successNum":"1","msgId":"19148964234899564","time":"20190128113251","errorMsg":""}</span><br></pre></td></tr></table></figure><h6 id="4-2-运行之前写的单元测试代码(输入一个错误的手机号):"><a href="#4-2-运行之前写的单元测试代码(输入一个错误的手机号):" class="headerlink" title="4.2.运行之前写的单元测试代码(输入一个错误的手机号):"></a>4.2.运行之前写的单元测试代码(输入一个错误的手机号):</h6><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">2019-01-28 11:35:27.177 INFO 15204 --- [ main] c.s.e.f.aspect.FeignStubAspect : -----【cn.seifon.example.feignstubmock.feign.stub.YunxunSmsFeignStub.send】---- 进入挡板模式... request: 【[{"msg":"登录验证码:{$var},请不要对非本人透露。","password":"XXXXXXX","report":"true","params":"130,123456","account":"XXXXXXX"}]】</span><br><span class="line">2019-01-28 11:35:27.900 INFO 15204 --- [ main] c.s.e.f.aspect.FeignStubAspect : -----【cn.seifon.example.feignstubmock.feign.stub.YunxunSmsFeignStub.send】---- 退出挡板模式... request: 【[{"msg":"登录验证码:{$var},请不要对非本人透露。","password":"XXXXXXX","report":"true","params":"130,123456","account":"XXXXXXX"}]】, response: 【{"code":"107","failNum":"0","successNum":"1","msgId":"","time":"20190128113527","errorMsg":"手机号码格式错误"}】</span><br><span class="line">{"code":"107","failNum":"0","successNum":"1","msgId":"","time":"20190128113527","errorMsg":"手机号码格式错误"}</span><br></pre></td></tr></table></figure><p>以上代码就完成了一个stub挡板功能,可有时候,我们已经拿到第三方接口的返回报文,并切不想去写一大段Stub代码。那么这个时候,我们就可以选择下面的Mock方式去完成我们的功能。</p><hr><h4 id="三、接下来进入Mock环节:"><a href="#三、接下来进入Mock环节:" class="headerlink" title="三、接下来进入Mock环节:"></a>三、接下来进入Mock环节:</h4><h5 id="1-首先准备一个mock服务,这里我就用自己比较喜欢的一个mock工具(mock-json-server)给大家演示:"><a href="#1-首先准备一个mock服务,这里我就用自己比较喜欢的一个mock工具(mock-json-server)给大家演示:" class="headerlink" title="1. 首先准备一个mock服务,这里我就用自己比较喜欢的一个mock工具(mock-json-server)给大家演示:"></a>1. 首先准备一个mock服务,这里我就用自己比较喜欢的一个mock工具(mock-json-server)给大家演示:</h5><h6 id="1-1-安装nodejs:"><a href="#1-1-安装nodejs:" class="headerlink" title="1.1 安装nodejs:"></a>1.1 安装nodejs:</h6><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">参看官网:http://nodejs.cn/</span><br></pre></td></tr></table></figure><h6 id="1-2-安装mock-json-server:"><a href="#1-2-安装mock-json-server:" class="headerlink" title="1.2 安装mock-json-server:"></a>1.2 安装mock-json-server:</h6><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">npm install -g mock-json-server</span><br></pre></td></tr></table></figure><h6 id="1-3-新建mock数据文件-命名为:data-json-:"><a href="#1-3-新建mock数据文件-命名为:data-json-:" class="headerlink" title="1.3 新建mock数据文件(命名为:data.json):"></a>1.3 新建mock数据文件(命名为:data.json):</h6><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"> "/msg/variable/json": {</span><br><span class="line"> "post": {</span><br><span class="line"> "code":"0",</span><br><span class="line"> "failNum":"0",</span><br><span class="line"> "successNum":"1",</span><br><span class="line"> "msgId":"19012516213625881",</span><br><span class="line"> "time":"20190125162136",</span><br><span class="line"> "errorMsg":""</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h6 id="1-4-运行:"><a href="#1-4-运行:" class="headerlink" title="1.4 运行:"></a>1.4 运行:</h6><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">mock-json-server {path}/data.json --port=1240</span><br><span class="line"></span><br><span class="line">{path}替换为存放data.json的绝对路径</span><br></pre></td></tr></table></figure><h6 id="1-5-如果显示如下结果,就代表mock服务运行成功:"><a href="#1-5-如果显示如下结果,就代表mock服务运行成功:" class="headerlink" title="1.5 如果显示如下结果,就代表mock服务运行成功:"></a>1.5 如果显示如下结果,就代表mock服务运行成功:</h6><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">JSON Server running at http://localhost:1240/</span><br></pre></td></tr></table></figure><blockquote><p>mock-json-server具体使用文档,请参考:<a href="https://www.npmjs.com/package/mock-json-server" target="_blank" rel="noopener">https://www.npmjs.com/package/mock-json-server</a></p></blockquote><h5 id="2-准备工作做好后,接下来,就进入Mock正式环节:"><a href="#2-准备工作做好后,接下来,就进入Mock正式环节:" class="headerlink" title="2. 准备工作做好后,接下来,就进入Mock正式环节:"></a>2. 准备工作做好后,接下来,就进入Mock正式环节:</h5><h6 id="2-1-首先,我们定义一个YunxunSmsFeignMock接口,并且继承YunxunSmsFeign接口"><a href="#2-1-首先,我们定义一个YunxunSmsFeignMock接口,并且继承YunxunSmsFeign接口" class="headerlink" title="2.1 首先,我们定义一个YunxunSmsFeignMock接口,并且继承YunxunSmsFeign接口"></a>2.1 首先,我们定义一个YunxunSmsFeignMock接口,并且继承YunxunSmsFeign接口</h6><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></pre></td><td class="code"><pre><span class="line">import cn.seifon.example.feignstubmock.feign.YunxunSmsFeign;</span><br><span class="line">import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;</span><br><span class="line">import org.springframework.cloud.openfeign.FeignClient;</span><br><span class="line">import org.springframework.context.annotation.Primary;</span><br><span class="line">import org.springframework.stereotype.Component;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * @Author: Seifon</span><br><span class="line"> * @Description:</span><br><span class="line"> * @Date: Created in 10:24 2019/1/7</span><br><span class="line"> */</span><br><span class="line">@Primary //注意:需要在原Feign接口@FeignClient注解加入primary = false 属性</span><br><span class="line">@Component</span><br><span class="line">@ConditionalOnProperty(name = "feign-stub.yunxun.sms.mode", havingValue = "mock")</span><br><span class="line">@FeignClient(name = "smsclient-mock", url = "${feign-stub.yunxun.sms.mockUrl}" ,path = "/")</span><br><span class="line">public interface YunxunSmsFeignMock extends YunxunSmsFeign {</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>注意:必须标注@Primary注解,否则启动时会报错。@FeignClient里的name属性不能跟原Feign接口名称相同,如果相同会启动报错。@ConditionalOnProperty的作用就是根据application.yaml配置的相关属性,判断是否注入Spring容器</p><h6 id="2-2-application-yaml文件,加入下面的配置:"><a href="#2-2-application-yaml文件,加入下面的配置:" class="headerlink" title="2.2 application.yaml文件,加入下面的配置:"></a>2.2 application.yaml文件,加入下面的配置:</h6><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">sms:</span><br><span class="line"> url: 'http://smssh1.253.com'</span><br><span class="line"></span><br><span class="line">#生产环境请勿添加此配置。mode说明:''-不开启, 'mock'-mock模式, 'stub'-stub模式。url说明:只有mock模式需要配置调试url。fund为第三方机构,repayment是业务名称</span><br><span class="line">#yunxun:代表第三方系统名称,sms:代表业务名称,mode:代表挡板模式,url:代表mock服务地址</span><br><span class="line">feign-stub:</span><br><span class="line"> yunxun:</span><br><span class="line"> sms:</span><br><span class="line"> mode: 'mock'</span><br><span class="line"> mockUrl: "http://localhost:1240"</span><br></pre></td></tr></table></figure><h6 id="2-3-为了区分返回的内容是Mock结果,我们可以写一个AOP切面打印日志:"><a href="#2-3-为了区分返回的内容是Mock结果,我们可以写一个AOP切面打印日志:" class="headerlink" title="2.3 为了区分返回的内容是Mock结果,我们可以写一个AOP切面打印日志:"></a>2.3 为了区分返回的内容是Mock结果,我们可以写一个AOP切面打印日志:</h6><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></pre></td><td class="code"><pre><span class="line">import com.alibaba.fastjson.JSON;</span><br><span class="line">import org.apache.commons.lang3.StringUtils;</span><br><span class="line">import org.aspectj.lang.ProceedingJoinPoint;</span><br><span class="line">import org.aspectj.lang.annotation.Around;</span><br><span class="line">import org.aspectj.lang.annotation.Aspect;</span><br><span class="line">import org.aspectj.lang.annotation.Pointcut;</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.stereotype.Component;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * @Author: Seifon</span><br><span class="line"> * @Description:</span><br><span class="line"> * @Date: Created in 10:24 2019/1/7</span><br><span class="line"> */</span><br><span class="line">@Aspect</span><br><span class="line">@Component</span><br><span class="line">public class FeignMockAspect {</span><br><span class="line"></span><br><span class="line"> private static final Logger LOG = LoggerFactory.getLogger(FeignMockAspect.class);</span><br><span class="line"></span><br><span class="line"> @Pointcut("execution(* cn.seifon.example.feignstubmock..mock.*.*(..))")</span><br><span class="line"> public void pointCut(){}</span><br><span class="line"></span><br><span class="line"> @Around("pointCut()")</span><br><span class="line"> public Object around(ProceedingJoinPoint pjp){</span><br><span class="line"> String name = StringUtils.join(pjp.getTarget().getClass().getName(), ".", pjp.getSignature().getName());</span><br><span class="line"> LOG.info("-----【{}】---- 进入Mock模式... request: 【{}】", name, JSON.toJSON(pjp.getArgs()));</span><br><span class="line"> try {</span><br><span class="line"> Object proceed = pjp.proceed();</span><br><span class="line"> LOG.info("-----【{}】---- 退出Mock模式... request: 【{}】, response: 【{}】", name, JSON.toJSON(pjp.getArgs()), JSON.toJSON(proceed));</span><br><span class="line"> return proceed;</span><br><span class="line"> } catch (Throwable e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> return null;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h6 id="2-4-运行之前的单元测试类,得到如下结果:"><a href="#2-4-运行之前的单元测试类,得到如下结果:" class="headerlink" title="2.4 运行之前的单元测试类,得到如下结果:"></a>2.4 运行之前的单元测试类,得到如下结果:</h6><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">2019-01-28 16:16:35.567 INFO 8976 --- [ main] c.s.e.f.aspect.FeignMockAspect : -----【com.sun.proxy.$Proxy95.send】---- 进入Mock模式... request: 【[{"msg":"登录验证码:{$var},请不要对非本人透露。","password":"XXXXXXX","report":"true","params":"13011112222,123456","account":"XXXXXXX"}]】</span><br><span class="line">2019-01-28 16:16:35.934 DEBUG 8976 --- [ main] c.s.e.f.feign.mock.YunxunSmsFeignMock : [YunxunSmsFeignMock#send] ---> POST http://localhost:1240/msg/variable/json HTTP/1.1</span><br><span class="line">2019-01-28 16:16:35.935 DEBUG 8976 --- [ main] c.s.e.f.feign.mock.YunxunSmsFeignMock : [YunxunSmsFeignMock#send] Content-Type: application/json;charset=UTF-8</span><br><span class="line">2019-01-28 16:16:35.936 DEBUG 8976 --- [ main] c.s.e.f.feign.mock.YunxunSmsFeignMock : [YunxunSmsFeignMock#send] Content-Length: 152</span><br><span class="line">2019-01-28 16:16:35.936 DEBUG 8976 --- [ main] c.s.e.f.feign.mock.YunxunSmsFeignMock : [YunxunSmsFeignMock#send] </span><br><span class="line">2019-01-28 16:16:35.937 DEBUG 8976 --- [ main] c.s.e.f.feign.mock.YunxunSmsFeignMock : [YunxunSmsFeignMock#send] {"account":"XXXXXXX","password":"XXXXXXX","msg":"登录验证码:{$var},请不要对非本人透露。","params":"13011112222,123456","report":"true"}</span><br><span class="line">2019-01-28 16:16:35.937 DEBUG 8976 --- [ main] c.s.e.f.feign.mock.YunxunSmsFeignMock : [YunxunSmsFeignMock#send] ---> END HTTP (152-byte body)</span><br><span class="line">2019-01-28 16:16:36.021 DEBUG 8976 --- [ main] c.s.e.f.feign.mock.YunxunSmsFeignMock : [YunxunSmsFeignMock#send] <--- HTTP/1.1 200 OK (82ms)</span><br><span class="line">2019-01-28 16:16:36.021 DEBUG 8976 --- [ main] c.s.e.f.feign.mock.YunxunSmsFeignMock : [YunxunSmsFeignMock#send] access-control-allow-origin: *</span><br><span class="line">2019-01-28 16:16:36.022 DEBUG 8976 --- [ main] c.s.e.f.feign.mock.YunxunSmsFeignMock : [YunxunSmsFeignMock#send] connection: keep-alive</span><br><span class="line">2019-01-28 16:16:36.023 DEBUG 8976 --- [ main] c.s.e.f.feign.mock.YunxunSmsFeignMock : [YunxunSmsFeignMock#send] content-length: 109</span><br><span class="line">2019-01-28 16:16:36.023 DEBUG 8976 --- [ main] c.s.e.f.feign.mock.YunxunSmsFeignMock : [YunxunSmsFeignMock#send] content-type: application/json; charset=utf-8</span><br><span class="line">2019-01-28 16:16:36.024 DEBUG 8976 --- [ main] c.s.e.f.feign.mock.YunxunSmsFeignMock : [YunxunSmsFeignMock#send] date: Mon, 28 Jan 2019 08:16:36 GMT</span><br><span class="line">2019-01-28 16:16:36.024 DEBUG 8976 --- [ main] c.s.e.f.feign.mock.YunxunSmsFeignMock : [YunxunSmsFeignMock#send] etag: W/"6d-XqhLoZB8r6IRF2Lb6CWoIVVNhIQ"</span><br><span class="line">2019-01-28 16:16:36.025 DEBUG 8976 --- [ main] c.s.e.f.feign.mock.YunxunSmsFeignMock : [YunxunSmsFeignMock#send] x-content-type-options: nosniff</span><br><span class="line">2019-01-28 16:16:36.026 DEBUG 8976 --- [ main] c.s.e.f.feign.mock.YunxunSmsFeignMock : [YunxunSmsFeignMock#send] x-powered-by: Express</span><br><span class="line">2019-01-28 16:16:36.027 DEBUG 8976 --- [ main] c.s.e.f.feign.mock.YunxunSmsFeignMock : [YunxunSmsFeignMock#send] </span><br><span class="line">2019-01-28 16:16:36.030 DEBUG 8976 --- [ main] c.s.e.f.feign.mock.YunxunSmsFeignMock : [YunxunSmsFeignMock#send] {"code":"0","failNum":"0","successNum":"1","msgId":"19012516213625881","time":"20190125162136","errorMsg":""}</span><br><span class="line">2019-01-28 16:16:36.030 DEBUG 8976 --- [ main] c.s.e.f.feign.mock.YunxunSmsFeignMock : [YunxunSmsFeignMock#send] <--- END HTTP (109-byte body)</span><br><span class="line">2019-01-28 16:16:36.227 INFO 8976 --- [ main] c.s.e.f.aspect.FeignMockAspect : -----【com.sun.proxy.$Proxy95.send】---- 退出Mock模式... request: 【[{"msg":"登录验证码:{$var},请不要对非本人透露。","password":"XXXXXXX","report":"true","params":"13011112222,123456","account":"XXXXXXX"}]】, response: 【{"code":"0","failNum":"0","successNum":"1","msgId":"19012516213625881","time":"20190125162136","errorMsg":""}】</span><br><span class="line">{"code":"0","failNum":"0","successNum":"1","msgId":"19012516213625881","time":"20190125162136","errorMsg":""}</span><br></pre></td></tr></table></figure><p>说明:此时我们根据日志,会发现feign调用的url已经变为我们的Mock服务地址了。同理,如果要返回失败结果,只需要修改data.json文件,再次调用后,即可得到我们想要的结果了。</p><hr><h4 id="四、结语:"><a href="#四、结语:" class="headerlink" title="四、结语:"></a>四、结语:</h4><p>如果有什么需要改进的地方,或者不正确的地方,请在评论里面提出并指正。谢谢!</p><blockquote><p>详细Demo代码,已经提交到Github,欢迎star</p></blockquote><p>Demo地址: <a href="https://github.com/Seifon/FeignStubMock" target="_blank" rel="noopener">https://github.com/Seifon/FeignStubMock</a></p><p>项目结构,如图:<br><img src="https://github.com/Seifon/FeignStubMock/raw/master/package_tree.png" alt=""></p>]]></content>
<summary type="html">
<h4 id="背景:"><a href="#背景:" class="headerlink" title="背景:"></a>背景:</h4><p>在项目开发中,会有调用第三方接口的场景。当开发时,对方不愿意提供测试服务器给我们调用,或者有的接口会按调用次数进行计费。当联调时,第
</summary>
</entry>
<entry>
<title>踩坑 Spring Cloud Hystrix 线程池队列配置</title>
<link href="http://www.seifon.cn/2018/12/08/%E8%B8%A9%E5%9D%91-Spring-Cloud-Hystrix-%E7%BA%BF%E7%A8%8B%E6%B1%A0%E9%98%9F%E5%88%97%E9%85%8D%E7%BD%AE/"/>
<id>http://www.seifon.cn/2018/12/08/踩坑-Spring-Cloud-Hystrix-线程池队列配置/</id>
<published>2018-12-08T01:50:00.000Z</published>
<updated>2018-12-08T01:52:54.939Z</updated>
<content type="html"><![CDATA[<h4 id="背景:"><a href="#背景:" class="headerlink" title="背景:"></a>背景:</h4><p>有一次在生产环境,突然出现了很多笔还款单被挂起,后来排查原因,发现是内部系统调用时出现了Hystrix调用异常。在开发过程中,因为核心线程数设置的比较大,没有出现这种异常。放到了测试环境,偶尔有出现这种情况,后来在网上查找解决方案,网上的方案是调整maxQueueSize属性就好了,当时调整了一下,确实有所改善。可没想到在生产环境跑了一段时间后却又出现这种了情况,此时我第一想法就是去查看maxQueueSize属性,可是maxQueueSize属性是设置值了。当时就比较纳闷了,为什么maxQueueSize属性不起作用,后来通过查看官方文档发现Hystrix还有一个queueSizeRejectionThreshold属性,这个属性是控制队列最大阈值的,而Hystrix默认只配置了5个,因此就算我们把maxQueueSize的值设置再大,也是不起作用的。两个属性必须同时配置</p><h4 id="先看一下正确的Hystrix配置姿势。"><a href="#先看一下正确的Hystrix配置姿势。" class="headerlink" title="先看一下正确的Hystrix配置姿势。"></a>先看一下正确的Hystrix配置姿势。</h4><p>application.yml:</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">hystrix:</span><br><span class="line"> threadpool:</span><br><span class="line"> default:</span><br><span class="line"> coreSize: 200 #并发执行的最大线程数,默认10</span><br><span class="line"> maxQueueSize: 1000 #BlockingQueue的最大队列数,默认值-1</span><br><span class="line"> queueSizeRejectionThreshold: 800 #即使maxQueueSize没有达到,达到queueSizeRejectionThreshold该值后,请求也会被拒绝,默认值5</span><br></pre></td></tr></table></figure><h4 id="接下来编写一个测试类,来验证几种错误配置,看看会出现什么情况。"><a href="#接下来编写一个测试类,来验证几种错误配置,看看会出现什么情况。" class="headerlink" title="接下来编写一个测试类,来验证几种错误配置,看看会出现什么情况。"></a>接下来编写一个测试类,来验证几种错误配置,看看会出现什么情况。</h4><h4 id="测试类代码(A调用方):"><a href="#测试类代码(A调用方):" class="headerlink" title="测试类代码(A调用方):"></a>测试类代码(A调用方):</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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * @Author: XiongFeng</span><br><span class="line"> * @Description:</span><br><span class="line"> * @Date: Created in 11:12 2018/6/11</span><br><span class="line"> */</span><br><span class="line">public class RepaymentHelperTest extends FundApplicationTests {</span><br><span class="line"></span><br><span class="line"> @Autowired</span><br><span class="line"> RepaymentHelper repaymentHelper;</span><br><span class="line"> @Autowired</span><br><span class="line"> private RouterFeign routerFeign;</span><br><span class="line"></span><br><span class="line"> @Test</span><br><span class="line"> public void hystrixTest() throws InterruptedException {</span><br><span class="line"></span><br><span class="line"> for (int i = 0; i < 135; i++) {</span><br><span class="line"> new Thread(new Runnable() {</span><br><span class="line"> @Override</span><br><span class="line"> public void run() {</span><br><span class="line"> job();</span><br><span class="line"> }</span><br><span class="line"> }).start();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> Thread.currentThread().join();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public void job() {</span><br><span class="line"> String repaymentNo = "xf1002";</span><br><span class="line"> String transNo = "T4324324234";</span><br><span class="line"> String reqNo = "xf1002";</span><br><span class="line"> String begintime = "20180831130030";</span><br><span class="line"> String endtime = "20180831130050";</span><br><span class="line"></span><br><span class="line"> TransRecQueryReqDto transRecQueryReqDto = new TransRecQueryReqDto();</span><br><span class="line"> transRecQueryReqDto.setTransNo(transNo);</span><br><span class="line"> transRecQueryReqDto.setBeginTime(begintime);</span><br><span class="line"> transRecQueryReqDto.setEndTime(endtime);</span><br><span class="line"> transRecQueryReqDto.setReqNo(reqNo);</span><br><span class="line"></span><br><span class="line"> Resp<List<TransRecDto>> queryTransRecListResp = routerFeign.queryTransRec(new Req<>(repaymentNo, "2018080200000002", null, null, transRecQueryReqDto));</span><br><span class="line"></span><br><span class="line"> System.out.println(String.format("获取结果为:【%s】", JsonUtil.toJson(queryTransRecListResp)));</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>这个测试类的作用就是创建135个线程,通过RouterFeign类并发请求B服务方,看看请求结果是否出现异常。</li></ul><h4 id="Feign调用代码:"><a href="#Feign调用代码:" class="headerlink" title="Feign调用代码:"></a>Feign调用代码:</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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">@FeignClient(value = "${core.name}", fallbackFactory = RouterFeignBackFactory.class, path = "/router")</span><br><span class="line">public interface RouterFeign {</span><br><span class="line"></span><br><span class="line"> /**</span><br><span class="line"> * 代扣结果查询</span><br><span class="line"> * @param transRecQueryReqDtoReq</span><br><span class="line"> * @return</span><br><span class="line"> */</span><br><span class="line"> @PostMapping("/queryTransRec")</span><br><span class="line"> Resp<List<TransRecDto>> queryTransRec(@RequestBody Req<TransRecQueryReqDto> transRecQueryReqDtoReq);</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>这个类,就是通过Feign方式去调用B服务方的客户端</li></ul><h4 id="服务提供方代码(B服务方):"><a href="#服务提供方代码(B服务方):" class="headerlink" title="服务提供方代码(B服务方):"></a>服务提供方代码(B服务方):</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></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * @Author: XiongFeng</span><br><span class="line"> * @Description:</span><br><span class="line"> * @Date: Created in 16:04 2018/5/24</span><br><span class="line"> */</span><br><span class="line">@Api("还款服务")</span><br><span class="line">@RefreshScope</span><br><span class="line">@RestController</span><br><span class="line">@RequestMapping("/router")</span><br><span class="line">public class TestController {</span><br><span class="line"></span><br><span class="line"> private static Logger logger = LoggerFactory.getLogger(TestController.class);</span><br><span class="line"></span><br><span class="line"> // 计数器</span><br><span class="line"> private static AtomicInteger count = new AtomicInteger(1);</span><br><span class="line"></span><br><span class="line"> @ApiOperation(value = "代扣结果查询")</span><br><span class="line"> @PostMapping("/queryTransRec")</span><br><span class="line"> Resp<List<TransRecDto>> queryTransRec(@RequestBody Req<TransRecQueryReqDto> transRecQueryReqDtoReq) throws InterruptedException {</span><br><span class="line"> System.out.println(String.format("查询支付结果......计数: %s", count.getAndAdd(1)));</span><br><span class="line"> Thread.sleep(500);</span><br><span class="line"> return Resp.success(RespStatus.SUCCESS.getDesc(), null);</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><ul><li>这个类的作用,就是一个服务提供方,计数并返回结果。</li></ul><h4 id="下面我们看一下几种错误的配置。"><a href="#下面我们看一下几种错误的配置。" class="headerlink" title="下面我们看一下几种错误的配置。"></a>下面我们看一下几种错误的配置。</h4><h5 id="案例一(将核心线程数调低,最大队列数调大一点,但是队列拒绝阈值设置小一点):"><a href="#案例一(将核心线程数调低,最大队列数调大一点,但是队列拒绝阈值设置小一点):" class="headerlink" title="案例一(将核心线程数调低,最大队列数调大一点,但是队列拒绝阈值设置小一点):"></a>案例一(将核心线程数调低,最大队列数调大一点,但是队列拒绝阈值设置小一点):</h5><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">hystrix:</span><br><span class="line"> threadpool:</span><br><span class="line"> default:</span><br><span class="line"> coreSize: 10</span><br><span class="line"> maxQueueSize: 1000</span><br><span class="line"> queueSizeRejectionThreshold: 20</span><br></pre></td></tr></table></figure><h5 id="此时的结果:"><a href="#此时的结果:" class="headerlink" title="此时的结果:"></a>此时的结果:</h5><p><img src="http://img.seifon.cn/9e409db67dea471ca06a4eff76febbe6.png" alt="image"></p><ul><li>左窗口是B服务方,右窗口是A调用方。从结果可以看出,调用135次,成功32次左右,其余线程全部抛异常。</li></ul><h5 id="案例二(将核心线程数调低,最大队列数调小一点,但是队列拒绝阈值设置大一点):"><a href="#案例二(将核心线程数调低,最大队列数调小一点,但是队列拒绝阈值设置大一点):" class="headerlink" title="案例二(将核心线程数调低,最大队列数调小一点,但是队列拒绝阈值设置大一点):"></a>案例二(将核心线程数调低,最大队列数调小一点,但是队列拒绝阈值设置大一点):</h5><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">hystrix:</span><br><span class="line"> threadpool:</span><br><span class="line"> default:</span><br><span class="line"> coreSize: 10</span><br><span class="line"> maxQueueSize: 15</span><br><span class="line"> queueSizeRejectionThreshold: 2000</span><br></pre></td></tr></table></figure><h5 id="此时的结果:-1"><a href="#此时的结果:-1" class="headerlink" title="此时的结果:"></a>此时的结果:</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@7d6d472b rejected from java.util.concurrent.ThreadPoolExecutor@17f8bcb7[Running, pool size = 3, active threads = 3, queued tasks = 15, completed tasks = 0]</span><br></pre></td></tr></table></figure><p><img src="http://img.seifon.cn/f7505a5a5c6b9516379328820c4c9a83.png" alt="image"></p><ul><li>左窗口是B服务方,右窗口是A调用方。从结果可以看出,调用135次,成功25次左右,其余线程全部抛异常。。</li></ul><h5 id="案例三(将核心线程数调低,最大队列数调大一点,但是队列拒绝阈值不设置值):"><a href="#案例三(将核心线程数调低,最大队列数调大一点,但是队列拒绝阈值不设置值):" class="headerlink" title="案例三(将核心线程数调低,最大队列数调大一点,但是队列拒绝阈值不设置值):"></a>案例三(将核心线程数调低,最大队列数调大一点,但是队列拒绝阈值不设置值):</h5><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">hystrix:</span><br><span class="line"> threadpool:</span><br><span class="line"> default:</span><br><span class="line"> coreSize: 10</span><br><span class="line"> maxQueueSize: 1500</span><br></pre></td></tr></table></figure><h5 id="此时的结果:-2"><a href="#此时的结果:-2" class="headerlink" title="此时的结果:"></a>此时的结果:</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">java.util.concurrent.RejectedExecutionException: Rejected command because thread-pool queueSize is at rejection threshold.</span><br></pre></td></tr></table></figure><p><img src="http://img.seifon.cn/161b9260d86c712f90b6a026184b2508.png" alt="image"></p><ul><li>左窗口是B服务方,右窗口是A调用方。此时的结果和案例一的情况一样,调用135次,成功47次左右,其余线程全部抛异常。报错跟案例一一样</li></ul><h5 id="案例四(将核心线程数调低,最大队列数不设值,但是队列拒绝阈值设置的比较大):"><a href="#案例四(将核心线程数调低,最大队列数不设值,但是队列拒绝阈值设置的比较大):" class="headerlink" title="案例四(将核心线程数调低,最大队列数不设值,但是队列拒绝阈值设置的比较大):"></a>案例四(将核心线程数调低,最大队列数不设值,但是队列拒绝阈值设置的比较大):</h5><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">hystrix:</span><br><span class="line"> threadpool:</span><br><span class="line"> default:</span><br><span class="line"> coreSize: 10</span><br><span class="line"> queueSizeRejectionThreshold: 1000</span><br></pre></td></tr></table></figure><h5 id="此时的结果:-3"><a href="#此时的结果:-3" class="headerlink" title="此时的结果:"></a>此时的结果:</h5><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">java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@23d268ea rejected from java.util.concurrent.ThreadPoolExecutor@66d0e2f4[Running, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]</span><br><span class="line">at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)</span><br><span class="line">at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)</span><br><span class="line">at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)</span><br><span class="line">at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)</span><br></pre></td></tr></table></figure><p><img src="http://img.seifon.cn/6353ad99b3e0af79bcc6753f7c915eab.png" alt="image"></p><ul><li>左窗口是B服务方,右窗口是A调用方。此时的结果和案例二的情况一样,调用135次,成功10次左右,其余线程全部抛异常。报错跟案例二一样</li></ul><h4 id="下面来看一看正确的配置案例"><a href="#下面来看一看正确的配置案例" class="headerlink" title="下面来看一看正确的配置案例"></a>下面来看一看正确的配置案例</h4><h5 id="案例一:将核心线程数调低,最大队列数和队列拒绝阈值的值都设置大一点):"><a href="#案例一:将核心线程数调低,最大队列数和队列拒绝阈值的值都设置大一点):" class="headerlink" title="案例一:将核心线程数调低,最大队列数和队列拒绝阈值的值都设置大一点):"></a>案例一:将核心线程数调低,最大队列数和队列拒绝阈值的值都设置大一点):</h5><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">hystrix:</span><br><span class="line"> threadpool:</span><br><span class="line"> default:</span><br><span class="line"> coreSize: 10</span><br><span class="line"> maxQueueSize: 1500</span><br><span class="line"> queueSizeRejectionThreshold: 1000</span><br></pre></td></tr></table></figure><h5 id="此时的结果:-4"><a href="#此时的结果:-4" class="headerlink" title="此时的结果:"></a>此时的结果:</h5><p><img src="http://img.seifon.cn/a372d90344c968f5ef1631ae13453e6d.png" alt="image"></p><ul><li>左窗口是B服务方,右窗口是A调用方。此时的结果就完全正常了,并发请求了135次,全部成功!</li></ul><h5 id="结论:官方默认队列阈值只有5个,-如果要调整队列,必须同时修改maxQueueSize和queueSizeRejectionThreshold属性的值,否则都会出现异常!"><a href="#结论:官方默认队列阈值只有5个,-如果要调整队列,必须同时修改maxQueueSize和queueSizeRejectionThreshold属性的值,否则都会出现异常!" class="headerlink" title="结论:官方默认队列阈值只有5个, 如果要调整队列,必须同时修改maxQueueSize和queueSizeRejectionThreshold属性的值,否则都会出现异常!"></a>结论:官方默认队列阈值只有5个, 如果要调整队列,必须同时修改maxQueueSize和queueSizeRejectionThreshold属性的值,否则都会出现异常!</h5><h5 id="参考文档:"><a href="#参考文档:" class="headerlink" title="参考文档:"></a>参考文档:</h5><p><a href="https://github.com/Netflix/Hystrix/wiki/Configuration#coreSize" target="_blank" rel="noopener">Spring Hystrix 官方文档</a></p>]]></content>
<summary type="html">
<h4 id="背景:"><a href="#背景:" class="headerlink" title="背景:"></a>背景:</h4><p>有一次在生产环境,突然出现了很多笔还款单被挂起,后来排查原因,发现是内部系统调用时出现了Hystrix调用异常。在开发过程中,因为核
</summary>
<category term="Spring" scheme="http://www.seifon.cn/categories/Spring/"/>
<category term="Hystrix" scheme="http://www.seifon.cn/tags/Hystrix/"/>
<category term="Spring Cloud" scheme="http://www.seifon.cn/tags/Spring-Cloud/"/>
<category term="多线程" scheme="http://www.seifon.cn/tags/%E5%A4%9A%E7%BA%BF%E7%A8%8B/"/>
</entry>
<entry>
<title>Spring统一返回Json工具类,带分页信息</title>
<link href="http://www.seifon.cn/2018/04/30/Spring%E7%BB%9F%E4%B8%80%E8%BF%94%E5%9B%9EJson%E5%B7%A5%E5%85%B7%E7%B1%BB%EF%BC%8C%E5%B8%A6%E5%88%86%E9%A1%B5%E4%BF%A1%E6%81%AF/"/>
<id>http://www.seifon.cn/2018/04/30/Spring统一返回Json工具类,带分页信息/</id>
<published>2018-04-30T12:37:00.000Z</published>
<updated>2019-06-16T16:01:02.210Z</updated>
<content type="html"><![CDATA[<p><img src="//ww1.sinaimg.cn/large/005zWjpngy1fqv13ul9pcj30m80d30ts.jpg" alt=""></p><h4 id="前言:"><a href="#前言:" class="headerlink" title="前言:"></a>前言:</h4><ul><li><p>项目做前后端分离时,我们会经常提供Json数据给前端,如果有一个统一的Json格式返回工具类,那么将大大提高开发效率和减低沟通成本。</p></li><li><p>此Json响应工具类,支持带分页信息,支持泛型,支持HttpStatus标准返回码</p></li></ul><h4 id="效果预览:"><a href="#效果预览:" class="headerlink" title="效果预览:"></a>效果预览:</h4><p><img src="//ww1.sinaimg.cn/large/005zWjpngy1fquzhh5zkvj30a60gs75a.jpg" alt=""></p><h4 id="步入正题:"><a href="#步入正题:" class="headerlink" title="步入正题:"></a>步入正题:</h4><h5 id="1-Resp工具类"><a href="#1-Resp工具类" class="headerlink" title="1. Resp工具类"></a>1. Resp工具类</h5><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><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br></pre></td><td class="code"><pre><span class="line">import java.io.Serializable;</span><br><span class="line">import java.util.Map;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * @Author: XiongFeng</span><br><span class="line"> * @Description: Restful统一Json响应对象封装</span><br><span class="line"> * @Date: Created in 9:39 2018/4/10</span><br><span class="line"> */</span><br><span class="line">public class Resp<T> implements Serializable {</span><br><span class="line"> private static final long serialVersionUID = 1L;</span><br><span class="line"></span><br><span class="line"> private final static String SUCCESS_CODE = "200";</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 String status;</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 String message;</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 T data;</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 PageInfo page;</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 Map<String, Object> ext;</span><br><span class="line"></span><br><span class="line"> public String getStatus() {</span><br><span class="line"> return status;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public void setStatus(String status) {</span><br><span class="line"> this.status = status;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public String getMessage() {</span><br><span class="line"> return message;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public void setMessage(String message) {</span><br><span class="line"> this.message = message;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public T getData() {</span><br><span class="line"> return data;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public void setData(T data) {</span><br><span class="line"> this.data = data;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public Map<String, Object> getExt() {</span><br><span class="line"> return ext;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public void setExt(Map<String, Object> ext) {</span><br><span class="line"> this.ext = ext;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public PageInfo getPage() {</span><br><span class="line"> return page;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public void setPage(PageInfo page) {</span><br><span class="line"> this.page = page;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public Resp(){</span><br><span class="line"> this.status = SUCCESS_CODE;</span><br><span class="line"> this.message = "SUCCESS";</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public Resp(String status, String message) {</span><br><span class="line"> this.status = status;</span><br><span class="line"> this.message = message;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public Resp(String status, String message, T data) {</span><br><span class="line"> this.status = status;</span><br><span class="line"> this.message = message;</span><br><span class="line"> this.data = data;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public Resp(String status, String message, T data, Map<String, Object> ext) {</span><br><span class="line"> this.status = status;</span><br><span class="line"> this.message = message;</span><br><span class="line"> this.data = data;</span><br><span class="line"> this.ext = ext;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public Resp(String status, String message, T data, PageInfo pageInfo) {</span><br><span class="line"> this.status = status;</span><br><span class="line"> this.message = message;</span><br><span class="line"> this.data = data;</span><br><span class="line"> this.page = pageInfo;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public Resp(String status, String message, T data, Map<String, Object> ext, PageInfo pageInfo) {</span><br><span class="line"> this.status = status;</span><br><span class="line"> this.message = message;</span><br><span class="line"> this.data = data;</span><br><span class="line"> this.ext = ext;</span><br><span class="line"> this.page = pageInfo;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public Resp(String status, String message, T data, Long total, Integer pageNo, Integer pageSize){</span><br><span class="line"> PageInfo pageInfo = new PageInfo(total, pageNo, pageSize);</span><br><span class="line"> this.status = status;</span><br><span class="line"> this.message = message;</span><br><span class="line"> this.data = data;</span><br><span class="line"> this.page = pageInfo;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public Resp(String status, String message, T data, Map<String, Object> ext, Long total, Integer pageNo, Integer pageSize){</span><br><span class="line"> PageInfo pageInfo = new PageInfo(total, pageNo, pageSize);</span><br><span class="line"> this.status = status;</span><br><span class="line"> this.message = message;</span><br><span class="line"> this.data = data;</span><br><span class="line"> this.ext = ext;</span><br><span class="line"> this.page = pageInfo;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> //快速返回成功</span><br><span class="line"> public static <T>Resp success(){</span><br><span class="line"> return new Resp<T>(SUCCESS_CODE,"请求成功",null);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public static <T>Resp success(T result){</span><br><span class="line"> return new Resp<T>(SUCCESS_CODE,"请求成功",result);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public static <T>Resp success(String message, T result){</span><br><span class="line"> return new Resp<T>(SUCCESS_CODE,message,result);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public static <T>Resp success(String message, T result, Map<String, Object> extra){</span><br><span class="line"> return new Resp<T>(SUCCESS_CODE,message,result, extra);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public static <T>Resp success(T result, Long total, Integer pageNo, Integer pageSize){</span><br><span class="line"> PageInfo pageInfo = new PageInfo(total, pageNo, pageSize);</span><br><span class="line"> return new Resp<T>(SUCCESS_CODE,"请求成功",result, pageInfo);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public static <T>Resp success(T result, Map<String, Object> extra, Long total, Integer pageNo, Integer pageSize){</span><br><span class="line"> PageInfo pageInfo = new PageInfo(total, pageNo, pageSize);</span><br><span class="line"> return new Resp<T>(SUCCESS_CODE,"请求成功",result, extra,pageInfo);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public static <T>Resp success(String message, T result, Long total, Integer pageNo, Integer pageSize){</span><br><span class="line"> PageInfo pageInfo = new PageInfo(total, pageNo, pageSize);</span><br><span class="line"> return new Resp<T>(SUCCESS_CODE,message,result,pageInfo);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public static <T>Resp success(String message, T result, Map<String, Object> extra, Long total, Integer pageNo, Integer pageSize){</span><br><span class="line"> PageInfo pageInfo = new PageInfo(total, pageNo, pageSize);</span><br><span class="line"> return new Resp<T>(SUCCESS_CODE,message,result, extra,pageInfo);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> //快速返回失败状态</span><br><span class="line"> public static <T>Resp fail(){</span><br><span class="line"> return new Resp<T>(ErrorCode.SYSTEM_ERROR.getCode(),ErrorCode.SYSTEM_ERROR.getMessage());</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public static <T>Resp fail(T result){</span><br><span class="line"> return new Resp<T>(ErrorCode.SYSTEM_ERROR.getCode(),ErrorCode.SYSTEM_ERROR.getMessage(),result);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public <T>Resp fail(String message, T result){</span><br><span class="line"> return new Resp<T>(ErrorCode.SYSTEM_ERROR.getCode(),message,result);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public <T>Resp fail(String message, T result, Map<String, Object> extra){</span><br><span class="line"> return new Resp<T>(ErrorCode.SYSTEM_ERROR.getCode(),message,result, extra);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public static <T>Resp fail(ErrorCode errorCode){</span><br><span class="line"> return new Resp<T>(errorCode.getCode(),errorCode.getMessage());</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public static <T>Resp fail(ErrorCode errorCode, T result){</span><br><span class="line"> return new Resp<T>(errorCode.getCode(),errorCode.getMessage(),result);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public static <T>Resp fail(ErrorCode errorCode, String message, T result){</span><br><span class="line"> return new Resp<T>(errorCode.getCode(),message,result);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public static <T>Resp fail(ErrorCode errorCode, String message, T result, Map<String, Object> extra){</span><br><span class="line"> return new Resp<T>(errorCode.getCode(),message,result, extra);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> //快速返回自定义状态码</span><br><span class="line"> public static <T>Resp result(String statusCode, String message){</span><br><span class="line"> return new Resp<T>(statusCode,message);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public static <T>Resp result(String statusCode, String message, T result){</span><br><span class="line"> return new Resp<T>(statusCode,message,result);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public static <T>Resp result(String statusCode, String message, T result, Map<String, Object> extra){</span><br><span class="line"> return new Resp<T>(statusCode,message,result, extra);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public static <T>Resp result(String statusCode, String message, T result, Long total, Integer pageNo, Integer pageSize){</span><br><span class="line"> PageInfo pageInfo = new PageInfo(total, pageNo, pageSize);</span><br><span class="line"> return new Resp<T>(statusCode,message,result, pageInfo);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public static <T>Resp result(String statusCode, String message, T result, Map<String, Object> extra, Long total, Integer pageNo, Integer pageSize){</span><br><span class="line"> PageInfo pageInfo = new PageInfo(total, pageNo, pageSize);</span><br><span class="line"> return new Resp<T>(statusCode,message,result, extra,pageInfo);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> //快速返回Http状态</span><br><span class="line"> public static <T>Resp httpStatus(HttpStatus httpStatus, String message){</span><br><span class="line"> return result(httpStatus.toString(),message);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public static <T>Resp httpStatus(HttpStatus httpStatus, String message, T result){</span><br><span class="line"> return result(httpStatus.toString(),message,result);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public static <T>Resp httpStatus(HttpStatus httpStatus, String message, T result, Map<String, Object> extra){</span><br><span class="line"> return result(httpStatus.toString(),message,result, extra);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public static <T>Resp httpStatus(HttpStatus httpStatus, String message, T result, Long total, Integer pageNo, Integer pageSize){</span><br><span class="line"> PageInfo pageInfo = new PageInfo(total, pageNo, pageSize);</span><br><span class="line"> return result(httpStatus.toString(),message,result, total, pageNo, pageSize);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public static <T>Resp httpStatus(HttpStatus httpStatus, String message, T result, Map<String, Object> extra, Long total, Integer pageNo, Integer pageSize){</span><br><span class="line"> PageInfo pageInfo = new PageInfo(total, pageNo, pageSize);</span><br><span class="line"> return result(httpStatus.toString(),message,result, extra, total, pageNo, pageSize);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="2-PageInfo-用于封装分页信息的"><a href="#2-PageInfo-用于封装分页信息的" class="headerlink" title="2. PageInfo 用于封装分页信息的"></a>2. PageInfo 用于封装分页信息的</h5><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">import java.io.Serializable;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * @Author: XiongFeng</span><br><span class="line"> * @Description: 分页信息</span><br><span class="line"> * @Date: Created in 9:39 2018/4/10</span><br><span class="line"> */</span><br><span class="line">public class PageInfo implements Serializable{</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">private static final long serialVersionUID = 1L;</span><br><span class="line">/**</span><br><span class="line"> * 总记录数</span><br><span class="line"> */</span><br><span class="line">private Long total;</span><br><span class="line">/**</span><br><span class="line"> * 总页数</span><br><span class="line"> */</span><br><span class="line">private Long totalPages;</span><br><span class="line">/**</span><br><span class="line"> * 当前页</span><br><span class="line"> */</span><br><span class="line">private Integer pageNo;</span><br><span class="line">/**</span><br><span class="line"> * 页记录数</span><br><span class="line"> */</span><br><span class="line">private Integer pageSize;</span><br><span class="line"></span><br><span class="line">public PageInfo(Long total) {</span><br><span class="line">this.total = total;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">public PageInfo(Long total, Integer pageNo,</span><br><span class="line"> Integer pageSize) {</span><br><span class="line">this.total = total;</span><br><span class="line">this.totalPages = (total - 1) / pageSize + 1;</span><br><span class="line">this.pageNo = pageNo;</span><br><span class="line">this.pageSize = pageSize;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">public static PageInfo page(Long total) {</span><br><span class="line">return new PageInfo(total);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">public static PageInfo page( Long total, Integer pageNo,</span><br><span class="line"> Integer pageSize) {</span><br><span class="line">return new PageInfo(total, pageNo, pageSize);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">public Long getTotal() {</span><br><span class="line">return total;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">public void setTotal(Long total) {</span><br><span class="line">this.total = total;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">public Long getTotalPages() {</span><br><span class="line">return totalPages;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">public void setTotalPages(Long totalPages) {</span><br><span class="line">this.totalPages = totalPages;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">public Integer getPageNo() {</span><br><span class="line">return pageNo;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">public void setPageNo(Integer pageNo) {</span><br><span class="line">this.pageNo = pageNo;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">public Integer getPageSize() {</span><br><span class="line">return pageSize;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">public void setPageSize(Integer pageSize) {</span><br><span class="line">this.pageSize = pageSize;</span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="4-ErrorCode-用于定义错误码"><a href="#4-ErrorCode-用于定义错误码" class="headerlink" title="4. ErrorCode 用于定义错误码"></a>4. ErrorCode 用于定义错误码</h5><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"> * @Author: XiongFeng</span><br><span class="line"> * @Description: 错误码</span><br><span class="line"> * @Date: Created in 9:39 2018/4/10</span><br><span class="line"> */</span><br><span class="line">public enum ErrorCode {</span><br><span class="line"></span><br><span class="line">SYSTEM_ERROR(500, "系统错误"),</span><br><span class="line">PARAMETER_CHECK_ERROR(400, "参数校验错误"),</span><br><span class="line"> AUTH_VALID_ERROR(701, "用户权限不足"),</span><br><span class="line"> UNLOGIN_ERROR(401, "用户未登录或登录状态超时失效"),</span><br><span class="line"> ;</span><br><span class="line"></span><br><span class="line"> private final Integer value;</span><br><span class="line"> private final String message;</span><br><span class="line"></span><br><span class="line"> ErrorCode(int value, String message) {</span><br><span class="line"> this.value = value;</span><br><span class="line"> this.message = message;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public int getValue() {</span><br><span class="line"> return value;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public String getMessage() {</span><br><span class="line"> return message;</span><br><span class="line"> }</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 value.toString();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public String getCode() {</span><br><span class="line"> return value.toString();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public static ErrorCode getByCode(Integer value) {</span><br><span class="line"> for (ErrorCode _enum : values()) {</span><br><span class="line"> if (_enum.getValue() == value) {</span><br><span class="line"> return _enum;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> return null;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="5-HttpStatus-提取自org-springframework-http-可以自己引入"><a href="#5-HttpStatus-提取自org-springframework-http-可以自己引入" class="headerlink" title="5. HttpStatus 提取自org.springframework.http,可以自己引入"></a>5. HttpStatus 提取自org.springframework.http,可以自己引入</h5><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><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br><span class="line">328</span><br><span class="line">329</span><br><span class="line">330</span><br><span class="line">331</span><br><span class="line">332</span><br><span class="line">333</span><br><span class="line">334</span><br><span class="line">335</span><br><span class="line">336</span><br><span class="line">337</span><br><span class="line">338</span><br><span class="line">339</span><br><span class="line">340</span><br><span class="line">341</span><br><span class="line">342</span><br><span class="line">343</span><br><span class="line">344</span><br><span class="line">345</span><br><span class="line">346</span><br><span class="line">347</span><br><span class="line">348</span><br><span class="line">349</span><br><span class="line">350</span><br><span class="line">351</span><br><span class="line">352</span><br><span class="line">353</span><br><span class="line">354</span><br><span class="line">355</span><br><span class="line">356</span><br><span class="line">357</span><br><span class="line">358</span><br><span class="line">359</span><br><span class="line">360</span><br><span class="line">361</span><br><span class="line">362</span><br><span class="line">363</span><br><span class="line">364</span><br><span class="line">365</span><br><span class="line">366</span><br><span class="line">367</span><br><span class="line">368</span><br><span class="line">369</span><br><span class="line">370</span><br><span class="line">371</span><br><span class="line">372</span><br><span class="line">373</span><br><span class="line">374</span><br><span class="line">375</span><br><span class="line">376</span><br><span class="line">377</span><br><span class="line">378</span><br><span class="line">379</span><br><span class="line">380</span><br><span class="line">381</span><br><span class="line">382</span><br><span class="line">383</span><br><span class="line">384</span><br><span class="line">385</span><br><span class="line">386</span><br><span class="line">387</span><br><span class="line">388</span><br><span class="line">389</span><br><span class="line">390</span><br><span class="line">391</span><br><span class="line">392</span><br><span class="line">393</span><br><span class="line">394</span><br><span class="line">395</span><br><span class="line">396</span><br><span class="line">397</span><br><span class="line">398</span><br><span class="line">399</span><br><span class="line">400</span><br><span class="line">401</span><br><span class="line">402</span><br><span class="line">403</span><br><span class="line">404</span><br><span class="line">405</span><br><span class="line">406</span><br><span class="line">407</span><br><span class="line">408</span><br><span class="line">409</span><br><span class="line">410</span><br><span class="line">411</span><br><span class="line">412</span><br><span class="line">413</span><br><span class="line">414</span><br><span class="line">415</span><br><span class="line">416</span><br><span class="line">417</span><br><span class="line">418</span><br><span class="line">419</span><br><span class="line">420</span><br><span class="line">421</span><br><span class="line">422</span><br><span class="line">423</span><br><span class="line">424</span><br><span class="line">425</span><br><span class="line">426</span><br><span class="line">427</span><br><span class="line">428</span><br><span class="line">429</span><br><span class="line">430</span><br><span class="line">431</span><br><span class="line">432</span><br><span class="line">433</span><br><span class="line">434</span><br><span class="line">435</span><br><span class="line">436</span><br><span class="line">437</span><br><span class="line">438</span><br><span class="line">439</span><br><span class="line">440</span><br><span class="line">441</span><br><span class="line">442</span><br><span class="line">443</span><br><span class="line">444</span><br><span class="line">445</span><br><span class="line">446</span><br><span class="line">447</span><br><span class="line">448</span><br><span class="line">449</span><br><span class="line">450</span><br><span class="line">451</span><br><span class="line">452</span><br><span class="line">453</span><br><span class="line">454</span><br><span class="line">455</span><br><span class="line">456</span><br><span class="line">457</span><br><span class="line">458</span><br><span class="line">459</span><br><span class="line">460</span><br><span class="line">461</span><br><span class="line">462</span><br><span class="line">463</span><br><span class="line">464</span><br><span class="line">465</span><br><span class="line">466</span><br><span class="line">467</span><br><span class="line">468</span><br><span class="line">469</span><br><span class="line">470</span><br><span class="line">471</span><br><span class="line">472</span><br><span class="line">473</span><br><span class="line">474</span><br><span class="line">475</span><br><span class="line">476</span><br><span class="line">477</span><br><span class="line">478</span><br><span class="line">479</span><br><span class="line">480</span><br><span class="line">481</span><br><span class="line">482</span><br><span class="line">483</span><br><span class="line">484</span><br><span class="line">485</span><br><span class="line">486</span><br><span class="line">487</span><br><span class="line">488</span><br><span class="line">489</span><br><span class="line">490</span><br><span class="line">491</span><br><span class="line">492</span><br><span class="line">493</span><br><span class="line">494</span><br><span class="line">495</span><br><span class="line">496</span><br><span class="line">497</span><br><span class="line">498</span><br><span class="line">499</span><br><span class="line">500</span><br><span class="line">501</span><br><span class="line">502</span><br><span class="line">503</span><br><span class="line">504</span><br><span class="line">505</span><br><span class="line">506</span><br><span class="line">507</span><br><span class="line">508</span><br><span class="line">509</span><br><span class="line">510</span><br><span class="line">511</span><br><span class="line">512</span><br><span class="line">513</span><br><span class="line">514</span><br><span class="line">515</span><br><span class="line">516</span><br><span class="line">517</span><br><span class="line">518</span><br><span class="line">519</span><br><span class="line">520</span><br><span class="line">521</span><br><span class="line">522</span><br><span class="line">523</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * Enumeration of HTTP status codes.</span><br><span class="line"> *</span><br><span class="line"> * <p>The HTTP status code series can be retrieved via {@link #series()}.</span><br><span class="line"> *</span><br><span class="line"> * @author Arjen Poutsma</span><br><span class="line"> * @author Sebastien Deleuze</span><br><span class="line"> * @author Brian Clozel</span><br><span class="line"> * @since 3.0</span><br><span class="line"> * @see HttpStatus.Series</span><br><span class="line"> * @see <a href="http://www.iana.org/assignments/http-status-codes">HTTP Status Code Registry</a></span><br><span class="line"> * @see <a href="http://en.wikipedia.org/wiki/List_of_HTTP_status_codes">List of HTTP status codes - Wikipedia</a></span><br><span class="line"> */</span><br><span class="line">public enum HttpStatus {</span><br><span class="line"></span><br><span class="line">// 1xx Informational</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * {@code 100 Continue}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.2.1">HTTP/1.1: Semantics and Content, section 6.2.1</a></span><br><span class="line"> */</span><br><span class="line">CONTINUE(100, "Continue"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 101 Switching Protocols}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.2.2">HTTP/1.1: Semantics and Content, section 6.2.2</a></span><br><span class="line"> */</span><br><span class="line">SWITCHING_PROTOCOLS(101, "Switching Protocols"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 102 Processing}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc2518#section-10.1">WebDAV</a></span><br><span class="line"> */</span><br><span class="line">PROCESSING(102, "Processing"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 103 Checkpoint}.</span><br><span class="line"> * @see <a href="http://code.google.com/p/gears/wiki/ResumableHttpRequestsProposal">A proposal for supporting</span><br><span class="line"> * resumable POST/PUT HTTP requests in HTTP/1.0</a></span><br><span class="line"> */</span><br><span class="line">CHECKPOINT(103, "Checkpoint"),</span><br><span class="line"></span><br><span class="line">// 2xx Success</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * {@code 200 OK}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.3.1">HTTP/1.1: Semantics and Content, section 6.3.1</a></span><br><span class="line"> */</span><br><span class="line">OK(200, "OK"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 201 Created}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.3.2">HTTP/1.1: Semantics and Content, section 6.3.2</a></span><br><span class="line"> */</span><br><span class="line">CREATED(201, "Created"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 202 Accepted}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.3.3">HTTP/1.1: Semantics and Content, section 6.3.3</a></span><br><span class="line"> */</span><br><span class="line">ACCEPTED(202, "Accepted"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 203 Non-Authoritative Information}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.3.4">HTTP/1.1: Semantics and Content, section 6.3.4</a></span><br><span class="line"> */</span><br><span class="line">NON_AUTHORITATIVE_INFORMATION(203, "Non-Authoritative Information"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 204 No Content}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.3.5">HTTP/1.1: Semantics and Content, section 6.3.5</a></span><br><span class="line"> */</span><br><span class="line">NO_CONTENT(204, "No Content"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 205 Reset Content}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.3.6">HTTP/1.1: Semantics and Content, section 6.3.6</a></span><br><span class="line"> */</span><br><span class="line">RESET_CONTENT(205, "Reset Content"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 206 Partial Content}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7233#section-4.1">HTTP/1.1: Range Requests, section 4.1</a></span><br><span class="line"> */</span><br><span class="line">PARTIAL_CONTENT(206, "Partial Content"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 207 Multi-Status}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc4918#section-13">WebDAV</a></span><br><span class="line"> */</span><br><span class="line">MULTI_STATUS(207, "Multi-Status"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 208 Already Reported}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc5842#section-7.1">WebDAV Binding Extensions</a></span><br><span class="line"> */</span><br><span class="line">ALREADY_REPORTED(208, "Already Reported"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 226 IM Used}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc3229#section-10.4.1">Delta encoding in HTTP</a></span><br><span class="line"> */</span><br><span class="line">IM_USED(226, "IM Used"),</span><br><span class="line"></span><br><span class="line">// 3xx Redirection</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * {@code 300 Multiple Choices}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.4.1">HTTP/1.1: Semantics and Content, section 6.4.1</a></span><br><span class="line"> */</span><br><span class="line">MULTIPLE_CHOICES(300, "Multiple Choices"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 301 Moved Permanently}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.4.2">HTTP/1.1: Semantics and Content, section 6.4.2</a></span><br><span class="line"> */</span><br><span class="line">MOVED_PERMANENTLY(301, "Moved Permanently"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 302 Found}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.4.3">HTTP/1.1: Semantics and Content, section 6.4.3</a></span><br><span class="line"> */</span><br><span class="line">FOUND(302, "Found"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 302 Moved Temporarily}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc1945#section-9.3">HTTP/1.0, section 9.3</a></span><br><span class="line"> * @deprecated in favor of {@link #FOUND} which will be returned from {@code HttpStatus.valueOf(302)}</span><br><span class="line"> */</span><br><span class="line">@Deprecated</span><br><span class="line">MOVED_TEMPORARILY(302, "Moved Temporarily"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 303 See Other}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.4.4">HTTP/1.1: Semantics and Content, section 6.4.4</a></span><br><span class="line"> */</span><br><span class="line">SEE_OTHER(303, "See Other"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 304 Not Modified}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7232#section-4.1">HTTP/1.1: Conditional Requests, section 4.1</a></span><br><span class="line"> */</span><br><span class="line">NOT_MODIFIED(304, "Not Modified"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 305 Use Proxy}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.4.5">HTTP/1.1: Semantics and Content, section 6.4.5</a></span><br><span class="line"> * @deprecated due to security concerns regarding in-band configuration of a proxy</span><br><span class="line"> */</span><br><span class="line">@Deprecated</span><br><span class="line">USE_PROXY(305, "Use Proxy"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 307 Temporary Redirect}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.4.7">HTTP/1.1: Semantics and Content, section 6.4.7</a></span><br><span class="line"> */</span><br><span class="line">TEMPORARY_REDIRECT(307, "Temporary Redirect"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 308 Permanent Redirect}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7238">RFC 7238</a></span><br><span class="line"> */</span><br><span class="line">PERMANENT_REDIRECT(308, "Permanent Redirect"),</span><br><span class="line"></span><br><span class="line">// --- 4xx Client Error ---</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * {@code 400 Bad Request}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.5.1">HTTP/1.1: Semantics and Content, section 6.5.1</a></span><br><span class="line"> */</span><br><span class="line">BAD_REQUEST(400, "Bad Request"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 401 Unauthorized}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7235#section-3.1">HTTP/1.1: Authentication, section 3.1</a></span><br><span class="line"> */</span><br><span class="line">UNAUTHORIZED(401, "Unauthorized"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 402 Payment Required}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.5.2">HTTP/1.1: Semantics and Content, section 6.5.2</a></span><br><span class="line"> */</span><br><span class="line">PAYMENT_REQUIRED(402, "Payment Required"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 403 Forbidden}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.5.3">HTTP/1.1: Semantics and Content, section 6.5.3</a></span><br><span class="line"> */</span><br><span class="line">FORBIDDEN(403, "Forbidden"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 404 Not Found}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.5.4">HTTP/1.1: Semantics and Content, section 6.5.4</a></span><br><span class="line"> */</span><br><span class="line">NOT_FOUND(404, "Not Found"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 405 Method Not Allowed}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.5.5">HTTP/1.1: Semantics and Content, section 6.5.5</a></span><br><span class="line"> */</span><br><span class="line">METHOD_NOT_ALLOWED(405, "Method Not Allowed"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 406 Not Acceptable}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.5.6">HTTP/1.1: Semantics and Content, section 6.5.6</a></span><br><span class="line"> */</span><br><span class="line">NOT_ACCEPTABLE(406, "Not Acceptable"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 407 Proxy Authentication Required}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7235#section-3.2">HTTP/1.1: Authentication, section 3.2</a></span><br><span class="line"> */</span><br><span class="line">PROXY_AUTHENTICATION_REQUIRED(407, "Proxy Authentication Required"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 408 Request Timeout}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.5.7">HTTP/1.1: Semantics and Content, section 6.5.7</a></span><br><span class="line"> */</span><br><span class="line">REQUEST_TIMEOUT(408, "Request Timeout"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 409 Conflict}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.5.8">HTTP/1.1: Semantics and Content, section 6.5.8</a></span><br><span class="line"> */</span><br><span class="line">CONFLICT(409, "Conflict"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 410 Gone}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.5.9">HTTP/1.1: Semantics and Content, section 6.5.9</a></span><br><span class="line"> */</span><br><span class="line">GONE(410, "Gone"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 411 Length Required}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.5.10">HTTP/1.1: Semantics and Content, section 6.5.10</a></span><br><span class="line"> */</span><br><span class="line">LENGTH_REQUIRED(411, "Length Required"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 412 Precondition failed}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7232#section-4.2">HTTP/1.1: Conditional Requests, section 4.2</a></span><br><span class="line"> */</span><br><span class="line">PRECONDITION_FAILED(412, "Precondition Failed"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 413 Payload Too Large}.</span><br><span class="line"> * @since 4.1</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.5.11">HTTP/1.1: Semantics and Content, section 6.5.11</a></span><br><span class="line"> */</span><br><span class="line">PAYLOAD_TOO_LARGE(413, "Payload Too Large"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 413 Request Entity Too Large}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc2616#section-10.4.14">HTTP/1.1, section 10.4.14</a></span><br><span class="line"> * @deprecated in favor of {@link #PAYLOAD_TOO_LARGE} which will be returned from {@code HttpStatus.valueOf(413)}</span><br><span class="line"> */</span><br><span class="line">@Deprecated</span><br><span class="line">REQUEST_ENTITY_TOO_LARGE(413, "Request Entity Too Large"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 414 URI Too Long}.</span><br><span class="line"> * @since 4.1</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.5.12">HTTP/1.1: Semantics and Content, section 6.5.12</a></span><br><span class="line"> */</span><br><span class="line">URI_TOO_LONG(414, "URI Too Long"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 414 Request-URI Too Long}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc2616#section-10.4.15">HTTP/1.1, section 10.4.15</a></span><br><span class="line"> * @deprecated in favor of {@link #URI_TOO_LONG} which will be returned from {@code HttpStatus.valueOf(414)}</span><br><span class="line"> */</span><br><span class="line">@Deprecated</span><br><span class="line">REQUEST_URI_TOO_LONG(414, "Request-URI Too Long"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 415 Unsupported Media Type}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.5.13">HTTP/1.1: Semantics and Content, section 6.5.13</a></span><br><span class="line"> */</span><br><span class="line">UNSUPPORTED_MEDIA_TYPE(415, "Unsupported Media Type"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 416 Requested Range Not Satisfiable}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7233#section-4.4">HTTP/1.1: Range Requests, section 4.4</a></span><br><span class="line"> */</span><br><span class="line">REQUESTED_RANGE_NOT_SATISFIABLE(416, "Requested range not satisfiable"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 417 Expectation Failed}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.5.14">HTTP/1.1: Semantics and Content, section 6.5.14</a></span><br><span class="line"> */</span><br><span class="line">EXPECTATION_FAILED(417, "Expectation Failed"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 418 I'm a teapot}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc2324#section-2.3.2">HTCPCP/1.0</a></span><br><span class="line"> */</span><br><span class="line">I_AM_A_TEAPOT(418, "I'm a teapot"),</span><br><span class="line">/**</span><br><span class="line"> * @deprecated See <a href="http://tools.ietf.org/rfcdiff?difftype=--hwdiff&url2=draft-ietf-webdav-protocol-06.txt">WebDAV Draft Changes</a></span><br><span class="line"> */</span><br><span class="line">@Deprecated</span><br><span class="line">INSUFFICIENT_SPACE_ON_RESOURCE(419, "Insufficient Space On Resource"),</span><br><span class="line">/**</span><br><span class="line"> * @deprecated See <a href="http://tools.ietf.org/rfcdiff?difftype=--hwdiff&url2=draft-ietf-webdav-protocol-06.txt">WebDAV Draft Changes</a></span><br><span class="line"> */</span><br><span class="line">@Deprecated</span><br><span class="line">METHOD_FAILURE(420, "Method Failure"),</span><br><span class="line">/**</span><br><span class="line"> * @deprecated See <a href="http://tools.ietf.org/rfcdiff?difftype=--hwdiff&url2=draft-ietf-webdav-protocol-06.txt">WebDAV Draft Changes</a></span><br><span class="line"> */</span><br><span class="line">@Deprecated</span><br><span class="line">DESTINATION_LOCKED(421, "Destination Locked"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 422 Unprocessable Entity}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc4918#section-11.2">WebDAV</a></span><br><span class="line"> */</span><br><span class="line">UNPROCESSABLE_ENTITY(422, "Unprocessable Entity"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 423 Locked}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc4918#section-11.3">WebDAV</a></span><br><span class="line"> */</span><br><span class="line">LOCKED(423, "Locked"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 424 Failed Dependency}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc4918#section-11.4">WebDAV</a></span><br><span class="line"> */</span><br><span class="line">FAILED_DEPENDENCY(424, "Failed Dependency"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 426 Upgrade Required}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc2817#section-6">Upgrading to TLS Within HTTP/1.1</a></span><br><span class="line"> */</span><br><span class="line">UPGRADE_REQUIRED(426, "Upgrade Required"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 428 Precondition Required}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc6585#section-3">Additional HTTP Status Codes</a></span><br><span class="line"> */</span><br><span class="line">PRECONDITION_REQUIRED(428, "Precondition Required"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 429 Too Many Requests}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc6585#section-4">Additional HTTP Status Codes</a></span><br><span class="line"> */</span><br><span class="line">TOO_MANY_REQUESTS(429, "Too Many Requests"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 431 Request Header Fields Too Large}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc6585#section-5">Additional HTTP Status Codes</a></span><br><span class="line"> */</span><br><span class="line">REQUEST_HEADER_FIELDS_TOO_LARGE(431, "Request Header Fields Too Large"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 451 Unavailable For Legal Reasons}.</span><br><span class="line"> * @see <a href="https://tools.ietf.org/html/draft-ietf-httpbis-legally-restricted-status-04"></span><br><span class="line"> * An HTTP Status Code to Report Legal Obstacles</a></span><br><span class="line"> * @since 4.3</span><br><span class="line"> */</span><br><span class="line">UNAVAILABLE_FOR_LEGAL_REASONS(451, "Unavailable For Legal Reasons"),</span><br><span class="line"></span><br><span class="line">// --- 5xx Server Error ---</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * {@code 500 Internal Server Error}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.6.1">HTTP/1.1: Semantics and Content, section 6.6.1</a></span><br><span class="line"> */</span><br><span class="line">INTERNAL_SERVER_ERROR(500, "Internal Server Error"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 501 Not Implemented}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.6.2">HTTP/1.1: Semantics and Content, section 6.6.2</a></span><br><span class="line"> */</span><br><span class="line">NOT_IMPLEMENTED(501, "Not Implemented"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 502 Bad Gateway}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.6.3">HTTP/1.1: Semantics and Content, section 6.6.3</a></span><br><span class="line"> */</span><br><span class="line">BAD_GATEWAY(502, "Bad Gateway"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 503 Service Unavailable}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.6.4">HTTP/1.1: Semantics and Content, section 6.6.4</a></span><br><span class="line"> */</span><br><span class="line">SERVICE_UNAVAILABLE(503, "Service Unavailable"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 504 Gateway Timeout}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.6.5">HTTP/1.1: Semantics and Content, section 6.6.5</a></span><br><span class="line"> */</span><br><span class="line">GATEWAY_TIMEOUT(504, "Gateway Timeout"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 505 HTTP Version Not Supported}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc7231#section-6.6.6">HTTP/1.1: Semantics and Content, section 6.6.6</a></span><br><span class="line"> */</span><br><span class="line">HTTP_VERSION_NOT_SUPPORTED(505, "HTTP Version not supported"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 506 Variant Also Negotiates}</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc2295#section-8.1">Transparent Content Negotiation</a></span><br><span class="line"> */</span><br><span class="line">VARIANT_ALSO_NEGOTIATES(506, "Variant Also Negotiates"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 507 Insufficient Storage}</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc4918#section-11.5">WebDAV</a></span><br><span class="line"> */</span><br><span class="line">INSUFFICIENT_STORAGE(507, "Insufficient Storage"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 508 Loop Detected}</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc5842#section-7.2">WebDAV Binding Extensions</a></span><br><span class="line"> */</span><br><span class="line">LOOP_DETECTED(508, "Loop Detected"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 509 Bandwidth Limit Exceeded}</span><br><span class="line"> */</span><br><span class="line">BANDWIDTH_LIMIT_EXCEEDED(509, "Bandwidth Limit Exceeded"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 510 Not Extended}</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc2774#section-7">HTTP Extension Framework</a></span><br><span class="line"> */</span><br><span class="line">NOT_EXTENDED(510, "Not Extended"),</span><br><span class="line">/**</span><br><span class="line"> * {@code 511 Network Authentication Required}.</span><br><span class="line"> * @see <a href="http://tools.ietf.org/html/rfc6585#section-6">Additional HTTP Status Codes</a></span><br><span class="line"> */</span><br><span class="line">NETWORK_AUTHENTICATION_REQUIRED(511, "Network Authentication Required");</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">private final int value;</span><br><span class="line"></span><br><span class="line">private final String reasonPhrase;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">HttpStatus(int value, String reasonPhrase) {</span><br><span class="line">this.value = value;</span><br><span class="line">this.reasonPhrase = reasonPhrase;</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"> * Return the integer value of this status code.</span><br><span class="line"> */</span><br><span class="line">public int value() {</span><br><span class="line">return this.value;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * Return the reason phrase of this status code.</span><br><span class="line"> */</span><br><span class="line">public String getReasonPhrase() {</span><br><span class="line">return this.reasonPhrase;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * Whether this status code is in the HTTP series</span><br><span class="line"> * {@link org.springframework.http.HttpStatus.Series#INFORMATIONAL}.</span><br><span class="line"> * This is a shortcut for checking the value of {@link #series()}.</span><br><span class="line"> */</span><br><span class="line">public boolean is1xxInformational() {</span><br><span class="line">return Series.INFORMATIONAL.equals(series());</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * Whether this status code is in the HTTP series</span><br><span class="line"> * {@link org.springframework.http.HttpStatus.Series#SUCCESSFUL}.</span><br><span class="line"> * This is a shortcut for checking the value of {@link #series()}.</span><br><span class="line"> */</span><br><span class="line">public boolean is2xxSuccessful() {</span><br><span class="line">return Series.SUCCESSFUL.equals(series());</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * Whether this status code is in the HTTP series</span><br><span class="line"> * {@link org.springframework.http.HttpStatus.Series#REDIRECTION}.</span><br><span class="line"> * This is a shortcut for checking the value of {@link #series()}.</span><br><span class="line"> */</span><br><span class="line">public boolean is3xxRedirection() {</span><br><span class="line">return Series.REDIRECTION.equals(series());</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"> * Whether this status code is in the HTTP series</span><br><span class="line"> * {@link org.springframework.http.HttpStatus.Series#CLIENT_ERROR}.</span><br><span class="line"> * This is a shortcut for checking the value of {@link #series()}.</span><br><span class="line"> */</span><br><span class="line">public boolean is4xxClientError() {</span><br><span class="line">return Series.CLIENT_ERROR.equals(series());</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * Whether this status code is in the HTTP series</span><br><span class="line"> * {@link org.springframework.http.HttpStatus.Series#SERVER_ERROR}.</span><br><span class="line"> * This is a shortcut for checking the value of {@link #series()}.</span><br><span class="line"> */</span><br><span class="line">public boolean is5xxServerError() {</span><br><span class="line">return Series.SERVER_ERROR.equals(series());</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * Returns the HTTP status series of this status code.</span><br><span class="line"> * @see HttpStatus.Series</span><br><span class="line"> */</span><br><span class="line">public Series series() {</span><br><span class="line">return Series.valueOf(this);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * Return a string representation of this status code.</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 Integer.toString(this.value);</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"> * Return the enum constant of this type with the specified numeric value.</span><br><span class="line"> * @param statusCode the numeric value of the enum to be returned</span><br><span class="line"> * @return the enum constant with the specified numeric value</span><br><span class="line"> * @throws IllegalArgumentException if this enum has no constant for the specified numeric value</span><br><span class="line"> */</span><br><span class="line">public static HttpStatus valueOf(int statusCode) {</span><br><span class="line">for (HttpStatus status : values()) {</span><br><span class="line">if (status.value == statusCode) {</span><br><span class="line">return status;</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">throw new IllegalArgumentException("No matching constant for [" + statusCode + "]");</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"> * Enumeration of HTTP status series.</span><br><span class="line"> * <p>Retrievable via {@link HttpStatus#series()}.</span><br><span class="line"> */</span><br><span class="line">public enum Series {</span><br><span class="line"></span><br><span class="line">INFORMATIONAL(1),</span><br><span class="line">SUCCESSFUL(2),</span><br><span class="line">REDIRECTION(3),</span><br><span class="line">CLIENT_ERROR(4),</span><br><span class="line">SERVER_ERROR(5);</span><br><span class="line"></span><br><span class="line">private final int value;</span><br><span class="line"></span><br><span class="line">Series(int value) {</span><br><span class="line">this.value = value;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * Return the integer value of this status series. Ranges from 1 to 5.</span><br><span class="line"> */</span><br><span class="line">public int value() {</span><br><span class="line">return this.value;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">public static Series valueOf(int status) {</span><br><span class="line">int seriesCode = status / 100;</span><br><span class="line">for (Series series : values()) {</span><br><span class="line">if (series.value == seriesCode) {</span><br><span class="line">return series;</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">throw new IllegalArgumentException("No matching constant for [" + status + "]");</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">public static Series valueOf(HttpStatus status) {</span><br><span class="line">return valueOf(status.value);</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="6-测试示例:"><a href="#6-测试示例:" class="headerlink" title="6. 测试示例:"></a>6. 测试示例:</h5><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">@ResponseBody</span><br><span class="line">@RequestMapping("/json")</span><br><span class="line">public Resp json(String token) {</span><br><span class="line"> MemberDetails member = memberService.getMemberDetailsByToken(token);</span><br><span class="line"> return Resp.success(member, 5L, 1, 3); //这里分页信息,请自己从PageHelper返回的数据中得到。参看下面注释内容:</span><br><span class="line"></span><br><span class="line"> //Page<Object> page = PageHelper.startPage(1, 5);</span><br><span class="line"> //MemberDetails member = memberService.getMemberDetailsByToken(token);</span><br><span class="line"> //return Resp.success(member, page.getTotal(), page.getPageNum(), page.getPageSize());</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">@ResponseBody</span><br><span class="line">@RequestMapping("/json2")</span><br><span class="line">public Resp json2(String token) {</span><br><span class="line"> MemberDetails member = memberService.getMemberDetailsByToken(token);</span><br><span class="line"> Map<String, Object> ext = new HashMap<>();</span><br><span class="line"> ext.put("msg", "扩展内容");</span><br><span class="line"> return Resp.success("成功了", member, ext, 5L, 1, 3);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">@ResponseBody</span><br><span class="line">@RequestMapping("/json3")</span><br><span class="line">public Resp json3(String token) {</span><br><span class="line"> MemberDetails member = memberService.getMemberDetailsByToken(token);</span><br><span class="line"> return Resp.fail();</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">@ResponseBody</span><br><span class="line">@RequestMapping("/json4")</span><br><span class="line">public Resp json4(String token) {</span><br><span class="line"> MemberDetails member = memberService.getMemberDetailsByToken(token);</span><br><span class="line"> Map<String, Object> ext = new HashMap<>();</span><br><span class="line"> ext.put("msg", "扩展内容");</span><br><span class="line"> return Resp.result("201", "成功了", member);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">@ResponseBody</span><br><span class="line">@RequestMapping("/json5")</span><br><span class="line">public Resp json5(String token) {</span><br><span class="line"> MemberDetails member = memberService.getMemberDetailsByToken(token);</span><br><span class="line"> return Resp.success(member);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">@ResponseBody</span><br><span class="line">@RequestMapping("/json6")</span><br><span class="line">public Resp json6(String token) {</span><br><span class="line"> MemberDetails member = memberService.getMemberDetailsByToken(token);</span><br><span class="line"> return Resp.httpStatus(HttpStatus.ACCEPTED, "成功了");</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="7-运行结果:"><a href="#7-运行结果:" class="headerlink" title="7. 运行结果:"></a>7. 运行结果:</h5><ul><li>访问:<a href="http://127.0.0.1:1230/json?token=123" target="_blank" rel="noopener">http://127.0.0.1:1230/json?token=123</a><br><img src="//ww1.sinaimg.cn/large/005zWjpngy1fquzhh5zkvj30a60gs75a.jpg" alt=""></li></ul><ul><li>访问:<a href="http://127.0.0.1:1230/json2?token=123" target="_blank" rel="noopener">http://127.0.0.1:1230/json2?token=123</a><br><img src="//ww1.sinaimg.cn/large/005zWjpngy1fqv06wcr61j30ap0f0wff.jpg" alt=""></li></ul><ul><li>访问:<a href="http://127.0.0.1:1230/json3?token=123" target="_blank" rel="noopener">http://127.0.0.1:1230/json3?token=123</a><br><img src="//ww1.sinaimg.cn/large/005zWjpngy1fqv08porc5j306l04sq30.jpg" alt=""></li></ul><ul><li>访问:<a href="http://127.0.0.1:1230/json4?token=123" target="_blank" rel="noopener">http://127.0.0.1:1230/json4?token=123</a><br><img src="//ww1.sinaimg.cn/large/005zWjpngy1fqv09vwl72j309q0baq3m.jpg" alt=""></li></ul><ul><li>访问:<a href="http://127.0.0.1:1230/json5?token=123" target="_blank" rel="noopener">http://127.0.0.1:1230/json5?token=123</a><br><img src="//ww1.sinaimg.cn/large/005zWjpngy1fqv0est94pj30970b974z.jpg" alt=""></li></ul><ul><li>访问:<a href="http://127.0.0.1:1230/json6?token=123" target="_blank" rel="noopener">http://127.0.0.1:1230/json6?token=123</a><br><img src="//ww1.sinaimg.cn/large/005zWjpngy1fqv0furfcgj305z04agln.jpg" alt=""></li></ul><blockquote><p>更多用法,请查看Resp类里面的静态方法</p></blockquote><h4 id="后记:"><a href="#后记:" class="headerlink" title="后记:"></a>后记:</h4><ul><li>如果大家有更好的改进建议或代码,欢迎在评论留言反馈,谢谢!</li></ul>]]></content>
<summary type="html">
<p><img src="//ww1.sinaimg.cn/large/005zWjpngy1fqv13ul9pcj30m80d30ts.jpg" alt=""></p>
<h4 id="前言:"><a href="#前言:" class="headerlink" title="
</summary>
<category term="Restful" scheme="http://www.seifon.cn/categories/Restful/"/>
<category term="Rest" scheme="http://www.seifon.cn/tags/Rest/"/>
<category term="Json" scheme="http://www.seifon.cn/tags/Json/"/>
<category term="Util" scheme="http://www.seifon.cn/tags/Util/"/>
</entry>
<entry>
<title>利用Filter和Spring拦截器,将用户信息动态传入Request方法</title>
<link href="http://www.seifon.cn/2018/04/21/%E5%88%A9%E7%94%A8Filter%E5%92%8C%E6%8B%A6%E6%88%AA%E5%99%A8%EF%BC%8C%E5%B0%86%E7%94%A8%E6%88%B7%E4%BF%A1%E6%81%AF%E5%8A%A8%E6%80%81%E4%BC%A0%E5%85%A5Request%E6%96%B9%E6%B3%95/"/>
<id>http://www.seifon.cn/2018/04/21/利用Filter和拦截器,将用户信息动态传入Request方法/</id>
<published>2018-04-21T12:14:00.000Z</published>
<updated>2019-06-16T16:01:02.197Z</updated>
<content type="html"><![CDATA[<h4 id="前言:"><a href="#前言:" class="headerlink" title="前言:"></a>前言:</h4><ul><li>在开发当中,经常会验证用户登录状态和获取用户信息。如果每次都手动调用用户信息查询接口,会非常的繁琐,而且代码冗余。为了提高开发效率,因此就有了今天这篇文章。</li></ul><h4 id="思路:"><a href="#思路:" class="headerlink" title="思路:"></a>思路:</h4><ul><li>用户请求我们的方法会携带一个Token,通过Filter过滤器将会员信息查出来并放到request请求参数中。接着在Cotroller层的请求方法中接收一个MemberDeatails类型的参数,就能直接获得会员信息了。</li></ul><h4 id="详细步骤:"><a href="#详细步骤:" class="headerlink" title="详细步骤:"></a>详细步骤:</h4><h5 id="1-Gradle引入需要的Jar包:"><a href="#1-Gradle引入需要的Jar包:" class="headerlink" title="1. Gradle引入需要的Jar包:"></a>1. Gradle引入需要的Jar包:</h5><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">compile "com.fasterxml.jackson.core:jackson-databind:2.8.10"</span><br></pre></td></tr></table></figure><h5 id="2-定义一个Login注解"><a href="#2-定义一个Login注解" class="headerlink" title="2. 定义一个Login注解"></a>2. 定义一个Login注解</h5><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">@Target({ElementType.METHOD})</span><br><span class="line">@Retention(RetentionPolicy.RUNTIME)</span><br><span class="line">@Documented</span><br><span class="line">public @interface Login {</span><br><span class="line"></span><br><span class="line"> String value() default "";</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="3-定义一个MemberDetails-class,用于封装用户信息"><a href="#3-定义一个MemberDetails-class,用于封装用户信息" class="headerlink" title="3. 定义一个MemberDetails.class,用于封装用户信息"></a>3. 定义一个MemberDetails.class,用于封装用户信息</h5><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MemberDetails</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String memberId;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String memberName;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String memberNickname;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String memberPhone;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String memberEmail;</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="5-定义一个会员接口类"><a href="#5-定义一个会员接口类" class="headerlink" title="5. 定义一个会员接口类"></a>5. 定义一个会员接口类</h5><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Author</span>: XiongFeng</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span>: 会员接口</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Date</span>: Created in 19:40 2018/4/10</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">MemberService</span> </span>{</span><br><span class="line"></span><br><span class="line"><span class="comment">/** 根据TokenId获取用户信息 */</span></span><br><span class="line"> <span class="function">MemberDto <span class="title">getMemberByToken</span><span class="params">(String token)</span></span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="6-定义一个会员接口实现类,在里面写上用户信息获取方法"><a href="#6-定义一个会员接口实现类,在里面写上用户信息获取方法" class="headerlink" title="6. 定义一个会员接口实现类,在里面写上用户信息获取方法"></a>6. 定义一个会员接口实现类,在里面写上用户信息获取方法</h5><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">@Service</span><br><span class="line">public class MemberServiceImpl implements MemberService {</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public MemberDetails getMemberDetailsByToken(String token) {</span><br><span class="line"> if (StringUtils.isBlank(token)) return null;</span><br><span class="line"> if (!"123".equals(token)) return null;</span><br><span class="line"> MemberDetails memberDetails = new MemberDetails();</span><br><span class="line"> memberDetails.setMemberId("123");</span><br><span class="line"> memberDetails.setMemberName("哈哈123");</span><br><span class="line"> memberDetails.setMemberEmail("[email protected]");</span><br><span class="line"> memberDetails.setMemberNickname("Seifon");</span><br><span class="line"> memberDetails.setMemberPhone("13100001111");</span><br><span class="line"> return memberDetails;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="7-定义一个Request请求包装类"><a href="#7-定义一个Request请求包装类" class="headerlink" title="7. 定义一个Request请求包装类"></a>7. 定义一个Request请求包装类</h5><ul><li>通过继承HttpServletRequestWrapper类,重写它里面的多个方法,对前端传过来的参数进行重新封装。因为在Filter,虽然可以通过request.getParameterMap()拿到一个含有参数的map,但是不能直接对request里面东西进行修改操作,一旦重新修改,就会报错。后来我发现j2ee已经给我们提供了解决的办法,使用HttpServletRequestWrapper类来解决向request添加额外参数的功能。于是我对HttpServletRequest进行重新包装,在里面重新定义一个map,将以前的参数put进去,并将我们需要添加的参数放进去,达到我们想要的效果。</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><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></pre></td><td class="code"><pre><span class="line">import javax.servlet.http.HttpServletRequest;</span><br><span class="line">import javax.servlet.http.HttpServletRequestWrapper;</span><br><span class="line">import java.util.Enumeration;</span><br><span class="line">import java.util.HashMap;</span><br><span class="line">import java.util.Map;</span><br><span class="line">import java.util.Vector;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * @Author: XiongFeng</span><br><span class="line"> * @Description: 对Request请求重新包装</span><br><span class="line"> * @Date: Created in 11:17 2018/4/13</span><br><span class="line"> */</span><br><span class="line">public class ParameterRequestWrapper extends HttpServletRequestWrapper {</span><br><span class="line"></span><br><span class="line"> private Map<String , String[]> params = new HashMap<String, String[]>();</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> @SuppressWarnings("unchecked")</span><br><span class="line"> public ParameterRequestWrapper(HttpServletRequest request) {</span><br><span class="line"> // 将request交给父类,以便于调用对应方法的时候,将其输出,其实父亲类的实现方式和第一种new的方式类似</span><br><span class="line"> super(request);</span><br><span class="line"> //将参数表,赋予给当前的Map以便于持有request中的参数</span><br><span class="line"> this.params.putAll(request.getParameterMap());</span><br><span class="line"> }</span><br><span class="line"> //重载一个构造方法</span><br><span class="line"> public ParameterRequestWrapper(HttpServletRequest request , Map<String , Object> extendParams) {</span><br><span class="line"> this(request);</span><br><span class="line"> addAllParameters(extendParams);//这里将扩展参数写入参数表</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> /**</span><br><span class="line"> * 复写获取key的方法</span><br><span class="line"> */</span><br><span class="line"> @Override</span><br><span class="line"> public Enumeration getParameterNames() {</span><br><span class="line"> Vector names = new Vector(params.keySet());</span><br><span class="line"> return names.elements();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> /**</span><br><span class="line"> * 复写获取值value的方法</span><br><span class="line"> */</span><br><span class="line"> @Override</span><br><span class="line"> public String getParameter(String name) {</span><br><span class="line"> Object v = params.get(name);</span><br><span class="line"> if (v == null) {</span><br><span class="line"> return null;</span><br><span class="line"> } else if (v instanceof String[]) {</span><br><span class="line"> String[] strArr = (String[]) v;</span><br><span class="line"> if (strArr.length > 0) {</span><br><span class="line"> return strArr[0];</span><br><span class="line"> } else {</span><br><span class="line"> return null;</span><br><span class="line"> }</span><br><span class="line"> } else if (v instanceof String) {</span><br><span class="line"> return (String) v;</span><br><span class="line"> } else {</span><br><span class="line"> return v.toString();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public String[] getParameterValues(String name) {</span><br><span class="line"> Object v = params.get(name);</span><br><span class="line"> if (v == null) {</span><br><span class="line"> return null;</span><br><span class="line"> } else if (v instanceof String[]) {</span><br><span class="line"> return (String[]) v;</span><br><span class="line"> } else if (v instanceof String) {</span><br><span class="line"> return new String[] { (String) v };</span><br><span class="line"> } else {</span><br><span class="line"> return new String[] { v.toString() };</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public void addAllParameters(Map<String , Object>otherParams) {//增加多个参数</span><br><span class="line"> for(Map.Entry<String , Object>entry : otherParams.entrySet()) {</span><br><span class="line"> addParameter(entry.getKey() , entry.getValue());</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"> public void addParameter(String name , Object value) {//增加参数</span><br><span class="line"> if(value != null) {</span><br><span class="line"> if(value instanceof String[]) {</span><br><span class="line"> params.put(name , (String[])value);</span><br><span class="line"> }else if(value instanceof String) {</span><br><span class="line"> params.put(name , new String[] {(String)value});</span><br><span class="line"> }else {</span><br><span class="line"> params.put(name , new String[] {String.valueOf(value)});</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> /** 简单封装,请根据需求改进 */</span><br><span class="line"> public void addObject(Object obj) {</span><br><span class="line"> Class<?> clazz = obj.getClass();</span><br><span class="line"> Method[] methods = clazz.getMethods();</span><br><span class="line"> try {</span><br><span class="line"> for (Method method : methods) {</span><br><span class="line"> if (!method.getName().startsWith("get")) {</span><br><span class="line"> continue;</span><br><span class="line"> }</span><br><span class="line"> Object invoke = method.invoke(obj);</span><br><span class="line"> if (invoke == null || "".equals(invoke)) {</span><br><span class="line"> continue;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> String filedName = method.getName().replace("get", "");</span><br><span class="line"> filedName = WordUtils.uncapitalize(filedName);</span><br><span class="line"></span><br><span class="line"> if (invoke instanceof Collection) {</span><br><span class="line"> Collection collections = (Collection) invoke;</span><br><span class="line"> if (collections != null && collections.size() > 0) {</span><br><span class="line"> String[] strings = (String[]) collections.toArray();</span><br><span class="line"> addParameter(filedName, strings);</span><br><span class="line"> return;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> addParameter(filedName, invoke);</span><br><span class="line"> }</span><br><span class="line"> } catch (IllegalAccessException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> } catch (InvocationTargetException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="8-定义一个过滤器"><a href="#8-定义一个过滤器" class="headerlink" title="8. 定义一个过滤器"></a>8. 定义一个过滤器</h5><ul><li>在这个过滤里面,主要校验Token是否有效以及将会员信息添加到request。首先,从Request请求头中拿到前端传过来的Token,并使用Token调用会员信息获取接口,得到用户的资料,然后将用户信息put到ParameterMap中,这个ParameterMap是我们通过ParameterRequestWrapper重新包装的一个map,因此可以在里面添加会员的参数,然后将新的request传递出去。</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><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></pre></td><td class="code"><pre><span class="line">import com.fasterxml.jackson.databind.ObjectMapper;</span><br><span class="line">import org.springframework.stereotype.Component;</span><br><span class="line"></span><br><span class="line">import javax.servlet.*;</span><br><span class="line">import javax.servlet.annotation.WebFilter;</span><br><span class="line">import javax.servlet.http.HttpServletRequest;</span><br><span class="line">import java.io.IOException;</span><br><span class="line">import java.util.Date;</span><br><span class="line">import java.util.HashMap;</span><br><span class="line">import java.util.Map;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * @Author: XiongFeng</span><br><span class="line"> * @Description: 会员登录信息过滤器</span><br><span class="line"> * @Date: Created in 11:17 2018/4/13</span><br><span class="line"> */</span><br><span class="line">@Component</span><br><span class="line">@WebFilter(urlPatterns = "/*")</span><br><span class="line">public class MemberFilter implements Filter {</span><br><span class="line"></span><br><span class="line"> MemberService memberService = new MemberServiceImpl();</span><br><span class="line"></span><br><span class="line"> ObjectMapper objectMapper = new ObjectMapper();</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public void init(FilterConfig filterConfig) throws ServletException {</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {</span><br><span class="line"></span><br><span class="line"> HttpServletRequest req = (HttpServletRequest) request;</span><br><span class="line"></span><br><span class="line"> String tokenId = req.getHeader("X-Authorization");</span><br><span class="line"></span><br><span class="line"> if (tokenId == null || "".equals(tokenId) || tokenId.isEmpty()) {</span><br><span class="line"> chain.doFilter(request, response);</span><br><span class="line"> return;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> MemberDetails memberDetails = memberService.getMemberDetailsByToken(tokenId);</span><br><span class="line"> if (memberDetails == null) this.respFail(response);</span><br><span class="line"></span><br><span class="line"> ParameterRequestWrapper requestWrapper = new ParameterRequestWrapper(req);</span><br><span class="line"> requestWrapper.addObject(memberDetails);</span><br><span class="line"> chain.doFilter(requestWrapper, response);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">/** 返回失败结果Json数据 */</span><br><span class="line"> private void respFail(ServletResponse response) throws IOException {</span><br><span class="line"> Map<String, Object> map = new HashMap<>();</span><br><span class="line"> map.put("status", 500);</span><br><span class="line"> map.put("message", "登录失效,请登录");</span><br><span class="line"> map.put("data", null);</span><br><span class="line"> String s = objectMapper.writeValueAsString(map);</span><br><span class="line"> response.setCharacterEncoding("UTF-8");</span><br><span class="line"> response.setContentType("application/json; charset=utf-8");</span><br><span class="line"> response.getWriter().write(s);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public void destroy() {</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="9-定义一个SpringMVC拦截器"><a href="#9-定义一个SpringMVC拦截器" class="headerlink" title="9. 定义一个SpringMVC拦截器"></a>9. 定义一个SpringMVC拦截器</h5><ul><li>在这个拦截器里面,主要验证Controller方法中是否需要MemberDetails和是否标了@Login注解。首先,从HandlerMethod中获取所有入参,看有没有需要MemberDetails参数,如果有,就从HttpServletRequest中拿memberId,如果不存在说明没有登录,存在就通过。然后HandlerMethod获取@Login注解,判断是否存在,如果存在,就看有没有memberId,没有就不通过。</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><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></pre></td><td class="code"><pre><span class="line">package cn.seifon.paymodle.interceptor;</span><br><span class="line"></span><br><span class="line">import cn.seifon.paymodle.annotations.Login;</span><br><span class="line">import cn.seifon.paymodle.dto.MemberDetails;</span><br><span class="line">import cn.seifon.paymodle.service.manager.member.MemberService;</span><br><span class="line">import cn.seifon.paymodle.service.manager.member.impl.MemberServiceImpl;</span><br><span class="line">import com.fasterxml.jackson.databind.ObjectMapper;</span><br><span class="line">import org.springframework.core.MethodParameter;</span><br><span class="line">import org.springframework.web.method.HandlerMethod;</span><br><span class="line">import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;</span><br><span class="line"></span><br><span class="line">import javax.servlet.http.HttpServletRequest;</span><br><span class="line">import javax.servlet.http.HttpServletResponse;</span><br><span class="line">import java.lang.reflect.Type;</span><br><span class="line">import java.util.HashMap;</span><br><span class="line">import java.util.Map;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * @Author: XiongFeng</span><br><span class="line"> * @Description: 会员登录信息拦截器</span><br><span class="line"> * @Date: Created in 11:17 2018/4/13</span><br><span class="line"> */</span><br><span class="line">public class MemberInterceptor extends HandlerInterceptorAdapter {</span><br><span class="line"></span><br><span class="line"> ObjectMapper objectMapper = new ObjectMapper();</span><br><span class="line"></span><br><span class="line"> MemberService memberService = new MemberServiceImpl();</span><br><span class="line"></span><br><span class="line"> public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {</span><br><span class="line"></span><br><span class="line"> HandlerMethod method = (HandlerMethod) handler;</span><br><span class="line"> String[] memberIds = request.getParameterValues("memberId");</span><br><span class="line"></span><br><span class="line"> MethodParameter[] methodParameters = method.getMethodParameters();</span><br><span class="line"> //判断方法类是否有MemberDetails入参</span><br><span class="line"> if (methodParameters.length > 0) {</span><br><span class="line"> for (MethodParameter methodParameter : methodParameters) {</span><br><span class="line"> Type genericParameterType = methodParameter.getGenericParameterType();</span><br><span class="line"> String typeName = genericParameterType.getTypeName();</span><br><span class="line"> if (!typeName.equals(MemberDetails.class.getTypeName())) continue;</span><br><span class="line"> if (memberIds == null || memberIds.length <= 0) return this.respFail(response); //如果找不到用户信息就返回失败</span><br><span class="line"> break;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> //判断是否有Login注解</span><br><span class="line"> Login login = method.getMethodAnnotation(Login.class);</span><br><span class="line"> if (login == null) return true;</span><br><span class="line"></span><br><span class="line"> if (memberIds == null || memberIds.length <= 0) return this.respFail(response); //如果找不到用户信息就返回失败</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">/** 返回失败结果Json数据 */</span><br><span class="line"> private boolean respFail(HttpServletResponse response) throws IOException {</span><br><span class="line"> Map<String, Object> map = new HashMap<>();</span><br><span class="line"> map.put("status", 500);</span><br><span class="line"> map.put("message", "登录失效,请登录");</span><br><span class="line"> map.put("data", null);</span><br><span class="line"> String s = objectMapper.writeValueAsString(map);</span><br><span class="line"> response.setCharacterEncoding("UTF-8");</span><br><span class="line"> response.setContentType("application/json; charset=utf-8");</span><br><span class="line"> response.getWriter().write(s);</span><br><span class="line"> return false;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="10-将拦截器注册到WebMvcConfigurer中"><a href="#10-将拦截器注册到WebMvcConfigurer中" class="headerlink" title="10. 将拦截器注册到WebMvcConfigurer中"></a>10. 将拦截器注册到WebMvcConfigurer中</h5><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">@Configuration</span><br><span class="line">public class MyWebAppConfigurer</span><br><span class="line"> extends WebMvcConfigurerAdapter {</span><br><span class="line"></span><br><span class="line"> @Override</span><br><span class="line"> public void addInterceptors(InterceptorRegistry registry) {</span><br><span class="line"> // addPathPatterns 用于添加拦截规则</span><br><span class="line"> registry.addInterceptor(new MemberInterceptor()).addPathPatterns("/**");</span><br><span class="line"> super.addInterceptors(registry);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="11-定义会员Controller"><a href="#11-定义会员Controller" class="headerlink" title="11. 定义会员Controller"></a>11. 定义会员Controller</h5><ul><li>经过一个过滤器和一个拦截器,request请求终于来到了我们Controller层。这时候,我们只需要在方法里面写入MemberDetails memberDetails 就OK了,不用做任何操作,我们就可以获取会员信息了,是不是炒鸡方便!另外还可以在方法上标@Login注解。</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></pre></td><td class="code"><pre><span class="line">@RestController</span><br><span class="line">public class MemberController {</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">@RequestMapping("/token")</span><br><span class="line"> @Login</span><br><span class="line"> public Map<String, Object> getUser(MemberDetails memberDetails) {</span><br><span class="line"> //User user = userManager.selectByPrimaryKey(id);</span><br><span class="line"> Map<String, Object> map = new LinkedHashMap<>();</span><br><span class="line"> map.put("status", 200);</span><br><span class="line"> map.put("message", "请求成功");</span><br><span class="line"> map.put("data", memberDetails);</span><br><span class="line"> return map;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>运行结果:</p><p><img src="//ww1.sinaimg.cn/large/005zWjpngy1fqkm3hli7hj30u60a0abm.jpg" alt="img"></p><p><img src="//ww1.sinaimg.cn/large/005zWjpngy1fqkm5g7xp3j30u10cr76b.jpg" alt="img"></p><h4 id="遇到的坑:"><a href="#遇到的坑:" class="headerlink" title="遇到的坑:"></a>遇到的坑:</h4><ul><li><p>当时我尝试过把会员参数放到session域中的Attribute,也尝试过在Model里setAttribute。后来发现这是行不通的,在filter中直接使用request.setAttribute()是无效的。放在Modle也是可行,但是Controller里面的方法需要加@ModelAttribute(“…”)才能得到用户信息,很不方便。唯有通过request.getParameterMap() put()进去,才是最方便的。</p></li><li><p>一开始我没想到用过滤器,因此我就尝试在拦截器里,直接通过ParameterRequestWrapper对request包装,后来发现不管我怎么弄都不成功。当时非常绝望,后来想了想会不会是拦截器不支持重新包装request,于是我就通过filter去做,没想到成功了。这时,我想既然用到了filter,那干脆直接在filter里面获取@Login注解和获取方法参数得了,后来发现filter里面拿不到方法的信息,哭。后来想到一个办法,可以通过先filter,后拦截器。于是就成功了!</p></li></ul><h4 id="后记:"><a href="#后记:" class="headerlink" title="后记:"></a>后记:</h4><ul><li>这篇文章只是记录了我的一点小小经验,如果有什么不对的地方或者有更好的方法,请大家在评论里留言指正!</li></ul><p>参考文章:<a href="http://www.importnew.com/19023.html" target="_blank" rel="noopener">http://www.importnew.com/19023.html</a></p>]]></content>
<summary type="html">
<h4 id="前言:"><a href="#前言:" class="headerlink" title="前言:"></a>前言:</h4><ul>
<li>在开发当中,经常会验证用户登录状态和获取用户信息。如果每次都手动调用用户信息查询接口,会非常的繁琐,而且代码冗余。为了提
</summary>
<category term="Spring" scheme="http://www.seifon.cn/categories/Spring/"/>
<category term="拦截器" scheme="http://www.seifon.cn/tags/%E6%8B%A6%E6%88%AA%E5%99%A8/"/>
<category term="Filter" scheme="http://www.seifon.cn/tags/Filter/"/>
</entry>
<entry>
<title>Nginx的五种负载算法模式</title>
<link href="http://www.seifon.cn/2017/09/05/Nginx%E7%9A%84%E4%BA%94%E7%A7%8D%E8%B4%9F%E8%BD%BD%E7%AE%97%E6%B3%95%E6%A8%A1%E5%BC%8F/"/>
<id>http://www.seifon.cn/2017/09/05/Nginx的五种负载算法模式/</id>
<published>2017-09-04T17:03:00.000Z</published>
<updated>2018-01-24T15:13:45.000Z</updated>
<content type="html"><![CDATA[<h4 id="1、轮询(默认)"><a href="#1、轮询(默认)" class="headerlink" title="1、轮询(默认)"></a>1、轮询(默认)</h4><p>每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。 </p><blockquote><p>例如: </p></blockquote><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">upstream bakend { </span><br><span class="line">server 192.168.0.14; </span><br><span class="line">server 192.168.0.15; </span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="2、weight权重"><a href="#2、weight权重" class="headerlink" title="2、weight权重"></a>2、weight权重</h4><p>指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。 </p><blockquote><p>例如: </p></blockquote><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">upstream bakend { </span><br><span class="line">server 192.168.0.14 weight=10; </span><br><span class="line">server 192.168.0.15 weight=10; </span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="3、ip-hash"><a href="#3、ip-hash" class="headerlink" title="3、ip_hash"></a>3、ip_hash</h4><p>每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。 </p><blockquote><p>例如: </p></blockquote><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">upstream bakend { </span><br><span class="line">ip_hash; </span><br><span class="line">server 192.168.0.14:88; </span><br><span class="line">server 192.168.0.15:80; </span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="4、fair(第三方)"><a href="#4、fair(第三方)" class="headerlink" title="4、fair(第三方)"></a>4、fair(第三方)</h4><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></pre></td><td class="code"><pre><span class="line">upstream backend { </span><br><span class="line">server server1; </span><br><span class="line">server server2; </span><br><span class="line">fair; </span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="5、url-hash(第三方)"><a href="#5、url-hash(第三方)" class="headerlink" title="5、url_hash(第三方)"></a>5、url_hash(第三方)</h4><p>按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。 </p><p>例:在upstream中加入hash语句,server语句中不能写入weight等其他的参数,hash_method是使用的hash算法 </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">upstream backend { </span><br><span class="line">server squid1:3128; </span><br><span class="line">server squid2:3128; </span><br><span class="line">hash $request_uri; </span><br><span class="line">hash_method crc32; </span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>tips: </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">upstream bakend{#定义负载均衡设备的Ip及设备状态 </span><br><span class="line">ip_hash; </span><br><span class="line">server 127.0.0.1:9090 down; </span><br><span class="line">server 127.0.0.1:8080 weight=2; </span><br><span class="line">server 127.0.0.1:6060; </span><br><span class="line">server 127.0.0.1:7070 backup; </span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>在需要使用负载均衡的server中增加 </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">proxy_pass http://bakend/;</span><br></pre></td></tr></table></figure><h4 id="每个设备的状态设置为"><a href="#每个设备的状态设置为" class="headerlink" title="每个设备的状态设置为:"></a>每个设备的状态设置为:</h4><ul><li>1.down 表示单前的server暂时不参与负载 </li><li>2.weight 默认为1.weight越大,负载的权重就越大。 </li><li>3.max_fails :允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream 模块定义的错误 </li><li>4.fail_timeout:max_fails次失败后,暂停的时间。 </li><li>5.backup: 其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。 </li></ul>]]></content>
<summary type="html">
<h4 id="1、轮询(默认)"><a href="#1、轮询(默认)" class="headerlink" title="1、轮询(默认)"></a>1、轮询(默认)</h4><p>每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。 </
</summary>
<category term="Nginx" scheme="http://www.seifon.cn/categories/Nginx/"/>
<category term="Nginx" scheme="http://www.seifon.cn/tags/Nginx/"/>
<category term="负载均衡" scheme="http://www.seifon.cn/tags/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1/"/>
</entry>
<entry>
<title>高CPU占用调优</title>
<link href="http://www.seifon.cn/2017/09/05/%E9%AB%98CPU%E5%8D%A0%E7%94%A8%E8%B0%83%E4%BC%98/"/>
<id>http://www.seifon.cn/2017/09/05/高CPU占用调优/</id>
<published>2017-09-04T16:39:00.000Z</published>
<updated>2019-06-16T16:01:02.203Z</updated>
<content type="html"><![CDATA[<h4 id="根据top命令,发现PID为28555的Java进程占用CPU高达200-,出现故障。"><a href="#根据top命令,发现PID为28555的Java进程占用CPU高达200-,出现故障。" class="headerlink" title="根据top命令,发现PID为28555的Java进程占用CPU高达200%,出现故障。"></a>根据top命令,发现PID为28555的Java进程占用CPU高达200%,出现故障。</h4><p><img src="http://ww1.sinaimg.cn/large/8e24145egy1fjqjr9mfhxj20nb07k7fy.jpg" alt=""></p><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">ps aux | grep PID</span><br></pre></td></tr></table></figure><p>可以进一步确定是tomcat进程出现了问题。</p><p>但是,怎么定位到具体线程或者代码呢?</p><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">ps -mp pid -o THREAD,tid,time</span><br></pre></td></tr></table></figure><p><img src="http://ww1.sinaimg.cn/large/8e24145egy1fjqjtoveipj20nb08idrh.jpg" alt=""></p><p>找到了耗时最高的线程28802,占用CPU时间快两个小时了!</p><h4 id="其次将需要的线程ID转换为16进制格式:"><a href="#其次将需要的线程ID转换为16进制格式:" class="headerlink" title="其次将需要的线程ID转换为16进制格式:"></a>其次将需要的线程ID转换为16进制格式:</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">printf "%x\n" tid</span><br></pre></td></tr></table></figure><p><img src="http://ww1.sinaimg.cn/large/8e24145egy1fjqjvwb86vj20n804f416.jpg" alt=""></p><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">jstack pid |grep tid(16进制线程ID) –A60</span><br></pre></td></tr></table></figure><p><img src="http://ww1.sinaimg.cn/large/8e24145egy1fjqjviodt2j20o00afncx.jpg" alt=""></p><p>找到有问题的java代码(省略),进行业务调整和编码修改</p><h4 id="最后,总结下排查CPU故障的方法和技巧有哪些:"><a href="#最后,总结下排查CPU故障的方法和技巧有哪些:" class="headerlink" title="最后,总结下排查CPU故障的方法和技巧有哪些:"></a>最后,总结下排查CPU故障的方法和技巧有哪些:</h4><ul><li><p>1、top命令:Linux命令。可以查看实时的CPU使用情况。也可以查看最近一段时间的CPU使用情况。</p></li><li><p>2、PS命令:Linux命令。强大的进程状态监控命令。可以查看进程以及进程中线程的当前CPU使用情况。属于当前状态的采样数据。</p></li><li><p>3、jstack:Java提供的命令。可以查看某个进程的当前线程栈运行情况。根据这个命令的输出可以定位某个进程的所有线程的当前运行状态、运行代码,以及是否死锁等等。</p></li></ul>]]></content>
<summary type="html">
<h4 id="根据top命令,发现PID为28555的Java进程占用CPU高达200-,出现故障。"><a href="#根据top命令,发现PID为28555的Java进程占用CPU高达200-,出现故障。" class="headerlink" title="根据top命
</summary>
<category term="JAVA调优" scheme="http://www.seifon.cn/categories/JAVA%E8%B0%83%E4%BC%98/"/>
<category term="调优" scheme="http://www.seifon.cn/tags/%E8%B0%83%E4%BC%98/"/>
<category term="Jstack" scheme="http://www.seifon.cn/tags/Jstack/"/>
<category term="栈" scheme="http://www.seifon.cn/tags/%E6%A0%88/"/>
</entry>
<entry>
<title>开关指定端口,以80为例</title>
<link href="http://www.seifon.cn/2017/07/09/%E5%BC%80%E5%85%B3%E6%8C%87%E5%AE%9A%E7%AB%AF%E5%8F%A3%EF%BC%8C%E4%BB%A580%E4%B8%BA%E4%BE%8B/"/>
<id>http://www.seifon.cn/2017/07/09/开关指定端口,以80为例/</id>
<published>2017-07-09T06:02:54.000Z</published>
<updated>2018-01-24T15:13:45.000Z</updated>
<content type="html"><![CDATA[<h4 id="开启80端口:"><a href="#开启80端口:" class="headerlink" title="开启80端口:"></a>开启80端口:</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">iptables -I INPUT -p tcp --dport 80 -j ACCEPT</span><br></pre></td></tr></table></figure><a id="more"></a><h4 id="关闭80端口:"><a href="#关闭80端口:" class="headerlink" title="关闭80端口:"></a>关闭80端口:</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">iptables -I INPUT -p tcp --dport 80 -j DROP</span><br></pre></td></tr></table></figure><h4 id="保存并重启Iptables:"><a href="#保存并重启Iptables:" class="headerlink" title="保存并重启Iptables:"></a>保存并重启Iptables:</h4><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">/etc/init.d/iptables save</span><br><span class="line">service iptables restart</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h4 id="开启80端口:"><a href="#开启80端口:" class="headerlink" title="开启80端口:"></a>开启80端口:</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">iptables -I INPUT -p tcp --dport 80 -j ACCEPT</span><br></pre></td></tr></table></figure>
</summary>
<category term="Iptables" scheme="http://www.seifon.cn/categories/Iptables/"/>
<category term="centos" scheme="http://www.seifon.cn/tags/centos/"/>
<category term="linux" scheme="http://www.seifon.cn/tags/linux/"/>
<category term="iptables" scheme="http://www.seifon.cn/tags/iptables/"/>
<category term="防火墙" scheme="http://www.seifon.cn/tags/%E9%98%B2%E7%81%AB%E5%A2%99/"/>
</entry>
<entry>
<title>Jenkins环境搭建</title>
<link href="http://www.seifon.cn/2017/07/08/Jenkins%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/"/>
<id>http://www.seifon.cn/2017/07/08/Jenkins环境搭建/</id>
<published>2017-07-07T17:52:00.000Z</published>
<updated>2019-06-16T16:01:02.185Z</updated>
<content type="html"><![CDATA[<h4 id="上传以下的包到-tmp-目录下:"><a href="#上传以下的包到-tmp-目录下:" class="headerlink" title="上传以下的包到/tmp/目录下:"></a>上传以下的包到/tmp/目录下:</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></pre></td><td class="code"><pre><span class="line">jdk-8u121-linux-x64.tar.gz</span><br><span class="line">apache-tomcat-7.0.75.tar.gz</span><br><span class="line">apache-maven-3.5.0-bin.tar.gz</span><br><span class="line"></span><br><span class="line">MySQL-client-5.5.52-1.el6.x86_64.rpm</span><br><span class="line">MySQL-devel-5.5.52-1.el6.x86_64.rpm</span><br><span class="line">MySQL-server-5.5.52-1.el6.x86_64.rpm</span><br><span class="line">MySQL-shared-5.5.52-1.el6.x86_64.rpm</span><br><span class="line"></span><br><span class="line">git-2.9.3.tar.gz</span><br><span class="line">jenkins.war</span><br></pre></td></tr></table></figure><h4 id="解压包到-opt-目录下:"><a href="#解压包到-opt-目录下:" class="headerlink" title="解压包到/opt/目录下:"></a>解压包到/opt/目录下:</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></pre></td><td class="code"><pre><span class="line">tar -xvzf /tmp/jdk-8u121-linux-x64.tar.gz -C /opt/</span><br><span class="line"></span><br><span class="line">tar -xvzf /tmp/apache-tomcat-7.0.75.tar.gz -C /opt/</span><br><span class="line"></span><br><span class="line">tar -xvzf /tmp/apache-maven-3.5.0-bin.tar.gz -C /opt/</span><br></pre></td></tr></table></figure><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><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">vim /etc/profile</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">JAVA_HOME=/opt/jdk1.8.0_121</span><br><span class="line">CATALINA_HOME=/opt/apache-tomcat-7.0.75</span><br><span class="line">MAVEN_HOME=/opt/apache-maven-3.5.0</span><br><span class="line"></span><br><span class="line">PATH=/opt/jdk1.8.0_121/bin:/opt/apache-tomcat-7.0.75/bin:/opt/apache-maven-3.5.0/bin:$PATH</span><br><span class="line">CLASSPATH=.:/opt/jdk1.8.0_121/lib/dt.jar:/opt/jdk1.8.0_121/lib/tools.jar</span><br><span class="line">export JAVA_HOME PATH CLASSPATH CATALINA_HOME MAVEN_HOME</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">source /etc/profile</span><br></pre></td></tr></table></figure><hr><h4 id="配置Tomcat自启动:"><a href="#配置Tomcat自启动:" class="headerlink" title="配置Tomcat自启动:"></a>配置Tomcat自启动:</h4><ul><li>(1)、在/etc/init.d目录下创建文件:tomcat 内容如下:</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><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></pre></td><td class="code"><pre><span class="line">#!/bin/bash</span><br><span class="line"># This is the init script for starting up the</span><br><span class="line"># Jakarta Tomcat server</span><br><span class="line">#</span><br><span class="line"># chkconfig: 345 91 10</span><br><span class="line"># description: Starts and stops the Tomcat daemon.</span><br><span class="line">#</span><br><span class="line"></span><br><span class="line"># Source function library.</span><br><span class="line">. /etc/rc.d/init.d/functions</span><br><span class="line"></span><br><span class="line"># Get config.</span><br><span class="line">. /etc/sysconfig/network</span><br><span class="line"></span><br><span class="line"># Check that networking is up.</span><br><span class="line">[ "${NETWORKING}" = "no" ] && exit 0</span><br><span class="line"></span><br><span class="line">export JAVA_HOME=/opt/jdk1.8.0_121</span><br><span class="line">export CATALINA_HOME=/opt/apache-tomcat-7.0.75</span><br><span class="line">startup=$CATALINA_HOME/bin/startup.sh</span><br><span class="line">shutdown=$CATALINA_HOME/bin/shutdown.sh</span><br><span class="line"></span><br><span class="line">start(){</span><br><span class="line"> echo -n "Starting Tomcat service:"</span><br><span class="line"> cd $tomcat_home</span><br><span class="line"> $startup</span><br><span class="line"> echo "tomcat is succeessfully started up"</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">stop(){</span><br><span class="line"> echo -n "Shutting down tomcat: "</span><br><span class="line"> cd $tomcat_home</span><br><span class="line"> $shutdown</span><br><span class="line"> echo "tomcat is succeessfully shut down."</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">status(){</span><br><span class="line"> numproc=`ps -ef | grep catalina | grep -v "grep catalina" | wc -l`</span><br><span class="line"> if [ $numproc -gt 0 ]; then</span><br><span class="line"> echo "Tomcat is running..."</span><br><span class="line"> else</span><br><span class="line"> echo "Tomcat is stopped..."</span><br><span class="line"> fi</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">restart(){</span><br><span class="line"> stop</span><br><span class="line"> start</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"># See how we were called.</span><br><span class="line">case "$1" in</span><br><span class="line">start)</span><br><span class="line"> start</span><br><span class="line"> ;;</span><br><span class="line">stop)</span><br><span class="line"> stop</span><br><span class="line"> ;;</span><br><span class="line">status)</span><br><span class="line"> status</span><br><span class="line"> ;;</span><br><span class="line">restart)</span><br><span class="line"> restart</span><br><span class="line"> ;;</span><br><span class="line">*)</span><br><span class="line"> echo $"Usage: $0 {start|stop|status|restart}"</span><br><span class="line"> exit 1</span><br><span class="line">esac</span><br></pre></td></tr></table></figure><ul><li>(2)、配置权限,并加入自启:</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></pre></td><td class="code"><pre><span class="line">cd /etc/init.d</span><br><span class="line">chmod 755 ./tomcat</span><br><span class="line">chkconfig --add tomcat</span><br><span class="line">chkconfig tomcat on</span><br></pre></td></tr></table></figure><ul><li>(3)、设置URIEncoding=”UTF-8”</li></ul><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">vim /opt/apache-tomcat-7.0.75/conf/server.xml</span><br></pre></td></tr></table></figure><ul><li>(4)、给Tomcat设置用户名密码</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></pre></td><td class="code"><pre><span class="line">vim /opt/apache-tomcat-7.0.75/conf/tomcat-users.xml</span><br><span class="line"></span><br><span class="line"><role rolename="manager-gui"/></span><br><span class="line"><role rolename="manager-script"/></span><br><span class="line"><role rolename="manager-jmx"/></span><br><span class="line"><role rolename="manager-status"/></span><br><span class="line"><user username="tomcat_user" password="123456" roles="manager-gui,manager-script,manager-jmx,manager-status" /></span><br></pre></td></tr></table></figure><ul><li>(5)、打开/etc/sysconfig/iptables 加入以下代码:</li></ul><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">-A INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT</span><br></pre></td></tr></table></figure><ul><li>(6)、重启防火墙服务</li></ul><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">service iptables restart</span><br></pre></td></tr></table></figure><hr><h4 id="安装Mysql服务:"><a href="#安装Mysql服务:" class="headerlink" title="安装Mysql服务:"></a>安装Mysql服务:</h4><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></pre></td><td class="code"><pre><span class="line">rpm -ivh /tmp/MySQL-server-5.5.52-1.el6.x86_64.rpm</span><br><span class="line"></span><br><span class="line">如果出现报错就执行:</span><br><span class="line">rpm -e --nodeps mysql-libs-5.1.73-7.el6.x86_64</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></pre></td><td class="code"><pre><span class="line">rpm -ivh /tmp/MySQL-client-5.5.52-1.el6.x86_64.rpm</span><br></pre></td></tr></table></figure><ul><li>启动MySQL服务</li></ul><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">service mysql start</span><br></pre></td></tr></table></figure><ul><li>修改MySQL服务器登录密码</li></ul><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">/usr/bin/mysqladmin -u root password 'root'</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">vim /etc/sysconfig/iptables</span><br><span class="line"></span><br><span class="line">-A INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT</span><br><span class="line"></span><br><span class="line">service iptables restart</span><br></pre></td></tr></table></figure><hr><h4 id="修改MySQL服务器访问权限"><a href="#修改MySQL服务器访问权限" class="headerlink" title="修改MySQL服务器访问权限"></a>修改MySQL服务器访问权限</h4><ul><li>第一步:登录MySQL服务器</li><li>第二步:use mysql;</li><li>第三步:查看user表部分内容</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></pre></td><td class="code"><pre><span class="line">mysql> select host,user,password from user;</span><br><span class="line">+--------------+------+-------------------------------------------+</span><br><span class="line">| host | user | password |</span><br><span class="line">+--------------+------+-------------------------------------------+</span><br><span class="line">| localhost | root | *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B |</span><br><span class="line">| computer0325 | root | |</span><br><span class="line">| 127.0.0.1 | root | |</span><br><span class="line">| ::1 | root | |</span><br><span class="line">| localhost | | |</span><br><span class="line">| computer0325 | | |</span><br><span class="line">+--------------+------+-------------------------------------------+</span><br><span class="line">6 rows in set (0.00 sec)</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></pre></td><td class="code"><pre><span class="line">insert into user(host,user,password) values('%','root','*81F5E21E35407D884A6CD4A731AEBFB6AF209E1B');</span><br></pre></td></tr></table></figure><ul><li>第五步:再次查看user表内容</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></pre></td><td class="code"><pre><span class="line">mysql> select host,user,password from user;</span><br><span class="line">+--------------+------+-------------------------------------------+</span><br><span class="line">| host | user | password |</span><br><span class="line">+--------------+------+-------------------------------------------+</span><br><span class="line">| localhost | root | *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B |</span><br><span class="line">| computer0325 | root | |</span><br><span class="line">| 127.0.0.1 | root | |</span><br><span class="line">| ::1 | root | |</span><br><span class="line">| localhost | | |</span><br><span class="line">| computer0325 | | |</span><br><span class="line">| % | root | *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B |</span><br><span class="line">+--------------+------+-------------------------------------------+</span><br></pre></td></tr></table></figure><ul><li>第六步:为root@%授权</li></ul><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">mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION;</span><br></pre></td></tr></table></figure><ul><li>第七步:退出MySQL</li></ul><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">mysql> exit;</span><br></pre></td></tr></table></figure><ul><li>第八步:重启MySQL服务</li></ul><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">service mysql restart;</span><br></pre></td></tr></table></figure><hr><h4 id="编译安装git"><a href="#编译安装git" class="headerlink" title="编译安装git"></a>编译安装git</h4><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><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel</span><br><span class="line"></span><br><span class="line">yum install gcc perl-ExtUtils-MakeMaker</span><br></pre></td></tr></table></figure></li><li><p>删除已有的git:</p></li></ul><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 remove git</span><br></pre></td></tr></table></figure><ul><li>编译git:</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></pre></td><td class="code"><pre><span class="line">tar -xvzf ./git-2.9.3.tar.gz -C /opt/</span><br><span class="line">cd /opt/git-2.9.3/</span><br><span class="line">make prefix=/usr/local/git all</span><br><span class="line">make prefix=/usr/local/git install</span><br><span class="line">echo "export PATH=$PATH:/usr/local/git/bin" >> /etc/bashrc</span><br><span class="line">source /etc/bashrc</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></pre></td><td class="code"><pre><span class="line">git --version</span><br></pre></td></tr></table></figure><hr><h4 id="部署Jenkins-war包,以及初始化环境:"><a href="#部署Jenkins-war包,以及初始化环境:" class="headerlink" title="部署Jenkins.war包,以及初始化环境:"></a>部署Jenkins.war包,以及初始化环境:</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">cp /tmp/jenkins.war /opt/apache-tomcat-7.0.75/webapps/</span><br></pre></td></tr></table></figure><ul><li>通过浏览器访问Tomcat下的jenkins应用</li></ul><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">例如:http://[server-address]:8080/jenkins/</span><br></pre></td></tr></table></figure><ul><li>输入内置密钥串</li></ul><p><img src="http://ww1.sinaimg.cn/large/8e24145egy1fi82tr5h3aj211t0ieq48.jpg" alt=""></p><ul><li>先不安装插件,后面有需要时再安装,点右上角的×</li></ul><p><img src="http://ww1.sinaimg.cn/large/8e24145egy1fi82wdsq6pj211t0iego2.jpg" alt=""></p><ul><li>修改默认管理员密码</li></ul><hr><h4 id="安装GitHub-plugin-和-Deploy-to-container-Plugin-插件"><a href="#安装GitHub-plugin-和-Deploy-to-container-Plugin-插件" class="headerlink" title="安装GitHub plugin 和 Deploy to container Plugin 插件"></a>安装GitHub plugin 和 Deploy to container Plugin 插件</h4><p><img src="http://ww1.sinaimg.cn/large/8e24145egy1fi83uloclej205300vjr5.jpg" alt=""></p><p><img src="http://ww1.sinaimg.cn/large/8e24145egy1fi83yo3d5pj205r00r0si.jpg" alt=""></p><ul><li>点击系统管理,进入系统设置界面</li></ul><p><img src="http://ww1.sinaimg.cn/large/8e24145egy1fi831ouwi2j20hx08naax.jpg" alt=""></p><blockquote><p>Configure Global Security</p></blockquote><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">①勾选允许用户注册,这样万一我们忘记了之前的账号密码还可以再注册一个</span><br><span class="line">②勾选任何用户可以做任何事(没有任何限制)</span><br><span class="line">③取消防止跨站点请求伪造勾选</span><br></pre></td></tr></table></figure><blockquote><p>Global Tool Configuration</p></blockquote><ul><li>①设置Maven</li></ul><p><img src="http://ww1.sinaimg.cn/large/8e24145egy1fi8341ynlxj20qk08tt92.jpg" alt=""></p><ul><li>②设置JDK,不要选自动安装,因为我们自己安装过了</li></ul><p><img src="http://ww1.sinaimg.cn/large/8e24145egy1fi83524o09j20qi07j0sr.jpg" alt=""></p><ul><li>③设置MAVEN_HOME,同样不要自动安装</li></ul><p><img src="http://ww1.sinaimg.cn/large/8e24145egy1fi835r1x01j20qj07h3yk.jpg" alt=""></p><ul><li>④设置Git:/usr/local/git/bin/git</li></ul><p><img src="http://ww1.sinaimg.cn/large/8e24145egy1fi836rzcysj20qf07oglm.jpg" alt=""></p>]]></content>
<summary type="html">
<h4 id="上传以下的包到-tmp-目录下:"><a href="#上传以下的包到-tmp-目录下:" class="headerlink" title="上传以下的包到/tmp/目录下:"></a>上传以下的包到/tmp/目录下:</h4><figure class="hi
</summary>
<category term="Jenkins" scheme="http://www.seifon.cn/categories/Jenkins/"/>
<category term="Jenkins" scheme="http://www.seifon.cn/tags/Jenkins/"/>
<category term="CI" scheme="http://www.seifon.cn/tags/CI/"/>
</entry>
<entry>
<title>Yaml语法说明</title>
<link href="http://www.seifon.cn/2017/06/27/Yaml%E8%AF%AD%E6%B3%95%E8%AF%B4%E6%98%8E/"/>
<id>http://www.seifon.cn/2017/06/27/Yaml语法说明/</id>
<published>2017-06-26T17:19:00.000Z</published>
<updated>2018-01-24T15:13:45.000Z</updated>
<content type="html"><![CDATA[<h4 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h4><p>YAML 是专门用来写配置文件的语言,非常简洁和强大,远比 JSON 格式方便。</p><h4 id="语法规则"><a href="#语法规则" class="headerlink" title="语法规则"></a>语法规则</h4><ul><li>大小写敏感</li><li>使用缩进表示层级关系</li><li>缩进时不允许使用Tab键,只允许使用空格。</li><li>缩进的空格数目不重要,只要相同层级的元素左侧对齐即可</li><li>:冒号后面必须有空格</li><li>#表示注释,从这个字符一直到行尾,都会被解析器忽略。</li></ul><h4 id="YAML支持三种数据结构:"><a href="#YAML支持三种数据结构:" class="headerlink" title="YAML支持三种数据结构:"></a>YAML支持三种数据结构:</h4><ul><li>对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)</li><li>数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)</li><li>纯量(scalars):单个的、不可再分的值</li></ul><hr><h4 id="对象"><a href="#对象" class="headerlink" title="对象"></a>对象</h4><blockquote><p><strong>一、对象的一组键值对,使用冒号结构表示。</strong></p></blockquote><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">animal: pets</span><br></pre></td></tr></table></figure><blockquote><p>转为 JavaScript 如下:</p></blockquote><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">{ animal: 'pets' }</span><br></pre></td></tr></table></figure><hr><blockquote><p><strong>二、将所有键值对写成一个行内对象。</strong></p></blockquote><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">hash: { name: Steve, foo: bar }</span><br></pre></td></tr></table></figure><blockquote><p>转为 JavaScript 如下</p></blockquote><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">{ hash: { name: 'Steve', foo: 'bar' } }</span><br></pre></td></tr></table></figure><h4 id="数组"><a href="#数组" class="headerlink" title="数组"></a>数组</h4><blockquote><p><strong>一、一组连词线开头的行,构成一个数组。</strong></p></blockquote><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">- Cat</span><br><span class="line">- Dog</span><br><span class="line">- Goldfish</span><br></pre></td></tr></table></figure><blockquote><p>转为 JavaScript 如下。</p></blockquote><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">[ 'Cat', 'Dog', 'Goldfish' ]</span><br></pre></td></tr></table></figure><blockquote><p>数据结构的子成员是一个数组,则可以在该项下面缩进一个空格。</p></blockquote><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"> - Cat</span><br><span class="line"> - Dog</span><br><span class="line"> - Goldfish</span><br></pre></td></tr></table></figure><blockquote><p>转为 JavaScript 如下。</p></blockquote><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">[ [ 'Cat', 'Dog', 'Goldfish' ] ]</span><br></pre></td></tr></table></figure><hr><blockquote><p><strong>二、数组也可以采用行内表示法。</strong></p></blockquote><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">animal: [Cat, Dog]</span><br></pre></td></tr></table></figure><blockquote><p>转为 JavaScript 如下。</p></blockquote><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">{ animal: [ 'Cat', 'Dog' ] }</span><br></pre></td></tr></table></figure><h4 id="复合结构"><a href="#复合结构" class="headerlink" title="复合结构"></a>复合结构</h4><blockquote><p>对象和数组可以结合使用,形成复合结构。</p></blockquote><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></pre></td><td class="code"><pre><span class="line">languages:</span><br><span class="line"> - Ruby</span><br><span class="line"> - Perl</span><br><span class="line"> - Python </span><br><span class="line">websites:</span><br><span class="line"> YAML: yaml.org </span><br><span class="line"> Ruby: ruby-lang.org </span><br><span class="line"> Python: python.org </span><br><span class="line"> Perl: use.perl.org</span><br></pre></td></tr></table></figure><blockquote><p>转为 JavaScript 如下:</p></blockquote><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">{ languages: [ 'Ruby', 'Perl', 'Python' ],</span><br><span class="line"> websites: </span><br><span class="line"> { YAML: 'yaml.org',</span><br><span class="line"> Ruby: 'ruby-lang.org',</span><br><span class="line"> Python: 'python.org',</span><br><span class="line"> Perl: 'use.perl.org' } }</span><br></pre></td></tr></table></figure><h4 id="纯量"><a href="#纯量" class="headerlink" title="纯量"></a>纯量</h4><blockquote><p>纯量是最基本的、不可再分的值。以下数据类型都属于 JavaScript 的纯量。</p></blockquote><blockquote><p>字符串<br>布尔值<br>整数<br>浮点数<br>Null<br>时间<br>日期</p></blockquote><hr><blockquote><p>数值直接以字面量的形式表示。</p></blockquote><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">number: 12.30</span><br></pre></td></tr></table></figure><blockquote><p>转为 JavaScript 如下。</p></blockquote><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">{ number: 12.30 }</span><br></pre></td></tr></table></figure><hr><blockquote><p>布尔值用true和false表示。</p></blockquote><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">isSet: true</span><br></pre></td></tr></table></figure><blockquote><p>转为 JavaScript 如下。</p></blockquote><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">{ isSet: true }</span><br></pre></td></tr></table></figure><hr><blockquote><p>null用~表示。</p></blockquote><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">parent: ~</span><br></pre></td></tr></table></figure><blockquote><p>转为 JavaScript 如下。</p></blockquote><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">{ parent: null }</span><br></pre></td></tr></table></figure><hr><blockquote><p>时间采用 ISO8601 格式。</p></blockquote><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">iso8601: 2001-12-14t21:59:43.10-05:00</span><br></pre></td></tr></table></figure><blockquote><p>转为 JavaScript 如下。</p></blockquote><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">{ iso8601: new Date('2001-12-14t21:59:43.10-05:00') }</span><br></pre></td></tr></table></figure><hr><blockquote><p>日期采用复合 iso8601 格式的年、月、日表示。</p></blockquote><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">date: 1976-07-31</span><br></pre></td></tr></table></figure><blockquote><p>转为 JavaScript 如下。</p></blockquote><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">{ date: new Date('1976-07-31') }</span><br></pre></td></tr></table></figure><hr><blockquote><p>YAML 允许使用两个感叹号,强制转换数据类型。</p></blockquote><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">e: !!str 123</span><br><span class="line">f: !!str true</span><br></pre></td></tr></table></figure><blockquote><p>转为 JavaScript 如下。</p></blockquote><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">{ e: '123', f: 'true' }</span><br></pre></td></tr></table></figure><h4 id="字符串"><a href="#字符串" class="headerlink" title="字符串"></a>字符串</h4><blockquote><p>字符串是最常见,也是最复杂的一种数据类型。字符串默认不使用引号表示。</p></blockquote><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">str: 这是一行字符串</span><br></pre></td></tr></table></figure><blockquote><p>转为 JavaScript 如下。</p></blockquote><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">{ str: '这是一行字符串' }</span><br></pre></td></tr></table></figure><hr><blockquote><p>如果字符串之中包含空格或特殊字符,需要放在引号之中。</p></blockquote><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">str: '内容: 字符串'</span><br></pre></td></tr></table></figure><blockquote><p>转为 JavaScript 如下。</p></blockquote><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">str: '内容: 字符串'</span><br></pre></td></tr></table></figure><hr><blockquote><p>单引号和双引号都可以使用,双引号不会对特殊字符转义。</p></blockquote><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">s1: '内容\n字符串'</span><br><span class="line">s2: "内容\n字符串"</span><br></pre></td></tr></table></figure><blockquote><p>转为 JavaScript 如下。</p></blockquote><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">{ s1: '内容\\n字符串', s2: '内容\n字符串' }</span><br></pre></td></tr></table></figure><hr><blockquote><p>单引号之中如果还有单引号,必须连续使用两个单引号转义。</p></blockquote><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">str: 'labor''s day'</span><br></pre></td></tr></table></figure><blockquote><p>转为 JavaScript 如下。</p></blockquote><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">{ str: 'labor\'s day' }</span><br></pre></td></tr></table></figure><hr><blockquote><p>字符串可以写成多行,从第二行开始,必须有一个单空格缩进。换行符会被转为空格。</p></blockquote><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">str: 这是一段</span><br><span class="line"> 多行</span><br><span class="line"> 字符串</span><br></pre></td></tr></table></figure><blockquote><p>转为 JavaScript 如下。</p></blockquote><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">{ str: '这是一段 多行 字符串' }</span><br></pre></td></tr></table></figure><hr><blockquote><p>多行字符串可以使用|保留换行符,也可以使用>折叠换行。</p></blockquote><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">this: |</span><br><span class="line"> Foo</span><br><span class="line"> Bar</span><br><span class="line">that: ></span><br><span class="line"> Foo</span><br><span class="line"> Bar</span><br></pre></td></tr></table></figure><blockquote><p>转为 JavaScript 代码如下。</p></blockquote><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">{ this: 'Foo\nBar\n', that: 'Foo Bar\n' }</span><br></pre></td></tr></table></figure><hr><blockquote><p>+表示保留文字块末尾的换行,-表示删除字符串末尾的换行。</p></blockquote><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></pre></td><td class="code"><pre><span class="line">s1: |</span><br><span class="line"> Foo</span><br><span class="line"></span><br><span class="line">s2: |+</span><br><span class="line"> Foo</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">s3: |-</span><br><span class="line"> Foo</span><br></pre></td></tr></table></figure><blockquote><p>转为 JavaScript 代码如下。</p></blockquote><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">{ s1: 'Foo\n', s2: 'Foo\n\n\n', s3: 'Foo' }</span><br></pre></td></tr></table></figure><hr><blockquote><p>字符串之中可以插入 HTML 标记。</p></blockquote><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">message: |</span><br><span class="line"></span><br><span class="line"> </span><br><span class="line"> 段落</span><br></pre></td></tr></table></figure><blockquote><p>转为 JavaScript 如下。</p></blockquote><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">{ message: '\n</span><br><span class="line">\n 段落\n</span><br><span class="line">\n' }</span><br></pre></td></tr></table></figure><h4 id="引用"><a href="#引用" class="headerlink" title="引用"></a>引用</h4><blockquote><p>锚点&和别名*,可以用来引用。</p></blockquote><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">defaults: &defaults</span><br><span class="line"> adapter: postgres</span><br><span class="line"> host: localhost</span><br><span class="line"></span><br><span class="line">development:</span><br><span class="line"> database: myapp_development</span><br><span class="line"> <<: *defaults</span><br><span class="line"></span><br><span class="line">test:</span><br><span class="line"> database: myapp_test</span><br><span class="line"> <<: *defaults</span><br></pre></td></tr></table></figure><blockquote><p>等同于下面的代码。</p></blockquote><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">defaults:</span><br><span class="line"> adapter: postgres</span><br><span class="line"> host: localhost</span><br><span class="line"></span><br><span class="line">development:</span><br><span class="line"> database: myapp_development</span><br><span class="line"> adapter: postgres</span><br><span class="line"> host: localhost</span><br><span class="line"></span><br><span class="line">test:</span><br><span class="line"> database: myapp_test</span><br><span class="line"> adapter: postgres</span><br><span class="line"> host: localhost</span><br></pre></td></tr></table></figure><blockquote><p>&用来建立锚点(defaults),<<表示合并到当前数据,*用来引用锚点。</p></blockquote><hr><blockquote><p>下面是另一个例子。</p></blockquote><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">- &showell Steve </span><br><span class="line">- Clark </span><br><span class="line">- Brian </span><br><span class="line">- Oren </span><br><span class="line">- *showell</span><br></pre></td></tr></table></figure><blockquote><p>转为 JavaScript 代码如下。</p></blockquote><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">[ 'Steve', 'Clark', 'Brian', 'Oren', 'Steve' ]</span><br></pre></td></tr></table></figure><h4 id="函数和正则表达式的转换"><a href="#函数和正则表达式的转换" class="headerlink" title="函数和正则表达式的转换"></a>函数和正则表达式的转换</h4><blockquote><p>这是 JS-YAML 库特有的功能,可以把函数和正则表达式转为字符串。</p></blockquote><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"># example.yml</span><br><span class="line">fn: function () { return 1 }</span><br><span class="line">reg: /test/</span><br></pre></td></tr></table></figure><blockquote><p>解析上面的 yml 文件的代码如下。</p></blockquote><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">var yaml = require('js-yaml');</span><br><span class="line">var fs = require('fs');</span><br><span class="line"></span><br><span class="line">try {</span><br><span class="line"> var doc = yaml.load(</span><br><span class="line"> fs.readFileSync('./example.yml', 'utf8')</span><br><span class="line"> );</span><br><span class="line"> console.log(doc);</span><br><span class="line">} catch (e) {</span><br><span class="line"> console.log(e);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><blockquote><p>从 JavaScript 对象还原到 yaml 文件的代码如下。</p></blockquote><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></pre></td><td class="code"><pre><span class="line">var yaml = require('js-yaml');</span><br><span class="line">var fs = require('fs');</span><br><span class="line"></span><br><span class="line">var obj = {</span><br><span class="line"> fn: function () { return 1 },</span><br><span class="line"> reg: /test/</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line">try {</span><br><span class="line"> fs.writeFileSync(</span><br><span class="line"> './example.yml',</span><br><span class="line"> yaml.dump(obj),</span><br><span class="line"> 'utf8'</span><br><span class="line"> );</span><br><span class="line">} catch (e) {</span><br><span class="line"> console.log(e);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h4 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h4><p>YAML 是专门用来写配置文件的语言,非常简洁和强大,远比 JSON 格式方便。</p>
<h4 id="语法规则"><a href="#语
</summary>
<category term="Yaml" scheme="http://www.seifon.cn/categories/Yaml/"/>
<category term="Yaml" scheme="http://www.seifon.cn/tags/Yaml/"/>
<category term="yml" scheme="http://www.seifon.cn/tags/yml/"/>
</entry>
<entry>
<title>Mysql异地定时备份方法</title>
<link href="http://www.seifon.cn/2017/05/03/Mysql%E5%BC%82%E5%9C%B0%E5%AE%9A%E6%97%B6%E5%A4%87%E4%BB%BD%E6%96%B9%E6%B3%95/"/>
<id>http://www.seifon.cn/2017/05/03/Mysql异地定时备份方法/</id>
<published>2017-05-02T16:51:00.000Z</published>
<updated>2018-01-24T15:13:45.000Z</updated>
<content type="html"><![CDATA[<h4 id="两台linux服务器:"><a href="#两台linux服务器:" class="headerlink" title="两台linux服务器:"></a>两台linux服务器:</h4><ul><li>一台199.20.30.222(mysql服务器)</li><li>一台199.20.30.226(与mysql互通的一台server)</li></ul><p>思路:mysql本地做一份备份;226Server做一份同步备份,脚本放在222上面,定时任务也设置在222上面。</p><h5 id="(1)mysql本地备份:"><a href="#(1)mysql本地备份:" class="headerlink" title="(1)mysql本地备份:"></a>(1)mysql本地备份:</h5><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">#!/bin/sh</span><br><span class="line">#mysql_backup</span><br><span class="line">DATE=`date +%Y%m%d`</span><br><span class="line">/opt/mysql/bin/mysqldump --opt jsweb -u root > /opt/mysqlbackup/$DATE.sql</span><br></pre></td></tr></table></figure><h5 id="(2)将本地备份同步到远端226上面:"><a href="#(2)将本地备份同步到远端226上面:" class="headerlink" title="(2)将本地备份同步到远端226上面:"></a>(2)将本地备份同步到远端226上面:</h5><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">#!/bin/bash</span><br><span class="line">#date:2013/09/24</span><br><span class="line">#function:The script is used copying mysqlbackup to 226</span><br><span class="line">DATE=`date +%Y%m%d`</span><br><span class="line">scp /opt/mysqlbackup/$DATE.sql [email protected]:/data/2013backup/mysql/</span><br></pre></td></tr></table></figure><h5 id="(3)222上面设置定时任务:"><a href="#(3)222上面设置定时任务:" class="headerlink" title="(3)222上面设置定时任务:"></a>(3)222上面设置定时任务:</h5><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">vim/etc/crontable OR crontable -e</span><br><span class="line">30 1 * * * /bin/sh /home/jiaoben/backup.sh ===============每天1:30执行</span><br><span class="line">30 3 * * * /bin/sh /home/jiaoben/scp.sh ===============每天3:30执行</span><br></pre></td></tr></table></figure><blockquote><p> 注意:两个linux之间相互拷贝文件,使用scp工具必须输入远端密码,所以在进行(2)时,需要规避输入密码,否则自动备份到remote不会生效,<br> 本人采用的方法:使两个服务器互相信任,执行scp时,就可以免输入密码。</p></blockquote><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">ssh-keygen -t rsa</span><br><span class="line">cd /root/.ssh/</span><br><span class="line">scp id_rsa.pub [email protected]:/root/ssh/</span><br><span class="line">ssh [email protected]</span><br><span class="line">mv /root/.ssh/id_isa_pub /root/.ssh/authorized_key</span><br></pre></td></tr></table></figure><h4 id="时间过长备份的mysql就需要定时清理"><a href="#时间过长备份的mysql就需要定时清理" class="headerlink" title="时间过长备份的mysql就需要定时清理"></a>时间过长备份的mysql就需要定时清理</h4><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">find /opt/mysqlbackup/ -type f -name \*.sql -mtime +10 -exec rm -fr {} \;</span><br><span class="line">find /opt/mysqlbackup/ -type f -name "*.sql" -mtime +10 -exec rm -fr {} \;</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h4 id="两台linux服务器:"><a href="#两台linux服务器:" class="headerlink" title="两台linux服务器:"></a>两台linux服务器:</h4><ul>
<li>一台199.20.30.222(mysql服务器)</l
</summary>
<category term="Mysql" scheme="http://www.seifon.cn/categories/Mysql/"/>
<category term="Mysql" scheme="http://www.seifon.cn/tags/Mysql/"/>
<category term="数据库" scheme="http://www.seifon.cn/tags/%E6%95%B0%E6%8D%AE%E5%BA%93/"/>
<category term="备份" scheme="http://www.seifon.cn/tags/%E5%A4%87%E4%BB%BD/"/>
<category term="定时" scheme="http://www.seifon.cn/tags/%E5%AE%9A%E6%97%B6/"/>
<category term="容灾" scheme="http://www.seifon.cn/tags/%E5%AE%B9%E7%81%BE/"/>
</entry>
<entry>
<title>CentOS7防火墙Firewalld配置和使用</title>
<link href="http://www.seifon.cn/2017/05/02/CentOS7%E9%98%B2%E7%81%AB%E5%A2%99Firewalld%E9%85%8D%E7%BD%AE%E5%92%8C%E4%BD%BF%E7%94%A8/"/>
<id>http://www.seifon.cn/2017/05/02/CentOS7防火墙Firewalld配置和使用/</id>
<published>2017-05-02T06:55:00.000Z</published>
<updated>2018-01-24T15:13:45.000Z</updated>
<content type="html"><![CDATA[<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">firewall-cmd --permanent --zone=public --add-port=80/tcp</span><br></pre></td></tr></table></figure><a id="more"></a><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">firewall-cmd --permanent --zone=public --remove-port=80/tcp</span><br></pre></td></tr></table></figure><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">firewall-cmd --reload</span><br></pre></td></tr></table></figure><h5 id="命令含义:"><a href="#命令含义:" class="headerlink" title="命令含义:"></a>命令含义:</h5><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">--zone #作用域</span><br><span class="line"></span><br><span class="line">--add-port=80/tcp #添加端口,格式为:端口/通讯协议</span><br><span class="line"></span><br><span class="line">--permanent #永久生效,没有此参数重启后失效</span><br></pre></td></tr></table></figure><hr><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">cat /etc/firewalld/zones/public.xml | less</span><br></pre></td></tr></table></figure><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">systemctl status firewalld.service</span><br></pre></td></tr></table></figure><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">systemctl start firewalld.service</span><br></pre></td></tr></table></figure><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">systemctl stop firewalld.service</span><br></pre></td></tr></table></figure><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">systemctl restart firewalld.service</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<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">firewall-cmd --permanent --zone=public --add-port=80/tcp</span><br></pre></td></tr></table></figure>
</summary>
<category term="Iptables" scheme="http://www.seifon.cn/categories/Iptables/"/>
<category term="centos" scheme="http://www.seifon.cn/tags/centos/"/>
<category term="linux" scheme="http://www.seifon.cn/tags/linux/"/>
<category term="iptables" scheme="http://www.seifon.cn/tags/iptables/"/>
<category term="防火墙" scheme="http://www.seifon.cn/tags/%E9%98%B2%E7%81%AB%E5%A2%99/"/>
</entry>
<entry>
<title>出圈算法</title>
<link href="http://www.seifon.cn/2017/04/13/%E5%87%BA%E5%9C%88%E7%AE%97%E6%B3%95/"/>
<id>http://www.seifon.cn/2017/04/13/出圈算法/</id>
<published>2017-04-12T16:58:00.000Z</published>
<updated>2018-01-24T15:13:45.000Z</updated>
<content type="html"><![CDATA[<h4 id="题目:有-people-个人站成一个圈,第一个人开始数数(从1开始),每数到-num-或者-num-的倍数此人就退出。最后剩下的人是多少号?"><a href="#题目:有-people-个人站成一个圈,第一个人开始数数(从1开始),每数到-num-或者-num-的倍数此人就退出。最后剩下的人是多少号?" class="headerlink" title="题目:有 people 个人站成一个圈,第一个人开始数数(从1开始),每数到 num 或者 num 的倍数此人就退出。最后剩下的人是多少号?"></a>题目:有 people 个人站成一个圈,第一个人开始数数(从1开始),每数到 num 或者 num 的倍数此人就退出。最后剩下的人是多少号?</h4><p>网上看了看,应该有很多种实现方法,在此摘录下来。</p><h5 id="方式一:"><a href="#方式一:" class="headerlink" title="方式一:"></a>方式一:</h5><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">static int cycle(int people, int num) { </span><br><span class="line"> int i, r = 0; </span><br><span class="line"> for (i = 2; i <= people; i++) { </span><br><span class="line"> r = (r + num) % i; </span><br><span class="line"> } </span><br><span class="line"> return r + 1; </span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="方式二:"><a href="#方式二:" class="headerlink" title="方式二:"></a>方式二:</h5><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">static int cycle(int people, int num) { </span><br><span class="line"> int i, r = 0; </span><br><span class="line"> for (i = 2; i <= people; i++) r = (r + num) % i;</span><br><span class="line"> return r + 1; </span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="方式三:"><a href="#方式三:" class="headerlink" title="方式三:"></a>方式三:</h5><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">private static int cycle(int people, int num) {</span><br><span class="line"> List<Integer> dataList = new LinkedList<Integer>(); </span><br><span class="line"> for (int i = 0; i < people; i++) { </span><br><span class="line"> dataList.add(new Integer(i + 1)); </span><br><span class="line"> } </span><br><span class="line"></span><br><span class="line"> int index = -1; </span><br><span class="line"> while (dataList.size() > 1) { </span><br><span class="line"> index = (index + num) % dataList.size(); </span><br><span class="line"> dataList.remove(index); </span><br><span class="line"> index--; </span><br><span class="line"> } </span><br><span class="line"> return dataList.get(0).intValue(); </span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h4 id="题目:有-people-个人站成一个圈,第一个人开始数数(从1开始),每数到-num-或者-num-的倍数此人就退出。最后剩下的人是多少号?"><a href="#题目:有-people-个人站成一个圈,第一个人开始数数(从1开始),每数到-num-或者-num-
</summary>
<category term="算法" scheme="http://www.seifon.cn/categories/%E7%AE%97%E6%B3%95/"/>
<category term="算法" scheme="http://www.seifon.cn/tags/%E7%AE%97%E6%B3%95/"/>
<category term="数据结构" scheme="http://www.seifon.cn/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"/>
<category term="面试" scheme="http://www.seifon.cn/tags/%E9%9D%A2%E8%AF%95/"/>
</entry>
</feed>