-
Notifications
You must be signed in to change notification settings - Fork 1
/
20181113.html
481 lines (425 loc) · 23.8 KB
/
20181113.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
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
<html >
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/vuetify/2.6.12/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/vuetify/2.0.4/vuetify.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/[email protected]/build/styles/rainbow.min.css">
<script src="https://cdn.jsdelivr.net/gh/highlightjs/[email protected]/build/highlight.min.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/MaterialDesign-Webfont/6.9.96/css/materialdesignicons.min.css" rel="stylesheet">
<link href="/css/three-cards-style.css" rel="stylesheet">
<meta name="robots" contect= "all">
<meta name="description" contect="一个热爱学习的 Java 程序员,喜欢 Vue,喜欢深度学习">
<!-- 主页使用 category作为 keywords,文章页使用文章的 keywords -->
<meta name="keywords" contect="java,Dubbo,RPC,ZooKeeper,Dubbo 教程">
<link rel="icon shortcut" type="image/ico" href=/images/favicon.jpg>
<title>
U2647's blog
</title>
<!-- 百度统计 -->
<!-- Google Search Console -->
<meta name="generator" content="Hexo 6.3.0"></head>
<body>
<div id="app">
<v-app>
<!-- 页头 -->
<v-card tile elevation="24" style="width: 80%; margin: 0 auto; text-align:center; background:rgba(0,0,0,0); margin-bottom: 3%;" gradient="to bottom, rgba(0,0,0,.1), rgba(0,0,0,.5)">
<v-img height="240" src="" class="white--text align-end" >
<v-card-title style="text-align: left; margin-left: 0.3%;">U2647's blog</v-card-title>
<v-card-text style="text-align: left;margin-left: 0.3%;" class="white--text">
一个热爱学习的 Java 程序员,喜欢 Vue,喜欢深度学习
</v-card-text>
<v-divider style="margin-left: 1.3%; margin-right: 1.3%;" class="success lighten-1"></v-divider>
<v-card-text style="text-align: left;" class="white--text">
<v-btn text class="white--text" style="text-transform:capitalize;" href="/categories/Dubbo">Dubbo</v-btn>
<v-btn text class="white--text" style="text-transform:capitalize;" href="/categories/Flutter">Flutter</v-btn>
<v-btn text class="white--text" style="text-transform:capitalize;" href="/categories/SpringBoot">SpringBoot</v-btn>
<v-btn text class="white--text" style="text-transform:capitalize;" href="/categories/Debug">Debug</v-btn>
<v-btn text class="white--text" style="text-transform:capitalize;" href="/categories/Notes">Notes</v-btn>
<v-btn text class="white--text" style="text-transform:capitalize;" href="/categories/Java">Java</v-btn>
<v-btn text class="white--text" style="text-transform:capitalize;" href="/categories/LeetCode">LeetCode</v-btn>
<v-btn text class="white--text" style="text-transform:capitalize;" href="/categories/Python">Python</v-btn>
<v-btn text class="white--text" style="text-transform:capitalize;" href="/categories/Redis">Redis</v-btn>
<v-btn text class="white--text" style="text-transform:capitalize;" href="/categories/Android">Android</v-btn>
<v-btn text class="white--text" style="text-transform:capitalize;" href="/categories/DesignPattern">DesignPattern</v-btn>
</v-card-text>
</v-img>
<v-divider style="margin-left: 1.3%; margin-right: 1.3%;" class="success lighten-1"></v-divider>
<v-card-actions >
<v-btn text x-large class="white--text" style="margin-left: 0.5%;margin-top:0.5%;margin-bottom: 0.5%;" href=/>
<v-icon right>
mdi-home-outline
</v-icon>
首页
</v-btn>
<v-btn text x-large class="white--text" style="margin-left: 0.5%;margin-top:0.5%;margin-bottom: 0.5%;" href=/tags>
<v-icon right>
mdi-cloud-outline
</v-icon>
标签云
</v-btn>
<v-btn text x-large class="white--text" style="margin-left: 0.5%;margin-top:0.5%;margin-bottom: 0.5%;" href=/timeline>
<v-icon right>
mdi-timeline-text-outline
</v-icon>
时间轴
</v-btn>
<v-spacer></v-spacer>
<v-btn text x-large class="white--text" style="margin-left: 0.5%;margin-top:0.5%;margin-bottom: 0.5%;">
<v-icon right>
mdi-draw-pen
</v-icon>
文章总数
</v-btn >
<v-btn icon style="margin-right: 0.5%;margin-top:0.5%;margin-bottom: 0.5%;">
<v-avatar color="success" size="35" >
<span class="white--text"> 62 </span>
</v-avatar>
</v-btn>
</v-card-actions>
</v-card>
<div style="width: 55%; margin: 0 auto; text-align:center;">
<v-card tile max-width="100%" elevation="24" style="margin-bottom: 3%;" >
<v-img height="240" class="white--text align-end" src=/random/material-30.jpg gradient="to bottom, rgba(0,0,0,.1), rgba(0,0,0,.5)">
<v-card-title style="text-align: left;margin-left: 0.6%;">
<span>Dubbo 学习笔记(一) Hello,Dubbo</span>
</v-card-title>
<v-card-text style="text-align: left;margin-left: 0.8%;">
Dubbo 学习笔记(一) Hello,Dubbo
</v-card-text>
<v-divider class="success lighten-1" style="margin-left:2%; margin-right: 2%;"></v-divider>
<v-card-actions style="text-align: left;" class="white--text" style="margin-left:2%; margin-right: 2%;">
<v-btn text class="white--text" style="text-transform:capitalize;margin-left:0.5%;">Dubbo</v-btn>
<v-btn text class="white--text" style="text-transform:capitalize;margin-left:0.5%;">RPC</v-btn>
<v-btn text class="white--text" style="text-transform:capitalize;margin-left:0.5%;">ZooKeeper</v-btn>
<v-btn text class="white--text" style="text-transform:capitalize;margin-left:0.5%;">Dubbo 教程</v-btn>
<v-spacer></v-spacer>
<v-btn text class="white--text" >
<v-icon right>
mdi-cursor-default-click-outline
</v-icon>
点击量
</v-btn >
<v-btn icon >
<v-avatar color="success" size="35" >
<span id = "busuanzi_value_page_pv" class="white--text"> 62 </span>
</v-avatar>
</v-btn>
</v-card-actions>
</v-img>
<v-card-text>
<div id = "post_container" class="text-justify" style="padding-left: 2%;padding-right: 2%;padding-bottom: 2%">
<ul>
<li><a target="_blank" rel="noopener" href="https://github.com/zdRan/learning">Dubbo 学习笔记 源码地址</a></li>
<li><a href="https://zdran.com/20181102.html">Dubbo 学习笔记(零) 自己实现一个 RPC 框架</a></li>
<li><a href="https://zdran.com/20181113.html">Dubbo 学习笔记(一) Hello,Dubbo</a></li>
<li><a href="https://zdran.com/20181216.html">Dubbo 学习笔记(二) Spring Boot 整合 Dubbo</a></li>
<li><a href="https://zdran.com/20190212.html">Dubbo 学习笔记(三) Spring Boot 整合 Dubbo(官方版)</a></li>
</ul>
<hr>
<h2 id="0-Dubbo-简介"><a href="#0-Dubbo-简介" class="headerlink" title="0. Dubbo 简介"></a>0. Dubbo 简介</h2><p>Dubbo是一个开源的RPC框架。详情见 <a target="_blank" rel="noopener" href="http://dubbo.apache.org/zh-cn/">Dubbo官网</a></p>
<h2 id="1-安装注册中心"><a href="#1-安装注册中心" class="headerlink" title="1. 安装注册中心"></a>1. 安装注册中心</h2><p><a target="_blank" rel="noopener" href="https://zookeeper.apache.org/">ZooKeeper</a> 是常用的注册中心之一。</p>
<p><a target="_blank" rel="noopener" href="http://mirror.bit.edu.cn/apache/zookeeper/">下载地址</a></p>
<p>解压:</p>
<pre><code>sudo tar -zxvf zookeeper-3.4.10.tar.gz
</code></pre>
<p>配置 ZooKeeper,将 <code>zookeeper-3.4.10/conf</code>下的 <code>zoo_sample.cfg </code> 复制一份,重命名为 <code>zoo.cfg</code></p>
<pre><code>cd zookeeper-3.4.10/conf
cp zoo_sample.cfg ./zoo.cfg
</code></pre>
<p>配置采用默认的就可以。</p>
<p>配置环境变量</p>
<pre><code># ZooKeeper Env
export ZOOKEEPER_HOME=/xxx/xxx/zookeeper-3.4.8
export PATH=$PATH:$ZOOKEEPER_HOME/bin
</code></pre>
<p>生效环境变量:</p>
<pre><code>source .bashrc
</code></pre>
<p>启动 ZooKeeper </p>
<pre><code>zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /root/soft/zookeeper-3.4.10/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
</code></pre>
<p>说明启动成功了。</p>
<h2 id="2-创建生产者(dubbomall-user)"><a href="#2-创建生产者(dubbomall-user)" class="headerlink" title="2. 创建生产者(dubbomall-user)"></a>2. 创建生产者(dubbomall-user)</h2><p>新建一个空白的 maven 项目。添加下面的依赖:</p>
<pre><code><?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>dubbomall</artifactId>
<groupId>com.zdran</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbomall-user</artifactId>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring.version>4.1.3.RELEASE</spring.version>
<dubbo.version>2.5.3</dubbo.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
<exclusions>
<exclusion>
<!-- 排除传递spring依赖 -->
<artifactId>spring</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- 导入zookeeper依赖 -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.3.3</version>
<exclusions>
<exclusion>
<artifactId>log4j</artifactId>
<groupId>log4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
</code></pre>
<p>创建一个 Service:</p>
<pre><code>public interface UserService {
/**
* 返回 hello 字符串
*
* @param name 姓名
* @return
*/
String sayHello(String name);
}
具体实现类:
@Service
public class UserServiceImpl implements UserService {
@Override
public String sayHello(String name) {
return "hello," + name;
}
}
</code></pre>
<p>在 <code>resources</code> 下创建一个 <code>dubbo-server.xml</code> dubbo的配置文件,内容如下:</p>
<pre><code><beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="dubbomall-user"/>
<!-- 这里使用的注册中心是zookeeper -->
<dubbo:registry address="zookeeper://127.0.0.1:2181" client="zkclient"/>
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20881"/>
<!-- 将该接口暴露到dubbo中 -->
<dubbo:service interface="com.zdran.dubbomall.user.service.UserService" ref="userServiceImpl"/>
<!-- 将具体的实现类加入到Spring容器中 -->
<bean id="userServiceImpl" class="com.zdran.dubbomall.user.service.impl.UserServiceImpl"/>
</beans>
</code></pre>
<p>创建一个启动类:</p>
<pre><code>public class ApplicationMain {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]
{"dubbo-server.xml"});
context.start();
System.in.read();
}
}
</code></pre>
<p><strong>注意:dubbo-server.xml 的路径是从 resources 下开始的</strong></p>
<p>启动这个 Main 方法。</p>
<h2 id="3-查看服务注册情况"><a href="#3-查看服务注册情况" class="headerlink" title="3. 查看服务注册情况"></a>3. 查看服务注册情况</h2><p>然后我们去 ZooKeeper 查看一下服务注册情况</p>
<p>连接 zookeeper </p>
<pre><code>zkCli.sh -server 127.0.0.1:2181
WATCHER::
WatchedEvent state:SyncConnected type:None path:null
[zk: 127.0.0.1:2181(CONNECTED) 0]
</code></pre>
<p>出现上面的情况说明连接成功了。</p>
<p>使用 <code>ls /</code>列出当前 zk上的所有 节点</p>
<pre><code>[zk: 127.0.0.1:2181(CONNECTED) 0] ls /
[dubbo, zookeeper]
</code></pre>
<p>我们看到有一个 dubbo 的节点。查看一下这个节点下面的服务</p>
<pre><code>[zk: 127.0.0.1:2181(CONNECTED) 1] ls /dubbo
[com.zdran.dubbomall.user.service.UserService]
</code></pre>
<p>这次我们看到了我们自己定义的 Service 的包路径,然后我们再看一下,这个节点下面的东西</p>
<pre><code>[zk: 127.0.0.1:2181(CONNECTED) 14]
ls /dubbo/com.zdran.dubbomall.user.service.UserService
[consumers, configurators, routers, providers]
</code></pre>
<p>重点看一下 consumers(消费者)、providers(生产者) ,这两个下面的节点分别对应该服务的消费者和生产者。</p>
<p>我们现在只有生产者,所以先看一下生产者下面的节点</p>
<pre><code>[zk: 127.0.0.1:2181(CONNECTED) 15] ls /dubbo/com.zdran.dubbomall.user.service.UserService/providers
[dubbo%3A%2F%2F192.168.56.1%3A20881%2Fcom.zdran.dubbomall.user.service.UserService
%3Fanyhost%3Dtrue%26application%3Ddubbomall-user%26dubbo%3D2.5.3%26interface
%3Dcom.zdran.dubbomall.user.service.UserService%26methods%3DsayHello%26pid
%3D5740%26side%3Dprovider%26timestamp%3D1542032564897]
</code></pre>
<p>现在不不需要关心这堆看似乱码的字符串,主要注意这里面的两个信息,一个是IP,如果不出意外的话,应该是你本地的IP地址,准确的说是,你启动Main方法的那台机器的IP,另一个是我们暴露的接口的包路径以及方法名。</p>
<p>如果你看过第一篇文章的话,我们当时实现的最简单的一个RPC框架,其中的注册中心是不是就是通过这两个信息来调用的远程服务。</p>
<p>消费者通过服务名,从注册中心获取对应的IP地址,然后来与远程服务通信。</p>
<p>下面我们实现一个消费者。</p>
<h2 id="4-创建消费者(dubbomall-web)"><a href="#4-创建消费者(dubbomall-web)" class="headerlink" title="4. 创建消费者(dubbomall-web)"></a>4. 创建消费者(dubbomall-web)</h2><p>重新创建一个项目。</p>
<p>添加生产者依赖。</p>
<pre><code><?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>dubbomall</artifactId>
<groupId>com.zdran</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbomall-web</artifactId>
<dependencies>
<dependency>
<groupId>com.zdran</groupId>
<artifactId>dubbomall-user</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
</code></pre>
<p>导入 dubbo 服务,在 resources 目录下创建<code>dubbo-server.xml</code>,内容如下:</p>
<pre><code><beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="dubbo-web"/>
<!-- 这里使用的注册中心是zookeeper -->
<dubbo:registry address="zookeeper://127.0.0.1:2181" client="zkclient"/>
<!-- 从注册中心中查找服务 -->
<dubbo:reference id="userService" interface="com.zdran.dubbomall.user.service.UserService"/>
</beans>
</code></pre>
<p>实现 RPC 调用,创建一个启动类,实现 main 方法,调用远程的 UserService 服务</p>
<pre><code>public class ApplicationMain {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
new String[]{"dubbo-server.xml"});
context.start();
UserService demoService = (UserService) context.getBean("userService");
String hello = demoService.sayHello("dubbo");
System.out.println(hello);
}
}
</code></pre>
<p>运行一下这个 main 方法,由于机器性能、网络问题等原因,调用结果可能要等待10s左右,才能得到结果。</p>
<h2 id="5-查看注册中心的消费者"><a href="#5-查看注册中心的消费者" class="headerlink" title="5. 查看注册中心的消费者"></a>5. 查看注册中心的消费者</h2><p>我们去注册中心看一下消费者的情况。</p>
<p><strong>注意:你要先运行消费者的main方法,然后运行期间不断的查看注册中心的消费者节点,才能看到。因为消费者一旦执行结束后,该节点就会自动被注册中心删除掉了</strong></p>
<pre><code>[zk: 127.0.0.1:2181(CONNECTED) 22] ls /dubbo/com.zdran.dubbomall.user.service.UserService/consumers
[]
[zk: 127.0.0.1:2181(CONNECTED) 23] ls /dubbo/com.zdran.dubbomall.user.service.UserService/consumers
[]
[zk: 127.0.0.1:2181(CONNECTED) 24] ls /dubbo/com.zdran.dubbomall.user.service.UserService/consumers
[]
[zk: 127.0.0.1:2181(CONNECTED) 25] ls /dubbo/com.zdran.dubbomall.user.service.UserService/consumers
[]
[zk: 127.0.0.1:2181(CONNECTED) 26] ls /dubbo/com.zdran.dubbomall.user.service.UserService/consumers
[consumer%3A%2F%2F192.168.56.1%2Fcom.zdran.dubbomall.user.service.UserService
%3Fapplication%3Ddubbo-web%26category%3Dconsumers%26check%3Dfalse%26dubbo
%3D2.5.3%26interface%3Dcom.zdran.dubbomall.user.service.UserService%26methods
%3DsayHello%26pid%3D4092%26side%3Dconsumer%26timestamp%3D1542034195230]
</code></pre>
<p>还是看其中的两个重要信息,第一个是IP,这个IP是消费者的IP,准确的说是,消费者的那个 main方法执行的机器IP。因为我是在同一个机器上启动的消费者和生产者,所以这个IP是一样的。<br>第二个就是接口的全路径以及方法名。有这两个信息,消费者就能从注册中心获取对应服务的IP,发起调用了。</p>
<p><strong>PS:消费者不应该直接依赖生产者。正确的做法是抽出一个API模块,由生产者来实现API的接口,然后消费者依赖API。</strong></p>
<p>就像我们在写代码时不会直接使用 UserServiceImpl ,而是使用 UserService,一样的道理。</p>
</div>
</v-card-text>
<v-divider class="success lighten-1" ></v-divider>
<v-card-text>
<v-alert style="margin-left:2%; margin-right: 2%;padding-top: 2%;padding-bottom: 2%;" dense text border="left" type="success">
版权声明:本博客所有文章除特别声明外,均采用 <a href="/creativecommons.html" target="_blank">CC BY-NC-SA 4.0 </a>许可协议。转载请注明出处!
</v-alert>
</v-card-text>
</v-card>
<!-- 分页 -->
</div>
<!-- 页脚 -->
<div style="width: 100%; margin-top: 2%; text-align:center;">
<v-footer padless style="background:rgba(76,175,80,0.4);">
<v-card style="width: 100%; text-align:center;background:rgba(0,0,0,0);" gradient="to top, rgba(0,0,0,.2), rgba(0,0,0,.8)" tile elevation="24" class="white--text text-center">
<v-card-actions style="text-align: center;">
<v-chip class="white--text" style="background:rgba(0,0,0,0);" href=https://github.com/zdRan>
我的GitHub
</v-chip>
<v-chip class="white--text" style="background:rgba(0,0,0,0);" href=https://leetcode.cn/u/u2647>
我的LeetCode
</v-chip>
<v-chip class="white--text" style="background:rgba(0,0,0,0);" href=https://juejin.cn/user/3896324938793943>
我的掘金
</v-chip>
<v-spacer></v-spacer>
<div>
<v-list-item two-line>
<!-- 很高兴您使用本主题,开发不易,希望您保留一下版权声明,它并不会影响页面效果 ~ -->
<v-list-item-content style="text-align: left;display: inline-block;">
<v-list-item-subtitle class="white--text">Powered by <a target="_blank" rel="noopener" href="https://hexo.io/zh-cn/" style="color: white;"><strong>Hexo</strong></a></v-list-item-subtitle>
<v-list-item-subtitle class="white--text">Powered by <a target="_blank" rel="noopener" href="https://github.com/zdRan/three-cards" style="color: white;"><strong>three-cards</strong></a></v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
</div>
</v-card-actions>
<v-divider class="success lighten-1"></v-divider>
<v-card-text class="white--text">
Copyright © 2017 - {{ new Date().getFullYear() }} <a target="_blank" href="http://www.miitbeian.gov.cn" rel="nofollow noopener" style="color: white;">某ICP备xxxxxxxx号</a>
</v-card-text>
</v-card>
</v-footer>
</div>
</v-app>
</div>
<script>
new Vue({
el: '#app',
vuetify: new Vuetify(),
});
//加载代码高亮
hljs.highlightAll();
</script>
</body>
</html>