-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathatom.xml
More file actions
463 lines (274 loc) · 437 KB
/
atom.xml
File metadata and controls
463 lines (274 loc) · 437 KB
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
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>CHILAM</title>
<subtitle>Just Do IT</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="http://chilam.me/"/>
<updated>2018-08-16T11:43:53.022Z</updated>
<id>http://chilam.me/</id>
<author>
<name>CHILAM</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>umi</title>
<link href="http://chilam.me/2018/08/16/umi/"/>
<id>http://chilam.me/2018/08/16/umi/</id>
<published>2018-08-16T11:17:59.000Z</published>
<updated>2018-08-16T11:43:53.022Z</updated>
<content type="html"><![CDATA[<h2 id="umi"><a href="#umi" class="headerlink" title="umi"></a>umi</h2><ul><li><a href="https://umijs.org/guide/" target="_blank" rel="noopener">官网</a></li></ul><h3 id="Hello-umi"><a href="#Hello-umi" class="headerlink" title="Hello umi"></a>Hello umi</h3><ul><li><p>安装npm install -g umi</p></li><li><p>创建应用 mkdir umi-demo && cd umi-demo</p></li><li><p>创建pages目录 mkdir pages</p></li><li><p>创建第一个页面echo ‘export default () => <div>Index Page</div>‘ > pages/index.js</p></li><li><p>启动 umi dev</p></li></ul><h3 id="目录约定"><a href="#目录约定" class="headerlink" title="目录约定"></a>目录约定</h3><p>在文件和目录组织上,umiJS尽量采取约定的方式,唯一的强约定是pages目录</p><h3 id="路由"><a href="#路由" class="headerlink" title="路由"></a>路由</h3><h4 id="基础路由"><a href="#基础路由" class="headerlink" title="基础路由"></a>基础路由</h4><p>假设pages的目录如下:</p><figure class="highlight haml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">+ pages/</span><br><span class="line"> + users/</span><br><span class="line"> -<span class="ruby"> index.js</span></span><br><span class="line"><span class="ruby"> - list.js</span></span><br><span class="line"><span class="ruby"> - index.js</span></span><br></pre></td></tr></table></figure><p>那么umi会自动生成路由</p><figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">[</span><br><span class="line"> { <span class="string">path:</span> <span class="string">'/'</span>: <span class="string">exact:</span> <span class="literal">true</span>, <span class="string">component:</span> <span class="string">'./pages/index.js'</span> },</span><br><span class="line"> { <span class="string">path:</span> <span class="string">'/users/'</span>: <span class="string">exact:</span> <span class="literal">true</span>, <span class="string">component:</span> <span class="string">'./pages/users/index.js'</span> },</span><br><span class="line"> { <span class="string">path:</span> <span class="string">'/users/list'</span>: <span class="string">exact:</span> <span class="literal">true</span>, <span class="string">component:</span> <span class="string">'./pages/users/list.js'</span> },</span><br><span class="line">]</span><br></pre></td></tr></table></figure><h4 id="动态路由"><a href="#动态路由" class="headerlink" title="动态路由"></a>动态路由</h4><p>umi里约定带$前缀的目录或文件为动态路由,例如下面的文件路径:</p><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">+ pages/</span><br><span class="line"> + <span class="variable">$post</span>/</span><br><span class="line"> - index.js</span><br><span class="line"> - comments.js</span><br><span class="line"> + users/</span><br><span class="line"> <span class="variable">$id</span>.js</span><br><span class="line"> - index.js</span><br></pre></td></tr></table></figure><p>会自动生成如下路由配置:</p><figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">[</span><br><span class="line"> { <span class="string">path:</span> <span class="string">'/'</span>: <span class="string">exact:</span> <span class="literal">true</span>, <span class="string">component:</span> <span class="string">'./pages/index.js'</span> },</span><br><span class="line"> { <span class="string">path:</span> <span class="string">'/users/:id'</span>: <span class="string">exact:</span> <span class="literal">true</span>, <span class="string">component:</span> <span class="string">'./pages/users/$id.js'</span> },</span><br><span class="line"> { <span class="string">path:</span> <span class="string">'/:post/'</span>: <span class="string">exact:</span> <span class="literal">true</span>, <span class="string">component:</span> <span class="string">'./pages/$post/index.js'</span> },</span><br><span class="line"> { <span class="string">path:</span> <span class="string">'/:post/comments'</span>: <span class="string">exact:</span> <span class="literal">true</span>, <span class="string">component:</span> <span class="string">'./pages/$post/comments.js'</span> },</span><br><span class="line">]</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
umi
</summary>
<category term="搬砖" scheme="http://chilam.me/categories/%E6%90%AC%E7%A0%96/"/>
<category term="umi" scheme="http://chilam.me/tags/umi/"/>
</entry>
<entry>
<title>dva</title>
<link href="http://chilam.me/2018/08/15/dva/"/>
<id>http://chilam.me/2018/08/15/dva/</id>
<published>2018-08-15T10:39:22.000Z</published>
<updated>2018-08-15T12:28:50.982Z</updated>
<content type="html"><![CDATA[<ul><li><a href="https://dvajs.com/" target="_blank" rel="noopener">官网</a></li></ul><h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>dva 首先是一个基于 redux 和 redux-saga 的数据流方案,然后为了简化开发体验,dva 还额外内置了 react-router 和 fetch,<br>所以也可以理解为一个轻量级的应用框架。</p><h2 id="Hello-DVA"><a href="#Hello-DVA" class="headerlink" title="Hello DVA"></a>Hello DVA</h2><ul><li><p>安装dva脚手架 npm install dva-cli -g</p></li><li><p>创建新项目 dva new dva-demo</p></li><li><p>启动npm start,访问<a href="http://localhost:8000" target="_blank" rel="noopener">http://localhost:8000</a></p></li><li><p>使用antd,npm install antd babel-plugin-import –save</p></li><li><p>编辑 .webpackrc,使 babel-plugin-import 插件生效。</p></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"extraBabelPlugins"</span>: [</span><br><span class="line"> [<span class="string">"import"</span>, { <span class="attr">"libraryName"</span>: <span class="string">"antd"</span>, <span class="attr">"libraryDirectory"</span>: <span class="string">"es"</span>, <span class="attr">"style"</span>: <span class="string">"css"</span> }]</span><br><span class="line"> ]</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>定义路由</li></ul><p>我们要写个应用来先显示产品列表。首先第一步是创建路由,路由可以想象成是组成应用的不同页面。新建src/routes/Production.js</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> react <span class="keyword">from</span> <span class="string">"react"</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> Products = <span class="function">(<span class="params">props</span>) =></span> (</span><br><span class="line"> <h2>List <span class="keyword">of</span> Products<<span class="regexp">/h2></span></span><br><span class="line"><span class="regexp">)</span></span><br><span class="line"><span class="regexp"></span></span><br><span class="line"><span class="regexp">export default Products</span></span><br></pre></td></tr></table></figure><p>添加路由信息到路由表,router.js</p><figure class="highlight livescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> React <span class="keyword">from</span> <span class="string">'react'</span>;</span><br><span class="line"><span class="keyword">import</span> { Router, Route, Switch } <span class="keyword">from</span> <span class="string">'dva/router'</span>;</span><br><span class="line"><span class="keyword">import</span> IndexPage <span class="keyword">from</span> <span class="string">'./routes/IndexPage'</span>;</span><br><span class="line"><span class="keyword">import</span> Products <span class="keyword">from</span> <span class="string">"./routes/Production"</span>;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> RouterConfig({ history }) {</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <Router history={history}></span><br><span class="line"> <Switch></span><br><span class="line"> <Route path=<span class="string">"/"</span> exact component={IndexPage} /></span><br><span class="line"> {<span class="comment">/*新增的路由信息*/</span>}</span><br><span class="line"> <Route path=<span class="string">"/products"</span> exact component={Products} /></span><br><span class="line"> </Switch></span><br><span class="line"> </Router></span><br><span class="line"> );</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> RouterConfig;</span><br></pre></td></tr></table></figure><ul><li>编写UI Component</li></ul><p>新建component/ProductionList.js</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> React <span class="keyword">from</span> <span class="string">"react"</span>;</span><br><span class="line"><span class="keyword">import</span> PropTypes <span class="keyword">from</span> <span class="string">"prop-types"</span>;</span><br><span class="line"><span class="keyword">import</span> {Table,Popconfirm,Button} <span class="keyword">from</span> <span class="string">"antd"</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> ProductList = <span class="function">(<span class="params">{onDelete,products}</span>) =></span> {</span><br><span class="line"> <span class="comment">//定义表格的表头属性</span></span><br><span class="line"> <span class="keyword">const</span> columns = [</span><br><span class="line"> {</span><br><span class="line"> title: <span class="string">"姓名"</span>,</span><br><span class="line"> dataIndex:<span class="string">"name"</span></span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> title: <span class="string">"动作"</span>,</span><br><span class="line"> render:<span class="function">(<span class="params">text,record</span>) =></span>{</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <Popconfirm title=<span class="string">"删除?"</span> onConfirm={()=>onDelete(record.id)} ></span><br><span class="line"> <Button>删除<<span class="regexp">/Button></span></span><br><span class="line"><span class="regexp"> </</span>Popconfirm></span><br><span class="line"> )</span><br><span class="line"> }</span><br><span class="line"> },</span><br><span class="line"> ]</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <Table dataSource={products} columns={columns}/></span><br><span class="line"> )</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//参数验证</span></span><br><span class="line">ProductList.propTypes = {</span><br><span class="line"> onDelete:PropTypes.func.isRequired,</span><br><span class="line"> products:PropTypes.array.isRequired</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> ProductList</span><br></pre></td></tr></table></figure><ul><li>定义Model</li></ul><p>完成UI后,现在开始数据和逻辑,dva通过model的概念把一个领域的模型管理起来,包含同步更新state的reducers,处理异步逻辑的effects,订阅<br>数据源的subscriptions。</p><p>新建model,model/products.js</p><figure class="highlight pf"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">export <span class="keyword">default</span> {</span><br><span class="line"> namespace:'products',</span><br><span class="line"> <span class="keyword">state</span>:[],</span><br><span class="line"> reducers: {</span><br><span class="line"> delete(<span class="keyword">state</span>, {payload: id}) {</span><br><span class="line"> return <span class="keyword">state</span>.filter(item => item.id !== id)</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>在index.js里加载Model</p><figure class="highlight coffeescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">app.model(<span class="built_in">require</span>(<span class="string">'./models/products'</span>).<span class="keyword">default</span>)</span><br></pre></td></tr></table></figure><ul><li>connect起来</li></ul><p>已经完成了model和component,接下来将他们串联起来</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> React <span class="keyword">from</span> <span class="string">"react"</span>;</span><br><span class="line"><span class="keyword">import</span> {connect} <span class="keyword">from</span> <span class="string">"dva"</span>;</span><br><span class="line"><span class="keyword">import</span> ProductionList <span class="keyword">from</span> <span class="string">"../components/ProductionList"</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">//路由页面, 用户发起请求dispatch</span></span><br><span class="line"><span class="keyword">const</span> Products = <span class="function">(<span class="params">{dispatch,products}</span>) =></span> {</span><br><span class="line"></span><br><span class="line"> <span class="comment">//定义用户行为</span></span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">handleDelete</span>(<span class="params">id</span>) </span>{</span><br><span class="line"> dispatch({</span><br><span class="line"> type: <span class="string">'products/delete'</span>,</span><br><span class="line"> payload: id</span><br><span class="line"> })</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <div></span><br><span class="line"> <h2>List Of Productions<<span class="regexp">/h2></span></span><br><span class="line"><span class="regexp"> <ProductionList onDelete={handleDelete} products={products} /</span>></span><br><span class="line"> <<span class="regexp">/div></span></span><br><span class="line"><span class="regexp"> )</span></span><br><span class="line"><span class="regexp"></span></span><br><span class="line"><span class="regexp">}</span></span><br><span class="line"><span class="regexp">/</span><span class="regexp">/将state串联到Products</span></span><br><span class="line"><span class="regexp">export default connect(({products}) => ({products}))(Products)</span></span><br></pre></td></tr></table></figure><ul><li>最后编辑index.js,添加一些数据</li></ul><figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">const app = dva({</span><br><span class="line"><span class="symbol"> initialState:</span>{</span><br><span class="line"><span class="symbol"> products:</span>[</span><br><span class="line"> {<span class="string">name:</span><span class="string">'dva'</span>,<span class="string">id:</span><span class="number">1</span>},</span><br><span class="line"> {<span class="string">name:</span><span class="string">'antd'</span>,<span class="string">id:</span><span class="number">2</span>},</span><br><span class="line"> {<span class="string">name:</span><span class="string">'css'</span>,<span class="string">id:</span><span class="number">3</span>},</span><br><span class="line"> ]</span><br><span class="line"> }</span><br><span class="line">});</span><br></pre></td></tr></table></figure><ul><li>最后执行 npm start就可以看见效果了</li></ul>]]></content>
<summary type="html">
dva
</summary>
<category term="搬砖" scheme="http://chilam.me/categories/%E6%90%AC%E7%A0%96/"/>
<category term="dva" scheme="http://chilam.me/tags/dva/"/>
</entry>
<entry>
<title>redux</title>
<link href="http://chilam.me/2018/08/15/redux/"/>
<id>http://chilam.me/2018/08/15/redux/</id>
<published>2018-08-15T05:35:23.000Z</published>
<updated>2018-08-15T10:35:29.165Z</updated>
<content type="html"><![CDATA[<ul><li><a href="https://redux.js.org/" target="_blank" rel="noopener">Redux</a></li></ul><h2 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h2><p>React只是DOM的一个抽象层,并不是Web应用的完整的解决方案。有2个方面,没有涉及:</p><ul><li>代码结构</li><li>组件之间的通信</li></ul><h3 id="Redux的使用场景"><a href="#Redux的使用场景" class="headerlink" title="Redux的使用场景"></a>Redux的使用场景</h3><ul><li>用户的使用方式复杂</li><li>不同的身份的用户有不同的使用方式</li><li>多个用户之间可以协作</li><li>与服务器之前大量交互,或者使用websocket</li><li>View要从多个地方获取数据源</li><li>多交互,多数据源</li></ul><p>从组件的角度看,如果应用有以下场景,可以考虑使用Redux</p><ul><li>某个组件的状态需要共享</li><li>某个状态需要任何地方都可以拿到</li><li>一个组件需要改变全局状态</li><li>一个组件需要更改另一个组件的状态</li></ul><h3 id="设计思想"><a href="#设计思想" class="headerlink" title="设计思想"></a>设计思想</h3><ul><li>web应用是一个状态机,视图与状态一一对应</li><li>所以的状态,保存在一个对象里</li></ul><h3 id="基本概念和API"><a href="#基本概念和API" class="headerlink" title="基本概念和API"></a>基本概念和API</h3><h4 id="Store"><a href="#Store" class="headerlink" title="Store"></a>Store</h4><p>Store 就是保存数据的地方,你可以把它看成一个容器。整个应用只能有一个 Store。</p><p>Redux 提供createStore这个函数,用来生成 Store。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> { createStore } <span class="keyword">from</span> <span class="string">'redux'</span>;</span><br><span class="line"><span class="keyword">const</span> store = createStore(fn);</span><br></pre></td></tr></table></figure><h4 id="State"><a href="#State" class="headerlink" title="State"></a>State</h4><p>Store包含所有的数据。如果想得到某个时点的数据,就要对Store生成快照,这种数据就叫做State。</p><figure class="highlight pf"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">import { createStore } <span class="keyword">from</span> 'redux';</span><br><span class="line">const store = createStore(fn);</span><br><span class="line"></span><br><span class="line">const <span class="keyword">state</span> = store.getState();</span><br></pre></td></tr></table></figure><p>Redux 规定, 一个 State 对应一个 View。只要 State 相同,View 就相同。</p><h4 id="Action"><a href="#Action" class="headerlink" title="Action"></a>Action</h4><p>State的变化会导致View的变化,但是用户接触不到State,只能接触到View.Action就是View发出的通知,表示State发生变化了<br>Action是一个对象,其中type属性是必须的,表示Action的名称。其他属性可以自由设置</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> action = {</span><br><span class="line"> <span class="keyword">type</span>:<span class="string">'ADD_TODO'</span>,</span><br><span class="line"> payload:<span class="string">'learn Redux'</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>上面的代码就是Action的名称是ADD_TODO,携带的信息就是字符串 learn Redux</p><h4 id="Action-Creator"><a href="#Action-Creator" class="headerlink" title="Action Creator"></a>Action Creator</h4><p>View 要发送多少种消息,就会有多少种 Action。如果都手写,会很麻烦。可以定义一个函数来生成 Action,这个函数就叫 Action Creator。</p><figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> ADD_TODO = <span class="string">'添加 TODO'</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">addTodo</span><span class="params">(text)</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> type: ADD_TODO,</span><br><span class="line"> text</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> action = addTodo(<span class="string">'Learn Redux'</span>);</span><br></pre></td></tr></table></figure><h4 id="store-dispatch"><a href="#store-dispatch" class="headerlink" title="store.dispatch()"></a>store.dispatch()</h4><p>是view发出Action的唯一方法</p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> { createStore } <span class="keyword">from</span> <span class="string">'redux'</span>;</span><br><span class="line"><span class="keyword">const</span> store = createStore(fn);</span><br><span class="line"></span><br><span class="line">store.dispatch({</span><br><span class="line"> <span class="keyword">type</span>: <span class="string">'ADD_TODO'</span>,</span><br><span class="line"> payload: <span class="string">'Learn Redux'</span></span><br><span class="line">});</span><br></pre></td></tr></table></figure><p>上面代码中,store.dispatch接受一个 Action 对象作为参数,将它发送出去。</p><h3 id="Reducer"><a href="#Reducer" class="headerlink" title="Reducer"></a>Reducer</h3><p>store收到Action后,必须给出一个新的state,这样view才会发生变化,这个state的计算过程就是reducer.<br>reducer是一个函数,接受当前action和当前state作为参数,返回一个新的state</p><figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> reducer = <span class="function"><span class="keyword">function</span> <span class="params">(state,action)</span></span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> new_state</span><br><span class="line">}</span><br></pre></td></tr></table></figure><figure class="highlight pf"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">const <span class="keyword">default</span>State = <span class="number">0</span>;</span><br><span class="line">const reducer = (<span class="keyword">state</span> = <span class="keyword">default</span>State, action) => {</span><br><span class="line"> switch (action.type) {</span><br><span class="line"> case 'ADD':</span><br><span class="line"> return <span class="keyword">state</span> + action.payload;</span><br><span class="line"> <span class="keyword">default</span>: </span><br><span class="line"> return <span class="keyword">state</span>;</span><br><span class="line"> }</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line">const <span class="keyword">state</span> = reducer(<span class="number">1</span>, {</span><br><span class="line"> type: 'ADD',</span><br><span class="line"> payload: <span class="number">2</span></span><br><span class="line">});</span><br></pre></td></tr></table></figure><h4 id="store-subscribe"><a href="#store-subscribe" class="headerlink" title="store.subscribe()"></a>store.subscribe()</h4><p>Store 允许使用store.subscribe方法设置监听函数,一旦 State 发生变化,就自动执行这个函数。</p><h2 id="React-Redux"><a href="#React-Redux" class="headerlink" title="React-Redux"></a>React-Redux</h2><p>React-Redux将所有组件分成2大类,UI组件和容器组件</p><h3 id="UI组件的特征"><a href="#UI组件的特征" class="headerlink" title="UI组件的特征"></a>UI组件的特征</h3><ul><li>只负责UI的呈现,不带有任何的业务</li><li>没有状态即不使用this.state</li><li>所有数据都由参数this.props提供</li><li>不使用redux的任何API</li></ul><h3 id="容器组件"><a href="#容器组件" class="headerlink" title="容器组件"></a>容器组件</h3><ul><li>负责管理数据和业务逻辑,不负责UI的呈现</li><li>带有内部状态</li><li>使用Redux的API</li></ul><p>React-Redux 规定,所有的 UI 组件都由用户提供,容器组件则是由 React-Redux 自动生成</p><h3 id="connect"><a href="#connect" class="headerlink" title="connect()"></a>connect()</h3><p>React-Redux 提供connect方法,用于从 UI 组件生成容器组件。connect的意思,就是将这两种组件连起来。</p><figure class="highlight arduino"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> { <span class="built_in">connect</span> } from <span class="string">'react-redux'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> VisibleTodoList = <span class="built_in">connect</span>(</span><br><span class="line"> mapStateToProps,</span><br><span class="line"> mapDispatchToProps</span><br><span class="line">)(TodoList)</span><br></pre></td></tr></table></figure><ul><li>mapStateToProps,负责输入逻辑,即将state映射到 UI 组件的参数(props)</li><li>mapDispatchToProps,输出逻辑,即将用户对 UI 组件的操作映射成 Action</li></ul><h4 id="mapStateToProps"><a href="#mapStateToProps" class="headerlink" title="mapStateToProps()"></a>mapStateToProps()</h4><p>mapStateToProps是一个函数。它的作用就是像它的名字那样,建立一个从(外部的)state对象到(UI 组件的)props对象的映射关系。</p><p>作为函数,mapStateToProps执行后应该返回一个对象,里面的每一个键值对就是一个映射。请看下面的例子。</p><figure class="highlight pf"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">const mapStateToProps = (<span class="keyword">state</span>) => {</span><br><span class="line"> return {</span><br><span class="line"> todos: getVisibleTodos(<span class="keyword">state</span>.todos, <span class="keyword">state</span>.visibilityFilter)</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="mapDispatchToProps"><a href="#mapDispatchToProps" class="headerlink" title="mapDispatchToProps()"></a>mapDispatchToProps()</h4><p>用来建立 UI 组件的参数到store.dispatch方法的映射。也就是说,<br>它定义了哪些用户的操作应该当作 Action,传给 Store。它可以是一个函数,也可以是一个对象。</p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> mapDispatchToProps = (</span><br><span class="line"> dispatch,</span><br><span class="line"> ownProps</span><br><span class="line">) => {</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> onClick: <span class="function"><span class="params">()</span> =></span> {</span><br><span class="line"> dispatch({</span><br><span class="line"> <span class="keyword">type</span>: <span class="string">'SET_VISIBILITY_FILTER'</span>,</span><br><span class="line"> filter: ownProps.filter</span><br><span class="line"> });</span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
redux
</summary>
<category term="搬砖" scheme="http://chilam.me/categories/%E6%90%AC%E7%A0%96/"/>
<category term="redux" scheme="http://chilam.me/tags/redux/"/>
</entry>
<entry>
<title>前端路由的实现原理-history,hash</title>
<link href="http://chilam.me/2018/08/15/router-history-hash/"/>
<id>http://chilam.me/2018/08/15/router-history-hash/</id>
<published>2018-08-15T02:09:25.000Z</published>
<updated>2018-08-15T02:57:33.135Z</updated>
<content type="html"><![CDATA[<h2 id="什么是路由"><a href="#什么是路由" class="headerlink" title="什么是路由"></a>什么是路由</h2><p>简单说明,假如有一台提供 Web 服务的服务器的网络地址是:10.0.0.1,而该 Web 服务又提供了三个可供用户访问的页面,其页面 URI 分别是:</p><ul><li><a href="http://10.0.0.1/" target="_blank" rel="noopener">http://10.0.0.1/</a></li><li><a href="http://10.0.0.1/about" target="_blank" rel="noopener">http://10.0.0.1/about</a></li><li><a href="http://10.0.0.1/concat" target="_blank" rel="noopener">http://10.0.0.1/concat</a></li></ul><p>那么其路径就分别是 /,/about,/concat。</p><p>当用户使用 <a href="http://10.0.0.1/about" target="_blank" rel="noopener">http://10.0.0.1/about</a> 来访问该页面时,Web 服务会接收到这个请求,然后会解析 URL 中的路径 /about,在 Web 服务的程序中,<br>该路径对应着相应的处理逻辑,程序会把请求交给路径所对应的处理逻辑,这样就完成了一次「路由分发」,这个分发就是通过「路由」来完成的。</p><p>简单的说,路由是根据不同的 url 地址展示不同的内容或页面</p><p>早期的路由都是后端实现,访问url通过后端Servlet的来返回页面,页面越来越复杂服务端的压力也越来越大,随着ajax的出现,页面可以不刷新就可以<br>获取到数据,就给前端路由的出现奠定了基础,我们可以通过URL来记录ajax的变化,从而实现前端路由。</p><p>在使用location.href,a标签的href方式,进行页面访问的时候,页面会刷新,但随着大前端的时代的到来,产生异步单页来提高性能,不再希望每次的<br>跳转都带来页面的刷新,而是仅仅希望这种跳转引起数据变化,从而改变视图。</p><h2 id="Hash"><a href="#Hash" class="headerlink" title="Hash"></a>Hash</h2><p>在 HTML5 的 history API 出现之前,前端的路由都是通过 hash 来实现的,hash 能兼容低版本的浏览器。<br>如果我们把上面例子中提到的 3 个页面用 hash 来实现的话,它的 URI 规则中需要带上 #。</p><ul><li><a href="http://10.0.0.1/" target="_blank" rel="noopener">http://10.0.0.1/</a></li><li><a href="http://10.0.0.1/#/about" target="_blank" rel="noopener">http://10.0.0.1/#/about</a></li><li><a href="http://10.0.0.1/#/concat" target="_blank" rel="noopener">http://10.0.0.1/#/concat</a></li></ul><p>Web 服务并不会解析 hash,也就是说 # 后的内容 Web 服务都会自动忽略,但是 JavaScript 是可以通过 window.location.hash 读取到的,<br>读取到路径加以解析之后就可以响应不同路径的逻辑处理。</p><h2 id="History-API"><a href="#History-API" class="headerlink" title="History-API"></a>History-API</h2><p>window.history是用来保存用户在一个会话期间的网站访问记录,并提供相应的方法进行追溯。对应其成员如下:</p><ul><li>方法:back(),forward(),go(num),pushState(stateData,title,url),replaceState(stateData,title,url)</li><li>属性:length,state</li><li>事件:window.onpopstate</li></ul><h3 id="方法说明"><a href="#方法说明" class="headerlink" title="方法说明"></a>方法说明</h3><ul><li>back()回到上一个访问记录</li><li>forward()前进到下一个访问记录</li><li>go(num)跳转到相应的访问记录,其中num>0则前进,num<0则后退</li><li>pushState()在history中创建一个新的访问记录,不能跨域,且不能造成页面刷新</li><li>replaceState()修改当前的访问记录,不能跨域,且不能造成页面刷新</li></ul><p>重点说其中的两个新增的API history.pushState 和 history.replaceState,这两个 API 都接收三个参数,分别是</p><ul><li><p>状态对象(state object) — 一个JavaScript对象,与用pushState()方法创建的新历史记录条目关联。<br>无论何时用户导航到新创建的状态,popstate事件都会被触发,并且事件对象的state属性都包含历史记录条目的状态对象的拷贝。</p></li><li><p>标题(title) — FireFox浏览器目前会忽略该参数,虽然以后可能会用上。考虑到未来可能会对该方法进行修改,传一个空字符串会比较安全。<br>或者,你也可以传入一个简短的标题,标明将要进入的状态。</p></li><li><p>地址(URL) — 新的历史记录条目的地址。该参数是可选的;不指定的话则为文档当前URL。</p></li></ul><h3 id="关于的pushState的例子"><a href="#关于的pushState的例子" class="headerlink" title="关于的pushState的例子"></a>关于的pushState的例子</h3><figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="number">1.</span>打开浏览器,访问www.baidu.com,然后F2打开控制台,输入下面语句,观察浏览器地址栏变化:</span><br><span class="line"></span><br><span class="line"><span class="number">2.</span><span class="built_in">window</span>.history.pushState(<span class="keyword">null</span>,<span class="keyword">null</span>,<span class="string">'https://www.baidu.com/?name=pear'</span>);浏览器地址框https:<span class="comment">//www.baidu.com/?name=pear</span></span><br><span class="line"></span><br><span class="line"><span class="number">3.</span><span class="built_in">window</span>.history.pushState(<span class="keyword">null</span>,<span class="keyword">null</span>,<span class="string">'https://www.baidu.com/name/pear'</span>);浏览器地址框https:<span class="comment">//www.baidu.com/name/pear</span></span><br><span class="line"></span><br><span class="line"><span class="number">4.</span><span class="built_in">window</span>.history.pushState(<span class="keyword">null</span>,<span class="keyword">null</span>,<span class="string">'?name=pear'</span>);地址栏https:<span class="comment">//www.baidu.com/name/pear?name=pear</span></span><br></pre></td></tr></table></figure><p>注意:这里的 url 不支持跨域,当我们把 <a href="http://www.baidu.com" target="_blank" rel="noopener">www.baidu.com</a> 换成 baidu.com 时就会报错。<br>回到上面例子中,每次改变 url 页面并没有刷新,同样根据上文所述,浏览器会产生历史记录,最后Ctrl+h 查看浏览器历史记录。</p><h3 id="浏览器history的变化与浏览器行为"><a href="#浏览器history的变化与浏览器行为" class="headerlink" title="浏览器history的变化与浏览器行为"></a>浏览器history的变化与浏览器行为</h3><p><img src="http://orkt468tj.bkt.clouddn.com/18-8-15/33289275.jpg" alt=""></p><ul><li>如图所示,展示了长度为4的history的栈,在不同的操作方法下的变化情况</li><li>step1-step4,均为history的方法,获取相应的历史记录中的url</li><li>step5通过location.href创建一个新的url记录,其将当前url2之后的记录清空,并在后其新增url5,history长度由4变为3,history的新增操作,<br>都会将其后记录清空,在其后面新增记录。</li><li>step6通过pushState方法新建一个url记录,其也是清空,再新增记录</li><li>step8通过replaceState方法修改一个url记录,不会产生新记录,而是将当前记录进行修改</li><li>值得注意的是,通过pushState新增或者修改的history记录,被访问时,当前页面不刷新。而locaiton.href生成的记录被访问时,页面将进行刷新。</li></ul>]]></content>
<summary type="html">
前端路由的实现原理-history,hash
</summary>
<category term="搬砖" scheme="http://chilam.me/categories/%E6%90%AC%E7%A0%96/"/>
<category term="html" scheme="http://chilam.me/tags/html/"/>
</entry>
<entry>
<title>react-router</title>
<link href="http://chilam.me/2018/08/14/react-router/"/>
<id>http://chilam.me/2018/08/14/react-router/</id>
<published>2018-08-14T09:15:37.000Z</published>
<updated>2018-08-15T03:50:36.245Z</updated>
<content type="html"><![CDATA[<h2 id="Hello-React-Router"><a href="#Hello-React-Router" class="headerlink" title="Hello React-Router"></a>Hello React-Router</h2><ul><li>安装创建react的脚手架</li></ul><figure class="highlight dsconfig"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">sudo </span><span class="string">npm </span><span class="string">install </span><span class="built_in">create-react-app</span> -g</span><br></pre></td></tr></table></figure><ul><li>使用脚手架创建router-demo</li></ul><figure class="highlight dsconfig"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">create-react-app</span> <span class="string">router-demo</span></span><br></pre></td></tr></table></figure><ul><li>安装router的依赖</li></ul><figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm <span class="keyword">install</span> react-router-dom</span><br></pre></td></tr></table></figure><ul><li>新建AppHome.js</li></ul><figure class="highlight dust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br></pre></td><td class="code"><pre><span class="line"><span class="xml">import React from "react";</span></span><br><span class="line"><span class="xml">import </span><span class="template-variable">{BrowserRouter as Router,Route,Link}</span><span class="xml"> from "react-router-dom";</span></span><br><span class="line"><span class="xml"></span></span><br><span class="line"><span class="xml">//Home组件</span></span><br><span class="line"><span class="xml">const Home = () => (</span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">div</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">h2</span>></span>Home<span class="tag"></<span class="name">h2</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"><span class="xml">)</span></span><br><span class="line"><span class="xml"></span></span><br><span class="line"><span class="xml">//About组件</span></span><br><span class="line"><span class="xml">const About = () => (</span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">div</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">h2</span>></span>About<span class="tag"></<span class="name">h2</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"><span class="xml">)</span></span><br><span class="line"><span class="xml"></span></span><br><span class="line"><span class="xml">//Topic组件</span></span><br><span class="line"><span class="xml">const Topic = (</span><span class="template-variable">{match}</span><span class="xml">) => (</span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">div</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">h3</span>></span></span><span class="template-variable">{match.params.topicId}</span><span class="xml"><span class="tag"></<span class="name">h3</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"><span class="xml">)</span></span><br><span class="line"><span class="xml"></span></span><br><span class="line"><span class="xml">//Topics组件</span></span><br><span class="line"><span class="xml">const Topics = (</span><span class="template-variable">{match}</span><span class="xml">) => (</span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">div</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">h2</span>></span>Topics<span class="tag"></<span class="name">h2</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">ul</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">li</span>></span><span class="tag"><<span class="name">Link</span> <span class="attr">to</span>=</span></span><span class="template-variable">{`${match.url}</span><span class="xml"><span class="tag">/<span class="attr">rendering</span>`}></span>Rendering with React<span class="tag"></<span class="name">Link</span>></span><span class="tag"></<span class="name">li</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">li</span>></span><span class="tag"><<span class="name">Link</span> <span class="attr">to</span>=</span></span><span class="template-variable">{`${match.url}</span><span class="xml"><span class="tag">/<span class="attr">components</span>`}></span>Components<span class="tag"></<span class="name">Link</span>></span><span class="tag"></<span class="name">li</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">li</span>></span><span class="tag"><<span class="name">Link</span> <span class="attr">to</span>=</span></span><span class="template-variable">{`${match.url}</span><span class="xml"><span class="tag">/<span class="attr">props-v-state</span>`}></span>props-v-state<span class="tag"></<span class="name">Link</span>></span><span class="tag"></<span class="name">li</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"></<span class="name">ul</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">Route</span> <span class="attr">path</span>=</span></span><span class="template-variable">{`${match.path}</span><span class="xml"><span class="tag">/<span class="attr">:topicId</span>`} <span class="attr">component</span>=</span></span><span class="template-variable">{Topic}</span><span class="xml"><span class="tag">/></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">Route</span> <span class="attr">exact</span> <span class="attr">path</span>=</span></span><span class="template-variable">{match.path}</span><span class="xml"><span class="tag"> <span class="attr">render</span>=</span></span><span class="template-variable">{()=>(</span></span><br><span class="line"><span class="template-variable"> <h3>please <span class="keyword">select</span> a topic!!!</h3></span></span><br><span class="line"><span class="template-variable"> )}</span><span class="xml">><span class="tag"></<span class="name">Route</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"><span class="xml">)</span></span><br><span class="line"><span class="xml"></span></span><br><span class="line"><span class="xml">const AppHome = () => (</span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">Router</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">div</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">ul</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">li</span>></span><span class="tag"><<span class="name">Link</span> <span class="attr">to</span>=<span class="string">"/"</span>></span>Home<span class="tag"></<span class="name">Link</span>></span><span class="tag"></<span class="name">li</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">li</span>></span><span class="tag"><<span class="name">Link</span> <span class="attr">to</span>=<span class="string">"/about"</span>></span>About<span class="tag"></<span class="name">Link</span>></span><span class="tag"></<span class="name">li</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">li</span>></span><span class="tag"><<span class="name">Link</span> <span class="attr">to</span>=<span class="string">"/topics"</span>></span>Topics<span class="tag"></<span class="name">Link</span>></span><span class="tag"></<span class="name">li</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"></<span class="name">ul</span>></span></span></span><br><span class="line"><span class="xml"></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">hr</span>/></span></span></span><br><span class="line"><span class="xml"></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">Route</span> <span class="attr">exact</span> <span class="attr">path</span>=<span class="string">"/"</span> <span class="attr">component</span>=</span></span><span class="template-variable">{Home}</span><span class="xml"><span class="tag">/></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">Route</span> <span class="attr">path</span>=<span class="string">"/about"</span> <span class="attr">component</span>=</span></span><span class="template-variable">{About}</span><span class="xml"><span class="tag">/></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">Route</span> <span class="attr">path</span>=<span class="string">"/topics"</span> <span class="attr">component</span>=</span></span><span class="template-variable">{Topics}</span><span class="xml"><span class="tag">/></span></span></span><br><span class="line"><span class="xml"> <span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"></<span class="name">Router</span>></span></span></span><br><span class="line"><span class="xml">)</span></span><br><span class="line"><span class="xml"></span></span><br><span class="line"><span class="xml">export default AppHome</span></span><br></pre></td></tr></table></figure><ul><li>编辑index.js引用AppHome.js</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> React <span class="keyword">from</span> <span class="string">'react'</span>;</span><br><span class="line"><span class="keyword">import</span> ReactDOM <span class="keyword">from</span> <span class="string">'react-dom'</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="string">'./index.css'</span>;</span><br><span class="line"><span class="keyword">import</span> registerServiceWorker <span class="keyword">from</span> <span class="string">'./registerServiceWorker'</span>;</span><br><span class="line"><span class="keyword">import</span> AppHome <span class="keyword">from</span> <span class="string">"./AppHome"</span>;</span><br><span class="line"></span><br><span class="line">ReactDOM.render(<span class="xml"><span class="tag"><<span class="name">AppHome</span>/></span></span>, <span class="built_in">document</span>.getElementById(<span class="string">'root'</span>));</span><br><span class="line">registerServiceWorker();</span><br></pre></td></tr></table></figure><ul><li>启动npm start</li></ul><p><a href="https://gitee.com/maxp/router-demo" target="_blank" rel="noopener">源码地址</a></p><h2 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h2><h3 id="路由器Router"><a href="#路由器Router" class="headerlink" title="路由器Router"></a>路由器Router</h3><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">对于网页项目,存在<span class="tag"><<span class="name">BrowserRouter</span>></span>和<span class="tag"><<span class="name">HashRouter</span>></span>2种组件。</span><br><span class="line">当存在服务来管理动态请求的时候需要使用<span class="tag"><<span class="name">BroswerRouter</span>></span>组件,而<span class="tag"><<span class="name">HashRouter</span>></span></span><br><span class="line">组件被用于静态网站。</span><br></pre></td></tr></table></figure><h4 id="History"><a href="#History" class="headerlink" title="History"></a>History</h4><p>每个路由器都会创建一个history对象并用其保持追踪当前location并且在有变化的时候对网站进行重新的渲染。history对象保证了React-Router提供<br>的其他组件的可用性,所以其他组件必须在Router组件内部渲染。</p><h4 id="渲染Router"><a href="#渲染Router" class="headerlink" title="渲染Router"></a>渲染Router</h4><p>路由器组件无法接受两个及以上的子元素。基于这种限制的存在,创建一个App组件来渲染应用其余部分是一个有效的方法<br>(对于服务端渲染,将应用从router组件中分离也是重要的)。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> { BrowserRouter } <span class="keyword">from</span> <span class="string">'react-router-dom'</span></span><br><span class="line">ReactDOM.render((</span><br><span class="line"> <BrowserRouter></span><br><span class="line"> <App /></span><br><span class="line"> <<span class="regexp">/BrowserRouter></span></span><br><span class="line"><span class="regexp">), document.getElementById('root'))</span></span><br></pre></td></tr></table></figure><h4 id="App组件"><a href="#App组件" class="headerlink" title="App组件"></a>App组件</h4><p>应用通过App组件定义。简化一下,我们将应用拆分成两个部分。<header>组件包含网站的导航链接。<main>组件则呈现其余内容。</main></header></p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> App = <span class="function"><span class="params">()</span> =></span> (</span><br><span class="line"> <div></span><br><span class="line"> <Header /></span><br><span class="line"> <Main /></span><br><span class="line"> <<span class="regexp">/div></span></span><br><span class="line"><span class="regexp">)</span></span><br></pre></td></tr></table></figure><h3 id="路由Route"><a href="#路由Route" class="headerlink" title="路由Route"></a>路由Route</h3><p>Route组件是React-Router中主要的结构单元,在任意位置只要匹配了URL路径名(pathname)就可以创建Route元素进行渲染。</p><h4 id="路径Path"><a href="#路径Path" class="headerlink" title="路径Path"></a>路径Path</h4><p>Route接受一个数为string类型的path,该值路由匹配的路径名的类型。</p><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><Route <span class="built_in">path</span>=<span class="string">'/roster'</span>/></span><br><span class="line">// 当路径名为<span class="string">'/'</span>时, <span class="built_in">path</span>不匹配</span><br><span class="line">// 当路径名为<span class="string">'/roster'</span>或<span class="string">'/roster/2'</span>时, <span class="built_in">path</span>匹配</span><br><span class="line">// 当你只想匹配<span class="string">'/roster'</span>时,你需要使用<span class="string">"exact"</span>参数</span><br><span class="line">// 则路由仅匹配<span class="string">'/roster'</span>而不会匹配<span class="string">'/roster/2'</span></span><br><span class="line"><Route exact <span class="built_in">path</span>=<span class="string">'/roster'</span>/></span><br></pre></td></tr></table></figure><p>注意:在匹配路由时,React Router只关注location的路径名。当URL如下时:</p><figure class="highlight livecodeserver"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">http</span>://www.example.com/my-projects/<span class="literal">one</span>?extra=<span class="literal">false</span></span><br></pre></td></tr></table></figure><ul><li>React Router去匹配的只是’/my-projects/one’这一部分。</li></ul><h4 id="Switch"><a href="#Switch" class="headerlink" title="Switch"></a>Switch</h4><p>可以在路由器(router)组件中的任意位置创建多个Route,但通常我们会把它们放在同一个位置。使用Switch组件来包裹一组Route。<br>Switch会遍历自身的子元素(即路由)并对第一个匹配当前路径的元素进行渲染。</p><p>假设,网站希望匹配以下路径:</p><ul><li><p>/ : 主页</p></li><li><p>/roster : 团体列表</p></li><li><p>/roster/:number :运动员页面,使用运动员的编号作为标识</p></li><li><p>/schedule :团队的赛程表</p></li></ul><figure class="highlight dust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="xml"><span class="tag"><<span class="name">Switch</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">Route</span> <span class="attr">exact</span> <span class="attr">path</span>=<span class="string">'/'</span> <span class="attr">component</span>=</span></span><span class="template-variable">{Home}</span><span class="xml"><span class="tag">/></span></span></span><br><span class="line"><span class="xml"> </span><span class="template-tag">{/* <span class="name">both</span> /roster and /roster/:number begin with /roster */}</span><span class="xml"></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">Route</span> <span class="attr">path</span>=<span class="string">'/roster'</span> <span class="attr">component</span>=</span></span><span class="template-variable">{Roster}</span><span class="xml"><span class="tag">/></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">Route</span> <span class="attr">path</span>=<span class="string">'/schedule'</span> <span class="attr">component</span>=</span></span><span class="template-variable">{Schedule}</span><span class="xml"><span class="tag">/></span></span></span><br><span class="line"><span class="xml"><span class="tag"></<span class="name">Switch</span>></span></span></span><br></pre></td></tr></table></figure><h4 id="Route如何渲染"><a href="#Route如何渲染" class="headerlink" title="Route如何渲染"></a>Route如何渲染</h4><p>当一个路由的path匹配成功后,路由用来确定渲染结果的参数有三种。只需要提供其中一个即可。</p><ul><li><p>component:一个React组件。当带有component参数的route匹配成功后,route会返回一个新的元素,其为component参数所对应的React组件</p></li><li><p>render:一个返回React element的函数。当匹配成功后调用该函数。该过程与传入component参数类似,并且对于行级渲染与需要向元素传入额外参数的操作会更有用。</p></li><li><p>children : 一个返回React element的函数。与上述两个参数不同,无论route是否匹配当前location,其都会被渲染。</p></li></ul><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">Route</span> <span class="attr">path</span>=<span class="string">'/page'</span> <span class="attr">component</span>=<span class="string">{Page}</span> /></span></span><br><span class="line">const extraProps = { color: 'red' }</span><br><span class="line"><span class="tag"><<span class="name">Route</span> <span class="attr">path</span>=<span class="string">'/page'</span> <span class="attr">render</span>=<span class="string">{(props)</span> =></span> (</span><br><span class="line"> <span class="tag"><<span class="name">Page</span> {<span class="attr">...props</span>} <span class="attr">data</span>=<span class="string">{extraProps}/</span>></span></span><br><span class="line">)}/></span><br><span class="line"><span class="tag"><<span class="name">Route</span> <span class="attr">path</span>=<span class="string">'/page'</span> <span class="attr">children</span>=<span class="string">{(props)</span> =></span> (</span><br><span class="line"> props.match</span><br><span class="line"> ? <span class="tag"><<span class="name">Page</span> {<span class="attr">...props</span>}/></span></span><br><span class="line"> : <span class="tag"><<span class="name">EmptyPage</span> {<span class="attr">...props</span>}/></span></span><br><span class="line">)}/></span><br></pre></td></tr></table></figure><p>通常component参数与render参数被更经常地使用。children参数偶尔会被使用,它更常用在path无法匹配时呈现的’空’状态。</p><p>通过Route渲染的元素会被传入一些参数。分别是match对象,当前location对象以及history对象(由router创建)</p><h3 id="Main组件"><a href="#Main组件" class="headerlink" title="Main组件"></a>Main组件</h3><p>现在我们清楚了根路由的结构,我们需要实际渲染我们的路由。对于这个应用,我们将会在Main组件中渲染Switch与Route,<br>这一过程会将route匹配生成的HTML放在main节点中。</p><figure class="highlight dust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="xml">import </span><span class="template-variable">{ Switch, Route }</span><span class="xml"> from 'react-router-dom'</span></span><br><span class="line"><span class="xml">const Main = () => (</span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">main</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">Switch</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">Route</span> <span class="attr">exact</span> <span class="attr">path</span>=<span class="string">'/'</span> <span class="attr">component</span>=</span></span><span class="template-variable">{Home}</span><span class="xml"><span class="tag">/></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">Route</span> <span class="attr">path</span>=<span class="string">'/roster'</span> <span class="attr">component</span>=</span></span><span class="template-variable">{Roster}</span><span class="xml"><span class="tag">/></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">Route</span> <span class="attr">path</span>=<span class="string">'/schedule'</span> <span class="attr">component</span>=</span></span><span class="template-variable">{Schedule}</span><span class="xml"><span class="tag">/></span></span></span><br><span class="line"><span class="xml"> <span class="tag"></<span class="name">Switch</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"></<span class="name">main</span>></span></span></span><br><span class="line"><span class="xml">)</span></span><br></pre></td></tr></table></figure><h4 id="嵌套路由"><a href="#嵌套路由" class="headerlink" title="嵌套路由"></a>嵌套路由</h4><p>运动员路由/roster/:number并未包含在上述Switch中。它由Roster组件负责在路径包含’/roster’的情形下进行渲染。</p><p>在<roster>组件中,我们将为两种路径进行渲染:</roster></p><ul><li>/roster :对应路径名仅仅是/roster时,因此需要在exact元素上添加exact参数。</li><li>/roster/:number : 该路由使用一个路由参数来获取/roster后的路径名。</li></ul><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">const Roster = () => (</span><br><span class="line"> <span class="tag"><<span class="name">div</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">h2</span>></span>This is a roster page!<span class="tag"></<span class="name">h2</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">Switch</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">Route</span> <span class="attr">exact</span> <span class="attr">path</span>=<span class="string">'/roster'</span> <span class="attr">component</span>=<span class="string">{FullRoster}/</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">Route</span> <span class="attr">path</span>=<span class="string">'/roster/:number'</span> <span class="attr">component</span>=<span class="string">{Player}/</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">Switch</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">div</span>></span></span><br><span class="line">)</span><br></pre></td></tr></table></figure><h4 id="路径参数"><a href="#路径参数" class="headerlink" title="路径参数"></a>路径参数</h4><p>有时路径名中存在我们需要获取的参数。例如,在运动员界面,我们需要获取运动员的编号。我们可以向route的路径字符串中添加path参数</p><p>如’/roster/:number’中:number这种写法意味着/roster/后的路径名将会被获取并存在match.params.number中。例如,路径名’/roster/6’会获取到一个对象:</p><figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{ <span class="string">number:</span> <span class="string">'6'</span> } <span class="comment">// 注获取的值是字符串类型的</span></span><br></pre></td></tr></table></figure><p>Player组件可以使用props.match.params对象来确定需要被渲染的运动员的数据。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 返回运动员对象的API</span></span><br><span class="line"><span class="keyword">import</span> PlayerAPI <span class="keyword">from</span> <span class="string">'./PlayerAPI'</span></span><br><span class="line"><span class="keyword">const</span> Player = <span class="function">(<span class="params">props</span>) =></span> {</span><br><span class="line"> <span class="keyword">const</span> player = PlayerAPI.get(</span><br><span class="line"> <span class="built_in">parseInt</span>(props.match.params.number, <span class="number">10</span>)</span><br><span class="line"> )</span><br><span class="line"> <span class="keyword">if</span> (!player) {</span><br><span class="line"> <span class="keyword">return</span> <span class="xml"><span class="tag"><<span class="name">div</span>></span>Sorry, but the player was not found<span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <div></span><br><span class="line"> <h1>{player.name} (#{player.number})</h1></span><br><span class="line"> <h2>{player.position}<<span class="regexp">/h2></span></span><br><span class="line"><span class="regexp"> </</span>div></span><br><span class="line">)</span><br></pre></td></tr></table></figure><h3 id="Link"><a href="#Link" class="headerlink" title="Link"></a>Link</h3><p>现在,我们应用需要在各个页面间切换。如果使用锚点元素(就是)实现,在每次点击时页面将被重新加载。<br>React Router提供了Link组件用来避免这种状况的发生。当你点击Link时,URL会更新,组件会被重新渲染,但是页面不会重新加载。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> { Link } <span class="keyword">from</span> <span class="string">'react-router-dom'</span></span><br><span class="line"><span class="keyword">const</span> Header = <span class="function"><span class="params">()</span> =></span> (</span><br><span class="line"> <header></span><br><span class="line"> <nav></span><br><span class="line"> <ul></span><br><span class="line"> <li><span class="xml"><span class="tag"><<span class="name">Link</span> <span class="attr">to</span>=<span class="string">'/'</span>></span>Home<span class="tag"></<span class="name">Link</span>></span></span><span class="xml"><span class="tag"></<span class="name">li</span>></span></span></span><br><span class="line"> <li><span class="xml"><span class="tag"><<span class="name">Link</span> <span class="attr">to</span>=<span class="string">'/roster'</span>></span>Roster<span class="tag"></<span class="name">Link</span>></span></span><span class="xml"><span class="tag"></<span class="name">li</span>></span></span></span><br><span class="line"> <li><span class="xml"><span class="tag"><<span class="name">Link</span> <span class="attr">to</span>=<span class="string">'/schedule'</span>></span>Schedule<span class="tag"></<span class="name">Link</span>></span></span><span class="xml"><span class="tag"></<span class="name">li</span>></span></span></span><br><span class="line"> <<span class="regexp">/ul></span></span><br><span class="line"><span class="regexp"> </</span>nav></span><br><span class="line"> <<span class="regexp">/header></span></span><br><span class="line"><span class="regexp">)</span></span><br></pre></td></tr></table></figure><p>Link使用’to’参数来描述需要定位的页面。它的值即可是字符串也可是location对象(包含pathname,search,hash与state属性)。<br>如果其值为字符床将会被转换为location对象。</p>]]></content>
<summary type="html">
react-router
</summary>
<category term="搬砖" scheme="http://chilam.me/categories/%E6%90%AC%E7%A0%96/"/>
<category term="react-router" scheme="http://chilam.me/tags/react-router/"/>
</entry>
<entry>
<title>webpack</title>
<link href="http://chilam.me/2018/08/13/webpack/"/>
<id>http://chilam.me/2018/08/13/webpack/</id>
<published>2018-08-13T07:57:02.000Z</published>
<updated>2018-08-14T08:17:57.944Z</updated>
<content type="html"><![CDATA[<h2 id="webpack"><a href="#webpack" class="headerlink" title="webpack"></a>webpack</h2><p>本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,<br>它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。</p><h3 id="Hello-Webpack"><a href="#Hello-Webpack" class="headerlink" title="Hello Webpack"></a>Hello Webpack</h3><ul><li>新建文件目录webpack-demo执行npm初始化</li></ul><figure class="highlight maxima"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">mkdir</span> webpack-<span class="built_in">demo</span> && cd webpack-<span class="built_in">demo</span></span><br><span class="line">npm init -yes</span><br></pre></td></tr></table></figure><ul><li>本地安装webpack,只是开发时需要</li></ul><figure class="highlight q"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npm install webpack --<span class="built_in">save</span>-<span class="built_in">dev</span></span><br><span class="line">npm install webpack-cli --<span class="built_in">save</span>-<span class="built_in">dev</span></span><br></pre></td></tr></table></figure><ul><li>新建src目录及新建index.js,内容如下</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> lodash <span class="keyword">from</span> <span class="string">'lodash'</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createDiv</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> helloDiv = <span class="built_in">document</span>.createElement(<span class="string">'div'</span>)</span><br><span class="line"> helloDiv.innerText = lodash.join([<span class="string">"hello"</span>,<span class="string">"webpack"</span>],<span class="string">"--"</span>)</span><br><span class="line"> <span class="keyword">return</span> helloDiv</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="built_in">document</span>.body.appendChild(createDiv())</span><br></pre></td></tr></table></figure><ul><li>新建webpack.config.js内容如下</li></ul><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">var <span class="built_in">path</span> = <span class="built_in">require</span>(<span class="string">'path'</span>)</span><br><span class="line"></span><br><span class="line">module.exports = {</span><br><span class="line"> mode: <span class="string">"development"</span>,</span><br><span class="line"> entry: <span class="string">"./src/index.js"</span>,</span><br><span class="line"> <span class="built_in">output</span>: {</span><br><span class="line"> filename: <span class="string">"bundle.js"</span>,</span><br><span class="line"> <span class="built_in">path</span>: <span class="built_in">path</span>.resolve(__dirname,<span class="string">"dist"</span>)</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>编辑package.json,添加scripts</li></ul><figure class="highlight stata"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"scripts"</span>: {</span><br><span class="line"> <span class="string">"test"</span>: <span class="string">"echo \"</span><span class="keyword">Error</span>: <span class="keyword">no</span> <span class="keyword">test</span> specified\<span class="string">" && exit 1"</span>,</span><br><span class="line"> <span class="string">"build"</span>: <span class="string">"webpack --config webpack.config.js"</span></span><br><span class="line">},</span><br></pre></td></tr></table></figure><ul><li>执行npm run build</li></ul><figure class="highlight armasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">> webpack --config webpack.config.js</span><br><span class="line"></span><br><span class="line"><span class="symbol">Hash</span>: <span class="number">47</span>c0d5514d044c340a9e</span><br><span class="line"><span class="symbol">Version</span>: webpack <span class="number">4</span>.<span class="number">16</span>.<span class="number">5</span></span><br><span class="line"><span class="symbol">Time</span>: <span class="number">868</span>ms</span><br><span class="line"><span class="keyword">Built </span>at: <span class="number">2018</span>/<span class="number">08</span>/<span class="number">13</span> 下午<span class="number">5</span>:<span class="number">44</span>:<span class="number">40</span></span><br><span class="line"> Asset Size Chunks Chunk Names</span><br><span class="line"><span class="keyword">bundle.js </span> <span class="number">551</span> KiB main [emitted] main</span><br><span class="line"><span class="symbol">Entrypoint</span> main = <span class="keyword">bundle.js</span></span><br><span class="line"><span class="keyword">[./node_modules/webpack/buildin/global.js] </span>(webpack)/<span class="keyword">buildin/global.js </span><span class="number">489</span> <span class="keyword">bytes </span>{main} [<span class="keyword">built]</span></span><br><span class="line"><span class="keyword">[./node_modules/webpack/buildin/module.js] </span>(webpack)/<span class="keyword">buildin/module.js </span><span class="number">497</span> <span class="keyword">bytes </span>{main} [<span class="keyword">built]</span></span><br><span class="line"><span class="keyword">[./src/index.js] </span><span class="number">227</span> <span class="keyword">bytes </span>{main} [<span class="keyword">built]</span></span><br><span class="line"><span class="keyword"> </span> + <span class="number">1</span> hidden module</span><br></pre></td></tr></table></figure><ul><li>新建index.html使用打包好的bundle.js</li></ul><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><!DOCTYPE html></span></span><br><span class="line"><span class="tag"><<span class="name">html</span> <span class="attr">lang</span>=<span class="string">"en"</span>></span></span><br><span class="line"><span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"UTF-8"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span>Title<span class="tag"></<span class="name">title</span>></span></span><br><span class="line"></span><br><span class="line"><span class="tag"></<span class="name">head</span>></span></span><br><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">script</span> <span class="attr">src</span>=<span class="string">"dist/bundle.js"</span>></span><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span></span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span></span><br></pre></td></tr></table></figure><h3 id="入口"><a href="#入口" class="headerlink" title="入口"></a>入口</h3><p>入口起点(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。</p><h3 id="出口"><a href="#出口" class="headerlink" title="出口"></a>出口</h3><p>output 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,默认值为 ./dist。基本上,<br>整个应用程序结构,都会被编译到你指定的输出路径的文件夹中。</p><h3 id="Loader"><a href="#Loader" class="headerlink" title="Loader"></a>Loader</h3><p>loader 让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)</p><h3 id="插件"><a href="#插件" class="headerlink" title="插件"></a>插件</h3><p>loader 被用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量。<br>插件接口功能极其强大,可以用来处理各种各样的任务。</p><h3 id="模式"><a href="#模式" class="headerlink" title="模式"></a>模式</h3><p>通过选择 development 或 production 之中的一个,来设置 mode 参数,你可以启用相应模式下的 webpack 内置的优化</p><h2 id="资源加载"><a href="#资源加载" class="headerlink" title="资源加载"></a>资源加载</h2><h3 id="加载CSS"><a href="#加载CSS" class="headerlink" title="加载CSS"></a>加载CSS</h3><ul><li>安装 npm install –save-dev style-loader css-loader</li><li><p>编辑 webpack.config.js添加css的配置</p><ul><li>test 属性,用于标识出应该被对应的 loader 进行转换的某个或某些文件。</li><li>use 属性,表示进行转换时,应该使用哪个 loader。<figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> path = <span class="built_in">require</span>(<span class="string">'path'</span>)</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = {</span><br><span class="line"> mode: <span class="string">"development"</span>,</span><br><span class="line"> entry: <span class="string">"./src/index.js"</span>,</span><br><span class="line"> output: {</span><br><span class="line"> filename: <span class="string">"bundle.js"</span>,</span><br><span class="line"> path: path.resolve(__dirname,<span class="string">"dist"</span>)</span><br><span class="line"> },</span><br><span class="line"> <span class="keyword">module</span>: {</span><br><span class="line"> rules: [{</span><br><span class="line"> test: <span class="regexp">/\.css$/</span>,</span><br><span class="line"> use:[</span><br><span class="line"> <span class="string">'style-loader'</span>,</span><br><span class="line"> <span class="string">'css-loader'</span></span><br><span class="line"> ]</span><br><span class="line"></span><br><span class="line"> }]</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ul></li><li><p>新建src/style.css</p></li></ul><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.hello</span>{</span><br><span class="line"> <span class="attribute">color</span>: red;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>编辑index.js引用style.css</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> lodash <span class="keyword">from</span> <span class="string">'lodash'</span></span><br><span class="line"><span class="comment">//引入样式文件</span></span><br><span class="line"><span class="keyword">import</span> <span class="string">'./style.css'</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createDiv</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> helloDiv = <span class="built_in">document</span>.createElement(<span class="string">'div'</span>)</span><br><span class="line"> helloDiv.innerText = lodash.join([<span class="string">"hello"</span>,<span class="string">"webpack"</span>],<span class="string">"--"</span>)</span><br><span class="line"> <span class="comment">//设置样式</span></span><br><span class="line"> helloDiv.className = <span class="string">"hello"</span></span><br><span class="line"> <span class="keyword">return</span> helloDiv</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="built_in">document</span>.body.appendChild(createDiv())</span><br></pre></td></tr></table></figure><ul><li>执行npm build run即可</li></ul><h3 id="加载图片"><a href="#加载图片" class="headerlink" title="加载图片"></a>加载图片</h3><ul><li><p>安装 npm install –save-dev file-loader</p></li><li><p>编辑webpack.config.js添加file-loader的配置</p></li></ul><figure class="highlight stata"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//处理图片的loader</span></span><br><span class="line">{</span><br><span class="line"> <span class="keyword">test</span>:/\.(png|jpg|svg|gif)$/,</span><br><span class="line"> <span class="keyword">use</span>:['<span class="keyword">file</span>-loader']</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>编辑src/index.js,使用图片资源,前提是先找一张图片icon.jpg放置到src目录</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> lodash <span class="keyword">from</span> <span class="string">'lodash'</span></span><br><span class="line"><span class="comment">//引入样式文件</span></span><br><span class="line"><span class="keyword">import</span> <span class="string">'./style.css'</span></span><br><span class="line"><span class="comment">//引用图片资源</span></span><br><span class="line"><span class="keyword">import</span> icon <span class="keyword">from</span> <span class="string">'./icon.jpg'</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createDiv</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="comment">//创建的div标签</span></span><br><span class="line"> <span class="keyword">const</span> helloDiv = <span class="built_in">document</span>.createElement(<span class="string">'div'</span>)</span><br><span class="line"> helloDiv.innerText = lodash.join([<span class="string">"hello"</span>,<span class="string">"webpack"</span>],<span class="string">"--"</span>)</span><br><span class="line"> <span class="comment">//设置样式</span></span><br><span class="line"> helloDiv.className = <span class="string">"hello"</span></span><br><span class="line"> <span class="comment">//创建image标签</span></span><br><span class="line"> <span class="keyword">const</span> myImage = <span class="keyword">new</span> Image()</span><br><span class="line"> myImage.src = icon</span><br><span class="line"> helloDiv.appendChild(myImage)</span><br><span class="line"> <span class="keyword">return</span> helloDiv</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="built_in">document</span>.body.appendChild(createDiv())</span><br></pre></td></tr></table></figure><ul><li>重新构建npm run build,用浏览器打开index.html</li></ul><figure class="highlight dts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">> webpack --config webpack.config.js</span><br><span class="line"></span><br><span class="line"><span class="symbol">Hash:</span> <span class="number">74</span>c244d6b4cfa5b137cf</span><br><span class="line"><span class="symbol">Version:</span> webpack <span class="number">4.16</span><span class="number">.5</span></span><br><span class="line"><span class="symbol">Time:</span> <span class="number">510</span>ms</span><br><span class="line">Built at: <span class="number">2018</span>/<span class="number">08</span>/<span class="number">14</span> 上午<span class="number">9</span>:<span class="number">48</span>:<span class="number">37</span></span><br><span class="line"> Asset Size Chunks Chunk Names</span><br><span class="line"><span class="number">49f</span>2d519a8fc7a261e61807b97dacf93.jpg <span class="number">31.2</span> KiB [emitted] </span><br><span class="line"> bundle.js <span class="number">573</span> KiB main [emitted] main</span><br><span class="line">Entrypoint main = bundle.js</span><br><span class="line">[./node_modules<span class="meta-keyword">/css-loader/</span>index.js!.<span class="meta-keyword">/src/</span>style.css] ./node_modules/css-loader!.<span class="meta-keyword">/src/</span>style.css <span class="number">317</span> <span class="class">bytes </span>{main} [built]</span><br><span class="line">[./node_modules<span class="meta-keyword">/webpack/</span>buildin/global.js] (webpack)<span class="meta-keyword">/buildin/</span>global.js <span class="number">489</span> <span class="class">bytes </span>{main} [built]</span><br><span class="line">[./node_modules<span class="meta-keyword">/webpack/</span>buildin/module.js] (webpack)<span class="meta-keyword">/buildin/</span>module.js <span class="number">497</span> <span class="class">bytes </span>{main} [built]</span><br><span class="line">[.<span class="meta-keyword">/src/</span>icon.jpg] <span class="number">82</span> <span class="class">bytes </span>{main} [built]</span><br><span class="line">[.<span class="meta-keyword">/src/</span>index.js] <span class="number">451</span> <span class="class">bytes </span>{main} [built]</span><br><span class="line">[.<span class="meta-keyword">/src/</span>style.css] <span class="number">1.05</span> <span class="class">KiB </span>{main} [built]</span><br><span class="line"> + <span class="number">5</span> hidden modules</span><br></pre></td></tr></table></figure><h4 id="通过css-loader来加载图片"><a href="#通过css-loader来加载图片" class="headerlink" title="通过css-loader来加载图片"></a>通过css-loader来加载图片</h4><p>当使用 css-loader 时,如上所示,你的 CSS 中的 url(‘./icon.jpg’) 。loader 会识别这是一个本地文件,<br>并将 ‘./icon.jpg’ 路径,替换为输出目录中图像的最终路径。</p><ul><li>编辑style.css如下,给hello样式添加背景图片</li></ul><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.hello</span>{</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">500px</span>;</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">500px</span>;</span><br><span class="line"> <span class="attribute">color</span>: red;</span><br><span class="line"> <span class="attribute">background</span>: <span class="built_in">url</span>(<span class="string">'./icon.jpg'</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>重新执行npm run build,此时就有了背景图片</li></ul><h3 id="加载字体"><a href="#加载字体" class="headerlink" title="加载字体"></a>加载字体</h3><p>file-loader可以处理任何文件,然后将其输出到构建目录</p><ul><li>编辑webpack.config.js处理字体资源</li></ul><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attribute">test</span>: /\.(woff|woff2|eot|ttf|otf)$/,</span><br><span class="line"> use: [<span class="string">'file-loader'</span>]</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>编辑style.css添加字体处理,先下载字体文件my-icon.ttf放到src目录下</li></ul><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">@<span class="keyword">font-face</span> {</span><br><span class="line"> <span class="attribute">font-family</span>: MyFont;</span><br><span class="line"> <span class="attribute">src</span>: <span class="built_in">url</span>(<span class="string">'./my-font.ttf'</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.hello</span>{</span><br><span class="line"> <span class="attribute">color</span>: red;</span><br><span class="line"> <span class="attribute">font-family</span>: MyFont;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>执行npm run build重新构建</li></ul><h3 id="加载数据"><a href="#加载数据" class="headerlink" title="加载数据"></a>加载数据</h3><p>加载JSON文件,CSV,TSV和XML数据,JSON是内置就支持的,import Data from ‘./data.json’ 默认将正常运行。<br>要导入CSV,TSV,XML文件需要使用loader文件进行加载。</p><h4 id="加载json数据,默认支持"><a href="#加载json数据,默认支持" class="headerlink" title="加载json数据,默认支持"></a>加载json数据,默认支持</h4><ul><li>新建data.json文件如下</li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"username"</span>:<span class="string">"张三"</span>,</span><br><span class="line"> <span class="attr">"password"</span>:<span class="string">"test123456."</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>编辑index.js文件如下</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> lodash <span class="keyword">from</span> <span class="string">'lodash'</span></span><br><span class="line"><span class="comment">//引入样式文件</span></span><br><span class="line"><span class="keyword">import</span> <span class="string">'./style.css'</span></span><br><span class="line"><span class="comment">//引入data.json文件</span></span><br><span class="line"><span class="keyword">import</span> Data <span class="keyword">from</span> <span class="string">'./data/data'</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createDiv</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="comment">//创建的div标签</span></span><br><span class="line"> <span class="keyword">const</span> helloDiv = <span class="built_in">document</span>.createElement(<span class="string">'div'</span>)</span><br><span class="line"> helloDiv.className = <span class="string">"hello"</span></span><br><span class="line"> helloDiv.innerText = lodash.join([<span class="string">"张三哈哈哈哈"</span>,<span class="string">"webpack"</span>,Data.username,Data.password],<span class="string">"--"</span>)</span><br><span class="line"> <span class="keyword">return</span> helloDiv</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="built_in">document</span>.body.appendChild(createDiv())</span><br></pre></td></tr></table></figure><ul><li>执行npm run build</li></ul><h4 id="加载CSV-TSV-XML数据"><a href="#加载CSV-TSV-XML数据" class="headerlink" title="加载CSV,TSV,XML数据"></a>加载CSV,TSV,XML数据</h4><ul><li>安装loader</li></ul><figure class="highlight q"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install --<span class="built_in">save</span>-<span class="built_in">dev</span> <span class="built_in">csv</span>-loader xml-loader</span><br></pre></td></tr></table></figure><ul><li>编辑webpack.config.js添加loader</li></ul><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attribute">test</span>:/\.(csv|tsv)$/,</span><br><span class="line"> use:[<span class="string">'csv-loader'</span>]</span><br><span class="line">},</span><br><span class="line">{</span><br><span class="line"> <span class="attribute">test</span>:/\.xml$/,</span><br><span class="line"> use:[<span class="string">'xml-loader'</span>]</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>新建data.xml文件如下所示</li></ul><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="php"><span class="meta"><?</span>xml version=<span class="string">"1.0"</span> encoding=<span class="string">"UTF-8"</span><span class="meta">?></span></span></span><br><span class="line"><span class="tag"><<span class="name">note</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">to</span>></span>李四<span class="tag"></<span class="name">to</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">from</span>></span>王五<span class="tag"></<span class="name">from</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">heading</span>></span>Reminder<span class="tag"></<span class="name">heading</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">body</span>></span>Call Cindy on Tuesday<span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">note</span>></span></span><br></pre></td></tr></table></figure><ul><li>编辑index.js如下</li></ul><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">import lodash from <span class="string">'lodash'</span></span><br><span class="line"><span class="comment">//引入样式文件</span></span><br><span class="line">import <span class="string">'./style.css'</span></span><br><span class="line">import Data from <span class="string">'./data/data.xml'</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">function createDiv() {</span><br><span class="line"> <span class="comment">//创建的div标签</span></span><br><span class="line"> const helloDiv = document.createElement(<span class="string">'div'</span>)</span><br><span class="line"> helloDiv<span class="selector-class">.className</span> = <span class="string">"hello"</span></span><br><span class="line"> console.log(Data<span class="selector-class">.note</span><span class="selector-class">.to</span>)</span><br><span class="line"> helloDiv<span class="selector-class">.innerText</span> = lodash.join([<span class="string">"张三哈哈哈哈"</span>,<span class="string">"webpack"</span>,Data<span class="selector-class">.note</span><span class="selector-class">.to</span><span class="selector-class">.toString</span>()],<span class="string">"--"</span>)</span><br><span class="line"> return helloDiv</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">document<span class="selector-class">.body</span><span class="selector-class">.appendChild</span>(createDiv())</span><br></pre></td></tr></table></figure><ul><li>重新npm run build</li></ul><h2 id="管理输出"><a href="#管理输出" class="headerlink" title="管理输出"></a>管理输出</h2><ul><li>新建src/print.js内容如下:</li></ul><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="builtin-name">export</span><span class="built_in"> default </span>function printMe() {</span><br><span class="line"> console.log(<span class="string">"print js....."</span>)</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>编辑src/index.js内容如下</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> printMe <span class="keyword">from</span> <span class="string">'./print'</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createDiv</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> divElement = <span class="built_in">document</span>.createElement(<span class="string">'div'</span>)</span><br><span class="line"> divElement.innerText = <span class="string">'hello, printMe'</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> btnElement = <span class="built_in">document</span>.createElement(<span class="string">'button'</span>)</span><br><span class="line"> btnElement.onclick = printMe</span><br><span class="line"> btnElement.innerHTML = <span class="string">'Click Me and print console'</span></span><br><span class="line"></span><br><span class="line"> divElement.appendChild(btnElement)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> divElement</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="built_in">document</span>.body.appendChild(createDiv())</span><br></pre></td></tr></table></figure><ul><li>编辑webpack.config.js内容如下</li></ul><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">const <span class="built_in">path</span> = <span class="built_in">require</span>(<span class="string">'path'</span>)</span><br><span class="line"></span><br><span class="line">module.exports = {</span><br><span class="line"> mode: <span class="string">'development'</span>,</span><br><span class="line"> //添加多个入口文件</span><br><span class="line"> entry: {</span><br><span class="line"> app:<span class="string">'./src/index.js'</span>,</span><br><span class="line"> <span class="built_in">print</span>:<span class="string">'./src/print.js'</span></span><br><span class="line"> },</span><br><span class="line"> <span class="built_in">output</span>:{</span><br><span class="line"> filename:<span class="string">'[name].bundle.js'</span>,</span><br><span class="line"> <span class="built_in">path</span>: <span class="built_in">path</span>.resolve(__dirname,<span class="string">"dist"</span>)</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>执行npm run build后会输出app.bundle.js和print.bundle.js</li></ul><figure class="highlight stata"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">> webpack --config webpack.config.js</span><br><span class="line"></span><br><span class="line">Hash: 150927976edcc6f13af2</span><br><span class="line"><span class="keyword">Version</span>: webpack 4.16.5</span><br><span class="line">Time: 106ms</span><br><span class="line">Built at: 2018/08/14 下午2:04:01</span><br><span class="line"> Asset Size Chunks Chunk Names</span><br><span class="line"> <span class="keyword">app</span>.bundle.js 4.89 KiB <span class="keyword">app</span> [emitted] <span class="keyword">app</span></span><br><span class="line"><span class="keyword">print</span>.bundle.js 4.04 KiB <span class="keyword">print</span> [emitted] <span class="keyword">print</span></span><br><span class="line">Entrypoint <span class="keyword">app</span> = <span class="keyword">app</span>.bundle.js</span><br><span class="line">Entrypoint <span class="keyword">print</span> = <span class="keyword">print</span>.bundle.js</span><br><span class="line">[./src/index.js] 401 bytes {<span class="keyword">app</span>} [built]</span><br><span class="line">[./src/<span class="keyword">print</span>.js] 70 bytes {<span class="keyword">print</span>} {<span class="keyword">app</span>} [built]</span><br></pre></td></tr></table></figure><ul><li>编辑index.html页面,分别引用生成的js文件</li></ul><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><!DOCTYPE html></span></span><br><span class="line"><span class="tag"><<span class="name">html</span> <span class="attr">lang</span>=<span class="string">"en"</span>></span></span><br><span class="line"><span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"UTF-8"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span>Title<span class="tag"></<span class="name">title</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">script</span> <span class="attr">src</span>=<span class="string">"./print.bundle.js"</span>></span><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span></span><br><span class="line"></span><br><span class="line"><span class="tag"></<span class="name">head</span>></span></span><br><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">script</span> <span class="attr">src</span>=<span class="string">"./app.bundle.js"</span>></span><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span></span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span></span><br></pre></td></tr></table></figure><h3 id="HtmlWebpackPlugin"><a href="#HtmlWebpackPlugin" class="headerlink" title="HtmlWebpackPlugin"></a><a href="https://github.com/jantimon/html-webpack-plugin" target="_blank" rel="noopener">HtmlWebpackPlugin</a></h3><p>上面我们假设更改了入口的文件名称,甚至添加了一个新名称会发生什么?重新生成的js文件将被重命名到dist目录,但是index.html中还是引用的<br>原来的js文件名称。可以使用HtmlWebpackPlugin来解决的这个问题。</p><ul><li><p>安装 npm install –save-dev html-webpack-plugin</p></li><li><p>配置webpack.config.js</p></li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">'path'</span>)</span><br><span class="line"><span class="keyword">const</span> HtmlWebpackPlugin = <span class="built_in">require</span>(<span class="string">'html-webpack-plugin'</span>)</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = {</span><br><span class="line"> mode: <span class="string">'development'</span>,</span><br><span class="line"> entry: {</span><br><span class="line"> app:<span class="string">'./src/index.js'</span>,</span><br><span class="line"> print:<span class="string">'./src/print.js'</span></span><br><span class="line"> },</span><br><span class="line"> output:{</span><br><span class="line"> filename:<span class="string">'[name].bundle.js'</span>,</span><br><span class="line"> path: path.resolve(__dirname,<span class="string">"dist"</span>)</span><br><span class="line"> },</span><br><span class="line"> plugins:[</span><br><span class="line"> <span class="keyword">new</span> HtmlWebpackPlugin({</span><br><span class="line"> <span class="comment">//重新生成index.html页面的title内容</span></span><br><span class="line"> title: <span class="string">'Output Management'</span></span><br><span class="line"> })</span><br><span class="line"> ]</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>执行npm run build</li></ul><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">> webpack --config webpack<span class="selector-class">.config</span><span class="selector-class">.js</span></span><br><span class="line"></span><br><span class="line">Hash: <span class="number">98</span>f902660e1ee6b0be93</span><br><span class="line">Version: webpack <span class="number">4.16</span>.<span class="number">5</span></span><br><span class="line">Time: <span class="number">447ms</span></span><br><span class="line">Built at: <span class="number">2018</span>/<span class="number">08</span>/<span class="number">14</span> 下午<span class="number">2</span>:<span class="number">21</span>:<span class="number">30</span></span><br><span class="line"> Asset Size Chunks Chunk Names</span><br><span class="line"> app<span class="selector-class">.bundle</span><span class="selector-class">.js</span> <span class="number">4.89</span> KiB app [emitted] app</span><br><span class="line">print<span class="selector-class">.bundle</span><span class="selector-class">.js</span> <span class="number">4.04</span> KiB print [emitted] print</span><br><span class="line"> index<span class="selector-class">.html</span> <span class="number">254</span> bytes [emitted] </span><br><span class="line">Entrypoint app = app<span class="selector-class">.bundle</span><span class="selector-class">.js</span></span><br><span class="line">Entrypoint print = print<span class="selector-class">.bundle</span><span class="selector-class">.js</span></span><br><span class="line">[./src/index.js] <span class="number">401</span> bytes {app} [built]</span><br><span class="line">[./src/print.js] <span class="number">70</span> bytes {print} {app} [built]</span><br><span class="line">Child html-webpack-plugin <span class="keyword">for</span> <span class="string">"index.html"</span>:</span><br><span class="line"> <span class="number">1</span> asset</span><br><span class="line"> Entrypoint undefined = index.html</span><br><span class="line"> [./node_modules/webpack/buildin/global.js] (webpack)/buildin/global<span class="selector-class">.js</span> <span class="number">489</span> bytes {<span class="number">0</span>} [built]</span><br><span class="line"> [./node_modules/webpack/buildin/module.js] (webpack)/buildin/module<span class="selector-class">.js</span> <span class="number">497</span> bytes {<span class="number">0</span>} [built]</span><br><span class="line"> + <span class="number">2</span> hidden modules</span><br></pre></td></tr></table></figure><ul><li>以上可知,每次执行npm run build都会重新生成index.html</li></ul><h2 id="清理dist目录"><a href="#清理dist目录" class="headerlink" title="清理dist目录"></a>清理dist目录</h2><ul><li><p>安装 npm install clean-webpack-plugin –save-dev</p></li><li><p>配置 webpack.config.js</p></li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">'path'</span>)</span><br><span class="line"><span class="keyword">const</span> HtmlWebpackPlugin = <span class="built_in">require</span>(<span class="string">'html-webpack-plugin'</span>)</span><br><span class="line"><span class="keyword">const</span> CleanWebpackPlugin = <span class="built_in">require</span>(<span class="string">'clean-webpack-plugin'</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = {</span><br><span class="line"> mode: <span class="string">'development'</span>,</span><br><span class="line"> entry: {</span><br><span class="line"> app:<span class="string">'./src/index.js'</span>,</span><br><span class="line"> print:<span class="string">'./src/print.js'</span></span><br><span class="line"> },</span><br><span class="line"> output:{</span><br><span class="line"> filename:<span class="string">'[name].bundle.js'</span>,</span><br><span class="line"> path: path.resolve(__dirname,<span class="string">"dist"</span>)</span><br><span class="line"> },</span><br><span class="line"> plugins:[</span><br><span class="line"> <span class="comment">//清理dist目录</span></span><br><span class="line"> <span class="keyword">new</span> CleanWebpackPlugin([<span class="string">'dist'</span>]),</span><br><span class="line"> <span class="keyword">new</span> HtmlWebpackPlugin({</span><br><span class="line"> <span class="comment">//重新生成index.html页面的title内容</span></span><br><span class="line"> title: <span class="string">'Output Management'</span></span><br><span class="line"> })</span><br><span class="line"> ]</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>执行npm run build,只会留下在被使用的文件</li></ul><h2 id="开发"><a href="#开发" class="headerlink" title="开发"></a>开发</h2><h3 id="使用source-map"><a href="#使用source-map" class="headerlink" title="使用source map"></a>使用source map</h3><p>当 webpack 打包源代码时,可能会很难追踪到错误和警告在源代码中的原始位置。例如,如果将三个源文件(a.js, b.js 和 c.js)<br>打包到一个 bundle(bundle.js)中,而其中一个源文件包含一个错误,那么堆栈跟踪就会简单地指向到 bundle.js。<br>这并通常没有太多帮助,因为你可能需要准确地知道错误来自于哪个源文件。</p><ul><li>编辑webpack.config.js添加devtool: “inline-source-map”</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">'path'</span>)</span><br><span class="line"><span class="keyword">const</span> HtmlWebpackPlugin = <span class="built_in">require</span>(<span class="string">'html-webpack-plugin'</span>)</span><br><span class="line"><span class="keyword">const</span> CleanWebpackPlugin = <span class="built_in">require</span>(<span class="string">'clean-webpack-plugin'</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = {</span><br><span class="line"> mode: <span class="string">'development'</span>,</span><br><span class="line"> entry: {</span><br><span class="line"> app:<span class="string">'./src/index.js'</span>,</span><br><span class="line"> print:<span class="string">'./src/print.js'</span></span><br><span class="line"> },</span><br><span class="line"> devtool: <span class="string">"inline-source-map"</span>,</span><br><span class="line"> output:{</span><br><span class="line"> filename:<span class="string">'[name].bundle.js'</span>,</span><br><span class="line"> path: path.resolve(__dirname,<span class="string">"dist"</span>)</span><br><span class="line"> },</span><br><span class="line"> plugins:[</span><br><span class="line"> <span class="keyword">new</span> HtmlWebpackPlugin({</span><br><span class="line"> <span class="comment">//重新生成index.html页面的title内容</span></span><br><span class="line"> title: <span class="string">'Output Management'</span></span><br><span class="line"> }),</span><br><span class="line"> <span class="keyword">new</span> CleanWebpackPlugin([<span class="string">'dist'</span>])</span><br><span class="line"> ]</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>测试,我们将print.js代码故意写错如下:</li></ul><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="builtin-name">export</span><span class="built_in"> default </span>function printMe() {</span><br><span class="line"> consoee.log(<span class="string">"print js....."</span>)</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>重新构建npm run build,访问index.html此时查看浏览器的控制台就可以看见明显的错误信息关联具体的print.js</li></ul><h3 id="开发工具webpack-dev-server"><a href="#开发工具webpack-dev-server" class="headerlink" title="开发工具webpack-dev-server"></a>开发工具webpack-dev-server</h3><p>ebpack-dev-server 为你提供了一个简单的 web 服务器,并且能够实时重新加载(live reloading)</p><ul><li><p>安装 npm install –save-dev webpack-dev-server</p></li><li><p>配置webpack-dev-server在webpack.config.js</p></li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">'path'</span>)</span><br><span class="line"><span class="keyword">const</span> HtmlWebpackPlugin = <span class="built_in">require</span>(<span class="string">'html-webpack-plugin'</span>)</span><br><span class="line"><span class="keyword">const</span> CleanWebpackPlugin = <span class="built_in">require</span>(<span class="string">'clean-webpack-plugin'</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = {</span><br><span class="line"> mode: <span class="string">'development'</span>,</span><br><span class="line"> entry: {</span><br><span class="line"> app:<span class="string">'./src/index.js'</span>,</span><br><span class="line"> print:<span class="string">'./src/print.js'</span></span><br><span class="line"> },</span><br><span class="line"> devtool: <span class="string">"inline-source-map"</span>,</span><br><span class="line"> devServer: {</span><br><span class="line"> contentBase:<span class="string">'./dist'</span></span><br><span class="line"> },</span><br><span class="line"> output:{</span><br><span class="line"> filename:<span class="string">'[name].bundle.js'</span>,</span><br><span class="line"> path: path.resolve(__dirname,<span class="string">"dist"</span>)</span><br><span class="line"> },</span><br><span class="line"> plugins:[</span><br><span class="line"> <span class="keyword">new</span> HtmlWebpackPlugin({</span><br><span class="line"> <span class="comment">//重新生成index.html页面的title内容</span></span><br><span class="line"> title: <span class="string">'Output Management'</span></span><br><span class="line"> }),</span><br><span class="line"> <span class="keyword">new</span> CleanWebpackPlugin([<span class="string">'dist'</span>])</span><br><span class="line"> ]</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>以上配置告知 webpack-dev-server,在 localhost:8080 下建立服务,将 dist 目录下的文件,作为可访问文件。</p><ul><li>添加scripts加package.json中</li></ul><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">"<span class="keyword">start</span><span class="string">":"</span>webpack-dev-<span class="keyword">server</span> <span class="comment">--open"</span></span><br></pre></td></tr></table></figure><ul><li>执行npm start,然后修改print.js自然就会同步编译和刷新浏览器</li></ul><h2 id="模块热替换"><a href="#模块热替换" class="headerlink" title="模块热替换"></a>模块热替换</h2><p>模块热替换(Hot Module Replacement 或 HMR)是 webpack 提供的最有用的功能之一。它允许在运行时更新各种模块,而无需进行完全刷新。</p><ul><li>启用HMR</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"> <span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">'path'</span>);</span><br><span class="line"> <span class="keyword">const</span> HtmlWebpackPlugin = <span class="built_in">require</span>(<span class="string">'html-webpack-plugin'</span>);</span><br><span class="line"> <span class="keyword">const</span> CleanWebpackPlugin = <span class="built_in">require</span>(<span class="string">'clean-webpack-plugin'</span>);</span><br><span class="line">+ <span class="keyword">const</span> webpack = <span class="built_in">require</span>(<span class="string">'webpack'</span>);</span><br><span class="line"></span><br><span class="line"> <span class="built_in">module</span>.exports = {</span><br><span class="line"> entry: {</span><br><span class="line">- app: <span class="string">'./src/index.js'</span>,</span><br><span class="line">- print: <span class="string">'./src/print.js'</span></span><br><span class="line">+ app: <span class="string">'./src/index.js'</span></span><br><span class="line"> },</span><br><span class="line"> devtool: <span class="string">'inline-source-map'</span>,</span><br><span class="line"> devServer: {</span><br><span class="line"> contentBase: <span class="string">'./dist'</span>,</span><br><span class="line">+ hot: <span class="literal">true</span></span><br><span class="line"> },</span><br><span class="line"> plugins: [</span><br><span class="line"> <span class="keyword">new</span> CleanWebpackPlugin([<span class="string">'dist'</span>]),</span><br><span class="line"> <span class="keyword">new</span> HtmlWebpackPlugin({</span><br><span class="line"> title: <span class="string">'Hot Module Replacement'</span></span><br><span class="line"> }),</span><br><span class="line">+ <span class="keyword">new</span> webpack.NamedModulesPlugin(),</span><br><span class="line">+ <span class="keyword">new</span> webpack.HotModuleReplacementPlugin()</span><br><span class="line"> ],</span><br><span class="line"> output: {</span><br><span class="line"> filename: <span class="string">'[name].bundle.js'</span>,</span><br><span class="line"> path: path.resolve(__dirname, <span class="string">'dist'</span>)</span><br><span class="line"> }</span><br><span class="line"> };</span><br></pre></td></tr></table></figure><ul><li>编辑index.js,以便print.js内部发生变化的时候可以告诉webpack接受更新的模块</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> printMe <span class="keyword">from</span> <span class="string">'./print'</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createDiv</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> divElement = <span class="built_in">document</span>.createElement(<span class="string">'div'</span>)</span><br><span class="line"> divElement.innerText = <span class="string">'hello, printMe'</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> btnElement = <span class="built_in">document</span>.createElement(<span class="string">'button'</span>)</span><br><span class="line"> btnElement.onclick = printMe</span><br><span class="line"> btnElement.innerHTML = <span class="string">'Click Me and print console'</span></span><br><span class="line"></span><br><span class="line"> divElement.appendChild(btnElement)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> inputEle = <span class="built_in">document</span>.createElement(<span class="string">'input'</span>)</span><br><span class="line"> inputEle.type = <span class="string">'text'</span></span><br><span class="line"></span><br><span class="line"> divElement.appendChild(inputEle)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> divElement</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="built_in">document</span>.body.appendChild(createDiv())</span><br><span class="line"></span><br><span class="line"><span class="comment">//当print.js发生改变的时候告知index.js</span></span><br><span class="line"><span class="keyword">if</span>(<span class="built_in">module</span>.hot){</span><br><span class="line"> <span class="built_in">module</span>.hot.accept(<span class="string">'./print.js'</span>,<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"正在更新print模块"</span>)</span><br><span class="line"> printMe()</span><br><span class="line"> })</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>执行npm start,然后更新print.js</li></ul><h2 id="生产环境构建"><a href="#生产环境构建" class="headerlink" title="生产环境构建"></a>生产环境构建</h2><ul><li>开发环境development</li></ul><p>在开发环境中,我们需要具有强大的、具有实时重新加载(live reloading)或热模块替换(hot module replacement)能力<br>的 source map 和 localhost server。</p><ul><li>生产环境production</li></ul><p>目标则转向于关注更小的 bundle,更轻量的 source map,以及更优化的资源,以改善加载时间。</p><h3 id="构建开发和生产环境"><a href="#构建开发和生产环境" class="headerlink" title="构建开发和生产环境"></a>构建开发和生产环境</h3><ul><li><p>安装 npm install –save-dev webpack-merge</p></li><li><p>新建webpack.common.js,webpack.development.js,webpack.production.js</p></li></ul>]]></content>
<summary type="html">
webpack
</summary>
<category term="搬砖" scheme="http://chilam.me/categories/%E6%90%AC%E7%A0%96/"/>
<category term="webpack" scheme="http://chilam.me/tags/webpack/"/>
</entry>
<entry>
<title>前端模块化</title>
<link href="http://chilam.me/2018/08/13/javascript-modules/"/>
<id>http://chilam.me/2018/08/13/javascript-modules/</id>
<published>2018-08-13T01:13:28.000Z</published>
<updated>2018-08-13T02:15:46.393Z</updated>
<content type="html"><![CDATA[<h2 id="JavaScript的模块化"><a href="#JavaScript的模块化" class="headerlink" title="JavaScript的模块化"></a>JavaScript的模块化</h2><h3 id="模块化"><a href="#模块化" class="headerlink" title="模块化"></a>模块化</h3><p>模块化是指在解决某一复杂的问题,依照某一种分类的思维把问题进行系统性的分解来处理。<br>一个模块化系统必须的能力:</p><ul><li>定义封装模块</li><li>定义新模块对其他模块的依赖</li><li>可对其他模块的支持</li></ul><h3 id="CommonJS"><a href="#CommonJS" class="headerlink" title="CommonJS"></a>CommonJS</h3><p>CommonJs是服务端的模块规范,NodeJs采用的这个规范。根据CommonJS规范,一个文件就是一个模块。加载模块使用require方法,该方法<br>读取一个文件返回,最后返回文件的内部的exports对象。</p><ul><li>CommonJS加载模块是同步的,所以只要加载完成才能执行后面的操作。</li><li>NodeJs主要用于服务器端编程,加载模块文件一般都已经在本地磁盘,所以加载起来比较快,不考虑异步加载的方式。</li></ul><h3 id="AMD"><a href="#AMD" class="headerlink" title="AMD"></a>AMD</h3><ul><li>Asynchronous Module Definition,异步模块定义</li></ul><h4 id="AMD写模块API"><a href="#AMD写模块API" class="headerlink" title="AMD写模块API"></a>AMD写模块API</h4><ul><li><p>define(id?,dependencies?factory)</p><ul><li>id,表示模块标识,为可选参数</li><li>dependencies,定义的当前模块所需要的依赖</li><li>factory,定义的函数或对象</li></ul></li><li><p>例1-定义无依赖的模块</p></li></ul><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">define</span>({</span><br><span class="line"> <span class="attribute">add </span>: <span class="built_in">function</span>(x,y){</span><br><span class="line"> return x + y;</span><br><span class="line"> }</span><br><span class="line">})</span><br></pre></td></tr></table></figure><ul><li>例2-定义有依赖的模块</li></ul><figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">define([<span class="string">"alpha"</span>], <span class="function"><span class="keyword">function</span><span class="params">( alpha )</span></span>{</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> verb : <span class="function"><span class="keyword">function</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="keyword">return</span> alpha.verb() + <span class="number">1</span> ;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">});</span><br></pre></td></tr></table></figure><h4 id="AMD模块加载"><a href="#AMD模块加载" class="headerlink" title="AMD模块加载"></a>AMD模块加载</h4><ul><li><p>require([module], callback)</p></li><li><p>例1</p></li></ul><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">require</span>([<span class="string">'math'</span>], <span class="function"><span class="keyword">function</span><span class="params">(math)</span></span> {</span><br><span class="line"> <span class="built_in">math</span>.add(<span class="number">2</span>, <span class="number">3</span>);</span><br><span class="line">});</span><br></pre></td></tr></table></figure><h4 id="RequireJS"><a href="#RequireJS" class="headerlink" title="RequireJS"></a><a href="https://requirejs.org/" target="_blank" rel="noopener">RequireJS</a></h4><ul><li>前端的模块化管理的工具库,遵循AMD规范</li><li>基本思想:通过一个函数来将所需要的模块加载进来,然后返回一个新的函数</li><li>主要解决问题:<ul><li>多个js文件可能有依赖关系,被依赖的文件需要早于依赖它的文件加载到浏览器 </li><li>js加载的时候浏览器会停止页面渲染,加载文件越多,页面失去响应时间越长 </li></ul></li><li>语法:define(id?, dependencies?, factory);<ul><li>require()函数在加载依赖的函数的时候是异步加载的,这样浏览器不会失去响应。</li><li>它指定的回调函数,只有前面的模块都加载成功后,才会运行,解决了依赖性的问题。</li></ul></li></ul><h3 id="CMD和SeaJS"><a href="#CMD和SeaJS" class="headerlink" title="CMD和SeaJS"></a>CMD和SeaJS</h3><ul><li>Common Module Definition</li></ul><p>CMD是SeaJS在推广过程中对模块定义的规范化产出</p><ul><li>对于依赖的模块AMD是提前执行,CMD是延迟执行,</li><li>CMD推崇依赖就近,AMD推崇依赖前置。</li><li>一个文件一个模块,所以经常就用文件名作为模块id</li><li>CMD推崇依赖就近,所以一般不在define的参数中写依赖,在factory中写</li></ul>]]></content>
<summary type="html">
amd,cmd,commonjs
</summary>
<category term="搬砖" scheme="http://chilam.me/categories/%E6%90%AC%E7%A0%96/"/>
<category term="modules" scheme="http://chilam.me/tags/modules/"/>
</entry>
<entry>
<title>react</title>
<link href="http://chilam.me/2018/08/11/react/"/>
<id>http://chilam.me/2018/08/11/react/</id>
<published>2018-08-11T11:18:10.000Z</published>
<updated>2018-08-14T01:19:46.994Z</updated>
<content type="html"><![CDATA[<h2 id="hello-react"><a href="#hello-react" class="headerlink" title="hello react"></a><a href="https://reactjs.org/" target="_blank" rel="noopener">hello react</a></h2><ul><li>预下载react先关的js包,也可以使用下面cdn</li></ul><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">curl -o react<span class="selector-class">.js</span> https:<span class="comment">//cdn.bootcss.com/react/16.4.0/umd/react.development.js</span></span><br><span class="line">curl -o react-dom<span class="selector-class">.js</span> https:<span class="comment">//cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js</span></span><br><span class="line">curl -o babel<span class="selector-class">.js</span> https:<span class="comment">//cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js</span></span><br></pre></td></tr></table></figure><ul><li>新建index.html内容如下:</li></ul><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><!DOCTYPE html></span></span><br><span class="line"><span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"UTF-8"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span>hello react<span class="tag"></<span class="name">title</span>></span></span><br><span class="line"> <span class="comment"><!-- react核心库 --></span></span><br><span class="line"> <span class="tag"><<span class="name">script</span> <span class="attr">src</span>=<span class="string">"https://unpkg.com/react@16/umd/react.development.js"</span>></span><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span></span><br><span class="line"> <span class="comment"><!-- react与dom相关的库--></span></span><br><span class="line"> <span class="tag"><<span class="name">script</span> <span class="attr">src</span>=<span class="string">"https://unpkg.com/react-dom@16/umd/react-dom.development.js"</span>></span><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span></span><br><span class="line"> <span class="comment"><!-- 将JSX语法转换为javascript语法 --></span></span><br><span class="line"> <span class="tag"><<span class="name">script</span> <span class="attr">src</span>=<span class="string">"https://unpkg.com/babel-standalone@6.15.0/babel.min.js"</span>></span><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span></span><br><span class="line"><span class="tag"></<span class="name">head</span>></span></span><br><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line"> <span class="comment"><!-- 声明一个根节点 --></span></span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">id</span>=<span class="string">"root"</span>></span><span class="tag"></<span class="name">div</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/babel"</span>></span><span class="undefined"></span></span><br><span class="line"><span class="undefined"> ReactDOM.render(</span></span><br><span class="line"><span class="javascript"> <h1>Hello React!!!<span class="xml"><span class="tag"></<span class="name">h1</span>></span></span>,</span></span><br><span class="line"><span class="javascript"> <span class="built_in">document</span>.getElementById(<span class="string">"root"</span>)</span></span><br><span class="line"><span class="undefined"> );</span></span><br><span class="line"><span class="undefined"> </span><span class="tag"></<span class="name">script</span>></span></span><br><span class="line"></span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span></span><br></pre></td></tr></table></figure><ul><li>用浏览器打开index.html即可看到效果</li></ul><h2 id="JSX语法"><a href="#JSX语法" class="headerlink" title="JSX语法"></a>JSX语法</h2><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/babel"</span>></span><span class="undefined"></span></span><br><span class="line"><span class="actionscript"> <span class="keyword">const</span> names = [<span class="string">'Lucy'</span>,<span class="string">'Simon'</span>,<span class="string">"Andy"</span>]</span></span><br><span class="line"><span class="undefined"> ReactDOM.render(</span></span><br><span class="line"><span class="handlebars"><span class="xml"> <span class="tag"><<span class="name">div</span>></span></span></span></span><br><span class="line"><span class="handlebars"><span class="xml"> <span class="tag"><<span class="name">h1</span>></span>姓名列表<span class="tag"></<span class="name">h1</span>></span></span></span></span><br><span class="line"><span class="undefined"> {</span></span><br><span class="line"><span class="actionscript"> names.map(<span class="function"><span class="keyword">function</span> <span class="params">(name)</span> </span>{</span></span><br><span class="line"><span class="javascript"> <span class="keyword">return</span> <span class="xml"><span class="tag"><<span class="name">h2</span>></span>姓名: {name} <span class="tag"></<span class="name">h2</span>></span></span></span></span><br><span class="line"><span class="undefined"> })</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="handlebars"><span class="xml"> <span class="tag"></<span class="name">div</span>></span>,</span></span></span><br><span class="line"><span class="javascript"> <span class="built_in">document</span>.getElementById(<span class="string">"root"</span>)</span></span><br><span class="line"><span class="undefined"> );</span></span><br><span class="line"><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span></span><br></pre></td></tr></table></figure><h3 id="JSX语法基本规则"><a href="#JSX语法基本规则" class="headerlink" title="JSX语法基本规则"></a>JSX语法基本规则</h3><ul><li>遇到HTML标签以<开头的,就用HTML规则解析</li><li>遇到代码块以{}开始的就用javascript规则解析</li><li>JSX允许直接在模板中插入javascript变量</li></ul><figure class="highlight dust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="xml"><span class="tag"><<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/babel"</span>></span><span class="undefined"></span></span></span><br><span class="line"><span class="xml"> var arr = [</span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">h1</span>></span>变量一<span class="tag"></<span class="name">h1</span>></span>,</span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">h1</span>></span>变量二<span class="tag"></<span class="name">h1</span>></span>,</span></span><br><span class="line"><span class="xml"> ]</span></span><br><span class="line"><span class="xml"> ReactDOM.render(</span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">div</span>></span></span></span><br><span class="line"><span class="xml"> </span><span class="template-variable">{arr}</span><span class="xml"></span></span><br><span class="line"><span class="xml"> <span class="tag"></<span class="name">div</span>></span>,</span></span><br><span class="line"><span class="xml"> document.getElementById("root")</span></span><br><span class="line"><span class="xml"> );</span></span><br><span class="line"><span class="xml"><span class="tag"></<span class="name">script</span>></span></span></span><br></pre></td></tr></table></figure><h3 id="在JSX中使用表达式"><a href="#在JSX中使用表达式" class="headerlink" title="在JSX中使用表达式"></a>在JSX中使用表达式</h3><ul><li>在JSX中可以使用Javascript表达式,在JSX中表达式要使用大括号括起来</li><li>推荐在书写JSX的时候带上换行和缩进,可以增强代码阅读性</li><li>推荐在JSX代码的外面括上一个小括号,这样可以防止分号自动插入的问题</li></ul><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"> <span class="tag"><<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/babel"</span>></span><span class="undefined"></span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="actionscript"> <span class="keyword">const</span> user = {</span></span><br><span class="line"><span class="actionscript"> firstName : <span class="string">'李'</span>,</span></span><br><span class="line"><span class="actionscript"> lastName : <span class="string">'二娃'</span></span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="actionscript"> <span class="function"><span class="keyword">function</span> <span class="title">formatUser</span><span class="params">(user)</span></span>{</span></span><br><span class="line"><span class="actionscript"> <span class="keyword">return</span> user.firstName + user.lastName;</span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="actionscript"> <span class="keyword">const</span> exprElement = (</span></span><br><span class="line"><span class="handlebars"><span class="xml"> <span class="tag"><<span class="name">h1</span>></span></span></span></span><br><span class="line"><span class="undefined"> {</span></span><br><span class="line"><span class="undefined"> formatUser(user)</span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="handlebars"><span class="xml"> <span class="tag"></<span class="name">h1</span>></span></span></span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="undefined"> )</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="undefined"> ReactDOM.render(</span></span><br><span class="line"><span class="undefined"> exprElement,</span></span><br><span class="line"><span class="javascript"> <span class="built_in">document</span>.getElementById(<span class="string">'root'</span>)</span></span><br><span class="line"><span class="undefined"> )</span></span><br><span class="line"><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span></span><br></pre></td></tr></table></figure><h3 id="JSX属性"><a href="#JSX属性" class="headerlink" title="JSX属性"></a>JSX属性</h3><ul><li>可以使用双引号来定义以字符串为值的属性</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> element = <span class="xml"><span class="tag"><<span class="name">div</span> <span class="attr">tabIndex</span>=<span class="string">"0"</span>></span><span class="tag"></<span class="name">div</span>></span></span>;</span><br></pre></td></tr></table></figure><ul><li>也可以使用大括号来定义Javascript表达式为值的属性 </li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> element = <span class="xml"><span class="tag"><<span class="name">img</span> <span class="attr">src</span>=<span class="string">{user.avatarUrl}</span>></span><span class="tag"></<span class="name">img</span>></span></span>;</span><br></pre></td></tr></table></figure><h2 id="组件"><a href="#组件" class="headerlink" title="组件"></a>组件</h2><ul><li>例1</li></ul><figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><script <span class="class"><span class="keyword">type</span></span>=<span class="string">"text/babel"</span>></span><br><span class="line"> <span class="comment">//react16以后React.createClass方法失效</span></span><br><span class="line"> <span class="comment">// var HelloMessage = React.createClass(</span></span><br><span class="line"> <span class="comment">// {</span></span><br><span class="line"> <span class="comment">// render:function () {</span></span><br><span class="line"> <span class="comment">// return <h1> Hello {this.props.name} </h1>;</span></span><br><span class="line"> <span class="comment">// }</span></span><br><span class="line"> <span class="comment">// }</span></span><br><span class="line"> <span class="comment">// );</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">////react16以后定义react组件方式</span></span><br><span class="line"> <span class="class"><span class="keyword">class</span> <span class="title">HelloMessage</span> <span class="keyword">extends</span> <span class="title">React</span>.<span class="title">Component</span></span>{</span><br><span class="line"></span><br><span class="line"> render(){</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <h2><span class="type">Hello</span>,{<span class="keyword">this</span>.props.name}</h2></span><br><span class="line"> )</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="type">ReactDOM</span>.render(</span><br><span class="line"> <<span class="type">HelloMessage</span> name=<span class="string">"张三"</span>/>,</span><br><span class="line"> document.getElementById(<span class="string">"root"</span>)</span><br><span class="line"> );</span><br><span class="line"></script></span><br></pre></td></tr></table></figure><ul><li>注意react版本,创建组件的方式不一样</li><li>组件类第一字母必须大写</li></ul><figure class="highlight vhdl"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="literal">Warning</span>: <helloMessage /> <span class="keyword">is</span> using incorrect casing. <span class="keyword">Use</span> PascalCase <span class="keyword">for</span> React components, <span class="keyword">or</span> lowercase <span class="keyword">for</span> HTML elements.</span><br></pre></td></tr></table></figure><ul><li>所有组件必须有自己的render()方法,用于输出组件</li><li>render()方法中只能包含一个顶层标签,存在多个顶层标签的话,只会渲染最有一个标签</li><li>组件的用法与原生的 HTML 标签完全一致,可以任意加入属性,如name,在组件内部使用this.props对象获取</li><li>添加属性也有个注意的地方,class属性要写成className,for属性要写成htmlFor,注意javascript的关键字</li></ul><h3 id="this-props-children"><a href="#this-props-children" class="headerlink" title="this.props.children"></a>this.props.children</h3><ul><li>this.props对象的属性与组件属性一一对应,但是this.props.children属性列外,它表示组件的所有的子节点。</li><li>例子如下</li></ul><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"> <span class="tag"><<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/babel"</span>></span><span class="undefined"></span></span><br><span class="line"><span class="actionscript"> <span class="class"><span class="keyword">class</span> <span class="title">NoteList</span> <span class="keyword">extends</span> <span class="title">React</span>.<span class="title">Component</span></span>{</span></span><br><span class="line"><span class="undefined"> render(){</span></span><br><span class="line"><span class="actionscript"> <span class="keyword">return</span> (</span></span><br><span class="line"><span class="handlebars"><span class="xml"> <span class="tag"><<span class="name">ol</span>></span></span></span></span><br><span class="line"><span class="undefined"> {</span></span><br><span class="line"><span class="actionscript"> <span class="keyword">this</span>.props.children.map(<span class="function"><span class="keyword">function</span> <span class="params">(child)</span> </span>{</span></span><br><span class="line"><span class="javascript"> <span class="keyword">return</span> <span class="xml"><span class="tag"><<span class="name">li</span>></span>{child}<span class="tag"></<span class="name">li</span>></span></span>;</span></span><br><span class="line"><span class="undefined"> })</span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="handlebars"><span class="xml"> <span class="tag"></<span class="name">ol</span>></span></span></span></span><br><span class="line"><span class="undefined"> )</span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="undefined"> ReactDOM.render(</span></span><br><span class="line"><span class="handlebars"><span class="xml"> <span class="tag"><<span class="name">div</span>></span></span></span></span><br><span class="line"><span class="handlebars"><span class="xml"> <span class="tag"><<span class="name">NoteList</span>></span></span></span></span><br><span class="line"><span class="handlebars"><span class="xml"> <span class="tag"><<span class="name">div</span>></span>Simon<span class="tag"></<span class="name">div</span>></span></span></span></span><br><span class="line"><span class="handlebars"><span class="xml"> <span class="tag"><<span class="name">div</span>></span>Lucy<span class="tag"></<span class="name">div</span>></span></span></span></span><br><span class="line"><span class="handlebars"><span class="xml"> <span class="tag"><<span class="name">div</span>></span>李四<span class="tag"></<span class="name">div</span>></span></span></span></span><br><span class="line"><span class="handlebars"><span class="xml"> <span class="tag"></<span class="name">NoteList</span>></span></span></span></span><br><span class="line"><span class="handlebars"><span class="xml"> <span class="tag"></<span class="name">div</span>></span>,</span></span></span><br><span class="line"><span class="javascript"> <span class="built_in">document</span>.getElementById(<span class="string">"root"</span>)</span></span><br><span class="line"><span class="undefined"> );</span></span><br><span class="line"><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span></span><br></pre></td></tr></table></figure><h3 id="propsType"><a href="#propsType" class="headerlink" title="propsType"></a><a href="https://www.npmjs.com/package/prop-types" target="_blank" rel="noopener">propsType</a></h3><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">注意: React<span class="selector-class">.PropTypes</span> 自 React v15.<span class="number">5</span> 起已弃用。请使用 prop-types 库代替。</span><br><span class="line">更多的参考:https:<span class="comment">//www.npmjs.com/package/prop-types</span></span><br></pre></td></tr></table></figure><p>组件的属性可以接收任意值,字符串,对象,函数等等都可以。有些时候我们需要一种机制,验证别人使用组件的时候,提供的参数是否符合要求。</p><ul><li>例子如下,需要引用prop-types.js</li></ul><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">script</span> <span class="attr">src</span>=<span class="string">"https://unpkg.com/prop-types@15.6/prop-types.js"</span>></span><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span> </span><br><span class="line"></span><br><span class="line"><span class="tag"><<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/babel"</span>></span><span class="undefined"></span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="actionscript"> <span class="class"><span class="keyword">class</span> <span class="title">MyTitle</span> <span class="keyword">extends</span> <span class="title">React</span>.<span class="title">Component</span></span>{</span></span><br><span class="line"><span class="undefined"> render(){</span></span><br><span class="line"><span class="javascript"> <span class="keyword">return</span> <span class="xml"><span class="tag"><<span class="name">h1</span>></span>使用参数类型验证-{this.props.title}<span class="tag"></<span class="name">h1</span>></span></span></span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="actionscript"> <span class="comment">//定义组件Mytitle的属性title的类型验证</span></span></span><br><span class="line"><span class="undefined"> MyTitle.propTypes = {</span></span><br><span class="line"><span class="undefined"> title: PropTypes.string</span></span><br><span class="line"><span class="undefined"> };</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="actionscript"> <span class="keyword">const</span> data = <span class="number">124</span></span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="undefined"> ReactDOM.render(</span></span><br><span class="line"><span class="handlebars"><span class="xml"> <span class="tag"><<span class="name">MyTitle</span> <span class="attr">title</span> = <span class="string">{data}</span> ></span><span class="tag"></<span class="name">MyTitle</span>></span>,</span></span></span><br><span class="line"><span class="javascript"> <span class="built_in">document</span>.getElementById(<span class="string">"root"</span>)</span></span><br><span class="line"><span class="undefined"> );</span></span><br><span class="line"><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span></span><br></pre></td></tr></table></figure><h3 id="获取真实的DOM节点"><a href="#获取真实的DOM节点" class="headerlink" title="获取真实的DOM节点"></a>获取真实的DOM节点</h3><ul><li>组件并不是真实的DOM节点,而是存在内存中的一种虚拟结构,叫做虚拟DOM.</li><li>只有当它插入文档后,才会变成真实的DOM</li><li>根据React的设计,所有DOM的变动,都需要先在虚拟DOM上发生变化,然后再实际发生变动的部分,反映在真实的DOM上,这种算法叫DOM diff</li></ul><figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><script <span class="class"><span class="keyword">type</span></span>=<span class="string">"text/babel"</span>></span><br><span class="line"></span><br><span class="line"> <span class="class"><span class="keyword">class</span> <span class="title">MyComponent</span> <span class="keyword">extends</span> <span class="title">React</span>.<span class="title">Component</span></span>{</span><br><span class="line"></span><br><span class="line"> constructor(props){</span><br><span class="line"> <span class="keyword">super</span>(props)</span><br><span class="line"> <span class="comment">//创建一个ref,用于存储Input DOM元素</span></span><br><span class="line"> <span class="keyword">this</span>.textInput = <span class="type">React</span>.createRef()</span><br><span class="line"> <span class="comment">//将ref传递给函数</span></span><br><span class="line"> <span class="keyword">this</span>.handleClick = <span class="keyword">this</span>.handleClick.bind(<span class="keyword">this</span>)</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> handleClick(){</span><br><span class="line"> <span class="comment">//current可以取得DOM节点</span></span><br><span class="line"> <span class="keyword">this</span>.textInput.current.focus()</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> render(){</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <div></span><br><span class="line"> <span class="comment">//关联创建的ref到React的组件里</span></span><br><span class="line"> <input <span class="class"><span class="keyword">type</span></span>=<span class="string">"text"</span> ref={<span class="keyword">this</span>.textInput}/></span><br><span class="line"> <input <span class="class"><span class="keyword">type</span></span>=<span class="string">"button"</span> value = <span class="symbol">'Focus</span> the text button' onClick={<span class="keyword">this</span>.handleClick} /></span><br><span class="line"> </div></span><br><span class="line"> )</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="type">ReactDOM</span>.render(</span><br><span class="line"> <<span class="type">MyComponent</span> />,</span><br><span class="line"> document.getElementById(<span class="string">"root"</span>)</span><br><span class="line"> );</span><br><span class="line"></script></span><br></pre></td></tr></table></figure><h3 id="this-state"><a href="#this-state" class="headerlink" title="this.state"></a>this.state</h3><p>组件避免不了要与用户互动,React的一大创新,就是将组件看成一个状态机,一开始有个初始状态,然后用户互动,导致状态发生变化,从而触发重新渲染UI</p><figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><script <span class="class"><span class="keyword">type</span></span>=<span class="string">"text/babel"</span>></span><br><span class="line"></span><br><span class="line"> <span class="class"><span class="keyword">class</span> <span class="title">LikeButton</span> <span class="keyword">extends</span> <span class="title">React</span>.<span class="title">Component</span></span>{</span><br><span class="line"></span><br><span class="line"> constructor(props){</span><br><span class="line"> <span class="keyword">super</span>(props)</span><br><span class="line"> <span class="keyword">this</span>.state = {<span class="type">Liked</span>: <span class="literal">false</span>}</span><br><span class="line"> <span class="comment">//一定要绑定当前this给下面定义函数,才能使用this</span></span><br><span class="line"> <span class="keyword">this</span>.changeState = <span class="keyword">this</span>.changeState.bind(<span class="keyword">this</span>)</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> changeState(){</span><br><span class="line"> <span class="keyword">this</span>.setState({</span><br><span class="line"> <span class="type">Liked</span>:!<span class="keyword">this</span>.state.<span class="type">Liked</span></span><br><span class="line"> });</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> render(){</span><br><span class="line"> const text = <span class="keyword">this</span>.state.<span class="type">Liked</span> ? <span class="symbol">'lik</span>e' : <span class="symbol">'dislik</span>e'</span><br><span class="line"> <span class="keyword">return</span> <p onClick={<span class="keyword">this</span>.changeState}></span><br><span class="line"> {text} toggle it!!!</span><br><span class="line"> </p></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="type">ReactDOM</span>.render(</span><br><span class="line"> <<span class="type">LikeButton</span> />,</span><br><span class="line"> document.getElementById(<span class="string">"root"</span>)</span><br><span class="line"> );</span><br><span class="line"></script></span><br></pre></td></tr></table></figure><h3 id="组件的生命周期"><a href="#组件的生命周期" class="headerlink" title="组件的生命周期"></a>组件的生命周期</h3><ul><li>Mounting:已插入真实的DOM</li><li>Updating:正在被重新渲染</li><li>Unmounting:已移除真实的DOM</li></ul><p>React为每个状态都提供了2种处理函数,will函数在进入状态之前调用,did函数在进入状态之后调用。</p><ul><li>componentWillMount()</li><li>componentDidMount()</li><li>componentWillUpdate()</li><li>componentDidUpdate()</li><li>componentWillUnmount()</li></ul><p>React还提供2种特殊处理的函数</p><ul><li>componentWillReceiveProps(object nextProps):已加载组件收到新的参数时调用</li><li>shouldComponentUpdate(object nextProps, object nextState):组件判断是否重新渲染时调用</li></ul><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/babel"</span>></span><span class="undefined"></span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="actionscript"> <span class="class"><span class="keyword">class</span> <span class="title">LikeButton</span> <span class="keyword">extends</span> <span class="title">React</span>.<span class="title">Component</span></span>{</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="javascript"> <span class="keyword">constructor</span>(props){</span></span><br><span class="line"><span class="actionscript"> <span class="keyword">super</span>(props)</span></span><br><span class="line"><span class="actionscript"> <span class="keyword">this</span>.state = {Liked: <span class="literal">false</span>}</span></span><br><span class="line"><span class="actionscript"> <span class="keyword">this</span>.changeState = <span class="keyword">this</span>.changeState.bind(<span class="keyword">this</span>)</span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="undefined"> componentWillMount(){</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">"componentWillMount ..............."</span>)</span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="undefined"> componentDidMount(){</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">"componentDidMount ..............."</span>)</span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="undefined"> componentWillUpdate(){</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">"componentWillUpdate ..............."</span>)</span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="undefined"> componentDidUpdate(){</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">"componentDidUpdate ..............."</span>)</span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="undefined"> componentWillUnmount() {</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">"componentWillUnmount ..............."</span>)</span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="undefined"> componentWillReceiveProps(){</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">"componentWillReceiveProps ..............."</span>)</span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="undefined"> shouldComponentUpdate(){</span></span><br><span class="line"><span class="javascript"> <span class="built_in">console</span>.log(<span class="string">"shouldComponentUpdate ..............."</span>)</span></span><br><span class="line"><span class="actionscript"> <span class="keyword">return</span> <span class="literal">true</span></span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="undefined"> changeState(){</span></span><br><span class="line"><span class="actionscript"> <span class="keyword">this</span>.setState({</span></span><br><span class="line"><span class="actionscript"> Liked:!<span class="keyword">this</span>.state.Liked</span></span><br><span class="line"><span class="undefined"> });</span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="undefined"> render(){</span></span><br><span class="line"><span class="actionscript"> <span class="keyword">const</span> text = <span class="keyword">this</span>.state.Liked ? <span class="string">'like'</span> : <span class="string">'dislike'</span></span></span><br><span class="line"><span class="javascript"> <span class="keyword">return</span> <span class="xml"><span class="tag"><<span class="name">p</span> <span class="attr">onClick</span>=<span class="string">{this.changeState}</span>></span></span></span></span><br><span class="line"><span class="undefined"> {text} toggle it!!!</span></span><br><span class="line"><span class="handlebars"><span class="xml"> <span class="tag"></<span class="name">p</span>></span></span></span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="undefined"> ReactDOM.render(</span></span><br><span class="line"><span class="handlebars"><span class="xml"> <span class="tag"><<span class="name">LikeButton</span> /></span>,</span></span></span><br><span class="line"><span class="javascript"> <span class="built_in">document</span>.getElementById(<span class="string">"root"</span>)</span></span><br><span class="line"><span class="undefined"> );</span></span><br><span class="line"><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
react
</summary>
<category term="搬砖" scheme="http://chilam.me/categories/%E6%90%AC%E7%A0%96/"/>
<category term="react" scheme="http://chilam.me/tags/react/"/>
</entry>
<entry>
<title>babel</title>
<link href="http://chilam.me/2018/08/11/babel/"/>
<id>http://chilam.me/2018/08/11/babel/</id>
<published>2018-08-11T08:03:02.000Z</published>
<updated>2018-08-11T08:30:07.659Z</updated>
<content type="html"><![CDATA[<h2 id="bable"><a href="#bable" class="headerlink" title="bable"></a><a href="https://babeljs.io/" target="_blank" rel="noopener">bable</a></h2><p>babel是个转码器,你可以现在就用 ES6 编写程序,而不用担心现有环境是否支持</p><ul><li>安装:npm install –save-dev babel-cli</li><li>新建.babelrc文件内容如下:</li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"presets"</span>: [],</span><br><span class="line"> <span class="attr">"plugins"</span>: []</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="其中presets字段设定转码规则,可以通过一下命令安装"><a href="#其中presets字段设定转码规则,可以通过一下命令安装" class="headerlink" title="其中presets字段设定转码规则,可以通过一下命令安装"></a>其中presets字段设定转码规则,可以通过一下命令安装</h3><h4 id="安装es2015转码"><a href="#安装es2015转码" class="headerlink" title="安装es2015转码"></a>安装es2015转码</h4><ul><li>npm install –save-dev babel-preset-es2015</li></ul><figure class="highlight xquery"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"devDependencies"</span>: {</span><br><span class="line"> <span class="string">"babel-cli"</span>: <span class="string">"^6.26.0"</span>,</span><br><span class="line"> <span class="string">"babel-preset-es2015"</span>: <span class="string">"^6.24.1"</span></span><br><span class="line">},</span><br></pre></td></tr></table></figure><ul><li>编辑文件.baberc文件如下</li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"presets"</span>: [</span><br><span class="line"> <span class="string">"es2015"</span></span><br><span class="line"> ],</span><br><span class="line"> <span class="attr">"plugins"</span>: []</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="安装react转码规则"><a href="#安装react转码规则" class="headerlink" title="安装react转码规则"></a>安装react转码规则</h4><ul><li>npm install –save-dev babel-preset-react</li></ul><figure class="highlight xquery"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"devDependencies"</span>: {</span><br><span class="line"> <span class="string">"babel-cli"</span>: <span class="string">"^6.26.0"</span>,</span><br><span class="line"> <span class="string">"babel-preset-es2015"</span>: <span class="string">"^6.24.1"</span>,</span><br><span class="line"> <span class="string">"babel-preset-react"</span>: <span class="string">"^6.24.1"</span></span><br><span class="line">},</span><br></pre></td></tr></table></figure><ul><li>编辑文件.baberc文件如下</li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"presets"</span>: [</span><br><span class="line"> <span class="string">"es2015"</span>,</span><br><span class="line"> <span class="string">"react"</span></span><br><span class="line"> ],</span><br><span class="line"> <span class="attr">"plugins"</span>: []</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="测试转码"><a href="#测试转码" class="headerlink" title="测试转码"></a>测试转码</h3><ul><li>新建babel.js内容如下</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> input = [];</span><br><span class="line"></span><br><span class="line">input.map(<span class="function"><span class="params">item</span> =></span> item + <span class="number">1</span>);</span><br></pre></td></tr></table></figure><ul><li>编辑package.json添加build脚本</li></ul><figure class="highlight xquery"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"scripts"</span>: {</span><br><span class="line"> <span class="string">"build"</span>: <span class="string">"babel babel.js"</span></span><br><span class="line"> },</span><br></pre></td></tr></table></figure><ul><li>运行npm run build显示如下:</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">> node-demo@<span class="number">1.0</span><span class="number">.0</span> build /home/maxp/codes/node-demo</span><br><span class="line">> babel babel.js</span><br><span class="line"></span><br><span class="line"><span class="meta">"use strict"</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> input = [];</span><br><span class="line"></span><br><span class="line">input.map(<span class="function"><span class="keyword">function</span> (<span class="params">item</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> item + <span class="number">1</span>;</span><br><span class="line">});</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
babel
</summary>
<category term="搬砖" scheme="http://chilam.me/categories/%E6%90%AC%E7%A0%96/"/>
<category term="bable" scheme="http://chilam.me/tags/bable/"/>
</entry>
<entry>
<title>nodejs</title>
<link href="http://chilam.me/2018/08/11/nodejs/"/>
<id>http://chilam.me/2018/08/11/nodejs/</id>
<published>2018-08-11T06:00:42.000Z</published>
<updated>2018-08-14T08:48:45.606Z</updated>
<content type="html"><![CDATA[<h2 id="Hello-Nodejs"><a href="#Hello-Nodejs" class="headerlink" title="Hello Nodejs"></a>Hello Nodejs</h2><ul><li>新建hello.js</li></ul><figure class="highlight 1c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">console.<span class="built_in">log</span>('hello nodejs');</span><br></pre></td></tr></table></figure><ul><li>执行 node hello.js 命令</li></ul><h2 id="模块"><a href="#模块" class="headerlink" title="模块"></a>模块</h2><p>在nodejs环境中每一个js文件就称为一个模块</p><h3 id="定义一个模块-gt-hello-js"><a href="#定义一个模块-gt-hello-js" class="headerlink" title="定义一个模块->hello.js"></a>定义一个模块->hello.js</h3><ul><li>新建hello.js文件,内容如下所示:</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">hello</span>(<span class="params">name</span>)</span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'hello '</span> + name);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">hi</span>(<span class="params">name</span>)</span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'hi '</span>+ name);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//暴露函数hello,hi</span></span><br><span class="line">modules.exports = {hello,hi};</span><br></pre></td></tr></table></figure><h3 id="引用hello-js模块"><a href="#引用hello-js模块" class="headerlink" title="引用hello.js模块"></a>引用hello.js模块</h3><ul><li>新建index.js内容如下</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//引用模块</span></span><br><span class="line"><span class="keyword">var</span> {hello,hi} = <span class="built_in">require</span>(<span class="string">'./hello'</span>);</span><br><span class="line"></span><br><span class="line">greet(<span class="string">'simon'</span>);</span><br><span class="line">hi(<span class="string">'andy'</span>);</span><br></pre></td></tr></table></figure><h3 id="nodejs内置模块"><a href="#nodejs内置模块" class="headerlink" title="nodejs内置模块"></a>nodejs内置模块</h3><ul><li>文件读写模块,fs,示例如下:</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//引用内置模块-fs文件操作</span></span><br><span class="line"><span class="keyword">var</span> fs = <span class="built_in">require</span>(<span class="string">'fs'</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//读文件</span></span><br><span class="line">fs.readFile(<span class="string">'index.js'</span>,<span class="string">'utf-8'</span>,<span class="function"><span class="keyword">function</span> (<span class="params">err,data</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span>(err){</span><br><span class="line"> <span class="built_in">console</span>.log(err);</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> <span class="built_in">console</span>.log(data);</span><br><span class="line"> }</span><br><span class="line">});</span><br><span class="line"></span><br><span class="line"><span class="comment">//写文件</span></span><br><span class="line"><span class="keyword">var</span> data = <span class="string">'写文件内容'</span>;</span><br><span class="line">fs.writeFile(<span class="string">'demo.txt'</span>,data,<span class="function"><span class="keyword">function</span> (<span class="params">err</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span>(err){</span><br><span class="line"> <span class="built_in">console</span>.log(err)</span><br><span class="line"> }</span><br><span class="line">})</span><br></pre></td></tr></table></figure><ul><li>更多的内置模块使用参考-<a href="http://nodejs.cn/" target="_blank" rel="noopener">http://nodejs.cn/</a></li></ul><h2 id="npm"><a href="#npm" class="headerlink" title="npm"></a>npm</h2><h3 id="npm-安装卸载更新命令"><a href="#npm-安装卸载更新命令" class="headerlink" title="npm 安装卸载更新命令"></a>npm 安装卸载更新命令</h3><ul><li>查看当前npm版本:npm -v</li><li>安装当前最新npm版本:npm install npm@latest -g</li><li>安装未来发布npm版本:npm install npm@next -g</li><li>本地安装依赖包:npm install <package_name></li><li>全局安装依赖包: npm install <package_name> -g</li><li>本地安装运行时依赖包:npm install <package_name> –save或者npm install <package_name> -S</li><li>本地安装开发时依赖包:npm install <package_name> –save-dev或者npm install <package_name> -D</li><li>卸载本地安装依赖包:npm uninstall <package_name> 注意参数–save,–save-dev</li><li>卸载全局安装依赖包:npm uninstall <package_name> -g</li><li>更新全局安装依赖包:npm update <package_name> -g</li></ul><h3 id="npm查看包信息"><a href="#npm查看包信息" class="headerlink" title="npm查看包信息"></a>npm查看包信息</h3><ul><li>查看依赖包所有版本:npm view <package_name> versions</li><li>查看依赖包的最新版本:npm view <package_name> version</li><li>查看更多的依赖信息:npm info <package_name></li><li>查看本地安装依赖包版本:npm ls <package_name></li><li>查看全局安装依赖包版本:npm ls <package_name> -g</li><li>安装指定版本号的依赖包:npm install <package_name>@version</li></ul><h3 id="package-json"><a href="#package-json" class="headerlink" title="package.json"></a>package.json</h3><p>管理本地安装包版本</p><ul><li>作为一个描述文件,描述项目的包依赖</li><li>允许语义化的规则指定包依赖的版本</li></ul><h4 id="如何创建package-json文件"><a href="#如何创建package-json文件" class="headerlink" title="如何创建package.json文件"></a>如何创建package.json文件</h4><ul><li>npm init 进入交互模式,输入相关信息后,即生成。</li><li>npm init -yes 默认生成。</li></ul><h4 id="package-json内容解释"><a href="#package-json内容解释" class="headerlink" title="package.json内容解释"></a>package.json内容解释</h4><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"name"</span>: <span class="string">"node-demo"</span>,</span><br><span class="line"> <span class="attr">"version"</span>: <span class="string">"1.0.0"</span>,</span><br><span class="line"> <span class="attr">"description"</span>: <span class="string">"- 新建hello.js"</span>,</span><br><span class="line"> <span class="attr">"main"</span>: <span class="string">"index.js"</span>,</span><br><span class="line"> <span class="attr">"dependencies"</span>: {</span><br><span class="line"> <span class="attr">"jquery"</span>: <span class="string">"^3.1.0"</span>,</span><br><span class="line"> <span class="attr">"lodash"</span>: <span class="string">"^4.17.10"</span></span><br><span class="line"> },</span><br><span class="line"> <span class="attr">"devDependencies"</span>: {},</span><br><span class="line"> <span class="attr">"scripts"</span>: {</span><br><span class="line"> <span class="attr">"test"</span>: <span class="string">"echo \"Error: no test specified\" && exit 1"</span></span><br><span class="line"> },</span><br><span class="line"> <span class="attr">"keywords"</span>: [],</span><br><span class="line"> <span class="attr">"author"</span>: <span class="string">"maxp"</span>,</span><br><span class="line"> <span class="attr">"license"</span>: <span class="string">"ISC"</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>name:全部小写,没有空格,可以使用下划线或者横线</li><li>version:x.x.x格式,符合语义化版本规则</li><li>description:描述信息,有助于搜索</li><li>main:入口文件,一般都是index.js</li><li>scripts:支持的脚本,默认是一个空的test</li><li>dependencies:运行时候需要的依赖包</li><li>devDependencies:开发和测试需要的依赖包,一些打包插件之类的</li><li>keywords:关键字,有助于人们使用npm search搜索的时候发现</li><li>author:作者</li><li>license:版权信息</li></ul><h4 id="语义化版本规则"><a href="#语义化版本规则" class="headerlink" title="语义化版本规则"></a><a href="https://docs.npmjs.com/getting-started/semantic-versioning" target="_blank" rel="noopener">语义化版本规则</a></h4><figure class="highlight xquery"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"dependencies"</span>: {</span><br><span class="line"><span class="string">"jquery"</span>: <span class="string">"^3.1.0"</span>,</span><br><span class="line"><span class="string">"lodash"</span>: <span class="string">"^4.17.10"</span></span><br><span class="line">},</span><br></pre></td></tr></table></figure><p>以dependencies中”jquery”:”^3.1.0”为例子,jquery为包的名称,3.1.0为版本号,那么^代表什么?</p><p>如果一个项目打算与别人分享,应该从 1.0.0 版本开始。以后要升级版本应该遵循以下标准:</p><ul><li>补丁版本:解决了 Bug 或者一些较小的更改,增加最后一位数字,比如 1.0.1</li><li>小版本:增加了新特性,同时不会影响之前的版本,增加中间一位数字,比如 1.1.0</li><li>大版本:大改版,无法兼容之前的,增加第一位数字,比如 2.0.0</li></ul><p>了解了提供者的版本规范后, npm 包使用者就可以针对自己的需要填写依赖包的版本规则。(假设当前版本1.0.4)</p><ul><li>如果只打算接受补丁版本的更新(也就是最后一位的改变),就可以这么写: <ul><li>1.0</li><li>1.0.x</li><li>~1.0.4</li></ul></li><li>如果接受小版本的更新(第二位的改变),就可以这么写: <ul><li>1</li><li>1.x</li><li>^1.0.4</li></ul></li><li>如果可以接受大版本的更新(自然接受小版本和补丁版本的改变),就可以这么写: <ul><li>*</li><li>X</li></ul></li></ul><h3 id="npm-scripts"><a href="#npm-scripts" class="headerlink" title="npm scripts"></a><a href="http://www.ruanyifeng.com/blog/2016/10/npm_scripts.html" target="_blank" rel="noopener">npm scripts</a></h3><p>npm 允许在package.json文件里面,使用scripts字段定义脚本命令。</p><figure class="highlight stata"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"scripts"</span>: {</span><br><span class="line"> <span class="string">"test"</span>: <span class="string">"echo \"</span><span class="keyword">Error</span>: <span class="keyword">no</span> <span class="keyword">test</span> specified\<span class="string">" && exit 1"</span></span><br><span class="line">},</span><br></pre></td></tr></table></figure><ul><li>执行npm run test 实际执行的就是 “echo \”Error: no test specified\” && exit 1”</li><li>查看当前项目的可执行的脚本命令:npm run</li></ul><h4 id="原理"><a href="#原理" class="headerlink" title="原理"></a>原理</h4><ul><li>每当执行npm run,就会自动新建一个 Shell,在这个 Shell 里面执行指定的脚本命令。</li><li>npm run新建的这个 Shell,会将当前目录的node_modules/.bin子目录加入PATH变量,执行结束后,再将PATH变量恢复原样。</li><li>由于 npm 脚本就是 Shell 脚本,因为可以使用 Shell 通配符。<em>表示任意文件名,<strong>表示任意一层子目录。”lint”: “jshint </strong>/</em>.js”</li><li>如果要将通配符传入原始命令,防止被 Shell 转义,要将星号转义。”test”: “tap test/*.js”</li><li>向 npm 脚本传入参数,要使用–标明。 </li></ul>]]></content>
<summary type="html">
nodejs
</summary>
<category term="搬砖" scheme="http://chilam.me/categories/%E6%90%AC%E7%A0%96/"/>
<category term="nodejs" scheme="http://chilam.me/tags/nodejs/"/>
</entry>
<entry>
<title>2.面试准备-框架</title>
<link href="http://chilam.me/2018/06/20/interview-2/"/>
<id>http://chilam.me/2018/06/20/interview-2/</id>
<published>2018-06-20T12:57:56.000Z</published>
<updated>2018-07-06T13:04:50.395Z</updated>
<content type="html"><![CDATA[<h2 id="阐述Session加载实体对象的过程。"><a href="#阐述Session加载实体对象的过程。" class="headerlink" title="阐述Session加载实体对象的过程。"></a>阐述Session加载实体对象的过程。</h2><ul><li>Session在调用数据库查询功能之前,首先会在一级缓存中通过实体类型和主键进行查找,如果一级缓存查找命中且数据状态合法,则直接返回; </li><li>如果一级缓存没有命中,接下来Session会在当前NonExists记录(相当于一个查询黑名单,如果出现重复的无效查询可以迅速做出判断,从而提升性能)中进行查找,如果NonExists中存在同样的查询条件,则返回null; </li><li>如果一级缓存查询失败则查询二级缓存,如果二级缓存命中则直接返回; </li><li>如果之前的查询都未命中,则发出SQL语句,如果查询未发现对应记录则将此次查询添加到Session的NonExists中加以记录,并返回null; </li><li>根据映射配置和SQL语句得到ResultSet,并创建对应的实体对象; </li><li>将对象纳入Session(一级缓存)的管理; </li><li>如果有对应的拦截器,则执行拦截器的onLoad方法; </li><li>如果开启并设置了要使用二级缓存,则将数据对象纳入二级缓存; </li><li>返回数据对象。</li></ul><h2 id="锁机制有什么用?简述Hibernate的悲观锁和乐观锁机制。"><a href="#锁机制有什么用?简述Hibernate的悲观锁和乐观锁机制。" class="headerlink" title="锁机制有什么用?简述Hibernate的悲观锁和乐观锁机制。"></a>锁机制有什么用?简述Hibernate的悲观锁和乐观锁机制。</h2><p>有些业务逻辑在执行过程中要求对数据进行排他性的访问,于是需要通过一些机制保证在此过程中数据被锁住不会被外界修改,这就是所谓的锁机制。 Hibernate支持悲观锁和乐观锁两种锁机制</p><ul><li>悲观锁,顾名思义悲观的认为在数据处理过程中极有可能存在修改数据的并发事务(包括本系统的其他事务或来自外部系统的事务),于是将处理的数据设置为锁定状态。悲观锁必须依赖数据库本身的锁机制才能真正保证数据访问的排他性,</li><li>乐观锁,顾名思义,对并发事务持乐观态度(认为对数据的并发操作不会经常性的发生),通过更加宽松的锁机制来解决由于悲观锁排他性的数据访问对系统性能造成的严重影响。最常见的乐观锁是通过数据版本标识来实现的,读取数据时获得数据的版本号,更新数据时将此版本号加1,然后和数据库表对应记录的当前版本号进行比较,如果提交的数据版本号大于数据库中此记录的当前版本号则更新数据,否则认为是过期数据无法更新。Hibernate中通过Session的get()和load()方法从数据库中加载对象时可以通过参数指定使用悲观锁;而乐观锁可以通过给实体类加整型的版本字段再通过XML或@Version注解进行配置。</li></ul><h2 id="如何理解Hibernate的延迟加载机制?在实际应用中,延迟加载与Session关闭的矛盾是如何处理的?"><a href="#如何理解Hibernate的延迟加载机制?在实际应用中,延迟加载与Session关闭的矛盾是如何处理的?" class="headerlink" title="如何理解Hibernate的延迟加载机制?在实际应用中,延迟加载与Session关闭的矛盾是如何处理的?"></a>如何理解Hibernate的延迟加载机制?在实际应用中,延迟加载与Session关闭的矛盾是如何处理的?</h2><p>延迟加载就是并不是在读取的时候就把数据加载进来,而是等到使用时再加载。Hibernate使用了虚拟代理机制实现延迟加载,我们使用Session的load()方法加载数据或者一对多关联映射在使用延迟加载的情况下从一的一方加载多的一方,得到的都是虚拟代理,简单的说返回给用户的并不是实体本身,而是实体对象的代理。代理对象在用户调用getter方法时才会去数据库加载数据。但加载数据就需要数据库连接。而当我们把会话关闭时,数据库连接就同时关闭了。</p><h3 id="延迟加载与session关闭的矛盾一般可以这样处理:"><a href="#延迟加载与session关闭的矛盾一般可以这样处理:" class="headerlink" title="延迟加载与session关闭的矛盾一般可以这样处理:"></a>延迟加载与session关闭的矛盾一般可以这样处理:</h3><ul><li>关闭延迟加载特性。这种方式操作起来比较简单,因为Hibernate的延迟加载特性是可以通过映射文件或者注解进行配置的,但这种解决方案存在明显的缺陷。首先,出现”no session or session was closed”通常说明系统中已经存在主外键关联,如果去掉延迟加载的话,每次查询的开销都会变得很大。 </li><li>在session关闭之前先获取需要查询的数据,可以使用工具方法Hibernate.isInitialized()判断对象是否被加载,如果没有被加载则可以使用Hibernate.initialize()方法加载对象。 </li><li>使用拦截器或过滤器延长Session的生命周期直到视图获得数据。Spring整合Hibernate提供的OpenSessionInViewFilter和OpenSessionInViewInterceptor就是这种做法。</li></ul><h2 id="谈一下你对继承映射的理解"><a href="#谈一下你对继承映射的理解" class="headerlink" title="谈一下你对继承映射的理解"></a>谈一下你对继承映射的理解</h2><p>继承关系的映射策略有三种: </p><ul><li>每个继承结构一张表(table per class hierarchy),不管多少个子类都用一张表。 </li><li>每个子类一张表(table per subclass),公共信息放一张表,特有信息放单独的表。 </li><li>每个具体类一张表(table per concrete class),有多少个子类就有多少张表。 </li></ul><p>第一种方式属于单表策略,其优点在于查询子类对象的时候无需表连接,查询速度快,适合多态查询;缺点是可能导致表很大。<br>后两种方式属于多表策略,其优点在于数据存储紧凑,其缺点是需要进行连接查询,不适合多态查询。</p><h2 id="常见的hibernate的优化策略"><a href="#常见的hibernate的优化策略" class="headerlink" title="常见的hibernate的优化策略"></a>常见的hibernate的优化策略</h2><ul><li>制定合理的缓存策略(二级缓存、查询缓存)。 </li><li>采用合理的Session管理机制。 </li><li>尽量使用延迟加载特性。 </li><li>设定合理的批处理参数。 </li><li>如果可以,选用UUID作为主键生成器。 </li><li>如果可以,选用基于版本号的乐观锁替代悲观锁。 </li><li>在开发过程中, 开启hibernate.show_sql选项查看生成的SQL,从而了解底层的状况;开发完成后关闭此选项。 </li><li>考虑数据库本身的优化,合理的索引、恰当的数据分区策略等都会对持久层的性能带来可观的提升,但这些需要专业的DBA(数据库管理员)提供支持。</li></ul><h2 id="OneToMany注解的mappedBy属性有什么作用?"><a href="#OneToMany注解的mappedBy属性有什么作用?" class="headerlink" title="@OneToMany注解的mappedBy属性有什么作用?"></a>@OneToMany注解的mappedBy属性有什么作用?</h2><p>@OneToMany用来配置一对多关联映射,但通常情况下,一对多关联映射都由多的一方来维护关联关系,例如学生和班级,应该在学生类中添加班级属性来维持学生和班级的关联关系(在数据库中是由学生表中的外键班级编号来维护学生表和班级表的多对一关系),如果要使用双向关联,在班级类中添加一个容器属性来存放学生,并使用@OneToMany注解进行映射,此时mappedBy属性就非常重要。如果使用XML进行配置,可以用<set>标签的inverse=”true”设置来达到同样的效果。</set></p><h2 id="MyBatis中使用-和-书写占位符有什么区别?"><a href="#MyBatis中使用-和-书写占位符有什么区别?" class="headerlink" title="MyBatis中使用#和$书写占位符有什么区别?"></a>MyBatis中使用#和$书写占位符有什么区别?</h2><ul><li>井号将传入的数据都当成一个字符串,会对传入的数据自动加上引号;</li><li>美元符号将传入的数据直接显示生成在SQL中。</li><li>使用美元符号占位符可能会导致SQL注射攻击,</li><li>能用井号的地方就不要使用美元符号,写order by子句的时候应该用美元符号而不是井号。</li></ul><h2 id="解释一下MyBatis中命名空间(namespace)的作用。"><a href="#解释一下MyBatis中命名空间(namespace)的作用。" class="headerlink" title="解释一下MyBatis中命名空间(namespace)的作用。"></a>解释一下MyBatis中命名空间(namespace)的作用。</h2><p>在大型项目中,可能存在大量的SQL语句,这时候为每个SQL语句起一个唯一的标识(ID)就变得并不容易了。为了解决这个问题,在MyBatis中,可以为每个映射文件起一个唯一的命名空间,这样定义在这个映射文件中的每个SQL语句就成了定义在这个命名空间中的一个ID。只要我们能够保证每个命名空间中这个ID是唯一的,即使在不同映射文件中的语句ID相同,也不会再产生冲突了。</p><h2 id="什么是IoC和DI?DI是如何实现的?"><a href="#什么是IoC和DI?DI是如何实现的?" class="headerlink" title="什么是IoC和DI?DI是如何实现的?"></a>什么是IoC和DI?DI是如何实现的?</h2><p>IoC叫控制反转,是Inversion of Control的缩写,DI(Dependency Injection)叫依赖注入,是对IoC更简单的诠释,控制反转是把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的”控制反转”就是对组件对象控制权的转移,从程序代码本身转移到了外部容器,由容器来创建对象并管理对象之间的依赖关系。</p><p>IoC体现了好莱坞原则 - “Don’t call me, we will call you”。依赖注入的基本原则是应用组件不应该负责查找资源或者其他依赖的协作对象。配置对象的工作应该由容器负责,查找资源的逻辑应该从应用组件的代码中抽取出来,交给容器来完成。</p><p>DI是对IoC更准确的描述,即组件之间的依赖关系由容器在运行期决定,形象的来说,即由容器动态的将某种依赖关系注入到组件之中。</p><p>依赖注入可以通过setter方法注入(设值注入)、构造器注入和接口注入三种方式来实现,Spring支持setter注入和构造器注入,通常使用构造器注入来注入必须的依赖关系,对于可选的依赖关系,则setter注入是更好的选择,setter注入需要类提供无参构造器或者无参的静态工厂方法来创建对象。</p><h2 id="Spring中Bean的作用域有哪些?"><a href="#Spring中Bean的作用域有哪些?" class="headerlink" title="Spring中Bean的作用域有哪些?"></a>Spring中Bean的作用域有哪些?</h2><p>在Spring的早期版本中,仅有两个作用域:singleton和prototype,前者表示Bean以单例的方式存在;后者表示每次从容器中调用Bean时,都会返回一个新的实例,prototype通常翻译为原型。</p><p>Spring 2.x中针对WebApplicationContext新增了3个作用域,分别是:request(每次HTTP请求都会创建一个新的Bean)、session(同一个HttpSession共享同一个Bean,不同的HttpSession使用不同的Bean)和globalSession(同一个全局Session共享一个Bean)。</p><h2 id="ThreadLocal"><a href="#ThreadLocal" class="headerlink" title="ThreadLocal"></a>ThreadLocal</h2><p>ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。ThreadLocal,顾名思义是线程的一个本地化对象,当工作于多线程中的对象使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程分配一个独立的变量副本,所以每一个线程都可以独立的改变自己的副本,而不影响其他线程所对应的副本。从线程的角度看,这个变量就像是线程的本地变量。</p><p>ThreadLocal类非常简单好用,只有四个方法,能用上的也就是下面三个方法: </p><ul><li>void set(T value):设置当前线程的线程局部变量的值。 </li><li>T get():获得当前线程所对应的线程局部变量的值。 </li><li>void remove():删除当前线程中线程局部变量的值。</li></ul><h2 id="解释一下什么叫AOP(面向切面编程)?"><a href="#解释一下什么叫AOP(面向切面编程)?" class="headerlink" title="解释一下什么叫AOP(面向切面编程)?"></a>解释一下什么叫AOP(面向切面编程)?</h2><p>AOP(Aspect-Oriented Programming)指一种程序设计范型,该范型以一种称为切面(aspect)的语言构造为基础,切面是一种新的模块化机制,用来描述分散在对象、类或方法中的横切关注点(crosscutting concern)。</p><h2 id="你如何理解AOP中的连接点(Joinpoint)、切点(Pointcut)、增强(Advice)、引介(Introduction)、织入(Weaving)、切面(Aspect)这些概念?"><a href="#你如何理解AOP中的连接点(Joinpoint)、切点(Pointcut)、增强(Advice)、引介(Introduction)、织入(Weaving)、切面(Aspect)这些概念?" class="headerlink" title="你如何理解AOP中的连接点(Joinpoint)、切点(Pointcut)、增强(Advice)、引介(Introduction)、织入(Weaving)、切面(Aspect)这些概念?"></a>你如何理解AOP中的连接点(Joinpoint)、切点(Pointcut)、增强(Advice)、引介(Introduction)、织入(Weaving)、切面(Aspect)这些概念?</h2><ul><li>连接点(Joinpoint):程序执行的某个特定位置(如:某个方法调用前、调用后,方法抛出异常后)。一个类或一段程序代码拥有一些具有边界性质的特定点,这些代码中的特定点就是连接点。Spring仅支持方法的连接点。</li><li>切点(Pointcut):如果连接点相当于数据中的记录,那么切点相当于查询条件,一个切点可以匹配多个连接点。Spring AOP的规则解析引擎负责解析切点所设定的查询条件,找到对应的连接点。 </li><li>增强(Advice):增强是织入到目标类连接点上的一段程序代码。Spring提供的增强接口都是带方位名的,如:BeforeAdvice、AfterReturningAdvice、ThrowsAdvice等。很多资料上将增强译为“通知”,这明显是个词不达意的翻译,让很多程序员困惑了许久。</li><li>引介(Introduction):引介是一种特殊的增强,它为类添加一些属性和方法。这样,即使一个业务类原本没有实现某个接口,通过引介功能,可以动态的未该业务类添加接口的实现逻辑,让业务类成为这个接口的实现类。 </li><li>织入(Weaving):织入是将增强添加到目标类具体连接点上的过程,AOP有三种织入方式:①编译期织入:需要特殊的Java编译期(例如AspectJ的ajc);②装载期织入:要求使用特殊的类加载器,在装载类的时候对类进行增强;③运行时织入:在运行时为目标类生成代理实现增强。Spring采用了动态代理的方式实现了运行时织入,而AspectJ采用了编译期织入和装载期织入的方式。 </li><li>切面(Aspect):切面是由切点和增强(引介)组成的,它包括了对横切关注功能的定义,也包括了对连接点的定义。</li></ul><h2 id="Spring中自动装配的方式有哪些?"><a href="#Spring中自动装配的方式有哪些?" class="headerlink" title="Spring中自动装配的方式有哪些?"></a>Spring中自动装配的方式有哪些?</h2><ul><li>no:不进行自动装配,手动设置Bean的依赖关系。 </li><li>byName:根据Bean的名字进行自动装配。 </li><li>byType:根据Bean的类型进行自动装配。 </li><li>constructor:类似于byType,不过是应用于构造器的参数,如果正好有一个Bean与构造器的参数类型相同则可以自动装配,否则会导致错误。 </li><li>autodetect:如果有默认的构造器,则通过constructor的方式进行自动装配,否则使用byType的方式进行自动装配。</li></ul><h2 id="Spring支持的事务管理类型有哪些?你在项目中使用哪种方式?"><a href="#Spring支持的事务管理类型有哪些?你在项目中使用哪种方式?" class="headerlink" title="Spring支持的事务管理类型有哪些?你在项目中使用哪种方式?"></a>Spring支持的事务管理类型有哪些?你在项目中使用哪种方式?</h2><p>Spring支持编程式事务管理和声明式事务管理。许多Spring框架的用户选择声明式事务管理,因为这种方式和应用程序的关联较少,因此更加符合轻量级容器的概念。声明式事务管理要优于编程式事务管理,尽管在灵活性方面它弱于编程式事务管理,因为编程式事务允许你通过代码控制业务。</p><p>事务分为全局事务和局部事务。全局事务由应用服务器管理,需要底层服务器JTA支持(如WebLogic、WildFly等)。局部事务和底层采用的持久化方案有关,例如使用JDBC进行持久化时,需要使用Connetion对象来操作事务;而采用Hibernate进行持久化时,需要使用Session对象来操作事务。</p><ul><li>DataSourceTransactionManager</li><li>HibernateTransactionManager</li><li>JdoTransactionManager</li><li>JtaTransactionManager</li><li>PersistenceBrokerTransactionManager</li></ul><p>Spring的事务管理机制是一种典型的策略模式,PlatformTransactionManager代表事务管理接口,该接口定义了三个方法,该接口并不知道底层如何管理事务,但是它的实现类必须提供getTransaction()方法(开启事务)、commit()方法(提交事务)、rollback()方法(回滚事务)的多态实现,这样就可以用不同的实现类代表不同的事务管理策略。</p><p>使用JTA全局事务策略时,需要底层应用服务器支持,而不同的应用服务器所提供的JTA全局事务可能存在细节上的差异,因此实际配置全局事务管理器是可能需要使用JtaTransactionManager的子类,如:WebLogicJtaTransactionManager(Oracle的WebLogic服务器提供)、UowJtaTransactionManager(IBM的WebSphere服务器提供)等。</p><h2 id="Spring-MVC的工作原理是怎样的?"><a href="#Spring-MVC的工作原理是怎样的?" class="headerlink" title="Spring MVC的工作原理是怎样的?"></a>Spring MVC的工作原理是怎样的?</h2><ul><li>客户端的所有请求都交给前端控制器DispatcherServlet来处理,它会负责调用系统的其他模块来真正处理用户的请求。 </li><li>DispatcherServlet收到请求后,将根据请求的信息(包括URL、HTTP协议方法、请求头、请求参数、Cookie等)以及HandlerMapping的配置找到处理该请求的Handler(任何一个对象都可以作为请求的Handler)。 </li><li>在这个地方Spring会通过HandlerAdapter对该处理器进行封装。 </li><li>HandlerAdapter是一个适配器,它用统一的接口对各种Handler中的方法进行调用。 </li><li>Handler完成对用户请求的处理后,会返回一个ModelAndView对象给DispatcherServlet,ModelAndView顾名思义,包含了数据模型以及相应的视图的信息。 </li><li>ModelAndView的视图是逻辑视图,DispatcherServlet还要借助ViewResolver完成从逻辑视图到真实视图对象的解析工作。 </li><li>当得到真正的视图对象后,DispatcherServlet会利用视图对象对模型数据进行渲染。 </li><li>客户端得到响应,可能是一个普通的HTML页面,也可以是XML或JSON字符串,还可以是一张图片或者一个PDF文件。</li></ul><h2 id="阐述Spring框架中Bean的生命周期?"><a href="#阐述Spring框架中Bean的生命周期?" class="headerlink" title="阐述Spring框架中Bean的生命周期?"></a>阐述Spring框架中Bean的生命周期?</h2><p><a href="https://www.cnblogs.com/zrtqsk/p/3735273.html" target="_blank" rel="noopener">很详细的参考链接</a></p><p><img src="https://images0.cnblogs.com/i/580631/201405/181453414212066.png" alt=""></p><p><img src="http://images.51cto.com/files/uploadimg/20110419/0930070.png" alt=""></p><ul><li>Spring IoC容器找到关于Bean的定义并实例化该Bean。 </li><li>Spring IoC容器对Bean进行依赖注入。 </li><li>如果Bean实现了BeanNameAware接口,则将该Bean的id传给setBeanName方法。 </li><li>如果Bean实现了BeanFactoryAware接口,则将BeanFactory对象传给setBeanFactory方法。 </li><li>如果Bean实现了BeanPostProcessor接口,则调用其postProcessBeforeInitialization方法</li><li>如果Bean实现了InitializingBean接口,则调用其afterPropertySet方法。 </li><li>如果有和Bean关联的BeanPostProcessors对象,则这些对象的postProcessAfterInitialization方法被调用。 </li><li>当销毁Bean实例时,如果Bean实现了DisposableBean接口,则调用其destroy方法。</li></ul><p>Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:</p><ol><li>Bean自身的方法这个包括了Bean本身调用的方法和通过配置文件中<bean>的init-method和destroy-method指定的方法</bean></li><li>Bean级生命周期接口方法:这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这些接口的方法</li><li>容器级生命周期接口方法:这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。</li><li>工厂后处理器接口方法这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。</li></ol><h2 id="什么是XSS攻击?什么是SQL注入攻击?什么是CSRF攻击?"><a href="#什么是XSS攻击?什么是SQL注入攻击?什么是CSRF攻击?" class="headerlink" title="什么是XSS攻击?什么是SQL注入攻击?什么是CSRF攻击?"></a>什么是XSS攻击?什么是SQL注入攻击?什么是CSRF攻击?</h2><ul><li>XSS(Cross Site Script,跨站脚本攻击)是向网页中注入恶意脚本在用户浏览网页时在用户浏览器中执行恶意脚本的攻击方式。跨站脚本攻击分有两种形式:反射型攻击(诱使用户点击一个嵌入恶意脚本的链接以达到攻击的目标,目前有很多攻击者利用论坛、微博发布含有恶意脚本的URL就属于这种方式)和持久型攻击(将恶意脚本提交到被攻击网站的数据库中,用户浏览网页时,恶意脚本从数据库中被加载到页面执行,QQ邮箱的早期版本就曾经被利用作为持久型跨站脚本攻击的平台)。XSS虽然不是什么新鲜玩意,但是攻击的手法却不断翻新,防范XSS主要有两方面:消毒(对危险字符进行转义)和HttpOnly(防范XSS攻击者窃取Cookie数据)。 </li><li>SQL注入攻击是注入攻击最常见的形式(此外还有OS注入攻击(Struts 2的高危漏洞就是通过OGNL实施OS注入攻击导致的)),当服务器使用请求参数构造SQL语句时,恶意的SQL被嵌入到SQL中交给数据库执行。SQL注入攻击需要攻击者对数据库结构有所了解才能进行,攻击者想要获得表结构有多种方式:(1)如果使用开源系统搭建网站,数据库结构也是公开的(目前有很多现成的系统可以直接搭建论坛,电商网站,虽然方便快捷但是风险是必须要认真评估的);</li><li>CSRF攻击(Cross Site Request Forgery,跨站请求伪造)是攻击者通过跨站请求,以合法的用户身份进行非法操作(如转账或发帖等)。CSRF的原理是利用浏览器的Cookie或服务器的Session,盗取用户身份,其原理如下图所示。防范CSRF的主要手段是识别请求者的身份,主要有以下几种方式:(1)在表单中添加令牌(token);(2)验证码;</li></ul><h2 id="Spring中的BeanFactory和ApplicationContext有什么联系?"><a href="#Spring中的BeanFactory和ApplicationContext有什么联系?" class="headerlink" title="Spring中的BeanFactory和ApplicationContext有什么联系?"></a>Spring中的BeanFactory和ApplicationContext有什么联系?</h2><ul><li>Spring通过配置文件描述Bean以及Bean之间的依赖关系,利用Java的反射机制实现Bean的实例化,并建立Bean之间的依赖关系,在此基础上,Spring的IoC容器还提供了Bean实例缓存、生命周期管理、Bean实例代理、事件发布、资源装载等高级服务。BeanFactory是Spring框架最核心的接口,它提供了IoC容器的配置机制。</li><li>ApplicationContext建立在BeanFactory之上,提供了更多面向应用的功能,包括对国际化和框架事件体系的支持。通常将BeanFactory称为IoC容器,而ApplicationContext称为应用上下文,前者更倾向于Spring本身,后者更倾向于开发者,因此被使用得更多。</li><li></li></ul>]]></content>
<summary type="html">
框架会问的问题
</summary>
<category term="搬砖" scheme="http://chilam.me/categories/%E6%90%AC%E7%A0%96/"/>
<category term="java" scheme="http://chilam.me/tags/java/"/>
</entry>
<entry>
<title>1.收藏的一些链接</title>
<link href="http://chilam.me/2018/06/17/links/"/>
<id>http://chilam.me/2018/06/17/links/</id>
<published>2018-06-17T06:28:01.000Z</published>
<updated>2018-07-06T07:43:07.369Z</updated>
<content type="html"><![CDATA[<h2 id="java"><a href="#java" class="headerlink" title="java"></a>java</h2><ul><li><a href="http://www.oracle.com/technetwork/java/javase/archive-139210.html" target="_blank" rel="noopener">Java所有版本</a></li><li><a href="http://hllvm.group.iteye.com/" target="_blank" rel="noopener">高级语言虚拟机圈子</a></li><li><a href="http://icyfenix.iteye.com/" target="_blank" rel="noopener">深入理解JVM作者博客</a></li><li><a href="https://docs.oracle.com/javase/10/" target="_blank" rel="noopener">JDK各个版本文档</a></li><li><a href="https://docs.oracle.com/javase/7/docs/index.html" target="_blank" rel="noopener">JDK7文档</a></li><li><a href="https://docs.oracle.com/javase/8/docs/index.html" target="_blank" rel="noopener">JDK8文档</a></li><li><a href="https://docs.oracle.com/javase/specs/index.html" target="_blank" rel="noopener">所有版本java语言和虚拟机规范</a></li><li><a href="https://docs.oracle.com/javase/tutorial/tutorialLearningPaths.html" target="_blank" rel="noopener">java官方学习文档</a></li></ul><h2 id="优秀博客"><a href="#优秀博客" class="headerlink" title="优秀博客"></a>优秀博客</h2><ul><li><a href="https://www.jianshu.com/u/581f548ef0ec" target="_blank" rel="noopener">李艳鹏-分布式服务相关</a></li><li><a href="http://ginobefunny.com/" target="_blank" rel="noopener">JVM相关</a></li><li><a href="https://www.jianshu.com/nb/13314305" target="_blank" rel="noopener">Java工程师系列</a></li><li><a href="http://www.cnblogs.com/ysocean/" target="_blank" rel="noopener">Java基础</a></li><li><a href="http://www.coolblog.xyz/" target="_blank" rel="noopener">比较多的源码分析-spring,jdk</a></li><li><a href="https://www.jianshu.com/p/bbd4cb15bc5f" target="_blank" rel="noopener">idea的使用文档</a></li><li><a href="https://www.cnblogs.com/oldtrafford/p/6883796.html" target="_blank" rel="noopener">G1垃圾收集</a></li><li><a href="https://github.com/crossoverJie/Java-Interview" target="_blank" rel="noopener">Java面试准备相关的</a></li><li><a href="https://blog.csdn.net/jackfrued" target="_blank" rel="noopener">骆昊的技术专栏</a></li></ul><h2 id="个人"><a href="#个人" class="headerlink" title="个人"></a>个人</h2><ul><li><a href="https://leetcode.com/" target="_blank" rel="noopener">LeetCode</a></li><li><a href="https://www.processon.com/diagrams" target="_blank" rel="noopener">在线画图工具</a></li><li><a href="http://jiantuku.com/#/albums/60563?scope=public" target="_blank" rel="noopener">图片存储</a></li><li><a href="https://smallpdf.com/cn/jpg-to-pdf" target="_blank" rel="noopener">JPG转PDF</a></li></ul>]]></content>
<summary type="html">
一些链接,随时会更新
</summary>
<category term="搬砖" scheme="http://chilam.me/categories/%E6%90%AC%E7%A0%96/"/>
<category term="links" scheme="http://chilam.me/tags/links/"/>
</entry>
<entry>
<title>黑胡椒意面</title>
<link href="http://chilam.me/2018/06/16/life-dinner-noodle/"/>
<id>http://chilam.me/2018/06/16/life-dinner-noodle/</id>
<published>2018-06-16T03:21:41.000Z</published>
<updated>2018-07-05T13:53:42.812Z</updated>
<content type="html"><![CDATA[<h2 id="意大利面"><a href="#意大利面" class="headerlink" title="意大利面"></a>意大利面</h2><ul><li>烹饪时间:2018年6月16日 午餐</li></ul><h3 id="材料"><a href="#材料" class="headerlink" title="材料"></a>材料</h3><p><img src="http://orkt468tj.bkt.clouddn.com/18-6-18/87605624.jpg" alt=""></p><ul><li>黑胡椒汁</li><li>番茄沙司</li><li>圆头香菇</li><li>胡萝卜半根</li><li>洋葱半个</li><li>红椒半个</li><li>西红柿一个</li><li>秘制酱肉</li><li>意大利面250g</li></ul><h3 id="制作步骤"><a href="#制作步骤" class="headerlink" title="制作步骤"></a>制作步骤</h3><ol><li>将意面煮15min,捞起来晒起</li><li>热油炒酱肉1分钟,在放胡萝卜和红椒,炒2分钟</li><li>放西红柿和洋葱炒1分钟</li><li>倒入意面,放番茄沙司,和胡萝卜汁搅拌均匀</li><li>放盐调味起锅</li></ol><h3 id="成品"><a href="#成品" class="headerlink" title="成品"></a>成品</h3><p><img src="http://orkt468tj.bkt.clouddn.com/18-6-18/84130571.jpg" alt=""></p><ul><li>黑胡椒和番茄沙司才是王道!!!</li><li>当然还有秘制酱肉</li><li>菜还是少了,该用一根胡萝卜,和一个红椒</li></ul>]]></content>
<summary type="html">
美食的啦
</summary>
<category term="1房2人3餐4季" scheme="http://chilam.me/categories/1%E6%88%BF2%E4%BA%BA3%E9%A4%904%E5%AD%A3/"/>
<category term="life" scheme="http://chilam.me/tags/life/"/>
</entry>
<entry>
<title>1.面试准备-Java</title>
<link href="http://chilam.me/2018/06/14/interview-1/"/>
<id>http://chilam.me/2018/06/14/interview-1/</id>
<published>2018-06-14T12:57:56.000Z</published>
<updated>2018-07-06T13:06:21.633Z</updated>
<content type="html"><![CDATA[<h2 id="面向的对象特征"><a href="#面向的对象特征" class="headerlink" title="面向的对象特征"></a>面向的对象特征</h2><ul><li>抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。 </li><li>继承:继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类、基类);得到继承信息的类被称为子类(派生类)。</li><li>封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。</li><li>多态性:多态性是指允许不同子类型的对象对同一消息作出不同的响应。简单的说就是用同样的对象引用调用同样的方法但是做了不同的事情。多态性分为编译时的多态性和运行时的多态性。如果将对象的方法视为对象向外界提供的服务,那么运行时的多态性可以解释为:当A系统访问B系统提供的服务时,B系统有多种提供服务的方式,但一切对A系统来说都是透明的。</li><li>方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称为后绑定)</li><li>运行时的多态是面向对象最精髓的东西,要实现多态需要做两件事:<ul><li>方法重写(子类继承父类并重写父类中已有的或抽象的方法);</li><li>对象造型(用父类型引用引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)。</li></ul></li></ul><h2 id="访问修饰符public-private-protected-以及不写(默认)时的区别?"><a href="#访问修饰符public-private-protected-以及不写(默认)时的区别?" class="headerlink" title="访问修饰符public,private,protected,以及不写(默认)时的区别?"></a>访问修饰符public,private,protected,以及不写(默认)时的区别?</h2><p><img src="http://orkt468tj.bkt.clouddn.com/18-7-6/75065795.jpg" alt=""></p><p>类的成员不写访问修饰时默认为default。默认对于同一个包中的其他类相当于公开(public),对于不是同一个包中的其他类相当于私有(private)。受保护(protected)对子类相当于公开,对不是同一包中的没有父子关系的类相当于私有。Java中,外部类的修饰符只能是public或默认,类的成员(包括内部类)的修饰符可以是以上四种。</p><h2 id="String-是最基本的数据类型吗?"><a href="#String-是最基本的数据类型吗?" class="headerlink" title="String 是最基本的数据类型吗?"></a>String 是最基本的数据类型吗?</h2><p>不是。Java中的基本数据类型只有8个:byte、short、int、long、float、double、char、boolean;除了基本类型(primitive type),剩下的都是引用类型(reference type),Java 5以后引入的枚举类型也算是一种比较特殊的引用类型。</p><h2 id="float-f-3-4-是否正确?"><a href="#float-f-3-4-是否正确?" class="headerlink" title="float f=3.4;是否正确?"></a>float f=3.4;是否正确?</h2><p>不正确。3.4是双精度数,将双精度型(double)赋值给浮点型(float)属于下转型(down-casting,也称为窄化)会造成精度损失,因此需要强制类型转换float f =(float)3.4; 或者写成float f =3.4F;。</p><h2 id="short-s1-1-s1-s1-1-有错吗-short-s1-1-s1-1-有错吗?"><a href="#short-s1-1-s1-s1-1-有错吗-short-s1-1-s1-1-有错吗?" class="headerlink" title="short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗?"></a>short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗?</h2><p>对于short s1 = 1; s1 = s1 + 1;由于1是int类型,因此s1+1运算结果也是int 型,需要强制转换类型才能赋值给short型。而short s1 = 1; s1 += 1;可以正确编译,因为s1+= 1;相当于s1 = (short)(s1 + 1);其中有隐含的强制类型转换。</p><h2 id="int和Integer有什么区别?"><a href="#int和Integer有什么区别?" class="headerlink" title="int和Integer有什么区别?"></a>int和Integer有什么区别?</h2><p>Java 为每个原始类型提供了包装类型:</p><ul><li>原始类型: boolean,char,byte,short,int,long,float,double </li><li>包装类型:Boolean,Character,Byte,Short,Integer,Long,Float,Double</li></ul><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title">AutoUnboxingTest</span> {</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span>(<span class="params">String[] args</span>) </span>{</span><br><span class="line"> Integer a = <span class="keyword">new</span> Integer(<span class="number">3</span>);</span><br><span class="line"> Integer b = <span class="number">3</span>; <span class="comment">// 将3自动装箱成Integer类型</span></span><br><span class="line"> <span class="keyword">int</span> c = <span class="number">3</span>;</span><br><span class="line"> System.<span class="keyword">out</span>.println(a == b); <span class="comment">// false 两个引用没有引用同一对象</span></span><br><span class="line"> System.<span class="keyword">out</span>.println(a == c); <span class="comment">// true a自动拆箱成int类型再和c比较</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title">Test03</span> {</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span>(<span class="params">String[] args</span>) </span>{</span><br><span class="line"> Integer f1 = <span class="number">100</span>, f2 = <span class="number">100</span>, f3 = <span class="number">150</span>, f4 = <span class="number">150</span>;</span><br><span class="line"> System.<span class="keyword">out</span>.println(f1 == f2);<span class="comment">//true</span></span><br><span class="line"> System.<span class="keyword">out</span>.println(f3 == f4);<span class="comment">//false</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>首先需要注意的是f1、f2、f3、f4四个变量都是Integer对象引用,所以下面的==运算比较的不是值而是引用。装箱的本质是什么呢?当我们给一个Integer对象赋一个int值的时候,会调用Integer类的静态方法valueOf,如果看看valueOf的源代码就知道发生了什么。</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Integer <span class="title">valueOf</span><span class="params">(<span class="keyword">int</span> i)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (i >= IntegerCache.low && i <= IntegerCache.high)</span><br><span class="line"> <span class="keyword">return</span> IntegerCache.cache[i + (-IntegerCache.low)];</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> Integer(i);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>IntegerCache是Integer的内部类,其代码如下所示:</li></ul><figure class="highlight zephir"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Cache to support the object identity semantics of autoboxing for values between</span></span><br><span class="line"><span class="comment"> * -128 and 127 (inclusive) as required by JLS.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * The cache is initialized on first usage. The size of the cache</span></span><br><span class="line"><span class="comment"> * may be controlled by the {<span class="doctag">@code</span> -XX:AutoBoxCacheMax=<size>} option.</span></span><br><span class="line"><span class="comment"> * During VM initialization, java.lang.Integer.IntegerCache.high property</span></span><br><span class="line"><span class="comment"> * may be set and saved in the private system properties in the</span></span><br><span class="line"><span class="comment"> * sun.misc.VM class.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">IntegerCache</span> </span>{</span><br><span class="line"> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> low = <span class="number">-128</span>;</span><br><span class="line"> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> high;</span><br><span class="line"> <span class="keyword">static</span> <span class="keyword">final</span> Integer cache[];</span><br><span class="line"></span><br><span class="line"> <span class="keyword">static</span> {</span><br><span class="line"> <span class="comment">// high value may be configured by property</span></span><br><span class="line"> <span class="keyword">int</span> h = <span class="number">127</span>;</span><br><span class="line"> String integerCacheHighPropValue =</span><br><span class="line"> sun.misc.VM.getSavedProperty(<span class="string">"java.lang.Integer.IntegerCache.high"</span>);</span><br><span class="line"> <span class="keyword">if</span> (integerCacheHighPropValue != <span class="keyword">null</span>) {</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="keyword">int</span> i = parseInt(integerCacheHighPropValue);</span><br><span class="line"> i = Math.max(i, <span class="number">127</span>);</span><br><span class="line"> <span class="comment">// Maximum array size is Integer.MAX_VALUE</span></span><br><span class="line"> h = Math.min(i, Integer.MAX_VALUE - (-low) <span class="number">-1</span>);</span><br><span class="line"> } <span class="keyword">catch</span>( NumberFormatException nfe) {</span><br><span class="line"> <span class="comment">// If the property cannot be parsed into an int, ignore it.</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> high = h;</span><br><span class="line"></span><br><span class="line"> cache = <span class="keyword">new</span> Integer[(high - low) + <span class="number">1</span>];</span><br><span class="line"> <span class="keyword">int</span> j = low;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> k = <span class="number">0</span>; k < cache.length; k++)</span><br><span class="line"> cache[k] = <span class="keyword">new</span> Integer(j++);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// range [-128, 127] must be interned (JLS7 5.1.7)</span></span><br><span class="line"> assert IntegerCache.high >= <span class="number">127</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> IntegerCache() {}</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><ul><li>简单的说,如果整型字面量的值在-128到127之间,那么不会new新的Integer对象,而是直接引用常量池中的Integer对象,所以上面的面试题中f1==f2的结果是true,而f3==f4的结果是false</li></ul><h2 id="amp-和-amp-amp-的区别?"><a href="#amp-和-amp-amp-的区别?" class="headerlink" title="&和&&的区别?"></a>&和&&的区别?</h2><p>&运算符有两种用法:(1)按位与;(2)逻辑与。&&运算符是短路与运算。&&之所以称为短路运算是因为,如果&&左边的表达式的值是false,右边的表达式会被直接短路掉,不会进行运算。很多时候我们可能都需要用&&而不是&。</p><h2 id="解释内存中的栈-stack-、堆-heap-和方法区-method-area-的用法。"><a href="#解释内存中的栈-stack-、堆-heap-和方法区-method-area-的用法。" class="headerlink" title="解释内存中的栈(stack)、堆(heap)和方法区(method area)的用法。"></a>解释内存中的栈(stack)、堆(heap)和方法区(method area)的用法。</h2><ul><li>通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用JVM中的栈空间。</li><li>而通过new关键字和构造器创建的对象则放在堆空间,堆是垃圾收集器管理的主要区域,由于现在的垃圾收集器都采用分代收集算法,所以堆空间还可以细分为新生代和老生代,再具体一点可以分为Eden、Survivor(又可分为From Survivor和To Survivor)、Tenured;</li><li>方法区和堆都是各个线程共享的内存区域,用于存储已经被JVM加载的类信息、常量、静态变量、JIT编译器编译后的代码等数据;</li><li>程序中的字面量(literal)如直接书写的100、”hello”和常量都是放在常量池中,常量池是方法区的一部分</li></ul><figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">String <span class="built_in">s1</span> = new StringBuilder(<span class="string">"go"</span>).append(<span class="string">"od"</span>).toString()<span class="comment">;</span></span><br><span class="line">System.out.println(<span class="built_in">s1</span>.intern() == <span class="built_in">s1</span>)<span class="comment">;</span></span><br><span class="line">String <span class="built_in">s2</span> = new StringBuilder(<span class="string">"ja"</span>).append(<span class="string">"va"</span>).toString()<span class="comment">;</span></span><br><span class="line">System.out.println(<span class="built_in">s2</span>.intern() == <span class="built_in">s2</span>)<span class="comment">;</span></span><br></pre></td></tr></table></figure><h2 id="Math-round-11-5-等于多少?Math-round-11-5-等于多少?"><a href="#Math-round-11-5-等于多少?Math-round-11-5-等于多少?" class="headerlink" title="Math.round(11.5) 等于多少?Math.round(-11.5)等于多少?"></a>Math.round(11.5) 等于多少?Math.round(-11.5)等于多少?</h2><p>Math.round(11.5)的返回值是12,Math.round(-11.5)的返回值是-11。四舍五入的原理是在参数上加0.5然后进行下取整。</p><h2 id="switch-是否能作用在byte-上,是否能作用在long-上,是否能作用在String上?"><a href="#switch-是否能作用在byte-上,是否能作用在long-上,是否能作用在String上?" class="headerlink" title="switch 是否能作用在byte 上,是否能作用在long 上,是否能作用在String上?"></a>switch 是否能作用在byte 上,是否能作用在long 上,是否能作用在String上?</h2><ul><li>在Java 5以前,switch(expr)中,expr只能是byte、short、char、int。</li><li>从Java 5开始,Java中引入了枚举类型,expr也可以是enum类型,</li><li>从Java 7开始,expr还可以是字符串(String)。</li></ul><h2 id="用最有效率的方法计算2乘以8?"><a href="#用最有效率的方法计算2乘以8?" class="headerlink" title="用最有效率的方法计算2乘以8?"></a>用最有效率的方法计算2乘以8?</h2><ul><li>2 << 3(左移3位相当于乘以2的3次方,右移3位相当于除以2的3次方)。</li></ul><h2 id="数组有没有length-方法?String有没有length-方法?"><a href="#数组有没有length-方法?String有没有length-方法?" class="headerlink" title="数组有没有length()方法?String有没有length()方法?"></a>数组有没有length()方法?String有没有length()方法?</h2><p>数组没有length()方法,有length 的属性。String 有length()方法。JavaScript中,获得字符串的长度是通过length属性得到的,这一点容易和Java混淆。</p><h2 id="两个对象值相同-x-equals-y-true-,但却可有不同的hash-code,这句话对不对?"><a href="#两个对象值相同-x-equals-y-true-,但却可有不同的hash-code,这句话对不对?" class="headerlink" title="两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?"></a>两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?</h2><p>不对,如果两个对象x和y满足x.equals(y) == true,它们的哈希码(hash code)应当相同。Java对于eqauls方法和hashCode方法是这样规定的:</p><ul><li>如果两个对象相同(equals方法返回true),那么它们的hashCode值一定要相同</li><li>如果两个对象的hashCode相同,它们并不一定相同。</li></ul><h3 id="equals方法介绍:"><a href="#equals方法介绍:" class="headerlink" title="equals方法介绍:"></a>equals方法介绍:</h3><ul><li>自反性(x.equals(x)必须返回true)</li><li>对称性(x.equals(y)返回true时,y.equals(x)也必须返回true)</li><li>传递性(x.equals(y)和y.equals(z)都返回true时,x.equals(z)也必须返回true)</li><li>一致性(当x和y引用的对象信息没有被修改时,多次调用x.equals(y)应该得到同样的返回值),</li><li>而且对于任何非null值的引用x,x.equals(null)必须返回false。</li></ul><h3 id="实现高质量的equals方法的诀窍包括:"><a href="#实现高质量的equals方法的诀窍包括:" class="headerlink" title="实现高质量的equals方法的诀窍包括:"></a>实现高质量的equals方法的诀窍包括:</h3><ol><li>使用==操作符检查”参数是否为这个对象的引用”;</li><li>使用instanceof操作符检查”参数是否为正确的类型”;</li><li>对于类中的关键属性,检查参数传入对象的属性是否与之相匹配;</li><li>编写完equals方法后,问自己它是否满足对称性、传递性、一致性;</li><li>重写equals时总是要重写hashCode;</li><li>不要将equals方法参数中的Object对象替换为其他的类型,在重写时不要忘掉@Override注解。</li></ol><h2 id="当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?"><a href="#当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?" class="headerlink" title="当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?"></a>当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?</h2><p>是值传递。Java语言的方法调用只支持参数的值传递。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的属性可以在被调用过程中被改变,但对对象引用的改变是不会影响到调用者的。</p><h2 id="String和StringBuilder、StringBuffer的区别?"><a href="#String和StringBuilder、StringBuffer的区别?" class="headerlink" title="String和StringBuilder、StringBuffer的区别?"></a>String和StringBuilder、StringBuffer的区别?</h2><p>Java平台提供了两种类型的字符串:String和StringBuffer/StringBuilder,它们可以储存和操作字符串。其中String是只读字符串,也就意味着String引用的字符串内容是不能被改变的。而StringBuffer/StringBuilder类表示的字符串对象可以直接进行修改。StringBuilder是Java 5中引入的,它和StringBuffer的方法完全相同,区别在于它是在单线程环境下使用的,因为它的所有方面都没有被synchronized修饰,因此它的效率也比StringBuffer要高。</p><ul><li>String对象的intern方法会得到字符串对象在常量池中对应的版本的引用(如果常量池中有一个字符串与String对象的equals结果是true),如果常量池中没有对应的字符串,则该字符串将被添加到常量池中,然后返回常量池中字符串的引用;</li><li>字符串的+操作其本质是创建了StringBuilder对象进行append操作,然后将拼接后的StringBuilder对象用toString方法处理成String对象,这一点可以用javap -c StringEqualTest.class命令获得class文件对应的JVM字节码指令就可以看出来。</li></ul><figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">class StringEqualTest {</span><br><span class="line"></span><br><span class="line"> public static void main(String[] args) {</span><br><span class="line"> String <span class="built_in">s1</span> = <span class="string">"Programming"</span><span class="comment">;</span></span><br><span class="line"> String <span class="built_in">s2</span> = new String(<span class="string">"Programming"</span>)<span class="comment">;</span></span><br><span class="line"> String <span class="built_in">s3</span> = <span class="string">"Program"</span><span class="comment">;</span></span><br><span class="line"> String <span class="built_in">s4</span> = <span class="string">"ming"</span><span class="comment">;</span></span><br><span class="line"> String <span class="built_in">s5</span> = <span class="string">"Program"</span> + <span class="string">"ming"</span><span class="comment">;</span></span><br><span class="line"> String <span class="built_in">s6</span> = <span class="built_in">s3</span> + <span class="built_in">s4</span><span class="comment">;</span></span><br><span class="line"> System.out.println(<span class="built_in">s1</span> == <span class="built_in">s2</span>)<span class="comment">;//false</span></span><br><span class="line"> System.out.println(<span class="built_in">s1</span> == <span class="built_in">s5</span>)<span class="comment">;//true</span></span><br><span class="line"> System.out.println(<span class="built_in">s1</span> == <span class="built_in">s6</span>)<span class="comment">;//false</span></span><br><span class="line"> System.out.println(<span class="built_in">s1</span> == <span class="built_in">s6</span>.intern())<span class="comment">;//true</span></span><br><span class="line"> System.out.println(<span class="built_in">s2</span> == <span class="built_in">s2</span>.intern())<span class="comment">;//false,返回的常量</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?"><a href="#重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?" class="headerlink" title="重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?"></a>重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?</h2><ul><li>重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;</li><li>重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。重载对返回类型没有特殊的要求。</li></ul><h2 id="描述一下JVM加载class文件的原理机制?"><a href="#描述一下JVM加载class文件的原理机制?" class="headerlink" title="描述一下JVM加载class文件的原理机制?"></a>描述一下JVM加载class文件的原理机制?</h2><p>JVM中类的装载是由类加载器(ClassLoader)和它的子类来实现的,Java中的类加载器是一个重要的Java运行时系统组件,它负责在运行时查找和装入类文件中的类。 </p><p>由于Java的跨平台性,经过编译的Java源程序并不是一个可执行程序,而是一个或多个类文件。当Java程序需要使用某个类时,JVM会确保这个类已经被加载、连接(验证、准备和解析)和初始化。</p><ul><li>类的加载是指把类的.class文件中的数据读入到内存中,通常是创建一个字节数组读入.class文件,然后产生与所加载类对应的Class对象。</li><li>加载完成后,Class对象还不完整,所以此时的类还不可用。当类被加载后就进入连接阶段,这一阶段包括验证、准备(为静态变量分配内存并设置默认的初始值)和解析(将符号引用替换为直接引用)三个步骤。</li><li><p>最后JVM对类进行初始化</p><ul><li>如果类存在直接的父类并且这个类还没有被初始化,那么就先初始化父类</li><li>如果类中存在初始化语句,就依次执行这些初始化语句。 </li></ul></li><li><p>类加载器包括:</p><ul><li>根加载器(BootStrap),一般用本地代码实现,负责加载JVM基础核心类库(rt.jar);</li><li>扩展加载器(Extension),从java.ext.dirs系统属性所指定的目录中加载类库,它的父加载器是Bootstrap</li><li>系统加载器(System),应用类加载器,其父类是Extension。它是应用最广泛的类加载器</li><li>用户自定义类加载器(java.lang.ClassLoader的子类) </li></ul></li><li><p>父亲委托机制<br>从Java 2(JDK 1.2)开始,类加载过程采取了父亲委托机制(PDM)。PDM更好的保证了Java平台的安全性,在该机制中,JVM自带的Bootstrap是根加载器,其他的加载器都有且仅有一个父类加载器。类的加载首先请求父类加载器加载,父类加载器无能为力时才由其子类加载器自行加载。JVM不会向Java程序提供对Bootstrap的引用。</p></li></ul><h2 id="抽象类(abstract-class)和接口(interface)有什么异同?"><a href="#抽象类(abstract-class)和接口(interface)有什么异同?" class="headerlink" title="抽象类(abstract class)和接口(interface)有什么异同?"></a>抽象类(abstract class)和接口(interface)有什么异同?</h2><p>抽象类和接口都不能够实例化,但可以定义抽象类和接口类型的引用。一个类如果继承了某个抽象类或者实现了某个接口都需要对其中的抽象方法全部进行实现,否则该类仍然需要被声明为抽象类。接口比抽象类更加抽象,因为抽象类中可以定义构造器,可以有抽象方法和具体方法,而接口中不能定义构造器而且其中的方法全部都是抽象方法。抽象类中的成员可以是private、默认、protected、public的,而接口中的成员全都是public的。抽象类中可以定义成员变量,而接口中定义的成员变量实际上都是常量。有抽象方法的类必须被声明为抽象类,而抽象类未必要有抽象方法。</p><h2 id="静态嵌套类-Static-Nested-Class-和内部类(Inner-Class)的不同?"><a href="#静态嵌套类-Static-Nested-Class-和内部类(Inner-Class)的不同?" class="headerlink" title="静态嵌套类(Static Nested Class)和内部类(Inner Class)的不同?"></a>静态嵌套类(Static Nested Class)和内部类(Inner Class)的不同?</h2><p>Static Nested Class是被声明为静态(static)的内部类,它可以不依赖于外部类实例被实例化。而通常的内部类需要在外部类实例化后才能实例化。</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Outer</span> {</span></span><br><span class="line"></span><br><span class="line"> <span class="class"><span class="keyword">class</span> <span class="title">Inner</span> {</span>}</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">foo</span><span class="params">()</span> </span>{ <span class="keyword">new</span> Inner(); }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">bar</span><span class="params">()</span> </span>{ <span class="keyword">new</span> Inner(); }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>{</span><br><span class="line"> <span class="keyword">new</span> Inner();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>ava中非静态内部类对象的创建要依赖其外部类对象,上面的面试题中foo和main方法都是静态方法,静态方法中没有this,也就是说没有所谓的外部类对象,因此无法创建内部类对象,如果要在静态方法中创建内部类对象,可以这样做 new Outer().new Inner();</p><h2 id="Java-中会存在内存泄漏吗,请简单描述。"><a href="#Java-中会存在内存泄漏吗,请简单描述。" class="headerlink" title="Java 中会存在内存泄漏吗,请简单描述。"></a>Java 中会存在内存泄漏吗,请简单描述。</h2><p>理论上Java因为有垃圾回收机制(GC)不会存在内存泄露问题(这也是Java被广泛使用于服务器端编程的一个重要原因);然而在实际开发中,可能会存在无用但可达的对象,这些对象不能被GC回收,因此也会导致内存泄露的发生。例如Hibernate的Session(一级缓存)中的对象属于持久态,垃圾回收器是不会回收这些对象的,然而这些对象中可能存在无用的垃圾对象,如果不及时关闭(close)或清空(flush)一级缓存就可能导致内存泄露。</p><h2 id="GC是什么?为什么要有GC?"><a href="#GC是什么?为什么要有GC?" class="headerlink" title="GC是什么?为什么要有GC?"></a>GC是什么?为什么要有GC?</h2><ul><li>Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。Java程序员不用担心内存管理,因为垃圾收集器会自动进行管理。</li><li>在垃圾收集过程中,可能会将对象移动到不同区域: <ul><li>伊甸园(Eden):这是对象最初诞生的区域,并且对大多数对象来说,这里是它们唯一存在过的区域。</li><li>幸存者乐园(Survivor):从伊甸园幸存下来的对象会被挪到这里。 </li><li>终身颐养园(Tenured):这是足够老的幸存对象的归宿。年轻代收集(Minor-GC)过程是不会触及这个地方的。当年轻代收集不能把对象放进终身颐养园时,就会触发一次完全收集(Major-GC),这里可能还会牵扯到压缩,以便为大对象腾出足够的空间。</li></ul></li></ul><h3 id="与垃圾回收相关的JVM参数:"><a href="#与垃圾回收相关的JVM参数:" class="headerlink" title="与垃圾回收相关的JVM参数:"></a>与垃圾回收相关的JVM参数:</h3><ol><li>-Xms / -Xmx — 堆的初始大小 / 堆的最大大小</li><li>-Xmn — 堆中年轻代的大小</li><li>-XX:-DisableExplicitGC — 让System.gc()不产生任何作用</li><li>-XX:+PrintGCDetails — 打印GC的细节</li><li>-XX:+PrintGCDateStamps — 打印GC操作的时间戳</li><li>-XX:NewSize / XX:MaxNewSize — 设置新生代大小/新生代最大大小</li><li>-XX:NewRatio — 可以设置老生代和新生代的比例</li><li>-XX:PrintTenuringDistribution — 设置每次新生代GC后输出幸存者乐园中对象年龄的分布</li><li>-XX:InitialTenuringThreshold / -XX:MaxTenuringThreshold:设置老年代阀值的初始值和最大值</li><li>-XX:TargetSurvivorRatio:设置幸存区的目标使用率</li></ol><h2 id=""><a href="#" class="headerlink" title=" "></a> </h2><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title">A</span> {</span><br><span class="line"></span><br><span class="line"> <span class="keyword">static</span> {</span><br><span class="line"> System.<span class="keyword">out</span>.print(<span class="string">"1"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="title">A</span>(<span class="params"></span>) </span>{</span><br><span class="line"> System.<span class="keyword">out</span>.print(<span class="string">"2"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title">B</span> <span class="title">extends</span> <span class="title">A</span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">static</span> {</span><br><span class="line"> System.<span class="keyword">out</span>.print(<span class="string">"a"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="title">B</span>(<span class="params"></span>) </span>{</span><br><span class="line"> System.<span class="keyword">out</span>.print(<span class="string">"b"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title">Hello</span> {</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span>(<span class="params">String[] args</span>) </span>{</span><br><span class="line"> A ab = <span class="keyword">new</span> B();</span><br><span class="line"> ab = <span class="keyword">new</span> B();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>执行结果:1a2b2b。创建对象时构造器的调用顺序是:先初始化静态成员,然后调用父类构造器,再初始化非静态成员,最后调用自身构造器。</p><h2 id="Error和Exception有什么区别"><a href="#Error和Exception有什么区别" class="headerlink" title="Error和Exception有什么区别"></a>Error和Exception有什么区别</h2><p>Error表示系统级的错误和程序不必处理的异常,是恢复不是不可能但很困难的情况下的一种严重问题;比如内存溢出,不可能指望程序能处理这样的情况;Exception表示需要捕捉或者需要程序进行处理的异常,是一种设计或实现问题;也就是说,它表示如果程序运行正常,从不会发生的情况。</p><h2 id="Java语言如何进行异常处理,关键字:throws、throw、try、catch、finally分别如何使用?"><a href="#Java语言如何进行异常处理,关键字:throws、throw、try、catch、finally分别如何使用?" class="headerlink" title="Java语言如何进行异常处理,关键字:throws、throw、try、catch、finally分别如何使用?"></a>Java语言如何进行异常处理,关键字:throws、throw、try、catch、finally分别如何使用?</h2><ul><li>在Java中,每个异常都是一个对象,它是Throwable类或其子类的实例。</li><li>一般情况下是用try来执行一段程序,如果系统会抛出(throw)一个异常对象,可以通过它的类型来捕获(catch)它,或通过总是执行代码块(finally)来处理;</li><li>throw语句用来明确地抛出一个异常</li><li>throws用来声明一个方法可能抛出的各种异常(当然声明异常时允许无病呻吟)</li></ul><h2 id="运行时异常与受检异常有何异同?"><a href="#运行时异常与受检异常有何异同?" class="headerlink" title="运行时异常与受检异常有何异同?"></a>运行时异常与受检异常有何异同?</h2><p>异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误,只要程序设计得没有问题通常就不会发生。受检异常跟程序运行的上下文环境有关,即使程序设计无误,仍然可能因使用的问题而引发。Java编译器要求方法必须声明抛出可能发生的受检异常,但是并不要求必须声明抛出未被捕获的运行时异常。异常和继承一样,是面向对象程序设计中经常被滥用的东西,在Effective Java中对异常的使用给出了以下指导原则: </p><p>不要将异常处理用于正常的控制流(设计良好的API不应该强迫它的调用者为了正常的控制流而使用异常) </p><ul><li>对可以恢复的情况使用受检异常,对编程错误使用运行时异常 </li><li>避免不必要的使用受检异常(可以通过一些状态检测手段来避免异常的发生) </li><li>优先使用标准的异常 </li><li>每个方法抛出的异常都要有文档 </li><li>保持异常的原子性 </li><li>不要在catch中忽略掉捕获到的异常</li></ul><h2 id="常见的运行时异常"><a href="#常见的运行时异常" class="headerlink" title="常见的运行时异常"></a>常见的运行时异常</h2><ul><li>ArithmeticException(算术异常) </li><li>ClassCastException (类转换异常) </li><li>IllegalArgumentException (非法参数异常) </li><li>IndexOutOfBoundsException (下标越界异常) </li><li>NullPointerException (空指针异常) </li><li>SecurityException (安全异常)</li></ul><h2 id="类ExampleA继承Exception,类ExampleB继承ExampleA。"><a href="#类ExampleA继承Exception,类ExampleB继承ExampleA。" class="headerlink" title="类ExampleA继承Exception,类ExampleB继承ExampleA。"></a>类ExampleA继承Exception,类ExampleB继承ExampleA。</h2><figure class="highlight arduino"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">try</span> {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> ExampleB(<span class="string">"b"</span>)</span><br><span class="line">} <span class="built_in">catch</span>(ExampleA e){</span><br><span class="line"> System.out.<span class="built_in">println</span>(<span class="string">"ExampleA"</span>);</span><br><span class="line">} <span class="built_in">catch</span>(Exception e){</span><br><span class="line"> System.out.<span class="built_in">println</span>(<span class="string">"Exception"</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>输出:ExampleA。(根据里氏代换原则[能使用父类型的地方一定能使用子类型],抓取ExampleA类型异常的catch块能够抓住try块中抛出的ExampleB类型的异常)</li></ul><h2 id="List、Set、Map是否继承自Collection接口?"><a href="#List、Set、Map是否继承自Collection接口?" class="headerlink" title="List、Set、Map是否继承自Collection接口?"></a>List、Set、Map是否继承自Collection接口?</h2><p>List、Set 是,Map 不是。Map是键值对映射容器,与List和Set有明显的区别,而Set存储的零散的元素且不允许有重复元素(数学中的集合也是如此),List是线性结构的容器,适用于按数值索引访问元素的情形。</p><h2 id="阐述ArrayList、Vector、LinkedList的存储性能和特性。"><a href="#阐述ArrayList、Vector、LinkedList的存储性能和特性。" class="headerlink" title="阐述ArrayList、Vector、LinkedList的存储性能和特性。"></a>阐述ArrayList、Vector、LinkedList的存储性能和特性。</h2><ul><li>ArrayList 和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢。</li><li>Vector中的方法由于添加了synchronized修饰,因此Vector是线程安全的容器,但性能上较ArrayList差,因此已经是Java中的遗留容器</li><li>LinkedList使用双向链表实现存储(将内存中零散的内存单元通过附加的引用关联起来,形成一个可以按序号索引的线性结构,这种链式存储方式与数组的连续存储方式相比,内存的利用率更高),按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。</li><li>但是由于ArrayList和LinkedListed都是非线程安全的,如果遇到多个线程操作同一个容器的场景,则可以通过工具类Collections中的synchronizedList方法将其转换成线程安全的容器后再使用。</li></ul><h2 id="Collection和Collections的区别?"><a href="#Collection和Collections的区别?" class="headerlink" title="Collection和Collections的区别?"></a>Collection和Collections的区别?</h2><p>Collection是一个接口,它是Set、List等容器的父接口;Collections是个一个工具类,提供了一系列的静态方法来辅助容器操作,这些方法包括对容器的搜索、排序、线程安全化等等。</p><h2 id="List、Map、Set三个接口存取元素时,各有什么特点?"><a href="#List、Map、Set三个接口存取元素时,各有什么特点?" class="headerlink" title="List、Map、Set三个接口存取元素时,各有什么特点?"></a>List、Map、Set三个接口存取元素时,各有什么特点?</h2><ul><li>List以特定索引来存取元素,可以有重复元素。</li><li>Set不能存放重复元素(用对象的equals()方法来区分元素是否重复)。</li><li>Map保存键值对(key-value pair)映射,映射关系可以是一对一或多对一</li><li>Set和Map容器都有基于哈希存储和排序树的两种实现版本,基于哈希存储的版本理论存取时间复杂度为O(1)</li></ul><h2 id="TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort-方法如何比较元素"><a href="#TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort-方法如何比较元素" class="headerlink" title="TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素"></a>TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素</h2><ul><li>TreeSet要求存放的对象所属的类必须实现Comparable接口,该接口提供了比较元素的compareTo()方法,当插入元素时会回调该方法比较元素的大小。</li><li>TreeMap要求存放的键值对映射的键必须实现Comparable接口从而根据键对元素进行排序。</li><li>Collections工具类的sort方法有两种重载的形式<ul><li>第一种要求传入的待排序容器中存放的对象比较实现Comparable接口以实现元素的比较</li><li>第二种不强制性的要求容器中的元素必须可比较,但是要求传入第二个参数,参数是Comparator接口的子类型(需要重写compare方法实现元素的比较),相当于一个临时定义的排序规则。</li></ul></li></ul><h2 id="Thread类的sleep-方法和对象的wait-方法都可以让线程暂停执行,它们有什么区别"><a href="#Thread类的sleep-方法和对象的wait-方法都可以让线程暂停执行,它们有什么区别" class="headerlink" title="Thread类的sleep()方法和对象的wait()方法都可以让线程暂停执行,它们有什么区别?"></a>Thread类的sleep()方法和对象的wait()方法都可以让线程暂停执行,它们有什么区别?</h2><ul><li>sleep()方法(休眠)是线程类(Thread)的静态方法,调用此方法会让当前线程暂停执行指定的时间,将执行机会(CPU)让给其他线程,但是对象的锁依然保持,因此休眠时间结束后会自动恢复。</li><li>wait()是Object类的方法,调用对象的wait()方法导致当前线程放弃对象的锁(线程暂停执行),进入对象的等待池(wait pool),只有调用对象的notify()方法(或notifyAll()方法)时才能唤醒等待池中的线程进入等锁池(lock pool),如果线程重新获得对象的锁就可以进入就绪状态。</li></ul><h2 id="线程的sleep-方法和yield-方法有什么区别?"><a href="#线程的sleep-方法和yield-方法有什么区别?" class="headerlink" title="线程的sleep()方法和yield()方法有什么区别?"></a>线程的sleep()方法和yield()方法有什么区别?</h2><ul><li>sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会</li><li>yield()方法只会给相同优先级或更高优先级的线程以运行的机会; </li><li>线程执行sleep()方法后转入阻塞(blocked)状态,</li><li>而执行yield()方法后转入就绪(ready)状态;</li><li>sleep()方法声明抛出InterruptedException,而yield()方法没有声明任何异常; </li><li>sleep()方法比yield()方法(跟操作系统CPU调度相关)具有更好的可移植性。</li></ul><h2 id="当一个线程进入一个对象的synchronized方法A之后,其它线程是否可进入此对象的synchronized方法B?"><a href="#当一个线程进入一个对象的synchronized方法A之后,其它线程是否可进入此对象的synchronized方法B?" class="headerlink" title="当一个线程进入一个对象的synchronized方法A之后,其它线程是否可进入此对象的synchronized方法B?"></a>当一个线程进入一个对象的synchronized方法A之后,其它线程是否可进入此对象的synchronized方法B?</h2><p>不能。其它线程只能访问该对象的非同步方法,同步方法则不能进入。因为非静态方法上的synchronized修饰符要求执行方法时要获得对象的锁,如果已经进入A方法说明对象锁已经被取走,那么试图进入B方法的线程就只能在等锁池(注意不是等待池哦)中等待对象的锁。</p><h2 id="请说出与线程同步以及线程调度相关的方法。"><a href="#请说出与线程同步以及线程调度相关的方法。" class="headerlink" title="请说出与线程同步以及线程调度相关的方法。"></a>请说出与线程同步以及线程调度相关的方法。</h2><ul><li>wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁; </li><li>sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要处理InterruptedException异常; </li><li>notify():唤醒一个处于等待状态的线程,当然在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且与优先级无关; </li><li>notityAll():唤醒所有处于等待状态的线程,该方法并不是将对象的锁给所有线程,而是让它们竞争,只有获得锁的线程才能进入就绪状态;</li></ul><h2 id="编写多线程程序有几种实现方式?"><a href="#编写多线程程序有几种实现方式?" class="headerlink" title="编写多线程程序有几种实现方式?"></a>编写多线程程序有几种实现方式?</h2><ul><li>一种是继承Thread类;</li><li>另一种是实现Runnable接口</li><li>实现Callable接口,该接口中的call方法可以在线程执行结束时产生一个返回值</li></ul><h2 id="什么是线程池(thread-pool)"><a href="#什么是线程池(thread-pool)" class="headerlink" title="什么是线程池(thread pool)"></a>什么是线程池(thread pool)</h2><p>在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源。在Java中更是如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收。所以提高服务程序效率的一个手段就是尽可能减少创建和销毁对象的次数,特别是一些很耗资源的对象创建和销毁,这就是”池化资源”技术产生的原因。</p><p>线程池顾名思义就是事先创建若干个可执行的线程放入一个池(容器)中,需要的时候从池中获取线程不用自行创建,使用完毕不需要销毁线程而是放回池中,从而减少创建和销毁线程对象的开销。<br>Java 5+中的Executor接口定义一个执行线程的工具。它的子类型即线程池接口是ExecutorService。要配置一个线程池是比较复杂的,尤其是对于线程池的原理不是很清楚的情况下,因此在工具类Executors面提供了一些静态工厂方法,生成一些常用的线程池,如下所示: </p><ul><li>newSingleThreadExecutor:创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。</li><li>newFixedThreadPool:创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。 </li><li>newCachedThreadPool:创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。 </li><li>newScheduledThreadPool:创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求。 </li><li>newSingleThreadExecutor:创建一个单线程的线程池。此线程池支持定时以及周期性执行任务的需求。</li></ul><h2 id="线程的基本状态以及状态之间的关系?"><a href="#线程的基本状态以及状态之间的关系?" class="headerlink" title="线程的基本状态以及状态之间的关系?"></a>线程的基本状态以及状态之间的关系?</h2><p><a href="https://img-blog.csdn.net/20150408002007838" target="_blank" rel="noopener"></a></p><ul><li>其中Running表示运行状态,</li><li>Runnable表示就绪状态(万事俱备,只欠CPU),</li><li>Blocked表示阻塞状态,阻塞状态又有多种情况,<ul><li>可能是因为调用wait()方法进入等待池,</li><li>也可能是执行同步方法或同步代码块进入等锁池,</li><li>或者是调用了sleep()方法或join()方法等待休眠或其他线程结束,或是因为发生了I/O中断。</li></ul></li></ul><h2 id="简述synchronized-和java-util-concurrent-locks-Lock的异同?"><a href="#简述synchronized-和java-util-concurrent-locks-Lock的异同?" class="headerlink" title="简述synchronized 和java.util.concurrent.locks.Lock的异同?"></a>简述synchronized 和java.util.concurrent.locks.Lock的异同?</h2><p>Lock是Java 5以后引入的新的API,和关键字synchronized相比主要相同点:</p><ul><li>Lock 能完成synchronized所实现的所有功能;</li><li>Lock有比synchronized更精确的线程语义和更好的性能,而且不强制性的要求一定要获得锁</li><li>synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且最好在finally 块中释放(这是释放外部资源的最好的地方)。</li></ul><h2 id="Java中如何实现序列化,有什么意义?"><a href="#Java中如何实现序列化,有什么意义?" class="headerlink" title="Java中如何实现序列化,有什么意义?"></a>Java中如何实现序列化,有什么意义?</h2><p>序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决对象流读写操作时可能引发的问题(如果不进行序列化可能会存在数据乱序的问题)。 </p><p>要实现序列化,需要让一个类实现Serializable接口,该接口是一个标识性接口,标注该类对象是可被序列化的,然后使用一个输出流来构造一个对象输出流并通过writeObject(Object)方法就可以将实现对象写出(即保存其状态);如果需要反序列化则可以用一个输入流建立对象输入流,然后通过readObject方法从流中读取对象。序列化除了能够实现对象的持久化之外,还能够用于对象的深度克隆</p><h2 id="阐述JDBC操作数据库的步骤。"><a href="#阐述JDBC操作数据库的步骤。" class="headerlink" title="阐述JDBC操作数据库的步骤。"></a>阐述JDBC操作数据库的步骤。</h2><ul><li>加载驱动</li><li>创建连接</li><li>创建语句</li><li>执行语句</li><li>处理结果</li><li>关闭资源</li></ul><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"> Class.forName(<span class="string">"oracle.jdbc.driver.OracleDriver"</span>);</span><br><span class="line"><span class="built_in"> Connection </span>con = DriverManager.getConnection(<span class="string">"jdbc:oracle:thin:@localhost:1521:orcl"</span>, <span class="string">"scott"</span>, <span class="string">"tiger"</span>);</span><br><span class="line">PreparedStatement ps = con.prepareStatement(<span class="string">"select * from emp where sal between ? and ?"</span>);</span><br><span class="line">ps.setInt(1, 1000);</span><br><span class="line">ps.setInt(2, 3000);</span><br><span class="line">ResultSet rs = ps.executeQuery();</span><br><span class="line"><span class="keyword">while</span>(rs.next()) {</span><br><span class="line"> System.out.println(rs.getInt(<span class="string">"empno"</span>) + <span class="string">" - "</span> + rs.getString(<span class="string">"ename"</span>));</span><br><span class="line">}</span><br><span class="line">finally {</span><br><span class="line"> <span class="keyword">if</span>(con != <span class="literal">null</span>) {</span><br><span class="line"> try {</span><br><span class="line"> con.close();</span><br><span class="line"> } catch (SQLException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>关闭外部资源的顺序应该和打开的顺序相反,也就是说先关闭ResultSet、再关闭Statement、在关闭Connection。</li></ul><h2 id="Statement和PreparedStatement有什么区别?哪个性能更好?"><a href="#Statement和PreparedStatement有什么区别?哪个性能更好?" class="headerlink" title="Statement和PreparedStatement有什么区别?哪个性能更好?"></a>Statement和PreparedStatement有什么区别?哪个性能更好?</h2><ul><li>PreparedStatement接口代表预编译的语句,它主要的优势在于可以减少SQL的编译错误并增加SQL的安全性(减少SQL注射攻击的可能性);</li><li>PreparedStatement中的SQL语句是可以带参数的,避免了用字符串连接拼接SQL语句的麻烦和不安全;</li><li>当批量处理SQL或频繁执行相同的查询时,PreparedStatement有明显的性能上的优势,由于数据库可以将编译优化后的SQL语句缓存起来,下次执行相同结构的语句时就会很快(不用再次编译和生成执行计划)。</li></ul><h2 id="使用JDBC操作数据库时,如何提升读取数据的性能?如何提升更新数据的性能?"><a href="#使用JDBC操作数据库时,如何提升读取数据的性能?如何提升更新数据的性能?" class="headerlink" title="使用JDBC操作数据库时,如何提升读取数据的性能?如何提升更新数据的性能?"></a>使用JDBC操作数据库时,如何提升读取数据的性能?如何提升更新数据的性能?</h2><ul><li>要提升读取数据的性能,可以指定通过结果集(ResultSet)对象的setFetchSize()方法指定每次抓取的记录数(典型的空间换时间策略)</li><li>要提升更新数据的性能可以使用PreparedStatement语句构建批处理,将若干SQL语句置于一个批处理中执行。</li></ul><h2 id="在进行数据库编程时,连接池有什么作用?"><a href="#在进行数据库编程时,连接池有什么作用?" class="headerlink" title="在进行数据库编程时,连接池有什么作用?"></a>在进行数据库编程时,连接池有什么作用?</h2><p>由于创建连接和释放连接都有很大的开销(尤其是数据库服务器不在本地时,每次建立连接都需要进行TCP的三次握手,释放连接需要进行TCP四次握手,造成的开销是不可忽视的),为了提升系统访问数据库的性能,可以事先创建若干连接置于连接池中,需要时直接从连接池获取,使用结束时归还连接池而不必关闭连接,从而避免频繁创建和释放连接所造成的开销。</p><h2 id="事务的ACID是指什么?"><a href="#事务的ACID是指什么?" class="headerlink" title="事务的ACID是指什么?"></a>事务的ACID是指什么?</h2><ul><li>原子性(Atomic):事务中各项操作,要么全做要么全不做,</li><li>一致性(Consistent):事务结束后系统状态是一致的;</li><li>隔离性(Isolated):并发执行的事务彼此无法看到对方的中间状态; </li><li>持久性(Durable):事务完成后所做的改动都会被持久化,即使发生灾难性的失败。通过日志和同步备份可以在故障发生后重建数据。</li></ul><p>只有存在并发数据访问时才需要事务。当多个事务访问同一数据时,可能会存在5类问题,包括3类数据读取问题(脏读、不可重复读和幻读)和2类数据更新问题(第1类丢失更新和第2类丢失更新)。</p><ul><li>脏读(Dirty Read):A事务读取B事务尚未提交的数据并在此基础上操作,而B事务执行回滚,那么A读取到的数据就是脏数据。</li></ul><p><img src="http://orkt468tj.bkt.clouddn.com/18-7-6/87650429.jpg" alt=""></p><ul><li>不可重复读(Unrepeatable Read):事务A重新读取前面读取过的数据,发现该数据已经被另一个已提交的事务B修改过了。</li></ul><p><img src="http://orkt468tj.bkt.clouddn.com/18-7-6/95804465.jpg" alt=""></p><ul><li>幻读(Phantom Read):事务A重新执行一个查询,返回一系列符合查询条件的行,发现其中插入了被事务B提交的行</li></ul><p><img src="http://orkt468tj.bkt.clouddn.com/18-7-6/62660957.jpg" alt=""></p><ul><li>第1类丢失更新:事务A撤销时,把已经提交的事务B的更新数据覆盖了。</li></ul><p><img src="http://orkt468tj.bkt.clouddn.com/18-7-6/96595208.jpg" alt=""></p><ul><li>第2类丢失更新:事务A覆盖事务B已经提交的数据,造成事务B所做的操作丢失。</li></ul><p><img src="http://orkt468tj.bkt.clouddn.com/18-7-6/65275664.jpg" alt=""></p><p>数据并发访问所产生的问题,在有些场景下可能是允许的,但是有些场景下可能就是致命的,数据库通常会通过锁机制来解决数据并发访问问题,按锁定对象不同可以分为表级锁和行级锁;按并发事务锁定关系可以分为共享锁和独占锁:</p><p><img src="http://orkt468tj.bkt.clouddn.com/18-7-6/82828779.jpg" alt=""></p><h2 id="JDBC中如何进行事务处理?"><a href="#JDBC中如何进行事务处理?" class="headerlink" title="JDBC中如何进行事务处理?"></a>JDBC中如何进行事务处理?</h2><ul><li>Connection提供了事务处理的方法,通过调用setAutoCommit(false)可以设置手动提交事务;当事务完成后用commit()显式提交事务;</li><li>如果在事务处理过程中发生异常则通过rollback()进行事务回滚。</li><li>除此之外,从JDBC 3.0中还引入了Savepoint(保存点)的概念,允许通过代码设置保存点并让事务回滚到指定的保存点。 </li></ul><h2 id="JDBC能否处理Blob和Clob?"><a href="#JDBC能否处理Blob和Clob?" class="headerlink" title="JDBC能否处理Blob和Clob?"></a>JDBC能否处理Blob和Clob?</h2><p>Blob是指二进制大对象(Binary Large Object),而Clob是指大字符对象(Character Large Objec),因此其中Blob是为存储大的二进制数据而设计的,而Clob是为存储大的文本数据而设计的。JDBC的PreparedStatement和ResultSet都提供了相应的方法来支持Blob和Clob操作。</p><h2 id="Java中是如何支持正则表达式操作的?"><a href="#Java中是如何支持正则表达式操作的?" class="headerlink" title="Java中是如何支持正则表达式操作的?"></a>Java中是如何支持正则表达式操作的?</h2><p>Java中的String类提供了支持正则表达式操作的方法,包括:matches()、replaceAll()、replaceFirst()、split()。此外,Java中可以用Pattern类表示正则表达式对象,它提供了丰富的API进行各种正则表达式操作。</p><h2 id="简述一下面向对象的”六原则一法则”。"><a href="#简述一下面向对象的”六原则一法则”。" class="headerlink" title="简述一下面向对象的”六原则一法则”。"></a>简述一下面向对象的”六原则一法则”。</h2><h3 id="单一职责原则"><a href="#单一职责原则" class="headerlink" title="单一职责原则"></a>单一职责原则</h3><p>一个类只做它该做的事情。(单一职责原则想表达的就是”高内聚”,写代码最终极的原则只有六个字”高内聚、低耦合”,就如同葵花宝典或辟邪剑谱的中心思想就八个字”欲练此功必先自宫”,所谓的高内聚就是一个代码模块只完成一项功能,在面向对象中,如果只让一个类完成它该做的事,而不涉及与它无关的领域就是践行了高内聚的原则,这个类就只有单一职责。</p><h3 id="开闭原则"><a href="#开闭原则" class="headerlink" title="开闭原则"></a>开闭原则</h3><p>软件实体应当对扩展开放,对修改关闭。</p><h3 id="依赖倒转原则"><a href="#依赖倒转原则" class="headerlink" title="依赖倒转原则"></a>依赖倒转原则</h3><p>面向接口编程。(该原则说得直白和具体一些就是声明方法的参数类型、方法的返回类型、变量的引用类型时,尽可能使用抽象类型而不用具体类型,因为抽象类型可以被它的任何一个子类型所替代,请参考下面的里氏替换原则。) </p><h3 id="里氏替换原则"><a href="#里氏替换原则" class="headerlink" title="里氏替换原则"></a>里氏替换原则</h3><p>任何时候都可以用子类型替换掉父类型。</p><h3 id="接口隔离原则"><a href="#接口隔离原则" class="headerlink" title="接口隔离原则"></a>接口隔离原则</h3><p>接口要小而专,绝不能大而全</p><h3 id="合成聚合复用原则"><a href="#合成聚合复用原则" class="headerlink" title="合成聚合复用原则"></a>合成聚合复用原则</h3><p>优先使用聚合或合成关系复用代码</p><h3 id="迪米特法则"><a href="#迪米特法则" class="headerlink" title="迪米特法则"></a>迪米特法则</h3><p>迪米特法则又叫最少知识原则,一个对象应当对其他对象有尽可能少的了解</p><h2 id="设计模式"><a href="#设计模式" class="headerlink" title="设计模式"></a>设计模式</h2><p>所谓设计模式,就是一套被反复使用的代码设计经验的总结(情境中一个问题经过证实的一个解决方案)。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。设计模式使人们可以更加简单方便的复用成功的设计和体系结构。将已证实的技术表述成设计模式也会使新系统开发者更加容易理解其设计思路。 </p><ul><li>工厂模式:工厂类可以根据条件生成不同的子类实例,这些子类有一个公共的抽象父类并且实现了相同的方法,但是这些方法针对不同的数据进行了不同的操作(多态方法)。当得到子类的实例后,开发人员可以调用基类中的方法而不必考虑到底返回的是哪一个子类的实例。 </li><li>代理模式:给一个对象提供一个代理对象,并由代理对象控制原对象的引用。实际开发中,按照使用目的的不同,代理可以分为:远程代理、虚拟代理、保护代理、Cache代理、防火墙代理、同步化代理、智能引用代理。 </li><li>适配器模式:把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起使用的类能够一起工作。 </li><li>模板方法模式:提供一个抽象类,将部分逻辑以具体方法或构造器的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法(多态实现),从而实现不同的业务逻辑。 </li></ul><h2 id="什么是UML"><a href="#什么是UML" class="headerlink" title="什么是UML"></a>什么是UML</h2><p>UML是统一建模语言(Unified Modeling Language)的缩写,它发表于1997年,综合了当时已经存在的面向对象的建模语言、方法和过程,是一个支持模型化和软件系统开发的图形化语言,为软件开发的所有阶段提供模型化和可视化支持。使用UML可以帮助沟通与交流,辅助应用设计和文档的生成,还能够阐释系统的结构和行为。</p><h2 id="UML中有哪些常用的图?"><a href="#UML中有哪些常用的图?" class="headerlink" title="UML中有哪些常用的图?"></a>UML中有哪些常用的图?</h2><p>UML定义了多种图形化的符号来描述软件系统部分或全部的静态结构和动态结构,包括:用例图(use case diagram)、类图(class diagram)、时序图(sequence diagram)、协作图(collaboration diagram)、状态图(statechart diagram)、活动图(activity diagram)、构件图(component diagram)、部署图(deployment diagram)等。在这些图形化符号中,有三种图最为重要,分别是:用例图(用来捕获需求,描述系统的功能,通过该图可以迅速的了解系统的功能模块及其关系)、类图(描述类以及类与类之间的关系,通过该图可以快速了解系统)、时序图(描述执行特定任务时对象之间的交互关系以及执行顺序,通过该图可以了解对象能接收的消息也就是说对象能够向外界提供的服务)。</p>]]></content>
<summary type="html">
<h2 id="面向的对象特征"><a href="#面向的对象特征" class="headerlink" title="面向的对象特征"></a>面向的对象特征</h2><ul>
<li>抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象
</summary>
<category term="搬砖" scheme="http://chilam.me/categories/%E6%90%AC%E7%A0%96/"/>
<category term="java" scheme="http://chilam.me/tags/java/"/>
</entry>
<entry>
<title>1.学习笔记-docker基本概念</title>
<link href="http://chilam.me/2018/01/04/docker/"/>
<id>http://chilam.me/2018/01/04/docker/</id>
<published>2018-01-04T00:25:17.000Z</published>
<updated>2018-07-04T01:45:44.615Z</updated>
<content type="html"><![CDATA[<h2 id="容器"><a href="#容器" class="headerlink" title="容器"></a>容器</h2><p>容器就是将软件打包成标准化单元,以用于开发、交付和部署。</p><ul><li>容器镜像是轻量的、可执行的独立软件包 ,包含软件运行所需的所有内容:代码、运行时环境、系统工具、系统库和设置。</li><li>容器化软件适用于基于Linux和Windows的应用,在任何环境中都能够始终如一地运行。</li><li>容器赋予了软件独立性 ,使其免受外在环境差异(例如,开发和预演环境的差异)的影响,从而有助于减少团队间在相同基础设施上运行不同软件时的冲突。</li></ul><h3 id="容器虚拟化"><a href="#容器虚拟化" class="headerlink" title="容器虚拟化"></a>容器虚拟化</h3><p>是操作系统而不是硬件,容器之间是共享同一套操作系统资源的。</p><h3 id="虚拟机技术"><a href="#虚拟机技术" class="headerlink" title="虚拟机技术"></a>虚拟机技术</h3><p>是虚拟出一套硬件后,在其上运行一个完整操作系统。因此容器的隔离级别会稍低一些。</p><h2 id="Docker"><a href="#Docker" class="headerlink" title="Docker"></a>Docker</h2><ul><li>Docker 是世界领先的软件容器平台。</li><li>Docker 使用 Google 公司推出的 Go 语言 进行开发实现,基于 Linux 内核 的cgroup,namespace,以及AUFS类的UnionFS等技术,对进程进行封装隔离,属于操作系统层面的虚拟化技术。 由于隔离的进程独立于宿主和其它的隔离的进 程,因此也称其为容器。</li><li>Docker 能够自动执行重复性任务,例如搭建和配置开发环境,从而解放了开发人员以便他们专注在真正重要的事情上:构建杰出的软件。</li><li>用户可以方便地创建和使用容器,把自己的应用放入容器。容器还可以进行版本管理、复制、分享、修改,就像管理普通的代码一样。</li></ul><h3 id="Docker容器的特点"><a href="#Docker容器的特点" class="headerlink" title="Docker容器的特点"></a>Docker容器的特点</h3><ul><li>轻量,在一台机器上运行的多个 Docker 容器可以共享这台机器的操作系统内核;它们能够迅速启动,只需占用很少的计算和内存资源。镜像是通过文件系统层进行构造的,并共享一些公共文件。这样就能尽量降低磁盘用量,并能更快地下载镜像。</li><li>标准,Docker 容器基于开放式标准,能够在所有主流 Linux 版本、Microsoft Windows 以及包括 VM、裸机服务器和云在内的任何基础设施上运行。</li><li>安全,Docker 赋予应用的隔离性不仅限于彼此隔离,还独立于底层的基础设施。Docker 默认提供最强的隔离,因此应用出现问题,也只是单个容器的问题,而不会波及到整台机器。</li><li>给软件提供一致的运行环境</li><li>更快速的启动时间</li><li>隔离性</li><li>弹性伸缩,快速扩展</li><li>迁移方便</li><li>持续交付和部署</li></ul><h2 id="容器与虚拟机"><a href="#容器与虚拟机" class="headerlink" title="容器与虚拟机"></a>容器与虚拟机</h2><p> 容器和虚拟机具有相似的资源隔离和分配优势,但功能有所不同,因为容器虚拟化的是操作系统,而不是硬件,因此容器更容易移植,效率也更高。</p><p> 容器是一个应用层抽象,用于将代码和依赖资源打包在一起。 多个容器可以在同一台机器上运行,共享操作系统内核,但各自作为独立的进程在用户空间中运行 。与虚拟机相比, 容器占用的空间较少(容器镜像大小通常只有几十兆),瞬间就能完成启动。</p><p> 虚拟机 (VM) 是一个物理硬件层抽象,用于将一台服务器变成多台服务器。 管理程序允许多个 VM 在一台机器上运行。每个VM都包含一整套操作系统、一个或多个应用、必要的二进制文件和库资源,因此 占用大量空间 。而且 VM 启动也十分缓慢 。</p><h2 id="Docker的基本概念"><a href="#Docker的基本概念" class="headerlink" title="Docker的基本概念"></a>Docker的基本概念</h2><h3 id="镜像Image"><a href="#镜像Image" class="headerlink" title="镜像Image"></a>镜像Image</h3><p> 一个特殊的文件系统,操作系统分为内核和用户空间。对于 Linux 而言,内核启动后,会挂载 root 文件系统为其提供用户空间支持。而Docker 镜像(Image),就相当于是一个 root 文件系统。</p><p> Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。 镜像不包含任何动态数据,其内容在构建之后也不会被改变。</p><p> Docker 设计时,就充分利用 Union FS的技术,将其设计为 分层存储的架构 。 镜像实际是由多层文件系统联合组成。</p><p>镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。</p><h3 id="容器Container"><a href="#容器Container" class="headerlink" title="容器Container"></a>容器Container</h3><p> 镜像运行时的实体</p><p>镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的 类 和 实例 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等 。</p><p>容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的 命名空间。</p><h3 id="仓库Repository"><a href="#仓库Repository" class="headerlink" title="仓库Repository"></a>仓库Repository</h3><p>集中存放镜像文件的地方</p><p>镜像仓库是Docker用来集中存放镜像文件的地方类似于我们之前常用的代码仓库。</p><p><a href="https://hub.docker.com/" target="_blank" rel="noopener">Docker Registry 公开服务</a>,和本地仓库</p><h2 id="Docker使用"><a href="#Docker使用" class="headerlink" title="Docker使用"></a>Docker使用</h2><h3 id="使用-yum-安装(CentOS-7下)"><a href="#使用-yum-安装(CentOS-7下)" class="headerlink" title="使用 yum 安装(CentOS 7下)"></a>使用 yum 安装(CentOS 7下)</h3><p>Docker 要求 CentOS 系统的内核版本高于 3.10 ,查看本页面的前提条件来验证你的CentOS 版本是否支持 Docker 。<br>通过 uname -r 命令查看你当前的内核版本 </p><ul><li>安装</li></ul><figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yum -y <span class="keyword">install</span> docker-io</span><br></pre></td></tr></table></figure><ul><li>启动</li></ul><figure class="highlight crmsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">service docker <span class="literal">start</span></span><br></pre></td></tr></table></figure><ul><li>测试运行</li></ul><figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker <span class="keyword">run</span><span class="bash"> hello world</span></span><br></pre></td></tr></table></figure><ul><li>镜像加速</li></ul><p>新版的 Docker 使用 /etc/docker/daemon.json(Linux)</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"registry-mirrors"</span>: [<span class="string">"http://hub-mirror.c.163.com"</span>]</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>Build(构建镜像) : 镜像就像是集装箱包括文件以及运行环境等等资源。</li><li>Ship(运输镜像) :主机和仓库间运输,这里的仓库就像是超级码头一样。</li><li>Run (运行镜像) :运行的镜像就是一个容器,容器就是运行程序的地方。- </li></ul><h3 id="使用Tomcat镜像"><a href="#使用Tomcat镜像" class="headerlink" title="使用Tomcat镜像"></a>使用Tomcat镜像</h3><ul><li>下载tomcat镜像</li></ul><figure class="highlight autoit"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[root<span class="symbol">@192</span> ~]<span class="meta"># docker pull tomcat</span></span><br></pre></td></tr></table></figure><ul><li>启动</li></ul><figure class="highlight applescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker <span class="built_in">run</span> <span class="comment">--name tomcat -p 8080:8080 -d tomcat</span></span><br></pre></td></tr></table></figure><ul><li>查看容器</li></ul><figure class="highlight elixir"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">[root<span class="variable">@192</span> ~]<span class="comment"># docker ps</span></span><br><span class="line">CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES</span><br><span class="line"><span class="number">4431</span>f5eb99df tomcat <span class="string">"catalina.sh run"</span> <span class="number">3</span> minutes ago Up <span class="number">3</span> minutes <span class="number">0</span>.<span class="number">0</span>.<span class="number">0</span>.<span class="number">0</span><span class="symbol">:</span><span class="number">8080</span>-><span class="number">8080</span>/tcp tomcat</span><br></pre></td></tr></table></figure><h3 id="关于maven项目的插件"><a href="#关于maven项目的插件" class="headerlink" title="关于maven项目的插件"></a>关于maven项目的插件</h3><p><a href="https://github.com/spotify/docker-maven-plugin" target="_blank" rel="noopener">docker-maven-plugin</a></p>]]></content>
<summary type="html">
dokcer的学习笔记
</summary>
<category term="搬砖" scheme="http://chilam.me/categories/%E6%90%AC%E7%A0%96/"/>
<category term="docker" scheme="http://chilam.me/tags/docker/"/>
</entry>
<entry>
<title>8.sb-原理</title>
<link href="http://chilam.me/2017/12/17/spring-boot-8/"/>
<id>http://chilam.me/2017/12/17/spring-boot-8/</id>
<published>2017-12-17T01:00:08.000Z</published>
<updated>2018-06-30T10:05:00.264Z</updated>
<content type="html"><![CDATA[<p>见识了SpringBoot为我们做的自动配置,确实方便快捷,但是对于新手来说,如果不大懂SpringBoot内部启动原理,<br>以后难免会吃亏。一起一步步揭开SpringBoot的神秘面纱,让它不在神秘。</p><p>我们开发任何一个Spring Boot项目,都会用到如下的启动类</p><figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Application</span> {</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> main(String[] args) {</span><br><span class="line"> SpringApplication.run(Application.<span class="keyword">class</span>, args);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>从上面代码可以看出,Annotation定义(@SpringBootApplication)和类定义(SpringApplication.run)最为耀眼,<br>所以要揭开SpringBoot的神秘面纱,我们要从这两位开始就可以了。</p><h2 id="SpringBootApplication"><a href="#SpringBootApplication" class="headerlink" title="@SpringBootApplication"></a>@SpringBootApplication</h2><figure class="highlight less"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="variable">@Target</span>(ElementType.TYPE)</span><br><span class="line"><span class="variable">@Retention</span>(RetentionPolicy.RUNTIME)</span><br><span class="line"><span class="variable">@Documented</span></span><br><span class="line"><span class="variable">@Inherited</span></span><br><span class="line"><span class="variable">@SpringBootConfiguration</span></span><br><span class="line"><span class="variable">@EnableAutoConfiguration</span></span><br><span class="line"><span class="variable">@ComponentScan</span>(excludeFilters = {</span><br><span class="line"><span class="variable">@Filter</span>(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),</span><br><span class="line"><span class="variable">@Filter</span>(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })</span><br><span class="line">public <span class="variable">@interface</span> SpringBootApplication {}</span><br></pre></td></tr></table></figure><ul><li>@Configuration(@SpringBootConfiguration点开查看发现里面还是应用了@Configuration)</li><li>@EnableAutoConfiguration</li><li>@ComponentScan</li></ul><h3 id="Configuration"><a href="#Configuration" class="headerlink" title="@Configuration"></a>@Configuration</h3><p>这里的@Configuration对我们来说不陌生,它就是JavaConfig形式的Spring Ioc容器的配置类使用的那个@Configuration,<br>SpringBoot社区推荐使用基于JavaConfig的配置形式,所以,这里的启动类标注了@Configuration之后,本身其实也是一个IoC容器的配置类。</p><p>回顾一下对于一个spring的bean使用xml方式配置的话是如下的</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="php"><span class="meta"><?</span>xml version=<span class="string">"1.0"</span> encoding=<span class="string">"UTF-8"</span><span class="meta">?></span></span></span><br><span class="line"><span class="tag"><<span class="name">beans</span> <span class="attr">xmlns</span>=<span class="string">"http://www.springframework.org/schema/beans"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">xmlns:xsi</span>=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">xsi:schemaLocation</span>=<span class="string">"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">bean</span> <span class="attr">id</span>=<span class="string">"userService"</span> <span class="attr">class</span>=<span class="string">"me.chilam.example.UserServiceImpl"</span>></span><span class="tag"></<span class="name">bean</span>></span></span><br><span class="line"></span><br><span class="line"><span class="tag"></<span class="name">beans</span>></span></span><br></pre></td></tr></table></figure><p>对于Java Config的方式应该是如下的:</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">package</span> <span class="selector-tag">me</span><span class="selector-class">.chilam</span><span class="selector-class">.example</span>;</span><br><span class="line"><span class="selector-tag">import</span> <span class="selector-tag">org</span><span class="selector-class">.springframework</span><span class="selector-class">.context</span><span class="selector-class">.annotation</span><span class="selector-class">.Bean</span>;</span><br><span class="line"><span class="selector-tag">import</span> <span class="selector-tag">org</span><span class="selector-class">.springframework</span><span class="selector-class">.context</span><span class="selector-class">.annotation</span><span class="selector-class">.Configuration</span>;</span><br><span class="line">@<span class="keyword">Configuration</span></span><br><span class="line"><span class="keyword">public</span> class UserConfig {</span><br><span class="line"></span><br><span class="line"> @<span class="keyword">Bean</span></span><br><span class="line"> public IUserService userService(){</span><br><span class="line"> <span class="selector-tag">return</span> <span class="selector-tag">new</span> <span class="selector-tag">UserServiceImpl</span>();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>任何一个标注了@Bean的方法,其返回值将作为一个bean定义注册到Spring的IoC容器,方法名将默认成该bean定义的id。</p><h3 id="ComponentScan"><a href="#ComponentScan" class="headerlink" title="@ComponentScan"></a>@ComponentScan</h3><p>@ComponentScan这个注解在Spring中很重要,它对应XML配置中的元素,@ComponentScan的功能其实就是自动扫描并加载符合条件的组件<br>(比如@Component和@Repository等)或者bean定义,最终将这些bean定义加载到IoC容器中。</p><p>我们可以通过basePackages等属性来细粒度的定制@ComponentScan自动扫描的范围,如果不指定,<br>则默认Spring框架实现会从声明@ComponentScan所在类的package进行扫描。</p><h3 id="EnableAutoConfiguration"><a href="#EnableAutoConfiguration" class="headerlink" title="@EnableAutoConfiguration"></a>@EnableAutoConfiguration</h3><p>大家是否还记得Spring框架提供的各种名字为@Enable开头的Annotation定义?比如@EnableScheduling、@EnableCaching、<br>@EnableMBeanExport等,@EnableAutoConfiguration的理念和做事方式其实一脉相承,简单概括一下就是,<br>借助@Import的支持,收集和注册特定场景相关的bean定义。</p><ul><li>@EnableScheduling是通过@Import将Spring调度框架相关的bean定义都加载到IoC容器。</li><li>@EnableMBeanExport是通过@Import将JMX相关的bean定义加载到IoC容器。</li></ul><p>而@EnableAutoConfiguration也是借助@Import的帮助,将所有符合自动配置条件的bean定义加载到IoC容器,仅此而已!</p><p>@EnableAutoConfiguration作为一个复合Annotation,其自身定义关键信息如下</p><figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Target(ElementType.TYPE)</span></span><br><span class="line"><span class="meta">@Retention(RetentionPolicy.RUNTIME)</span></span><br><span class="line"><span class="meta">@Documented</span></span><br><span class="line"><span class="meta">@Import(EnableConfigurationPropertiesImportSelector.class)</span></span><br><span class="line"><span class="keyword">public</span> <span class="meta">@interface</span> EnableConfigurationProperties {</span><br><span class="line">Class<?>[] value() <span class="keyword">default</span> {};</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
Spring Boot还没有写完,感觉还是先把所有功能过一遍在来搞原理
</summary>
<category term="搬砖" scheme="http://chilam.me/categories/%E6%90%AC%E7%A0%96/"/>
<category term="spring-boot" scheme="http://chilam.me/tags/spring-boot/"/>
</entry>
<entry>
<title>7.sb-jdbcTemplate</title>
<link href="http://chilam.me/2017/12/17/spring-boot-7/"/>
<id>http://chilam.me/2017/12/17/spring-boot-7/</id>
<published>2017-12-17T01:00:07.000Z</published>
<updated>2018-06-30T10:05:00.264Z</updated>
<content type="html"><![CDATA[<p>本文介绍在Spring Boot基础下配置数据源和通过JdbcTemplate编写数据访问的示例。</p><h2 id="添加依赖"><a href="#添加依赖" class="headerlink" title="添加依赖"></a>添加依赖</h2><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.springframework.boot<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>spring-boot-starter-jdbc<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"><span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"><span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>mysql<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>mysql-connector-java<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>5.1.38<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"><span class="tag"></<span class="name">dependency</span>></span></span><br></pre></td></tr></table></figure><h2 id="数据源配置"><a href="#数据源配置" class="headerlink" title="数据源配置"></a>数据源配置</h2><p>Spring Boot默认数据源配置,spring-boot-starter-jdbc 默认使用tomcat-jdbc数据源,</p><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">spring<span class="selector-class">.datasource</span><span class="selector-class">.driver-class-name</span>=com<span class="selector-class">.mysql</span><span class="selector-class">.jdbc</span><span class="selector-class">.Driver</span></span><br><span class="line">spring<span class="selector-class">.datasource</span><span class="selector-class">.url</span>=jdbc:mysql:<span class="comment">//localhost:3306/boot_db</span></span><br><span class="line">spring<span class="selector-class">.datasource</span><span class="selector-class">.username</span>=root</span><br><span class="line">spring<span class="selector-class">.datasource</span><span class="selector-class">.password</span>=test123456</span><br></pre></td></tr></table></figure><h2 id="初始化库表"><a href="#初始化库表" class="headerlink" title="初始化库表"></a>初始化库表</h2><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> t_user</span><br><span class="line">(</span><br><span class="line"> <span class="keyword">id</span> <span class="built_in">INT</span> AUTO_INCREMENT PRIMARY <span class="keyword">KEY</span>,</span><br><span class="line"> <span class="keyword">name</span> <span class="built_in">VARCHAR</span>(<span class="number">100</span>) <span class="literal">NULL</span>,</span><br><span class="line"> age <span class="built_in">INT</span> <span class="literal">NULL</span></span><br><span class="line">);</span><br></pre></td></tr></table></figure><h2 id="编写dao类"><a href="#编写dao类" class="headerlink" title="编写dao类"></a>编写dao类</h2><ul><li>IUserDao接口</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> me.chilam.dao;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> me.chilam.vo.User;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">IUserDAO</span> </span>{</span><br><span class="line"> <span class="function">List<User> <span class="title">selectUsers</span><span class="params">()</span></span>;</span><br><span class="line"> <span class="function"><span class="keyword">int</span> <span class="title">insertUser</span><span class="params">(User user)</span></span>;</span><br><span class="line"> <span class="function"><span class="keyword">int</span> <span class="title">deleteUserById</span><span class="params">(Long id)</span></span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>UserDaoImpl实现类</li></ul><p>Spring的jdbcTemplate是自动配置的,可以直接使用@Autowried自动注入</p><figure class="highlight aspectj"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> me.chilam.dao;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> me.chilam.vo.User;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.jdbc.core.JdbcTemplate;</span><br><span class="line"><span class="keyword">import</span> org.springframework.jdbc.core.RowMapper;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Repository;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.sql.ResultSet;</span><br><span class="line"><span class="keyword">import</span> java.sql.SQLException;</span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Repository</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">UserDaoImpl</span> <span class="keyword">implements</span> <span class="title">IUserDAO</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 直接注入使用即可</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">private</span> JdbcTemplate jdbcTemplate;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> List<User> selectUsers() {</span><br><span class="line"> <span class="function"><span class="keyword">return</span> jdbcTemplate.<span class="title">query</span><span class="params">(<span class="string">"SELECT * FROM t_user"</span>, <span class="keyword">new</span> RowMapper<User>()</span> </span>{</span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> <span class="function">User <span class="title">mapRow</span><span class="params">(ResultSet resultSet, <span class="keyword">int</span> i)</span> <span class="keyword">throws</span> SQLException </span>{</span><br><span class="line"> User user = <span class="keyword">new</span> User();</span><br><span class="line"> user.setId(resultSet.getLong(<span class="string">"id"</span>));</span><br><span class="line"> user.setName(resultSet.getString(<span class="string">"name"</span>));</span><br><span class="line"> user.setAge(resultSet.getInt(<span class="string">"age"</span>));</span><br><span class="line"> <span class="keyword">return</span> user;</span><br><span class="line"> }</span><br><span class="line"> });</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">int</span> <span class="title">insertUser</span><span class="params">(User user)</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> jdbcTemplate.update(<span class="string">"INSERT INTO t_user(name,age) VALUE (?,?)"</span>,user.getName(),user.getAge());</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">int</span> <span class="title">deleteUserById</span><span class="params">(Long id)</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">return</span> jdbcTemplate.<span class="title">update</span><span class="params">(<span class="string">"DELETE FROM t_user WHERE id=?"</span>,id)</span></span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="编写Service类"><a href="#编写Service类" class="headerlink" title="编写Service类"></a>编写Service类</h2><ul><li>IUserService接口</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> me.chilam.service;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> me.chilam.vo.User;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">IUserService</span> </span>{</span><br><span class="line"> <span class="function">List<User> <span class="title">getAllUsers</span><span class="params">()</span></span>;</span><br><span class="line"> <span class="function"><span class="keyword">int</span> <span class="title">addUser</span><span class="params">(User user)</span></span>;</span><br><span class="line"> <span class="function"><span class="keyword">int</span> <span class="title">removeUserById</span><span class="params">(Long id)</span></span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>UserServiceImpl实现类</li></ul><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">package</span> <span class="selector-tag">me</span><span class="selector-class">.chilam</span><span class="selector-class">.service</span>;</span><br><span class="line"></span><br><span class="line"><span class="selector-tag">import</span> <span class="selector-tag">me</span><span class="selector-class">.chilam</span><span class="selector-class">.dao</span><span class="selector-class">.IUserDAO</span>;</span><br><span class="line"><span class="selector-tag">import</span> <span class="selector-tag">me</span><span class="selector-class">.chilam</span><span class="selector-class">.vo</span><span class="selector-class">.User</span>;</span><br><span class="line"><span class="selector-tag">import</span> <span class="selector-tag">org</span><span class="selector-class">.springframework</span><span class="selector-class">.beans</span><span class="selector-class">.factory</span><span class="selector-class">.annotation</span><span class="selector-class">.Autowired</span>;</span><br><span class="line"><span class="selector-tag">import</span> <span class="selector-tag">org</span><span class="selector-class">.springframework</span><span class="selector-class">.stereotype</span><span class="selector-class">.Service</span>;</span><br><span class="line"></span><br><span class="line"><span class="selector-tag">import</span> <span class="selector-tag">java</span><span class="selector-class">.util</span><span class="selector-class">.List</span>;</span><br><span class="line"></span><br><span class="line">@<span class="keyword">Service</span></span><br><span class="line"><span class="keyword">public</span> class UserServiceImpl implements IUserService {</span><br><span class="line"></span><br><span class="line"> @<span class="keyword">Autowired</span></span><br><span class="line"> IUserDAO userDAO;</span><br><span class="line"></span><br><span class="line"> @<span class="keyword">Override</span></span><br><span class="line"> public List<User> getAllUsers() {</span><br><span class="line"> <span class="selector-tag">return</span> <span class="selector-tag">userDAO</span><span class="selector-class">.selectUsers</span>();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> @<span class="keyword">Override</span></span><br><span class="line"> public int addUser(User user) {</span><br><span class="line"> <span class="selector-tag">return</span> <span class="selector-tag">userDAO</span><span class="selector-class">.insertUser</span>(<span class="selector-tag">user</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> @<span class="keyword">Override</span></span><br><span class="line"> public int removeUserById(Long id) {</span><br><span class="line"> <span class="selector-tag">return</span> <span class="selector-tag">userDAO</span><span class="selector-class">.deleteUserById</span>(<span class="selector-tag">id</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="编写控制类"><a href="#编写控制类" class="headerlink" title="编写控制类"></a>编写控制类</h2><figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> me.chilam.web;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> io.swagger.annotations.ApiImplicitParam;</span><br><span class="line"><span class="keyword">import</span> io.swagger.annotations.ApiOperation;</span><br><span class="line"><span class="keyword">import</span> me.chilam.service.IUserService;</span><br><span class="line"><span class="keyword">import</span> me.chilam.vo.User;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.<span class="keyword">annotation</span>.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.<span class="keyword">annotation</span>.*;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"></span><br><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="meta">@RequestMapping(<span class="meta-string">"users"</span>)</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">UserController</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> IUserService userService;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@ApiOperation(value=<span class="meta-string">"获取用户列表"</span>, notes=<span class="meta-string">"获取用户列表的数据"</span>)</span></span><br><span class="line"> <span class="meta">@RequestMapping(value={<span class="meta-string">""</span>}, method= RequestMethod.GET)</span></span><br><span class="line"> <span class="keyword">public</span> List<User> getUserList() {</span><br><span class="line"> List<User> r = userService.getAllUsers();</span><br><span class="line"> <span class="keyword">return</span> r;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="meta">@ApiOperation(value=<span class="meta-string">"创建用户"</span>, notes=<span class="meta-string">"根据User对象创建用户"</span>)</span></span><br><span class="line"> <span class="meta">@ApiImplicitParam(name = <span class="meta-string">"user"</span>, value = <span class="meta-string">"用户详细实体user"</span>, required = true, dataType = <span class="meta-string">"User"</span>)</span></span><br><span class="line"> <span class="meta">@RequestMapping(value=<span class="meta-string">""</span>, method=RequestMethod.POST)</span></span><br><span class="line"> <span class="keyword">public</span> String postUser(<span class="meta">@RequestBody</span> User user) {</span><br><span class="line"> userService.addUser(user);</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"success"</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="meta">@ApiOperation(value=<span class="meta-string">"删除用户"</span>, notes=<span class="meta-string">"根据url的id来指定删除对象"</span>)</span></span><br><span class="line"> <span class="meta">@ApiImplicitParam(name = <span class="meta-string">"id"</span>, value = <span class="meta-string">"用户ID"</span>, required = true, dataType = <span class="meta-string">"Long"</span>)</span></span><br><span class="line"> <span class="meta">@RequestMapping(value=<span class="meta-string">"/{id}"</span>, method=RequestMethod.GET)</span></span><br><span class="line"> <span class="keyword">public</span> String deleteUser(<span class="meta">@PathVariable</span> <span class="built_in">Long</span> id) {</span><br><span class="line"> userService.removeUserById(id);</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"success"</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="自定义数据源配置"><a href="#自定义数据源配置" class="headerlink" title="自定义数据源配置"></a>自定义数据源配置</h2><ul><li>使用druid数据源,添加依赖如下:</li></ul><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.alibaba<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>druid<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>1.1.5<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"><span class="tag"></<span class="name">dependency</span>></span></span><br></pre></td></tr></table></figure><ul><li>Druid配置类</li></ul><p>如下的配置,Spring boot会智能适配jdbcTemplate</p><figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> com.alibaba.druid.pool.DruidDataSource;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.<span class="keyword">annotation</span>.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.<span class="keyword">annotation</span>.Bean;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.<span class="keyword">annotation</span>.Configuration;</span><br><span class="line"><span class="keyword">import</span> org.springframework.core.env.Environment;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> javax.sql.DataSource;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DruidConfiguration</span> </span>{</span><br><span class="line"> </span><br><span class="line"> <span class="comment">//使用Spring自定义环境变量</span></span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> Environment environment;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Bean(destroyMethod = <span class="meta-string">"close"</span>)</span></span><br><span class="line"> <span class="keyword">public</span> DataSource dataSource(){</span><br><span class="line"> DruidDataSource dataSource = new DruidDataSource();</span><br><span class="line"> dataSource.setUrl(environment.getProperty(<span class="string">"spring.datasource.url"</span>));</span><br><span class="line"> dataSource.setUsername(environment.getProperty(<span class="string">"spring.datasource.username"</span>));<span class="comment">//用户名</span></span><br><span class="line"> dataSource.setPassword(environment.getProperty(<span class="string">"spring.datasource.password"</span>));<span class="comment">//密码</span></span><br><span class="line"> dataSource.setDriverClassName(environment.getProperty(<span class="string">"spring.datasource.driver-class-name"</span>));</span><br><span class="line"> dataSource.setInitialSize(<span class="number">2</span>);<span class="comment">//初始化时建立物理连接的个数</span></span><br><span class="line"> dataSource.setMaxActive(<span class="number">20</span>);<span class="comment">//最大连接池数量</span></span><br><span class="line"> dataSource.setMinIdle(<span class="number">0</span>);<span class="comment">//最小连接池数量</span></span><br><span class="line"> dataSource.setMaxWait(<span class="number">60000</span>);<span class="comment">//获取连接时最大等待时间,单位毫秒。</span></span><br><span class="line"> dataSource.setValidationQuery(<span class="string">"SELECT 1"</span>);<span class="comment">//用来检测连接是否有效的sql</span></span><br><span class="line"> dataSource.setTestOnBorrow(<span class="literal">false</span>);<span class="comment">//申请连接时执行validationQuery检测连接是否有效</span></span><br><span class="line"> dataSource.setTestWhileIdle(<span class="literal">true</span>);<span class="comment">//建议配置为true,不影响性能,并且保证安全性。</span></span><br><span class="line"> dataSource.setPoolPreparedStatements(<span class="literal">false</span>);<span class="comment">//是否缓存preparedStatement,也就是PSCache</span></span><br><span class="line"> <span class="keyword">return</span> dataSource;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
Spring Boot的jdbcTemplate
</summary>
<category term="搬砖" scheme="http://chilam.me/categories/%E6%90%AC%E7%A0%96/"/>
<category term="spring-boot" scheme="http://chilam.me/tags/spring-boot/"/>
</entry>
<entry>
<title>6.sb-DevTools</title>
<link href="http://chilam.me/2017/12/17/spring-boot-6/"/>
<id>http://chilam.me/2017/12/17/spring-boot-6/</id>
<published>2017-12-17T01:00:06.000Z</published>
<updated>2018-06-30T10:05:00.264Z</updated>
<content type="html"><![CDATA[<h2 id="添加依赖"><a href="#添加依赖" class="headerlink" title="添加依赖"></a>添加依赖</h2><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"><!-- Spring Boot开发插件 --></span></span><br><span class="line"><span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.springframework.boot<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>spring-boot-devtools<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">optional</span>></span>true<span class="tag"></<span class="name">optional</span>></span></span><br><span class="line"><span class="tag"></<span class="name">dependency</span>></span></span><br></pre></td></tr></table></figure><p>将依赖关系标记为可选<optional>true</optional>是一种最佳做法,可以防止使用项目将devtools传递性地应用于其他模块。</p><h2 id="默认属性"><a href="#默认属性" class="headerlink" title="默认属性"></a>默认属性</h2><p>在Spring Boot集成Thymeleaf时,spring.thymeleaf.cache属性设置为false可以禁用模板引擎编译的缓存结果。<br>现在,devtools会自动帮你做到这些,禁用所有模板的缓存,包括Thymeleaf, Freemarker, Groovy Templates, Velocity, Mustache等。<br>更多的默认配置可以查看org.springframework.boot.devtools.env.DevToolsPropertyDefaultsPostProcessor</p><h2 id="自动重启"><a href="#自动重启" class="headerlink" title="自动重启"></a>自动重启</h2><p>自动重启的原理在于spring boot使用两个classloader:不改变的类(如第三方jar)由base类加载器加载,正在开发的类由restart类加载器加载。<br>应用重启时,restart类加载器被扔掉重建,而base类加载器不变,这种方法意味着应用程序重新启动通常比“冷启动”快得多,因为base类加载器已经可用并已填充。</p><p>所以,当我们开启devtools后,classpath中的文件变化会导致应用自动重启。<br>当然不同的IDE效果不一样,Eclipse中保存文件即可引起classpath更新(注:需要打开自动编译),<br>从而触发重启。而IDEA则需要自己手动CTRL+F9重新编译一下(感觉IDEA这种更好,不然每修改一个地方就重启,会很卡的)</p><h2 id="排除静态资源文件"><a href="#排除静态资源文件" class="headerlink" title="排除静态资源文件"></a>排除静态资源文件</h2><p>静态资源文件在改变之后有时候没必要触发应用程序重启,例如thymeleaf模板文件就可以实时编辑,默认情况下,更改/META-INF/maven, /META-INF/resources ,/resources ,/static ,/public<br>或/templates下的资源不会触发重启,而是触发live reload(devtools内嵌了一个LiveReload server,当资源发生改变时,浏览器刷新,下面会介绍)。</p><p>可以使用spring.devtools.restart.exclude属性配置,例如</p><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">spring<span class="selector-class">.devtools</span><span class="selector-class">.restart</span><span class="selector-class">.exclude</span>=static<span class="comment">/**,public/**</span></span><br></pre></td></tr></table></figure><p>如果想保留默认配置,同时增加新的配置,则可使用</p><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">spring<span class="selector-class">.devtools</span><span class="selector-class">.restart</span><span class="selector-class">.additional-exclude</span>=</span><br></pre></td></tr></table></figure><h2 id="观察额外的路径"><a href="#观察额外的路径" class="headerlink" title="观察额外的路径"></a>观察额外的路径</h2><p>如果你想观察不在classpath中的路径的文件变化并触发重启,则可以配置 spring.devtools.restart.additional-paths 属性。</p><h2 id="关闭自动重启"><a href="#关闭自动重启" class="headerlink" title="关闭自动重启"></a>关闭自动重启</h2><p>设置 spring.devtools.restart.enabled 属性为false,可以关闭该特性。可以在application.properties中设置,也可以通过设置环境变量的方式。</p><h2 id="LiveReload"><a href="#LiveReload" class="headerlink" title="LiveReload"></a>LiveReload</h2><p>DevTools内置了一个LiveReload服务,可以在资源变化时用来触发浏览器刷新。当然这个需要你浏览器安装了LiveReload插件,并且启动这个插件才行。</p>]]></content>
<summary type="html">
Spring Boot的开发工具,以及热部署工具
</summary>
<category term="搬砖" scheme="http://chilam.me/categories/%E6%90%AC%E7%A0%96/"/>
<category term="spring-boot" scheme="http://chilam.me/tags/spring-boot/"/>
</entry>
<entry>
<title>5.sb-Swagger</title>
<link href="http://chilam.me/2017/12/17/spring-boot-5/"/>
<id>http://chilam.me/2017/12/17/spring-boot-5/</id>
<published>2017-12-17T01:00:05.000Z</published>
<updated>2018-06-30T10:05:00.264Z</updated>
<content type="html"><![CDATA[<h2 id="配置依赖"><a href="#配置依赖" class="headerlink" title="配置依赖"></a>配置依赖</h2><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"><!--Swagger--></span></span><br><span class="line"><span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>io.springfox<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>springfox-swagger2<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>2.7.0<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"><span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"><span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>io.springfox<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>springfox-swagger-ui<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>2.7.0<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"><span class="tag"></<span class="name">dependency</span>></span></span><br></pre></td></tr></table></figure><h2 id="配置类"><a href="#配置类" class="headerlink" title="配置类"></a>配置类</h2><figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><span class="meta-keyword">import</span> org.springframework.context.annotation.Bean;</span></span><br><span class="line"><span class="meta"><span class="meta-keyword">import</span> org.springframework.context.annotation.Configuration;</span></span><br><span class="line"><span class="meta"><span class="meta-keyword">import</span> springfox.documentation.builders.ApiInfoBuilder;</span></span><br><span class="line"><span class="meta"><span class="meta-keyword">import</span> springfox.documentation.builders.PathSelectors;</span></span><br><span class="line"><span class="meta"><span class="meta-keyword">import</span> springfox.documentation.builders.RequestHandlerSelectors;</span></span><br><span class="line"><span class="meta"><span class="meta-keyword">import</span> springfox.documentation.service.ApiInfo;</span></span><br><span class="line"><span class="meta"><span class="meta-keyword">import</span> springfox.documentation.spi.DocumentationType;</span></span><br><span class="line"><span class="meta"><span class="meta-keyword">import</span> springfox.documentation.spring.web.plugins.Docket;</span></span><br><span class="line"><span class="meta"><span class="meta-keyword">import</span> springfox.documentation.swagger2.annotations.EnableSwagger2;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Swagger的配置类</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">@Configuration</span><br><span class="line">@EnableSwagger2</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SwaggerConfiguration</span> </span>{</span><br><span class="line"></span><br><span class="line"> @Bean</span><br><span class="line"> <span class="keyword">public</span> Docket createRestApi() {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> Docket(DocumentationType.SWAGGER_2)</span><br><span class="line"> .apiInfo(apiInfo())</span><br><span class="line"> .select()</span><br><span class="line"> .apis(RequestHandlerSelectors.basePackage(<span class="string">"me.chilam.web"</span>))</span><br><span class="line"> .paths(PathSelectors.any())</span><br><span class="line"> .build();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> ApiInfo apiInfo() {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> ApiInfoBuilder()</span><br><span class="line"> .title(<span class="string">"Spring Boot中使用Swagger2构建RESTful APIs"</span>)</span><br><span class="line"> .description(<span class="string">"测试描述信息"</span>)</span><br><span class="line"> .termsOfServiceUrl(<span class="string">"http://localhost:8080/"</span>)</span><br><span class="line"> .version(<span class="string">"1.0"</span>)</span><br><span class="line"> .build();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="启动类"><a href="#启动类" class="headerlink" title="启动类"></a>启动类</h2><figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> org.springframework.boot.SpringApplication;</span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.autoconfigure.SpringBootApplication;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.<span class="keyword">annotation</span>.ComponentScan;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.<span class="keyword">annotation</span>.Import;</span><br><span class="line"></span><br><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="meta">@ComponentScan(basePackages = {<span class="meta-string">"me.chilam.**"</span>})</span></span><br><span class="line"><span class="comment">//引入Swagger的配置</span></span><br><span class="line"><span class="meta">@Import(SwaggerConfiguration.class)</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Application</span></span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> static void main(String[] args) {</span><br><span class="line"> SpringApplication.run(Application.<span class="keyword">class</span>,args);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="Restful控制器"><a href="#Restful控制器" class="headerlink" title="Restful控制器"></a>Restful控制器</h2><figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> me.chilam.web;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> io.swagger.annotations.ApiImplicitParam;</span><br><span class="line"><span class="keyword">import</span> io.swagger.annotations.ApiImplicitParams;</span><br><span class="line"><span class="keyword">import</span> io.swagger.annotations.ApiOperation;</span><br><span class="line"><span class="keyword">import</span> me.chilam.vo.User;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.<span class="keyword">annotation</span>.*;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.*;</span><br><span class="line"></span><br><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="meta">@RequestMapping(<span class="meta-string">"users"</span>)</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">UserController</span> </span>{</span><br><span class="line"></span><br><span class="line"> static Map<<span class="built_in">Long</span>, User> users = Collections.synchronizedMap(new HashMap<<span class="built_in">Long</span>, User>());</span><br><span class="line"></span><br><span class="line"> <span class="meta">@ApiOperation(value=<span class="meta-string">"获取用户列表"</span>, notes=<span class="meta-string">""</span>)</span></span><br><span class="line"> <span class="meta">@RequestMapping(value={<span class="meta-string">""</span>}, method= RequestMethod.GET)</span></span><br><span class="line"> <span class="keyword">public</span> List<User> getUserList() {</span><br><span class="line"> List<User> r = new ArrayList<>(users.values());</span><br><span class="line"> <span class="keyword">return</span> r;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="meta">@ApiOperation(value=<span class="meta-string">"创建用户"</span>, notes=<span class="meta-string">"根据User对象创建用户"</span>)</span></span><br><span class="line"> <span class="meta">@ApiImplicitParam(name = <span class="meta-string">"user"</span>, value = <span class="meta-string">"用户详细实体user"</span>, required = true, dataType = <span class="meta-string">"User"</span>)</span></span><br><span class="line"> <span class="meta">@RequestMapping(value=<span class="meta-string">""</span>, method=RequestMethod.POST)</span></span><br><span class="line"> <span class="keyword">public</span> String postUser(<span class="meta">@RequestBody</span> User user) {</span><br><span class="line"> users.put(user.getId(), user);</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"success"</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="meta">@ApiOperation(value=<span class="meta-string">"获取用户详细信息"</span>, notes=<span class="meta-string">"根据url的id来获取用户详细信息"</span>)</span></span><br><span class="line"> <span class="meta">@ApiImplicitParam(name = <span class="meta-string">"id"</span>, value = <span class="meta-string">"用户ID"</span>, required = true, dataType = <span class="meta-string">"Long"</span>)</span></span><br><span class="line"> <span class="meta">@RequestMapping(value=<span class="meta-string">"/{id}"</span>, method=RequestMethod.GET)</span></span><br><span class="line"> <span class="keyword">public</span> User getUser(<span class="meta">@PathVariable</span> <span class="built_in">Long</span> id) {</span><br><span class="line"> <span class="keyword">return</span> users.<span class="keyword">get</span>(id);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="meta">@ApiOperation(value=<span class="meta-string">"更新用户详细信息"</span>, notes=<span class="meta-string">"根据url的id来指定更新对象,并根据传过来的user信息来更新用户详细信息"</span>)</span></span><br><span class="line"> <span class="meta">@ApiImplicitParams({</span></span><br><span class="line"><span class="meta"> @ApiImplicitParam(name = <span class="meta-string">"id"</span>, value = <span class="meta-string">"用户ID"</span>, required = true, dataType = <span class="meta-string">"Long"</span>)</span>,</span><br><span class="line"> <span class="meta">@ApiImplicitParam(name = <span class="meta-string">"user"</span>, value = <span class="meta-string">"用户详细实体user"</span>, required = true, dataType = <span class="meta-string">"User"</span>)</span></span><br><span class="line"> })</span><br><span class="line"> <span class="meta">@RequestMapping(value=<span class="meta-string">"/{id}"</span>, method=RequestMethod.PUT)</span></span><br><span class="line"> <span class="keyword">public</span> String putUser(<span class="meta">@PathVariable</span> <span class="built_in">Long</span> id, <span class="meta">@RequestBody</span> User user) {</span><br><span class="line"> User u = users.<span class="keyword">get</span>(id);</span><br><span class="line"> u.setName(user.getName());</span><br><span class="line"> u.setAge(user.getAge());</span><br><span class="line"> users.put(id, u);</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"success"</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="meta">@ApiOperation(value=<span class="meta-string">"删除用户"</span>, notes=<span class="meta-string">"根据url的id来指定删除对象"</span>)</span></span><br><span class="line"> <span class="meta">@ApiImplicitParam(name = <span class="meta-string">"id"</span>, value = <span class="meta-string">"用户ID"</span>, required = true, dataType = <span class="meta-string">"Long"</span>)</span></span><br><span class="line"> <span class="meta">@RequestMapping(value=<span class="meta-string">"/{id}"</span>, method=RequestMethod.DELETE)</span></span><br><span class="line"> <span class="keyword">public</span> String deleteUser(<span class="meta">@PathVariable</span> <span class="built_in">Long</span> id) {</span><br><span class="line"> users.remove(id);</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"success"</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="观察启动日志中Swagger"><a href="#观察启动日志中Swagger" class="headerlink" title="观察启动日志中Swagger"></a>观察启动日志中Swagger</h2><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">2017</span>-<span class="number">12</span>-<span class="number">25</span> <span class="number">09</span>:<span class="number">13</span>:<span class="number">16.606</span> INFO <span class="number">952</span> --- [ main] s<span class="selector-class">.w</span><span class="selector-class">.s</span><span class="selector-class">.m</span><span class="selector-class">.m</span><span class="selector-class">.a</span><span class="selector-class">.RequestMappingHandlerMapping</span> : Mapped <span class="string">"{[/swagger-resources/configuration/ui]}"</span> onto public org<span class="selector-class">.springframework</span><span class="selector-class">.http</span><span class="selector-class">.ResponseEntity</span><springfox<span class="selector-class">.documentation</span><span class="selector-class">.swagger</span><span class="selector-class">.web</span><span class="selector-class">.UiConfiguration</span>> springfox<span class="selector-class">.documentation</span><span class="selector-class">.swagger</span><span class="selector-class">.web</span><span class="selector-class">.ApiResourceController</span><span class="selector-class">.uiConfiguration</span>()</span><br><span class="line"><span class="number">2017</span>-<span class="number">12</span>-<span class="number">25</span> <span class="number">09</span>:<span class="number">13</span>:<span class="number">16.607</span> INFO <span class="number">952</span> --- [ main] s<span class="selector-class">.w</span><span class="selector-class">.s</span><span class="selector-class">.m</span><span class="selector-class">.m</span><span class="selector-class">.a</span><span class="selector-class">.RequestMappingHandlerMapping</span> : Mapped <span class="string">"{[/swagger-resources]}"</span> onto public org<span class="selector-class">.springframework</span><span class="selector-class">.http</span><span class="selector-class">.ResponseEntity</span><java<span class="selector-class">.util</span><span class="selector-class">.List</span><springfox<span class="selector-class">.documentation</span><span class="selector-class">.swagger</span><span class="selector-class">.web</span><span class="selector-class">.SwaggerResource</span>>> springfox<span class="selector-class">.documentation</span><span class="selector-class">.swagger</span><span class="selector-class">.web</span><span class="selector-class">.ApiResourceController</span><span class="selector-class">.swaggerResources</span>()</span><br><span class="line"><span class="number">2017</span>-<span class="number">12</span>-<span class="number">25</span> <span class="number">09</span>:<span class="number">13</span>:<span class="number">16.607</span> INFO <span class="number">952</span> --- [ main] s<span class="selector-class">.w</span><span class="selector-class">.s</span><span class="selector-class">.m</span><span class="selector-class">.m</span><span class="selector-class">.a</span><span class="selector-class">.RequestMappingHandlerMapping</span> : Mapped <span class="string">"{[/swagger-resources/configuration/security]}"</span> onto public org<span class="selector-class">.springframework</span><span class="selector-class">.http</span><span class="selector-class">.ResponseEntity</span><springfox<span class="selector-class">.documentation</span><span class="selector-class">.swagger</span><span class="selector-class">.web</span><span class="selector-class">.SecurityConfiguration</span>> springfox<span class="selector-class">.documentation</span><span class="selector-class">.swagger</span><span class="selector-class">.web</span><span class="selector-class">.ApiResourceController</span><span class="selector-class">.securityConfiguration</span>()</span><br></pre></td></tr></table></figure><h2 id="访问Swagger-UI"><a href="#访问Swagger-UI" class="headerlink" title="访问Swagger UI"></a>访问Swagger UI</h2><figure class="highlight dts"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="symbol">http:</span><span class="comment">//localhost:8080/swagger-ui.html</span></span><br></pre></td></tr></table></figure><p><img src="http://orkt468tj.bkt.clouddn.com/17-12-25/95941782.jpg" alt=""></p>]]></content>
<summary type="html">
Spring Boot集成Swagger的入门示例
</summary>
<category term="搬砖" scheme="http://chilam.me/categories/%E6%90%AC%E7%A0%96/"/>
<category term="spring-boot" scheme="http://chilam.me/tags/spring-boot/"/>
</entry>
<entry>
<title>4.sb-日志</title>
<link href="http://chilam.me/2017/12/17/spring-boot-4/"/>
<id>http://chilam.me/2017/12/17/spring-boot-4/</id>
<published>2017-12-17T01:00:04.000Z</published>
<updated>2018-06-30T10:05:00.264Z</updated>
<content type="html"><![CDATA[<h2 id="默认日志"><a href="#默认日志" class="headerlink" title="默认日志"></a>默认日志</h2><p>Spring Boot在所有内部日志中使用Commons Logging,但是默认配置也提供了对常用日志的支持,<br>如:Java Util Logging,Log4J, Log4J2和Logback。每种Logger都可以通过配置使用控制台或者文件输出日志内容。</p><p>SLF4J——Simple Logging Facade For Java,它是一个针对于各类Java日志框架的统一Facade抽象。<br>Java日志框架众多——常用的有java.util.logging, log4j, logback,commons-logging,<br>Spring框架使用的是Jakarta Commons Logging API (JCL)。而SLF4J定义了统一的日志抽象接口,而真正的日志实现则是在运行时决定的<br>——它提供了各类日志框架的binding。</p><p>Logback是log4j框架的作者开发的新一代日志框架,它效率更高、能够适应诸多的运行环境,同时天然支持SLF4J。</p><p>默认情况下,Spring Boot会用Logback来记录日志,并用INFO级别输出到控制台。在运行应用程序和其他例子时,<br>你应该已经看到很多INFO级别的日志了。</p><figure class="highlight taggerscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line">"C:<span class="symbol">\P</span>rogram Files<span class="symbol">\J</span>ava<span class="symbol">\j</span>dk1.8.0_151<span class="symbol">\b</span>in<span class="symbol">\j</span>ava" "-javaagent:E:<span class="symbol">\P</span>rogram Files<span class="symbol">\J</span>etBrains<span class="symbol">\I</span>ntelliJ IDEA 2017.3.1<span class="symbol">\l</span>ib<span class="symbol">\i</span>dea_rt.jar=56049:E:<span class="symbol">\P</span>rogram Files<span class="symbol">\J</span>etBrains<span class="symbol">\I</span>ntelliJ IDEA 2017.3.1<span class="symbol">\b</span>in" -Dfile.encoding=UTF-8 -classpath "C:<span class="symbol">\P</span>rogram Files<span class="symbol">\J</span>ava<span class="symbol">\j</span>dk1.8.0_151<span class="symbol">\j</span>re<span class="symbol">\l</span>ib<span class="symbol">\c</span>harsets.jar;C:<span class="symbol">\P</span>rogram Files<span class="symbol">\J</span>ava<span class="symbol">\j</span>dk1.8.0_151<span class="symbol">\j</span>re<span class="symbol">\l</span>ib<span class="symbol">\d</span>eploy.jar;C:<span class="symbol">\P</span>rogram Files<span class="symbol">\J</span>ava<span class="symbol">\j</span>dk1.8.0_151<span class="symbol">\j</span>re<span class="symbol">\l</span>ib<span class="symbol">\e</span>xt<span class="symbol">\a</span>ccess-bridge-64.jar;C:<span class="symbol">\P</span>rogram Files<span class="symbol">\J</span>ava<span class="symbol">\j</span>dk1.8.0_151<span class="symbol">\j</span>re<span class="symbol">\l</span>ib<span class="symbol">\e</span>xt<span class="symbol">\c</span>ldrdata.jar;C:<span class="symbol">\P</span>rogram Files<span class="symbol">\J</span>ava<span class="symbol">\j</span>dk1.8.0_151<span class="symbol">\j</span>re<span class="symbol">\l</span>ib<span class="symbol">\e</span>xt<span class="symbol">\d</span>nsns.jar;C:<span class="symbol">\P</span>rogram Files<span class="symbol">\J</span>ava<span class="symbol">\j</span>dk1.8.0_151<span class="symbol">\j</span>re<span class="symbol">\l</span>ib<span class="symbol">\e</span>xt<span class="symbol">\j</span>access.jar;C:<span class="symbol">\P</span>rogram Files<span class="symbol">\J</span>ava<span class="symbol">\j</span>dk1.8.0_151<span class="symbol">\j</span>re<span class="symbol">\l</span>ib<span class="symbol">\e</span>xt<span class="symbol">\j</span>fxrt.jar;C:<span class="symbol">\P</span>rogram Files<span class="symbol">\J</span>ava<span class="symbol">\j</span>dk1.8.0_151<span class="symbol">\j</span>re<span class="symbol">\l</span>ib<span class="symbol">\e</span>xt<span class="symbol">\l</span>ocaledata.jar;C:<span class="symbol">\P</span>rogram Files<span class="symbol">\J</span>ava<span class="symbol">\j</span>dk1.8.0_151<span class="symbol">\j</span>re<span class="symbol">\l</span>ib<span class="symbol">\e</span>xt<span class="symbol">\n</span>ashorn.jar;C:<span class="symbol">\P</span>rogram Files<span class="symbol">\J</span>ava<span class="symbol">\j</span>dk1.8.0_151<span class="symbol">\j</span>re<span class="symbol">\l</span>ib<span class="symbol">\e</span>xt<span class="symbol">\s</span>unec.jar;C:<span class="symbol">\P</span>rogram Files<span class="symbol">\J</span>ava<span class="symbol">\j</span>dk1.8.0_151<span class="symbol">\j</span>re<span class="symbol">\l</span>ib<span class="symbol">\e</span>xt<span class="symbol">\s</span>unjce_provider.jar;C:<span class="symbol">\P</span>rogram Files<span class="symbol">\J</span>ava<span class="symbol">\j</span>dk1.8.0_151<span class="symbol">\j</span>re<span class="symbol">\l</span>ib<span class="symbol">\e</span>xt<span class="symbol">\s</span>unmscapi.jar;C:<span class="symbol">\P</span>rogram Files<span class="symbol">\J</span>ava<span class="symbol">\j</span>dk1.8.0_151<span class="symbol">\j</span>re<span class="symbol">\l</span>ib<span class="symbol">\e</span>xt<span class="symbol">\s</span>unpkcs11.jar;C:<span class="symbol">\P</span>rogram Files<span class="symbol">\J</span>ava<span class="symbol">\j</span>dk1.8.0_151<span class="symbol">\j</span>re<span class="symbol">\l</span>ib<span class="symbol">\e</span>xt<span class="symbol">\z</span>ipfs.jar;C:<span class="symbol">\P</span>rogram Files<span class="symbol">\J</span>ava<span class="symbol">\j</span>dk1.8.0_151<span class="symbol">\j</span>re<span class="symbol">\l</span>ib<span class="symbol">\j</span>avaws.jar;C:<span class="symbol">\P</span>rogram Files<span class="symbol">\J</span>ava<span class="symbol">\j</span>dk1.8.0_151<span class="symbol">\j</span>re<span class="symbol">\l</span>ib<span class="symbol">\j</span>ce.jar;C:<span class="symbol">\P</span>rogram Files<span class="symbol">\J</span>ava<span class="symbol">\j</span>dk1.8.0_151<span class="symbol">\j</span>re<span class="symbol">\l</span>ib<span class="symbol">\j</span>fr.jar;C:<span class="symbol">\P</span>rogram Files<span class="symbol">\J</span>ava<span class="symbol">\j</span>dk1.8.0_151<span class="symbol">\j</span>re<span class="symbol">\l</span>ib<span class="symbol">\j</span>fxswt.jar;C:<span class="symbol">\P</span>rogram Files<span class="symbol">\J</span>ava<span class="symbol">\j</span>dk1.8.0_151<span class="symbol">\j</span>re<span class="symbol">\l</span>ib<span class="symbol">\j</span>sse.jar;C:<span class="symbol">\P</span>rogram Files<span class="symbol">\J</span>ava<span class="symbol">\j</span>dk1.8.0_151<span class="symbol">\j</span>re<span class="symbol">\l</span>ib<span class="symbol">\m</span>anagement-agent.jar;C:<span class="symbol">\P</span>rogram Files<span class="symbol">\J</span>ava<span class="symbol">\j</span>dk1.8.0_151<span class="symbol">\j</span>re<span class="symbol">\l</span>ib<span class="symbol">\p</span>lugin.jar;C:<span class="symbol">\P</span>rogram Files<span class="symbol">\J</span>ava<span class="symbol">\j</span>dk1.8.0_151<span class="symbol">\j</span>re<span class="symbol">\l</span>ib<span class="symbol">\r</span>esources.jar;C:<span class="symbol">\P</span>rogram Files<span class="symbol">\J</span>ava<span class="symbol">\j</span>dk1.8.0_151<span class="symbol">\j</span>re<span class="symbol">\l</span>ib<span class="symbol">\r</span>t.jar;E:<span class="symbol">\c</span>odes<span class="symbol">\j</span>ava<span class="symbol">\s</span>pring-boot-demo<span class="symbol">\t</span>arget<span class="symbol">\c</span>lasses;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\o</span>rg<span class="symbol">\s</span>pringframework<span class="symbol">\b</span>oot<span class="symbol">\s</span>pring-boot-starter-web<span class="symbol">\1</span>.5.9.RELEASE<span class="symbol">\s</span>pring-boot-starter-web-1.5.9.RELEASE.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\o</span>rg<span class="symbol">\s</span>pringframework<span class="symbol">\b</span>oot<span class="symbol">\s</span>pring-boot-starter<span class="symbol">\1</span>.5.9.RELEASE<span class="symbol">\s</span>pring-boot-starter-1.5.9.RELEASE.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\o</span>rg<span class="symbol">\s</span>pringframework<span class="symbol">\b</span>oot<span class="symbol">\s</span>pring-boot<span class="symbol">\1</span>.5.9.RELEASE<span class="symbol">\s</span>pring-boot-1.5.9.RELEASE.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\o</span>rg<span class="symbol">\s</span>pringframework<span class="symbol">\b</span>oot<span class="symbol">\s</span>pring-boot-autoconfigure<span class="symbol">\1</span>.5.9.RELEASE<span class="symbol">\s</span>pring-boot-autoconfigure-1.5.9.RELEASE.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\o</span>rg<span class="symbol">\s</span>pringframework<span class="symbol">\b</span>oot<span class="symbol">\s</span>pring-boot-starter-logging<span class="symbol">\1</span>.5.9.RELEASE<span class="symbol">\s</span>pring-boot-starter-logging-1.5.9.RELEASE.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\c</span>h<span class="symbol">\q</span>os<span class="symbol">\l</span>ogback<span class="symbol">\l</span>ogback-classic<span class="symbol">\1</span>.1.11<span class="symbol">\l</span>ogback-classic-1.1.11.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\c</span>h<span class="symbol">\q</span>os<span class="symbol">\l</span>ogback<span class="symbol">\l</span>ogback-core<span class="symbol">\1</span>.1.11<span class="symbol">\l</span>ogback-core-1.1.11.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\o</span>rg<span class="symbol">\s</span>lf4j<span class="symbol">\s</span>lf4j-api<span class="symbol">\1</span>.7.25<span class="symbol">\s</span>lf4j-api-1.7.25.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\o</span>rg<span class="symbol">\s</span>lf4j<span class="symbol">\j</span>cl-over-slf4j<span class="symbol">\1</span>.7.25<span class="symbol">\j</span>cl-over-slf4j-1.7.25.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\o</span>rg<span class="symbol">\s</span>lf4j<span class="symbol">\j</span>ul-to-slf4j<span class="symbol">\1</span>.7.25<span class="symbol">\j</span>ul-to-slf4j-1.7.25.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\o</span>rg<span class="symbol">\s</span>lf4j<span class="symbol">\l</span>og4j-over-slf4j<span class="symbol">\1</span>.7.25<span class="symbol">\l</span>og4j-over-slf4j-1.7.25.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\o</span>rg<span class="symbol">\s</span>pringframework<span class="symbol">\s</span>pring-core<span class="symbol">\4</span>.3.13.RELEASE<span class="symbol">\s</span>pring-core-4.3.13.RELEASE.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\o</span>rg<span class="symbol">\y</span>aml<span class="symbol">\s</span>nakeyaml<span class="symbol">\1</span>.17<span class="symbol">\s</span>nakeyaml-1.17.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\o</span>rg<span class="symbol">\s</span>pringframework<span class="symbol">\b</span>oot<span class="symbol">\s</span>pring-boot-starter-tomcat<span class="symbol">\1</span>.5.9.RELEASE<span class="symbol">\s</span>pring-boot-starter-tomcat-1.5.9.RELEASE.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\o</span>rg<span class="symbol">\a</span>pache<span class="symbol">\t</span>omcat<span class="symbol">\e</span>mbed<span class="symbol">\t</span>omcat-embed-websocket<span class="symbol">\8</span>.5.23<span class="symbol">\t</span>omcat-embed-websocket-8.5.23.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\o</span>rg<span class="symbol">\h</span>ibernate<span class="symbol">\h</span>ibernate-validator<span class="symbol">\5</span>.3.6.Final<span class="symbol">\h</span>ibernate-validator-5.3.6.Final.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\j</span>avax<span class="symbol">\v</span>alidation<span class="symbol">\v</span>alidation-api<span class="symbol">\1</span>.1.0.Final<span class="symbol">\v</span>alidation-api-1.1.0.Final.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\o</span>rg<span class="symbol">\j</span>boss<span class="symbol">\l</span>ogging<span class="symbol">\j</span>boss-logging<span class="symbol">\3</span>.3.1.Final<span class="symbol">\j</span>boss-logging-3.3.1.Final.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\c</span>om<span class="symbol">\f</span>asterxml<span class="symbol">\c</span>lassmate<span class="symbol">\1</span>.3.4<span class="symbol">\c</span>lassmate-1.3.4.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\c</span>om<span class="symbol">\f</span>asterxml<span class="symbol">\j</span>ackson<span class="symbol">\c</span>ore<span class="symbol">\j</span>ackson-databind<span class="symbol">\2</span>.8.10<span class="symbol">\j</span>ackson-databind-2.8.10.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\c</span>om<span class="symbol">\f</span>asterxml<span class="symbol">\j</span>ackson<span class="symbol">\c</span>ore<span class="symbol">\j</span>ackson-annotations<span class="symbol">\2</span>.8.0<span class="symbol">\j</span>ackson-annotations-2.8.0.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\c</span>om<span class="symbol">\f</span>asterxml<span class="symbol">\j</span>ackson<span class="symbol">\c</span>ore<span class="symbol">\j</span>ackson-core<span class="symbol">\2</span>.8.10<span class="symbol">\j</span>ackson-core-2.8.10.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\o</span>rg<span class="symbol">\s</span>pringframework<span class="symbol">\s</span>pring-web<span class="symbol">\4</span>.3.13.RELEASE<span class="symbol">\s</span>pring-web-4.3.13.RELEASE.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\o</span>rg<span class="symbol">\s</span>pringframework<span class="symbol">\s</span>pring-aop<span class="symbol">\4</span>.3.13.RELEASE<span class="symbol">\s</span>pring-aop-4.3.13.RELEASE.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\o</span>rg<span class="symbol">\s</span>pringframework<span class="symbol">\s</span>pring-beans<span class="symbol">\4</span>.3.13.RELEASE<span class="symbol">\s</span>pring-beans-4.3.13.RELEASE.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\o</span>rg<span class="symbol">\s</span>pringframework<span class="symbol">\s</span>pring-context<span class="symbol">\4</span>.3.13.RELEASE<span class="symbol">\s</span>pring-context-4.3.13.RELEASE.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\o</span>rg<span class="symbol">\s</span>pringframework<span class="symbol">\s</span>pring-webmvc<span class="symbol">\4</span>.3.13.RELEASE<span class="symbol">\s</span>pring-webmvc-4.3.13.RELEASE.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\o</span>rg<span class="symbol">\s</span>pringframework<span class="symbol">\s</span>pring-expression<span class="symbol">\4</span>.3.13.RELEASE<span class="symbol">\s</span>pring-expression-4.3.13.RELEASE.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\j</span>avax<span class="symbol">\s</span>ervlet<span class="symbol">\j</span>stl<span class="symbol">\1</span>.2<span class="symbol">\j</span>stl-1.2.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\o</span>rg<span class="symbol">\a</span>pache<span class="symbol">\t</span>omcat<span class="symbol">\e</span>mbed<span class="symbol">\t</span>omcat-embed-core<span class="symbol">\8</span>.5.23<span class="symbol">\t</span>omcat-embed-core-8.5.23.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\o</span>rg<span class="symbol">\a</span>pache<span class="symbol">\t</span>omcat<span class="symbol">\t</span>omcat-annotations-api<span class="symbol">\8</span>.5.23<span class="symbol">\t</span>omcat-annotations-api-8.5.23.jar;E:<span class="symbol">\m</span>aven_repos<span class="symbol">\o</span>rg<span class="symbol">\a</span>pache<span class="symbol">\t</span>omcat<span class="symbol">\e</span>mbed<span class="symbol">\t</span>omcat-embed-el<span class="symbol">\8</span>.5.23<span class="symbol">\t</span>omcat-embed-el-8.5.23.jar" Application</span><br><span class="line"></span><br><span class="line"> . ____ _ __ _ _</span><br><span class="line"> /<span class="symbol">\\</span> / ___'_ __ _ _(_)_ __ __ _ <span class="symbol">\ </span><span class="symbol">\ </span><span class="symbol">\ </span>\</span><br><span class="line">( ( )<span class="symbol">\_</span>__ | '_ | '_| | '_ <span class="symbol">\/</span> _` | <span class="symbol">\ </span><span class="symbol">\ </span><span class="symbol">\ </span>\</span><br><span class="line"> <span class="symbol">\\</span>/ ___)| |_)| | | | | || (_| | ) ) ) )</span><br><span class="line"> ' |____| .__|_| |_|_| |_<span class="symbol">\_</span>_, | / / / /</span><br><span class="line"> =========|_|==============|___/=/_/_/_/</span><br><span class="line"> :: Spring Boot :: (v1.5.9.RELEASE)</span><br><span class="line"></span><br><span class="line">2017-12-18 11:49:38.689 INFO 11064 --- [ main] Application : Starting Application on USER-20170427SG with PID 11064 (E:<span class="symbol">\c</span>odes<span class="symbol">\j</span>ava<span class="symbol">\s</span>pring-boot-demo<span class="symbol">\t</span>arget<span class="symbol">\c</span>lasses started by Administrator in E:<span class="symbol">\c</span>odes<span class="symbol">\j</span>ava<span class="symbol">\s</span>pring-boot-demo)</span><br><span class="line">2017-12-18 11:49:38.692 INFO 11064 --- [ main] Application : No active profile set, falling back to default profiles: default</span><br><span class="line">2017-12-18 11:49:38.753 INFO 11064 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@3bd94634: startup date [Mon Dec 18 11:49:38 CST 2017]; root of context hierarchy</span><br><span class="line">2017-12-18 11:49:40.329 INFO 11064 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http)</span><br><span class="line">2017-12-18 11:49:40.339 INFO 11064 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]</span><br><span class="line">2017-12-18 11:49:40.340 INFO 11064 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.23</span><br><span class="line">2017-12-18 11:49:40.435 INFO 11064 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext</span><br><span class="line">2017-12-18 11:49:40.435 INFO 11064 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1685 ms</span><br><span class="line">2017-12-18 11:49:40.550 INFO 11064 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/]</span><br><span class="line">2017-12-18 11:49:40.554 INFO 11064 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*]</span><br><span class="line">2017-12-18 11:49:40.554 INFO 11064 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]</span><br><span class="line">2017-12-18 11:49:40.554 INFO 11064 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*]</span><br><span class="line">2017-12-18 11:49:40.554 INFO 11064 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*]</span><br><span class="line">2017-12-18 11:49:40.833 INFO 11064 --- [ main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@3bd94634: startup date [Mon Dec 18 11:49:38 CST 2017]; root of context hierarchy</span><br><span class="line">2017-12-18 11:49:40.901 INFO 11064 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/jsp/index.do]}" onto public java.lang.String me.chilam.web.JspController.execute()</span><br><span class="line">2017-12-18 11:49:40.903 INFO 11064 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)</span><br><span class="line">2017-12-18 11:49:40.904 INFO 11064 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)</span><br><span class="line">2017-12-18 11:49:40.930 INFO 11064 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/hello/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]</span><br><span class="line">2017-12-18 11:49:40.930 INFO 11064 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]</span><br><span class="line">2017-12-18 11:49:40.930 INFO 11064 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]</span><br><span class="line">2017-12-18 11:49:40.975 INFO 11064 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]</span><br><span class="line">2017-12-18 11:49:41.086 INFO 11064 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup</span><br><span class="line">2017-12-18 11:49:41.136 INFO 11064 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)</span><br><span class="line">2017-12-18 11:49:41.140 INFO 11064 --- [ main] Application : Started Application in 2.737 seconds (JVM running for 3.146)</span><br></pre></td></tr></table></figure><p>从上图可以看到,日志输出内容元素具体如下:</p><ul><li>时间日期:精确到毫秒</li><li>日志级别:ERROR, WARN, INFO, DEBUG or TRACE</li><li>进程ID</li><li>分隔符:— 标识实际日志的开始</li><li>线程名:方括号括起来(可能会截断控制台输出)</li><li>Logger名:通常使用源代码的类名</li><li>日志内容</li></ul><h3 id="控制台输出日志"><a href="#控制台输出日志" class="headerlink" title="控制台输出日志"></a>控制台输出日志</h3><p>日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出。</p><p>在application.properties中配置debug=true,该属性置为true的时候,核心Logger(包含嵌入式容器、hibernate、spring)<br>会输出更多内容,但是你自己应用的日志并不会输出为DEBUG级别。</p><h3 id="文件输出"><a href="#文件输出" class="headerlink" title="文件输出"></a>文件输出</h3><p>默认情况下,Spring Boot将日志输出到控制台,不会写到日志文件。如果要编写除控制台输出之外的日志文件,<br>则需在application.properties中设置logging.file或logging.path属性。</p><ul><li>logging.file,设置文件,可以是绝对路径,也可以是相对路径。如:logging.file=my.log</li><li>logging.path,设置目录,会在该目录下创建spring.log文件,并写入日志内容,如:logging.path=/var/log</li></ul><p>如果只配置 logging.file,会在项目的当前路径下生成一个 xxx.log 日志文件。<br>如果只配置 logging.path,在 /var/log文件夹生成一个日志文件为 spring.log</p><p><strong>注:二者不能同时使用,如若同时使用,则只有logging.file生效</strong></p><p>默认情况下,日志文件的大小达到10MB时会切分一次,产生新的日志文件,默认级别为:ERROR、WARN、INFO</p><h3 id="级别控制"><a href="#级别控制" class="headerlink" title="级别控制"></a>级别控制</h3><p>所有支持的日志记录系统都可以在Spring Boot环境中设置记录级别(例如在application.properties中)<br>格式为:’logging.level.* = LEVEL’</p><ul><li>logging.level:日志级别控制前缀,*为包名或Logger名</li><li>LEVEL:选项TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF</li></ul><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 配置org.springframework的日志级别为WARN</span></span><br><span class="line">logging.level.org.<span class="attribute">springframework</span>=WARN</span><br></pre></td></tr></table></figure><h3 id="自定义日志配置"><a href="#自定义日志配置" class="headerlink" title="自定义日志配置"></a>自定义日志配置</h3><p>常见的日志有很多种方式,根据不同的日志系统,可以按照规则组织配置文件名,就能被正确加载:</p><ul><li>Logback:logback-spring.xml, logback-spring.groovy, logback.xml, logback.groovy</li><li>Log4j:log4j-spring.properties, log4j-spring.xml, log4j.properties, log4j.xml</li><li>Log4j2:log4j2-spring.xml, log4j2.xml</li><li>JDK (Java Util Logging):logging.properties</li></ul><p>Spring Boot官方推荐优先使用带有-spring的文件名作为你的日志配置(如使用logback-spring.xml,而不是logback.xml),<br>命名为logback-spring.xml的日志配置文件,spring boot可以为它添加一些spring boot特有的配置项(下面会提到)。</p><p>上面是默认的命名规则,并且放在src/main/resources下面即可。</p><p>如果你即想完全掌控日志配置,但又不想用logback.xml作为Logback配置的名字,<br>可以在application.properties配置文件里面通过logging.config属性指定自定义的名字:</p><figure class="highlight arduino"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">logging.<span class="built_in">config</span>=classpath:logging-<span class="built_in">config</span>.xml</span><br></pre></td></tr></table></figure><p>关于logback的配置的介绍,这里就不再做多余的介绍,请参考的logback的官网的文档</p>]]></content>
<summary type="html">
默认日志配置,自定义日志配置
</summary>
<category term="搬砖" scheme="http://chilam.me/categories/%E6%90%AC%E7%A0%96/"/>
<category term="spring-boot" scheme="http://chilam.me/tags/spring-boot/"/>
</entry>
</feed>