-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathsearch.xml
453 lines (218 loc) · 79.8 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>Netty传输对象消息</title>
<link href="/2019/09/23/netty/netty-object/"/>
<url>/2019/09/23/netty/netty-object/</url>
<content type="html"><![CDATA[<h3 id="概要"><a href="#概要" class="headerlink" title="概要"></a>概要</h3><blockquote><p>netty进行对象传输首先对象需要序列化,然后通过ByteBuf的形式进行传输</p></blockquote><h3 id="Netty服务端实现"><a href="#Netty服务端实现" class="headerlink" title="Netty服务端实现"></a>Netty服务端实现</h3><blockquote><p>创建StudentServer与客户端建立通道进行通信 </p></blockquote><pre><code>public class StudentServer { public void run(Integer port){ //创建EventLoopGroup 处理时间 EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1) EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); // (2) b.group(bossGroup, workerGroup) //指定所使用的NIO传输 Channel .channel(NioServerSocketChannel.class) // (3) .childHandler(new StudentServerChannelInitializer()) .option(ChannelOption.SO_BACKLOG, 1024) // (5) .childOption(ChannelOption.SO_KEEPALIVE, true); // (6) //绑定端口,同步等待绑定成功 ChannelFuture f = b.bind(port).sync(); // (7) //等到服务器监听端口关闭 f.channel().closeFuture().sync(); } catch (Exception e){ e.printStackTrace(); }finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { new StudentServer().run(8000); }}</code></pre><blockquote><p>创建StudentServerChannelInitializer服务端的通道初始化,绑定处理的Handler </p></blockquote><pre><code>public class StudentServerChannelInitializer extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel ch) throws Exception { //添加对象解析器,负责对象序列号POJO对象进行解码,设置对象序列号最大长度为1M 防止内存溢出 //设置WeakReferenceMap对类加载器进行缓存,支持多线程并发访问,防止内存溢出 ch.pipeline().addLast(new ObjectDecoder(1024 * 1024, ClassResolvers.weakCachingConcurrentResolver(this.getClass().getClassLoader()))); //添加对象编码器,在服务器对外发信息的时候实现自动序列号 ch.pipeline().addLast(new ObjectEncoder()); //处理网络IO ch.pipeline().addLast(new StudentServerHandler()); }}</code></pre><blockquote><p>创建StudentServerHandler处理Channel的生命周期,接收客户端发送的消息数据,这里使用的是ChannelInboundHandlerAdapter绑定的对象是Object,服务端读取数据的时候需要进行强转</p></blockquote><pre><code>public class StudentServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { //接收客户端发过来的消息 StudentInput studentInput = (StudentInput) msg; System.out.println("接收客户端发过来的消息:" + studentInput.toString()); //返回给客户端消息 StudentOutput studentOutput = new StudentOutput(); studentOutput.setName("李四"); studentOutput.setAge(20); studentOutput.setSex("男"); ctx.writeAndFlush(studentOutput); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); }}</code></pre><blockquote><p>StudentServerSimpleHandler 继承的SimpleChannelInboundHandlerd对象是可以直接接收的对象,在客户端发送数据的时候就进行序列化数据和反序列数据,在接收端就可以指定接收数据的类型。 </p></blockquote><pre><code>public class StudentServerSimpleHandler extends SimpleChannelInboundHandler<StudentInput> { @Override protected void channelRead0(ChannelHandlerContext ctx, StudentInput msg) throws Exception { //接收客户端发过来的消息 System.out.println("接收客户端发过来的消息:" + msg.toString()); //返回给客户端消息 StudentOutput studentOutput = new StudentOutput(); studentOutput.setName("李四"); studentOutput.setAge(20); studentOutput.setSex("男"); ctx.writeAndFlush(studentOutput); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); }}</code></pre><h3 id="Netty客户端实现"><a href="#Netty客户端实现" class="headerlink" title="Netty客户端实现"></a>Netty客户端实现</h3><blockquote><p>创建StudentClient与服务端建立连接,并指定使用StudentClientChannelInitializer通道初始化。</p></blockquote><pre><code>public class StudentClient { public void connect(String host, int port){ //配置辅助启动类 EventLoopGroup group = new NioEventLoopGroup(); try { // 客户端辅助启动类 对客户端配置 Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group) .channel(NioSocketChannel.class) .handler(new StudentClientChannelInitializer()) .option(ChannelOption.TCP_NODELAY,true); //异步连接服务器 ChannelFuture channelFuture =bootstrap.connect(host, port).sync(); //异步等待连接关闭 channelFuture.channel().closeFuture().sync(); }catch (Exception e){ e.printStackTrace(); }finally { group.shutdownGracefully(); } } public static void main(String[] args) { new StudentClient().connect("127.0.0.1",8000); }}</code></pre><blockquote><p>StudentClientChannelInitializer通道初始化设置解析器进行序列号传输和处理IO的Handler来进行数据的通讯。</p></blockquote><pre><code>public class StudentClientChannelInitializer extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel ch) throws Exception { //添加对象解析器,负责对象序列号POJO对象进行解码,设置对象序列号最大长度为1M 防止内存溢出 //设置WeakReferenceMap对类加载器进行缓存,支持多线程并发访问,防止内存溢出 ch.pipeline().addLast(new ObjectDecoder(1024 * 1024, ClassResolvers.weakCachingConcurrentResolver(this.getClass().getClassLoader()))); //添加对象编码器,在服务器对外发信息的时候实现自动序列号 ch.pipeline().addLast(new ObjectEncoder()); //处理网络IO ch.pipeline().addLast(new StudentClientSimpleHandler()); }}</code></pre><blockquote><p>创建StudentClientHandler处理器与服务端进行通讯,进行数据的发送和接收。</p></blockquote><pre><code>public class StudentClientHandler extends ChannelInboundHandlerAdapter { //服务器和客户端连接成功 @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { StudentInput studentInput = new StudentInput(); studentInput.setAge(10); studentInput.setName("张三"); ctx.writeAndFlush(studentInput); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { try { StudentOutput studentOutput = (StudentOutput) msg; System.out.println(studentOutput.toString()); }catch (Exception e){ e.printStackTrace(); }finally { ReferenceCountUtil.release(msg); } }}</code></pre><p>StudentClientSimpleHandler 采用继承了SimpleChannelInboundHandler的方式,可以指定传输的数据类型</p><pre><code>public class StudentClientSimpleHandler extends SimpleChannelInboundHandler<StudentOutput> { //服务器和客户端连接成功 @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { StudentInput studentInput = new StudentInput(); studentInput.setAge(10); studentInput.setName("张三"); ctx.writeAndFlush(studentInput); } @Override protected void channelRead0(ChannelHandlerContext ctx, StudentOutput msg) throws Exception { StudentOutput studentOutput = (StudentOutput) msg; System.out.println("客户端接收到服务器的消息:" + studentOutput.toString()); }}</code></pre>]]></content>
<categories>
<category> JAVA </category>
<category> Netty </category>
</categories>
<tags>
<tag> JAVA </tag>
<tag> Netty </tag>
</tags>
</entry>
<entry>
<title>Netty 入门</title>
<link href="/2019/09/17/netty/get-start/"/>
<url>/2019/09/17/netty/get-start/</url>
<content type="html"><![CDATA[<blockquote><p>Netty是一个高效的非阻塞(NIO)的网络应用程序框架。用于快速开发高性能协议服务器和客户端。 </p></blockquote><p><img src="/medias/loading.svg" data-original="/netty/net_request_process.png" alt="网络请求过程"></p><blockquote><p>Netty 主要是基于Reactor模式的。Reactor 直译为反应器、反应堆。这个翻译容易误导人。其实将 Reactor 意译为分发器更为恰当。<br>Reactor 模式本质上是一个事件机制,通过一个或一组线程检查事件,<br>发现事件之后交由另一组事件处理线程执行该事件所对应的事件处理器(回调),从而实现高响应的程序。</p></blockquote><blockquote><p>Reactor 模型中有 2 个关键组成:<br>1)Reactor:Reactor 在一个单独的线程中运行,负责监听和分发事件,分发给适当的处理程序来对 IO 事件做出反应。它就像公司的电话接线员,它接听来自客户的电话并将线路转移到适当的联系人;<br>2)Handlers:处理程序执行 I/O 事件要完成的实际事件,类似于客户想要与之交谈的公司中的实际官员。Reactor 通过调度适当的处理程序来响应 I/O 事件,处理程序执行非阻塞操作。</p></blockquote><p><img src="/medias/loading.svg" data-original="/netty/nettty_reactor.jpg" alt="Handler过程"></p><h3 id="Netty-服务端实现"><a href="#Netty-服务端实现" class="headerlink" title="Netty 服务端实现"></a>Netty 服务端实现</h3><blockquote><p>创建服务器与客户端建立连接 </p></blockquote><pre><code>public class EchoServer { private int port; public EchoServer(int port) { this.port = port; } public void run() throws Exception { //创建EventLoopGroup 处理时间 EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1) EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); // (2) b.group(bossGroup, workerGroup) //指定所使用的NIO传输 Channel .channel(NioServerSocketChannel.class) // (3) .childHandler(new ChannelInitializer<SocketChannel>() { // (4) @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new EchoServerHandler()); } }) .option(ChannelOption.SO_BACKLOG, 128) // (5) .childOption(ChannelOption.SO_KEEPALIVE, true); // (6) // Bind and start to accept incoming connections. ChannelFuture f = b.bind(port).sync(); // (7) // Wait until the server socket is closed. f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { int port = 8080; if (args.length > 0) { port = Integer.parseInt(args[0]); } new EchoServer(port).run(); }}</code></pre><blockquote><p>创建EchoServerHandler处理客户端请求过来的数据 </p></blockquote><pre><code>public class EchoServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf byteBuffer = (ByteBuf) msg; System.out.println("server receive:" + byteBuffer.toString(CharsetUtil.UTF_8)); //将接受到消息回写给发送者 ctx.write(byteBuffer); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { //将未消息冲刷到远程节点,并且关闭该 Channel ctx.writeAndFlush(Unpooled.EMPTY_BUFFER) .addListener(ChannelFutureListener.CLOSE); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { //打印异常栈跟踪 cause.printStackTrace(); //关闭该Channel ctx.close(); }}</code></pre><h3 id="Netty-客户端实现"><a href="#Netty-客户端实现" class="headerlink" title="Netty 客户端实现"></a>Netty 客户端实现</h3><blockquote><p>创建EchoClient客户端与服务器建立通讯 </p></blockquote><pre><code>public class EchoClient { private final String host; private final int port; public EchoClient(String host, int port) { this.host = host; this.port = port; } public void start() throws InterruptedException { EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(group) .channel(NioSocketChannel.class) .remoteAddress(new InetSocketAddress(host, port)) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { socketChannel.pipeline().addLast(new EchoClientHandler()); } }); ChannelFuture channelFuture = b.connect().sync(); channelFuture.channel().closeFuture().sync(); } finally { group.shutdownGracefully().sync(); } } public static void main(String[] args) throws InterruptedException { new EchoClient("127.0.0.1", 8080).start(); }}</code></pre><blockquote><p>创建EchoClientHandler处理器,处理客户端与服务端之间的通讯 </p></blockquote><pre><code>@ChannelHandler.Sharablepublic class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> { /** * 渠道读取服务器传递过来的消息 * @param channelHandlerContext * @param byteBuf * @throws Exception */ @Override protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception { System.out.println("Client received: "+ byteBuf.toString(CharsetUtil.UTF_8)); } /** * 服务器建立后调用 * @param ctx * @throws Exception */ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { ctx.writeAndFlush(Unpooled.copiedBuffer("Netty rocks",CharsetUtil.UTF_8)); } /** * 传递异常时候调用 * @param ctx * @param cause * @throws Exception */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); }}</code></pre><blockquote><p>我们可以从ChannelInboundHandlerAdapter的源码看到ChannelInboundHandler的行为周期 </p></blockquote><pre><code> /** *通道注册的时候调用 */ @Skip @Override public void channelRegistered(ChannelHandlerContext ctx) throws Exception { ctx.fireChannelRegistered(); } /** *通道未注册的时候调用 */ @Skip @Override public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { ctx.fireChannelUnregistered(); } /** * channel被启用的时候触发(在建立连接的时候) * 客户端连接到服务端后进行 */ @Skip @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { ctx.fireChannelActive(); } /** * channel被禁用的时候触发(在断开连接的时候) * 客户端与服务端断开连接后进行 */ @Skip @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { ctx.fireChannelInactive(); } /** * 读取客户端发送的数据 */ @Skip @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ctx.fireChannelRead(msg); } /** * 数据读取完成的时候触发 */ @Skip @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.fireChannelReadComplete(); } /** * 用户时间触发的时候调用 */ @Skip @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { ctx.fireUserEventTriggered(evt); } /** * 信道可写性已更改的时候调用 */ @Skip @Override public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception { ctx.fireChannelWritabilityChanged(); } /** * exceptionCaught() 事件处理方法是当出现 Throwable 对象才会被调用, * 即当 Netty 由于 IO 错误或者处理器在处理事件时抛出的异常时。 * 在大部分情况下,捕获的异常应该被记录下来并且把关联的 channel 给关闭掉。 * 然而这个方法的处理方式会在遇到不同异常的情况下有不同的实现, * 比如你可能想在关闭连接之前发送一个错误码的响应消息。 */ @Skip @Override @SuppressWarnings("deprecation") public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.fireExceptionCaught(cause); } /** * 每当从服务端收到新的客户端连接时调用 */ @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { // NOOP } /** * 每当从服务端收到新的客户端断开时调用 */ @Override public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { // NOOP }</code></pre>]]></content>
<categories>
<category> JAVA </category>
<category> Netty </category>
</categories>
<tags>
<tag> JAVA </tag>
<tag> Netty </tag>
</tags>
</entry>
<entry>
<title>Python 使用Django 搭建web应用</title>
<link href="/2019/09/05/python/python-django/"/>
<url>/2019/09/05/python/python-django/</url>
<content type="html"><![CDATA[<h2 id="环境安装"><a href="#环境安装" class="headerlink" title="环境安装"></a>环境安装</h2><h3 id="Python-环境安装"><a href="#Python-环境安装" class="headerlink" title="Python 环境安装"></a>Python 环境安装</h3><blockquote><p>下载python安装包进行安装,或者使用Anaconda进行安装,我本机是使用Anaconda的安装方式,<br>正常下载安装包之后,只要选择默认选项即可</p></blockquote><h3 id="Django环境安装"><a href="#Django环境安装" class="headerlink" title="Django环境安装"></a>Django环境安装</h3><blockquote><p>运行命令: <code>pip install django</code></p></blockquote><h2 id="Djangon-操作"><a href="#Djangon-操作" class="headerlink" title="Djangon 操作"></a>Djangon 操作</h2><h3 id="Djangon命令"><a href="#Djangon命令" class="headerlink" title="Djangon命令"></a>Djangon命令</h3><pre><code>startproject #创建一个Django项目startapp #创建一个Django应用check #校验项目完整性runserver #本地简易运行Django项目shell #进入Django项目的python shelltest #执行Django用例测试makemigrations #创建模型变更的迁移文件migrate #执行上一个命令创建的迁移文件dumpdata #把数据库数据导出到文件loaddata #把文件数据导入数据库</code></pre><blockquote><p>创建一个项目<br><code>django-admin startproject django_introduction</code> </p></blockquote><blockquote><p>创建一个Django App应用<br><code>python manage.py stratapp blog</code> //创建Django App应用 </p></blockquote><h3 id="Django应用目录介绍"><a href="#Django应用目录介绍" class="headerlink" title="Django应用目录介绍"></a>Django应用目录介绍</h3><pre><code>views.py: 视图处理的地方models.py: 定义应用模型的地方admin.py: 定义Admin模块管理对象的地方apps.py:声明应用的地方tests.py:编写应用测试的地方urls.py:(自行创建)管理应用路由的地方</code></pre><blockquote><p>生成模型的迁移文件<br><code>python manage.py makemigrations</code> </p></blockquote><blockquote><p>同步迁移文件到数据库<br><code>python manage.py migrate</code> </p></blockquote><blockquote><p>进入Django Shell命令<br><code>python manage.py shell</code></p></blockquote><h3 id="Django-Admin模块使用"><a href="#Django-Admin模块使用" class="headerlink" title="Django Admin模块使用"></a>Django Admin模块使用</h3><blockquote><p>创建管理员用户<br><code>python manage.py createsuperuser</code></p></blockquote><blockquote><p>登录页面进行操作<br><code>python manage.py runserver</code> </p></blockquote><h3 id="Django模板"><a href="#Django模板" class="headerlink" title="Django模板"></a>Django模板</h3><h4 id="基本语法"><a href="#基本语法" class="headerlink" title="基本语法"></a>基本语法</h4><pre><code>变量 {{ title }} for循环 {% for x in list%} {% endfor %} if else判断 {% if %} {% else %} {% endif %} </code></pre>]]></content>
<categories>
<category> Python </category>
<category> Django </category>
<category> Web </category>
</categories>
<tags>
<tag> Python </tag>
<tag> Django </tag>
</tags>
</entry>
<entry>
<title>Python 使用Scrapy爬虫框架</title>
<link href="/2019/09/04/python/gecco/"/>
<url>/2019/09/04/python/gecco/</url>
<content type="html"><![CDATA[<h2 id="安装环境"><a href="#安装环境" class="headerlink" title="安装环境"></a>安装环境</h2><h3 id="安装Scrapy"><a href="#安装Scrapy" class="headerlink" title="安装Scrapy"></a>安装Scrapy</h3><blockquote><p>scrapy 是一套基于Twisted的异步开发框架,是纯python 实现的爬虫框架。</p></blockquote><p>使用<code>conda</code>安装Scrapy 运行:<br><code>conda install -c conda-forge scrapy</code><br>或者熟悉了python包的安装,那么可以从pypi安装scrappy及其依赖项,方法是:</p><pre><code>pip3 install scrapy</code></pre><p>我采用的是pip安装,过程中遇到的问题</p><pre><code>Traceback (most recent call last): File "d:\study\python\anaconda3\lib\runpy.py", line 193, in _run_module_as_main "__main__", mod_spec) File "d:\study\python\anaconda3\lib\runpy.py", line 85, in _run_code exec(code, run_globals) File "D:\Study\Python\Anaconda3\Scripts\scrapy.exe\__main__.py", line 5, in <module> File "d:\study\python\anaconda3\lib\site-packages\scrapy\__init__.py", line 34, in <module> from scrapy.spiders import Spider File "d:\study\python\anaconda3\lib\site-packages\scrapy\spiders\__init__.py", line 10, in <module> from scrapy.http import Request File "d:\study\python\anaconda3\lib\site-packages\scrapy\http\__init__.py", line 11, in <module> from scrapy.http.request.form import FormRequest File "d:\study\python\anaconda3\lib\site-packages\scrapy\http\request\form.py", line 11, in <module> import lxml.html File "d:\study\python\anaconda3\lib\site-packages\lxml\html\__init__.py", line 54, in <module> from .. import etreeImportError: DLL load failed: 找不到指定的模块。</code></pre><blockquote><p>解决方法是参考博客<a href="https://www.cnblogs.com/shuibingyue/p/7090624.html" target="_blank" rel="noopener">lxml不含etree模块</a>,<br>我的python版本是<code>3.7.1</code>,下载的非官方whl文件是lxml-4.3.5-cp37-cp37m-win_amd64.whl</p></blockquote><pre><code>第一步:移除现在的lxml 运行命令:pip unistall lxml第二步:下载相应版本的lxml非官方whl文件,并安装lxml</code></pre><h3 id="安装Mongodb数据库"><a href="#安装Mongodb数据库" class="headerlink" title="安装Mongodb数据库"></a>安装Mongodb数据库</h3><p>windows 上安装Mongodb数据库 <a href="https://www.runoob.com/mongodb/mongodb-window-install.html" target="_blank" rel="noopener">安装教程</a></p><h2 id="创建项目"><a href="#创建项目" class="headerlink" title="创建项目"></a>创建项目</h2><blockquote><p>创建爬虫项目icomic</p></blockquote><pre><code>scrapy startproject icomic</code></pre><h3 id="生成抓取的spider爬虫文件"><a href="#生成抓取的spider爬虫文件" class="headerlink" title="生成抓取的spider爬虫文件"></a>生成抓取的spider爬虫文件</h3><pre><code>scrapy genspider icomic_spider www.manhuatai.com</code></pre><h3 id="项目启动"><a href="#项目启动" class="headerlink" title="项目启动"></a>项目启动</h3><pre><code>scrapy crawl icomic_spider</code></pre><p><img src="/medias/loading.svg" data-original="python/scrapy-framework.jpg" alt="scrapy框架图"></p><p><a href="https://www.imooc.com/learn/1017" target="_blank" rel="noopener">视频教程</a></p><blockquote><p>注意的地方:<br>中间件定义之后要在setting里面启用,爬虫文件名和爬虫项目名称不能相同</p></blockquote>]]></content>
<categories>
<category> Python </category>
<category> Scrapy </category>
</categories>
<tags>
<tag> 爬虫 </tag>
<tag> Python </tag>
<tag> Scrapy </tag>
</tags>
</entry>
<entry>
<title>SpringCloud zuul网关</title>
<link href="/2019/08/29/java/spring-cloud/api-gateway/"/>
<url>/2019/08/29/java/spring-cloud/api-gateway/</url>
<content type="html"><![CDATA[<h2 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h2><h3 id="添加依赖"><a href="#添加依赖" class="headerlink" title="添加依赖"></a>添加依赖</h3><blockquote><p>在项目根目录下的pom.xml文件中添加依赖 </p></blockquote><pre><code><!--eureka客户端--><dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><!--网关--><dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId></dependency></code></pre><h3 id="启动注解"><a href="#启动注解" class="headerlink" title="启动注解"></a>启动注解</h3><p>在启动类上添加注解 <code>@EnableZuulProxy</code> </p><pre><code>@SpringBootApplication@EnableDiscoveryClient@EnableZuulProxypublic class ApiGatewayApplication { public static void main(String[] args) { SpringApplication.run(ApiGatewayApplication.class, args); }}</code></pre><h3 id="配置网关信息"><a href="#配置网关信息" class="headerlink" title="配置网关信息"></a>配置网关信息</h3><p>在resource 目录下的bootstrap.yml文件中配置网关信息</p><pre><code>eureka: client: service-url: defaultZone: http://localhost:8761/eureka/spring: application: name: api-gateway</code></pre><h2 id="路由"><a href="#路由" class="headerlink" title="路由"></a>路由</h2><h3 id="路由转发"><a href="#路由转发" class="headerlink" title="路由转发"></a>路由转发</h3><p>在bootstrap.yml里面进行配置路由转发的规则</p><pre><code>zuul: routes:# 简介写法 product: /myProduct/**# 禁止访问的地址 ignored-patterns: - /**/product/listForOrder</code></pre><h3 id="路由自定义"><a href="#路由自定义" class="headerlink" title="路由自定义"></a>路由自定义</h3><blockquote><p>在bootstrap.yml里面进行配置哪个服务的id,对应哪个地址</p><pre><code>zuul: routes:</code></pre></blockquote><h1 id="简介写法"><a href="#简介写法" class="headerlink" title="简介写法"></a>简介写法</h1><pre><code>path: /myProduct/**serviceId: product</code></pre><pre><code>### Cookie从源码中我们可以知道我们默认是过来了请求头的`"Cookie", "Set-Cookie", "Authorization"`属性</code></pre><p>private Set<string> sensitiveHeaders = new LinkedHashSet<>(<br> Arrays.asList(“Cookie”, “Set-Cookie”, “Authorization”`));</string></p><pre><code>如果我们要请求携带Cookie的话,只需要讲sensitiveHeaders设置为空就可以。</code></pre><p>zuul:<br> routes:</p><h1 id="简介写法-1"><a href="#简介写法-1" class="headerlink" title="简介写法"></a>简介写法</h1><pre><code>product: /myProduct/**sensitiveHeaders:</code></pre><pre><code>### 动态路由通过统一配置中心动态获取参数信息,从而动态配置路由信息达到动态路由的效果</code></pre><p>@Component<br>public class ZuulConfig {</p><pre><code>@ConfigurationProperties("zull")@RefreshScopepublic ZuulProperties zuulProperties(){ return new ZuulProperties();}</code></pre><p>}</p><pre><code>## 高可用将多个Zuul节点注册到Eureka Server上即可实现Zuul的高可用## 过滤### Pre和Post过滤器前置过滤器的作用</code></pre><p>限流<br>鉴权<br>参数校验<br>请求转发</p><pre><code>后置过滤器的作用</code></pre><p>数据的统计<br>日志的记录</p><pre><code>## 限流>如果一个项目中有既有限流,又有鉴权的话,限流的优先级应该优先于鉴权的优先级 >新增一个限流过滤类实现网关过滤器</code></pre><p>/**</p><ul><li><p>令牌桶限流</p></li><li><p>/<br>@Component<br>public class RateLimitFilter extends ZuulFilter {<br> /<strong>每秒100个令牌</strong>/<br> private static final RateLimiter RATE_LIMITER = RateLimiter.create(100);<br> @Override<br> public String filterType() {</p><pre><code> return PRE_TYPE;</code></pre><p> }<br> @Override<br> public int filterOrder() {</p><pre><code> return SERVLET_DETECTION_FILTER_ORDER - 1;</code></pre><p> }<br> @Override<br> public boolean shouldFilter() {</p><pre><code> return true;</code></pre><p> }<br> @Override<br> public Object run() throws ZuulException {</p><pre><code> if(!RATE_LIMITER.tryAcquire()){ throw new RateLimitException(); } return null;</code></pre><p> }<br>}</p></li></ul><pre><code>## 鉴权>新建一个TokenFilter过滤类继承ZuulFilter类。</code></pre><p>@Component<br>public class TokenFilter extends ZuulFilter {<br> @Override<br> public String filterType() {<br> return PRE_TYPE;<br> }<br> /**<br> * 过滤值越小,执行优先级越高<br> * @return<br> */<br> @Override<br> public int filterOrder() {<br> //减一,自定义的过滤器就会在PRE_DECORATION_FILTER_ORDER过滤器之前执行<br> return PRE_DECORATION_FILTER_ORDER -1;<br> }<br> @Override<br> public boolean shouldFilter() {<br> return true;<br> }<br> @Override<br> public Object run() throws ZuulException {<br> RequestContext currentContext = RequestContext.getCurrentContext();<br> HttpServletRequest request = currentContext.getRequest();</p><pre><code> // 从url参数里获取,也可以从cookie,header里获取 String token = request.getParameter("token"); if(StringUtils.isEmpty(token)){ //token为空,限权校验不通过 currentContext.setSendZuulResponse(false); currentContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value()); } return null;}</code></pre><p>}</p><pre><code>## 跨域在项目config配置文件包中,新增CorsConfig配置类 </code></pre><p>@Configuration<br>public class CorsConfig{<br> @Bean<br> public CorsFilter corsFilter(){<br> final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();<br> CorsConfiguration configuration = new CorsConfiguration();<br> configuration.setAllowCredentials(true);/<em>设置是否支持cookie跨域</em>/<br> configuration.setAllowedOrigins(Arrays.asList(“*”));/<em>设置原始域 <a href="http://www.a.com" target="_blank" rel="noopener">http://www.a.com</a></em>/<br> configuration.setAllowedHeaders(Arrays.asList(“*”));<br> configuration.setAllowedMethods(Arrays.asList(“*”));<br> configuration.setMaxAge(300l);//设置缓存时间<br> source.registerCorsConfiguration(“/**”,configuration);<br> return new CorsFilter();<br> }<br>}</p><pre><code></code></pre>]]></content>
<categories>
<category> SpringCloud </category>
<category> JAVA </category>
</categories>
<tags>
<tag> JAVA </tag>
<tag> SpringCloud </tag>
<tag> Zuul </tag>
</tags>
</entry>
<entry>
<title>Spring-Cloud使用openFeign实现服务间的调用</title>
<link href="/2019/08/21/java/spring-cloud/openfeign/"/>
<url>/2019/08/21/java/spring-cloud/openfeign/</url>
<content type="html"><![CDATA[<blockquote><p>今天我们记录一下openFeign实现SpringCloud微服务之间的调度,本文使用到的信息均来自<br><a href="https://github.com/smwsk/mall">springCloud搭建的商城</a>,本项目把客户端用到的实体类统一提取到<br>一个公共的common子项目中,防止项目中client和server中的实体的冗余。</p></blockquote><h3 id="项目结构"><a href="#项目结构" class="headerlink" title="项目结构"></a>项目结构</h3><p><img src="/medias/loading.svg" data-original="/openfeign_files/1.png" alt="项目结构图"></p><h3 id="项目依赖"><a href="#项目依赖" class="headerlink" title="项目依赖"></a>项目依赖</h3><p><code>product商品模块</code></p><blockquote><p>product父模块的pom.xml 添加openFeign依赖</p></blockquote><pre><code><dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency></dependencies></code></pre><blockquote><p>product-server子模块的pom.xml添加商品客户端依赖,用来实现客户端对外暴露的接口。</p></blockquote><pre><code><dependencies> <dependency> <groupId>com.smwsk</groupId> <artifactId>product-client</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency></dependencies></code></pre><blockquote><p>product-client子模块的pom.xml添加spring-web依赖,用于@RequestMapping(),@getMapping()等注解的使用。</p></blockquote><pre><code><dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId></dependency></code></pre><p><code>order订单模块</code> </p><blockquote><p>order父模块的pom.xml 添加openFeign依赖</p></blockquote><pre><code><dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency></dependencies></code></pre><blockquote><p>order-server子模块的pom.xml 添加商品模块客户端的依赖,因为我们到时候要调用商品模块的客户端接口</p></blockquote><pre><code><dependency> <groupId>com.smwsk</groupId> <artifactId>product-client</artifactId> <version>0.0.1-SNAPSHOT</version></dependency></code></pre><blockquote><p>order-client子模块的pom.xml添加spring-web依赖,用于@RequestMapping(),@getMapping()等注解的使用。</p></blockquote><pre><code><dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId></dependency></code></pre><h3 id="openFegin使用"><a href="#openFegin使用" class="headerlink" title="openFegin使用"></a>openFegin使用</h3><blockquote><p>在order服务的OrderServerApplication 类中添加@EnableFeignClients注解,开启feign通讯,<br>basePackages 指定扫描哪些客户端的包名,basePackages接收的可以是一个字符串数组。</p></blockquote><pre><code>@EnableFeignClients(basePackages = "com.smwsk.product.client")</code></pre><h4 id="在order-server中调用product-client"><a href="#在order-server中调用product-client" class="headerlink" title="在order-server中调用product-client"></a>在order-server中调用product-client</h4><blockquote><p>直接引入spring bean管理的ProductClient对象 </p></blockquote><p>例子:</p><pre><code>@RestController@Slf4jpublic class ClientController { @Autowired private ProductClient productClient; @RequestMapping(value = "/getProductMsg") public String getProductMsg(){ String msg = productClient.getMsg(); log.info("receive msg:{}",msg); return msg; }}</code></pre>]]></content>
<categories>
<category> JAVA </category>
<category> SpringCloud </category>
</categories>
<tags>
<tag> SpringCloud </tag>
<tag> OpenFeign </tag>
</tags>
</entry>
<entry>
<title>Vue部署到阿里云OSS对象存储</title>
<link href="/2019/08/16/vue/vue-deploy/"/>
<url>/2019/08/16/vue/vue-deploy/</url>
<content type="html"><![CDATA[<blockquote><p>我目前使用的是人人开源的renren-fast管理后台,在这个基础上进行修改功能,确实能比较快的交付一些简单的项目<br>人人开源项目是前后端分离的,平时我们可以用nginx来进行映射部署前端项目。不过这个不是我们今天的主题,我们今天的<br>主题是要把前端部署到阿里云的对象存储(OSS)上面,因为我们对象存储管理后台上传不会自动创建文件夹,所以我们找个插件<br>实现代码自动部署。</p></blockquote><h3 id="新建一个oss配置文件"><a href="#新建一个oss配置文件" class="headerlink" title="新建一个oss配置文件"></a>新建一个oss配置文件</h3><blockquote><p>在根目录下新建一个oss.js文件(如图1),文件内容为oss的配置</p><pre><code>module.exports = { region: 'oss-cn-shanghai', // eg. oss-cn-hangzhou accessKeyId: 'XXXXXXXXXX', accessKeySecret: 'XXXXXXXXXXXXXXXXXXXXXXXX', bucket: 'XXXXX'}</code></pre></blockquote><pre><code>![图片1](/medias/vue/vue-oss-1.png)### 安装OSS上传插件</code></pre><p>npm install webpack-aliyun-oss -D</p><pre><code>### 对webpack.prod.conf.js进行修改配置>导入插件和配置文件</code></pre><p>const AliyunossWebpackPlugin = require(‘aliyunoss-webpack-plugin’)<br>const oss = require(‘../oss’)</p><pre><code>在plugins最后面加入配置信息</code></pre><p>plugins: [<br> …,<br>// 插入到最后面<br>new AliyunossWebpackPlugin({<br> buildPath: ‘dist/**’,<br> region: oss.region,<br> accessKeyId: oss.accessKeyId,<br> accessKeySecret: oss.accessKeySecret,<br> bucket: oss.bucket,<br> deleteAll: true,<br> generateObjectPath: function(filename, file) {<br> return file.replace(/dist//, ‘’)<br> },<br>})<br>]</p><pre><code>### 进行上传OSS>目前我的解决方法是分成两部进行,第一步进行编译好运行的文件,第二部就是把运行的文件上传的oss上#### 执行编译>第一次执行编译的时候把 new AliyunossWebpackPlugin({})这段内容给注释掉,然后执行 `npm run build --prod`,等待dist文件目录下的内容都生成完成后执行上传#### 上传编译内容>第二次执行上传的时候把项目根路径下的gulpfile.js的文件中create:versionCatalog后面的内容注释掉然后执行 `npm run build --prod`</code></pre><p>gulp.start([‘build’, ‘create:versionCatalog’/* , ‘replace:cdnUrl’, ‘replace:version’, ‘concat:config’ */], function () {<br> // 清除, 编译 / 处理项目中产生的文件<br> del([<code>${distPath}/static</code>, <code>${versionPath}/static/config</code>])<br>})</p><pre><code>>在执行了两次npm run build --prod命令之后,我们的文件就上传到oss上面,目前的方案会多上传一些文件上去,还没找到更好的解决方法,如果你有更好的解决方法,可以在评论下留下的方法,thank!!!参考博客地址:</code></pre><p><a href="https://blog.csdn.net/weixin_45066862/article/details/92671531" target="_blank" rel="noopener">https://blog.csdn.net/weixin_45066862/article/details/92671531</a><br>```</p>]]></content>
<categories>
<category> Vue </category>
</categories>
<tags>
<tag> Vue </tag>
<tag> OSS </tag>
</tags>
</entry>
<entry>
<title>Spring @Transactional事务注解</title>
<link href="/2019/08/07/java/springmvc/springmvc-transactional/"/>
<url>/2019/08/07/java/springmvc/springmvc-transactional/</url>
<content type="html"><![CDATA[<h2 id="使用场景"><a href="#使用场景" class="headerlink" title="使用场景"></a>使用场景</h2><blockquote><p>在使用Transaction注解前,我们要先知道注解用在什么业务上面,比如我把一张表(<code>table</code>)的数据备份到另外一张历史表(<code>table_history</code>)的时候,<br>我们要先把table的数据复制到table_history表,然后再删除table表的数据,如果我们中间一个环节出现异常,table数据没有复制到table_history表,<br>但是删除操作已经执行了,那就有问题了。这时候就要用Transaction来保证数据的统一性了。</p></blockquote><h2 id="事务的特性"><a href="#事务的特性" class="headerlink" title="事务的特性"></a>事务的特性</h2><p>事务有4个特性:ACID</p><h3 id="原子性(Atomicity)"><a href="#原子性(Atomicity)" class="headerlink" title="原子性(Atomicity)"></a>原子性(Atomicity)</h3><pre><code>事务是一个原子操作,由一系列动作组成。事务的原子性确保动作要么全部完成,要么完全不起作用。</code></pre><h3 id="一致性(Consistency)"><a href="#一致性(Consistency)" class="headerlink" title="一致性(Consistency)"></a>一致性(Consistency)</h3><pre><code>一旦事务完成(不管成功还是失败),系统必须确保它所建模的业务处于一致的状态,而不会是部分完成部分失败。在现实中的数据不应该被破坏。</code></pre><h3 id="隔离性(Isolation)"><a href="#隔离性(Isolation)" class="headerlink" title="隔离性(Isolation)"></a>隔离性(Isolation)</h3><pre><code>可能有许多事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏。</code></pre><h3 id="持久性(Durability)"><a href="#持久性(Durability)" class="headerlink" title="持久性(Durability)"></a>持久性(Durability)</h3><pre><code>一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响,这样就能从任何系统崩溃中恢复过来。通常情况下,事务的结果被写到持久化存储器中。</code></pre><h2 id="事务的传播"><a href="#事务的传播" class="headerlink" title="事务的传播"></a>事务的传播</h2><blockquote><p>Spring中的@Transaction是基于动态代理的机制,提供了一种透明的事务管理机制,在日常开发过程中一般是用@Transaction<br>注解来快速解决事务问题。<br> @Transactional(propagation=Propagation.NOT_SUPPORTED)<br>Propagation事务的传播有7种不同的传播方式</p><pre><code>REQUIRED: 如果存在一个事务,则使用当前事务,如果没有事务则开启一个事务,Spring默认的事务传播级别.REQUIRES_NEW: 总是开启一个新的事务,如果一个事务已经存在,则将这个存在的事务挂起,执行当前新建事务完成以后,上下文事务恢复再执行。SUPPORTS: 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行。NOT_SUPPORTED: 总是非事务地执行,并挂起任何存在的事务。MANDATORY: 该级别的事务要求上下文中必须要存在事务,否则就会抛出异常。NEVER:要求上下文中不能存在事务,一旦有事务,就抛出runtime异常,强制停止执行。NESTED: 如果上下文中存在事务,则嵌套事务执行,如果不存在事务,则新建事务。</code></pre></blockquote><h2 id="数据隔离级别"><a href="#数据隔离级别" class="headerlink" title="数据隔离级别"></a>数据隔离级别</h2><blockquote><p>spring中使用@Transaction(isolation=Isolation.DEFAULT) 来指定隔离级别,Isolation.DEFAULT:为数据源的默认隔离级别</p></blockquote><table><thead><tr><th align="center">隔离级别</th><th align="center">脏读</th><th align="center">不可重复读取</th><th align="center">幻读</th></tr></thead><tbody><tr><td align="center">Serializable</td><td align="center">不会</td><td align="center">不会</td><td align="center">不会</td></tr><tr><td align="center">REPEATABLE_READ</td><td align="center">不会</td><td align="center">不会</td><td align="center">会</td></tr><tr><td align="center">READ_COMMITTED</td><td align="center">不会</td><td align="center">会</td><td align="center">会</td></tr><tr><td align="center">READ_UNCOMMITTED</td><td align="center">会</td><td align="center">会</td><td align="center">会</td></tr></tbody></table><pre><code>Serializable(序列化级别):提供了严格的事务隔离,要求事务序列化执行,只能一个接着一个执行,不能进行并行。REPEATABLE_READ(可重复读取级别):以操作同一行数据为前提,读事务禁止其他写事务(但允许其他读事务)。READ_COMMITTED(授权读取级别):以操作同一行数据为前提,读事务允许其他读事务和写事务,未提交的写事务禁止其他读事务和写事务。READ_UNCOMMITTED(未授权读取级别):以操作同一行数据为前提,读事务允许其他读事务和写事务,未提交的写事务禁止其他写事务(但允许其他读事务)。</code></pre><h2 id="Spring-注解管理事务的实现步骤"><a href="#Spring-注解管理事务的实现步骤" class="headerlink" title="Spring 注解管理事务的实现步骤"></a>Spring 注解管理事务的实现步骤</h2><blockquote><p>@Transactional注解管理事务的实现分为两步,第一步配置事务管理,第二部声明在哪个类或者哪个方法上使用事务注解()@Transactional。</p></blockquote><h3 id="xml配置事务管理器"><a href="#xml配置事务管理器" class="headerlink" title="xml配置事务管理器"></a>xml配置事务管理器</h3><pre><code><tx:annotation-driven /> //开启事务注解<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /></bean></code></pre><h3 id="注解方式配置事务管理器"><a href="#注解方式配置事务管理器" class="headerlink" title="注解方式配置事务管理器"></a>注解方式配置事务管理器</h3><pre><code>@EnableTransactionManagement //启用事务管理功能@SpringBootApplicationpublic class DemoApplication { // 其中 dataSource 框架会自动为我们注入 @Bean public PlatformTransactionManager txManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); }}</code></pre><h3 id="自定义事务管理器"><a href="#自定义事务管理器" class="headerlink" title="自定义事务管理器"></a>自定义事务管理器</h3><pre><code>@Beanpublic PlatformTransactionManager transactionManager() { JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setDataSource(dataSource()); return transactionManager;}</code></pre><h2 id="避免-Spring-的-AOP-的自调用问题"><a href="#避免-Spring-的-AOP-的自调用问题" class="headerlink" title="避免 Spring 的 AOP 的自调用问题"></a>避免 Spring 的 AOP 的自调用问题</h2><blockquote><p>在Spring的AOP代理下,只有目标方法由外部调用,目标方法才由Spring生成的代理对象来管理,这会造成自调用问题。<br>若同一类中的其他没有@Transactional 注解的方法内部调用有@Transactional 注解的方法,有@Transactional注解的方法的事务被忽略,不会发生回滚<br>解决方法</p></blockquote><h3 id="使用AspectJ取代Spring-AOP代理"><a href="#使用AspectJ取代Spring-AOP代理" class="headerlink" title="使用AspectJ取代Spring AOP代理"></a>使用AspectJ取代Spring AOP代理</h3><blockquote><p>需要将下面的 AspectJ 信息添加到 xml 配置信息</p><pre><code><tx:annotation-driven mode="aspectj" /><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /></bean><bean class="org.springframework.transaction.aspectj.AnnotationTransactionAspect"factory-method="aspectOf"> <property name="transactionManager" ref="transactionManager" /></bean></code></pre></blockquote><h3 id="使用手动获取Spring-Bean对象"><a href="#使用手动获取Spring-Bean对象" class="headerlink" title="使用手动获取Spring Bean对象"></a>使用手动获取Spring Bean对象</h3><blockquote><p>用SpringContextUtil.getBeanOfType()的方式,手动获取Spring生成的代理对象</p></blockquote><h2 id="Transactional不起作用的情况"><a href="#Transactional不起作用的情况" class="headerlink" title="@Transactional不起作用的情况"></a>@Transactional不起作用的情况</h2><pre><code>1.@Transactional应用的方法不是用public修饰2.事务级别设置为: TransactionDefinition.PROPAGATION_SUPPORTS TransactionDefinition.PROPAGATION_NOT_SUPPORTED TransactionDefinition.PROPAGATION_SUPPORTS</code></pre><p>参考文章:<br> <a href="https://www.ibm.com/developerworks/cn/java/j-master-spring-transactional-use/index.html" target="_blank" rel="noopener">IBM-Developer的@Transaction</a><br> <a href="https://coolfire9201207034819.iteye.com/blog/1663544" target="_blank" rel="noopener">Spring事务的五个隔离级别</a></p>]]></content>
<categories>
<category> JAVA </category>
</categories>
<tags>
<tag> JAVA </tag>
<tag> Spring </tag>
<tag> Transactional </tag>
</tags>
</entry>
<entry>
<title>Docker安装JAVA</title>
<link href="/2019/08/06/docker/docker-java/"/>
<url>/2019/08/06/docker/docker-java/</url>
<content type="html"><![CDATA[<h2 id="查找镜像"><a href="#查找镜像" class="headerlink" title="查找镜像"></a>查找镜像</h2><blockquote><p>命令:</p><pre><code>docker search java</code></pre><p>执行结果:</p><pre><code>Last login: Tue Aug 6 15:50:02 2019 from 110.87.82.244[root@vultr ~]# docker search javaNAME DESCRIPTION STARS OFFICIAL AUTOMATEDnode Node.js is a JavaScript-based platform for s… 7696 [OK] tomcat Apache Tomcat is an open source implementati… 2483 [OK] java Java is a concurrent, class-based, and objec… 1976 [OK] openjdk OpenJDK is an open-source implementation of … 1822 [OK] ghost Ghost is a free and open source blogging pla… 1011 [OK] jetty Jetty provides a Web server and javax.servle… 310 [OK] groovy Apache Groovy is a multi-faceted language fo… 74 [OK] lwieske/java-8 Oracle Java 8 Container - Full + Slim - Base… 43 [OK]nimmis/java-centos This is docker images of CentOS 7 with diffe… 42 [OK]fabric8/java-jboss-openjdk8-jdk Fabric8 Java Base Image (JBoss, OpenJDK 8) 28 [OK]frekele/java docker run --rm --name java frekele/java 12 [OK]blacklabelops/java Java Base Images. 8 [OK]bitnami/java Bitnami Java Docker Image 4 [OK]cloudbees/java-with-docker-client Java image with Docker client installed, use… 4 [OK]rightctrl/java Oracle Java 3 [OK]zoran/java10-sjre Slim Docker image based on AlpineLinux with … 2 [OK]dwolla/java Dwolla’s custom Java image 1 [OK]cfje/java-buildpack Java Buildpack CI Image 1 cfje/java-resource Java Concourse Resource 1 cfje/java-test-applications Java Test Applications CI Image 1 buildo/java8-wkhtmltopdf Java 8 + wkhtmltopdf 1 [OK]cfje/java-buildpack-memory-calculator Java Buildpack Memory Calculator CI Image 0 cfje/java-buildpack-dependency-builder Java Buildpack Dependencies Builder Image 0 thingswise/java-docker Java + dcd 0 [OK]jelastic/javaengine An image of the Java Engine server maintaine… 0 </code></pre></blockquote><h2 id="下载镜像"><a href="#下载镜像" class="headerlink" title="下载镜像"></a>下载镜像</h2><blockquote><p>我们选择第四个oracle提供的java,使用命令进行下载</p><pre><code>docker pull java</code></pre><p>执行结果:</p><pre><code>[root@vultr ~]# docker pull javaUsing default tag: latestlatest: Pulling from library/java5040bd298390: Pull complete fce5728aad85: Pull complete 76610ec20bf5: Pull complete 60170fec2151: Pull complete e98f73de8f0d: Pull complete 11f7af24ed9c: Pull complete 49e2d6393f32: Pull complete bb9cdec9c7f3: Pull complete Digest: sha256:c1ff613e8ba25833d2e1940da0940c3824f03f802c449f3d1815a66b7f8c0e9dStatus: Downloaded newer image for java:latestdocker.io/library/java:latest</code></pre></blockquote><h2 id="查看安装的镜像"><a href="#查看安装的镜像" class="headerlink" title="查看安装的镜像"></a>查看安装的镜像</h2><pre><code>docker images</code></pre><p>执行结果:</p><pre><code>[root@vultr ~]# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEmysql latest 2151acc12881 2 weeks ago 445MBjava latest d23bdf5b1b1b 2 years ago 643MB</code></pre><h2 id="启动容器"><a href="#启动容器" class="headerlink" title="启动容器"></a>启动容器</h2><blockquote><p>创建一个运行状态的容器</p></blockquote><pre><code>docker run -it --name myjava java bash</code></pre><pre><code>参数: -it: 运行的时候启动一个交互界面 --name: 给容器命名一个名字 bash: 用bash的形式运行这个容器</code></pre><p>运行结果:</p><pre><code>[root@vultr ~]# docker run -it --name myjava java bashroot@c1084f446259:/#</code></pre><blockquote><p>我们采用java -version 来验证java容器是否安装成</p><pre><code>root@c1084f446259:/# java -versionopenjdk version "1.8.0_111"OpenJDK Runtime Environment (build 1.8.0_111-8u111-b14-2~bpo8+1-b14)OpenJDK 64-Bit Server VM (build 25.111-b14, mixed mode)root@c1084f446259:/# </code></pre><p>到这里我们的java容器就创建成功了!!!</p></blockquote>]]></content>
<categories>
<category> Docker </category>
</categories>
<tags>
<tag> Docker </tag>
<tag> JAVA </tag>
</tags>
</entry>
<entry>
<title>Docker安装Mysql</title>
<link href="/2019/08/06/docker/docker-mysql/"/>
<url>/2019/08/06/docker/docker-mysql/</url>
<content type="html"><![CDATA[<h2 id="查找镜像"><a href="#查找镜像" class="headerlink" title="查找镜像"></a>查找镜像</h2><pre><code>docker search mysql</code></pre><h2 id="下载镜像"><a href="#下载镜像" class="headerlink" title="下载镜像"></a>下载镜像</h2><pre><code>docker pull mysql</code></pre><h2 id="查看安装的镜像"><a href="#查看安装的镜像" class="headerlink" title="查看安装的镜像"></a>查看安装的镜像</h2><pre><code>docker images</code></pre><h2 id="创建容器"><a href="#创建容器" class="headerlink" title="创建容器"></a>创建容器</h2><pre><code>docker run --name some-mysql -p 3307:3306 -e MYSQL_ROOT_PASSWORD=Wsk1234.. -e MYSQL_DATABASE=renren-fast -d mysql:latest</code></pre><p>参数:</p><pre><code>--name 给容器取个名称-p 端口映射,把docker内部的3306端口映射到主机的3307端口-e mysql环境参数 更详情的参考 https://hub.docker.com/_/mysql-d 在后台运行MYSQL_ROOT_PASSWORD 数据库密码MYSQL_DATABASE 初始化一个数据库</code></pre><h2 id="远程连接"><a href="#远程连接" class="headerlink" title="远程连接"></a>远程连接</h2><blockquote><p>当前的新建出来的数据库还无法远程连接,要进行登录到mysql中进行修改配置</p></blockquote><h3 id="进入容器"><a href="#进入容器" class="headerlink" title="进入容器"></a>进入容器</h3><pre><code>docker exec -it 0abb bash</code></pre><blockquote><p>oabb 指的是容器的id(不用全写,只要前缀能唯一确定的mysql容器的id即可),容器id可以通过<br>docker images 进行查看</p></blockquote><h3 id="登录mysql"><a href="#登录mysql" class="headerlink" title="登录mysql"></a>登录mysql</h3><blockquote><p>进入容器后,通过mysql命令进行登录后进行修改配置</p><pre><code>root@0abbaf97c7d6:/# mysql -uroot -p</code></pre></blockquote><h3 id="修改配置"><a href="#修改配置" class="headerlink" title="修改配置"></a>修改配置</h3><blockquote><p>mysql5.0版本用以下命令</p><pre><code>GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'password' WITH GRANT OPTION;</code></pre></blockquote><blockquote><p>mysql8.0版本用以下命令</p></blockquote><pre><code>use mysql;update user set host='%' where user='root';GRANT ALL ON *.* TO 'root'@'%';ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'Zr12345..';#语句生效FLUSH PRIVILEGES;</code></pre><blockquote><p>用mysql8.0版本的时候,如果遇到一下情况</p><pre><code>ERROR 1062 (23000): Duplicate entry '%-root' for key 'PRIMARY'</code></pre><p>说明use表中的root用户有两条记录,删掉限权是本地的就可以了</p><pre><code>delete from user where user='root' and host='localhost';</code></pre></blockquote>]]></content>
<categories>
<category> Docker </category>
</categories>
<tags>
<tag> Docker </tag>
<tag> Mysql </tag>
</tags>
</entry>
<entry>
<title>Docker入门</title>
<link href="/2019/08/05/docker/docker-deploy/"/>
<url>/2019/08/05/docker/docker-deploy/</url>
<content type="html"><![CDATA[<h2 id="1-安装Docker"><a href="#1-安装Docker" class="headerlink" title="1.安装Docker"></a>1.安装Docker</h2><pre><code> curl -sSL https://get.docker.com/ | sh </code></pre><h2 id="2-启动Docker"><a href="#2-启动Docker" class="headerlink" title="2.启动Docker"></a>2.启动Docker</h2><pre><code>service docker start </code></pre><blockquote><p>查看docker版本信息 </p></blockquote><pre><code>docker version</code></pre><h2 id="3-镜像"><a href="#3-镜像" class="headerlink" title="3.镜像"></a>3.镜像</h2><blockquote><p>docker中的镜像就像我们平时下载软件的安装包一样,或者说是exe可执行文件,<br>我们可以通过查找镜像,来进行下载</p></blockquote><h3 id="查找镜像"><a href="#查找镜像" class="headerlink" title="查找镜像"></a>查找镜像</h3><pre><code>docker search 镜像名称如:docker search java</code></pre><h3 id="下载镜像"><a href="#下载镜像" class="headerlink" title="下载镜像"></a>下载镜像</h3><pre><code>docker pull 镜像名称如:docker pull java</code></pre><h3 id="查看镜像"><a href="#查看镜像" class="headerlink" title="查看镜像"></a>查看镜像</h3><pre><code>docker image ls 或者 docker images</code></pre><h3 id="删除镜像"><a href="#删除镜像" class="headerlink" title="删除镜像"></a>删除镜像</h3><pre><code>docker image rm fce289e99eb9强制删除docker rmi -f fce289e99eb9</code></pre><h2 id="4-容器"><a href="#4-容器" class="headerlink" title="4.容器"></a>4.容器</h2><blockquote><p>我们下载可执行文件之后,要通过命令去启动他,才可以使用这个软件,<br>我们容器就相当于启动后的软件,我们才能再这个软件上进行操作</p></blockquote><h3 id="启动容器"><a href="#启动容器" class="headerlink" title="启动容器"></a>启动容器</h3><pre><code>docker run -d -p 8080:80 hub.c.163.com/library/nginx </code></pre><p>参数: </p><pre><code>-d 后台运行-p 端口映射,把docker的80端口映射到主机的8080端口上-v 目录映射 -v /usr/nginx/:/etc/home 把docker的/etc/home映射到/usr/nginx目录</code></pre><h3 id="查看容器状态"><a href="#查看容器状态" class="headerlink" title="查看容器状态"></a>查看容器状态</h3><pre><code>docker ps -a</code></pre><h3 id="进入容器"><a href="#进入容器" class="headerlink" title="进入容器"></a>进入容器</h3><pre><code>docker exec -it 69d1 bash或者docker attach 69d1</code></pre><h3 id="暂停容器"><a href="#暂停容器" class="headerlink" title="暂停容器"></a>暂停容器</h3><pre><code>docker pause myjava</code></pre><h3 id="恢复容器运行"><a href="#恢复容器运行" class="headerlink" title="恢复容器运行"></a>恢复容器运行</h3><pre><code>docker unpause myjava</code></pre><h3 id="停止容器"><a href="#停止容器" class="headerlink" title="停止容器"></a>停止容器</h3><pre><code>docker stop myjava</code></pre><h3 id="恢复容器运行-1"><a href="#恢复容器运行-1" class="headerlink" title="恢复容器运行"></a>恢复容器运行</h3><pre><code>docker start -i myjava</code></pre><p>注意:删除容器之前需要先停止容器的运行</p><h3 id="退出容器"><a href="#退出容器" class="headerlink" title="退出容器"></a>退出容器</h3><blockquote><p>用命令<code>exit</code>进行容器退出<br>用<code>exec</code>命令进入的退出后容器还在后台运行<br>用<code>attach</code>命令进入的退出后,容器就停止运行了</p></blockquote><h3 id="容器导出"><a href="#容器导出" class="headerlink" title="容器导出"></a>容器导出</h3><blockquote><p>使用命令<code>docker save 镜像名称 > 文件保存的位置</code> 进行容器的导出,例如</p><pre><code>docker save java > /home/java.tar.gz</code></pre></blockquote><h3 id="容器导入"><a href="#容器导入" class="headerlink" title="容器导入"></a>容器导入</h3><blockquote><p>使用命令<code>docker load < 文件</code> 进行容器的导出,例如</p><pre><code>docker load < /home/java.tar.gz</code></pre></blockquote>]]></content>
<categories>
<category> Docker </category>
</categories>
<tags>
<tag> Docker </tag>
</tags>
</entry>
<entry>
<title>sqlmap 常用命令</title>
<link href="/2019/08/02/ctf/sqlmap/sqlmap-zero/"/>
<url>/2019/08/02/ctf/sqlmap/sqlmap-zero/</url>
<content type="html"><![CDATA[<h2 id="输出等级-V"><a href="#输出等级-V" class="headerlink" title="输出等级 V"></a>输出等级 V</h2><blockquote><p>V这个命令分为7个等级,不同的等级在控制台输出的内容不一样</p><pre><code> 0:只显示 Python 的 tracebacks 信息、错误信息 [ERROR] 和关键信息 [CRITICAL]; 1:同时显示普通信息 [INFO] 和警告信息 [WARNING]; 2:同时显示调试信息 [DEBUG]; 3:同时显示注入使用的攻击荷载; 4:同时显示 HTTP 请求; 5:同时显示 HTTP 响应头; 6:同时显示 HTTP 响应体。</code></pre><p>初学者建议指定等级为3,这样会显示payload,便于学习</p></blockquote><h2 id="指定目标-U"><a href="#指定目标-U" class="headerlink" title="指定目标 U"></a>指定目标 U</h2><h2 id="列库-dbs"><a href="#列库-dbs" class="headerlink" title="列库 dbs"></a>列库 dbs</h2><h2 id="列表-tables"><a href="#列表-tables" class="headerlink" title="列表 tables"></a>列表 tables</h2><h2 id="列表中的字段-columns"><a href="#列表中的字段-columns" class="headerlink" title="列表中的字段 columns"></a>列表中的字段 columns</h2><h2 id="线程数-–threads"><a href="#线程数-–threads" class="headerlink" title="线程数 –threads"></a>线程数 –threads</h2>]]></content>
<categories>
<category> CTF </category>
</categories>
<tags>
<tag> sqlmap </tag>
</tags>
</entry>
<entry>
<title>CTF第二题-Xss漏洞</title>
<link href="/2019/07/29/ctf/xss/xss-one/"/>
<url>/2019/07/29/ctf/xss/xss-one/</url>
<content type="html"><![CDATA[<h2 id="xss的类型"><a href="#xss的类型" class="headerlink" title="xss的类型"></a>xss的类型</h2><p> xss漏洞的类型分为3种:</p><h3 id="反射型XSS"><a href="#反射型XSS" class="headerlink" title="反射型XSS"></a>反射型XSS</h3><blockquote><p>恶意代码并没有保存在目标网站,通过引诱用户点击一个链接到目标网站的恶意链接来实施攻击的。</p></blockquote><h3 id="存储型XSS"><a href="#存储型XSS" class="headerlink" title="存储型XSS"></a>存储型XSS</h3><blockquote><p>把恶意的JavaScript,Html代码存储在目标网站的数据库上,正常都是通过评论,留言等方式。</p></blockquote><h3 id="DOM型-XSS"><a href="#DOM型-XSS" class="headerlink" title="DOM型 XSS"></a>DOM型 XSS</h3><blockquote><p>利用DOM标签的属性,来触发JavaScript的恶意代码,例如</p><pre><code> <img src="" onerror="alert(1)"></img></code></pre></blockquote><p>本题总共有4个flag </p><blockquote><p>第一个flag 在page的Title中,存在存储型XSS,我们将JavaScript代码填入title中,<br>会显示弹出框,返回主界面的时候就会发现flag。</p><pre><code> <script>alert(1)</script></code></pre></blockquote><blockquote><p>第二个flag是属于反射型XSS,存在edit编辑界面,在参数后面加个空格 ‘ 会获取到我们的flag。</p><pre><code> 34.94.3.143/05bde5b27b/page/edit/1 '</code></pre></blockquote><blockquote><p>第三个flag是属于DOM型XSS,存在了body中,我们在body中新增一句DOM型XSS代码,查看源代码就会发现我们的dom上就出现了第三个flag。</p><pre><code> <img src="" onerror="alert(1)"></img></code></pre></blockquote><blockquote><p>第四个flag是属于越权漏洞,我们在新增界面的时候回发现id是从8开的,中间的3,4,5,6,7是无法访问的,会有个界面是403返回码,<br>我们可以尝试着从编辑界面进去看看,结果又找到了一个新的flag。</p></blockquote>]]></content>
<categories>
<category> CTF </category>
</categories>
<tags>
<tag> CTF </tag>
<tag> XSS漏洞 </tag>
</tags>
</entry>
<entry>
<title>Hacker101-sql注入入门</title>
<link href="/2019/07/28/ctf/sqlmap/sqlmap-one/"/>
<url>/2019/07/28/ctf/sqlmap/sqlmap-one/</url>
<content type="html"><![CDATA[<p>Hacker101中的第三题Micro-CMS v2主要考验的sql注入的问题 </p><h2 id="sql注入"><a href="#sql注入" class="headerlink" title="sql注入"></a>sql注入</h2><blockquote><p>本题创建网页和编辑网页的时候都会提示限权问题,跳转到登录界面,所以我们只能从登录的入口进行入手<br>我们使用burpSuite工具和sqlmap工具进行测试</p></blockquote><h3 id="使用burpSuite工具"><a href="#使用burpSuite工具" class="headerlink" title="使用burpSuite工具"></a>使用burpSuite工具</h3><blockquote><p>在做好监听本地请求的情况下,发送登录请求<br><img src="/medias/loading.svg" data-original="/medias/ctf/3/request-content.png" alt="拦截登录请求图片"><br>把请求的信息保存到sql.txt文本中</p></blockquote><h3 id="使用sqlmap工具"><a href="#使用sqlmap工具" class="headerlink" title="使用sqlmap工具"></a>使用sqlmap工具</h3><p>使用以下命令进行漏洞扫描</p><pre><code> python sqlmap.py -r D:/Study/CTF/SqlMap/workspace/sql.txt --dbs</code></pre><p><img src="/medias/loading.svg" data-original="/medias/ctf/3/sql-content.png" alt="sql.txt内容"><br><img src="/medias/loading.svg" data-original="/medias/ctf/3/injection-content.png" alt="扫描出来的结果"><br>使用命令把数据库下载到本地</p><pre><code> python sqlmap.py -r D:/Study/CTF/SqlMap/workspace/sql.txt --dbs --dump</code></pre><p><img src="/medias/loading.svg" data-original="/medias/ctf/3/injection-content-dump.png" alt="下载数据库到本地"></p><p>这样数据库的内容取到了,我们也同时拿到了两个flag</p><h2 id="请求方法"><a href="#请求方法" class="headerlink" title="请求方法"></a>请求方法</h2><blockquote><p>使用burpSuite进行拦截编辑网页请求,把请求添加到repeater上,尝试修改用其他方法进行请求数据</p></blockquote><p><img src="/medias/loading.svg" data-original="/medias/ctf/3/request-edit-content.png" alt="拦截编辑请求"> </p><p><img src="/medias/loading.svg" data-original="/medias/ctf/3/request-edit-repeater-content.png" alt="修改请求的方法"><br>点击go进行重新请求,然后另外一个flag也就出来了。</p>]]></content>
<categories>
<category> CTF </category>
</categories>
<tags>
<tag> CTF </tag>
<tag> sql注入 </tag>
</tags>
</entry>
<entry>
<title>MarkDown常用的语法</title>
<link href="/2019/07/26/study-markdown/"/>
<url>/2019/07/26/study-markdown/</url>
<content type="html"><![CDATA[<h2 id="标题"><a href="#标题" class="headerlink" title="标题"></a>标题</h2><blockquote><p>用#号来进行创建标题</p></blockquote><pre><code># 一级标题## ##二级标题### ###三级标题 </code></pre><h2 id="列表"><a href="#列表" class="headerlink" title="列表"></a>列表</h2><blockquote><p>使用 * - + 三种字符来进行展示列表</p></blockquote><pre><code>例子: * 列表1 - 列表2 + 列表3</code></pre><blockquote><p>效果</p></blockquote><ul><li>列表1</li></ul><ul><li>列表2</li></ul><ul><li>列表3</li></ul><h2 id="代码块"><a href="#代码块" class="headerlink" title="代码块"></a>代码块</h2><pre><code>使用``` 内容 ```的形式来表达</code></pre><h2 id="强调"><a href="#强调" class="headerlink" title="强调"></a>强调</h2><p>在Markdown中,可以使用 * 和 _ 来表示斜体和加粗。</p><pre><code>例子: **Coding,让开发更简单** __Coding,让开发更简单__</code></pre><p>效果: </p><blockquote><p><strong>Coding,让开发更简单</strong><br><strong>Coding,让开发更简单</strong></p></blockquote><h2 id="缩进"><a href="#缩进" class="headerlink" title="缩进"></a>缩进</h2><blockquote><p>使用>符号进行缩进</p><pre><code>例子:使用>进行缩进</code></pre></blockquote><h2 id="表格"><a href="#表格" class="headerlink" title="表格"></a>表格</h2><h3 id="普通表格"><a href="#普通表格" class="headerlink" title="普通表格"></a>普通表格</h3><pre><code>姓名|技能|排行--|:--:|--:刘备|哭|大哥关羽|打|二哥张飞|骂|三弟</code></pre><p>效果: </p><table><thead><tr><th>姓名</th><th align="center">技能</th><th align="right">排行</th></tr></thead><tbody><tr><td>刘备</td><td align="center">哭</td><td align="right">大哥</td></tr><tr><td>关羽</td><td align="center">打</td><td align="right">二哥</td></tr><tr><td>张飞</td><td align="center">骂</td><td align="right">三弟</td></tr></tbody></table><h3 id="表格居中"><a href="#表格居中" class="headerlink" title="表格居中"></a>表格居中</h3><pre><code>姓名 | 技能 | 排行:----------- | :-----------: | -----------:刘备|哭|大哥关羽|打|二哥张飞|骂|三弟</code></pre><p>效果:</p><table><thead><tr><th align="center">姓名</th><th align="center">技能</th><th align="center">排行</th></tr></thead><tbody><tr><td align="center">刘备</td><td align="center">哭</td><td align="center">大哥</td></tr><tr><td align="center">关羽</td><td align="center">打</td><td align="center">二哥</td></tr><tr><td align="center">张飞</td><td align="center">骂</td><td align="center">三弟</td></tr></tbody></table><blockquote><p>说明:<br><code>:--表示居左</code><br><code>:--: 表示居中</code><br><code>--: 表示居右</code></p></blockquote><h2 id="图片"><a href="#图片" class="headerlink" title="图片"></a>图片</h2><blockquote><p>使用![Alt text][id]的方式来进行设置图片信息 </p></blockquote><pre><code>例子: ![Alt text](/path/to/img.jpg) 或 ![Alt text](/path/to/img.jpg "Optional title")</code></pre><p><img src="/medias/loading.svg" data-original="https://cbu01.alicdn.com/img/ibank/2018/334/469/9053964433_533245986.220x220xz.jpg" alt="图片1"></p><p><img src="/medias/loading.svg" data-original="https://cbu01.alicdn.com/img/ibank/2019/363/937/10893739363_1518424921.220x220xz.jpg,%22%E6%A0%87%E9%A2%98%22" alt="图片2"></p><blockquote><p>修改图片大小</p></blockquote><pre><code> ![test image size](url){:class="img-responsive"} ![test image size](url){:height="50%" width="50%"} ![test image size](url){:height="100px" width="400px"}</code></pre><blockquote><p>效果:</p></blockquote><p><img src="/medias/loading.svg" data-original="https://cbu01.alicdn.com/img/ibank/2018/334/469/9053964433_533245986.220x220xz.jpg" alt="图片1"> {: width=”100px” height=”100px”} </p><p><img src="/medias/loading.svg" data-original="https://cbu01.alicdn.com/img/ibank/2018/334/469/9053964433_533245986.220x220xz.jpg" alt="图片1 w=500px"></p>]]></content>
<categories>
<category> 其他 </category>
</categories>
<tags>
<tag> 入门 </tag>
<tag> MarkDown </tag>
</tags>
</entry>
<entry>
<title>Hello World</title>
<link href="/2019/07/25/hello-world/"/>
<url>/2019/07/25/hello-world/</url>
<content type="html"><![CDATA[<p>Welcome to <a href="https://hexo.io/" target="_blank" rel="noopener">Hexo</a>! This is your very first post. Check <a href="https://hexo.io/docs/" target="_blank" rel="noopener">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href="https://hexo.io/docs/troubleshooting.html" target="_blank" rel="noopener">troubleshooting</a> or you can ask me on <a href="https://github.com/hexojs/hexo/issues">GitHub</a>.</p><h2 id="Quick-Start"><a href="#Quick-Start" class="headerlink" title="Quick Start"></a>Quick Start</h2><h3 id="Create-a-new-post"><a href="#Create-a-new-post" class="headerlink" title="Create a new post"></a>Create a new post</h3><pre class=" language-bash"><code class="language-bash">$ hexo new <span class="token string">"My New Post"</span></code></pre><p>More info: <a href="https://hexo.io/docs/writing.html" target="_blank" rel="noopener">Writing</a></p><h3 id="Run-server"><a href="#Run-server" class="headerlink" title="Run server"></a>Run server</h3><pre class=" language-bash"><code class="language-bash">$ hexo server</code></pre><p>More info: <a href="https://hexo.io/docs/server.html" target="_blank" rel="noopener">Server</a></p><h3 id="Generate-static-files"><a href="#Generate-static-files" class="headerlink" title="Generate static files"></a>Generate static files</h3><pre class=" language-bash"><code class="language-bash">$ hexo generate</code></pre><p>More info: <a href="https://hexo.io/docs/generating.html" target="_blank" rel="noopener">Generating</a></p><h3 id="Deploy-to-remote-sites"><a href="#Deploy-to-remote-sites" class="headerlink" title="Deploy to remote sites"></a>Deploy to remote sites</h3><pre class=" language-bash"><code class="language-bash">$ hexo deploy</code></pre><p>More info: <a href="https://hexo.io/docs/deployment.html" target="_blank" rel="noopener">Deployment</a></p>]]></content>
<categories>
<category> JAVA </category>
</categories>
<tags>
<tag> 搭建 </tag>
</tags>
</entry>
</search>