-
Notifications
You must be signed in to change notification settings - Fork 2
/
baidusitemap.xml
636 lines (463 loc) · 131 KB
/
baidusitemap.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>http://dreajay.github.io/2014/11/21/mybatis-build-SqlSessionFactory/</loc>
<lastmod>2017-03-08T13:06:07.000Z</lastmod>
<data>
<display>
<title>mybatis构建SqlSessionFactory</title>
<pubTime>2014-11-21T03:40:57.000Z</pubTime>
<tag>java </tag>
<tag>mybatis </tag>
<tag>SqlSessionFactory </tag>
<content><![CDATA[<p>SqlSessionFactory是mybatis的重要角色,是mybatis的整个程序的入口.<br><a id="more"></a></p>
<ol>
<li><p>SqlSessionFactory生命周期<br>SqlSessionFactory生命周期为贯穿整个应用程序,一般保持生命周期都使用同一个实例,所以SqlSessionFactory应该保持全局静态变量或使用单利模式来使用它。如果有多个数据源的时候,需要创建不同的SqlSessionFactory。</p>
</li>
<li><p>构建SqlSessionFactory<br>在mybatis中构建SqlSessionFactory有两种方式,一种是根据xml配置文件方式,另一种是也手动编写Java代码方式,手动构建比较繁琐,也不好维护,推荐使用xml配置方式,下面是详细代码。</p>
</li>
</ol>
<figure class="highlight Java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div></pre></td><td class="code"><pre><div class="line"><span class="javadoc">/**</span></div><div class="line"> * SqlSessionFactory生命周期为贯穿整个应用程序,一般保持生命周期都使用同一个实例,所以SqlSessionFactory应该保持全局静态变量或使用单利模式来使用它</div><div class="line"> * </div><div class="line"> *<span class="javadoctag"> @author</span> dreajay</div><div class="line"> * </div><div class="line"> */</div><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SqlSessionFactoryManager</span> </span>{</div><div class="line"> <span class="comment">// SqlSessionFactory一个实例对应一个数据库配置</span></div><div class="line"> <span class="keyword">public</span> SqlSessionFactory sqlSessionFactory;</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="keyword">static</span> SqlSessionFactoryManager INSTANCE = <span class="keyword">new</span> SqlSessionFactoryManager();</div><div class="line"></div><div class="line"> <span class="keyword">private</span> <span class="title">SqlSessionFactoryManager</span>() {</div><div class="line"> sqlSessionFactory = buildSqlSessionFactoryFromXML(<span class="string">"SqlMapConfig.xml"</span>);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="keyword">static</span> SqlSessionFactory <span class="title">getSqlSessionFactory</span>() {</div><div class="line"> <span class="keyword">return</span> INSTANCE.sqlSessionFactory;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="javadoc">/**</span></div><div class="line"> * 根据配置文件创建SqlSessionFactory</div><div class="line"> * </div><div class="line"> *<span class="javadoctag"> @param</span> SqlMapConfigFile</div><div class="line"> * SqlMapConfig配置文件,文件应该放在当前的classpath中</div><div class="line"> *<span class="javadoctag"> @return</span> SqlSessionFactory</div><div class="line"> */</div><div class="line"> <span class="keyword">private</span> SqlSessionFactory <span class="title">buildSqlSessionFactoryFromXML</span>(String SqlMapConfigFile) {</div><div class="line"> Reader reader = <span class="keyword">null</span>;</div><div class="line"> <span class="keyword">try</span> {</div><div class="line"> reader = Resources.getResourceAsReader(SqlMapConfigFile);</div><div class="line"> <span class="comment">// SqlSessionFactoryBuilder创建完SqlSessionFactory就不需要了,生命周期在方法内,不需要保存本地变量</span></div><div class="line"> <span class="keyword">return</span> <span class="keyword">new</span> SqlSessionFactoryBuilder().build(reader);</div><div class="line"> } <span class="keyword">catch</span> (IOException e) {</div><div class="line"> e.printStackTrace();</div><div class="line"> Log4jUtil.error(SqlSessionFactoryManager.class, <span class="string">"创建SqlSessionFactory出错"</span>, e);</div><div class="line"> <span class="keyword">return</span> <span class="keyword">null</span>;</div><div class="line"> } <span class="keyword">finally</span> {</div><div class="line"> <span class="keyword">if</span> (reader != <span class="keyword">null</span>) {</div><div class="line"> <span class="keyword">try</span> {</div><div class="line"> reader.close();</div><div class="line"> reader = <span class="keyword">null</span>;</div><div class="line"> } <span class="keyword">catch</span> (IOException e) {</div><div class="line"> }</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="javadoc">/**</span></div><div class="line"> * 手动创建SqlSessionFactory</div><div class="line"> * </div><div class="line"> *<span class="javadoctag"> @return</span> SqlSessionFactory</div><div class="line"> */</div><div class="line"> <span class="keyword">private</span> SqlSessionFactory <span class="title">buildSqlSessionFactoryFromJava</span>() {</div><div class="line"> DataSource dataSource = <span class="keyword">null</span>;<span class="comment">// 数据库连接</span></div><div class="line"> <span class="comment">// dataSource = BlogDataSourceFactory.getBlogDataSource();</span></div><div class="line"> TransactionFactory transactionFactory = <span class="keyword">new</span> JdbcTransactionFactory();</div><div class="line"> Environment environment = <span class="keyword">new</span> Environment(<span class="string">"development"</span>, transactionFactory, dataSource);</div><div class="line"> Configuration configuration = <span class="keyword">new</span> Configuration(environment);</div><div class="line"> configuration.addMapper(UserMapper.class);</div><div class="line"> <span class="keyword">return</span> <span class="keyword">new</span> SqlSessionFactoryBuilder().build(configuration);</div><div class="line"> }</div><div class="line"></div><div class="line">}</div></pre></td></tr></table></figure>
]]></content>
<breadCrumb title="java" url="http://dreajay.github.io/categories/java/"/>
<breadCrumb title="java-framework" url="http://dreajay.github.io/categories/java/java-framework/"/>
</display>
</data>
</url>
<url>
<loc>http://dreajay.github.io/2014/11/19/Design-Pattern-Singleton/</loc>
<lastmod>2015-10-28T16:23:32.000Z</lastmod>
<data>
<display>
<title>设计模式之单例模式</title>
<pubTime>2014-11-18T17:49:49.000Z</pubTime>
<tag>设计模式 </tag>
<tag>单例模式 </tag>
<tag>Singleton模式 </tag>
<content><![CDATA[<h2 id="定义">定义</h2>
<p>Singleton是指在应用程序中只被实例化一次的类。</p>
<a id="more"></a>
<h2 id="创建单例模式的方法">创建单例模式的方法</h2>
<h3 id="第一种">第一种</h3>
<p>恶汉式,程序加载自己时就会创建静态Singleton实例。</p>
<figure class="highlight Java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//通过静态final变量获取Singleton</span></div><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Singleton</span> </span>{</div><div class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> Singleton singleton = <span class="keyword">new</span> Singleton();</div><div class="line"> <span class="comment">//私有构造器</span></div><div class="line"> <span class="keyword">private</span> <span class="title">Singleton</span>() { </div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<figure class="highlight Java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//通过静态方法获取实例</span></div><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Singleton</span> </span>{</div><div class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> Singleton singleton = <span class="keyword">new</span> Singleton();</div><div class="line"> <span class="comment">//私有构造器</span></div><div class="line"> <span class="keyword">private</span> <span class="title">Singleton</span>() { </div><div class="line"> }</div><div class="line"> <span class="keyword">public</span> <span class="keyword">static</span> Singleton <span class="title">getInstance</span>() {</div><div class="line"> <span class="keyword">return</span> singleton;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="第二种">第二种</h3>
<p>懒汉式,当需要使用的时候再进行创建,使用synchronized锁保证只能生成一个实例,否则多线程下可能会产生多个实例,但synchronized会导致性能下降,虽然现在的JDK版本做了很多优化。</p>
<figure class="highlight Java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Singleton</span> </span>{</div><div class="line"> <span class="keyword">private</span> <span class="keyword">static</span> Singleton singleton = <span class="keyword">null</span>;</div><div class="line"> <span class="comment">//私有构造器</span></div><div class="line"> <span class="keyword">private</span> <span class="title">Singleton</span>() { </div><div class="line"> }</div><div class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">synchronized</span> Singleton <span class="title">getInstance</span>() {</div><div class="line"> <span class="keyword">if</span>(singleton == <span class="keyword">null</span>) {</div><div class="line"> sinleton = <span class="keyword">new</span> Singleton();</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> sinleton;</div><div class="line"> } </div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="第三种">第三种</h3>
<p>懒汉式,下面这种方法是上面方法的改进,但多线程下可能造成创建多个实例问题,假如第一次在创建对象的时候,另外一个线程已经进入if(singleton == null) 中等待synchronized,最后执行完就会产生两个Singleton,导致单例失效。</p>
<figure class="highlight Java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Singleton</span> </span>{</div><div class="line"> <span class="keyword">private</span> <span class="keyword">static</span> Singleton singleton = <span class="keyword">null</span>;</div><div class="line"> <span class="comment">//私有构造器</span></div><div class="line"> <span class="keyword">private</span> <span class="title">Singleton</span>() { </div><div class="line"> }</div><div class="line"> <span class="keyword">public</span> <span class="keyword">static</span> Singleton <span class="title">getInstance</span>() {</div><div class="line"> <span class="keyword">if</span>(singleton == <span class="keyword">null</span>) {</div><div class="line"> <span class="keyword">synchronized</span>(Singleton.class) {</div><div class="line"> sinleton = <span class="keyword">new</span> Singleton();</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> sinleton;</div><div class="line"> } </div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="第四种">第四种</h3>
<p>双重检查,这个方法避免了第三种创建多个实例对象的问题,但这种方式在老版本的JDK并不能保证正常工作,详情请参考<a href="http://ifeve.com/jmm-faq-dcl/" target="_blank" rel="external">http://ifeve.com/jmm-faq-dcl/</a>。</p>
<figure class="highlight Java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Singleton</span> </span>{</div><div class="line"> <span class="keyword">private</span> <span class="keyword">static</span> Singleton singleton = <span class="keyword">null</span>;</div><div class="line"> <span class="comment">//私有构造器</span></div><div class="line"> <span class="keyword">private</span> <span class="title">Singleton</span>() { </div><div class="line"> }</div><div class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">synchronized</span> Singleton <span class="title">getInstance</span>() {</div><div class="line"> <span class="keyword">if</span>(singleton == <span class="keyword">null</span>) {</div><div class="line"> <span class="keyword">synchronized</span>(Singleton.class){</div><div class="line"> <span class="keyword">if</span>(singleton == <span class="keyword">null</span>) {</div><div class="line"> sinleton = <span class="keyword">new</span> Singleton();</div><div class="line"> }</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> sinleton;</div><div class="line"> } </div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="第五种">第五种</h3>
<p>改良的懒汉模式,通过私有静态final内部类间接构造Singleton。</p>
<figure class="highlight Java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Singleton</span> </span>{ </div><div class="line"> <span class="keyword">private</span> <span class="title">Singleton</span>() {} </div><div class="line"> <span class="comment">//私有静态</span></div><div class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">Holder</span> </span>{ </div><div class="line"> <span class="comment">//static final Singleton</span></div><div class="line"> <span class="keyword">static</span> <span class="keyword">final</span> Singleton instance = <span class="keyword">new</span> Singleton(); </div><div class="line"> } </div><div class="line"> </div><div class="line"> <span class="keyword">public</span> <span class="keyword">static</span> Singleton <span class="title">getInstance</span>() { </div><div class="line"> <span class="keyword">return</span> Holder.instance; </div><div class="line"> } </div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="第六种">第六种</h3>
<p>枚举实现单例模式,在《effective java》一书中有介绍,这是实现单例的最佳方式。之前第一种方法第一个例子通过静态final变量获取Singleton,通过反射调用私有构造器可以创建另一个实例,会导致破坏Singleton,防御方法为是在构造器中进行判断第二次创建时抛出异常;另外一方面为了给Singleton序列化(Serializable),仅仅在声明中加上“implements Serializable ”,是不够的,为了保证Singleton,必须声明所有实例域都是瞬时的(transient),并提供一个readResolve方法,否则每次反序列化时都会创建一个新的实例,使用枚举方法简洁并无偿的提供了序列化机制,绝对防止多次实例化,即使在面对复杂的序列化或者反射攻击的时候。</p>
<figure class="highlight Java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="keyword">enum</span> Singleton {</div><div class="line"> INSTANCE {</div><div class="line"> <span class="comment">// init . . .</span></div><div class="line"> };</div><div class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">someMethod</span>() {</div><div class="line"> <span class="comment">// do . . .</span></div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<h2 id="总结">总结</h2>
<p>枚举创建单例这么多好处,以后应该多用枚举方式来实现单例模式;当Singleton不需要序列化,或一般不会被反射时,我一般使用第一种恶汉式来创建,简单,也不需要考虑多线程,虽然一开始就需要消耗内存去创建,但现在的机器是不用太担心的,懒汉式会让单例变得更加复杂。<br><strong><em>注意:</em></strong><br>在分布式式中,程序可能会跨服务器、跨JVM,包含多个类装载器,Singleton可能会被不同的类装载器装载,这样就会导致Singleton失效。</p>
]]></content>
<breadCrumb title="设计模式" url="http://dreajay.github.io/categories/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/"/>
</display>
</data>
</url>
<url>
<loc>http://dreajay.github.io/2015/01/19/webservice-develop/</loc>
<lastmod>2015-01-19T15:10:01.000Z</lastmod>
<data>
<display>
<title>webservice 开发笔记</title>
<pubTime>2015-01-19T14:09:48.000Z</pubTime>
<tag>webservice </tag>
<tag>cxf </tag>
<content><![CDATA[<p>把之前学习webservice的知识笔记整理一下,学习webservice先要了解webservice的产生理念,或者叫目标,webservice是为了解决异构平台,夸操作系统、夸语言、夸终端之间的交互,比如一个使用.net开发的微软系统平台要和一个使用Java语言开发的平台交互,就可以采用webservcie。 </p>
<p>webservice开发框架有很多,比较出名的有axis2和cxf,axis2是由axis1发展而来,cxf是由XFire和Celtix发展而来,它们都是Apache旗下的开源框架,为什么Apache要搞两个不同的框架呢,其实axis2支持多种语言,比如c++,所以包含内容会比较多,而cxf主要是针对java平台的,相对axis来说,体积小了很多,其实Java平台本身也提供了webservice的开发JAX-RS,但cxf是能简化以及加强Java本身的webservice开发,并不是替代,cxf完全实现了JAX-RS 2.0标准。具体对比可以参考这篇文章: <a href="http://www.cnblogs.com/growup/archive/2011/03/06/1972464.html" target="_blank" rel="external">Axis,axis2,Xfire以及cxf对比</a>。</p>
<p>在学习使用cxf开发webservice的时候,最好先了解一下webservice由哪几部分组成,其实最主要的就是WSDL、SOAP和UUDI,知道了这三个是什么东西,有什么作用之后,开发webservice就相对来说挺简单的了。<br>WSDL称为webservcie的描述语言,英文为Web Service Description Language。这句话太抽象了,其实你只需要知道这个文件就是描述webservcie提供了哪些服务,这些服务是由什么接口提供的,这些接口包含了哪些方法,方法的输入和输出参数是什么,这样想一下就很容易理解了。参考教程:<a href="http://www.w3school.com.cn/wsdl/" target="_blank" rel="external">http://www.w3school.com.cn/wsdl/</a></p>
<p>SOAP称为简单对象访问协议,英文为Simple Object Access Protocol,它是一种协议,我们有接触过TCP、HTTP等协议,相对比较熟悉,这个也类似,只不过这个协议主要是由XML来组织,XML包含了Envelope元素,Envelope包含了HEAD、BODY元素,BODY里面具体定义了传输方法和参数,参考教程:<a href="http://www.w3school.com.cn/soap/index.asp。" target="_blank" rel="external">http://www.w3school.com.cn/soap/index.asp。</a></p>
<p>UUDI称为统一描述、发现和集成协议,英文为Universal Description Discovery and Integration。有了服务就需要别人找得到,否则他们就无法使用,UUDI就是干这个的,让你可以查找到有哪些webservcie服务,参考教程:<a href="http://www.w3school.com.cn/wsdl/wsdl_uddi.asp。" target="_blank" rel="external">http://www.w3school.com.cn/wsdl/wsdl_uddi.asp。</a></p>
<p>了解了webservice三要素后,开发起来就相对简单。使用Java本身自带的服务开发也很简单,这里不再描述,下面记录一下cxf开发webservice的资料,学习CXF的最好教程就是官方文档了,官方文档例子实在很齐全,没必要再看其他教程了,教程为英文,如果不太懂,可以直接看例子。</p>
<p>下载:<br><a href="http://cxf.apache.org/download.html" target="_blank" rel="external">http://cxf.apache.org/download.html</a><br>apache-cxf-2.7.14.tar.gz<br>解压后包含:<br>bin:很多实用工具:wsdl2java、java2wsdl….<br>docs:java文档<br>lib:包含所有依赖包<br>modules:包含各种模块<br>samples:包含很多例子可以参考,例子描述:</p>
<p>具体的使用都能在CXF User’s Guide找到:<br><a href="http://cxf.apache.org/docs/index.html" target="_blank" rel="external">http://cxf.apache.org/docs/index.html</a></p>
<p>服务端开发:<br><a href="http://cxf.apache.org/docs/developing-a-service.html" target="_blank" rel="external">http://cxf.apache.org/docs/developing-a-service.html</a></p>
<p>客户端开发:<br><a href="http://cxf.apache.org/docs/how-do-i-develop-a-client.html" target="_blank" rel="external">http://cxf.apache.org/docs/how-do-i-develop-a-client.html</a></p>
<p>CXF包含的例子<br>Apache CXF Example Projects:<br><a href="http://cxf.apache.org/docs/sample-projects.html" target="_blank" rel="external">http://cxf.apache.org/docs/sample-projects.html</a><br><a href="http://svn.apache.org/viewvc/cxf/trunk/distribution/src/main/release/samples/" target="_blank" rel="external">http://svn.apache.org/viewvc/cxf/trunk/distribution/src/main/release/samples/</a><br>JAX-WS Examples<br>WSDL-First Examples<br>JAX-REST Examples<br>Javascript Examples<br>WS-* Examples<br>Data Bindings Examples<br>CXF and JMS Examples<br>JBI Examples<br>JCA Examples<br>Miscellaneous Examples<br>CORBA Examples</p>
<p>CXF与spring集成<br><a href="http://cxf.apache.org/docs/writing-a-service-with-spring.html" target="_blank" rel="external">http://cxf.apache.org/docs/writing-a-service-with-spring.html</a></p>
<p>CXF开发RESTful services<br>参考例子JAX-REST Examples<br><a href="http://cxf.apache.org/docs/restful-services.html" target="_blank" rel="external">http://cxf.apache.org/docs/restful-services.html</a></p>
<p>CXF Maven:<br>CXF开发推荐使用maven来开发,参考文章:<a href="http://cxf.apache.org/docs/using-cxf-with-maven.html" target="_blank" rel="external">http://cxf.apache.org/docs/using-cxf-with-maven.html</a><br>参考文章:使用 Apache Maven 和 CXF 构建 RESTful web services<br><a href="http://www.ibm.com/developerworks/cn/opensource/os-restfulwebservices/index.html" target="_blank" rel="external">http://www.ibm.com/developerworks/cn/opensource/os-restfulwebservices/index.html</a></p>
<p>pom依赖:</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="title">properties</span>></span></div><div class="line"> <span class="tag"><<span class="title">cxf.version</span>></span>2.7.14<span class="tag"></<span class="title">cxf.version</span>></span></div><div class="line"><span class="tag"></<span class="title">properties</span>></span></div><div class="line"><span class="tag"><<span class="title">dependencies</span>></span></div><div class="line"> <span class="tag"><<span class="title">dependency</span>></span></div><div class="line"> <span class="tag"><<span class="title">groupId</span>></span>org.apache.cxf<span class="tag"></<span class="title">groupId</span>></span></div><div class="line"> <span class="tag"><<span class="title">artifactId</span>></span>cxf-rt-frontend-jaxws<span class="tag"></<span class="title">artifactId</span>></span></div><div class="line"> <span class="tag"><<span class="title">version</span>></span>${cxf.version}<span class="tag"></<span class="title">version</span>></span></div><div class="line"> <span class="tag"></<span class="title">dependency</span>></span></div><div class="line"> <span class="tag"><<span class="title">dependency</span>></span></div><div class="line"> <span class="tag"><<span class="title">groupId</span>></span>org.apache.cxf<span class="tag"></<span class="title">groupId</span>></span></div><div class="line"> <span class="tag"><<span class="title">artifactId</span>></span>cxf-rt-transports-http<span class="tag"></<span class="title">artifactId</span>></span></div><div class="line"> <span class="tag"><<span class="title">version</span>></span>${cxf.version}<span class="tag"></<span class="title">version</span>></span></div><div class="line"> <span class="tag"></<span class="title">dependency</span>></span></div><div class="line"> <span class="comment"><!-- Jetty is needed if you're using the CXFServlet --></span></div><div class="line"> <span class="tag"><<span class="title">dependency</span>></span></div><div class="line"> <span class="tag"><<span class="title">groupId</span>></span>org.apache.cxf<span class="tag"></<span class="title">groupId</span>></span></div><div class="line"> <span class="tag"><<span class="title">artifactId</span>></span>cxf-rt-transports-http-jetty<span class="tag"></<span class="title">artifactId</span>></span></div><div class="line"> <span class="tag"><<span class="title">version</span>></span>${cxf.version}<span class="tag"></<span class="title">version</span>></span></div><div class="line"> <span class="tag"></<span class="title">dependency</span>></span></div><div class="line"><span class="tag"></<span class="title">dependencies</span>></span></div></pre></td></tr></table></figure>
<p>CXF3和CXF2<br>CXF3完全实现了JAX-RS 2.0,cxf只支持部分,还要一些其他的特性,完整说明:<br>CXF3:<a href="http://cxf.apache.org/docs/30-migration-guide.html" target="_blank" rel="external">http://cxf.apache.org/docs/30-migration-guide.html</a><br>CXF2:<a href="http://cxf.apache.org/docs/27-migration-guide.html" target="_blank" rel="external">http://cxf.apache.org/docs/27-migration-guide.html</a></p>
]]></content>
<breadCrumb title="webservice" url="http://dreajay.github.io/categories/webservice/"/>
</display>
</data>
</url>
<url>
<loc>http://dreajay.github.io/2014/12/17/rolling-table-data/</loc>
<lastmod>2014-12-17T09:55:01.000Z</lastmod>
<data>
<display>
<title>表格数据动态滚动</title>
<pubTime>2014-12-17T09:36:25.000Z</pubTime>
<tag>jquery </tag>
<tag>html </tag>
<content><![CDATA[<p>最近项目中需要实现一个功能使表格的数据滚动,网上看了一些代码都比较复杂而且不是我想要的效果,这里自己实现的代码很简单,这里用到了jquery对表格的增删操作。<br>实现思路:表格的数据是从后台获取动态加载的,如果数据量大于表格预先设置的行数,则之前加载的数据的就删除,添加新获取的数据,如果每次都有新数据到来,而且不间断(例子中使用定时器假设数据不间断),就能达到数据在表格中滚动的效果,具体看代码:</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="title">html</span>></span></div><div class="line"><span class="tag"><<span class="title">head</span>></span></div><div class="line"><span class="tag"><<span class="title">meta</span> <span class="attribute">http-equiv</span>=<span class="value">"content-type"</span> <span class="attribute">content</span>=<span class="value">"text/html; charset=UTF-8"</span>></span></div><div class="line"><span class="tag"><<span class="title">style</span>></span><span class="css"></span></div><div class="line"><span class="tag">tr</span> <span class="rules">{</span></div><div class="line"> <span class="rule"><span class="attribute">line-height</span>:<span class="value"> <span class="number">24px</span></span></span>;</div><div class="line"> <span class="rule"><span class="attribute">height</span>:<span class="value"> <span class="number">24px</span></span></span>;</div><div class="line"><span class="rule">}</span></div><div class="line"><span class="tag">tr</span> <span class="tag">th</span> <span class="rules">{</span></div><div class="line"> <span class="rule"><span class="attribute">width</span>:<span class="value"> <span class="number">200px</span></span></span></div><div class="line">}</div><div class="line"><span class="tag">tr</span> <span class="tag">td</span> <span class="rules">{</span></div><div class="line"> <span class="rule"><span class="attribute">text-align</span>:<span class="value"> center</span></span>;</div><div class="line"><span class="rule">}</span></div><div class="line"><span class="tag"></<span class="title">style</span>></span></div><div class="line"><span class="tag"><<span class="title">script</span> <span class="attribute">src</span>=<span class="value">"../js/jquery-2.1.1.min.js"</span>></span><span class="javascript"></span><span class="tag"></<span class="title">script</span>></span></div><div class="line"><span class="tag"></<span class="title">head</span>></span></div><div class="line"><span class="tag"><<span class="title">body</span>></span></div><div class="line"> <span class="tag"><<span class="title">input</span> <span class="attribute">type</span>=<span class="value">"button"</span> <span class="attribute">onclick</span>=<span class="value">"startRefresh();"</span> <span class="attribute">value</span>=<span class="value">"开始刷新"</span>></span></div><div class="line"> <span class="tag"><<span class="title">input</span> <span class="attribute">type</span>=<span class="value">"button"</span> <span class="attribute">onclick</span>=<span class="value">"stopRefresh();"</span> <span class="attribute">value</span>=<span class="value">"停止刷新"</span>></span></div><div class="line"> <span class="tag"><<span class="title">br</span>></span></div><div class="line"> <span class="tag"><<span class="title">br</span>></span></div><div class="line"> <span class="tag"><<span class="title">table</span> <span class="attribute">id</span>=<span class="value">"table1"</span> <span class="attribute">bgcolor</span>=<span class="value">"#cccccc"</span> <span class="attribute">border</span>=<span class="value">"1"</span> <span class="attribute">cellpadding</span>=<span class="value">"0"</span> <span class="attribute">cellspacing</span>=<span class="value">"0"</span> <span class="attribute">width</span>=<span class="value">"400px"</span>></span></div><div class="line"> <span class="tag"><<span class="title">thead</span>></span></div><div class="line"> <span class="tag"><<span class="title">tr</span>></span></div><div class="line"> <span class="tag"><<span class="title">th</span>></span>序号<span class="tag"></<span class="title">th</span>></span></div><div class="line"> <span class="tag"><<span class="title">th</span>></span>名称<span class="tag"></<span class="title">th</span>></span></div><div class="line"> <span class="tag"></<span class="title">tr</span>></span></div><div class="line"> <span class="tag"></<span class="title">thead</span>></span></div><div class="line"> <span class="tag"><<span class="title">tbody</span>></span></div><div class="line"> <span class="tag"></<span class="title">tbody</span>></span></div><div class="line"> <span class="tag"></<span class="title">table</span>></span></div><div class="line"> <span class="tag"><<span class="title">script</span> <span class="attribute">type</span>=<span class="value">"text/javascript"</span>></span><span class="javascript"></span></div><div class="line"> <span class="keyword">var</span> tableRowNum = <span class="number">10</span>;</div><div class="line"> <span class="comment">//刷新任务</span></div><div class="line"> <span class="keyword">var</span> refreshTask;</div><div class="line"> <span class="comment">//刷新时间,单位毫秒</span></div><div class="line"> <span class="keyword">var</span> refreshTime = <span class="number">1000</span>;</div><div class="line"> <span class="comment">//刷新开始标志</span></div><div class="line"> <span class="keyword">var</span> refreshStart = <span class="literal">false</span>;</div><div class="line"> <span class="comment">//开始刷新</span></div><div class="line"> <span class="function"><span class="keyword">function</span> <span class="title">startRefresh</span><span class="params">()</span> </span>{</div><div class="line"> <span class="comment">//没有开始刷新,才调用刷新定时器</span></div><div class="line"> <span class="keyword">if</span> (!refreshStart) {</div><div class="line"> refreshTask = setInterval(<span class="string">"addData()"</span>, refreshTime);</div><div class="line"> refreshStart = <span class="literal">true</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="comment">//停止刷新</span></div><div class="line"> <span class="function"><span class="keyword">function</span> <span class="title">stopRefresh</span><span class="params">()</span> </span>{</div><div class="line"> <span class="comment">//如果刷新开始了,才进行停止</span></div><div class="line"> <span class="keyword">if</span> (refreshStart) {</div><div class="line"> clearInterval(refreshTask);</div><div class="line"> refreshStart = <span class="literal">false</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="comment">//绑定鼠标动作,鼠标进入停止刷新,鼠标移出开始刷新,当想停止刷新看具体行数据的时候鼠标进入即可 </span></div><div class="line"> $(<span class="string">"#table1"</span>).bind({</div><div class="line"> mouseover : <span class="function"><span class="keyword">function</span><span class="params">()</span> </span>{</div><div class="line"> stopRefresh();</div><div class="line"> },</div><div class="line"> mouseout : <span class="function"><span class="keyword">function</span><span class="params">()</span> </span>{</div><div class="line"> startRefresh();</div><div class="line"> }</div><div class="line"> });</div><div class="line"> <span class="keyword">var</span> i = <span class="number">1</span>;</div><div class="line"> <span class="comment">//添加表格数据</span></div><div class="line"> <span class="function"><span class="keyword">function</span> <span class="title">addData</span><span class="params">()</span> </span>{</div><div class="line"> <span class="keyword">var</span> size = $(<span class="string">'#table1 tbody tr'</span>).size();</div><div class="line"> <span class="built_in">console</span>.info(<span class="string">"size:"</span> + size);</div><div class="line"> <span class="keyword">if</span> (size >= tableRowNum) {</div><div class="line"> delData();</div><div class="line"> }</div><div class="line"> $(<span class="string">'<tr><td>'</span> + i + <span class="string">'</td><td>插入'</span> + i + <span class="string">'</td></tr>'</span>).appendTo(</div><div class="line"> $(<span class="string">'#table1 tbody'</span>));</div><div class="line"> i++;</div><div class="line"> }</div><div class="line"> <span class="comment">//删除表格数据</span></div><div class="line"> <span class="function"><span class="keyword">function</span> <span class="title">delData</span><span class="params">()</span> </span>{</div><div class="line"> $(<span class="string">'#table1 tbody tr:first'</span>).remove();</div><div class="line"> }</div><div class="line"> <span class="comment">//开始刷新</span></div><div class="line"> startRefresh();</div><div class="line"> <span class="tag"></<span class="title">script</span>></span></div><div class="line"><span class="tag"></<span class="title">body</span>></span></div><div class="line"><span class="tag"></<span class="title">html</span>></span></div></pre></td></tr></table></figure>
<p>jquery操作表格可以参考:<a href="http://www.jb51.net/article/48943.htm" target="_blank" rel="external">jQuery操作表格(table)的常用方法、技巧汇总</a></p>
]]></content>
<breadCrumb title="web前端" url="http://dreajay.github.io/categories/web%E5%89%8D%E7%AB%AF/"/>
</display>
</data>
</url>
<url>
<loc>http://dreajay.github.io/2014/12/15/install-activemq-in-mac/</loc>
<lastmod>2014-12-15T13:14:56.000Z</lastmod>
<data>
<display>
<title>MAC系统安装acitivemq</title>
<pubTime>2014-12-15T12:47:49.000Z</pubTime>
<tag>activemq </tag>
<tag>jms </tag>
<tag>mac </tag>
<content><![CDATA[<h1 id="安装">安装</h1>
<p>官方推荐使用brew安装,前提是Mac要先安装brew,也可以手动下载压缩包解压安装,如果已经安装了brew很简单,只需要下面一句话,安装位置:/usr/local/Cellar/activemq/5.10.0</p>
<pre><code><span class="variable">$ </span>brew install apache-activemq
<span class="variable">$ </span>cd /usr/local/<span class="constant">Cellar</span>/activemq/<span class="number">5.10</span>.<span class="number">0</span>
</code></pre><p>查看信息: </p>
<pre><code><span class="variable">$ </span>bin/activemq
</code></pre><p>配置activemq运行环境,默认路径/etc/default/activemq 或 /Users/user/.activemqrc </p>
<pre><code>activemq setup <span class="regexp">/Users/</span>apple<span class="regexp">/.activemqrc</span>
</code></pre><p>activemq官方建议设置访问权限,这一步是可选的:</p>
<pre><code><span class="variable">$chown</span> <span class="string">'apple'</span><span class="symbol">:nogroup</span> <span class="string">'/Users/apple/.activemqrc'</span>
<span class="variable">$chmod</span> <span class="number">600</span> <span class="string">'/Users/apple/.activemqrc'</span>
</code></pre><h1 id="启动">启动</h1>
<p>前台启动: </p>
<pre><code><span class="variable">$ </span>activemq console
</code></pre><p>后台启动: </p>
<pre><code><span class="variable">$ </span>activemq start
</code></pre><p>指定运行日志输出到指定文件启动:</p>
<pre><code><span class="input"><span class="prompt">$ activemq start ></span> /tmp/smlog <span class="number">2</span>>&<span class="number">1</span> & </span>
</code></pre><p>查看是否启动成功,查看端口61616是否运行成功:</p>
<pre><code>$ netstat -<span class="keyword">an</span>|<span class="keyword">grep</span> <span class="number">61616</span>
</code></pre><p>或者浏览器访问activemq管理控制台:<a href="http://localhost:8161/admin/" target="_blank" rel="external">http://localhost:8161/admin/</a>,用户名和密码为admin:admin</p>
<h1 id="停止">停止</h1>
<pre><code>$ activemq <span class="keyword">stop</span>
</code></pre><p>或者:</p>
<pre><code>$ <span class="keyword">ps</span> -ef|<span class="keyword">grep</span> activemq
$ kill -<span class="number">9</span> pid
</code></pre><h1 id="其他资料">其他资料</h1>
<p>activemq使用文档:<br><a href="http://activemq.apache.org/using-activemq-5.html" target="_blank" rel="external">http://activemq.apache.org/using-activemq-5.html</a></p>
<p>activemq jndi支持:<br><a href="http://activemq.apache.org/jndi-support.html" target="_blank" rel="external">http://activemq.apache.org/jndi-support.html</a></p>
<p>activemq spring支持:<br><a href="http://activemq.apache.org/spring-support.html" target="_blank" rel="external">http://activemq.apache.org/spring-support.html</a></p>
<p>使用spring JMS:<br><a href="http://docs.spring.io/spring/docs/2.5.x/reference/jms.html#jms-mdp" target="_blank" rel="external">http://docs.spring.io/spring/docs/2.5.x/reference/jms.html#jms-mdp</a></p>
]]></content>
<breadCrumb title="java" url="http://dreajay.github.io/categories/java/"/>
<breadCrumb title="java-framework" url="http://dreajay.github.io/categories/java/java-framework/"/>
</display>
</data>
</url>
<url>
<loc>http://dreajay.github.io/2014/12/08/build-RESTful-use-springmvc/</loc>
<lastmod>2014-12-15T11:24:23.000Z</lastmod>
<data>
<display>
<title>使用springmvc创建RESTful风格软件架构</title>
<pubTime>2014-12-08T05:38:32.000Z</pubTime>
<tag>RESTful </tag>
<tag>javaee </tag>
<tag>spring </tag>
<tag>springmvc </tag>
<tag>ajax </tag>
<tag>json </tag>
<content><![CDATA[<p>RESTful是一个现在非常流行的词汇,RESTful是一种软件架构风格,提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。RESTful中的REST(英文:Representational State Transfer,简称REST)描述了一个架构样式的网络系统,比如 web应用程序。它首次出现在 2000 年 Roy Fielding 的博士论文中,他是 HTTP 规范的主要编写者之一。关于RESTful可以参考很多文章,本文不过多介绍。</p>
<h1 id="REST">REST</h1>
<h2 id="原则条件">原则条件</h2>
<p>REST 指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是 RESTful。<br>Web 应用程序最重要的 REST 原则是,客户端和服务器之间的交互在请求之间是无状态的。从客户端到服务器的每个请求都必须包含理解请求所必需的信息。如果服务器在请求之间的任何时间点重启,客户端不会得到通知。此外,无状态请求可以由任何可用服务器回答,这十分适合云计算之类的环境。客户端可以缓存数据以改进性能。</p>
<p>在服务器端,应用程序状态和功能可以分为各种资源。资源是一个有趣的概念实体,它向客户端公开。资源的例子有:应用程序对象、数据库记录、算法等等。每个资源都使用 URI (Universal Resource Identifier) 得到一个唯一的地址。所有资源都共享统一的接口,以便在客户端和服务器之间传输状态。使用的是标准的 HTTP 方法,比如 GET、PUT、POST 和 DELETE。Hypermedia 是应用程序状态的引擎,资源表示通过超链接互联。</p>
<h2 id="分层系统">分层系统</h2>
<p>另一个重要的 REST 原则是分层系统,这表示组件无法了解它与之交互的中间层以外的组件。通过将系统知识限制在单个层,可以限制整个系统的复杂性,促进了底层的独立性。<br>当 REST 架构的约束条件作为一个整体应用时,将生成一个可以扩展到大量客户端的应用程序。它还降低了客户端和服务器之间的交互延迟。统一界面简化了整个系统架构,改进了子系统之间交互的可见性。REST 简化了客户端和服务器的实现。</p>
<p>关于RESTful的理解可以参考阮一峰的文章:《<a href="http://www.ruanyifeng.com/blog/2011/09/restful.html" target="_blank" rel="external">理解RESTful架构</a>》。</p>
<p>关于REST中状态的说明可以参考这篇文章《<a href="http://developer.51cto.com/art/200906/129424.htm" target="_blank" rel="external">对于REST中无状态(stateless)的一点认识</a>》,文章中提到应用状态(Application State)和资源状态(Resource State)的不同,应用状态指的是与某一特定请求相关的状态信息,而资源状态则反映了某一存储在服务器端资源在某一时刻的特定状态,该状态不会因为用户请求而改变,任何用户在同一时刻对该资源的请求都会获得这一状态的表现(Representation)。应用状态的典型例子就是在登录的时候需要提供身份验证,这是和登录请求相关的状态信息,而资源状态的典型例子就是会话状态Session ID,这个是服务端负责保存的,其实有状态和无状态与请求本身没有多大关联,重要的是状态信息是由请求方还是响应方负责保存,最后归集为应用状态为REST风格,而资源状态属于UNREST风格.</p>
<h1 id="springmvc实现RESTful">springmvc实现RESTful</h1>
<p>使用springmvc很容易实现RESTful风格架构,通过给注解@RequestMapping指定method参数就可以完成,method参数的值包括RequestMethod.GET、RequestMethod.POST、RequestMethod.PUT、RequestMethod.DELETE,分别对应HTTP的标准方法GET、POST、PUT、DELETE。这四个方法就对应资源的增删改查操作,在本案例中对应的方法如下:</p>
<pre><code>HTTP GET /<span class="literal">user</span>/<span class="number">1</span> ——》 SpringMVC get 获得ID为<span class="number">1</span>的用户
HTTP PATCH /<span class="literal">user</span> ——》 SpringMVC getList 获得用户列表
HTTP POST /<span class="literal">user</span> ——》 SpringMVC add 添加用户
HTTP PUT /<span class="literal">user</span> ——》 SpringMVC update 更新用户
HTTP DELETE /<span class="literal">user</span>/<span class="number">1</span> ——》 SpringMVC delete 删除用户为<span class="number">1</span>的用户
</code></pre><h2 id="后端">后端</h2>
<p>后端使用springmvc的实现,Controller要注意的两个地方就是,在POST、PUT提交的时候请求参数使用注解@RequestBody指定请求参数为<code>json字符串</code>类型,非json对象,所以前端上送的数据需要格式化为json字符串,返回值使用注解@ResponseBody指定返回类型为json。具体代码:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div><div class="line">94</div><div class="line">95</div><div class="line">96</div><div class="line">97</div></pre></td><td class="code"><pre><div class="line"><span class="annotation">@Controller</span></div><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RESTfulController</span> <span class="keyword">extends</span> <span class="title">Context</span> </span>{</div><div class="line"> <span class="javadoc">/**</span></div><div class="line"> * 查询单个用户</div><div class="line"> * </div><div class="line"> *<span class="javadoctag"> @param</span> userId</div><div class="line"> *<span class="javadoctag"> @return</span></div><div class="line"> */</div><div class="line"> <span class="annotation">@RequestMapping</span>(value = <span class="string">"/user/{userId}"</span>, method = RequestMethod.GET)</div><div class="line"> <span class="annotation">@ResponseBody</span></div><div class="line"> <span class="keyword">public</span> User <span class="title">get</span>(@<span class="title">PathVariable</span>("userId") <span class="keyword">int</span> userId) {</div><div class="line"> Log4jUtil.debug(<span class="keyword">this</span>, <span class="string">"获取用户userId="</span> + userId);</div><div class="line"> User user = createUser(userId);</div><div class="line"> <span class="keyword">return</span> user;</div><div class="line"> }</div><div class="line"> <span class="javadoc">/**</span></div><div class="line"> * 查询用户列表</div><div class="line"> * </div><div class="line"> *<span class="javadoctag"> @param</span> user</div><div class="line"> *<span class="javadoctag"> @return</span></div><div class="line"> */</div><div class="line"> <span class="annotation">@RequestMapping</span>(value = <span class="string">"/user"</span>, method = RequestMethod.PATCH)</div><div class="line"> <span class="annotation">@ResponseBody</span></div><div class="line"> <span class="keyword">public</span> List<User> <span class="title">getList</span>(@RequestBody User user) {</div><div class="line"> <span class="comment">// 可以根据具体参数来查询所有符合的用户,比如查询用户名称为张三的人,username='张三'</span></div><div class="line"> Log4jUtil.debug(<span class="keyword">this</span>, <span class="string">"获取用户列表user="</span> + user);</div><div class="line"> List<User> list = <span class="keyword">new</span> ArrayList<User>();</div><div class="line"> list.add(createUser(<span class="number">1</span>));</div><div class="line"> list.add(createUser(<span class="number">2</span>));</div><div class="line"> list.add(createUser(<span class="number">3</span>));</div><div class="line"> list.add(createUser(<span class="number">4</span>));</div><div class="line"> list.add(createUser(<span class="number">5</span>));</div><div class="line"> <span class="keyword">return</span> list;</div><div class="line"> }</div><div class="line"> <span class="javadoc">/**</span></div><div class="line"> * 新增用户</div><div class="line"> * </div><div class="line"> *<span class="javadoctag"> @param</span> user</div><div class="line"> *<span class="javadoctag"> @return</span></div><div class="line"> */</div><div class="line"> <span class="annotation">@RequestMapping</span>(value = <span class="string">"/user"</span>, method = RequestMethod.POST)</div><div class="line"> <span class="annotation">@ResponseBody</span></div><div class="line"> <span class="keyword">public</span> Object <span class="title">add</span>(@RequestBody User user) {</div><div class="line"> Log4jUtil.debug(<span class="keyword">this</span>, <span class="string">"新增用户:"</span> + user);</div><div class="line"> Map<String, Object> dataMap = <span class="keyword">new</span> HashMap<String, Object>();</div><div class="line"> dataMap.put(<span class="string">"user"</span>, user);</div><div class="line"> dataMap.put(<span class="string">"result"</span>, <span class="string">"新增用户成功"</span>);</div><div class="line"> <span class="keyword">return</span> dataMap;</div><div class="line"> }</div><div class="line"> <span class="javadoc">/**</span></div><div class="line"> * 更新用户</div><div class="line"> * </div><div class="line"> *<span class="javadoctag"> @param</span> user</div><div class="line"> *<span class="javadoctag"> @return</span></div><div class="line"> */</div><div class="line"> <span class="annotation">@RequestMapping</span>(value = <span class="string">"/user"</span>, method = RequestMethod.PUT)</div><div class="line"> <span class="annotation">@ResponseBody</span></div><div class="line"> <span class="keyword">public</span> Object <span class="title">update</span>(@RequestBody User user) {</div><div class="line"> User u = createUser(<span class="number">5</span>);</div><div class="line"> u.setUsername(user.getUsername());</div><div class="line"> Log4jUtil.debug(<span class="keyword">this</span>, <span class="string">"更新用户:"</span> + user);</div><div class="line"> Map<String, Object> dataMap = <span class="keyword">new</span> HashMap<String, Object>();</div><div class="line"> dataMap.put(<span class="string">"user"</span>, user);</div><div class="line"> dataMap.put(<span class="string">"result"</span>, <span class="string">"更新用户成功"</span>);</div><div class="line"> <span class="keyword">return</span> dataMap;</div><div class="line"> }</div><div class="line"> <span class="javadoc">/**</span></div><div class="line"> * 删除用户</div><div class="line"> * </div><div class="line"> *<span class="javadoctag"> @param</span> userId</div><div class="line"> *<span class="javadoctag"> @return</span></div><div class="line"> */</div><div class="line"> <span class="annotation">@RequestMapping</span>(value = <span class="string">"/user/{userId}"</span>, method = RequestMethod.DELETE)</div><div class="line"> <span class="annotation">@ResponseBody</span></div><div class="line"> <span class="keyword">public</span> Object <span class="title">delete</span>(@<span class="title">PathVariable</span>("userId") <span class="keyword">int</span> userId) {</div><div class="line"> Log4jUtil.debug(<span class="keyword">this</span>, <span class="string">"删除用户userId="</span> + userId);</div><div class="line"> Map<String, Object> dataMap = <span class="keyword">new</span> HashMap<String, Object>();</div><div class="line"> dataMap.put(<span class="string">"result"</span>, <span class="string">"删除用户成功"</span>);</div><div class="line"> <span class="keyword">return</span> dataMap;</div><div class="line"> }</div><div class="line"> <span class="javadoc">/**</span></div><div class="line"> * 创建用户</div><div class="line"> * </div><div class="line"> *<span class="javadoctag"> @param</span> userId</div><div class="line"> *<span class="javadoctag"> @return</span></div><div class="line"> */</div><div class="line"> <span class="keyword">private</span> User <span class="title">createUser</span>(<span class="keyword">int</span> userId) {</div><div class="line"> User user = <span class="keyword">new</span> User();</div><div class="line"> user.setUserId(userId);</div><div class="line"> user.setUsername(<span class="string">"user"</span> + userId);</div><div class="line"> user.setPassword(<span class="string">"123456"</span>);</div><div class="line"> user.setEmail(<span class="string">"user"</span> + userId + <span class="string">"@xxx.com"</span>);</div><div class="line"> user.setSex(<span class="string">"男"</span>);</div><div class="line"> user.setTelephone(<span class="string">"1234567"</span>);</div><div class="line"> <span class="keyword">return</span> user;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<h2 id="前端">前端</h2>
<p>这里前端使用Ajax方式提交,非表单提交,Ajax提交的时候注意几个参数:type、dataType、contentType,type根据方法不同可以设置为:GET、POST、PUT、DELETE,dataType指定为’json’格式,contentType指定为’application/json’,data数据在非GET请求时需要使用<code>JSON.stringify</code>进行格式化为json字符串,具体代码如下:</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div></pre></td><td class="code"><pre><div class="line"><span class="doctype"><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"></span></div><div class="line"><span class="tag"><<span class="title">html</span>></span></div><div class="line"><span class="tag"><<span class="title">head</span>></span></div><div class="line"><span class="tag"><<span class="title">meta</span> <span class="attribute">http-equiv</span>=<span class="value">"Content-Type"</span> <span class="attribute">content</span>=<span class="value">"text/html; charset=UTF-8"</span>></span></div><div class="line"><span class="tag"><<span class="title">title</span>></span>restful test<span class="tag"></<span class="title">title</span>></span></div><div class="line"><span class="tag"><<span class="title">script</span> <span class="attribute">type</span>=<span class="value">"text/javascript"</span> <span class="attribute">src</span>=<span class="value">"js/jquery-1.11.1.min.js"</span>></span><span class="javascript"></span><span class="tag"></<span class="title">script</span>></span></div><div class="line"><span class="tag"><<span class="title">script</span> <span class="attribute">type</span>=<span class="value">"text/javascript"</span>></span><span class="javascript"></span></div><div class="line"> <span class="function"><span class="keyword">function</span> <span class="title">getUser</span><span class="params">()</span> </span>{</div><div class="line"> $.ajax({</div><div class="line"> url : <span class="string">"user/1"</span>,</div><div class="line"> type : <span class="string">'GET'</span>,</div><div class="line"> dataType : <span class="string">'json'</span>,</div><div class="line"> contentType : <span class="string">'application/json'</span>,</div><div class="line"> success : successFunc,</div><div class="line"> error : errorFunc</div><div class="line"> });</div><div class="line"> }</div><div class="line"> <span class="function"><span class="keyword">function</span> <span class="title">getUserList</span><span class="params">()</span> </span>{</div><div class="line"> $.ajax({</div><div class="line"> url : <span class="string">"user"</span>,</div><div class="line"> data : <span class="built_in">JSON</span>.stringify({<span class="string">'username'</span>:<span class="string">'user'</span>}),</div><div class="line"> type : <span class="string">'PATCH'</span>,</div><div class="line"> dataType : <span class="string">'json'</span>,</div><div class="line"> contentType : <span class="string">'application/json'</span>,</div><div class="line"> success : successFunc,</div><div class="line"> error : errorFunc</div><div class="line"> });</div><div class="line"> }</div><div class="line"> <span class="function"><span class="keyword">function</span> <span class="title">addUser</span><span class="params">()</span> </span>{</div><div class="line"> $.ajax({</div><div class="line"> url : <span class="string">"user"</span>,</div><div class="line"> data : <span class="built_in">JSON</span>.stringify({<span class="string">'userId'</span>:<span class="number">1</span>, <span class="string">'email'</span>:<span class="string">'[email protected]'</span>, <span class="string">'telephone'</span>:<span class="string">'1234567'</span>, <span class="string">'username'</span>:<span class="string">'user1'</span>, <span class="string">'password'</span>:<span class="string">'123456'</span>, <span class="string">'sex'</span>:<span class="string">'男'</span> }),</div><div class="line"> type : <span class="string">'POST'</span>,</div><div class="line"> dataType : <span class="string">'json'</span>,</div><div class="line"> contentType : <span class="string">'application/json'</span>,</div><div class="line"> success : successFunc,</div><div class="line"> error : errorFunc</div><div class="line"> });</div><div class="line"> }</div><div class="line"> <span class="function"><span class="keyword">function</span> <span class="title">updateUser</span><span class="params">()</span> </span>{</div><div class="line"> $.ajax({</div><div class="line"> url : <span class="string">"user"</span>,</div><div class="line"> data : <span class="built_in">JSON</span>.stringify({<span class="string">'userId'</span>:<span class="number">1</span>, <span class="string">'email'</span>:<span class="string">'[email protected]'</span>, <span class="string">'telephone'</span>:<span class="string">'1234567'</span>, <span class="string">'username'</span>:<span class="string">'user1_newName'</span>, <span class="string">'password'</span>:<span class="string">'123456'</span>, <span class="string">'sex'</span>:<span class="string">'男'</span> }),</div><div class="line"> type : <span class="string">'PUT'</span>,</div><div class="line"> async : <span class="literal">true</span>,</div><div class="line"> dataType : <span class="string">'json'</span>,</div><div class="line"> contentType : <span class="string">'application/json'</span>,</div><div class="line"> success : successFunc,</div><div class="line"> error : errorFunc</div><div class="line"> });</div><div class="line"> }</div><div class="line"> <span class="function"><span class="keyword">function</span> <span class="title">deleteUser</span><span class="params">()</span> </span>{</div><div class="line"> $.ajax({</div><div class="line"> url : <span class="string">"user/1"</span>,</div><div class="line"> type : <span class="string">'DELETE'</span>,</div><div class="line"> dataType : <span class="string">'json'</span>,</div><div class="line"> contentType : <span class="string">'application/json'</span>,</div><div class="line"> success : successFunc,</div><div class="line"> error : errorFunc</div><div class="line"> });</div><div class="line"> }</div><div class="line"> <span class="function"><span class="keyword">function</span> <span class="title">successFunc</span><span class="params">(data)</span> </span>{</div><div class="line"> $(<span class="string">"#msg"</span>).text(<span class="built_in">JSON</span>.stringify(data))</div><div class="line"> }</div><div class="line"> <span class="function"><span class="keyword">function</span> <span class="title">errorFunc</span><span class="params">(data)</span> </span>{</div><div class="line"> $(<span class="string">"#msg"</span>).text(<span class="built_in">JSON</span>.stringify(data))</div><div class="line"> }</div><div class="line"><span class="tag"></<span class="title">script</span>></span></div><div class="line"><span class="tag"></<span class="title">head</span>></span></div><div class="line"><span class="tag"><<span class="title">body</span>></span></div><div class="line"> <span class="tag"><<span class="title">input</span> <span class="attribute">type</span>=<span class="value">"button"</span> <span class="attribute">onclick</span>=<span class="value">"getUser();"</span> <span class="attribute">value</span>=<span class="value">"get user"</span>></span><span class="tag"><<span class="title">br</span>></span></div><div class="line"> <span class="tag"><<span class="title">input</span> <span class="attribute">type</span>=<span class="value">"button"</span> <span class="attribute">onclick</span>=<span class="value">"getUserList();"</span> <span class="attribute">value</span>=<span class="value">"get user list"</span>></span><span class="tag"><<span class="title">br</span>></span></div><div class="line"> <span class="tag"><<span class="title">input</span> <span class="attribute">type</span>=<span class="value">"button"</span> <span class="attribute">onclick</span>=<span class="value">"addUser();"</span> <span class="attribute">value</span>=<span class="value">"add user"</span>></span><span class="tag"><<span class="title">br</span>></span></div><div class="line"> <span class="tag"><<span class="title">input</span> <span class="attribute">type</span>=<span class="value">"button"</span> <span class="attribute">onclick</span>=<span class="value">"updateUser();"</span> <span class="attribute">value</span>=<span class="value">"update user"</span>></span><span class="tag"><<span class="title">br</span>></span></div><div class="line"> <span class="tag"><<span class="title">input</span> <span class="attribute">type</span>=<span class="value">"button"</span> <span class="attribute">onclick</span>=<span class="value">"deleteUser();"</span> <span class="attribute">value</span>=<span class="value">"delete user"</span>></span><span class="tag"><<span class="title">br</span>></span></div><div class="line"> <span class="tag"><<span class="title">div</span> <span class="attribute">id</span>=<span class="value">"msg"</span>></span><span class="tag"></<span class="title">div</span>></span></div><div class="line"><span class="tag"></<span class="title">body</span>></span></div><div class="line"><span class="tag"></<span class="title">html</span>></span></div></pre></td></tr></table></figure>
<p><a href="https:/dreajay/springMVC-demo" target="_blank" rel="external">代码下载</a></p>
]]></content>
<breadCrumb title="javaee" url="http://dreajay.github.io/categories/javaee/"/>
</display>
</data>
</url>
<url>
<loc>http://dreajay.github.io/2014/12/01/effective%20java-%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0-%E7%AC%AC%E5%9B%9B%E7%AB%A0%20%E7%B1%BB%E5%92%8C%E6%8E%A5%E5%8F%A3/</loc>
<lastmod>2014-12-06T13:55:33.000Z</lastmod>
<data>
<display>
<title>effective java-读书笔记-第四章 类和接口</title>
<pubTime>2014-12-01T13:01:21.000Z</pubTime>
<tag>effective java </tag>
<tag>读书笔记 </tag>
<content><![CDATA[<h1 id="第四章_类和接口">第四章 类和接口</h1>
<h2 id="第13条_使类和成员的访问性最小">第13条 使类和成员的访问性最小</h2>
<p><strong> 原则:尽可能地使每个类或者成员不被外界访问。</strong><br>信息隐藏或封装可以有效的解除组成系统的各个模块之间的耦合关系,使得这些模块可以独立地开发、测试、优化、使用、理解和修改。这样可以加快系统开发速度,因为这些模块可以并行开发,它也减轻了维护的负担。</p>
<p>类和接口有两种访问级别:<br>包级私有(package-private)和公有(public)。</p>
<p>成员有四种返回级别,访问性逐渐递增:<br>私有的(private)< 包级私有(package-private)也叫缺省(default)访问级别 < 受保护的(protected)< 公有的(public)。</p>
<p><em>除了公有静态final域的特殊之外,公有类都不应该包含公有域,并且要确保公有静态final域所引用的对象是不可变得。</em></p>
<h2 id="第14条_在公有类中使用访问方法而非公有域">第14条 在公有类中使用访问方法而非公有域</h2>
<p>原则上公有类永远都不应该暴露可变的域,应该提供方法来访问。让公有类暴露不可变的域其危害性比价小。<br>反面例子:</p>
<pre><code>java.awt.Point(<span class="keyword">public</span> <span class="keyword">int</span> x;<span class="keyword">public</span> <span class="keyword">int</span> y;)
java.awt.Dimension(<span class="keyword">public</span> <span class="keyword">int</span> width;<span class="keyword">public</span> <span class="keyword">int</span> height;)
</code></pre><p>如果类是包级私有的,或者私有的嵌套类,直接暴露它的数据域并没有本质的错误——假设这些数据域确实描述了该类所提供的抽象。<br>包级私有的类,域被限定在包含改类的包中。<br>私有的嵌套类,域改变的作用范围被进一步限制在外围类中。</p>
<h2 id="第15条_使类可变性最小化">第15条 使类可变性最小化</h2>
<p>不可变类指的是其实例不能被修改的类。<br>不可变类的优点:比可变类更加易于设计、实现和使用,不容易出错,且更加安全。<br>不可变对象本质是是同步的,它们不要求同步。<br><strong> 编写不可变类的规则: </strong></p>
<ol>
<li>不要提供任何会修改对象状态的方法。</li>
<li>保证类不会被扩展。</li>
<li>使所有的域都是final的。</li>
<li>使所有的域都成为私有的。</li>
<li>确保对于任何可变组件的互斥访问。如果类具有指向可变对象的域,确保改域不会被外部修改。</li>
</ol>
<p><strong> 让类变成不可变类: </strong><br>一种方法是加上final修饰类。更加推荐的方法是,让类构造器变成私有,提供静态工厂来代替公有构造器。JDK中的例子,String、基本数据类型封装类。</p>
<pre><code><span class="keyword">public</span> <span class="keyword">static</span> Integer <span class="title">valueOf</span>(<span class="keyword">int</span> i);
<span class="keyword">public</span> <span class="keyword">static</span> Integer <span class="title">getInteger</span>(String nm);
</code></pre><h2 id="第16条_复合优先于继承">第16条 复合优先于继承</h2>
<p>继承功能很强大,但也存在诸多问题,因为它违反了封装性。只有当子类和超类之间确实存在子类型(is-a)关系时,使用继承才是恰当的。即便如此,如果子类和超类不在同一包中,并且超类并不是为了继承而设计的,那么继承将会导致脆弱性,为了避免这种脆弱性,可以使用复合和转发机制来代替继承,尤其是存在适当的接口可以实现包装类的时候。包装类不仅比子类更加健壮,而且功能更加强大。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//转发类</span></div><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ForwardingSet</span><<span class="title">E</span>> <span class="keyword">implements</span> <span class="title">Set</span><<span class="title">E</span>> </span>{</div><div class="line"> <span class="keyword">private</span> <span class="keyword">final</span> Set<E> s;</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="title">ForwardingSet</span>(Set<E> s) {</div><div class="line"> <span class="keyword">this</span>.s = s;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">clear</span>() {</div><div class="line"> s.clear();</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">contains</span>(Object o) {</div><div class="line"> <span class="keyword">return</span> s.contains(o);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isEmpty</span>() {</div><div class="line"> <span class="keyword">return</span> s.isEmpty();</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="keyword">int</span> <span class="title">size</span>() {</div><div class="line"> <span class="keyword">return</span> s.size();</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> Iterator<E> <span class="title">iterator</span>() {</div><div class="line"> <span class="keyword">return</span> s.iterator();</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">add</span>(E e) {</div><div class="line"> <span class="keyword">return</span> s.add(e);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">remove</span>(Object o) {</div><div class="line"> <span class="keyword">return</span> s.remove(o);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">containsAll</span>(Collection<?> c) {</div><div class="line"> <span class="keyword">return</span> s.containsAll(c);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">addAll</span>(Collection<? extends E> c) {</div><div class="line"> <span class="keyword">return</span> s.addAll(c);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">removeAll</span>(Collection<?> c) {</div><div class="line"> <span class="keyword">return</span> s.removeAll(c);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">retainAll</span>(Collection<?> c) {</div><div class="line"> <span class="keyword">return</span> s.retainAll(c);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> Object[] <span class="title">toArray</span>() {</div><div class="line"> <span class="keyword">return</span> s.toArray();</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <T> T[] <span class="title">toArray</span>(T[] a) {</div><div class="line"> <span class="keyword">return</span> s.toArray(a);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">equals</span>(Object o) {</div><div class="line"> <span class="keyword">return</span> s.equals(o);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">public</span> <span class="keyword">int</span> <span class="title">hashCode</span>() {</div><div class="line"> <span class="keyword">return</span> s.hashCode();</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">public</span> String <span class="title">toString</span>() {</div><div class="line"> <span class="keyword">return</span> s.toString();</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<figure class="highlight"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//包装类</span></div><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">InstrumentedSet</span><<span class="title">E</span>> <span class="keyword">extends</span> <span class="title">ForwardingSet</span><<span class="title">E</span>> </span>{</div><div class="line"> <span class="keyword">private</span> <span class="keyword">int</span> addCount = <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="title">InstrumentedSet</span>(Set<E> s) {</div><div class="line"> <span class="keyword">super</span>(s);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">add</span>(E e) {</div><div class="line"> addCount++;</div><div class="line"> <span class="keyword">return</span> <span class="keyword">super</span>.add(e);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">addAll</span>(Collection<? extends E> c) {</div><div class="line"> addCount += c.size();</div><div class="line"> <span class="keyword">return</span> <span class="keyword">super</span>.addAll(c);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getAddCount</span>() {</div><div class="line"> <span class="keyword">return</span> addCount;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span>(String[] args) {</div><div class="line"> InstrumentedSet<String> s = <span class="keyword">new</span> InstrumentedSet<String>(</div><div class="line"> <span class="keyword">new</span> HashSet<String>());</div><div class="line"> s.addAll(Arrays.asList(<span class="string">"Snap"</span>, <span class="string">"Crackle"</span>, <span class="string">"Pop"</span>));</div><div class="line"> System.out.println(s.getAddCount());</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<p>包装器不适合用在回调框架(callback framework)中,在回调框架中,对象把自身的引用传递给其他对象,用于后续的调用(回调)。因为被包装起来的对象并不知道它外面的包装对象,所以它传递一个指向自身的引用,回调时避开了外面的包装对象。这被称为SELF问题。</p>
<p>编写转发方法有点繁琐,但是只需要给每个接口编写一次构造器,转发类则可以通过包含接口的包替你实现。</p>
<h2 id="第17条_要么为继承而设计,并提供文档说明,要么就禁止继承">第17条 要么为继承而设计,并提供文档说明,要么就禁止继承</h2>
<p>对于为了继承而设计的类,该类文档必须精确的描述每个方法带来的影像。指明该方法或构造器调用了哪些可覆盖的方法,是以什么顺序调用的,每个调用结果又将怎样影像后续处理过程。</p>
<p>对于为了继承而设计的类,唯一的测试方法就是编写子类。必须在发布类之前先编写子类对类进行测试。</p>
<p>为了允许继承,类还必须遵守其他一些约束,构造器觉不能调用可被覆盖的方法,无论是直接调用还是间接调用,如果违反了这条规则,很可能导致程序失败。比如:</p>
<figure class="highlight Super"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="keyword">class</span> Super {</div><div class="line"> <span class="comment">// Broken - constructor invokes an overridable method</span></div><div class="line"> <span class="keyword">public</span> <span class="title">Super</span>() {</div><div class="line"> overrideMe();</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">overrideMe</span>() {</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<figure class="highlight"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">Sub</span> <span class="keyword">extends</span> <span class="title">Super</span> </span>{</div><div class="line"> <span class="keyword">private</span> <span class="keyword">final</span> Date date; <span class="comment">// Blank final, set by constructor</span></div><div class="line"></div><div class="line"> Sub() {</div><div class="line"> date = <span class="keyword">new</span> Date();</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// Overriding method invoked by superclass constructor</span></div><div class="line"> <span class="annotation">@Override</span></div><div class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">overrideMe</span>() {</div><div class="line"> System.out.println(date);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span>(String[] args) {</div><div class="line"> Sub sub = <span class="keyword">new</span> Sub();</div><div class="line"> sub.overrideMe();</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<p>可能期待打印2次日期,但这里打印出来的结果是第一次为null,第二次才有值,第一次父类构造器调用子类overrideme的时候,子类的date还没有初始化。如果这里去调用不是打印方法,而是date的具体方法,就会出现空指针异常NullPointerException。</p>
<p>对于那些为了安全的进行子类化而设计和编写的文档的类,要禁止子类化。比如使用final类,私有构造器、静态工厂类代替,包装类。</p>
<h2 id="第18条_接口优于抽象类">第18条 接口优于抽象类</h2>
<p>Java只允许单继承,抽象类作为类型定义受到了极大的限制。</p>
<p><strong>接口优于抽象类:</strong></p>
<ul>
<li>现有的类可以很容易被更新,以实现新的接口。</li>
<li>接口是定义混合类型(mixin)的理想选择。 </li>
<li>接口允许我们构造非层次结构的类型框架。</li>
</ul>
<p>导出的每个重要的接口去实现骨架框架,更好的结合抽象类,接口定义类型,骨架实现类接管了所有与接口实现想关的工作。<br> Interface——》AbstractInterface——》SimpleAdapter(Simple Implementation)——》DetailImplement</p>
<h2 id="第19条_接口只用于定义类型">第19条 接口只用于定义类型</h2>
<p>当类实现接口时,接口就充当可以引用这个类的实例的类型(type)。</p>
<p>接口应该只被用来定义类型,它们不应该被用来导出常量。</p>
<p>常量接口模式是对接口的不良使用。Java平台反面例子:java.io.ObjectStreamConstants。</p>
<h2 id="第20条_类层次优于标签类">第20条 类层次优于标签类</h2>
<p>有时候,可能会遇到带有2种甚至更多种风格的实例的类,并包含表示实例风格的标签域,例如,下面这个类可以表示圆形或矩形:</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div></pre></td><td class="code"><pre><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">Figure</span> </span>{</div><div class="line"> <span class="keyword">enum</span> Shape {</div><div class="line"> RECTANGLE, CIRCLE</div><div class="line"> };</div><div class="line"></div><div class="line"> <span class="comment">// Tag field - the shape of this figure</span></div><div class="line"> <span class="keyword">final</span> Shape shape;</div><div class="line"></div><div class="line"> <span class="comment">// These fields are used only if shape is RECTANGLE</span></div><div class="line"> <span class="keyword">double</span> length;</div><div class="line"> <span class="keyword">double</span> width;</div><div class="line"></div><div class="line"> <span class="comment">// This field is used only if shape is CIRCLE</span></div><div class="line"> <span class="keyword">double</span> radius;</div><div class="line"></div><div class="line"> <span class="comment">// Constructor for circle</span></div><div class="line"> Figure(<span class="keyword">double</span> radius) {</div><div class="line"> shape = Shape.CIRCLE;</div><div class="line"> <span class="keyword">this</span>.radius = radius;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// Constructor for rectangle</span></div><div class="line"> Figure(<span class="keyword">double</span> length, <span class="keyword">double</span> width) {</div><div class="line"> shape = Shape.RECTANGLE;</div><div class="line"> <span class="keyword">this</span>.length = length;</div><div class="line"> <span class="keyword">this</span>.width = width;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">double</span> area() {</div><div class="line"> <span class="keyword">switch</span> (shape) {</div><div class="line"> <span class="keyword">case</span> RECTANGLE:</div><div class="line"> <span class="keyword">return</span> length * width;</div><div class="line"> <span class="keyword">case</span> CIRCLE:</div><div class="line"> <span class="keyword">return</span> Math.PI * (radius * radius);</div><div class="line"> <span class="keyword">default</span>:</div><div class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> AssertionError();</div><div class="line"> }</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<p>这种标签类有许多缺点,充斥着样板代码,包括枚举声明、标签域以及条件语句,过于冗长,容易出错,并且效力低下。</p>
<p>定义能表示多种风格对象的单个数据类型时,可以使用子类型化(subtyping),标签类是类层次的一种简单的仿效。将标签类转换成类层次,首先要为标签类中的每个方法定义一个包含抽象方法的抽象类, 这每个方法的行为都依赖于标签值。在Figure中只有这样一个方法:area,Figure具体的类层次如下:</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">Figure</span> </span>{</div><div class="line"> <span class="keyword">abstract</span> <span class="keyword">double</span> area();</div><div class="line">}</div></pre></td></tr></table></figure>
<figure class="highlight"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">Circle</span> <span class="inheritance"><span class="keyword">extends</span></span> <span class="title">Figure</span> </span>{</div><div class="line"> <span class="keyword">final</span> <span class="keyword">double</span> radius;</div><div class="line"></div><div class="line"> Circle(<span class="keyword">double</span> radius) {</div><div class="line"> <span class="keyword">this</span>.radius = radius;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">double</span> area() {</div><div class="line"> <span class="keyword">return</span> Math.PI * (radius * radius);</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<figure class="highlight"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">Rectangle</span> <span class="inheritance"><span class="keyword">extends</span></span> <span class="title">Figure</span> </span>{</div><div class="line"> <span class="keyword">final</span> <span class="keyword">double</span> length;</div><div class="line"> <span class="keyword">final</span> <span class="keyword">double</span> width;</div><div class="line"></div><div class="line"> Rectangle(<span class="keyword">double</span> length, <span class="keyword">double</span> width) {</div><div class="line"> <span class="keyword">this</span>.length = length;</div><div class="line"> <span class="keyword">this</span>.width = width;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">double</span> area() {</div><div class="line"> <span class="keyword">return</span> length * width;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<h2 id="第21条_用函数对象表示策略">第21条 用函数对象表示策略</h2>
<p>函数指针的主要用途就是实现策略(Strategy)模式。实现策略模式,要声明一个接口来表示该策略,并且为每个具体策略声明一个实现了该接口的类。当一个具体策略只被使用一次时,通常使用匿名内部类来声明和实化这个具体策略类,当一个具体策略类是设计用来重复使用时,它的类通常就要被实现为私有的静态成员类,并通过共有的静态final域被导出,其类型为该策略的接口。</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 匿名内部类实现策略</span></div><div class="line">Arrays.sort(stringArray, <span class="keyword">new</span> Comparator<String>() {</div><div class="line"> <span class="keyword">public</span> <span class="keyword">int</span> <span class="title">compare</span>(String s1, String s2) {</div><div class="line"> <span class="keyword">return</span> s1.length() - s2.length();</div><div class="line"> }</div><div class="line">});</div></pre></td></tr></table></figure>
<figure class="highlight"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//重复使用时,使用这种方法,减少开销</span></div><div class="line">class Host {</div><div class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">StrLenCmp</span> <span class="keyword">implements</span> <span class="title">Comparator</span><<span class="title">String</span>>, <span class="title">Serializable</span> </span>{</div><div class="line"> <span class="keyword">public</span> <span class="keyword">int</span> <span class="title">compare</span>(String s1, String s2) {</div><div class="line"> <span class="keyword">return</span> s1.length() - s2.length();</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="comment">//reutrned comparator is serizlizable</span></div><div class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> Comparator<String> STRING_LENGTH_COMPARATOR = <span class="keyword">new</span> StrLenCmp();</div><div class="line"></div><div class="line">}</div></pre></td></tr></table></figure>
<h2 id="第22条_优先考虑静态成员类">第22条 优先考虑静态成员类</h2>
<p>嵌套类包含四种:静态成员类、非静态成员类、匿名类和局部类。</p>
<p>静态成员类的常见用法是作为共有的辅助器,仅当与它的外部类一起使用时才有意义。</p>
<p>非静态成员类的常见用法是定义一个Adapter,它允许外部类的实例被看作是另一个不相关的类的实例。</p>
<p>私有静态成员类的一种常见做法是用来表示外围类所代表的对象的组件。</p>
<p><strong>全套类的用法</strong></p>
<ul>
<li>如果一个嵌套类需要在单个方法之外仍然是可见的,或者它太长了,不适合放在方法内部,就应该使用成员类。</li>
<li>如果成员类的每个实例都需要一个指向其外围实例的引用,就要把成员类做成非静态的,否则,就该做成静态的。</li>
<li>假设这个嵌套类属于一个方法的内部,如果你只需要在一个地方创建实例,并且已经有了一个预设的类型可以说明这个类的特征,就要把它做成匿名类,否则就做成局部类。</li>
</ul>
]]></content>
<breadCrumb title="java" url="http://dreajay.github.io/categories/java/"/>
<breadCrumb title="读书笔记" url="http://dreajay.github.io/categories/java/%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/"/>
</display>
</data>
</url>
<url>
<loc>http://dreajay.github.io/2014/11/30/effective%20java-%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0-%E7%AC%AC%E4%B8%89%E7%AB%A0%20%E5%AF%B9%E4%BA%8E%E6%89%80%E6%9C%89%E5%AF%B9%E8%B1%A1%E9%83%BD%E9%80%9A%E7%94%A8%E7%9A%84%E6%96%B9%E6%B3%95/</loc>
<lastmod>2014-11-30T15:02:53.000Z</lastmod>
<data>
<display>
<title>effective java-读书笔记-第三章 对于所有对象都通用的方法</title>
<pubTime>2014-11-30T14:57:04.000Z</pubTime>
<tag>effective java </tag>
<tag>读书笔记 </tag>
<content><![CDATA[<h1 id="第三章_对于所有对象都通用的方法">第三章 对于所有对象都通用的方法</h1>
<p>所有非final方法(equals、hashCode、toString、clone、finalize)都有明确的通用约定,因为它们被设计成是要被覆盖的,如果不遵守,基于散列的集合(HashMap、HashSet、HashTable)可能无法结合该类一起运作。</p>
<h2 id="第8条_覆盖equals时请遵守通用约定">第8条 覆盖equals时请遵守通用约定</h2>
<p><strong>覆盖equals规范:</strong></p>
<ol>
<li>自反性(reflexive)。对于任何非null的引用值x,x.equals(x)必须返回true。</li>
<li>对称性(symmetric)。对于任何非null的引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)必须返回true。</li>
<li>传递性(transitive)。对于任何非null的引用值x、y和z,如果x.equals(y)返回true,并且y.equals(z)也返回true,那么x.equals(z)必须返回true。</li>
<li>一致性(consistent)。对于任何非null的引用值x和y,只有equals的比较操作在对象中所用的信息没有被修改,多次调用x.equals(y)就会一致的返回true或者false。</li>
</ol>
<p><strong>实现equals方法:</strong></p>
<ol>
<li>使用==操作符检查“参数是否为这个对象的引用”。如果是,返回true。</li>
<li>使用instanceof操作符检查”参数是否为正确的类型”。如果不是返回false。</li>
<li>把参数转换成正确的类型。转换之前用instanceof判断,确保正确。</li>
<li>对于该类中的每个”关键“字段,检查参数中的字段是否与该对象中对应的字段相匹配。如果这些测试检查成功,返回true,否则返回false。</li>
<li>当编写完equals方法,编写单元测试校验它是否是对称的、传递的、一致的。</li>
</ol>
<p><strong>注意:</strong></p>
<ol>
<li>覆盖equals方法时总要覆盖hashCode方法。</li>
<li>不要企图让equals方法过于智能。比如File不应该和文件链接当作相等来看待。</li>
<li>不要将equals方法声明中的Object对象替换为其他类型。</li>
</ol>
<h2 id="第9条_覆盖equals时总要覆盖hashCode">第9条 覆盖equals时总要覆盖hashCode</h2>
<p>hashcode方法返回该对象的哈希码值。通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。</p>
<p><strong>hashCode常规协定</strong></p>
<ol>
<li>在应用程序执行期间,只要对象的equals方法的比较操作中所用的信息没有被修改,那么对这同一对象多次调用,hashCode方法都必须一致地返回同样的整数。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。 </li>
<li>如果两个对象根据equals(Object)方法比较是相等的,那么调用两个对象中的任意一个对象上hashCode 方法都必须产生相同的整数结果。 </li>
<li>如果两个对象根据equals(Object)方法比较是不相等的,那么调用两个对象中的任意一个对象上hashCode 方法,则不一定产生不同的整数结果。但是,程序员应该知道,为不相等的对象生成不同整数结果可以提高哈希表的性能。 </li>
</ol>
<p><em>对于equals()相等的两个对象,其hashCode()返回的值一定相等</em></p>
<p><strong>重写hashCode方法</strong></p>
<ol>
<li>保证equals相等的对象hash码要一定相等</li>
<li>对于equals不同的对象要尽量做到hash码不同<br>具体步骤就是:<br>[1]把某个非零常数值(一般取素数),例如17,保存在int变量result中;<br>[2]对于对象中每一个关键域f(指equals方法中考虑的每一个域):<br>[2.1]boolean型,计算(f ? 0 : 1);<br>[2.2]byte、char、short、int型,计算(int)f;<br>[2.3]long型,计算(int) (f ^ (f>>>32));<br>[2.4]float型,计算Float.floatToIntBits(afloat);<br>[2.5]double型,计算Double.doubleToLongBits(adouble)得到一个long,再执行[2.3];<br>[2.6]对象引用,递归调用它的hashCode方法;<br>[2.7]数组域,对其中每个元素调用它的hashCode方法。<br>[3]将上面计算得到的散列码保存到int变量c,然后执行 result=37<em>result+c;<br>[4]返回result。<br>其实其思路就是:先取一个基数,然后对于equals()中考虑的每一个域,先转换成整数,再执行result=37</em>result+c;例如:</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">hashCode</span>(){</div><div class="line"> <span class="keyword">int</span> result = <span class="number">17</span>;</div><div class="line"> result = <span class="number">31</span>*result+age;</div><div class="line"> result=<span class="number">31</span>*result+name.hashCode();</div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div></pre></td></tr></table></figure>
<h2 id="第10条_始终要覆盖toString">第10条 始终要覆盖toString</h2>
<p>toString通用约定指出被返回的字符串应该是简洁的、但信息丰富,并且易于阅读的表达形式。提供好的toString方法可以使类用起来更加舒适,当对象被传递给println、pringtf、字符串联合操作+、日志打印,toString会被自动调用。</p>
<p><em>建议所有的子类都覆盖toString方法。</em></p>
<h2 id="第11条_谨慎地覆盖clone">第11条 谨慎地覆盖clone</h2>
<p>Cloneable接口表明这样的对象允许克隆,它没有包含任何方法,它改变了超类中受保护的方法clone的行为,如果一个类实现了Cloneable接口,Object的clone方法就返回该对象的逐层拷贝,否则就会抛出CloneNotSupportException异常。</p>
<p>覆盖clone方法要非常小心,如果类里面含有复杂数据类型,要进行深度复制,如果类里面有final属性,则无法进行clone,因为final属性在clone时无法再进行赋值。</p>
<p><em>建议对象不使用clone方法,而使用静态拷贝工厂或拷贝构造器替代clone方法</em></p>
<figure class="highlight"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="title">Obj</span>(Obj obj);</div><div class="line"><span class="keyword">public</span> <span class="keyword">static</span> Obj <span class="title">newInstance</span>(Obj obj);</div></pre></td></tr></table></figure>
<h2 id="第12条_考虑实现Comparable接口">第12条 考虑实现Comparable接口</h2>
<p>Comparable接口表明它的实例具有内在排序关系。</p>
<p><strong>Comparable声明:</strong></p>
<ol>
<li>如果第一个对象小于第二个对象,则第二个对象一定大于第一个对象;如果第一个对象等于第二个对象,则第二个对象一定等于第一个对象;如果第一个对象大于第二个对象,则第二个对象一定小于第一个对象。</li>
<li>如果第一个对象大于第二个对象,并且第二个对象又大于第三个对象,那么第一个对象一定大于第三个对象。</li>
<li>在比较时被认为相等的所有对象,它们跟别的对象做比较时一定会产生同样的结果。</li>
</ol>
<p>Comparable的声明和equals的声明类似,也遵守自反性、对称性和传递性。</p>
<p><em>强烈建议( (x.compareTo(y)==0)==(x.eauals(y) ),但这并非绝对必要。</em></p>
<p><strong>Comparable实现</strong></p>
<p>compareTo方法中的域的比较时顺序的比较,而不是等同性的比较。笔记对象引用域可以使通过递归地调用compareTo方法来实现。如果一个域没有实现Comparable接口,或者你需要一个非标准的排序关系,就可以使用一个显示的Comparator接口来代替。</p>
<figure class="highlight 例子"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">compareTo</span>(PhoneNumber pn) {</div><div class="line"> <span class="keyword">int</span> areaCodeDiff = areaCode - pn.areaCode;</div><div class="line"> <span class="keyword">if</span> (areaCodeDiff != <span class="number">0</span>)</div><div class="line"> <span class="keyword">return</span> areaCodeDiff;</div><div class="line"> <span class="keyword">int</span> prefixDiff = prefix - pn.prefix;</div><div class="line"> <span class="keyword">if</span> (prefixDiff != <span class="number">0</span>)</div><div class="line"> <span class="keyword">return</span> prefixDiff;</div><div class="line"> <span class="comment">// 下面可能会发生超出int最大值异常</span></div><div class="line"> <span class="keyword">return</span> lineNumber - pn.lineNumber;</div><div class="line"> }</div></pre></td></tr></table></figure>
]]></content>
<breadCrumb title="java" url="http://dreajay.github.io/categories/java/"/>
<breadCrumb title="读书笔记" url="http://dreajay.github.io/categories/java/%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/"/>
</display>
</data>
</url>
<url>
<loc>http://dreajay.github.io/2014/11/24/hexo-github-build-blog/</loc>
<lastmod>2014-11-25T11:22:10.000Z</lastmod>
<data>
<display>
<title>hexo+github搭建博客系统</title>
<pubTime>2014-11-24T13:02:40.000Z</pubTime>
<tag>博客 </tag>
<tag>hexo </tag>
<tag>github </tag>
<tag>markdown </tag>
<content><![CDATA[<p>个人博客大概包含了以下几个模块:首页、文章存档、文章分类、关于、友情链接,有些博客资源丰富,功能强大,还会加上一些诸如站内搜索、评论、分享、微博秀、广告等一些功能,很多框架都可以快速搭建起一个包含以上功能的博客,关于有哪些框架可以搭建博客,可以移步知乎讨论:<a href="http://www.zhihu.com/question/21981094" target="_blank" rel="external">应用github pages创建自己的个人博客</a>。<br><a id="more"></a><br>本博客是用hexo+github搭建的,选择<a href="http://hexo.io/" target="_blank" rel="external">hexo</a>是因为它比较简单,选择<a href="https:" target="_blank" rel="external">github</a>因为它免费,哈哈,免费的东西总是能让人趋之若鹜。本博客的搭建也是参考很多他人资料,会在后面列出,我这里总结一下自己搭建博客各个模块用到的资源。</p>
<h1 id="创建github博客">创建github博客</h1>
<p>IT人员应该人手必备一个<a href="https:" target="_blank" rel="external">github</a>账号,否则无法跟上这个逼格的年代,先注册一个github账号,然后创建自己的博客GitHub Pages,仓库名字固定结尾github.io,加上你的前缀,比如xxx.github.io。这里不会具体展开,相信你能做到:<a href="http://jingyan.baidu.com/article/ed2a5d1f3732cb09f7be1745.html" target="_blank" rel="external">http://jingyan.baidu.com/article/ed2a5d1f3732cb09f7be1745.html</a>。</p>
<h1 id="hexo">hexo</h1>
<h2 id="安装">安装</h2>
<p>因为<a href="http://hexo.io/" target="_blank" rel="external">hexo</a>是居于note.js的,所以要安装hexo,必须先安装note.js环境,这里并不一定需要很深入的了解notejs,如果你只想简单的使用hexo的话,安装很简单,直接到官网下载安装:<a href="http://www.nodejs.org" target="_blank" rel="external">http://www.nodejs.org</a>,安装完了notejs,打开命令行[cmd、git bash]执行命令即可安装hexo:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ npm install -g hexo</div></pre></td></tr></table></figure>
<h2 id="快速开始">快速开始</h2>
<p><a href="http://hexo.io/" target="_blank" rel="external">Hexo</a>的官网有很多文档资料,花一点时间看看文档,对你很有帮助,虽然是英文,但是不难,下面介绍几个常用的命令来搭建hexo博客。</p>
<h3 id="创建博客">创建博客</h3>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">$ hexo init c:/blog</div><div class="line">$ npm install</div></pre></td></tr></table></figure>
<h3 id="新建一篇文章">新建一篇文章</h3>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ hexo new <span class="string">"test"</span></div></pre></td></tr></table></figure>
<p>在sourece/_posts目录下会生成一个test.md文件,md为markdown文件格式,你可以用记事本来编辑,不过我更加推荐sublime text这款编辑器。markdown非常简单,更多请参考:<a href="https:/riku/Markdown-Syntax-CN" target="_blank" rel="external">Markdown 语法 (简体中文版)</a>,在线编辑工具:<a href="https://www.zybuluo.com/mdeditor" target="_blank" rel="external">作业部落Cmd</a>, <a href="http://maxiang.info/" target="_blank" rel="external">马克飞象</a>。</p>
<h3 id="运行服务">运行服务</h3>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ hexo s</div></pre></td></tr></table></figure>
<p>访问<a href="http://localhost:4000" target="_blank" rel="external">http://localhost:4000</a>,即可看到刚才的文章。</p>
<p>More info: <a href="http://hexo.io/docs/server.html" target="_blank" rel="external">Server</a></p>
<h3 id="生成静态文件">生成静态文件</h3>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ hexo g</div></pre></td></tr></table></figure>
<h3 id="发布到github">发布到github</h3>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ hexo d</div></pre></td></tr></table></figure>
<p>需要在_config.yml配置你的github博客地址。</p>
<h2 id="hexo主题">hexo主题</h2>
<p>hexo有很多漂亮的主题:<a href="https:/hexojs/hexo/wiki/Themes" target="_blank" rel="external">https:/hexojs/hexo/wiki/Themes</a>,你可以拿来修改成自己的,再次提醒参考<a href="http://hexo.io/docs/" target="_blank" rel="external">hexo</a>官方文档对你很有帮助。</p>
<h1 id="功能扩展">功能扩展</h1>
<p>给博客添加一些额外的功能,比如添加RSS订阅、分享、评论、404页面等待,这里不会具体展开怎么去做,具体还是需要自己去实践,可参看前人博客。</p>
<h2 id="网站图标">网站图标</h2>
<p><a href="http://www.bitbug.net/" target="_blank" rel="external">http://www.bitbug.net/</a><br><a href="http://creatr.cc/creatr/" target="_blank" rel="external">http://creatr.cc/creatr/</a></p>
<h2 id="分享">分享</h2>
<p>加网:<a href="http://www.jiathis.com/" target="_blank" rel="external">http://www.jiathis.com/</a><br>百度:<a href="http://share.baidu.com/code" target="_blank" rel="external">http://share.baidu.com/code</a><br>bShare:<a href="http://www.bshare.cn/" target="_blank" rel="external">http://www.bshare.cn/</a></p>
<h2 id="评论">评论</h2>
<p>多说:<a href="http://duoshuocom/" target="_blank" rel="external">http://duoshuo.com/</a> 国内用得多,方便快速<br>disqus:<a href="https://www.disqus.com/" target="_blank" rel="external">https://www.disqus.com/</a> 功能强大</p>
<h2 id="新浪微博秀">新浪微博秀</h2>
<p>微博秀:<a href="http://open.weibo.com/widget/like.php" target="_blank" rel="external">http://open.weibo.com/widget/like.php</a></p>
<h2 id="fork_me_on_github">fork me on github</h2>
<p>给博客加入github的fork链接:<a href="https:/blog/273-github-ribbons" target="_blank" rel="external">https:/blog/273-github-ribbons</a></p>
<h2 id="回到顶部">回到顶部</h2>
<p>参考文章:<a href="http://wuchong.me/blog/2014/01/08/hexo-scrollup/" target="_blank" rel="external">http://wuchong.me/blog/2014/01/08/hexo-scrollup/</a></p>
<h2 id="百度统计">百度统计</h2>
<p><a href="http://tongji.baidu.com/web/welcome/login" target="_blank" rel="external">http://tongji.baidu.com/web/welcome/login</a></p>
<h2 id="站内搜索">站内搜索</h2>
<p>百度站长平台包含站内搜索并且还有其他很多功能:<a href="http://zhanzhang.baidu.com/" target="_blank" rel="external">http://zhanzhang.baidu.com/</a></p>
<h2 id="RSS订阅和sitemap">RSS订阅和sitemap</h2>
<p>RSS和sitemap有现成的插件可以很快集成到hexo,安装插件</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">$ npm install hexo-generator-feed</div><div class="line">$ npm install hexo-generator-sitemap</div></pre></td></tr></table></figure>
<p>修改_config.yml,增加以下内容</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line">Plugins:</div><div class="line">- hexo-generator-feed</div><div class="line">- hexo-generator-sitemap</div><div class="line"></div><div class="line"><span class="comment">#Feed Atom</span></div><div class="line">feed:</div><div class="line"> <span class="built_in">type</span>: atom</div><div class="line"> path: atom.xml</div><div class="line"> limit: <span class="number">20</span></div><div class="line"></div><div class="line"><span class="comment">#sitemap</span></div><div class="line">sitemap:</div><div class="line"> path: sitemap.xml</div></pre></td></tr></table></figure>
<p>执行命令 hexo d 能生成下面2个文件即表示成功:<br>xxx/public/atom.xml<br>xxx/public/sitemap.xml</p>
<h2 id="404页面">404页面</h2>
<p>当找不到你的网页时,提供一个友好的404会显得你更加专业。<br>腾讯404公益页面:<a href="http://www.qq.com/404/" target="_blank" rel="external">http://www.qq.com/404/</a></p>
<h2 id="图床">图床</h2>
<p>图床是用来存储你的图片的,你上传一张本地图片,图床会给你生成一个链接,你引用链接即可找到你的图片,有很多免费的图床可用:新浪、七牛。</p>
<h1 id="参考资料">参考资料</h1>
<hr>
<p>[1] <a href="http://cnfeat.com/2014/05/10/2014-05-11-how-to-build-a-blog/" target="_blank" rel="external">如何搭建一个独立博客——简明Github Pages与Hexo教程</a> by cnfeat<br>[2] <a href="http://zipperary.com/categories/hexo/" target="_blank" rel="external">hexo 系列教程</a> by zippera<br>[3] <a href="http://zipperary.com/2013/05/26/ssh-errors-with-github/" target="_blank" rel="external">Git push时重复输入用户名密码的问题</a> by zippera</p>
]]></content>
<breadCrumb title="博客" url="http://dreajay.github.io/categories/%E5%8D%9A%E5%AE%A2/"/>
<breadCrumb title="hexo" url="http://dreajay.github.io/categories/%E5%8D%9A%E5%AE%A2/hexo/"/>
</display>
</data>
</url>
<url>
<loc>http://dreajay.github.io/2014/11/25/%E8%BF%9B%E5%8C%96%EF%BC%9A%E5%B1%8C%E4%B8%9D%E7%9A%84%E4%BA%92%E8%81%94%E7%BD%91%E9%80%86%E8%A2%AD%E4%B9%8B%E8%B7%AF/</loc>
<lastmod>2014-11-25T05:33:33.000Z</lastmod>
<data>
<display>
<title>进化:屌丝的互联网逆袭之路</title>
<pubTime>2014-11-25T05:10:13.000Z</pubTime>
<tag>职业规划 </tag>
<tag>互联网 </tag>
<tag>迷茫 </tag>
<content><![CDATA[<p>这是我在CSDN参加《<a href="http://blog.csdn.net/blogdevteam/article/details/40047403" target="_blank" rel="external">有奖试读&征文——我们在互联网上奋斗的故事</a>》活动写的一篇读后感,并且获奖。</p>
<p>文章内容包括:</p>
<pre><code><span class="bullet">1. </span>书籍介绍
<span class="bullet">2. </span>屌丝的现状
<span class="bullet">3. </span>激情燃烧的岁月-互联网进化
<span class="bullet">4. </span>屌丝逆袭之路进化为互联网高富帅
<span class="bullet">5. </span>后记
<span class="bullet">6. </span>资料推荐
</code></pre><p>原文:<a href="http://blog.csdn.net/dreajay/article/details/40812623" target="_blank" rel="external">进化:屌丝的互联网逆袭之路</a>。</p>
]]></content>
<breadCrumb title="职业规划" url="http://dreajay.github.io/categories/%E8%81%8C%E4%B8%9A%E8%A7%84%E5%88%92/"/>
</display>
</data>
</url>
</urlset>