This repository has been archived by the owner on Oct 1, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
316 lines (286 loc) · 77.8 KB
/
index.html
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
<!DOCTYPE html><html class="theme-next muse use-motion" lang="zh-Hans"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1"><script src="//cdn.bootcss.com/pace/1.0.2/pace.min.js"></script><link href="//cdn.bootcss.com/pace/1.0.2/themes/pink/pace-theme-flash.css" rel="stylesheet"><style>.pace .pace-progress{background:#1e92fb;height:3px}.pace .pace-progress-inner{box-shadow:0 0 10px #1e92fb,0 0 5px #1e92fb}.pace .pace-activity{border-top-color:#1e92fb;border-left-color:#1e92fb}</style><meta name="theme-color" content="#222"><script></script><meta http-equiv="Cache-Control" content="no-transform"><meta http-equiv="Cache-Control" content="no-siteapp"><link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css"><link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css"><link href="/css/main.css?v=5.1.4" rel="stylesheet" type="text/css"><link rel="icon" type="image/png" sizes="32x32" href="/images/favicon.png?v=5.1.4"><link rel="icon" type="image/png" sizes="16x16" href="/images/favicon.png?v=5.1.4"><meta name="keywords" content="工具,技术"><link rel="alternate" href="/atom.xml" title="jian" type="application/atom+xml"><meta name="keywords" content="工具,技术"><meta property="og:type" content="website"><meta property="og:title" content="jian"><meta property="og:url" content="http://blog.zhangjian.ml/index.html"><meta property="og:site_name" content="jian"><meta property="og:locale" content="zh-Hans"><meta name="twitter:card" content="summary"><meta name="twitter:title" content="jian"><script type="text/javascript" id="hexo.configurations">var NexT=window.NexT||{},CONFIG={root:"/",scheme:"Muse",version:"5.1.4",sidebar:{position:"left",display:"post",offset:12,b2t:!1,scrollpercent:!1,onmobile:!1},fancybox:!0,tabs:!0,motion:{enable:!0,async:!1,transition:{post_block:"fadeIn",post_header:"slideDownIn",post_body:"slideDownIn",coll_header:"slideLeftIn",sidebar:"slideUpIn"}},duoshuo:{userId:"0",author:"博主"},algolia:{applicationID:"",apiKey:"",indexName:"",hits:{per_page:10},labels:{input_placeholder:"Search for Posts",hits_empty:"We didn't find any results for the search: ${query}",hits_stats:"${hits} results found in ${time} ms"}}}</script><link rel="canonical" href="http://blog.zhangjian.ml/"><title>jian</title></head><body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans"><div class="container sidebar-position-left page-home"><div class="headband"></div><header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader"><div class="header-inner"><div class="site-brand-wrapper"><div class="site-meta custom-logo"><div class="site-meta-headline"> <a><img class="custom-logo-image" src="/images/logo.jpg" alt="jian"></a></div><div class="custom-logo-site-title"><a href="/" class="brand" rel="start"><span class="logo-line-before"><i></i></span> <span class="site-title">jian</span><span class="logo-line-after"><i></i></span></a></div><h1 class="site-subtitle" itemprop="description"></h1></div><div class="site-nav-toggle"> <button><span class="btn-bar"></span><span class="btn-bar"></span><span class="btn-bar"></span></button></div></div><nav class="site-nav"><ul id="menu" class="menu"><li class="menu-item menu-item-home"><a href="/" rel="section"><i class="menu-item-icon fa fa-fw fa-home"></i><br> 首页</a></li><li class="menu-item menu-item-about"><a href="/about/" rel="section"><i class="menu-item-icon fa fa-fw fa-user"></i><br> 关于</a></li><li class="menu-item menu-item-tags"><a href="/tags/" rel="section"><i class="menu-item-icon fa fa-fw fa-tags"></i><br> 标签</a></li><li class="menu-item menu-item-categories"><a href="/categories/" rel="section"><i class="menu-item-icon fa fa-fw fa-th"></i><br> 分类</a></li><li class="menu-item menu-item-archives"><a href="/archives/" rel="section"><i class="menu-item-icon fa fa-fw fa-archive"></i><br> 归档</a></li><li class="menu-item menu-item-search"><a href="javascript:;" class="popup-trigger"><i class="menu-item-icon fa fa-search fa-fw"></i><br> 搜索</a></li></ul><div class="site-search"><div class="popup search-popup local-search-popup"><div class="local-search-header clearfix"><span class="search-icon"><i class="fa fa-search"></i></span><span class="popup-btn-close"><i class="fa fa-times-circle"></i></span><div class="local-search-input-wrapper"> <input autocomplete="off" placeholder="搜索..." spellcheck="false" type="text" id="local-search-input"></div></div><div id="local-search-result"></div></div></div></nav></div></header><main id="main" class="main"><div class="main-inner"><div class="content-wrap"><div id="content" class="content"><section id="posts" class="posts-expand"><article class="post post-type-normal" itemscope itemtype="http://schema.org/Article"><div class="post-block"><link itemprop="mainEntityOfPage" href="http://blog.zhangjian.ml/2018/09/16/jmockit/"><span hidden itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="name" content="jian zhang"><meta itemprop="description" content=""><meta itemprop="image" content="/images/avatar.gif"></span><span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="jian"></span><header class="post-header"><h2 class="post-title" itemprop="name headline"> <a class="post-title-link" href="/2018/09/16/jmockit/" itemprop="url">jmockit</a></h2><div class="post-meta"><span class="post-time"><span class="post-meta-item-icon"><i class="fa fa-calendar-o"></i></span> <span class="post-meta-item-text">发表于</span> <time title="创建于" itemprop="dateCreated datePublished" datetime="2018-09-16T17:08:49+08:00">2018-09-16</time></span> <span class="post-category"><span class="post-meta-divider">|</span><span class="post-meta-item-icon"><i class="fa fa-folder-o"></i></span> <span class="post-meta-item-text">分类于</span> <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/技术/" itemprop="url" rel="index"><span itemprop="name">技术</span></a></span> , <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/技术/后端/" itemprop="url" rel="index"><span itemprop="name">后端</span></a></span></span> <span id="/2018/09/16/jmockit/" class="leancloud_visitors" data-flag-title="jmockit"><span class="post-meta-divider">|</span><span class="post-meta-item-icon"><i class="fa fa-eye"></i></span> <span class="post-meta-item-text">阅读次数:</span><span class="leancloud-visitors-count"></span></span></div></header><div class="post-body" itemprop="articleBody"><p> 之前试过powermock,虽然可以mock 静态方法,但是得依赖maven 插件,而后找到了<code>jmockit</code>,配置非常简洁、性能高。<br> <a href="http://jmockit.cn/showChannel.htm?channel=2" target="_blank" rel="noopener">中文文档</a></p><h1 id="脚本录制规范"><a href="#脚本录制规范" class="headerlink" title="脚本录制规范"></a>脚本录制规范</h1><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><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="keyword">new</span> Expectations() {</span><br><span class="line"> <span class="comment">// 这是一个Expectations匿名内部类</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">//result赋值要紧跟在方法调用后面</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">//result赋值</span></span><br><span class="line"> }</span><br><span class="line">};</span><br><span class="line"> </span><br><span class="line">还可以再写<span class="keyword">new</span>一个Expectations,只要出现在重放阶段之前均有效。</span><br><span class="line"><span class="keyword">new</span> Expectations() {</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><br><span class="line">};</span><br></pre></td></tr></table></figure><h1 id="mock整个类"><a href="#mock整个类" class="headerlink" title="mock整个类"></a>mock整个类</h1><p><code>@Injectabe</code>: 只mock<code>jmockit</code>初始化的实例;<br><code>@Mocked</code>: mock标注类的所有实例,包括手动实例化;<br><code>@Capturing</code>: 影响接口所有子类的实现,包括动态代理;</p><p>示例:<br></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><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="comment">//Expectations对外部类的mock对象进行录制</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ExpectationsTest</span> </span>{</span><br><span class="line"> <span class="meta">@Mocked</span></span><br><span class="line"> Calendar cal;</span><br><span class="line"> </span><br><span class="line"> <span class="meta">@Test</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testRecordOutside</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">new</span> Expectations() {</span><br><span class="line"> {</span><br><span class="line"> <span class="comment">// 对cal.get方法进行录制,并匹配参数 Calendar.YEAR</span></span><br><span class="line"> cal.get(Calendar.YEAR);</span><br><span class="line"> result = <span class="number">2016</span>;<span class="comment">// 年份不再返回当前小时。而是返回2016年</span></span><br><span class="line"> <span class="comment">// 对cal.get方法进行录制,并匹配参数 Calendar.HOUR_OF_DAY</span></span><br><span class="line"> cal.get(Calendar.HOUR_OF_DAY);</span><br><span class="line"> result = <span class="number">7</span>;<span class="comment">// 小时不再返回当前小时。而是返回早上7点钟</span></span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line"> Assert.assertTrue(cal.get(Calendar.YEAR) == <span class="number">2016</span>);</span><br><span class="line"> Assert.assertTrue(cal.get(Calendar.HOUR_OF_DAY) == <span class="number">7</span>);</span><br><span class="line"> <span class="comment">// 因为没有录制过,所以这里月份返回默认值 0</span></span><br><span class="line"> Assert.assertTrue(cal.get(Calendar.DAY_OF_MONTH) == <span class="number">0</span>);</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line">}</span><br></pre></td></tr></table></figure><p></p><h1 id="对类部分mock"><a href="#对类部分mock" class="headerlink" title="对类部分mock"></a>对类部分mock</h1><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//通过Expectations对其构造函数mock对象进行录制</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ExpectationsConstructorTest2</span> </span>{</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// 把类传入Expectations的构造函数</span></span><br><span class="line"> <span class="meta">@Test</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testRecordConstrutctor1</span><span class="params">()</span> </span>{</span><br><span class="line"> Calendar cal = Calendar.getInstance();</span><br><span class="line"> <span class="comment">// 把待Mock的类传入Expectations的构造函数,可以达到只mock类的部分行为的目的</span></span><br><span class="line"> <span class="keyword">new</span> Expectations(Calendar.class) {</span><br><span class="line"> {</span><br><span class="line"> <span class="comment">// 只对get方法并且参数为Calendar.HOUR_OF_DAY进行录制</span></span><br><span class="line"> cal.get(Calendar.HOUR_OF_DAY);</span><br><span class="line"> result = <span class="number">7</span>;<span class="comment">// 小时永远返回早上7点钟</span></span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line"> Calendar now = Calendar.getInstance();</span><br><span class="line"> <span class="comment">// 因为下面的调用mock过了,小时永远返回7点钟了</span></span><br><span class="line"> Assert.assertTrue(now.get(Calendar.HOUR_OF_DAY) == <span class="number">7</span>);</span><br><span class="line"> <span class="comment">// 因为下面的调用没有mock过,所以方法的行为不受mock影响,</span></span><br><span class="line"> Assert.assertTrue(now.get(Calendar.DAY_OF_MONTH) == (<span class="keyword">new</span> Date()).getDate());</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// 把对象传入Expectations的构造函数</span></span><br><span class="line"> <span class="meta">@Test</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testRecordConstrutctor2</span><span class="params">()</span> </span>{</span><br><span class="line"> Calendar cal = Calendar.getInstance();</span><br><span class="line"> <span class="comment">// 把待Mock的对象传入Expectations的构造函数,可以达到只mock类的部分行为的目的,但只对这个对象影响</span></span><br><span class="line"> <span class="keyword">new</span> Expectations(cal) {</span><br><span class="line"> {</span><br><span class="line"> <span class="comment">// 只对get方法并且参数为Calendar.HOUR_OF_DAY进行录制</span></span><br><span class="line"> cal.get(Calendar.HOUR_OF_DAY);</span><br><span class="line"> result = <span class="number">7</span>;<span class="comment">// 小时永远返回早上7点钟</span></span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// 因为下面的调用mock过了,小时永远返回7点钟了</span></span><br><span class="line"> Assert.assertTrue(cal.get(Calendar.HOUR_OF_DAY) == <span class="number">7</span>);</span><br><span class="line"> <span class="comment">// 因为下面的调用没有mock过,所以方法的行为不受mock影响,</span></span><br><span class="line"> Assert.assertTrue(cal.get(Calendar.DAY_OF_MONTH) == (<span class="keyword">new</span> Date()).getDate());</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// now是另一个对象,上面录制只对cal对象的影响,所以now的方法行为没有任何变化</span></span><br><span class="line"> Calendar now = Calendar.getInstance();</span><br><span class="line"> <span class="comment">// 不受mock影响</span></span><br><span class="line"> Assert.assertTrue(now.get(Calendar.HOUR_OF_DAY) == (<span class="keyword">new</span> Date()).getHours());</span><br><span class="line"> <span class="comment">// 不受mock影响</span></span><br><span class="line"> Assert.assertTrue(now.get(Calendar.DAY_OF_MONTH) == (<span class="keyword">new</span> Date()).getDate());</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h1 id="验证"><a href="#验证" class="headerlink" title="验证"></a>验证</h1><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><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="keyword">new</span> Verifications() {</span><br><span class="line"> <span class="comment">// 这是一个Verifications匿名内部类</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">//times/minTimes/maxTime 表示调用次数的限定要求。赋值要紧跟在方法调用后面,也可以不写(表示只要调用过就行,不限次数)</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">//times/minTimes/maxTime赋值</span></span><br><span class="line"> }</span><br><span class="line">};</span><br><span class="line"> </span><br><span class="line">还可以再写<span class="keyword">new</span>一个Verifications,只要出现在重放阶段之后均有效。</span><br><span class="line"><span class="keyword">new</span> Verifications() {</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><br><span class="line">};</span><br></pre></td></tr></table></figure><hr></div><div></div><footer class="post-footer"><div class="post-eof"></div></footer></div></article><article class="post post-type-normal" itemscope itemtype="http://schema.org/Article"><div class="post-block"><link itemprop="mainEntityOfPage" href="http://blog.zhangjian.ml/2018/09/16/powermock/"><span hidden itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="name" content="jian zhang"><meta itemprop="description" content=""><meta itemprop="image" content="/images/avatar.gif"></span><span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="jian"></span><header class="post-header"><h2 class="post-title" itemprop="name headline"> <a class="post-title-link" href="/2018/09/16/powermock/" itemprop="url">powermock</a></h2><div class="post-meta"><span class="post-time"><span class="post-meta-item-icon"><i class="fa fa-calendar-o"></i></span> <span class="post-meta-item-text">发表于</span> <time title="创建于" itemprop="dateCreated datePublished" datetime="2018-09-16T16:51:53+08:00">2018-09-16</time></span> <span class="post-category"><span class="post-meta-divider">|</span><span class="post-meta-item-icon"><i class="fa fa-folder-o"></i></span> <span class="post-meta-item-text">分类于</span> <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/技术/" itemprop="url" rel="index"><span itemprop="name">技术</span></a></span> , <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/技术/后端/" itemprop="url" rel="index"><span itemprop="name">后端</span></a></span></span> <span id="/2018/09/16/powermock/" class="leancloud_visitors" data-flag-title="powermock"><span class="post-meta-divider">|</span><span class="post-meta-item-icon"><i class="fa fa-eye"></i></span> <span class="post-meta-item-text">阅读次数:</span><span class="leancloud-visitors-count"></span></span></div></header><div class="post-body" itemprop="articleBody"><h1 id="特性"><a href="#特性" class="headerlink" title="特性"></a>特性</h1><p>首先mockito框架,可以mock,也可以spy,但是不能mock静态方法,和私有方法,<br>然而powermock支持;<br><a href="https://github.com/hehonghui/mockito-doc-zh/blob/master/mr.simple.md" target="_blank" rel="noopener">mockito中文文档</a></p><h1 id="maven-依赖"><a href="#maven-依赖" class="headerlink" title="maven 依赖"></a>maven 依赖</h1><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></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">properties</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">powermock.version</span>></span>1.7.1<span class="tag"></<span class="name">powermock.version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">mockito1.version</span>></span>1.10.19<span class="tag"></<span class="name">mockito1.version</span>></span></span><br><span class="line"><span class="tag"></<span class="name">properties</span>></span></span><br><span class="line"><span class="tag"><<span class="name">dependencies</span>></span></span><br><span class="line"> <span class="comment"><!-- 依赖 --></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<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>spring-test<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>${spring.version}<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>junit<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>junit<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>4.12<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>org.mockito<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>mockito-core<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>${mockito1.version}<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">scope</span>></span>test<span class="tag"></<span class="name">scope</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>org.powermock<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>powermock-module-junit4<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>${powermock.version}<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">scope</span>></span>test<span class="tag"></<span class="name">scope</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>org.powermock<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>powermock-api-mockito<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>${powermock.version}<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">scope</span>></span>test<span class="tag"></<span class="name">scope</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>org.powermock<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>powermock-module-junit4-rule-agent<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>${powermock.version}<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">scope</span>></span>test<span class="tag"></<span class="name">scope</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">dependencies</span>></span></span><br><span class="line"><span class="tag"><<span class="name">build</span>></span></span><br><span class="line"> <span class="comment"><!-- 插件配置 --></span></span><br><span class="line"> <span class="tag"><<span class="name">plugins</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">plugin</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.apache.maven.plugins<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>maven-surefire-plugin<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">configuration</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">argLine</span>></span>-javaagent:${settings.localRepository}/org/powermock/powermock-module-javaagent/1.7.1/powermock-module-javaagent-1.7.1.jar -XX:-UseSplitVerifier<span class="tag"></<span class="name">argLine</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">configuration</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">plugin</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">plugins</span>></span></span><br><span class="line"><span class="tag"></<span class="name">build</span>></span></span><br></pre></td></tr></table></figure><h1 id="测试用例"><a href="#测试用例" class="headerlink" title="测试用例"></a>测试用例</h1><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@WebAppConfiguration</span></span><br><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="meta">@ContextConfiguration</span>(locations = {<span class="string">"classpath:spring-application.xml"</span>})</span><br><span class="line"><span class="meta">@RunWith</span>(SpringJUnit4ClassRunner.class)</span><br><span class="line"><span class="meta">@PrepareForTest</span>(HttpPayUtil.class)<span class="comment">//准备静态类</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ControllerTest</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">protected</span> MockMvc mockMvc;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Rule</span></span><br><span class="line"> <span class="keyword">public</span> PowerMockRule rule = <span class="keyword">new</span> PowerMockRule();</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Autowired</span></span><br><span class="line"> <span class="keyword">protected</span> WebApplicationContext webApplicationContext;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="meta">@Before</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setUp</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>{</span><br><span class="line"> PropertyConfigurator.configure(<span class="keyword">new</span> FileInputStream(ResourceUtils.getFile(ResourceUtils.CLASSPATH_URL_PREFIX+<span class="string">"log4j.properties"</span>)));</span><br><span class="line"> mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();</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="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> Exception</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@Test</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test</span><span class="params">()</span><span class="keyword">throws</span> Exception</span>{</span><br><span class="line"> <span class="comment">//mock静态类</span></span><br><span class="line"> PowerMockito.mockStatic(HttpPayUtil.class);</span><br><span class="line"> <span class="comment">//录制脚本</span></span><br><span class="line"> PowerMockito.when(HttpPayUtil.queryOrderDetail(<span class="string">"1"</span>, PayConstants.PaySource.WEAPP))</span><br><span class="line"> .thenReturn(<span class="keyword">new</span> String[]{<span class="string">"2"</span>,<span class="string">"3"</span>});</span><br><span class="line"></span><br><span class="line"> String[] stss = HttpPayUtil.queryOrderDetail(<span class="string">"1"</span>, PayConstants.PaySource.WEAPP);</span><br><span class="line"> System.out.println(stss[<span class="number">0</span>]);</span><br><span class="line"> System.out.println(stss[<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><h1 id="运行测试"><a href="#运行测试" class="headerlink" title="运行测试"></a>运行测试</h1><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mvn test</span><br></pre></td></tr></table></figure><hr></div><div></div><footer class="post-footer"><div class="post-eof"></div></footer></div></article><article class="post post-type-normal" itemscope itemtype="http://schema.org/Article"><div class="post-block"><link itemprop="mainEntityOfPage" href="http://blog.zhangjian.ml/2018/09/16/vue-阿里云上传组件/"><span hidden itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="name" content="jian zhang"><meta itemprop="description" content=""><meta itemprop="image" content="/images/avatar.gif"></span><span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="jian"></span><header class="post-header"><h2 class="post-title" itemprop="name headline"> <a class="post-title-link" href="/2018/09/16/vue-阿里云上传组件/" itemprop="url">vue-阿里云上传组件</a></h2><div class="post-meta"><span class="post-time"><span class="post-meta-item-icon"><i class="fa fa-calendar-o"></i></span> <span class="post-meta-item-text">发表于</span> <time title="创建于" itemprop="dateCreated datePublished" datetime="2018-09-16T16:45:00+08:00">2018-09-16</time></span> <span class="post-category"><span class="post-meta-divider">|</span><span class="post-meta-item-icon"><i class="fa fa-folder-o"></i></span> <span class="post-meta-item-text">分类于</span> <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/技术/" itemprop="url" rel="index"><span itemprop="name">技术</span></a></span> , <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/技术/前端/" itemprop="url" rel="index"><span itemprop="name">前端</span></a></span></span> <span id="/2018/09/16/vue-阿里云上传组件/" class="leancloud_visitors" data-flag-title="vue-阿里云上传组件"><span class="post-meta-divider">|</span><span class="post-meta-item-icon"><i class="fa fa-eye"></i></span> <span class="post-meta-item-text">阅读次数:</span><span class="leancloud-visitors-count"></span></span></div></header><div class="post-body" itemprop="articleBody"><ul><li><a href="https://cn.vuejs.org/v2/guide/" target="_blank" rel="noopener">vue中文文档</a></li><li><a href="http://element.eleme.io/#/" target="_blank" rel="noopener">elementui文档</a></li><li><p><a href="https://github.com/ElemeFE/element" target="_blank" rel="noopener">elementui源码</a></p></li><li><p>复用<code>elementUI</code>的<code>el-upload</code>,并覆盖<code>http-request</code>方法,实现自定义的上传行为;</p></li><li>通过<code>computed</code>的属性带入初始链接;</li><li>通过<code>prop.sync</code>/<code>update:prop</code>,回传链接;</li><li><p>用html的<code>audio</code>标签自动获取音频时长;</p> <img src="/2018/09/16/vue-阿里云上传组件/vue-code.png" title="vue-code"></li></ul></div><div></div><footer class="post-footer"><div class="post-eof"></div></footer></div></article><article class="post post-type-normal" itemscope itemtype="http://schema.org/Article"><div class="post-block"><link itemprop="mainEntityOfPage" href="http://blog.zhangjian.ml/2018/09/16/vim高级功能/"><span hidden itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="name" content="jian zhang"><meta itemprop="description" content=""><meta itemprop="image" content="/images/avatar.gif"></span><span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="jian"></span><header class="post-header"><h2 class="post-title" itemprop="name headline"> <a class="post-title-link" href="/2018/09/16/vim高级功能/" itemprop="url">vim高级功能</a></h2><div class="post-meta"><span class="post-time"><span class="post-meta-item-icon"><i class="fa fa-calendar-o"></i></span> <span class="post-meta-item-text">发表于</span> <time title="创建于" itemprop="dateCreated datePublished" datetime="2018-09-16T16:34:53+08:00">2018-09-16</time></span> <span class="post-category"><span class="post-meta-divider">|</span><span class="post-meta-item-icon"><i class="fa fa-folder-o"></i></span> <span class="post-meta-item-text">分类于</span> <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/工具/" itemprop="url" rel="index"><span itemprop="name">工具</span></a></span> , <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/工具/文本编辑/" itemprop="url" rel="index"><span itemprop="name">文本编辑</span></a></span></span> <span id="/2018/09/16/vim高级功能/" class="leancloud_visitors" data-flag-title="vim高级功能"><span class="post-meta-divider">|</span><span class="post-meta-item-icon"><i class="fa fa-eye"></i></span> <span class="post-meta-item-text">阅读次数:</span><span class="leancloud-visitors-count"></span></span></div></header><div class="post-body" itemprop="articleBody"><h1 id="多文件编辑"><a href="#多文件编辑" class="headerlink" title="多文件编辑"></a>多文件编辑</h1><blockquote><p>vim 1.txt 2.txt</p></blockquote><ul><li>在vim命令后面跟<code>多个文件名</code>,即可同时编辑多个文件</li><li><code>命令模式</code>下,<code>:n</code>,切换到下一个文件</li><li><code>命令模式</code>下,<code>:N</code>,编辑上一个文件</li><li><code>:n!</code>/<code>:N</code>,丢弃未保存的内容,强制切换</li><li><code>命令模式</code>下,<code>:e 3.txt</code>,编辑新文件“3.txt”</li><li><code>命令模式</code>下,<code>:e#</code>,回到上一次编辑的文件</li><li><code>命令模式</code>下,<code>:ls</code>,列出同时编辑的多个文件项目列表</li><li><code>命令模式</code>下,<code>:b 2.txt</code>(文件名)/<code>:b 2</code>(编辑列表中的文件项目编号),可直接切换到指定的文件</li><li><code>命令模式</code>下,<code>:bd 2.txt</code>(文件名)/<code>:bd 2</code>(编辑列表中的文件项目编号),将文件项目从编辑列表中删除</li><li><code>命令模式</code>下,<code>:e! 4.txt</code>,放弃未保存的内容,强制打开文件</li><li><code>命令模式</code>下,<code>:f</code>,显示正在编辑的文件名</li><li><code>命令模式</code>下,<code>:f new.txt</code>,重命名当前编辑的文件名为“new.txt”</li></ul><h1 id="可视模式-选择模式"><a href="#可视模式-选择模式" class="headerlink" title="可视模式/选择模式"></a>可视模式/选择模式</h1><ul><li><code>普通模式</code>下,<code>9G</code>(大写),跳转到第9行</li><li><code>普通模式</code>下,<code>v</code>(小写),进入<code>字符选择模式</code>,然后利用光标移动键移动光标,光标走过的字符被选中,再次<code>v</code>(小写)取消选择</li><li><code>普通模式</code>下,<code>V</code>(大写),进入<code>行选择模式</code>,可以上下移动光标选择更多行,再次<code>V</code>(大写)取消选择</li><li><code>普通模式</code>下,<code>ctrl+v</code>(小写),进入<code>区域选择模式</code>,再次<code>ctrl+v</code>(小写)取消选择</li><li>在<code>选择模式</code>(字符/行/区域)下,<code>d</code>删除选取内容,<code>y</code>复制选取内容,<code>></code>选中内容缩进</li></ul><h1 id="窗口命令-ctrl-w"><a href="#窗口命令-ctrl-w" class="headerlink" title="窗口命令(ctrl+w)"></a>窗口命令(ctrl+w)</h1><p><code>命令模式</code>下,<code>:sp 1.txt</code>,横向打开视窗编辑1.txt文件</p><p><code>命令模式</code>下,<code>:vsp 1.txt</code>,纵向打开视窗编辑1.txt文件</p><p><code>普通模式</code>下,<code>ctrl+w <以下命令></code>:</p><ul><li><code>s</code>,水平分割窗口</li><li><code>v</code>,垂直分割窗口</li><li><code>q</code>,结束分割出来的新窗口,有未保存的内容则需要,<code>q!</code></li><li><code>j</code>、<code>k</code>、<code>h</code>、<code>l</code>,移动到上下左右窗口</li><li>大写jkhl,将窗口移动到上下左右</li><li><code>-</code>、<code>+</code>,减小/增加视窗的的高度</li></ul><h1 id="外部命令"><a href="#外部命令" class="headerlink" title="外部命令"></a>外部命令</h1><p><code>命令模式</code>下,<code>!</code>可执行外部shell命令,如<code>:!ls</code>显示当前目录的内容</p><h1 id="多行编辑"><a href="#多行编辑" class="headerlink" title="多行编辑"></a>多行编辑</h1><p><code>ctrl +v</code> 选取多行,<code>shift+i</code>进行插入,然后两次<code>esc</code> 退出</p><h1 id="复制"><a href="#复制" class="headerlink" title="复制"></a>复制</h1><ul><li>单行复制<br>在命令模式下,将光标移动到将要复制的行处,按“yy”进行复制;</li><li>多行复制<br>在命令模式下,将光标移动到将要复制的首行处,按“nyy”复制n行;其中n为1、2,</li></ul><h1 id="粘贴"><a href="#粘贴" class="headerlink" title="粘贴"></a>粘贴</h1><p>在命令模式下,将光标移动到将要粘贴的行处,按“p”进行粘贴</p><h1 id="删除"><a href="#删除" class="headerlink" title="删除"></a>删除</h1><p><code>x</code> : 删除光标后一个字符<br><code>dd</code> : 删除光标所在行,n dd 删除指定的行数</p><h1 id="撤销"><a href="#撤销" class="headerlink" title="撤销"></a>撤销</h1><p><code>u</code> : 一步一步撤销<br><code>Ctr-r</code> : 反撤销</p></div><div></div><footer class="post-footer"><div class="post-eof"></div></footer></div></article><article class="post post-type-normal" itemscope itemtype="http://schema.org/Article"><div class="post-block"><link itemprop="mainEntityOfPage" href="http://blog.zhangjian.ml/2018/09/16/CC助手-超越剪贴板/"><span hidden itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="name" content="jian zhang"><meta itemprop="description" content=""><meta itemprop="image" content="/images/avatar.gif"></span><span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="jian"></span><header class="post-header"><h2 class="post-title" itemprop="name headline"> <a class="post-title-link" href="/2018/09/16/CC助手-超越剪贴板/" itemprop="url">CC助手-超越剪贴板</a></h2><div class="post-meta"><span class="post-time"><span class="post-meta-item-icon"><i class="fa fa-calendar-o"></i></span> <span class="post-meta-item-text">发表于</span> <time title="创建于" itemprop="dateCreated datePublished" datetime="2018-09-16T16:00:26+08:00">2018-09-16</time></span> <span class="post-category"><span class="post-meta-divider">|</span><span class="post-meta-item-icon"><i class="fa fa-folder-o"></i></span> <span class="post-meta-item-text">分类于</span> <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/工具/" itemprop="url" rel="index"><span itemprop="name">工具</span></a></span> , <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/工具/效率/" itemprop="url" rel="index"><span itemprop="name">效率</span></a></span></span> <span id="/2018/09/16/CC助手-超越剪贴板/" class="leancloud_visitors" data-flag-title="CC助手-超越剪贴板"><span class="post-meta-divider">|</span><span class="post-meta-item-icon"><i class="fa fa-eye"></i></span> <span class="post-meta-item-text">阅读次数:</span><span class="leancloud-visitors-count"></span></span></div></header><div class="post-body" itemprop="articleBody"><p><img src="https://upload-images.jianshu.io/upload_images/659256-3389618a5437a0ad.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p><h1 id="随时收藏-两次-CTRL-C"><a href="#随时收藏-两次-CTRL-C" class="headerlink" title="随时收藏-两次^CTRL+C"></a>随时收藏-两次<code>^CTRL+C</code></h1><p><img src="https://upload-images.jianshu.io/upload_images/659256-548e1d28ec99c835.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p><p><strong>对比</strong>:<br>| 没有cc助手 | cc助手 |<br>| ———————————————————— | ——————– |<br>| 1.选中文字,<code>^Ctrl-C</code>进行复制;<br>2.找到笔记程序并打开;<br>3.新建一篇笔记;<br>4.<code>^Ctrl-V</code> 粘贴内容;<br>5.切换回网页继续阅读。OK,刚才看到哪了? | <code>^Ctrl-C</code>再<code>^Ctrl-C</code> |</p><hr><h1 id="Anything-Anywhere"><a href="#Anything-Anywhere" class="headerlink" title="Anything, Anywhere"></a>Anything, Anywhere</h1> <label style="color:green"><em>只要能复制的地方,就可以收藏</em></label><h1 id="插件系统"><a href="#插件系统" class="headerlink" title="插件系统"></a>插件系统</h1><ul><li>OCR</li></ul><p><img src="https://upload-images.jianshu.io/upload_images/659256-50535abf6e8887be.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="文字识别"></p><ul><li>单词翻译</li></ul><p><img src="https://upload-images.jianshu.io/upload_images/659256-cedbd34b87bf9933.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="单词翻译"></p><ul><li>开放的插件系统<blockquote><p>支持 JavaScript 编写插件,海量的开源资源任你发挥<br>(插件体系尚在完善中,正式发布时会开放)</p></blockquote></li></ul><p><img src="https://upload-images.jianshu.io/upload_images/659256-6e6f2bc0d58dd510.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="插件"></p><h1 id="查看"><a href="#查看" class="headerlink" title="查看"></a>查看</h1><ul><li><code>^Ctrl-Alt-C</code>快捷键,激活列表页</li><li><code>Tab</code> 以及左右箭头,切换 tab</li><li>上下箭头切换焦点</li><li>任意字符输入进入搜索状态, / 筛选不同类型(文字、图片),# 筛选分类</li><li>Esc取消搜索或者隐藏界面</li></ul><p><img src="https://upload-images.jianshu.io/upload_images/659256-08f8beff31a8e91d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="列表页"></p><hr><p>CC助手下载地址:<a href="https://ccyixia.com" target="_blank" rel="noopener">https://ccyixia.com</a></p></div><div></div><footer class="post-footer"><div class="post-eof"></div></footer></div></article><article class="post post-type-normal" itemscope itemtype="http://schema.org/Article"><div class="post-block"><link itemprop="mainEntityOfPage" href="http://blog.zhangjian.ml/2018/09/08/BandwagonHost-番-羽/"><span hidden itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="name" content="jian zhang"><meta itemprop="description" content=""><meta itemprop="image" content="/images/avatar.gif"></span><span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="jian"></span><header class="post-header"><h2 class="post-title" itemprop="name headline"> <a class="post-title-link" href="/2018/09/08/BandwagonHost-番-羽/" itemprop="url">BandwagonHost-番#羽</a></h2><div class="post-meta"><span class="post-time"><span class="post-meta-item-icon"><i class="fa fa-calendar-o"></i></span> <span class="post-meta-item-text">发表于</span> <time title="创建于" itemprop="dateCreated datePublished" datetime="2018-09-08T12:45:40+08:00">2018-09-08</time></span> <span class="post-category"><span class="post-meta-divider">|</span><span class="post-meta-item-icon"><i class="fa fa-folder-o"></i></span> <span class="post-meta-item-text">分类于</span> <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/工具/" itemprop="url" rel="index"><span itemprop="name">工具</span></a></span> , <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/工具/网络/" itemprop="url" rel="index"><span itemprop="name">网络</span></a></span></span> <span id="/2018/09/08/BandwagonHost-番-羽/" class="leancloud_visitors" data-flag-title="BandwagonHost-番#羽"><span class="post-meta-divider">|</span><span class="post-meta-item-icon"><i class="fa fa-eye"></i></span> <span class="post-meta-item-text">阅读次数:</span><span class="leancloud-visitors-count"></span></span></div></header><div class="post-body" itemprop="articleBody"><h1 id="国外服务器"><a href="#国外服务器" class="headerlink" title="国外服务器"></a>国外服务器</h1><h2 id="注册账号"><a href="#注册账号" class="headerlink" title="注册账号"></a>注册账号</h2><p><a href="https://www.bwh1.net/clientarea.php" target="_blank" rel="noopener">BandwagonHost官网</a></p> <img src="/2018/09/08/BandwagonHost-番-羽/注册账号.png" title="注册账号"><h2 id="购买服务器"><a href="#购买服务器" class="headerlink" title="购买服务器"></a>购买服务器</h2><ul><li><p>点击<code>VPS Hosting</code>, 选择<code>$19.99</code> 下面的<code>order kvm</code> ;</p> <img src="/2018/09/08/BandwagonHost-番-羽/购买服务器.jpg" title="购买服务器"></li><li><p>然后点击 <code>Add Cart</code>, 也就是 <code>加入购物车</code> 的意思;</p></li><li><p>然后点击<code>Checkout</code>, 也就是<code>结算</code> ;</p></li><li><p>选择 <code>支付宝</code> 支付,完成订单;</p> <img src="/2018/09/08/BandwagonHost-番-羽/支付.png" title="支付"></li></ul><ul><li>接下来的页面,点解<code>pay now</code> ,进行支付宝付款,就购买完成。</li></ul><h2 id="配置服务器"><a href="#配置服务器" class="headerlink" title="配置服务器"></a>配置服务器</h2><ul><li><p>登录网站,<code>client area</code> -> <code>my services</code> -> <code>control panel</code> ,进入kvm 管理界面 ;</p> <img src="/2018/09/08/BandwagonHost-番-羽/配置服务器.png" title="配置服务器"></li><li><p>默认安装的是centos,个人更习惯Ubuntu,先在 <code>main controls</code> 里面<code>stop</code> 掉机器,然后 <code>install new os</code> 可以选择安装Ubuntu系统;</p></li><li><p>然后,会收到邮件,告知,root密码,ssh端口;</p> <img src="/2018/09/08/BandwagonHost-番-羽/邮件通知.png" title="邮件通知"></li></ul><h1 id="shadow-socks配置"><a href="#shadow-socks配置" class="headerlink" title="shadow-socks配置"></a>shadow-socks配置</h1><h2 id="服务端"><a href="#服务端" class="headerlink" title="服务端"></a>服务端</h2><ul><li>安装</li></ul><figure class="highlight shell"><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">apt-get install python-pip</span><br><span class="line">pip install shadowsocks</span><br></pre></td></tr></table></figure><ul><li>使用</li></ul><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ssserver -p 443 -k password -m rc4-md5</span><br></pre></td></tr></table></figure><p>如果要后台运行:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo ssserver -p 443 -k password -m rc4-md5 --user nobody -d start</span><br></pre></td></tr></table></figure><p>如果要停止:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo ssserver -d stop</span><br></pre></td></tr></table></figure><p> 如果要检查日志:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo less /var/log/shadowsocks.log</span><br></pre></td></tr></table></figure><ul><li>报错</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">AttributeError: /usr/local/ssl/lib/libcrypto.so.1.1: undefined symbol: EVP_CIPHER_CTX_cleanup</span><br></pre></td></tr></table></figure><p>vim打开文件openssl.py</p><blockquote><p>路径不同根据报错路径而定</p></blockquote><p> 修改libcrypto.EVP_CIPHER_CTX_cleanup.argtypes</p><p><code>:%s/cleanup/reset/</code></p><p><code>:x</code></p><blockquote><p>以上两条为VIM命令, 替换文中<strong>libcrypto.EVP_CIPHER_CTX_cleanup.argtypes</strong> 为<strong>libcrypto.EVP_CIPHER_CTX_reset.argtypes</strong> 共两处,并保存</p></blockquote><p>重新运行</p><h2 id="客户端"><a href="#客户端" class="headerlink" title="客户端"></a>客户端</h2><p>github 上下载window客户端</p> <img src="/2018/09/08/BandwagonHost-番-羽/客户端1.png" title="客户端1"> <img src="/2018/09/08/BandwagonHost-番-羽/客户端配置.png" title="客户端配置"><p>ubuntu客户端:</p><figure class="highlight shell"><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">sudo add-apt-repository ppa:hzwhuang/ss-qt5</span><br><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install shadowsocks-qt5</span><br></pre></td></tr></table></figure><p>debiancn源<br></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><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">echo "deb https://repo.debiancn.org/ testing main" | sudo tee /etc/apt/sources.list.d/debiancn.list;</span><br><span class="line">wget https://repo.debiancn.org/pool/main/d/debiancn-keyring/debiancn-keyring_0~20161212_all.deb -O /tmp/debiancn-keyring.deb;</span><br><span class="line">sudo apt install /tmp/debiancn-keyring.deb;</span><br><span class="line">sudo apt update;</span><br><span class="line">rm /tmp/debiancn-keyring.deb;</span><br></pre></td></tr></table></figure><p></p><p><a href="https://github.com/debiancn/repo" target="_blank" rel="noopener">https://github.com/debiancn/repo</a></p></div><div></div><footer class="post-footer"><div class="post-eof"></div></footer></div></article></section></div></div><div class="sidebar-toggle"><div class="sidebar-toggle-line-wrap"><span class="sidebar-toggle-line sidebar-toggle-line-first"></span><span class="sidebar-toggle-line sidebar-toggle-line-middle"></span><span class="sidebar-toggle-line sidebar-toggle-line-last"></span></div></div><aside id="sidebar" class="sidebar"><div class="sidebar-inner"><section class="site-overview-wrap sidebar-panel sidebar-panel-active"><div class="site-overview"><div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person"><p class="site-author-name" itemprop="name">jian zhang</p><p class="site-description motion-element" itemprop="description"></p></div><nav class="site-state motion-element"><div class="site-state-item site-state-posts"> <a href="/archives/"><span class="site-state-item-count">6</span> <span class="site-state-item-name">日志</span></a></div><div class="site-state-item site-state-categories"> <a href="/categories/index.html"><span class="site-state-item-count">7</span> <span class="site-state-item-name">分类</span></a></div><div class="site-state-item site-state-tags"> <a href="/tags/index.html"><span class="site-state-item-count">9</span> <span class="site-state-item-name">标签</span></a></div></nav><div class="feed-link motion-element"><a href="/atom.xml" rel="alternate"><i class="fa fa-rss"></i> RSS</a></div></div></section></div></aside></div></main><footer id="footer" class="footer"><div class="footer-inner"><div class="copyright">© <span itemprop="copyrightYear">2018</span><span class="with-love"><i class="fa fa-user"></i></span> <span class="author" itemprop="copyrightHolder">jian zhang</span></div></div></footer><div class="back-to-top"><i class="fa fa-arrow-up"></i></div></div><script type="text/javascript">"[object Function]"!==Object.prototype.toString.call(window.Promise)&&(window.Promise=null)</script><script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script><script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script><script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script><script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script><script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script><script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script><script type="text/javascript" src="/js/src/utils.js?v=5.1.4"></script><script type="text/javascript" src="/js/src/motion.js?v=5.1.4"></script><script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.4"></script><script type="text/javascript">
// Popup Window;
var isfetched = false;
var isXml = true;
// Search DB path;
var search_path = "search.xml";
if (search_path.length === 0) {
search_path = "search.xml";
} else if (/json$/i.test(search_path)) {
isXml = false;
}
var path = "/" + search_path;
// monitor main search box;
var onPopupClose = function (e) {
$('.popup').hide();
$('#local-search-input').val('');
$('.search-result-list').remove();
$('#no-result').remove();
$(".local-search-pop-overlay").remove();
$('body').css('overflow', '');
}
function proceedsearch() {
$("body")
.append('<div class="search-popup-overlay local-search-pop-overlay"></div>')
.css('overflow', 'hidden');
$('.search-popup-overlay').click(onPopupClose);
$('.popup').toggle();
var $localSearchInput = $('#local-search-input');
$localSearchInput.attr("autocapitalize", "none");
$localSearchInput.attr("autocorrect", "off");
$localSearchInput.focus();
}
// search function;
var searchFunc = function(path, search_id, content_id) {
'use strict';
// start loading animation
$("body")
.append('<div class="search-popup-overlay local-search-pop-overlay">' +
'<div id="search-loading-icon">' +
'<i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>' +
'</div>' +
'</div>')
.css('overflow', 'hidden');
$("#search-loading-icon").css('margin', '20% auto 0 auto').css('text-align', 'center');
$.ajax({
url: path,
dataType: isXml ? "xml" : "json",
async: true,
success: function(res) {
// get the contents from search data
isfetched = true;
$('.popup').detach().appendTo('.header-inner');
var datas = isXml ? $("entry", res).map(function() {
return {
title: $("title", this).text(),
content: $("content",this).text(),
url: $("url" , this).text()
};
}).get() : res;
var input = document.getElementById(search_id);
var resultContent = document.getElementById(content_id);
var inputEventFunction = function() {
var searchText = input.value.trim().toLowerCase();
var keywords = searchText.split(/[\s\-]+/);
if (keywords.length > 1) {
keywords.push(searchText);
}
var resultItems = [];
if (searchText.length > 0) {
// perform local searching
datas.forEach(function(data) {
var isMatch = false;
var hitCount = 0;
var searchTextCount = 0;
var title = data.title.trim();
var titleInLowerCase = title.toLowerCase();
var content = data.content.trim().replace(/<[^>]+>/g,"");
var contentInLowerCase = content.toLowerCase();
var articleUrl = decodeURIComponent(data.url);
var indexOfTitle = [];
var indexOfContent = [];
// only match articles with not empty titles
if(title != '') {
keywords.forEach(function(keyword) {
function getIndexByWord(word, text, caseSensitive) {
var wordLen = word.length;
if (wordLen === 0) {
return [];
}
var startPosition = 0, position = [], index = [];
if (!caseSensitive) {
text = text.toLowerCase();
word = word.toLowerCase();
}
while ((position = text.indexOf(word, startPosition)) > -1) {
index.push({position: position, word: word});
startPosition = position + wordLen;
}
return index;
}
indexOfTitle = indexOfTitle.concat(getIndexByWord(keyword, titleInLowerCase, false));
indexOfContent = indexOfContent.concat(getIndexByWord(keyword, contentInLowerCase, false));
});
if (indexOfTitle.length > 0 || indexOfContent.length > 0) {
isMatch = true;
hitCount = indexOfTitle.length + indexOfContent.length;
}
}
// show search results
if (isMatch) {
// sort index by position of keyword
[indexOfTitle, indexOfContent].forEach(function (index) {
index.sort(function (itemLeft, itemRight) {
if (itemRight.position !== itemLeft.position) {
return itemRight.position - itemLeft.position;
} else {
return itemLeft.word.length - itemRight.word.length;
}
});
});
// merge hits into slices
function mergeIntoSlice(text, start, end, index) {
var item = index[index.length - 1];
var position = item.position;
var word = item.word;
var hits = [];
var searchTextCountInSlice = 0;
while (position + word.length <= end && index.length != 0) {
if (word === searchText) {
searchTextCountInSlice++;
}
hits.push({position: position, length: word.length});
var wordEnd = position + word.length;
// move to next position of hit
index.pop();
while (index.length != 0) {
item = index[index.length - 1];
position = item.position;
word = item.word;
if (wordEnd > position) {
index.pop();
} else {
break;
}
}
}
searchTextCount += searchTextCountInSlice;
return {
hits: hits,
start: start,
end: end,
searchTextCount: searchTextCountInSlice
};
}
var slicesOfTitle = [];
if (indexOfTitle.length != 0) {
slicesOfTitle.push(mergeIntoSlice(title, 0, title.length, indexOfTitle));
}
var slicesOfContent = [];
while (indexOfContent.length != 0) {
var item = indexOfContent[indexOfContent.length - 1];
var position = item.position;
var word = item.word;
// cut out 100 characters
var start = position - 20;
var end = position + 80;
if(start < 0){
start = 0;
}
if (end < position + word.length) {
end = position + word.length;
}
if(end > content.length){
end = content.length;
}
slicesOfContent.push(mergeIntoSlice(content, start, end, indexOfContent));
}
// sort slices in content by search text's count and hits' count
slicesOfContent.sort(function (sliceLeft, sliceRight) {
if (sliceLeft.searchTextCount !== sliceRight.searchTextCount) {
return sliceRight.searchTextCount - sliceLeft.searchTextCount;
} else if (sliceLeft.hits.length !== sliceRight.hits.length) {
return sliceRight.hits.length - sliceLeft.hits.length;
} else {
return sliceLeft.start - sliceRight.start;
}
});
// select top N slices in content
var upperBound = parseInt('1');
if (upperBound >= 0) {
slicesOfContent = slicesOfContent.slice(0, upperBound);
}
// highlight title and content
function highlightKeyword(text, slice) {
var result = '';
var prevEnd = slice.start;
slice.hits.forEach(function (hit) {
result += text.substring(prevEnd, hit.position);
var end = hit.position + hit.length;
result += '<b class="search-keyword">' + text.substring(hit.position, end) + '</b>';
prevEnd = end;
});
result += text.substring(prevEnd, slice.end);
return result;
}
var resultItem = '';
if (slicesOfTitle.length != 0) {
resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + highlightKeyword(title, slicesOfTitle[0]) + "</a>";
} else {
resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + title + "</a>";
}
slicesOfContent.forEach(function (slice) {
resultItem += "<a href='" + articleUrl + "'>" +
"<p class=\"search-result\">" + highlightKeyword(content, slice) +
"...</p>" + "</a>";
});
resultItem += "</li>";
resultItems.push({
item: resultItem,
searchTextCount: searchTextCount,
hitCount: hitCount,
id: resultItems.length
});
}
})
};
if (keywords.length === 1 && keywords[0] === "") {
resultContent.innerHTML = '<div id="no-result"><i class="fa fa-search fa-5x" /></div>'
} else if (resultItems.length === 0) {
resultContent.innerHTML = '<div id="no-result"><i class="fa fa-frown-o fa-5x" /></div>'
} else {
resultItems.sort(function (resultLeft, resultRight) {
if (resultLeft.searchTextCount !== resultRight.searchTextCount) {
return resultRight.searchTextCount - resultLeft.searchTextCount;
} else if (resultLeft.hitCount !== resultRight.hitCount) {
return resultRight.hitCount - resultLeft.hitCount;
} else {
return resultRight.id - resultLeft.id;
}
});
var searchResultList = '<ul class=\"search-result-list\">';
resultItems.forEach(function (result) {
searchResultList += result.item;
})
searchResultList += "</ul>";
resultContent.innerHTML = searchResultList;
}
}
if ('auto' === 'auto') {
input.addEventListener('input', inputEventFunction);
} else {
$('.search-icon').click(inputEventFunction);
input.addEventListener('keypress', function (event) {
if (event.keyCode === 13) {
inputEventFunction();
}
});
}
// remove loading animation
$(".local-search-pop-overlay").remove();
$('body').css('overflow', '');
proceedsearch();
}
});
}
// handle and trigger popup window;
$('.popup-trigger').click(function(e) {
e.stopPropagation();
if (isfetched === false) {
searchFunc(path, 'local-search-input', 'local-search-result');
} else {
proceedsearch();
};
});
$('.popup-btn-close').click(onPopupClose);
$('.popup').click(function(e){
e.stopPropagation();
});
$(document).on('keyup', function (event) {
var shouldDismissSearchPopup = event.which === 27 &&
$('.search-popup').is(':visible');
if (shouldDismissSearchPopup) {
onPopupClose();
}
});
</script><script src="https://cdn1.lncld.net/static/js/av-core-mini-0.6.4.js"></script><script>AV.initialize("nCiu8dstmlbEp1XdCxs4OXqE-gzGzoHsz","iRjO3TkSyUF4fQ5SGBj6bzVT")</script><script>function showTime(e){var t=new AV.Query(e),c=[],u=$(".leancloud_visitors");u.each(function(){c.push($(this).attr("id").trim())}),t.containedIn("url",c),t.find().done(function(e){var t=".leancloud-visitors-count";if(0!==e.length){for(var n=0;n<e.length;n++){var o=e[n],i=o.get("url"),s=o.get("time"),r=document.getElementById(i);$(r).find(t).text(s)}for(n=0;n<c.length;n++){i=c[n],r=document.getElementById(i);var l=$(r).find(t);""==l.text()&&l.text(0)}}else u.find(t).text(0)}).fail(function(e,t){console.log("Error: "+t.code+" "+t.message)})}function addCount(i){var e=$(".leancloud_visitors"),s=e.attr("id").trim(),r=e.attr("data-flag-title").trim(),t=new AV.Query(i);t.equalTo("url",s),t.find({success:function(e){if(0<e.length){var t=e[0];t.fetchWhenSave(!0),t.increment("time"),t.save(null,{success:function(e){$(document.getElementById(s)).find(".leancloud-visitors-count").text(e.get("time"))},error:function(e,t){console.log("Failed to save Visitor num, with error message: "+t.message)}})}else{var n=new i,o=new AV.ACL;o.setPublicReadAccess(!0),o.setPublicWriteAccess(!0),n.setACL(o),n.set("title",r),n.set("url",s),n.set("time",1),n.save(null,{success:function(e){$(document.getElementById(s)).find(".leancloud-visitors-count").text(e.get("time"))},error:function(e,t){console.log("Failed to create")}})}},error:function(e){console.log("Error:"+e.code+" "+e.message)}})}$(function(){var e=AV.Object.extend("Counter");1==$(".leancloud_visitors").length?addCount(e):1<$(".post-title-link").length&&showTime(e)})</script></body><script type="text/javascript" src="/js/src/love.js"></script><script type="text/javascript" src="/js/src/particle.js"></script></html>