-
Notifications
You must be signed in to change notification settings - Fork 0
/
search.xml
737 lines (737 loc) · 255 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
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title><![CDATA[Maven及其核心概念]]></title>
<url>%2F2020%2F04%2F01%2FMaven%2FMaven%E5%8F%8A%E5%85%B6%E6%A0%B8%E5%BF%83%E6%A6%82%E5%BF%B5%2F</url>
<content type="text"><![CDATA[很早的时候接触到Maven,很多人都称呼其为”构建工具”,过程中也是描述它是把源代码搞成一个发布的“构件”的东西,但是Maven它确实一个更复杂的东西“项目管理工具”。 在刚开始工作的时候最新接触到的打包工具是Ant,如果你接触过Ant你会发现Ant这种构件工具比较关注预处理,编译,打包,测试和分发等功能,而且需要写复杂的脚本,Maven可以说是提供了这些工具功能并具备其他的功能,Maven还可以生成报告,生成 Web 站点,虽然一直没有使用过用它维护站点,一般我都是使用Hexo、Jekyll或者现在刚换的gitbook等工具生成站点,这并不影响Maven成为一个构建的工具,它仅仅需要输入简单的命令就可以完成像是Ant那样写一堆的脚本完成的那些繁琐的工作,像是Package、install等,这些都得益于它抽象的生命周期,这些简单的生命周期消除了构建的重复并能很好的标准化构建过程,我还记得当时第一次知道Maven这个东西的时候就被它简单一致的构建概念深深吸引,其实最重要的感觉是“我靠,这玩意不用花太多的时间学习就能用”。除了上面说的它是一个优秀的构建工具外,它也是一个优秀的依赖管理工具及项目信息管理工具,它提供了中央仓库可以帮助项目构建过程中自动下载依赖的jar包等,随着各个组织和公司开放的私服或者自己搭建私服依赖下载变得也越来越简单,如果对Nexux私服安装部署感兴趣的话可以参考Maven私服-NexusMaven同样也是一个跨平台的工具,或许很多人觉得跨平台是现在的标配,但是的确很多工具是没有办法跨平台使用的,Maven跨平台其实也是得益于基于JAVA开发的原因,在各个平台上操作命令统一,这样也是它能迅速推广流行的原因之一。 除了上面我们说的这些它的硬性的特性之外,使用Maven管理项目另外体会到的就是它约定优于配置(ConventionOver Configuration)的思想,它约定了项目目录结构、测试用例命名方式等,使用它只需要遵循这些成熟的规则即可,使用Maven还能享受一个额外的好处,即Maven对于项目目录结构、测试用例命名方式等内容都有既定的规则,只要遵循了这些成熟的规则即可,这就减少了我们拿到一个新的项目之后还要重新熟悉项目的目录结构构建方式等,不过约定优于配置肯定不是约定不允许配置,Maven很多默认行为还是可配置的,例如项目源码的资源文件的位置可以被自定义,JAR 文件的名字可以被自定义,在开发自定义插件的时候,几乎任何行为可以被裁剪以满足你特定的环境需求,如果你不想遵循约定,Maven 也会允许你自定义默认值来适应你的需求,但是项目开发过程中我一般不会允许项目中的成员开发中,或者其他人因为引入某些东西去随意更改项目的这些默认行为,如果滥用其允许更改的特性,那项目将慢慢变得面目全非。 那我们下面从对Maven安装目录进行介绍开始再简要介绍一下Maven的核心概念 一、maven的安装目录结构12345678910111213binbootconflibLICENSE.txtNOTICE.txtREADME.txt Bin该目录包含了mvn运行的脚本,这些脚本用来配置Java命令,准备好classpath和相关的Java系统属性,然后执行Java命令。其中mvn是基于UNIX平台的shell脚本,mvn.bat是基于Windows平台的bat脚本。在命令行输入任何一条mvn命令时,实际上就是在调用这些脚本。该目录还包含了mvnDebug和mvnDebug.bat两个文件,同样,前者是UNIX平台的shell脚本,后者是windows的bat脚本。那么mvn和mvnDebug有什么区别和关系呢?打开文件我们就可以看到,两者基本是一样的,只是mvnDebug多了一条MAVEN_DEBUG_OPTS配置,作用就是在运行Maven时开启debug,以便调试Maven本身。此外,该目录还包含m2.conf文件,这是classworlds的配置文件。 Boot该目录只包含一个文件,以maven 3.0为例,该文件为plexus-classworlds-2.2.3.jar。plexus-classworlds是一个类加载器框架,相对于默认的java类加载器,它提供了更丰富的语法以方便配置,Maven使用该框架加载自己的类库。更多关于classworlds的信息请参考http://classworlds.codehaus.org/。对于一般的Maven用户来说,不必关心该文件。 Conf该目录包含了一个非常重要的文件settings.xml。直接修改该文件,就能在机器上全局地定制Maven的行为。一般情况下,我们更偏向于复制该文件至~/.m2/目录下(这里~表示用户目录),然后修改该文件,在用户范围定制Maven的行为。 Lib该目录包含了所有Maven运行时需要的Java类库,Maven本身是分模块开发的,因此用户能看到诸如mavn-core-3.0.jar、maven-model-3.0.jar之类的文件,此外这里还包含一些Maven用到的第三方依赖如common-cli-1.2.jar、google-collection-1.0.jar等等。可以说,这个lib目录就是真正的Maven。关于该文件,还有一点值得一提的是,用户可以在这个目录中找到Maven内置的超级POM, 其他: LICENSE.txt记录了Maven使用的软件许可证Apache License Version 2.0; NOTICE.txt记录了Maven包含的第三方软件;而README.txt则包含了Maven的简要介绍,包括安装需求及如何安装的简要指令等等。 二、Maven生命周期Maven的生命周期是对所有的构建过程进行抽象和统一。Maven的生命周期是抽象的,这意味着生命周期本身不做任何实际的工作,生命周期只是定义了一系列的阶段,并确定这些阶段的执行顺序。而在执行这些阶段时,实际的工作还是由插件来完成的。 上面我们也说到过,生命周期包含一些阶段,这些阶段是有顺序的,并且后面的阶段依赖于前面的阶段,用户和Maven最直接的交互方式就是调用这些生命周期阶段。 clean生命周期clean生命周期的目的是清理项目,它包含三个阶段: pre-clean 执行一些清理前需要完成的工作。 clean 清理上一次构建生成的文件。 post-clean 执行一些清理后需要完成的工作。 default生命周期default生命周期定义了真正构件时所需要执行的所有步骤,它是生命周期中最核心的部分,它包含的阶段如下: validate 验证项目是否正确和所有需要的相关资源是否可用 initialize 初始化构建 generate-sources process-sources 处理源代码 generate-resources process-resources 处理项目主资源文件。对src/main/resources目录的内容进行变量替换等工作后,复制到项目输出的主classpath目录中。 compile 编译项目的主源代码 process-classes generate-test-sources process-test-sources 处理项目测试资源文件 generate-test-resources process-test-resources 处理测试的资源文件 test-compile 编译项目的测试代码 process-test-classes test 使用单元测试框架运行测试,测试代码不会被打包或部署 prepare-package 做好打包的准备 package 接受编译好的代码,打包成可发布的格式 pre-integration-test integration-test postintegration-test verify install 将包安装到Maven本地仓库,供本地其他Maven项目使用 deploy 将最终的包复制到远程仓库,供其他开发人员和Maven项目使用 site生命周期site生命周期的目的是建立和发布项目站点,Maven能够基于POM所包含的信息,自动生成一个友好的站点,方便团队交流和发布项目信息。该生命周期包含如下阶段: pre-site 执行一些在生成项目站点之前需要完成的工作 site 生成项目站点文档 post-site 执行一些在生成项目站点之后需要完成的工作 site-deploy 将生成的项目站点发布到服务器上 用户在mvn命令后可以指定三个生命周期中的任何阶段,则Maven会按以下逻辑执行:首先会得到该阶段所属生命周期,从该生命周期中的第一个阶段开始按顺序执行,直至该阶段本身。例如执行mvnclean命令会依次执行clean生命周期中的pre-clean阶段及clean阶段。mvn命令后可以指定多个阶段,Maven会按照输入的顺序依次执行,每次执行都会按照之前描述的逻辑执行 三、projectobject Model & Artifact & Repositoriesprojectobject Modelpom是一个xml,是maven工作的基础,执行任务时,maven会到项目根目录下读取pom.xml获得需要的配置信息pom文件中包含了项目的信息和maven build项目所需的配置信息,通常有项目信息(如版本、成员)、项目的依赖、插件和goal、build选项等等pom是可以继承的,通常对于一个大型的项目或是多个module的情况,子模块的pom需要指定父模块的pom Artifact & RepositoriesArtifact:一个项目将要产生的文件,可以是jar文件,源文件,二进制文件,war文件,甚至是pomRepositories是用来存储Artifact的Repositories分为本地仓库和远程仓库,远程仓库是指远程服务器上用于存储Artifact的仓库,本地仓库是指本机存储Artifact的仓库 四、Maven坐标Maven坐标是一组可以惟一标识构件的三元组值 groupId代表构件的实体或组织例如:org.inspur.loushang,groupId一般遵循包路径的命名规范 artifactId 实际的构件的名称,例如framework version,对应项目的版本号 packaging 定义Maven项目打包的方式,首先,打包方式通常与所生成构件的文件扩展名对应,如上例中的packaging为jar,最终的文件名为my-app-0.0.1-SNAPSHOT.jar。也可以打包成war, ear等。当不定义packaging的时候,Maven 会使用默认值jar classifier: 该元素用来帮助定义构建输出的一些附件。附属构件与主构件对应,如上例中的主构件为my-app-0.0.1-SNAPSHOT.jar,该项目可能还会通过一些插件生成如my-app-0.0.1-SNAPSHOT-javadoc.jar,my-app-0.0.1-SNAPSHOT-sources.jar, 这样附属构件也就拥有了自己唯一的坐标 五、Maven仓库如果说仓库的话必然需要说到使用JAR包,我们在pom.mxl通过jar包的坐标即通过groupId,artifactId,以及version确定一个唯一的jar包,如下: 1234567891011<dependency> <groupId>org.limingming</groupId> <artifactId>test</artifactId> <version>2.0.0-SNAPSHOT</version> <!-- scope是声明这个jar包在生命周期中生效的范围。--> <scope>compile</scope></dependency> 当项目构建过程中,如果我们依赖上面的jar包,会先去本地仓库查看是否有该资源,如果有的话,判断版本是否正确,如果一切都没问题则直接使用;否则会去中央仓库或者其他仓库中去寻找jar包,如果配置的仓库中有则会下载到本地并进行使用。 在Maven中会涉及到几种概念: 1 工作空间,即我们的项目工程,这里面可能会放着pom.xml文件,这个pom.xml就是maven的配置文件 2 本地仓库,本地仓库用于存放jar包,其实Jar包并不是直接放入工作空间的,它是存放在本地仓库,然后在执行发布打包的时候,添加依赖路径 3 私库:私库是使用者自己搭建的maven仓库,用于缓解频繁从外网下载jar包资源的压力。而且使用私库作为缓存层,也相对安全一些。]]></content>
<categories>
<category>Maven</category>
</categories>
<tags>
<tag>介绍</tag>
<tag>仓库</tag>
<tag>Maven</tag>
<tag>生命周期</tag>
<tag>坐标</tag>
</tags>
</entry>
<entry>
<title><![CDATA[使用Maven常见问题]]></title>
<url>%2F2020%2F03%2F31%2FMaven%2F%E4%BD%BF%E7%94%A8Maven%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%2F</url>
<content type="text"><![CDATA[仓库存在jar包但依旧提示无法下载最近服务器的迁移,把原来服务器的地址都更改了,所以私服的地址也改动了,原来项目下载到本地仓库的包,但是重新构建过程中竟然发现依然要提示下载,本地仓库里面明明有包,为什么还要下载? 解决办法:去maven仓库包下面你会发现有_remote.repositories文件,下载不下来问题就是因为这个文件导致的。你可能会发现nexus=的信息在这个文件中,这个文件中已经连接不上原来的nexus私服了,所有会报错依然会生成lastUpdatedw文件,如果你可以从新的服务地址中下载,你可以选择删除掉这个包,重新下载,如果不能的话可以选择改掉nexus=的信息,改成可以连接的地址,那它就不会重新下载了,例如改成 central=,这代表是从中央仓库进行下载的。 下载异常导致的错误12was cached in the local repository, resolution will not be reattempted until the update interval of central has elapsed or updates are forced -> [Help 1][ERROR] 或许你遇到过这个错误,我看到这个错误的时候以为我配置的私服无法连接网络,其实并不是私服的问题,我删除LastUpdate文件,但是有时候好使有时候不好使,可能是因为开着eclipse的原因吧,刚删除可能它自己有请求有生成了一个。 所以采取了一个简单的方法: 1mvn -U clean install 就会重新下载了,或者也可以修改配置使用私服的地方: 1234567891011121314151617<profiles> <profile> ... <repositories> <repository> <id>myRepo</id> <name>My Repository</name> <releases> <enabled>false</enabled> <updatePolicy>always</updatePolicy> <checksumPolicy>warn</checksumPolicy> </releases> </repository> </repositories> ... </profile> </profiles> 清除LastUpdated脚本上面提到如果因为网络或者其他的原因,没有下载成功或者下载被中断,将会出现一个LastUpdated的文件,这个时候,就算网络好了,也不能正常使用这个构件。可以使用脚本进行批量清除: 在linux系统上可以切换到仓库的目录下执行: 1find ./ -name "*.lastUpdated" -exec grep -q "Could not transfer" {} \; -print -exec rm {} \; 在windows系统下可以保存到后缀为bat的文件中修改仓库的目录执行:12345678rem 这里写你的仓库路径set REPOSITORY_PATH=E:\storage\maven\repositoryrem 正在搜索...for /f "delims=" %%i in ('dir /b /s "%REPOSITORY_PATH%\*lastUpdated*"') do ( del /s /q %%i)rem 搜索完毕pause 执行上面的命令后删掉本地仓库的.lastupdate文件,重新构建,必要的情况可以开vpn下载。某些一直报错的jar包,校验MD5,不对的请删掉重新构建 错误总结Maven项目导入eclipse中很多时候都出现报错的情况,出错的原因大致可以分为下列几种: JDK版本不一致 网络问题无法下载,可以尝试开vpn下载 私有jar包 多个WEB模块打包实现问题在项目开发中可能会遇到这种那种的maven问题,尤其是在企业原有的开发模式转换到mavne方式进行开发的时候,以下就列出在企业项目拆分的过程中总结的maven多个子web模块的整合遇到的问题。 在各个子模块中可以添加,注意relativePath,在子模块中设置,可以在项目构建时先在本地项目中查找,使用../.. ,然后在去仓库和私服查找父pom: 123456<parent> <groupId>com.founder.fix.fixflow</groupId> <artifactId>fixflow-root</artifactId> <version>5.0</version> <relativePath>../..</relativePath> </parent> 在依赖中添加对另一个web模块打成jar包的依赖,使用war,如下: 123456<dependency> <groupId>org.loushang.framework</groupId> <artifactId>loushang-framework</artifactId> <version>${loushang-framework.version}</version> <type>war</type></dependency> 可以声明多个依赖; build中添加相关设置,如果不添加的话可以设置是否:123456789101112131415161718192021222324<build> <finalName>lousing</finalName> <plugins> <!-- 合并多个war --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <configuration> <packagingExcludes>WEB-INF/web.xml</packagingExcludes> < overlays> <!-- 声明合并war --> <overlay> <groupId>com.founder.fix.fixflow</groupId> <artifactId>fixflow-webapp-taskcenter</artifactId> <excludes> <!-- 声明排除war包中的部分 --> <exclude>*/web.xml,WEB-INF/lib/*</exclude> </excludes> </overlay> </overlays> </configuration> </plugin> </plugins> </build> 注意在被合并的子模块没有web.xml部分,要声明: 1234567891011121314151617181920212223<plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-war-plugin</artifactId><version>2.6</version><configuration> <!—- 设置将其他文件打包到war包 --><webResources><resource><directory>${basedir}/../commonFiles/jsp</directory><!-- <directory>src/main/resources</directory> --><filtering>true</filtering> <targetPath>/</targetPath></resource></webResources><!-- 解决web模块中没有web.xml报错的问题 --><failOnMissingWebXml>false</failOnMissingWebXml> <!-- 解决打包时候排除空文件不打包 --><includeEmptyDirectories>true</includeEmptyDirectories></configuration></plugin></plugins> 多WEB模块打包排除jar包建议在原有的web项目基础上拆分出了多个web项目,后台代码还是在各个web模块中,现在的需求是要合并多个web模块整合到一个war中部署。 配置建议 新建打包的web模块用以合并多个web模块项目,在pom中声明合并打包的各个模块,例如要合并A模块和B模块,如下: 123456789101112131415161718192021222324252627<dependencies><dependency><groupId>com.inspur.test</groupId><artifactId>A</artifactId><version>0.0.1-SNAPSHOT</version><type>war</type></dependency><dependency><groupId>com.inspur.test</groupId><artifactId>A</artifactId><version>0.0.1-SNAPSHOT</version><type>pom</type></dependency><dependency><groupId>com.inspur.test</groupId><artifactId>B</artifactId><version>0.0.1-SNAPSHOT</version><type>war</type></dependency><dependency><groupId>com.inspur.test</groupId><artifactId>B</artifactId><version>0.0.1-SNAPSHOT</version><type>pom</type></dependency></dependencies> 我们需要在合并打包的项目中依赖要合并的各个war包和各个模块的pom。 排除各个模块的lib:123456789101112131415161718192021222324252627282930<build><finalName>B</finalName><plugins> <!-- 合并多个war --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-war-plugin</artifactId><version>2.6</version><configuration><overlays> <!-- 声明合并war --><overlay><groupId>com.inspur.test</groupId><artifactId>A</artifactId><excludes><!-- 声明排除war包中的部分 --><exclude>WEB-INF/lib/*</exclude></excludes></overlay></overlays><overlays> <!-- 声明合并war --><overlay><groupId>com.inspur.test</groupId><artifactId>B</artifactId><excludes><!-- 声明排除war包中的部分 --><exclude>WEB-INF/lib/*</exclude></excludes></overlay></overlays></configuration></plugin></plugins></build> 直接使用JAR包方法通过Scope使用系统本地JAR包有一次由于私服出了问题,我又不想将jar包安装到本地仓库,所以想直接引用本地的jar包,所以就使用了接下来的设置。使用Dependency声明:1234567<dependency> <groupId>org.ibm</groupId> <artifactId>jms</artifactId> <version>1.0.0</version> <scope>system</scope> <systemPath>${project.basedir}/lib/jms.jar</systemPath> </dependency> 但是这也存在着一些问题,当我们打包的时候,不能把scope为system的打到war包中,我们声明了scope为system, 它使用起来和provided差不多,即此依赖由系统提供,但是与provided有点不同的是,它需要显式的使用systemPath指定lib所在的路径。 注: 正想上面说的这样有个问题是我们可以声明用到此jar包进行编译构建,但是最终的结果中不会将此jar包打包到项目中,也不会将此jar包安装到仓库里,我觉得如果非要采用这种方式进行引用构建的话,将jar包放到webapp下WEBINF下的lib文件夹中引用,这样就会将jar包构建到结果项目中了。12345<systemPath>${project.basedir}/lib/jms.jar</systemPath> ``` 正想上面说的这样有个问题是我们可以声明用到此jar包进行编译构建,但是最终的结果中不会将此jar包打包到项目中,也不会将此jar包安装到仓库里,我觉得如果非要采用这种方式进行引用构建的话,将jar包放到webapp下WEBINF下的lib文件夹中引用,这样就会将jar包构建到结果项目中了。scope的作用范围有五种: compile,缺省值,适用于所有阶段,会随着项目一起发布。provided,类似compile,期望JDK、容器或使用者会提供这个依赖。如servlet.jar。 runtime,只在运行时使用,如JDBC驱动,适用运行和测试阶段。test,只在测试时使用,用于编译和运行测试代码。不会随项目发布。system,类似provided,需要显式提供包含依赖的jar,Maven不会在Repository中查找它。1如果感兴趣可以查看下面的官网对于相关类型的解释如下: Dependency scopeis used to limit the transitivity of a dependency, and also to affect theclasspath used for various build tasks. There are 6scopes available: compileThis is the default scope, used if none is specified. Compile dependencies are available in all classpaths of a project. Furthermore, those dependencies are propagated to dependent projects.providedThis is much like compile, but indicates you expect the JDK or a container to provide the dependency at runtime. For example, when building a web application for the Java Enterprise Edition, you would set the dependency on the Servlet API and related Java EE APIs to scope provided because the web container provides those classes. This scope is only available on the compilation and test classpath, and is not transitive.runtimeThis scope indicates that the dependency is not required for compilation, but is for execution. It is in the runtime and test classpaths, but not the compile classpath.testThis scope indicates that the dependency is not required for normal use of the application, and is only available for the test compilation and execution phases. This scope is not transitive.systemThis scope is similar to provided except that you have to provide the JAR which contains it explicitly. The artifact is always available and is not looked up in a repository.import (only available in Maven 2.0.9 or later)This scope is only used on a dependency of type pom in the section. It indicates that the specified POM should be replaced with the dependencies in that POM’s section. Since they are replaced, dependencies with a scope of import do not actually participate in limiting the transitivity of a dependency.1234## 安装JAR包到本地仓库安装jar包到仓库可以使用命令进行安装 mvn install:install-file –Dfile=loushang-home-6.0.RELEASE.jar –DgroupId=org.loushang.framework –DartifactId=loushang-home –Dversion=6.0.RELEASE –Dpackaging=jar12可以替换掉里面对应参数对应的值就可以通过命令安装JAR包到本地仓库了,但是这个方法仅推进为个人使用,入托团队协作的话建议使用mvn deploy的方式将开发的jar包推到远程仓库进行协作,开发中话使用-SNAPSHOT的后缀命名构件名称;如果大家有一堆遗留的项目需要推送安装到仓库,那可以使用脚本: python脚本批量上传jar包到私服:from xml.etree.ElementTree import Element, SubElement, tostring,ElementTreeimport globimport os def mvn_script(filename): return “mvn deploy:deploy-file -DrepositoryId=open2-baidu -Durl=http://10.100.10.131:8119/nexus-2.3.0-04/content/repositories/open2-baidu -DgroupId=com.pzoom -DartifactId=”+filename[0:len(filename)-4]+” -Dversion=1.0 -Dpackaging=jar -Dfile=”+filenamedef writeDependency(filename): dependencies = Element(“dependencies”) dependency = SubElement(dependencies,”dependency”) groupId = SubElement(dependency, “groupId”) groupId.text = “com.pzoom” artifactId = SubElement(dependency, “artifactId”) artifactId.text = filename[0:len(filename)-4] version = SubElement(dependency, “version”) version.text=”1.0” ElementTree(dependencies).write(“out.xml”) files = glob.glob(‘*.jar’)for file in files: writeDependency(file) print(file) os.system(mvn_script(file)) print(‘upload success’) print(‘delete the file : ‘+file) os.remove(file) 123# 跳过测试在编译大型的项目的时候例如hadoop、ranger等项目的时候,如果执行测试可能会耗费很多时间,这时候需要跳过测试,执行命令: mvn install -DskipTests #或者执行命令:mvn install -Dmaven.test.skip=true`或者我们使用maven-surefire-plugin插件的方式配置跳过测试]]></content>
<categories>
<category>Maven</category>
</categories>
<tags>
<tag>问题</tag>
<tag>Maven</tag>
<tag>常见</tag>
<tag>汇总</tag>
</tags>
</entry>
<entry>
<title><![CDATA[wikibase安装部署]]></title>
<url>%2F2020%2F02%2F22%2FKG%2Fwikibase%E5%AE%89%E8%A3%85%E9%83%A8%E7%BD%B2%2F</url>
<content type="text"><![CDATA[在2017年最先接触到wikibase的时候是因为于工作需要的缘故,需要了解wikibase的数据结构,以至于阅读了很长时间的php源码,了解了它的运行机制等,但是脑子毕竟是一个容易遗忘的存储部件,虽然当时经过了那么漫长学习时至今日还是会遗忘,所以现在针对于wikibase相关的内容做一下记录,此篇记录主要是针对于搭建wikibase进行记录,文章最后提供了简便的方式进行部署。 前提安装MediaWikiWikibase 是 MediaWiki 的扩展扩展插件,包含两个两个扩展,所以需要先安装部署 MediaWiki。安装部署MediaWiki需要注意兼容的PHP版本,此篇文章适宜MediaWiki-1.33.0版本为例,我在Centos上安装了PHP7.0版本,但是运行MediaWiki的时候提示必须使用PHP7.3版本及以上版本,所以又重新安装了PHP7.4版本,Mysql数据库使用5.5.8+。另外Wikibase并不能兼容老版本MediaWiki,当然旧版本的Wikibase也很大可能无法与最新的MediaWiki版本兼容。所以安装部署完成MediaWiki后最后使用相应版本的Wikibase。 下载mediawiki可以下载mediawiki-1.33.0.tar.gz,如果以上的连接因为网络原因无法下载的话可以,从Git库获取: 12345git clone https://gerrit.wikimedia.org/r/mediawiki/core.git --branch REL1_33 mediawiki#发行版分支中有很多 Git 子模块,用于常用的扩展和皮肤(主分支没有这些)。 要更新子模块,请运行:cd mediawikigit submodule update --init 运行环境 1234[root@localhost ~]# php -vPHP 7.4.3 (cli) (built: Feb 18 2020 11:53:05) ( NTS )Copyright (c) The PHP GroupZend Engine v3.4.0, Copyright (c) Zend Technologies 配置apache http支持php,这里面如果没有接触过php的话安装部署可能会遇到一系列的问题,建议使用 Apache/2.4.6 (CentOS) + PHP 7.4.3 (cli)进行部署,遇到最大的问题可能就是phplib.so不生成的问题,通过yum安装php和源码编辑都会遇到这个问题,可以自行搜索一下。 部署运行环境没有问题的话就可以进行部署了,将mediawiki-1.33.0解压放到http服务站点下就可以访问了,跟着界面引导的步骤就可以安装部署了。 填写完成所有的信息后会生成LocalSettings.php文件,将文件放到mediawiki-1.33.0部署的路径下就可以了。这时候对应的Mysql数据库中已经有mediawiki运行初始化的所有的表,但是还不包含Wikibase的表(以wb_开头的表) 安装Composer使用Composer可以简单的将依赖进行全部安装,安装Composer有很多中方式不同的操作系统安装方式不同,可以自行搜索。 Mac OS x 上的用户,你可以使用 Homebrew 安装 composer: 1wget https://getcomposer.org/composer.phar Window用户可以访问网址 安装Wikibase成功安装完成MediaWiki及Composer之后,下面就是安装Wikibase了,分为四个步骤: 下载Wikibase扩展 获取依赖项 修改 LocalSettings.php 配置文件 运行维护脚本 下载Wikibase扩展为了获取和mediawiki相应的版本,建议使用git进行下载:从部署的mediawiki-1.33.0中进入 extensions 目录下:12345cd extensionsgit clone -b REL1_33 https://github.com/wikimedia/mediawiki-extensions-Wikibase.git Wikibase#注意保证git下来的项目名称为Wikibasecd Wikibasegit submodule update --init --recursive # get the dependencies using submodules 获取依赖项 拷贝mediawiki-1.33.0目录下的composer.local.json-sample并更名为composer.local.json,写入:123456789{ "extra": { "merge-plugin": { "include": [ "extensions/Wikibase/composer.json" ] } }} 从 mediawiki-1.33.0 安装的根目录选择以下三种方法中的一种方法运行:12345composer install --no-dev# if you downloaded composer.pharphp composer.phar install --no-dev# Or use dockerized version (does not require PHP or composer installed)docker run -it --rm --user $(id -u):$(id -g) -v ~/.composer:/tmp -v $(pwd):/app docker.io/composer install --no-dev 修改 LocalSettings.php 配置文件修改mediawiki-1.33.0 安装的根目录下LocalSettings.php配置文件,以下三种配置取决于你是否想启用维基库存储库、维基库客户端或者想同时启用它们。 只启用维基资源库 1234$wgEnableWikibaseRepo = true;$wgEnableWikibaseClient = false;require_once "$IP/extensions/Wikibase/repo/Wikibase.php";require_once "$IP/extensions/Wikibase/repo/ExampleSettings.php"; 只启用维基客户端 1234$wgEnableWikibaseRepo = false;$wgEnableWikibaseClient = true;require_once "$IP/extensions/Wikibase/client/WikibaseClient.php";require_once "$IP/extensions/Wikibase/client/ExampleSettings.php"; 同时启用维基资源库和维基客户端 123456$wgEnableWikibaseRepo = true;$wgEnableWikibaseClient = true;require_once "$IP/extensions/Wikibase/repo/Wikibase.php";require_once "$IP/extensions/Wikibase/repo/ExampleSettings.php";require_once "$IP/extensions/Wikibase/client/WikibaseClient.php";require_once "$IP/extensions/Wikibase/client/ExampleSettings.php"; 运行脚本 在mediawiki-1.33.0下123php maintenance/update.phpcd extensions/Wikibasephp lib/maintenance/populateSitesTable.php 运行完这一步就会在数据库中生成相应的wb_前缀的表,这些就是wikibase需要用到的关键表。 For Wikibase Repository only 12cd extensions/Wikibasephp repo/maintenance/rebuildItemsPerSite.php For Wikibase Client only 12cd extensions/Wikibasephp client/maintenance/populateInterwiki.php For Wikibase Repository and Wikibase Client 123cd extensions/Wikibasephp repo/maintenance/rebuildItemsPerSite.phpphp client/maintenance/populateInterwiki.php 检查最终成 访问mediawiki-1.33.0部署的应用 如果安装成功的话首页上左侧会出现添加链接的按钮(启用client),在特殊页面中会有wikibase的选项 简单部署 下载完整安装包_ 解压运行sql到mysql数据库 修改LocalSettings.php配置文件中配置为自己的配置123456789$wgServer = "http://127.0.0.1:8083";$wgEmergencyContact = "[email protected]";$wgPasswordSender = "[email protected]";## Database settings$wgDBtype = "mysql";$wgDBserver = "127.0.0.1";$wgDBname = "mediawiki-test1";$wgDBuser = "root";$wgDBpassword = "pw"; 参考 Wikibase/Installation Composer Manual:Installation guide 原文链接]]></content>
<categories>
<category>KG</category>
</categories>
<tags>
<tag>安装</tag>
<tag>部署</tag>
<tag>wikibase</tag>
</tags>
</entry>
<entry>
<title><![CDATA[MacOS 下安装openJDK]]></title>
<url>%2F2019%2F12%2F11%2F%E5%BC%80%E5%8F%91%E8%80%85%E6%89%8B%E5%86%8C%2FMacOS-%E4%B8%8B%E5%AE%89%E8%A3%85openJDK%2F</url>
<content type="text"><![CDATA[安装123brew tap AdoptOpenJDK/openjdk# <<XXX>>可以选择adoptopenjdk-openjdk8、adoptopenjdk-openjdk9、adoptopenjdk-openjdk10brew install <XXX> 安装包 下载链接 安装会默认安装到 /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk 配置配置到环境变量设置中: 1234#java_home配置export JAVA_8_HOME=`/usr/libexec/java_home -v 1.8`export JAVA_7_HOME=`/usr/libexec/java_home -v 1.7`export JAVA_HOME=$JAVA_8_HOME]]></content>
<categories>
<category>开发者手册</category>
</categories>
<tags>
<tag>安装</tag>
<tag>Mac OS</tag>
<tag>openJDK</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Mysql创建新用户并处理权限]]></title>
<url>%2F2019%2F11%2F20%2FDB%2FMysql%E5%88%9B%E5%BB%BA%E6%96%B0%E7%94%A8%E6%88%B7%E5%B9%B6%E5%A4%84%E7%90%86%E6%9D%83%E9%99%90%2F</url>
<content type="text"><![CDATA[创建用户12[root@localhost ~]# mysql -uroot -pEnter password: 输入密码后 1CREATE USER '用户名'@'host' IDENTIFIED BY 'password'; 用户名:创建的用户名host:制定可以登录的主机host,如果需要任意的主机都可以登录可以使用%替代host如“CREATE USER ‘用户名‘@’%’ IDENTIFIED BY ‘password’;”password:创建的用户的登录密码,可以设置空% : 匹配所有主机,host可以替换为%,或如:192.168.0.% 权限设置权限创建用户后需要设置对某些数据库某些表的权限:1GRANT 权限 ON 数据库名.表名 TO 'username'@'host' 权限:可以为SELECT,INSERT,UPDATE等,所有的权限使用ALL替代数据库名:数据库名称表名:表名,全部的表用星花表示,如”数据库名.*”例子:1GRANT ALL ON *.* TO 'tom'@'%'; tom想和个用户无法给其他的用户进行授权操作如果想让tom可以对其他的用户进行授权可以使用: 1GRANT 权限 ON 数据库名.表名 TO 'tom'@'host' WITH GRANT OPTION; 撤销用户权限1REVOKE 权限 ON 数据库名.表名 FROM '用户名'@'host'; 例子:1REVOKE SELECT ON 数据库名.* FROM 'tom'@'%'; 用户密码设置用户密码:1SET PASSWORD FOR '用户名'@'host' = PASSWORD('新密码'); 如果是当前登录的用户:1SET PASSWORD = PASSWORD("newpassword"); 如: 1SET PASSWORD FOR 'tom'@'%' = PASSWORD("TTT.VVV.123456"); 删除用户1DROP USER '用户名'@'host';]]></content>
<categories>
<category>Mysql</category>
</categories>
<tags>
<tag>mysql</tag>
<tag>权限</tag>
<tag>创建</tag>
<tag>新用户</tag>
</tags>
</entry>
<entry>
<title><![CDATA[mysql数据库1067错误]]></title>
<url>%2F2019%2F11%2F13%2FFAQ%2Fmysql%E6%95%B0%E6%8D%AE%E5%BA%931067%E9%94%99%E8%AF%AF%2F</url>
<content type="text"><![CDATA[在Mysql数据库导出数据库后迁移到其他数据无法重新导入SQL报错如下: 1ERROR 1067 (42000): Invalid default value for XXX 通过在导入数据前声明以下内容进行解决 1SET sql_mode = ''; 还有其他的内容可以参考: ERROR 1067 (42000): Invalid default value for ‘created_at’]]></content>
<categories>
<category>FAQ</category>
</categories>
<tags>
<tag>1067</tag>
<tag>ERROR</tag>
</tags>
</entry>
<entry>
<title><![CDATA[名词缩写及其相关概念]]></title>
<url>%2F2019%2F04%2F24%2F%E5%BC%80%E5%8F%91%E8%80%85%E6%89%8B%E5%86%8C%2F%E5%90%8D%E8%AF%8D%E7%BC%A9%E5%86%99%E5%8F%8A%E5%85%B6%E7%9B%B8%E5%85%B3%E6%A6%82%E5%BF%B5%2F</url>
<content type="text"><![CDATA[最近更换了些工作内容,接触了一些乱七八糟的工作和很多的异样的名词,这个算是我梳理这些名词的笔记吧,很多这些都是在学校的时候学习过,但是大多都已经模糊了 LAMPLAMP是指一组通常一起使用来运行动态网站或者服务器的自由软件名称首字母缩写: L指的是Linux A指的是Apache网页服务器 M指的是MariaDB或MySQL,数据库管理系统(或者数据库服务器) P指的是PHP、Perl或Python,脚本语言 变种:LAPP(以PostgreSQL替代MySQL)LAMP(最后两个字母意味着Middleware和PostgreSQL)LNMP[1]或LEMP[2](以Nginx替代Apache)WAMP(以Microsoft Windows替代Linux)MAMP(以Macintosh替代Linux)LAMJ(以JSP/servlet替代PHP)BAMP(以BSD替代Linux)WIMP(指Microsoft Windows, Microsoft IIS,MySQL, PHP)AMP(单指Apache, MySQL和PHP)XAMP(以XML替代Linux)[3] 数据库四种语言SQL四种语言:DDL,DML,DCL,TCL DDL(Data Definition Language)数据库定义语言statements are used to define the database structure or schema.123456CREATEALTERDROPTRUNCATECOMMENTRENAME DML(Data Manipulation Language)数据操纵语言statements are used for managing data within schema objects. 12345678SELECTINSERTUPDATEDELETEMERGECALLEXPLAIN PLANLOCK TABLE DCL(Data Control Language)数据库控制语言 授权,角色控制等12GRANT 授权REVOKE 取消授权 TCL(Transaction Control Language)事务控制语言123SAVEPOINT 设置保存点ROLLBACK 回滚SET TRANSACTION (1)数据定义。(SQL DDL)用于定义SQL模式、基本表、视图和索引的创建和撤消操作。(2)数据操纵。(SQL DML)数据操纵分成数据查询和数据更新两类。数据更新又分成插入、删除、和修改三种操作。(3)数据控制。包括对基本表和视图的授权,完整性规则的描述,事务控制等内容。(4)嵌入式SQL的使用规定。涉及到SQL语句嵌入在宿主语言程序中使用的规则。 MPPMPP即大规模并行处理(Massively Parallel Processor )。 在数据库非共享集群中,每个节点都有独立的磁盘存储系统和内存系统,业务数据根据数据库模型和应用特点划分到各个节点上,每台数据节点通过专用网络或者商业通用网络互相连接,彼此协同计算,作为整体提供数据 库服务。非共享数据库集群有完全的可伸缩性、高可用、高性能、优秀的性价比、资源共享等优势。 Greenplum是一种基于PostgreSQL的分布式数据库elasticsearch也是一种MPP架构的数据库,Presto、Impala等都是MPP engine,各节点不共享资源,每个executor可以独自完成数据的读取和计算,缺点在于怕stragglers,遇到后整个engine的性能下降到该straggler的能力,所谓木桶的短板,这也是为什么MPP架构不适合异构的机器,要求各节点配置一样。 Spark SQL应该还是算做Batching Processing, 中间计算结果需要落地到磁盘,所以查询效率没有MPP架构的引擎(如Impala)高 OLTP、OLAP数据处理大致可以分成两大类:联机事务处理OLTP(on-line transaction processing)、联机分析处理OLAP(On-Line Analytical Processing)。OLTP是传统的关系型数据库的主要应用,主要是基本的、日常的事务处理,例如银行交易。OLAP是数据仓库系统的主要应用,支持复杂的分析操作,侧重决策支持,并且提供直观易懂的查询结果。 SOA面向服务的体系结构(英语:service-oriented architecture)并不特指一种技术,而是一种分布式运算的软件设计方法。软件的部分组件(调用者),可以透过网络上的通用协议调用另一个应用软件组件运行、运作,让调用者获得服务。SOA原则上采用开放标准、与软件资源进行交互并采用表示的标准方式。因此应能跨越厂商、产品与技术。一项服务应视为一个独立的功能单元,可以远程访问并独立运行与更新,例如在线查询信用卡账单。 SOA中的一项服务应有以下四个特性: 针对某特定要求的输出,该服务就是运作一项商业逻辑 具有完备的特性(self-contained) 消费者并不需要了解此服务的运作过程 可能由底层其他服务组成]]></content>
<categories>
<category>开发者手册</category>
</categories>
<tags>
<tag>概念</tag>
<tag>名词</tag>
<tag>缩写</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Linux上安装部署Redis]]></title>
<url>%2F2019%2F02%2F23%2F%E5%BC%80%E5%8F%91%E8%80%85%E6%89%8B%E5%86%8C%2FLinux%E4%B8%8A%E5%AE%89%E8%A3%85%E9%83%A8%E7%BD%B2Redis%2F</url>
<content type="text"><![CDATA[原文: http://limingming.org/index.php/2019/02/linux-redis-install/ 介绍Redis是一个使用ANSI C编写的开源、支持网络、基于内存、可选持久性的键值对存储数据库。从2015年6月开始,Redis的开发由Redis Labs赞助,而2013年5月至2015年6月期间,其开发由Pivotal赞助。在2013年5月之前,其开发由VMware赞助。根据月度排行网站DB-Engines.com的数据显示,Redis是最流行的键值对存储数据库。 –维基百科 安装步骤 下载1wget http://download.redis.io/releases/redis-3.0.0.tar.gz 安装到/usr/local下: 123cp redis-3.0.0.rar.gz /usr/localtar -zxvf redis-3.0.0.tar.gz cd /usr/local/redis-3.0.0 指定安装目录/usr/local/redis: 1make PREFIX=/usr/local/redis install 配置文件redis.conf是redis的配置文件,将安装目录下的redis.conf拷贝到安装目录下: 123cd /usr/local/redismkdir confcp /usr/local/redis-3.0.0/redis.conf /usr/local/redis/conf 查看bin目录下内容 123456~ pwd/usr/local/redis/bin~ lsdump.rdb redis-check-aof redis-cli redis-serverredis-benchmark redis-check-dump redis-sentinel~ redis-check-aof AOF文件修复工具 redis-cli redis命令行客户端 redis-server redis服务进程 redis-benchmark redis性能测试工具 redis-sentinal redis集群管理工具 修改环境变量 1vi /etc/profile 添加:12export REDIS_HOME=/usr/local/redisexport PATH=$REDIS_HOME/bin:$PATH 1source /etc/profile 这样redis/bin下的命令就可以随处使用了。 启动reids直接执行redis-server,会前台启动,终端关闭后就直接关闭了,所以我们可以修改redis.conf文件改为后台启动:1vim /usr/local/redis/conf/redis.conf 修改 By default Redis does not run as a daemon. Use ‘yes’ if you need it.Note that Redis will write a pid file in /var/run/redis.pid when daemonized.daemonize yes 将daemonize no改为daemonize yes启动:1234~ cd /usr/local/redis/conf~ pwd/usr/local/redis/conf ~ redis-server redis.conf redis-cli 测试 12345678910111213~ redis-cli 127.0.0.1:6379> set name 123OK127.0.0.1:6379> get name"123"127.0.0.1:6379> set key1 value1OK127.0.0.1:6379> key*(error) ERR unknown command 'key*'127.0.0.1:6379> keys *1) "key1"2) "name"127.0.0.1:6379> exit 关闭redis强制关闭redis会让redis数据丢失,正常关闭redis流程是: 1redis-cli shutdown 强制关闭redis:1pkill redis-server 设置redis开机自启动:1vim /etc/rc.local 添加:1redis-server /usr/local/redis/conf/redis-conf 配置文件参数1234~ redis-cli 127.0.0.1:6379> CONFIG GET daemonize1) "daemonize"2) "yes" 可以通过redis-cli来看redis的配置,那所有的配置项:123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131127.0.0.1:6379> CONFIG GET * 1) "dbfilename" 2) "dump.rdb" 3) "requirepass" 4) "" 5) "masterauth" 6) "" 7) "unixsocket" 8) "" 9) "logfile" 10) "" 11) "pidfile" 12) "/var/run/redis.pid" 13) "maxmemory" 14) "0" 15) "maxmemory-samples" 16) "5" 17) "timeout" 18) "0" 19) "tcp-keepalive" 20) "0" 21) "auto-aof-rewrite-percentage" 22) "100" 23) "auto-aof-rewrite-min-size" 24) "67108864" 25) "hash-max-ziplist-entries" 26) "512" 27) "hash-max-ziplist-value" 28) "64" 29) "list-max-ziplist-entries" 30) "512" 31) "list-max-ziplist-value" 32) "64" 33) "set-max-intset-entries" 34) "512" 35) "zset-max-ziplist-entries" 36) "128" 37) "zset-max-ziplist-value" 38) "64" 39) "hll-sparse-max-bytes" 40) "3000" 41) "lua-time-limit" 42) "5000" 43) "slowlog-log-slower-than" 44) "10000" 45) "latency-monitor-threshold" 46) "0" 47) "slowlog-max-len" 48) "128" 49) "port" 50) "6379" 51) "tcp-backlog" 52) "511" 53) "databases" 54) "16" 55) "repl-ping-slave-period" 56) "10" 57) "repl-timeout" 58) "60" 59) "repl-backlog-size" 60) "1048576" 61) "repl-backlog-ttl" 62) "3600" 63) "maxclients" 64) "10000" 65) "watchdog-period" 66) "0" 67) "slave-priority" 68) "100" 69) "min-slaves-to-write" 70) "0" 71) "min-slaves-max-lag" 72) "10" 73) "hz" 74) "10" 75) "cluster-node-timeout" 76) "15000" 77) "cluster-migration-barrier" 78) "1" 79) "cluster-slave-validity-factor" 80) "10" 81) "repl-diskless-sync-delay" 82) "5" 83) "cluster-require-full-coverage" 84) "yes" 85) "no-appendfsync-on-rewrite" 86) "no" 87) "slave-serve-stale-data" 88) "yes" 89) "slave-read-only" 90) "yes" 91) "stop-writes-on-bgsave-error" 92) "yes" 93) "daemonize" 94) "yes" 95) "rdbcompression" 96) "yes" 97) "rdbchecksum" 98) "yes" 99) "activerehashing"100) "yes"101) "repl-disable-tcp-nodelay"102) "no"103) "repl-diskless-sync"104) "no"105) "aof-rewrite-incremental-fsync"106) "yes"107) "aof-load-truncated"108) "yes"109) "appendonly"110) "no"111) "dir"112) "/usr/local/redis/conf"113) "maxmemory-policy"114) "noeviction"115) "appendfsync"116) "everysec"117) "save"118) "900 1 300 10 60 10000"119) "loglevel"120) "notice"121) "client-output-buffer-limit"122) "normal 0 0 0 slave 268435456 67108864 60 pubsub 33554432 8388608 60"123) "unixsocketperm"124) "0"125) "slaveof"126) ""127) "notify-keyspace-events"128) ""129) "bind"130) "" 参数说明(来自菜鸟教程)redis.conf 配置项说明如下: Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程 daemonize no 当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,可以通过pidfile指定 pidfile /var/run/redis.pid 指定Redis监听端口,默认端口为6379,作者在自己的一篇博文中解释了为什么选用6379作为默认端口,因为6379在手机按键上MERZ对应的号码,而MERZ取自意大利歌女Alessia Merz的名字 port 6379 绑定的主机地址 bind 127.0.0.1 5.当 客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能 timeout 300 指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,默认为verbose loglevel verbose 日志记录方式,默认为标准输出,如果配置Redis为守护进程方式运行,而这里又配置为日志记录方式为标准输出,则日志将会发送给/dev/null logfile stdout 设置数据库的数量,默认数据库为0,可以使用SELECT 命令在连接上指定数据库id databases 16 指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合 save Redis默认配置文件中提供了三个条件: save 900 1 save 300 10 save 60 10000 分别表示900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改以及60秒内有10000个更改。 指定存储至本地数据库时是否压缩数据,默认为yes,Redis采用LZF压缩,如果为了节省CPU时间,可以关闭该选项,但会导致数据库文件变的巨大 rdbcompression yes 指定本地数据库文件名,默认值为dump.rdb dbfilename dump.rdb 指定本地数据库存放目录 dir ./ 设置当本机为slav服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从master进行数据同步 slaveof 当master服务设置了密码保护时,slav服务连接master的密码 masterauth 设置Redis连接密码,如果配置了连接密码,客户端在连接Redis时需要通过AUTH 命令提供密码,默认关闭 requirepass foobared 设置同一时间最大客户端连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数,如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息 maxclients 128 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key,当此方法处理 后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis新的vm机制,会把Key存放内存,Value会存放在swap区 maxmemory 指定是否在每次更新操作后进行日志记录,Redis在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为 redis本身同步数据文件是按上面save条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为no appendonly no 指定更新日志文件名,默认为appendonly.aof appendfilename appendonly.aof 指定更新日志条件,共有3个可选值:no:表示等操作系统进行数据缓存同步到磁盘(快)always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全)everysec:表示每秒同步一次(折中,默认值) appendfsync everysec 指定是否启用虚拟内存机制,默认值为no,简单的介绍一下,VM机制将数据分页存放,由Redis将访问量较少的页即冷数据swap到磁盘上,访问多的页面由磁盘自动换出到内存中(在后面的文章我会仔细分析Redis的VM机制) vm-enabled no 虚拟内存文件路径,默认值为/tmp/redis.swap,不可多个Redis实例共享 vm-swap-file /tmp/redis.swap 将所有大于vm-max-memory的数据存入虚拟内存,无论vm-max-memory设置多小,所有索引数据都是内存存储的(Redis的索引数据 就是keys),也就是说,当vm-max-memory设置为0的时候,其实是所有value都存在于磁盘。默认值为0 vm-max-memory 0 Redis swap文件分成了很多的page,一个对象可以保存在多个page上面,但一个page上不能被多个对象共享,vm-page-size是要根据存储的 数据大小来设定的,作者建议如果存储很多小对象,page大小最好设置为32或者64bytes;如果存储很大大对象,则可以使用更大的page,如果不 确定,就使用默认值 vm-page-size 32 设置swap文件中的page数量,由于页表(一种表示页面空闲或使用的bitmap)是在放在内存中的,,在磁盘上每8个pages将消耗1byte的内存。 vm-pages 134217728 设置访问swap文件的线程数,最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的,可能会造成比较长时间的延迟。默认值为4 vm-max-threads 4 设置在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启 glueoutputbuf yes 指定在超过一定的数量或者最大的元素超过某一临界值时,采用一种特殊的哈希算法 hash-max-zipmap-entries 64 hash-max-zipmap-value 512 指定是否激活重置哈希,默认为开启(后面在介绍Redis的哈希算法时具体介绍) activerehashing yes 指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件 include /path/to/local.conf]]></content>
<categories>
<category>开发者手册</category>
</categories>
<tags>
<tag>安装</tag>
<tag>部署</tag>
<tag>redis</tag>
<tag>linux</tag>
</tags>
</entry>
<entry>
<title><![CDATA[java远程调试]]></title>
<url>%2F2019%2F02%2F20%2FJava%2Fjava%E8%BF%9C%E7%A8%8B%E8%B0%83%E8%AF%95%2F</url>
<content type="text"><![CDATA[原文: http://limingming.org/index.php/2019/02/java-remote-debugging/ 简介Eclipse远程调试已经不是新鲜事情了,在工作过程中一般用到远程调试都是在部署到远程的虚拟机或者服务器上出现了问题,但是在本地复现的过程中始终无法复现,所以一边在这种情况下会用到远程调试。 操作修改tomcat容器修改catalina.sh文件:1CATALINA_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n" 前一段时间看同事需要更改oozie的源码,因为关联大数据组件及其他种种原因没有办法在本地部署调试,导致开发过程中遇到的问题无法及时调试,我看oozie部署的容器是tomcat,所以我想远程调试应该会生效,所以也决定记录一下远程调试的过程,但是部署oozie的catalina.sh和正常的tomcat的有稍微的区别正常情况下我们需要添加到cygwin=false上面就行了,能使CATALINA_OPTS生效就可以了:12# OS specific support. $var _must_ be set to either true or false.cygwin=false 关于oozie部分启动容器在oozie-4.3.1/oozie-server,catalina.sh在/oozie-4.3.1/oozie-server/bin下,但是修改完成之后并不生效,所以找了它的启动脚本,发现是它在启动脚本中设置的,所以更改它的启动脚本就可以了: 123456789101112catalina_opts="${catalina_opts} -Doozie.log4j.reload=${OOZIE_LOG4J_RELOAD}"; catalina_opts="${catalina_opts} -Doozie.http.hostname=${OOZIE_HTTP_HOSTNAME}"; catalina_opts="${catalina_opts} -Doozie.admin.port=${OOZIE_ADMIN_PORT}"; catalina_opts="${catalina_opts} -Doozie.http.port=${OOZIE_HTTP_PORT}"; catalina_opts="${catalina_opts} -Doozie.https.port=${OOZIE_HTTPS_PORT}"; catalina_opts="${catalina_opts} -Doozie.base.url=${OOZIE_BASE_URL}"; catalina_opts="${catalina_opts} -Doozie.https.keystore.file=${OOZIE_HTTPS_KEYSTORE_FILE}"; catalina_opts="${catalina_opts} -Doozie.https.keystore.pass=${OOZIE_HTTPS_KEYSTORE_PASS}"; # debug catalina_opts="${catalina_opts} -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n"; 启动过程中如果配置成功日志中会打印Listening for transport dt_socket at address: 8000当然监听的端口不一定是8000还可以改成其他的没有被占有的端口都可以 修改eclipse配置找到小虫子那个debug的按钮,下来菜单中打开Debug Configurations,左边栏中找到Remote Java Application; Name:自定义方便记录就行了;Project:需要远程debug的项目(本地源码);Host:远程IP;Port:8000,与修改的catalina.sh对应;点击Apply,再点击Debug就可以开始远程debug了(debug前要启动远程tomcat服务) 如果debug总是超时,那可以通过修改Preferences–>java–>debug,其中有设置超时的设置,可以设置超时时长,适当加大点就可以了 远程调试原理JPDA什么是JPDA (Java Platform Debugger Architecture) The Java Platform Debugger Architecture (JPDA) consists of three interfaces designed for use by debuggers in development environments for desktop systems. JVMTI(Java Virtual Machine Tool Interface) JDWP(Java Debugger Wire Protocol) JDI(Java Debug Interface) 介绍上面的JVMTI是一个programming interface,用在开发和监控上,提供了接口去观察应用的状态控制应用执行等,通过它提供的接口相关的工具可以实现profiling、debuging、debuging、thread analysis等;什么是JDWP(Java Debug Wire Protocol)?Java Debug Wire Protocol,是debugger和它要debug的JVM之间进行通讯的协议,感兴趣可以看一下协议内容,需要理解的是具体的实现不是有它去是做的,而是我们debugger的操作发送给它最终转给JVMTI去做具体的控制实现;JDI是暴露在最高层的一个接口,通过JDI,debugger可以更方便的编写符合JDWP格式的数据,用来进行调试数据传输。总体来看,JPDA像是互相通信的程序,能让我们在任意的地点方便调试另一个JVM上的运行程序,我们上面通过配置eclipse界面操作的时候往往会忽略底层的实现,根本上我们通过操作IDE的工具通过调用JDI发送数据到JDWP,再经过JVMTI最终实现。]]></content>
<categories>
<category>Java</category>
</categories>
<tags>
<tag>远程</tag>
<tag>调试</tag>
<tag>java</tag>
<tag>eclipse</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Eclipse异常:Plugin execution not covered by lifecycle configuration]]></title>
<url>%2F2019%2F01%2F30%2F%E5%BC%80%E5%8F%91%E8%80%85%E6%89%8B%E5%86%8C%2FEclipse%E5%BC%82%E5%B8%B8%EF%BC%9APlugin-execution-not-covered-by-lifecycle-configuration%2F</url>
<content type="text"><![CDATA[原文:http://limingming.org/index.php/2019/01/eclipse-plugin-execution-not-covered-by-lifecycle-configuration 最近编译oozie,导入到eclipse发现pom文件中有一些异常: Plugin execution not covered by lifecycle configuration: org.apache.openjpa:openjpa-maven-plugin:2.4.1:enhance (execution: enhancer, phase: process-classes) 导致这个错误的原因是eclipse的m2e插件还没有支持到execution,链接。 解决:将在下的 含有此种类型报错信息的plugin标签整体 移动到下的下的里。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354<build> <plugins> <plugin> <groupId>org.apache.openjpa</groupId> <artifactId>openjpa-maven-plugin</artifactId> <executions> <execution> <id>enhancer</id> <phase>process-classes</phase> <goals> <goal>enhance</goal> </goals> <configuration> <includes> **/JsonWorkflowJob.class, **/JsonWorkflowAction.class, **/JsonCoordinatorJob.class, **/JsonCoordinatorAction.class, **/JsonSLAEvent.class, **/JsonSLARegistrationEvent.class, **/JsonBundleJob.class, **/WorkflowJobBean.class, **/WorkflowActionBean.class, **/CoordinatorJobBean.class, **/CoordinatorActionBean.class, **/SLAEventBean.class, **/SLARegistrationBean.class, **/SLACalculatorBean.class, **/SLASummaryBean.class, **/BundleJobBean.class, **/BundleActionBean.class, **/ValidateConnectionBean.class, </includes> <addDefaultConstructor>true</addDefaultConstructor> <enforcePropertyRestrictions>true</enforcePropertyRestrictions> </configuration> </execution> </executions> <dependencies> <dependency> <groupId>org.apache.openjpa</groupId> <artifactId>openjpa</artifactId> <version>${openjpa.version}</version> </dependency> <dependency> <groupId>xerces</groupId> <artifactId>xercesImpl</artifactId> <version>${xerces.version}</version> </dependency> </dependencies> </plugin> </plugins></build> 如上面的plugin标签中的executions报错,可以将plugin整体移动到: 1234567<build> <pluginManagement> <plugin> 这里!!!!!! </plugins> </pluginManagement></build>]]></content>
<categories>
<category>开发者手册</category>
</categories>
<tags>
<tag>eclipse</tag>
<tag>插件异常</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Spring Boot 中自定义Filter]]></title>
<url>%2F2019%2F01%2F25%2FSpring%2FSpring-Boot-%E4%B8%AD%E8%87%AA%E5%AE%9A%E4%B9%89Filter%2F</url>
<content type="text"><![CDATA[原文: http://limingming.org/index.php/2019/01/spring-boot-filter/ 介绍Servlet过滤器是在Java Servlet规范2.3中定义的,它能够对Servlet容器的请求和响应对象进行检查和修改。它本身不能产生请求和响应对象,智能提供过滤功能,能在servlet调用钱检查Request对象修改Header和Request内容,在调用之后检查Response对象,修改Header和Response内容, 过滤器接口构成所有Servlet过滤器类都必须实现javax.servlet.Filter接口,这个接口含有3个过滤器类必须实现的方法: init(FilterConfig)这是Servlet过滤器的初始化方法,Servlet容器创建Servlet过滤器实例后将调用这个方法。在这个方法中可以读取web.xml文件中Servlet过滤器的初始化参数 doFilter(ServletRequest,ServletResponse,FilterChain)这个方法完成实际的过滤操作,当客户请求访问于过滤器关联的URL时,Servlet容器将先调用过滤器的doFilter方法。FilterChain参数用于访问后续过滤器 destroy()Servlet容器在销毁过滤器实例前调用该方法,这个方法中可以释放Servlet过滤器占用的资源 web.xml原来的时候我们一般会在web.xml中声明Filter,例如: 编码过滤器1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950public class EncodingFilter implements Filter { private String encoding; private Map<String, String> params = new HashMap<String, String>(); // 项目结束时就已经进行销毁 public void destroy() { System.out.println("end do the encoding filter!"); params=null; encoding=null; } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { //UtilTimerStack.push("EncodingFilter_doFilter:"); System.out.println("before encoding " + encoding + " filter!"); req.setCharacterEncoding(encoding); // resp.setCharacterEncoding(encoding); // resp.setContentType("text/html;charset="+encoding); chain.doFilter(req, resp); System.out.println("after encoding " + encoding + " filter!"); System.err.println("----------------------------------------"); //UtilTimerStack.pop("EncodingFilter_doFilter:"); } // 项目启动时就已经进行读取 public void init(FilterConfig config) throws ServletException { System.out.println("begin do the encoding filter!"); encoding = config.getInitParameter("encoding"); for (Enumeration e = config.getInitParameterNames(); e .hasMoreElements();) { String name = (String) e.nextElement(); String value = config.getInitParameter(name); params.put(name, value); } } } ``` ## web.xml中配置```xml<!-- 编码过滤器 --> <filter> <filter-name>setCharacterEncoding</filter-name> <filter-class>com.company.strutstudy.web.servletstudy.filter.EncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>setCharacterEncoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> Spring以上很明显的是我们原来项目中声明的方式,但是在Spring Boot中很明显是不能这么实现的。 定义Filter 12345678910111213141516171819202122package com.cppba.filter;import javax.servlet.*;import java.io.IOException;public class TestFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("TestFilter"); } @Override public void destroy() { }} 在Configuration.java中增加一个@bean 1234567891011121314@Configurationpublic class ApplicationConfiguration {@Bean public FilterRegistrationBean testFilterRegistration() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new TestFilter()); registration.addUrlPatterns("/*"); registration.addInitParameter("paramName", "paramValue"); registration.setName("testFilter"); registration.setOrder(1); return registration; }} 这种方式是spring中就可以使用的,一般情况下可以在Filter是第三方的包中的,无法在Filter上添加任何注解,可以通过@Configuration、@Bean这种java配置的方式装配Bean。以上testFilterRegistration的方式可以和xml的方式对应查看。 Spring Boot 定义Filter 123456789101112131415161718192021@Order(1)//重点@WebFilter(filterName = "testFilter1", urlPatterns = "/*")public class TestFilterFirst implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("TestFilter1"); filterChain.doFilter(servletRequest,servletResponse); } @Override public void destroy() { }} 自定义类上面加上@WebFilter,其中@Order注解表示执行过滤顺序,值越小,越先执行 Spring Boot入口处注解ServletComponentScan123456789@SpringBootApplication(scanBasePackages = "com.cppba")//重点@ServletComponentScanpublic class Application { public static void main(String[] args) throws UnknownHostException { SpringApplication app = new SpringApplication(Application.class); Environment environment = app.run(args).getEnvironment(); }}]]></content>
<categories>
<category>Spring</category>
</categories>
<tags>
<tag>Spring</tag>
<tag>Boot</tag>
<tag>注解</tag>
<tag>Filter</tag>
<tag>过滤器</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Spring多线程事务]]></title>
<url>%2F2019%2F01%2F15%2FSpring%2FSpring%E5%A4%9A%E7%BA%BF%E7%A8%8B%E4%BA%8B%E5%8A%A1%2F</url>
<content type="text"><![CDATA[原文: http://limingming.org/index.php/2019/01/spring-multithreading-transaction/ 单线程多个操作我们在平时使用spring开发的过程中有很多在一个业务方法中对多个数据库进行操作,有好多时候是第二个或者第三个调用操作的接口出现问题,我们需要回滚事务,那回滚的机制是什么呢? 我们常用的配置是:1234567<!-- Jpa 事务配置 --><bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"><property name="entityManagerFactory" ref="entityManagerFactory"/> </bean> <!-- 开启注解事务 --><tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" /> 在spring的配置文件中,如果数据源的defaultAutoCommit设置为True了: 方法中如果自己捕获了异常,事务是不会自己回滚 如果没有自己捕获了异常则事务会回滚 如果你发现你并没有配置,如果使用ali的com.alibaba.druid.pool.DruidDataSource,那么还是会回滚的,因为缺省的配置是True。 例子: 没有手动捕获异常 12345@Transactional(rollbackOn = { Exception.class }) public void test() throws Exception { doOperate1(); doOperate2();//如果此方法抛出异常,那么doOperate1操作会回滚} 手动捕获异常 123456789@Transactional(rollbackOn = { Exception.class }) public void test() throws Exception { try{ doOperate1(); doOperate2();//如果此方法抛出异常,那么doOperate1操作“不会“回滚 } catch (Exception e) { e.printStackTrace(); } } 可以在catch中手动回滚事务,在catche中添加:1TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 以上为单个线程对一个数据库操作事务的问题,下面看一下多线程对与事物的操作。 多线程以为线程不是spring管理的,所以在多线程中不能默认使用spring事务。 如果在一个类的方法中如上单线程中的例子,doOperate1()和doOperate2()不会被添加到多线程的事务,就算是在test方法上添加了@Transactional也不会生效。 如果要进行事务管理需要将doOperate1()和doOperate2()放到一个新的类里面去,并且在方法上添加 @Transactional 注解,就能成功的加入到事务管理中,依赖注入这个新的类,用这个类调用这两个方法。 thread的run方法,有个特别之处,它不会抛出异常,但异常会导致线程终止运行,在主线程中try cache也无法捕获到异常, 以下是网上找到的示例,供大家参考: ①处要抛出异常 ②处要捕捉异常,并且要抛出RuntimeException ③处手动处理回滚逻辑 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566@Service public class ServiceA { @Autowired private ServiceB serviceB; @Transactional public void threadMethod(){ this.insert(); System.out.println("main insert is over"); for(int a=0 ;a<3;a++){ ThreadOperation threadOperation= new ThreadOperation(); Thread innerThread = new Thread(threadOperation); innerThread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread t, Throwable e) { try { serviceB.delete();③ } catch (Exception e1) { e1.printStackTrace(); } } }); innerThread.start(); } } public class ThreadOperation implements Runnable { public ThreadOperation(){ } @Override public void run(){ try { serviceB.insert(); }catch (Exception ex){ ② System.out.println(" Exception in run "); throw new RuntimeException(); } System.out.println("thread insert is over"); } } public void insert(){ //do insert...... } } @Service public class ServiceB { @Transactional public void insert() throws Exception{ ① //do insert...... } @Transactional public void delete() throws Exception{ //do delete...... } }]]></content>
<categories>
<category>Spring</category>
</categories>
<tags>
<tag>spring</tag>
<tag>多线程</tag>
<tag>事务</tag>
<tag>管理</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Spring DI static的静态变量]]></title>
<url>%2F2019%2F01%2F15%2FSpring%2FSpring-DI-static%E7%9A%84%E9%9D%99%E6%80%81%E5%8F%98%E9%87%8F%2F</url>
<content type="text"><![CDATA[原文:http://limingming.org/index.php/2019/01/spring-di-static/ 介绍在spring中我们一般不会将一个变量依赖注入的时候声明为静态的,在最近使用spring boot过程中,因为一些原因,需要将一个依赖注入的变量声明为静态的。例如:12@Autowiredprivate static Class class; 但是使用过程中,大家可能已经能看出来了,这个class会是空,因为静态的变量构造的时候bean尚未初始化,所以依赖注入的内容为空,静态变量/类扩大了静态方法的使用范围,静态方法在spring中不推荐使用,依赖注入是spring管理对象的实例,如果声明为静态的,那某种程度上,这个方法是全局共享的,则背弃了spring的原则,所以spring并不推荐这么做。 解决虽然不推荐,但是也要找出能够这么干的办法: xml方式实现适用于存在xml配置文件的spring web项目。 123<bean id="Util" class="com.*.*.Util" init-method="init"> <property name="class" ref="class"/> </bean> 123456789101112public class Util { private static YClass class; private static Util classUtil; public void init() { classUtil = this; classUtil.class = this.class; } } @PostConstruct1234567891011121314@Component public class Util { @Autowired private static YClass class; private static Util classUtil; @PostConstruct public void init() { classUtil = this; classUtil.class = this.class; } } 因为使用@postConstruct这种方式,bean已经都被完全初始化,可以使用依赖项,保证bean生命周期只调用一次此方法。 PS:如果你使用new的方式构造对象执行,那么new出来的实例将脱离spring的管理,获取不到注解的属性值,如果你要执行的类中含有注解,必须以依赖注入的方式使用,使用new的方式是无法正确获取到此类中的注入的值的。]]></content>
<categories>
<category>Spring</category>
</categories>
<tags>
<tag>spring</tag>
<tag>依赖注入</tag>
<tag>静态变量</tag>
<tag>空</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Mysql常用规范整理记录]]></title>
<url>%2F2018%2F12%2F31%2FDB%2FMysql%E5%B8%B8%E7%94%A8%E8%A7%84%E8%8C%83%E6%95%B4%E7%90%86%E8%AE%B0%E5%BD%95%2F</url>
<content type="text"><![CDATA[介绍在开发过程中大家遵循一个良好的规范可以进行高效的协同开发效率,更好的维护代码,数据库设计的过程中包含表字段等命名规范同样也是其中很重要的一部分,还有数据库的设计范式,当然也有随着现在技术和架构的变化反范式的出现,还有存储引擎的选择等 三大范式我们需要范式的原因是针对于编程简单,数据量不大,更新少量的数据,减少数据存储的冗余,但是更少的冗余代表着需要更过的group、join的操作。为了建立一个冗余较小,结构合理的数据库,在关系型数据库中必须遵循散发范式。 第一范式:数据表每一列都是不可分割的基本数据项,也就是确保每列保持原子性,就像是学生表的学号、性别等第二范式:数据表里的所有数据都要和该数据表里的主键有完全相依赖的关系,不能只依赖表中的部分数据,也就是说一个数据库表中,只能保存部分数据,不可以把多中数据放在一个数据库表中。第三范式:确保每列都和主键列直接相关,而不是间接相关 如果遵循范式我们可以建立一个冗余较小、结构合理的数据库,但是我们也不要一味的追求绝对的范式设计,虽然能达到减少冗余,但是却必然使查询变得相当复杂,查询时需要更多的连接join等,我们可以根据自己的需求进行一些反范式的设计,实现减少了连接,可以更好的利用索引进行筛选和排序,对查询操作可以提高性能,但是也对编码带来一定的要求,要实现一个平衡点可能还需要根据自己切身的需求去恒定。 存储引擎 InnoDBInnoDB:支持事务安全的引擎,支持外键、行锁、事务是InnoDB最大的特点,如果有大量的update和insert,建议使用InnoDB,特别是针对多个并发和QPS较高的情况 12345671.灾难恢复性好2.支持4中级别的事务,默认事务的隔离级别是Repeatable Read,事务支持是通过MVCC多版本并发控制来提供的。3.使用行级锁,并发性能高。4.使用此存储引擎的表,数据的物理组织形式是簇表,数据按主键来组织,即主键索引和数据是在一起的,B+树就是这样的5.实现缓冲管理,能缓存索引也能缓存数据。6.支持外键7.支持热备份 MyISAMMyISAM:默认表类型,它是基于传统的ISAM类型,ISAM是Indexed Sequential Access Method (有索引的顺序访问方法) 的缩写,它是存储记录和文件的标准方法。不是事务安全的,而且不支持外键,如果执行大量的select,insert MyISAM比较适合 12345671.配合锁,实现操作系统下的复制备份,迁移2.使用表记锁并发性差3.支持全文索引4.主机宕机后,表容易损坏,灾难恢复性不佳5.无事务支持6.只缓存索引,数据缓存利用操作系统缓冲区实现的,引发过多系统调用,性能不佳。7.数据紧凑存储,可以获得更快的索引和更快的全表扫描性能。 我们现在默认使用的是InnoDB使用事务,并发高支持外键,更重要的是能适应高并发,高QPS。 阿里Mysql数据库规范以下内容来自《阿里巴巴Java开发手册》 建表规约 【强制】表达是与否概念的字段,必须使用 is_xxx 的方式命名,数据类型是 unsigned tinyint (1 表示是,0 表示否)。说明:任何字段如果为非负数,必须是 unsigned。注意:POJO 类中的任何布尔类型的变量,都不要加 is 前缀,所以,需要在设置 从 is_xxx 到 Xxx 的映射关系。数据库表示是与否的值,使用 tinyint 类型,坚持 is_xxx 的 命名方式是为了明确其取值含义与取值范围。正例:表达逻辑删除的字段名 is_deleted,1 表示删除,0 表示未删除。 【强制】表名、字段名必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只 出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。 说明:MySQL 在 Windows 下不区分大小写,但在 Linux 下默认是区分大小写。因此,数据库名、 表名、字段名,都不允许出现任何大写字母,避免节外生枝。 正例:aliyun_admin,rdc_config,level3_name 反例:AliyunAdmin,rdcConfig,level_3_name 【强制】表名不使用复数名词。 说明:表名应该仅仅表示表里面的实体内容,不应该表示实体数量,对应于 DO 类名也是单数 形式,符合表达习惯。 【强制】禁用保留字,如 desc、range、match、delayed 等,请参考 MySQL 官方保留字。 【强制】主键索引名为 pk_字段名;唯一索引名为 uk_字段名;普通索引名则为 idx_字段名。说明:pk_ 即 primary key;uk_ 即 unique key;idx_ 即 index 的简称。 【强制】小数类型为 decimal,禁止使用 float 和 double。说明:float 和 double 在存储的时候,存在精度损失的问题,很可能在值的比较时,得到不 正确的结果。如果存储的数据范围超过 decimal 的范围,建议将数据拆成整数和小数分开存储。 【强制】如果存储的字符串长度几乎相等,使用 char 定长字符串类型。 【强制】varchar 是可变长字符串,不预先分配存储空间,长度不要超过 5000,如果存储长 度大于此值,定义字段类型为 text,独立出来一张表,用主键来对应,避免影响其它字段索 引效率。 【强制】表必备三字段:id, gmt_create, gmt_modified。 说明:其中id必为主键,类型为bigint unsigned、单表时自增、步长为1。gmt_create, gmt_modified 的类型均为 datetime 类型,前者现在时表示主动创建,后者过去分词表示被 动更新。 【推荐】表的命名最好是加上“业务名称_表的作用”。正例:alipay_task / force_project / trade_config 【推荐】库名与应用名称尽量一致。 【推荐】如果修改字段含义或对字段表示的状态追加时,需要及时更新字段注释。 【推荐】字段允许适当冗余,以提高查询性能,但必须考虑数据一致。冗余字段应遵循: 1)不是频繁修改的字段。2)不是 varchar 超长字段,更不能是 text 字段。正例:商品类目名称使用频率高,字段长度短,名称基本一成不变,可在相关联的表中冗余存 储类目名称,避免关联查询。 【推荐】单表行数超过 500 万行或者单表容量超过 2GB,才推荐进行分库分表。 说明:如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表。 【参考】合适的字符存储长度,不但节约数据库表空间、节约索引存储,更重要的是提升检 索速度。 索引规约 【强制】业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。 说明:不要以为唯一索引影响了 insert 速度,这个速度损耗可以忽略,但提高查找速度是明 显的;另外,即使在应用层做了非常完善的校验控制,只要没有唯一索引,根据墨菲定律,必 然有脏数据产生。 【强制】超过三个表禁止 join。需要 join 的字段,数据类型必须绝对一致;多表关联查询时, 保证被关联的字段需要有索引。说明:即使双表 join 也要注意表索引、SQL 性能。 【强制】在 varchar 字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据 实际文本区分度决定索引长度即可。26/38阿里巴巴 Java 开发手册 说明:索引的长度与区分度是一对矛盾体,一般对字符串类型数据,长度为 20 的索引,区分度会高达 90%以上,可以使用 count(distinct left(列名, 索引长度))/count(*)的区分度 来确定。 【强制】页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。 说明:索引文件具有 B-Tree 的最左前缀匹配特性,如果左边的值未确定,那么无法使用此索 引。 【推荐】如果有 order by 的场景,请注意利用索引的有序性。order by 最后的字段是组合 索引的一部分,并且放在索引组合顺序的最后,避免出现 file_sort 的情况,影响查询性能。 正例:where a=? and b=? order by c; 索引:a_b_c 反例:索引中有范围查找,那么索引有序性无法利用,如:WHERE a>10 ORDER BY b; 索引 a_b 无法排序。 【推荐】利用覆盖索引来进行查询操作,避免回表。说明:如果一本书需要知道第 11 章是什么标题,会翻开第 11 章对应的那一页吗?目录浏览 一下就好,这个目录就是起到覆盖索引的作用。 正例:能够建立索引的种类分为主键索引、唯一索引、普通索引三种,而覆盖索引只是一种查 询的一种效果,用explain的结果,extra列会出现:using index。 【推荐】利用延迟关联或者子查询优化超多分页场景。说明:MySQL 并不是跳过 offset 行,而是取 offset+N 行,然后返回放弃前 offset 行,返回 N 行,那当 offset 特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过 特定阈值的页数进行 SQL 改写。正例:先快速定位需要获取的 id 段,然后再关联:SELECT a.* FROM 表 1 a, (select id from 表 1 where 条件 LIMIT 100000,20 ) b where a.id=b.id 【推荐】SQL 性能优化的目标:至少要达到 range 级别,要求是 ref 级别,如果可以是 consts 最好。说明:1)consts 单表中最多只有一个匹配行(主键或者唯一索引),在优化阶段即可读取到数据。 2)ref 指的是使用普通的索引(normal index)。3)range 对索引进行范围检索。反例:explain 表的结果,type=index,索引物理文件全扫描,速度非常慢,这个 index 级 别比较 range 还低,与全表扫描是小巫见大巫。 【推荐】建组合索引的时候,区分度最高的在最左边。正例:如果 where a=? and b=? ,如果 a 列的几乎接近于唯一值,那么只需要单建 idx_a 索引即可。 说明:存在非等号和等号混合时,在建索引时,请把等号条件的列前置。如:where c>? and d=? 那么即使 c 的区分度更高,也必须把 d 放在索引的最前列,即索引 idx_d_c。 【推荐】防止因字段类型不同造成的隐式转换,导致索引失效。 【参考】创建索引时避免有如下极端误解: 1)宁滥勿缺。认为一个查询就需要建一个索引。 2)宁缺勿滥。认为索引会消耗空间、严重拖慢更新和新增速度。 3)抵制惟一索引。认为业务的惟一性一律需要在应用层通过“先查后插”方式解决。 SQL语句 【强制】不要使用 count(列名)或 count(常量)来替代 count(),count()是 SQL92 定义的 标准统计行数的语法,跟数据库无关,跟 NULL 和非 NULL 无关。 说明:count(*)会统计值为 NULL 的行,而 count(列名)不会统计此列为 NULL 值的行。 【强制】count(distinct col) 计算该列除 NULL 之外的不重复行数,注意 count(distinct col1, col2) 如果其中一列全为NULL,那么即使另一列有不同的值,也返回为0。 【强制】当某一列的值全是 NULL 时,count(col)的返回结果为 0,但 sum(col)的返回结果为 NULL,因此使用 sum()时需注意 NPE 问题。 正例:可以使用如下方式来避免sum的NPE问题:SELECT IF(ISNULL(SUM(g)),0,SUM(g)) FROM table; 【强制】使用 ISNULL()来判断是否为 NULL 值。 说明:NULL 与任何值的直接比较都为 NULL。 NULL<>NULL的返回结果是NULL,而不是false。 NULL=NULL的返回结果是NULL,而不是true。 NULL<>1的返回结果是NULL,而不是true。 【强制】 在代码中写分页查询逻辑时,若 count 为 0 应直接返回,避免执行后面的分页语句。 【强制】不得使用外键与级联,一切外键概念必须在应用层解决。 说明:以学生和成绩的关系为例,学生表中的 student_id 是主键,那么成绩表中的 student_id 则为外键。如果更新学生表中的 student_id,同时触发成绩表中的 student_id 更新,即为 级联更新。外键与级联更新适用于单机低并发,不适合分布式、高并发集群;级联更新是强阻 塞,存在数据库更新风暴的风险;外键影响数据库的插入速度。 【强制】禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。 【强制】数据订正(特别是删除、修改记录操作)时,要先 select,避免出现误删除,确认无误才能执行更新语句。 【推荐】in 操作能避免则避免,若实在避免不了,需要仔细评估 in 后边的集合元素数量,控 制在 1000 个之内。 【参考】如果有国际化需要,所有的字符存储与表示,均以 utf-8 编码,注意字符统计函数的区别。说明:SELECT LENGTH(“轻松工作”); 返回为12SELECT CHARACTER_LENGTH(“轻松工作”); 返回为4 如果需要存储表情,那么选择 utf8mb4 来进行存储,注意它与 utf-8 编码的区别。 【参考】TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少,但 TRUNCATE 无事务且不触发 trigger,有可能造成事故,故不建议在开发代码中使用此语句。 说明:TRUNCATE TABLE 在功能上与不带 WHERE 子句的 DELETE 语句相同。 ORM 映射 【强制】在表查询中,一律不要使用 * 作为查询的字段列表,需要哪些字段必须明确写明。 说明:1)增加查询分析器解析成本。2)增减字段容易与 resultMap 配置不一致。3)无用字 段增加网络消耗,尤其是 text 类型的字段。 【强制】POJO 类的布尔属性不能加 is,而数据库字段必须加 is_,要求在 resultMap 中进行 字段与属性之间的映射。说明:参见定义 POJO 类以及数据库字段定义规定,在中增加映射,是必须的。 在MyBatis Generator生成的代码中,需要进行对应的修改。 【强制】不要用 resultClass 当返回参数,即使所有类属性名与数据库字段一一对应,也需 要定义;反过来,每一个表也必然有一个 POJO 类与之对应。 说明:配置映射关系,使字段与 DO 类解耦,方便维护。 【强制】sql.xml 配置参数使用:#{},#param# 不要使用${} 此种方式容易出现 SQL 注入。 【强制】iBATIS自带的queryForList(String statementName,int start,int size)不推 荐使用。说明:其实现方式是在数据库取到 statementName 对应的 SQL 语句的所有记录,再通过 subList 取 start,size 的子集合。正例:Map<String, Object> map = new HashMap<>(); map.put(“start”, start);map.put(“size”, size); 【强制】不允许直接拿 HashMap 与 Hashtable 作为查询结果集的输出。说明:resultClass=”Hashtable”,会置入字段名和属性值,但是值的类型不可控。 【强制】更新数据表记录时,必须同时更新记录对应的 gmt_modified 字段值为当前时间。 【推荐】不要写一个大而全的数据更新接口。传入为 POJO 类,不管是不是自己的目标更新字段,都进行 update table set c1=value1,c2=value2,c3=value3; 这是不对的。执行 SQL 时,不要更新无改动的字段,一是易出错;二是效率低;三是增加 binlog 存储。 【参考】@Transactional 事务不要滥用。事务会影响数据库的 QPS,另外使用事务的地方需 要考虑各方面的回滚方案,包括缓存回滚、搜索引擎回滚、消息补偿、统计修正等。 【参考】中的 compareValue 是与属性值对比的常量,一般是数字,表示相等时带 上此条件;表示不为空且不为 null 时执行;表示不为 null 值时 执行。]]></content>
<categories>
<category>Mysql</category>
</categories>
<tags>
<tag>mysql</tag>
<tag>规范</tag>
<tag>记录</tag>
</tags>
</entry>
<entry>
<title><![CDATA[mysql安装目录]]></title>
<url>%2F2018%2F12%2F31%2FDB%2Fmysql%E5%AE%89%E8%A3%85%E7%9B%AE%E5%BD%95%2F</url>
<content type="text"><![CDATA[原文:http://limingming.org/index.php/2018/12/mysql-centos-uninstall/ 介绍前段时间因为需要对数据库的数据进行迁移,原来数据存储在系统盘,可能是因为开发环境的原因,一直没有处理,但是长期使用的确影响到了使用,所以需要对与数据库数据改到相关的挂载到存储比较大的磁盘上,所以对mysql数据库卸载做了相关的总结记录。 查看mysql安装目录123456789select @@basedir as basePath from dual;mysql> select @@basedir as basePath from dual;+----------+| basePath |+----------+| /usr/ |+----------+1 row in set (0.00 sec) 完全删除卸载mysql 停止mysql服务 执行卸载 1234567891011121314151617sudo rm /usr/local/mysqlsudo rm -rf /usr/local/mysql*sudo rm -rf /Library/StartupItems/MySQLCOMsudo rm -rf /Library/PreferencePanes/My*vim /etc/hostconfig and removed the line MYSQLCOM=-YES-rm -rf ~/Library/PreferencePanes/My*sudo rm -rf /Library/Receipts/mysql*sudo rm -rf /Library/Receipts/mysql* sudo rm -rf /var/db/receipts/com.mysql.*]]></content>
<categories>
<category>Mysql</category>
</categories>
<tags>
<tag>Mysql</tag>
<tag>卸载</tag>
<tag>centos</tag>
</tags>
</entry>
<entry>
<title><![CDATA[ansible使用playbook总结]]></title>
<url>%2F2018%2F12%2F30%2FLinux%2Fansible%E4%BD%BF%E7%94%A8playbook%E6%80%BB%E7%BB%93%2F</url>
<content type="text"><![CDATA[原文 http://limingming.org/index.php/2018/12/ansible-playbook-use-summ/ SSH免密钥登录设置使用ssh-keygen生成key-pair: 123456789101112131415161718192021ssh-keygen -t rsa -P ''# 以下为系统输出内容:Generating public/private rsa key pair.Enter file in which to save the key (/root/.ssh/id_rsa): Created directory '/root/.ssh'.Your identification has been saved in /root/.ssh/id_rsa.Your public key has been saved in /root/.ssh/id_rsa.pub.The key fingerprint is:03:4a:1c:e1:7b:ca:84:11:2e:4e:4a:d7:d0:a3:83:d2 [email protected] key's randomart image is:+--[ RSA 2048]----+| ..+. || . +o+ ||.++.=.o ||*oE* o . ||o.. = . S || o o . || o || || |+-----------------+ 从上面就可以看到密钥存储在了/root/.ssh/id_rsa,将该文件夹下的id_rsa.pub内容配置到被控制的机子的/root/.ssh/authorized_keys文件中。 重新ssh连接一次,就不需要密码了:1234567[root@localhost .ssh]# ssh [email protected] authenticity of host '10.111.24.67 (10.111.24.67)' can't be established.ECDSA key fingerprint is ee:87:55:3a:d4:96:9e:c7:78:0e:a8:c1:8b:26:d3:75.Are you sure you want to continue connecting (yes/no)? yesWarning: Permanently added '10.111.24.67' (ECDSA) to the list of known hosts.Last login: Tue Dec 25 11:08:54 2018 from 10.9.11.40[root@localhost ~]# 配置Ansible使用Ansible需要配置/etc/anisble/路径下的hosts和ansible.cfg文件,需要使用root权限修改,默认安装成功后应该不存在这两个文件,所以需要创建: 1234567mkdir -p /etc/ansible vi /etc/ansible/ansible.cfg# 写入内容# remote_port 这个设置是你系统默认的远程SSH端口,如果不指定,默认为22号端口[defaults]remote_port = 22private_key_file = /root/.ssh/id_rsa 以上配置文件修改可以参考地址 Ansibleke可以操作属于同一个组的多个主机,组和主机之间的关系通过 inventory 文件(INI 格式)配置,默认的文件路径为 /etc/ansible/hosts,一个系统可以属于不同的组,比如一台服务器可以同时属于A组和B组,还有C组,所以修改host文件: 1234vi /etc/ansible/hosts# 写入内容[test]10.111.24.67 除了配置以上的host文件之外,还可以配置环境变量引用文件路径: 1export ANSIBLE_HOSTS=~/test/qiuyi_ansible/test_hosts playbook一个playbook中可以包含多个play。每个play都至少包含有tasks和hosts这两项,还可以包含其他非必须项,如vars,vars_files,remote_user等。tasks中可以通过模块调用定义一系列的action。只不过,绝大多数时候,一个playbook都只定义一个play。123playbook: [play1,play2,play3]play: [hosts,tasks,vars,remote_user...]tasks: [module1,module2,...] 需要注意,有些时候play中使用了role,可能看上去没有tasks,这是因为role本身就是整合playbook的,所以没有也没关系。但没有使用role的时候,必须得包含hosts和tasks。ansilbe提供了2种方式去执行完成任务,一个是playbook,一个是ad-hoc,ad-hoc只可以做一些简单的操作,如果要部署的话最好采用playbook来做,即是:ansible-palybook命令;通过上面的配置,我们现在可以放心的看一下ansible-playbook有哪些参数: 12345678910[root@localhost ~]# ansible-playbook --helpUsage: ansible-playbook [options] playbook.yml [playbook2 ...]Runs Ansible playbooks, executing the defined tasks on the targeted hosts.Options: --ask-vault-pass ask for vault password -C, --check don't make any changes; instead, try to predict some# 等等··· Playbooks适合部署复杂的应用,能用在声明配置,可以编排有序的执行过程,本文主要是记录并整理部署应用的过程,我要部署的应用大约包含部署tomcat及web应用,还有执行安装相关的python应用等 基础语法playbook使用了YAML格式的语法,编程少不了使用配置文件,yaml文件也是作为配置文件格式的一个主要方式,比如我经常用的使用markdown编写博客的HEXO,就是经常改动yaml文件,所以说,YAML是专门用来写配置文件的语言,非常简洁和强大,远比 JSON 格式方便。 如果感兴趣可以参考YAML语言介绍 12345大小写敏感 使用缩进表示层级关系 缩进时不允许使用Tab键,只允许使用空格 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可 # 表示注释,从这个字符一直到行尾,都会被解析器忽略 在test组(我们上面说到的配置/etc/ansible/hosts)使用root用户执行安装wget命令,如下: 123456- hosts: test remote_user: root gather_facts: True tasks: - name: "安装wget命令" command: yum -y insatll wget hosts也可以使用ip的方式,每个ip用逗号隔开 语法注意:”-“以及”:”后面都需要一个空格,从上面可以看出,有两个基本的属性,一个是hosts,一个是remote_user,他们可以定位到我们需啊哟执行命令的主机,定义tasks就可以执行task的一些命令了,上面的例子中是执行安装wget的命令,playbook执行任务需要通过不同的模块进行控制。从上面的实例可以看出有两个必须的属性,那就是服务器主机hosts以及远程用户remote_user,有了它们就可以干点其它事了tasks,自然而然在playbook执行任务是需要通过模块的来操控的。使用命令检查yaml的语法: 1ansible-playbook main.yml --syntax-check command在上面举例中也是使用command执行安装wget命令: 123456- hosts: test remote_user: root gather_facts: True tasks: - name: "安装wget命令" command: yum -y insatll wget shell我们也可以使用shell替换到command: 123456- hosts: test remote_user: root gather_facts: True tasks: - name: "安装wget命令" shell: yum -y insatll wget script执行shell脚本: 123456- hosts: test remote_user: root gather_facts: True tasks: - name: "被控节点执行控制节点的shell脚本" script: /home/limm/test.sh copy将控制节点的文件上传到test服务器【被控节点】上:1234567891011- hosts: test remote_user: root gather_facts: True tasks: - name: "控节点文件复制到到被控制节点服务器" copy: src=/home/limm/dialog.war dest=/opt/limm/apache-tomcat/webapps/ owner=root group=root mode=0644 src代表控制节点路径,dest代表被控节点路径,其它的为可选项目 yum使用yum安装vim,yum该模块仅仅适合contOS相似的发行版:123456- hosts: test remote_user: root gather_facts: True tasks: - name: "安装vim" yum: name=vim state=latest name为安装软件的名称state为安装的版本 servicetest用户组以root用户重启apache2服务:123456- hosts: test remote_user: root gather_facts: True tasks: - name: "重启apache2服务" service: name=apache2 state=restarted 我们平时启动可能使用systemctl restart httpd这种,但是在state中需要使用加-ed的方式,如: stsrted stoped restarted; notify 与 handlersnotify这个action可用于在每个play的最后被触发,这样可以避免多次有改变发生时每次都执行指定的操作,在notify中列出的操作称为handler,也即notify中调用handler中定义的操作。Handlers 也是一些 task 的列表,通过名字来引用,它们和一般的 task 并没有什么区别,Handlers 是由通知者进行 notify, 如果没有被 notify,handlers 不会执行。不管有多少个通知者进行了 notify,等到 play 中的所有 task 执行完成之后,handlers 也只会被执行一次。Handlers 最佳的应用场景是用来重启服务,或者触发系统重启操作。 12345678910- hosts: test remote_user: root tasks: - name: "test notify" shell: ls notify: - restart apache2 handlers: - name: restart apache2 service: name=apache2 state=restarted vars在playbook中定义变量1234567- hosts: test remote_user: root vars: config_path: "/root/application/sise.conf" tasks: - name: "test notify" command: touch {{config_path}} Ansible允许你使用Jinja2模板系统在playbook中引用变量,加上引号 “,在执行ansible脚本的时候赋值:例如:1234567- hosts: {{hosts}} remote_user: root vars: config_path: "/root/application/sise.conf" tasks: - name: "test notify" command: touch {{config_path}} 执行脚本:123ansible-playbook main.yml --extra-vars hosts=test#如果有多个参数:ansible-playbook release.yml --extra-vars "version=1.23.45 other_variable=foo" Roles、includeRoles是ansible自1.2版本引入的新特性,用于层次性,结构化地组织playbook,roles能够根据层次型结构自动自动装在变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中。role构建的项目目录:12345678910111213141516171819site.ymlcmd.ymlroles/ common/ files/ templates/ tasks/ handlers/ vars/ defaults/ meta/ web/ files/ templates/ tasks/ handlers/ vars/ defaults/ meta/ Role内各目录可用的文件:123456789101112131415tasks目录:至少创建一个名为main.yml的文件,其定义了此角色的任务列表:此文件可以使用 include包含其他的位于此目录中的tasks文件:files目录:存放由copy或者script等模块调用的文件:templates目录:templates模块会自动在此目录中寻找Jinjia2模板文件:handlers目录:此目录中应当包含一个main。yml文件:用于定义此角色用到的各handler:在handler中使用include包含的其他的handler文件也应该位于此目录中:vars目录:应当包含一个main.yml文件,用于定义此角色用到的变量meta目录:应当包含一个main.yml文件,用于定义此角色的特殊设定及其依赖关系:ansible 1.3及其以后的版本才支持default目录:为当前角色定义默认变量时使用此目录,应该包含一个main.yml文件 而在playbook(site.yml)中可以这样使用roles: 12345---- hosts: test roles: - common - web 也可以向roles传递参数,例如: 12345---- hosts: test roles: - common - { role: foo_app_instance , dir: '/opt/a', port: 8080 } 可以给roles指定tags,使用ansible-playbook -t指定此roles的tags,使用roles都应该定义tags: 12345---- hosts: test roles: - { role: common , tags: "common"} - web 只执行common的角色:1ansible-playbook -t common -i /etc/ansible/hosts site.yml -vv include使用语法:1- include: cmd.yml 补充 查看任务所指定的host列表 1$ ansible-playbook main.yml --list-hosts –ask-pass、–ask-sudo-pass普通用户执行命令需要输入密码 1$ ansible-playbook main.ym --ask-sudo-pass --ask-pass]]></content>
<categories>
<category>Linux</category>
</categories>
<tags>
<tag>使用</tag>
<tag>ansible</tag>
<tag>playbook</tag>
<tag>学习</tag>
<tag>总结</tag>
</tags>
</entry>
<entry>
<title><![CDATA[YAML语言介绍]]></title>
<url>%2F2018%2F12%2F30%2F%E5%BC%80%E5%8F%91%E8%80%85%E6%89%8B%E5%86%8C%2FYAML%E8%AF%AD%E8%A8%80%E4%BB%8B%E7%BB%8D%2F</url>
<content type="text"><![CDATA[原文: http://limingming.org/index.php/2018/12/yaml-intro 介绍YAML(/ˈjæməl/,尾音类似camel骆驼)是一个可读性高,用来表达数据序列的格式。YAML参考了其他多种语言,包括:C语言、Python、Perl,并从XML、邮箱的数据格式(RFC 2822)中获得灵感。Clark Evans在2001年首次发表了这种语言,另外Ingy döt Net与Oren Ben-Kiki也是这语言的共同设计者。当前已经有数种编程语言或脚本语言支持(或者说解析)这种语言。 YAML是”YAML Ain’t a Markup Language”(YAML不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:”Yet Another Markup Language”(仍是一种标记语言)但为了强调这种语言以数据做为中心,而不是以标记语言为重点,而用反向缩略语重命名。– 维基百科 上面我们也看到了YAML Ain’t a Markup Language,这个让我想起了,GNU对UNIX来说不,YAML是对XML说不,所以YAML应该是试图用一种比XML更敏捷的方式,来完成XML所完成的任务,在我们编程过程中很多时候会用到YAML文件编写配置文件,如果使用java的话可能用的比较多的是properties的配置文件居多,但是很多时候也会用到YAML文件,比如我经常使用的HEXO,修改比较多的就是YAML文件。 概括YAML的语法和其他高级语言类似,并且可以简单表达清单、散列表,标量等数据形态,下面主要针对于YAML文件相关语法做简要的记录,我平时用的比较多的是JAVA,所以针对于java也有很多YAML的实现,如果按照语法来说的话YAML文件几乎可以总结成: Structure通过空格来展示。Sequence里的项用”-“来代表,Map里的键值对用”:”分隔. 抽象出来的的对象,java里面Map、Hash这种 Collection相关的List、Set这种 单一的int这种 Structure通过空格来展示,可以组合成javabean这种对象,Sequence可以实现Arrays等,:分割实现对象、Map类的数据结构,外加其他的数据类型,可以涵盖所有的我们常用的数据类型。1234YAML大小写敏感;使用缩进代表层级关系;缩进只能使用空格,不能使用TAB,不要求空格个数,只需要相同层级左对齐(一般2个或4个空格)使用#注释 语法对象数据类型使用冒号,冒号后面跟一个空格,缩紧表示层级关系 12345keyFirst: valuekey: key1: value1 key2:value2 还可以支持行内语法表示对象: 1key: {key1: value, key2: value2} 数组使用一个短横线加一个空格代表一个数组项: 123- value1- value2- value3 数据结构的子成员是一个数组,则可以在该项下面缩进一个空格。12345678910- - value1 - valu2 - value3# 如果上面作为作为value的话就是:key:- - value1 - valu2 - value3 数组也同样可以使用行内:1key: [value1, value2] 举一个复杂的例子: 123456789key: - key1: value key2: value key3: value - key4: value key5: value key6: value 上面这种写法也是可以的,可以对应的是一个list的value,list中包含两个map对象; 单一常量YAML中提供了多种常量结构,包括:整数,浮点数,字符串,NULL,日期,布尔,时间,常量是最基本的、不可再分的值。 12345678910111213141516171819boolean: - TRUE #true,True都可以 - FALSE #false,False都可以float: - 3.14 - 6.8523015e+5 #可以使用科学计数法int: - 123 - 0b1010_0111_0100_1010_1110 #二进制表示null: nodeName: 'node' parent: ~ #使用~表示nullstring: - 你好 - 'Hello' #可以使用双引号或者单引号包裹特殊字符date: - 2018-02-17 #日期必须使用ISO 8601格式,即yyyy-MM-dddatetime: - 2018-02-17T15:02:31+08:00 #时间使用ISO 8601格式,时间和日期之间使用T连接,最后使用+代表时区 其他 引用使用锚点:&别名:* 重复的内容在YAML中可以使用&来完成锚点定义,使用*来完成锚点引用,例如:123456key:- value1 - &mark1 value2key2:- *mark1 - value3 上面中使用*mark1相当于替代了value2,那么key2的第一个元素应该是value2; 还可以:定义复杂的:1234key1: &mark2 - value3 - value4key2: *mark2 上面的*mark2相当于定义了key1中的数组内容,但要注意的是需要和key2写在一行还有不能单独定义锚点,如:&mark value1,这种形式是不可以的 补充:和锚点配合使用的还可能是合并内容,例如: 12345key1: - &mark1 { key2: value2, key3: value3 }key11: <<: *mark1 key4: value4 那么上面通过 <<: *mark1 这种方式就将key11变成了:1234key11: key2: value2 key3: value3 key4: value4 通过合并内容可以有效的共用相同的配置。 三个短横线 YAML文件中,可以使用— 表示文档的开始,Springboot中profile的定义就是如此,可以一个YAML文件中,包含多个profile,每个—都是一个profile的开始,例如:12345678910111213server: address: 192.168.1.100---spring: profiles: development server: address: 127.0.0.1 ---spring: profiles: production server: address: 192.168.1.120 …和—配合使用来表示配置文件中一个文件的结束 类型转换!! 表示强制的类型转换: 12string: - !!str 54321 折叠换行与保留换行在字符串中折叠换行,| 保留换行符 例如: 123456key1: > 1 2 3 4 5 6key2: | 7 8 9 10 11 12 那么key1=1 2 3 4 5 6,就是没有保留换行符,将黄换行符转换成了空格; 而key2 12key2=7 8 9 10 11 12 key2 保留的换行符。 注释 使用”#”来表示注释]]></content>
<categories>
<category>开发者手册</category>
</categories>
<tags>
<tag>介绍</tag>
<tag>YAML</tag>
<tag>语言</tag>
<tag>语法</tag>
</tags>
</entry>
<entry>
<title><![CDATA[vim编辑器使用]]></title>
<url>%2F2018%2F12%2F29%2FLinux%2Fvim%E7%BC%96%E8%BE%91%E5%99%A8%E4%BD%BF%E7%94%A8%2F</url>
<content type="text"><![CDATA[原文 介绍平时在使用linux like系统的时候肯定接触过vim,拿“鸟哥”的话来说的话就是,文本模式来处理Linux 的系统设置,不但可以让你比较容易了解到Linux的运行状况,也比较容易了解整个设计的基本思想,基本上我们接触的类linux系统都有vim编辑器,虽然有着繁杂的命令,但是基本上都是靠键盘输入,编辑文件简单快速,虽然在大学学习的时候总感觉为什么不用word,这玩意这么难用,为什么还要用这个玩意,到了慢慢熟悉使用vi之后才知道这个才是好的编辑器。 vi使用模式vi操作有很多,此文仅记录常用的相关操作,及vi的几种模式,分别是命令模式(command mode)、插入模式(Insert mode)和命令行模式(last line mode),各模式的功能区分如下: 一般模式(command mode)控制屏幕光标的移动,字符、字或行的删除,移动复制某区段及进入Insert mode下,或者到 last line mode。 插入模式(Insert mode)只有在Insert mode下,才可以做文字输入,按「ESC」键可回到命令行模式。 命令行模式(last line mode)将文件保存或退出vi,也可以设置编辑环境,如寻找字符串、列出行号……等。 基本操作进入vi : 1vi 文件路径/文件名 进入之后处于一般模式,如果要切换到插入模式可以使用i、o、a: 按「i」切换进入插入模式「insert mode」,按“i”进入插入模式后是从光标当前位置开始输入文件;按「a」进入插入模式后,是从目前光标所在位置的下一个位置开始输入文字;按「o」进入插入模式后,是插入新的一行,从行首开始输入文字。 如果要回到命令行模式「ESC」可以帮你退回到一般模式,在「一般模式(command mode)」下,按一下「:」冒号键进入「Last line mode」,常用的进入命令行模式,一般进入命令行模式会执行一些操作,例如保存并退出“:wq”,例如设置展示行号,“:se nu” 例如查找某些单词:“:/word”等等 一般模式下按键操作 移动光标但正规的vi是用小写英文字母「h」、「j」、「k」、「l」,分别控制光标左、下、上、右移一格翻页:按「ctrl」+「b」:屏幕往“后”移动一页。按「ctrl」+「f」:屏幕往“前”移动一页。按「ctrl」+「u」:屏幕往“后”移动半页。按「ctrl」+「d」:屏幕往“前”移动半页。 常用跳到行头和行尾:按数字「0」:移到文章的开头,按「$」:移动到光标所在行的“行尾” G相关:G: 移动到这个文件最后一行nG:n为数字移动到这个文件的第n行gg: 移动到文件的第一行,相当于1GN【Enter】 : N为数字,向下移动N行 复制粘贴 「yw」:将光标所在之处到字尾的字符。「#yw」:复制#个字到缓冲区「yy」:复制光标所在行(常用)「#yy」:例如,「6yy」表示拷贝从光标所在的该行“往下数”6行文字。(常用)「p」: 粘贴 删除 x: 删除当前光标下的字符X; 删除光标前面的字符dw; 删除从当前光标到单词结尾的字符d^; 删除从当前光标到行首的字符d$ ;删除从当前光标到行尾的字符D ;删除从当前光标到行尾的字符dd 删除当前光标所在的行(常用)ndd: n是数字,删除光标所在行向下n行 撤销、重做u: 复原前一个操作Ctrl+r,重做上一个操作. : 小数点,重复前一个操作 命令行模式操作 列出行号set nu 定位到某行#:井号代表一个数字,在Lastline mode提示符号“:”前输入数字,再按Enter就会跳到该行了,等同于在一般模式下的#G 寻找字符串/关键字:先按/,再输入您想寻找的字(字母“n”为向下继续查找)?关键字:先按?,再输入您想寻找的字(字母“n”为向下继续查找) 取代字符串1,$s/string/replae/g:在lastline mode输入“1,$s/string/replace/g”会将全文的string字符串取代为replace字符串,其中1,$s就是指搜寻区间为文章从头至尾的意思,g则是表示全部取代不必确认%s/string/replace/c:同样会将全文的string字符串取代为replace字符串,和上面指令不同的地方是,%s和1,$s是相同的功能,c则是表示要替代之前必须再次确认是否取代1,20s/string/replace/g:将1至20行间的string替代为relpace字符串 存储w:在lastline mode提示符号“:”前按w即可将文件保存#,# wfilename:如果您想摘取文章的某一段,存成另一个文件,可用这个指令#代表行号,例如30,50 wnice,将您正在编辑文章的第30~50行存成nice这个文件。 离开q:按q就离开,有时如果无法离开vi,可搭配“!:强置离开vi,如“q!”qw:一般建议离开时,搭配w一起使用,如此离开时还可存文件]]></content>
<categories>
<category>Linux</category>
</categories>
<tags>
<tag>使用</tag>
<tag>vim</tag>
<tag>vi</tag>
<tag>编辑器</tag>
</tags>
</entry>
<entry>
<title><![CDATA[centos常见配置修改]]></title>
<url>%2F2018%2F12%2F26%2FLinux%2Fcentos%E5%B8%B8%E8%A7%81%E9%85%8D%E7%BD%AE%E4%BF%AE%E6%94%B9%2F</url>
<content type="text"><![CDATA[原文: http://limingming.org/index.php/2018/12/linux-common-config-vi/ 字符集在登录系统的时候经常会看到乱码的情况,经常会修改配置utf-8解决中文乱码的问题; centos6.5和centos7修改系统默认字符集的方式有所改变,通过执行命令修改配置的方式是一样的: 查看系统支持的字符集 1locale -a centos6.5修改系统字符集 临时生效:1234LANG="zh_CN.utf8"echo $LANG# 显示zh_CN.utf8 永久生效:123vim /etc/sysconfig/i18n# 编辑内容LANG="zh_CN.utf8" centos7修改系统字符集 临时生效的方式和Centos6.5设置一样; 永久生效需要修改配置文件/etc/locale.conf: 123vim /etc/locale.conf # 编辑内容LANG="zh_CN.utf8" 时间设置时区 查看当前时区 1date -R 修改设置Linux服务器时区 方法一 1tzselect 方法二 仅限于RedHat Linux 和 CentOS 1timeconfig 替换系统时区文件 1cp /usr/share/zoneinfo/$主时区/$次时区 /etc/localtime 例如设置为上海的时区,但是需要注意的是,如果你设置的时间是北京时间早上7点,可能你执行覆盖上海的时区的时候会加一个小时,变成早上8点,因为上海属于东9区。1cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 修改时间 查看时间和日期 1date 设置时间和日期例如:将系统日期设定成2018年12月26日,晚上9点18分25秒 12date -s 12/26/2018date -s 21:18:25 将当前时间和日期写入BIOS,避免重启后失效 1hwclock -w cal 命令cal命令可以用来显示公历(阳历)日历。公历是现在国际通用的历法,又称格列历,通称阳历 1cal [参数][月份][年份]]]></content>
<categories>
<category>Linux</category>
</categories>
<tags>
<tag>修改</tag>
<tag>Centos</tag>
<tag>日期</tag>
<tag>字符集</tag>
<tag>乱码</tag>
</tags>
</entry>
<entry>
<title><![CDATA[syntax error near unexpected token $ do 报错问题]]></title>
<url>%2F2018%2F12%2F22%2FLinux%2Fsyntax-error-near-unexpected-token-do-r%E6%8A%A5%E9%94%99%E9%97%AE%E9%A2%98%2F</url>
<content type="text"><![CDATA[原文: http://limingming.org/index.php/2018/12/syntax-error-nea…pected-token-dor/ 介绍不知道大家有没有在windows上面编写shell脚本,然后部署到linux上运行的经历,如果你做过类似的事情,那你可能遇到过这个问题:syntax error near unexpected token $’do\r”,或者类似的问题。 运行shell脚本shell脚本,运行出错:syntax error near unexpected token$’do\r 问题原因Linux和windows下的回车换行符不兼容 文件格式区别 很久以前,人们用老式的电传打字机作为输入设备,它使用两个字符来另起新行。一个字符把滑动架移回首位 (称为回车:,另一个字符把纸上移一行(称为换行:), 当计算机问世后,由于存储器曾经非常昂贵。有些人就认定没必要用两个字符来表示行尾。于是UNIX 开发者决定他们可以用即,一个字符来表示行尾。Apple 开发者规定了用。开发 MS-DOS (以及微软视窗) 的那些家伙则决定沿用老式的 三种行尾格式如下: 1231. unix为: <LF> : /n 2. dos为: <CR><LF> : /r/n3. mac为: <CR> : /r 所以这也是为什么window将的文件转移到unix上会出现syntax error near unexpected token `$’do\r”的原因。 问题解决 在windows上可以用文本编辑器查看所有字符,例如notepad++,视图->显示符号->显示所有符号在每行的结尾显示了CRLF的符号问题正是由此产生的。 用文本编辑器解决办法,eclipse等编辑器都可以解决,拿notepad++来说,编辑->档案格式转换->转换为UNIX格式,再放到linux上运行就不会出现以上报错了。 使用dos2unix工具进行处理 在linux上安装dos2unix工具:sudo apt-get install dos2unix(根据系统使用不同命令安装),安装成功后可以定义一个shell脚本,或者手动执行一下命令: 1dos2unix *.sh 输出:dos2unix: converting file eval1.sh to Unix format … 就将这个文件转换为了linux下的执行文件了。]]></content>
<categories>
<category>Linux</category>
</categories>
<tags>
<tag>问题</tag>
<tag>do\r</tag>
<tag>字符</tag>
</tags>
</entry>
<entry>
<title><![CDATA[macOS常见问题记录]]></title>
<url>%2F2018%2F12%2F22%2F%E8%AE%A1%E7%AE%97%E6%9C%BA%2FmacOS%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E8%AE%B0%E5%BD%95%2F</url>
<content type="text"><![CDATA[安装第三方应用Mac安装第三方应用时提示”*.app”已损坏,打不开.这是因为安装权限问题,把隐私偏好设置的”允许所有来源”安装选项即可.新版Mac系统默认隐藏了”允许任何来源”隐藏了.使用sudo spctl –master-disable命令打开即可. 打开终端程序执行命令: 1sudo spctl --master-disable 然后输入你的密码就可以了 MAC打开多个Eclipse空间Mac上打开多个Eclipse方法是:找到Eclipse.app的位置,在Terminal中cd到这个目录 然后执行: 1open -n Eclipse.app]]></content>
<categories>
<category>计算机</category>
</categories>
<tags>
<tag>问题</tag>
<tag>MAC</tag>
<tag>OS</tag>
<tag>常见</tag>
</tags>
</entry>
<entry>
<title><![CDATA[log4j2使用]]></title>
<url>%2F2018%2F12%2F22%2FJava%2Flog4j2%E4%BD%BF%E7%94%A8%2F</url>
<content type="text"><![CDATA[原文:http://limingming.org/index.php/2018/12/log4j2-user-config/ 介绍log4j 兼容jdk6, 最新版本是1.2.17(不再进行更新),log4j2 不兼容jdk7之前的版本。但是,log4j 2 采用了异步写文件的机制,比log4j 提高了10倍以上的性能,log4j组件2.4以后的版本能够支持.properties格式的配置文件(之前的2.x版均不支持.properties配置),新版properties格式配置文件与其他格式(XML格式、JSON格式文件等)一样,配置的主要任务是完成对各类插件及其属性的定义。 xml 配置在spring boot2.1.1.RELEASE中配置使用log4j2: 123456789101112131415161718192021222324252627<!-- Exclude Spring Boot's Default Logging --><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency><!-- Add Log4j2 Dependency --><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId></dependency> 无厘头的问题使用以上配置之后出现了异常: 123456objc[24414]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_112.jdk/Contents/Home/bin/java (0x1045c54c0) and /Library/Java/JavaVirtualMachines/jdk1.8.0_112.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x1055ef4e0). One of the two will be used. Which one is undefined.SLF4J: Class path contains multiple SLF4J bindings.SLF4J: Found binding in [jar:file:/Users/limm/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]SLF4J: Found binding in [jar:file:/Users/limm/.m2/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.11.1/log4j-slf4j-impl-2.11.1.jar!/org/slf4j/impl/StaticLoggerBinder.class]SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder] 所以尝试排除各种依赖解决这个异常错误,但是排除了各种依赖,都没有解决这个问题,干脆重新删掉项目在eclipse中重新执行了一下: 1mvn clean eclipse:eclipse 然后重新导入到eclipse中,发现这个错误竟然好了,我真的对这个东西无语了,姑且认为我的这个错误是因为eclipse导致的吧,但是我更愿意相信可能我在操作这个的过程中,修改的某个地方但是我忘记了。但是第二天我重新建立一个项目,pom中配置的内容一样还是出现了上面的问题,我没有做其他任何操作重新执行了上面的步骤异常就消失了,我到写这个博客的日子还没有抛弃eclipse,具体来说应该是sts,接下来我可能换IDEA了。 XML配置文件我使用的是Spring boot2.1.1,所以log4j2 为2.1.1版本,所以我们用通用的xml配置。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051<?xml version="1.0" encoding="UTF-8"?><!--日志级别排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL --><!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出--><!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数--><configuration status="ERROR" monitorInterval="60"> <Properties> <!-- 下文中通过${log.path}获取这个配置路径 --> <Property name="log.path">/Users/limm/log/dialog-demo-web</Property> </Properties> <!--先定义所有的appender--> <appenders> <!--这个输出控制台的配置--> <console name="Console" target="SYSTEM_OUT"> <!--输出日志的格式--> <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/> </console> <File name="log" fileName="${log.path}/test.log" append="false"> <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/> </File> <RollingFile name="RollingFileInfo" fileName="${log.path}/info.log" filePattern="${log.path}/logs/${date:yyyy-MM}/info-%d{yyyy-MM-dd}.log.zip"> <!--只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)--> <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/> <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/> <Policies> <TimeBasedTriggeringPolicy modulate="true" interval="1"/> </Policies> </RollingFile> </appenders> <loggers> <!--过滤掉spring和mybatis的一些无用的DEBUG信息--> <logger name="org.springframework" level="INFO"/> <logger name="org.mybatis" level="INFO"/> <logger name="com.inspur.demo.web" level="INFO"/> <root level="info"> <appender-ref ref="Console"/> <appender-ref ref="RollingFileInfo"/> </root> </loggers></configuration> 启动过程中遇到: 12018-12-21 20:23:58,444 main INFO Log4j appears to be running in a Servlet environment, but there's no log4j-web module available. If you want better web container support, please add the log4j-web JAR to your web archive or server lib directory. 添加了依赖: 1234<dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-web</artifactId></dependency> XML配置语法 根节点属性根节点有两个属性,一个是status,一个是monitorinterval, status用来指定log4j2本身的日志的级别,我们上面的xml中为WARNmonitorinterval用于指定log4j自动监测间隔时间,单位是s,最小是5s Properties 标签在xml文件中,可以使用Properties 标签来自定义变量,方便其他地方的引用,当然用的最多的是通过log.path获取log,输出的跟路径。 123<Properties> <Property name="log.path">这里写日志输入的跟路径</Property></Properties> Appenders 节点 我们上面log4j中提到Appender,Appender是用来定义日志输出点的,一般常用有三个子节点,分别为Console、RollingFile、File,也可以参考log4j,下面介绍一下各个子节点的用处及常用的属性 Console节点用来定义输出到控制台的Appender: name : 指定Appender的名字,用于Logger节点引用 target : SYSTEM_OUT 或 SYSTEM_ERR,一般设置为:SYSTEM_OUT PatternLayout : 指定日志输出格式,默认为%m%n 1234<console name="Console" target="SYSTEM_OUT"> <!--输出日志的格式--> <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/></console> File节点用来定义输出到指定位置的文件的Appender: name : 和console一样,指定Appender的名字,用于Logger节点引用 fileName : 指定输出日志的目的文件带全路径的文件名 append : 是否追加,默认为ture。ture是将新日志追加到原日志文件尾部,false则是删除已有文件,重建新文件 PatternLayout : 指定日志输出格式,默认为%m%n 123<File name="log" fileName="log/test.log" append="false"> <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/></File> 上面的File节点指定输出文件位置的Appender,但是对于文件输入的约束是很弱的,而RollingFile节点也用来定义输出到指定位置的文件的Appender,但是却灵活的多,记录的文件内容可进行详细的拆分,例如对于文件大小,根据时间等: name : 指定Appender的名字,用于Logger节点引用 fileName : 指定输出日志的目的文件带全路径的文件名 filePattern:指定拆分出去的日志文件的全路径的文件名以及格式 PatternLayout : 指定日志输出格式,默认为%m%n Policies : 指定滚动日志的策略,就是什么时候进行新建日志文件输出日志. TimeBasedTriggeringPolicy : 基于时间进行日志的滚动 SizeBasedTriggeringPolicy : 基于文件大小进行日志的滚动 ThresholdFilter : 日志过滤器 1234567891011121314151617181920212223<RollingFile name="RollingFileInfo" fileName="${log.path}/info.log" filePattern="${log.path}/logs/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log.zip"> <!--只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)--> <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/> <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/> <Policies> <TimeBasedTriggeringPolicy modulate="true" interval="1"/> </Policies></RollingFile> <!-- 一般般情况下都使用RollingRandomAccessFile,RollingRandomAccessFile可以按照日志名称的格式进行定期备份,拥有一定的备份策略。 1.是否压缩备份日志:直接在filePattern属性的文件名称最后加对应的压缩后缀,如gzip压缩用 .gz --> <RollingRandomAccessFile name="errorFile" fileName="${fileName}/mic-error.log" filePattern="${fileGz}/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.mic-error.gz"> <PatternLayout> <pattern>%d %p %C{1.} [%t] %m%n</pattern> </PatternLayout> <Policies> <TimeBasedTriggeringPolicy interval="6" modulate="true" /> <SizeBasedTriggeringPolicy size="10 MB"/> </Policies> <!-- 指定每天的最大压缩包个数,默认7个,超过了会覆盖之前的 --> <DefaultRolloverStrategy max="50"/> </RollingRandomAccessFile> Ps:TimeBasedTriggeringPolicy这个滚动策略的属性interval,它是指日志进行滚动的间隔,那么它的单位具体是什么呢?关键点在于filePattern的日志文件名所含有的日期格式%d{yyyy-MM-dd},这里日期格式具体到了天,那么以天为单位,若是日期具体到%d{yyyy-MM-dd-HH-mm}分钟的话,那么就是以分钟为单位。 Loggers节点 Loggers节点下一般会配置root和logger节点,root节点用来指定项目的根日志,如果没有单独指定logger,那么就会默认使用该root日志输出。 level :日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF. appender-ref :root的子节点,用来指定该日志输出到哪个Appender 1234<root level="info"> <appender-ref ref="Console"/> <appender-ref ref="RollingFileInfo"/></root> Logger节点用来单独指定日志的形式,比如要为某个包下所有的class或者某个具体的class指定不同的日志级别等。 level : 日志输出级别 name : 用来指定该Logger所适用的类或者包. AppenderRef :Logger的子节点,用来指定该日志输出到哪个Appender,如果没有指定,就会默认继承自Root additivity :是否向上级传递日志 true(默认)或false 1234<!--过滤掉spring和mybatis的一些无用的DEBUG信息--><logger name="org.springframework" level="INFO"/><logger name="org.mybatis" level="INFO"/><logger name="com.baiding" level="INFO"/> 若我们为logger指定了AppenderRef ,别忘了将logger的additivity 属性设置为false,要不然日志可能会在指定的Appender中输出两遍 Log4j2异步输出日志Log4j2突出新特性支持高效低延迟的异步化写日志,日志异步优点是单独的进程打印日志,可以提高日志执行效率,减少日志功能对正常业务的影响。使用了disruptor这个开源的并发框架进行日志的异步输出,所以首先得导入disruptor.jar包 12345<dependency> <groupId>com.lmax</groupId> <artifactId>disruptor</artifactId> <version>3.4.2</version></dependency> 异步输出模式 全异步 异步和非异步混合输出 异步和非异步混合模式,性能还是比较好的,这种模式的启用,主要在于两个节点的使用,分别为AsyncRoot和AsyncLogger,这两个节点可以和Root 或 Logger节点混合使用。 123456789<loggers> <AsyncRoot level="info"> <appender-ref ref="Console"/> <appender-ref ref="RollingFileInfo"/> </AsyncRoot> <AsyncLogger name="com.baiding" level="INFO" /> <AsyncLogger name="org.mybatis" level="INFO" /> <AsyncLogger name="org.springframework" level="INFO" /></loggers> 参考配置文件模版12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485<?xml version="1.0" encoding="UTF-8"?> <!-- 在运行时,可以动态修改配置文件,不用重启服务,在固定时长更新一次配置文件。monitorInterval设置更新配置文件时长, 单位为seconds , min senconds >= 5secondes --> <Configuration monitorInterval="30" > <Properties> <Property name="log.path">E:\log4j2_log\</Property> </Properties> <Appenders> <!-- 控制台appdener--> <Console name="STDOUT" target="SYSTEM_OUT"> <PatternLayout charset="UTF-8" pattern="%m%n"/> </Console> <!-- File appdener--> <File name="MyFile" fileName="logs/app.log" bufferedIO="true" > <PatternLayout> <Charset>UTF-8</Charset> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> </File> <!-- RandomAccessFile 性能高于 File--> <RandomAccessFile name="MyFile" fileName="logs/RandomAccessFile.log" > <PatternLayout> <Charset>UTF-8</Charset> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> </RandomAccessFile> <!--<RollingFile></RollingFile>--> <!-- 注意:一般情况下都使用RollingRandomAccessFile 。 RollingRandomAccessFile可以按照日志名称的格式进行定期备份,拥有一定的备份策略。 1.是否压缩备份日志:直接在filePattern属性的文件名称最后加对应的压缩后缀,如gzip压缩用 .gz --> <RollingRandomAccessFile name="RollingRandomAccessFile" fileName="logs/RollingRandomAccessFile.log" filePattern="logs/RollingRandomAccessFile-%d{yyyy-MM-dd}-%i.log.gz"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> <!-- 备份策略:满足其中一个就可以启动备份--> <Policies> <!-- interval 多久执行一次备份,单位为 RollingRandomAccessFile的属性filePattern中%d{yyyy-MM-dd}的最小时间单位,此处是天--> <TimeBasedTriggeringPolicy interval="1" modulate="true"/> <SizeBasedTriggeringPolicy size="250 MB"/> </Policies> <!-- 默认的备份策略:max="7"表示最多只保留7份日志,fileIndex属性是在拥有多个备份日志的时候,命令是以递增的数为文件名,max值时值大的文件是最新的内容,min值时值大的是最久的内容--> <DefaultRolloverStrategy fileIndex="max" max="7"> <!-- 删除指定目录下60天之前的日志--> <Delete basePath="${log.path}" maxDepth="2"> <IfFileName glob="*/app-*.log.gz" /> <IfLastModified age="60d" /> </Delete> </DefaultRolloverStrategy> </RollingRandomAccessFile> <!-- 异步 appder ,使用的是ArrayBlocingQueue --> <Async name="Async"> <AppenderRef ref="MyFile"/> </Async> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="MyFile"/> </Root> <!-- logger additivity属性:如果设置为true(默认值)则log会被打印两次,这里的logger和root--> <Logger name="com.foo.bar.MyApp" level="info" additivity="true"> <appender-ref ref="RandomAccessFile"/> </Logger> <!-- 异步 logger:使用了disruptor类库,代替Jdk中的queue,性能提高很多 includeLocation属性是指layout中的 %C or $class, %F or %file, %l or %location, %L or %line, %M or %method,异步logger默认为false,如果设置为true,会影响logger的性能 --> <AsyncLogger name="com.foo.test" level="info" additivity="false" includeLocation="false"> <appender-ref ref="log4j2test"/> <appender-ref ref="STDOUT"/> </AsyncLogger> </Loggers> </Configuration>]]></content>
<categories>
<category>Java</category>
</categories>
<tags>
<tag>log4j2</tag>
<tag>介绍</tag>
<tag>配置</tag>
<tag>使用</tag>
</tags>
</entry>
<entry>
<title><![CDATA[spring boot2.x日志体系问题]]></title>
<url>%2F2018%2F12%2F21%2FSpring%2Fspring-boot2-x%E6%97%A5%E5%BF%97%E4%BD%93%E7%B3%BB%E9%97%AE%E9%A2%98%2F</url>
<content type="text"><![CDATA[原文:http://limingming.org/index.php/2018/12/spring-boot2-x-log-config/ 介绍原来一直使用spring mvc,spring框架是3.6.2.配置的是log4j的日志,使用slf4j的log4j结合的方式,最近开发一个新的项目,我搭建了spring boot1.3.6.RELEASE的框架,能使用集成log4j,但是确实有冲突的问题,一直报logback有冲突的信息:12345SLF4J: Class path contains multiple SLF4J bindings.SLF4J: Found binding in [jar:file:/Users/limm/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]SLF4J: Found binding in [jar:file:/Users/limm/.m2/repository/org/slf4j/slf4j-log4j12/1.6.1/slf4j-log4j12-1.6.1.jar!/org/slf4j/impl/StaticLoggerBinder.class]SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder] 操作:123456789101112131415161718<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> <exclusion> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </exclusion> </exclusions> </dependency> 通过依赖树进行了各种排除,才能解决不使用slf4j,使用log4j输出日志,但是接下来进行了spring boot的升级,升级之后才发现springboot 2.x版本不支持log4j了,支持log4j2,既然log4j2是它本来支持的所以准备换成log4j2,配置文件是xml支持原来的log4j.properties,key value的properties文件了。 经过这一番折腾,才发现日志这个体系太繁杂了,所以想梳理一下日志相关的这个体系。 日志体系见的Java日志框架有log4j、logback、j.u.l (java.util.logging),常用的日志门面,SLF4J、commons-logging,其中,j.u.l是Java原生库,但是在Java 1.4中才被引用; commons-logging出自Apache,用于桥接j.u.l和log4j;log4j、logback和SLF4J出自同一个作者。出现的时间顺序: log4j—>j.u.l—-> commons-logging—–>SLF4J—->logback log4j在JDK 1.3及以前,Java打日志System.err.println()或者e.printStackTrace(),或者这样根本不算是完善的日志,Debug日志被写到STDOUT流,错误日志被写到STDERR流,这样的日志无法定制,日志粒度小,哪里有压迫哪里就有反抗,哪里有问题,哪里就有有解决问题的办法,所以log4j应运而生,如果感兴趣可以看一下log4j使用。 j.u.l在log4j之后,可能是受到了log4j的启发,Sun在Java1.4版本中引入了java.util.logging,但是不如log4j完善,需要开发人员编写Appenders(Sun称之为Handlers)。 commons-logging第三个出现的是commons-logging,是一个API bridge,可以兼容上面的两个框架,然而commons-logging对Log4j和j.u.l的配置问题兼容的并不好,使用commons-loggings还可能会遇到类加载问题,导致NoClassDefFoundError的错误出现,或许你也经常会遇到这个问题。 SLF4J看到上面的这些问题,可能log4j的作者忍不住了(纯属我个人观点),他发起了SLF4j,只要使用SLF4J提供的接口,即可隐藏日志的具体实现,SLF4J提供的核心API是一些接口和一个LoggerFactory的工厂类,大大简便了开发人员的日志配置,方便使用。 logbacklogback和log4j是同一个作者创作,可以认为logback比log4j有更多的优点。 Spring 依赖日志包日志框架出现先看一下spring boot 2.1.1.RELEASE版本依赖的日志: 从上图可以看出,Spring Boot通过jul-to-slf4j.jar去适配了我们上面提到的JUL日志框架,通过log4j-to-slf4j.jar去适配了log4j日志框架。Spring5.x相对于Spring4.x去除了原来默认使用的JCL 框架,而是采用SLF4j这个通用的日志门面,所以Spring Boot2.x相对于Spring Boot1.x来说去除了对JCL的适配。 SpringBoot能自动适配所有的日志,其底层使用slf4j+logback的方式记录日志,引入其他框架的时候,只需要 把这个框架依赖的日志框架排除掉即可,因为Spring Boot会通过自己的jar去替代; logback日志级别logbac日志级别从低到高分别为TRACE, DEBUG, INFO, WARN, ERROR 配置文件:logback.xml也可以命名为logback-spring.xml , logback-spring.groovy , logback.xml ,logback.groovy,上面提到的更多优点,也包含这个,支持多种格式的配置文件。 以xml为例:1234567891011121314151617181920212223242526272829303132333435363738394041<?xml version="1.0" encoding="UTF-8"?><configuration scan="true" scanPeriod="60 seconds" debug="false"> <contextName>spring-boot-logging</contextName> <property name="log.path" value="log" /> <!--输出到控制台--> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <!-- 级别过滤 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>INFO</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> <encoder> <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <!--输出到文件--> <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${log.path}/spring-boot-logging.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${log.path}/spring-boot-logging.%d{yyyy-MM-dd}.log.zip</fileNamePattern> <!-- 日志保存周期 --> <maxHistory>30</maxHistory> <!-- 总大小 --> <totalSizeCap>1GB</totalSizeCap> </rollingPolicy> <encoder> <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <root level="info"> <appender-ref ref="console" /> <appender-ref ref="file" /> </root> <!-- logback为java中的包 --> <logger name="com.baiding"/></configuration> log4j2123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657<?xml version="1.0" encoding="UTF-8"?><!--日志级别排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL --><!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出--><!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数--><configuration status="WARN" monitorInterval="30"> <Properties> <Property name="log.path">log</Property> </Properties> <!--先定义所有的appender--> <appenders> <!--这个输出控制台的配置--> <console name="Console" target="SYSTEM_OUT"> <!--输出日志的格式--> <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/> </console> <File name="log" fileName="${log.path}/test.log" append="false"> <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/> </File> <RollingFile name="RollingFileInfo" fileName="${log.path}/info.log" filePattern="${log.path}/logs/${date:yyyy-MM}/info-%d{yyyy-MM-dd}.log.zip"> <!--只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)--> <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/> <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/> <Policies> <TimeBasedTriggeringPolicy modulate="true" interval="1"/> </Policies> </RollingFile> </appenders> <!--然后定义logger,只有定义了logger并引入appender,appender才会生效--> <loggers> <!--过滤掉spring和mybatis的一些无用的DEBUG信息--> <logger name="org.springframework" level="INFO"/> <logger name="org.mybatis" level="INFO"/> <logger name="com.baiding" level="INFO"/> <root level="info"> <appender-ref ref="Console"/> <appender-ref ref="RollingFileInfo"/> </root> </loggers></configuration>]]></content>
<categories>
<category>Spring</category>
</categories>
<tags>
<tag>日志</tag>
<tag>spring</tag>
<tag>输出</tag>
<tag>体系</tag>
</tags>
</entry>
<entry>
<title><![CDATA[log4j使用]]></title>
<url>%2F2018%2F12%2F19%2FJava%2Flog4j%E4%BD%BF%E7%94%A8%2F</url>
<content type="text"><![CDATA[原文:http://limingming.org/index.php/2018/12/log4j-use-log/ log4j介绍Log4j由三个组件构成: 日志信息的优先级 日志输出级别优先级:ERROR、WARN、 INFO、DEBUG,从名称就可以看出显示的为日志的重要级别程度 日志信息的输出目的地 日志信息的输出目的地指定了日志将打印到控制台还是输出到文件中 日志信息的输出格式 而输出格式则控制了日志信息内容的显示格式 引用包这里引用包是在spring boot低版本的时候支持,spring boot高版本支持log4j2了,下面我们会有相关的记录。 1234<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j</artifactId> </dependency> 上面是列举的在spring boot中使用log4j,继承父项目中的版本,版本应该是1.3.2.RELEASE版本,如果其他项目可以自己指定log4j的版本,使用maven的话可以有相关联的间接依赖包,如下图: 配置配置文件在使用log4j中是至关重要的,但是也可以不采用配置文件,可以在代码中配置log4j的使用,但是会比较零散,而且不灵活,配置文件的配置方式又分为xml格式的配置文件和键值对类型的配置文件。 properties文件123456789101112131415161718192021222324252627282930313233343536LOG_DIR=/Users/limm/log/dialog-demo-web# Set root category priority to WARN and its only appender to FILE.log4j.rootLogger=INFO,tracelog4j.logger.com.inspur.dialog.demo.web=DEBUG,projectlog4j.additivity.com.inspur.dialog.demo=false#spring日志监控log4j.logger.org.springframework.web=INFO,springlog4j.additivity.org.springframework=false# 控制台输出log4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n#spring日志打印log4j.appender.spring=org.apache.log4j.RollingFileAppenderlog4j.appender.spring.File=${LOG_DIR}/spring.loglog4j.appender.spring.MaxFileSize=5000000log4j.appender.spring.layout=org.apache.log4j.PatternLayoutlog4j.appender.spring.layout.ConversionPattern==[%d{ISO8601}] %-5p %-x %X{user} %n %m%nlog4j.appender.trace=org.apache.log4j.RollingFileAppenderlog4j.appender.trace.File=${LOG_DIR}/trace.loglog4j.appender.trace.MaxFileSize=5000000log4j.appender.trace.layout=org.apache.log4j.PatternLayoutlog4j.appender.trace.layout.ConversionPattern=[%d{ISO8601}] %-5p %-x %X{user} %n %m%nlog4j.appender.project=org.apache.log4j.RollingFileAppenderlog4j.appender.project.File=${LOG_DIR}/dialog-demo-web.loglog4j.appender.project.MaxFileSize=5000000log4j.appender.project.layout=org.apache.log4j.PatternLayoutlog4j.appender.project.layout.ConversionPattern=[%d{ISO8601}] %-5p %-x %X{user} %n %m%n 配置跟语法: 123log4j.rootLogger = [ level ] , appenderName, appenderName, …# level可以为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL,也可以允许自定义,log4j建议使用我们开头所说的那四类级别:ERROR、WARN、INFO、DEBUG 通过level的定义,我们能控制日志的输入级别,如果定义为WARN的话,那INFO和DEBUG讲不会输出;通过appenderName控制日志输出的位置,可以指定多个输出的目的地。 配置输出位置1234log4j.appender.appenderName = appender类的全路径限定类名称log4j.appender.appenderName.option1 = value1 … log4j.appender.appenderName.option = valueN 上面提到的“appender类的全路径限定类名称”有以下几种: org.apache.log4j.ConsoleAppender(控制台) org.apache.log4j.FileAppender(文件) org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件) org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件) org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方) 日志信息的输出格式1234log4j.appender.appenderName.layout =layout类的全路径限定类名称log4j.appender.appenderName.layout.option1 = value1 … log4j.appender.appenderName.layout.option = valueN “layout类的全路径限定类名称”: org.apache.log4j.HTMLLayout(以HTML表格形式布局) org.apache.log4j.PatternLayout(可以灵活地指定布局模式) org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串) org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息) log4j采用类似于C语言中print函数格式化日志信息,参数如下: 12345678%m 输出代码中的指定消息%p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL %r 输出自应用启动到输出该log信息耗费的毫秒数 %c 输出所属的类目,通常就是所在类的全名 %t 输出产生该日志事件的线程名 %n 输出一个回车换行符,Windows平台为“rn”,Unix平台为“n” %d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921 %l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java:10) 代码中使用123456789101112131415161718192021package org.limingming.springboot.web;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;/** * @author limm on 2018/06/03 */@RestControllerpublic class Log4jController { private Logger logger = LoggerFactory.getLogger(this.getClass()); @RequestMapping("/test") public String sayHello(){ logger.info("这里是log4j使用的demo"); return "Hello,World!"; }} 或许你已经发现了,我们使用的是slf4j:import org.slf4j.Logger;import org.slf4j.LoggerFactory;如果我们直接使用log4j的话可能就变成了: 1234567891011121314151617181920package org.limingming.springboot.web;import org.apache.log4j.Logger;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;/** * @author limm on 2018/06/03 */@RestControllerpublic class Log4jController { private Logger logger = Logger.getLogger(this.getClass()); @RequestMapping("/test") public String sayHello(){ logger.error("异常", e); return "Hello,World!"; }} SLF4J不同于其他日志类库,与其它有很大的不同。SLF4J(Simple logging Facade for Java)不是一个真正的日志实现,而是一个抽象层( abstraction layer),它允许你在后台使用任意一个日志类库。 SLF4J在语法上比log4j有更优的处理: 代码简化 log4j: 123if (logger.isDebugEnabled()) { logger.debug("Processing trade with id: " + id + " symbol: " + symbol);} slf4j: 1logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol); 联想补充: e.printStackTrace()不会做任何操作,不会输出到日志,只会打印到控制台信息,不要使用这种方式 log.error(e.getMessage())log4j的话,只能够输出异常信息,但是并不包括异常堆栈,不能定位到准确的出错信息 log.error(e)log4j,除了输出异常信息外,还能输出异常类型,但是同样不包括异常堆栈 显示堆栈信息的话可以采用上面我们给出的例子的那种方式:log.error(Object var1, Throwable var2); 使用java 包: 123slf4j-api-1.6.1.jar – JAR for SLF4J APIlog4j-1.2.16.jar – JAR for Log4J APIslf4j-log4j12-1.6.1.jar – Log4J Adapter for SLF4J 如果使用maven的话: 1234567891011<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.6.1</version></dependency><dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.6.1</version></dependency> 如果在spring boot中使用的话,引用可能会的导致冲突的异常,无法让日志生效,需要从spring中排除掉依赖的包!]]></content>
<categories>
<category>Java</category>
</categories>
<tags>
<tag>配置</tag>
<tag>使用</tag>
<tag>log4j</tag>
<tag>日志</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Spring boot 部署到tomcat中注意事项]]></title>
<url>%2F2018%2F12%2F18%2FSpring%2FSpring-boot-%E9%83%A8%E7%BD%B2%E5%88%B0tomcat%E4%B8%AD%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9%2F</url>
<content type="text"><![CDATA[原文:http://limingming.org/index.php/2018/12/spring-boot-deploy-to-tomcat/ 介绍一般我们使用spring boot是使用内嵌的容器,一般不会将其部署到tomcat容器里,但是会有一些情况需要我们部署spring boot到tomcat中,部署过程中遇到一些问题,特此记录。 修改Application类如果你没有修改你的Application类就直接部署到tomcat中肯定会遇到一些无法请求到后台的服务的问题,只可以访问前端页面,修改你的Application类如下: 123456789@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class}) public class Application extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(Application.class); } } 如果我们用jar包启动,流程是执行SpringBootApplication的run方法,启动IOC容器,然后创建嵌入式Servlet容器,war包流程是先是启动Servlet服务器,服务器启动Springboot应用(springBootServletInitizer),然后启动IOC容器,根据Servlet3.0+规则,tomcat启动过程中会经过一系列的过程,最终会找到每个相关的WebApplicationInitilizer调用自己的onstartup方法,WebApplicationInitializer有个抽象实现类SpringBootServletInitializer(继承这个这个类),则会调用每一个WebApplicationInitializer实例(包括SpringBootServletInitializer)的onStartup方法。实例执行onStartup方法的时候会通过createRootApplicationContext方法来执行run方法,那这个过程就意味着,我们启动就和jar包启动一样了,如果你启动tomcat过程中仔细观看打印信息,也会注意到这一点。 SpringBootServletInitializer即是一个org.springframework.web.context.WebApplicationContext,容器启动时会调用其onStartup(ServletContext servletContext)方法,主要方法就是createRootApplicationContext(servletContext)方法。 12345678910111213public void onStartup(ServletContext servletContext) throws ServletException { this.logger = LogFactory.getLog(this.getClass()); final WebApplicationContext rootAppContext = this.createRootApplicationContext(servletContext); if(rootAppContext != null) { servletContext.addListener(new ContextLoaderListener(rootAppContext) { public void contextInitialized(ServletContextEvent event) { } }); } else { this.logger.debug("No ContextLoaderListener registered, as createRootApplicationContext() did not return an application context"); } }]]></content>
<categories>
<category>Spring</category>
</categories>
<tags>
<tag>部署</tag>
<tag>Spring</tag>
<tag>boot</tag>
<tag>tomcat</tag>
</tags>
</entry>
<entry>
<title><![CDATA[centos下各种源的配置方式]]></title>
<url>%2F2018%2F12%2F17%2FLinux%2Fcentos%E4%B8%8B%E5%90%84%E7%A7%8D%E6%BA%90%E7%9A%84%E9%85%8D%E7%BD%AE%E6%96%B9%E5%BC%8F%2F</url>
<content type="text"><![CDATA[原文:http://limingming.org/index.php/2018/12/centos-repo-config/ 介绍平时在开发过程中很多时候部署环境,或者使用一些开发工具都会用到外部的源,特此记录分享; yum源配置编辑文件: 添加/etc/yum.repos.d/CentOS-inspur.repo 12345[CentOS-inspur]name=Nexus Repositorybaseurl=http://maven.inspur.com/repository/yum-public/$releasever/os/$basearch/enabled=1gpgcheck=0 执行命令: 12yum clean all yum list all pip源编辑文件: 全局的位于 /etc/pip.conf用户级别的位于 $HOME/.pip/pip.conf 123[global]trusted-host = maven.inspur.comindex-url = http://maven.inspur.com/repository/pypi-public/simple easy_install源 临时使用使用-i 参数,这个也适用于pip命令 1easy_install pip -i http://maven.inspur.com/repository/pypi-public/simple 修改配置文件修改~/.pydistutils.cfg 12[easy_install]index_url = http://maven.inspur.com/repository/pypi-public/simple npm源执行命令: 1npm config set registry http://maven.inspur.com/repository/npm-public/]]></content>
<categories>
<category>Linux</category>
</categories>
<tags>
<tag>centos</tag>
<tag>配置</tag>
<tag>pip</tag>
<tag>yum</tag>
<tag>源</tag>
</tags>
</entry>
<entry>
<title><![CDATA[CentOS7 安装pip]]></title>
<url>%2F2018%2F12%2F17%2FLinux%2FCentOS7-%E5%AE%89%E8%A3%85pip%2F</url>
<content type="text"><![CDATA[原文:http://limingming.org/index.php/2018/12/centos7-install-pip/ 准备环境yum install gcc libffi-devel openssl-devel libxml2 libslt-devel libxml2-devel python-devel -y 安装easy_installyum install python-setuptools 安装pipeasy_install pip 如果你安装的服务器处于断网状态,需要配置内部能访问的源,可以参考各种配置源的方式]]></content>
<categories>
<category>Linux</category>
</categories>
<tags>
<tag>安装</tag>
<tag>centos</tag>
<tag>pip</tag>
</tags>
</entry>
<entry>
<title><![CDATA[jenkins中SSH remote hosts配置]]></title>
<url>%2F2018%2F12%2F15%2F%E5%BC%80%E5%8F%91%E8%80%85%E6%89%8B%E5%86%8C%2Fjenkins%E4%B8%ADSSH-remote-hosts%E9%85%8D%E7%BD%AE%2F</url>
<content type="text"><![CDATA[原文 介绍今天配置自己的系统在jenkins中,能让测试人员实时的构建测试,但是在配置ssh remote hosts的时候出现了一点小问题,特此记录;使用pipeline的方式和执行shell脚本的方式很快就能搭建完成,但是本来有可以配置“构建一个maven项目”的配置为什么还要使用其他的呢,所以就采用了这种方式。但是却在最后一步出现了问题,使用ssh部署到远程服务器上的时候找不到在哪里配置remote hosts。 操作 在Jenkins主界面,系统管理->管理插件->安装SSH Plugin; 系统管理->Configure(系统设置)->SSH remote hosts 配置完成但是无法连接,测试连接粗错; 所以进行了以下操作: * 两台机执行ssh-keygen -t rsa ,生成id_rsa.pub文件 * 在jenkins linux执行命令:scp /home/xxxx/.ssh/id_rsa.pub [email protected]:/home/xxxx/.ssh/authorized_keys 输入密码拷贝文件 就可以了,其实这样就可以进行不实用密码在jenkins上执行远程机器的命令: 1ssh -p 22 [email protected].*.* "df -h" 再测试就可以连接成功了。如果中间再出现访问权限问题(Jenkins Publish over ssh authentification failed with private key),那可以考虑一下远程机器是不是权限设置有问题,在远程机器上执行: 12chmod 700 ~/.sshchmod 600 ~/.ssh/authorized_keys 冲突解决人生不如意,十之八九,git使用过程中如果没有遇到过冲突,那绝对也是很离奇的事件。 我们平时使用git遇到冲突一般是pull代码或者push代码的时候,还有合并分支的时候。“git pull”操作等于“git fetch + git merge refs/remotes/origin/master”由此可见,git fetch更安全一点,不会合并代码。 一般解决过程: 在报错的目录下执行: git rebase remote-branch-name 先编辑冲突,然后git commit提交 执行 git add -u(-u 表示把所有已track的文件的新的修改加入缓存,但不加入新的文件) git rebase –continue (重复这这些步骤,直到rebase冲突解决完成) 如果想要恢复修改bug之前的状态,执行:git rebase –abort 冲突产生后会有<<<<>>>>这些内容,<<<<<<<HEAD 和=====之间的内容是我们本地的修改。 为什么会使用rebase? git rebase 和 git merge 一样都是用于从一个分支获取并且合并到当前分支,但是他们采取不同的工作流程。从上面你可以可能看到了git rebase是一个一个处理冲突的。本质上git merge会产生一个新的commit,合并的时候是全部合并,修改完成冲突就可以提交了,记录了真实的commit情况,包括每个分支的详情,但是如果频繁的使用,就会导致commit信息比较混乱。git rebase不会一次性合并,而是一个一个处理,不会有commit信息,会合并之前的commit历史,这样会让他的提交历史比较简洁,它的优点也是它的缺点,以为重写了commit历史,所以,导致提交历史不明晰。]]></content>
<categories>
<category>开发者手册</category>
</categories>
<tags>
<tag>远程</tag>
<tag>ssh</tag>
<tag>jenkins</tag>
<tag>连接</tag>
</tags>
</entry>
<entry>
<title><![CDATA[This account is currently not available问题]]></title>
<url>%2F2018%2F12%2F15%2FLinux%2FThis-account-is-currently-not-available%E9%97%AE%E9%A2%98%2F</url>
<content type="text"><![CDATA[原文:http://limingming.org/index.php/2018/12/this-account-is-currently-not-available/ 问题描述增加一个用户,并切换用户时提示错误: 1234567891011useradd limmpasswd limmsu limm# 错误信息# This account is currently not available``` # 解决办法```shellusermod -s /bin/bash limm 虽然简单,但是实用,的确困扰了自己几分钟的时间!]]></content>
<categories>
<category>Linux</category>
</categories>
<tags>
<tag>解决</tag>
<tag>用户</tag>
<tag>无法</tag>
<tag>切换</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Git使用介绍]]></title>
<url>%2F2018%2F12%2F13%2FGit%2FGit%E4%BD%BF%E7%94%A8%E4%BB%8B%E7%BB%8D%2F</url>
<content type="text"><![CDATA[git是一个分布式版本控制软件,最初由林纳斯·托瓦兹创作,于2005年以GPL发布。最初目的是为更好地管理Linux内核开发而设计。应注意的是,这与GNU Interactive Tools(一个类似Norton Commander界面的文件管理器)有所不同。git最初的开发动力来自于BitKeeper和Monotone。git最初只是作为一个可以被其他前端(比如Cogito或Stgit)包装的后端而开发的,但后来git内核已经成熟到可以独立地用作版本控制。很多著名的软件都使用git进行版本控制,其中包括Linux内核、X.Org服务器和OLPC内核等项目的开发流程。 一、重要概念 Workspace:工作区(在当前仓库中,新增,更改,删除,即当前的工作空间) Index / Stage:暂存区(它实际上就是一个包含文件索引的目录树,像是一个虚拟的工作区,这个工作区内存储了文件名、文件的状态等,这些都是存储在.git下的index文件中,文件内容存储在.git/object中,如果使用git add命令添加,将会更新到暂存区内) Repository:仓库区(或本地仓库) Remote:远程仓库 下图中为专业术语英文对照表: Git提及到代码的流程是:1工作区 -- add -- > 暂存区 -- commit -- > 版本库 -- push -- > 远程仓库 仓库区和版本库、暂存库的关系: 二、常用命令(1) 获取代码仓库12345678# 创建一个代码仓库,在当前目录下$ git init# 创建代码仓库,在projectname文件夹下初始化仓库$ git init [projectname]# 从远程下载仓库并获取仓库的“所有”信息$ git clone [url] (2) 操作文件1234567891011121314151617181920# 添加指定文件到暂存区$ git add [file1] [file2] ...# 添加指定目录到暂存区,包括子目录和子目录文件$ git add [dir]# 添加当前目录下的的所有的文件到暂存区中去$ git add .# p是patch的意思,对于同一个文件的多处变化,可以实现分次提交$ git add -p# 将工作区中的文件删除并同步删除操作到暂存区$ git rm [file1] [file2] ...# 停止追踪指定文件的状态,但是文件还会保留在工作区,比如误提了忽略文件,再添加忽略文件的时候可以执行这个命令忽略追踪这个文件的状态,让忽略文件生效$ git rm --cached [file]# 改名工作区文件,并同步到缓存区$ git mv [file-original] [file-renamed] (3) 提交代码123456789101112131415161718# add内容后,内容在暂存区,这个操作让暂存区内容到仓库区$ git commit -m [message]# 同上,不过指定了文件$ git commit [file1] [file2] ... -m [message]# 提交工作区与上次commit的变化,直接到仓库区$ git commit -a# 提交时后显示所有的diff信息$ git commit -v# 替换上一次的提交,包含提交信息$ git commit --amend -m [message]# 从新做一次commit,不包含提示信息$ git commit --amend [file1] [file2] ... (4) 分支操作123456789101112131415161718192021222324252627282930313233343536373839404142434445# 列出所有本地分支$ git branch# 列出所有远程分支$ git branch -r# 列出所有本地分支和远程分支$ git branch -a# 创建一个新分支,但是还是处于当前分支,不会切换到新分支下$ git branch [branch-name]# 新建一个分支,并切换到新的分支下$ git checkout -b [branch]# 新建一个分支,指向指定分支的commit$ git branch [branch] [commit]# 新建一个分支,与指定的远程分支建立同步的追踪关系$ git branch --track [branch] [remote-branch]# 切换到指定分支,并更新工作区$ git checkout [branch-name]# 切换到上一个分支$ git checkout -# 建立追踪关系,在现有分支与指定的远程分支之间$ git branch --set-upstream [branch] [remote-branch]# 合并指定分支到当前分支$ git merge [branch]# 将一个commit合并进当前分支$ git cherry-pick [commit]# 删除某个分支$ git branch -d [branch-name]# 删除远程分支$ git push origin --delete [branch-name]$ git branch -dr [remote/branch]# 设置默认提交分支$ git branch --set-upstream-to=origin/<branch> master (5) 标签操作1234567891011121314151617181920212223242526# 列出tag列表$ git tag# 在当前commit下创建一个tag$ git tag [tag]# 在执行commit下创建tag$ git tag [tag] [commit]# 删除本地tag$ git tag -d [tag]# 删除远程tag$ git push origin :refs/tags/[tagName]# 查看tag信息$ git show [tag]# 提交指定tag$ git push [remote] [tag]# 提交所有tag$ git push [remote] --tags# 新建一个分支,指向某个tag$ git checkout -b [branch] [tag] (6) 查看信息123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657# 显示有变更的文件$ git status# 显示当前分支的版本历史$ git log# 显示commit历史包含commit变更的文件等$ git log --stat# 搜根据关键词搜索提交历史$ git log -S [keyword]# 显示某一个commit之后的一切变动信息$ git log [tag] HEAD --pretty=format:%s# 同上,不过提交信息必须符合过滤搜索特征$ git log [tag] HEAD --grep feature# 显示文件的版本历史$ git log --follow [file]$ git whatchanged [file]# 显示文件的一切diff$ git log -p [file]# 指定过去的几次提交,实例中为5$ git log -5 --pretty --oneline# 按照提交次序显示提交过的用户$ git shortlog -sn# 显示人对于某个文件修改的时间等$ git blame [file]# 显示暂存区和工作区的差异,这个经常会用到$ git diff# 显示暂存区和上一个提交commit的差异$ git diff --cached [file]# 显示工作区与当前分支最新commit之间的差异$ git diff HEAD# 显示两次提交之间的差异$ git diff [first-branch]...[second-branch]# 显示某次提交的元数据和内容变化$ git show [commit]# 显示某次提交发生变化的文件$ git show --name-only [commit]# 显示某次提交时,某个文件的内容$ git show [commit]:[filename]# 显示当前分支的最近几次提交$ git reflog (7) 同步代码1234567891011121314151617181920212223242526# 下载远程仓库的所有变动,不会强制合并$ git fetch [remote]# 显示所有远程仓库$ git remote -v# 显示某个远程仓库的信息$ git remote show [remote]# 增加一个新的远程仓库,并命名$ git remote add [shortname] [url]# 取回远程仓库的变化,并与本地分支合并$ git pull [remote] [branch]# 上传本地指定分支到远程仓库$ git push [remote] [branch]# 强行推送当前分支到远程仓库,即使有冲突$ git push [remote] --force# 推送所有分支到远程仓库$ git push [remote] --all# 提交本地分支代码到远程分支$ git push origin develop:本地分支名称 (8) 撤销操作123456789101112131415161718192021222324252627282930313233# 恢复暂存区的指定文件到工作区$ git checkout [file]# 恢复某个commit的指定文件到暂存区和工作区$ git checkout [commit] [file]# 恢复暂存区的所有文件到工作区$ git checkout .# 重置暂存区的指定文件,与上一次commit保持一致,但工作区不变$ git reset [file]# 重置暂存区与工作区,与上一次commit保持一致$ git reset --hard # 重置当前分支的指针为指定commit,同时重置暂存区,但工作区不变$ git reset [commit]# 重置当前分支的HEAD为指定commit,同时重置暂存区和工作区,与指定commit一致$ git reset --hard [commit]git中用HEAD表示当前版本,HEAD^表示上一个版本,HEAD^^表示上上个版本,往上100个版本就是HEAD~100回退到上一个版本: git reset --hard HEAD^ # 重置当前HEAD为指定commit,但保持暂存区和工作区不变$ git reset --keep [commit]# 新建一个commit,用来撤销指定commit# 后者的所有变化都将被前者抵消,并且应用到当前分支$ git revert [commit]# 暂时将未提交的变化移除,稍后再移入$ git stash$ git stash pop (9) 配置123456789# 显示当前的Git配置,user.name,user.email等等$ git config --list# 编辑Git配置文件$ git config -e [--global]# 设置提交代码时包含的用户信息$ git config [--global] user.name "[name]"$ git config [--global] user.email "[email address]" (10) 其他常用创建并提交代码流程:123456789101. git init2. - 添加到暂存区; git add <文件名> - 或者从暂存区移除: git rm --cache 文件3. git commit -m "chore: 注释内容" #从此完成了本地提交4. git remote add origin [email protected]:repos/xxx/xxx/xxx.git5. git push origin 本地分支:远程分支6. 查看仓库状态: git status 7. 查看提交历史 git log 放弃更改代码,进行强制更新:12git fetch --allgit reset--hard origin/master git fetch只是下载远程的库的内容,不做任何的合并 git reset 把HEAD指向刚刚下载的最新的版本 取消merge:12git merge —abortgit reset 三、冲突解决人生不如意,十之八九,git使用过程中如果没有遇到过冲突,那绝对也是很离奇的事件。 我们平时使用git遇到冲突一般是pull代码或者push代码的时候,还有合并分支的时候。“git pull”操作等于“git fetch + git merge refs/remotes/origin/master”由此可见,git fetch更安全一点,不会合并代码。 一般解决过程: 在报错的目录下执行: git rebase remote-branch-name 先编辑冲突,然后git commit提交 执行 git add -u(-u 表示把所有已track的文件的新的修改加入缓存,但不加入新的文件) git rebase –continue (重复这这些步骤,直到rebase冲突解决完成) 如果想要恢复修改bug之前的状态,执行:git rebase –abort 冲突产生后会有<<<<>>>>这些内容,<<<<<<<HEAD 和=====之间的内容是我们本地的修改。 为什么会使用rebase? git rebase 和 git merge 一样都是用于从一个分支获取并且合并到当前分支,但是他们采取不同的工作流程。从上面你可以可能看到了git rebase是一个一个处理冲突的。本质上git merge会产生一个新的commit,合并的时候是全部合并,修改完成冲突就可以提交了,记录了真实的commit情况,包括每个分支的详情,但是如果频繁的使用,就会导致commit信息比较混乱。git rebase不会一次性合并,而是一个一个处理,不会有commit信息,会合并之前的commit历史,这样会让他的提交历史比较简洁,它的优点也是它的缺点,以为重写了commit历史,所以,导致提交历史不明晰。 四、.gitignore 忽略文件在代码开发过程中经常使用Eclipe、IDEA等开发工具,项目开发过程中不可以将.setting、.classpath等文件提交到代码库,所以我们需要将这些添加到忽略文件中,避免代码协作过程中因为这些配置文件的问题导致冲突。]]></content>
<categories>
<category>Git</category>
</categories>
<tags>
<tag>git</tag>
<tag>命令</tag>
<tag>常用</tag>
<tag>概念</tag>
</tags>
</entry>
<entry>
<title><![CDATA[CentOS7修改防火墙配置开放端口]]></title>
<url>%2F2018%2F12%2F12%2FLinux%2FCentOS7%E4%BF%AE%E6%94%B9%E9%98%B2%E7%81%AB%E5%A2%99%E9%85%8D%E7%BD%AE%E5%BC%80%E6%94%BE%E7%AB%AF%E5%8F%A3%2F</url>
<content type="text"><![CDATA[原文:http://limingming.org/index.php/2018/12/centos7-firewall-config/ 设置开放端口12sudo firewall-cmd --zone=public --add-port=3000/tcp --permanentsudo firewall-cmd --reload –zone #作用域–add-port=80/tcp #添加端口,格式为:端口/通讯协议–permanent #永久生效,没有此参数重启后失效 之后检查新的防火墙规则firewall-cmd –list-all 重启防火墙1firewall-cmd --reload 关闭防火墙12systemctl stop firewalld.service #停止firewallsystemctl disable firewalld.service #禁止firewall开机启动 常用命令firewall-cmd –state ##查看防火墙状态,是否是runningfirewall-cmd –reload ##重新载入配置,比如添加规则之后,需要执行此命令firewall-cmd –get-zones ##列出支持的zonefirewall-cmd –get-services ##列出支持的服务,在列表中的服务是放行的firewall-cmd –query-service ftp ##查看ftp服务是否支持,返回yes或者nofirewall-cmd –add-service=ftp ##临时开放ftp服务firewall-cmd –add-service=ftp –permanent ##永久开放ftp服务firewall-cmd –remove-service=ftp –permanent ##永久移除ftp服务firewall-cmd –add-port=80/tcp –permanent ##永久添加80端口iptables -L -n ##查看规则,这个命令是和iptables的相同的man firewall-cmd ##查看帮助]]></content>
<categories>
<category>Linux</category>
</categories>
<tags>
<tag>centos 7</tag>
<tag>修改防火墙配置</tag>
<tag>开发端口</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Mysql连接SSL错误警告]]></title>
<url>%2F2018%2F12%2F12%2FDB%2FMysql%E8%BF%9E%E6%8E%A5SSL%E9%94%99%E8%AF%AF%E8%AD%A6%E5%91%8A%2F</url>
<content type="text"><![CDATA[原文:http://limingming.org/index.php/2018/12/mysql-ssl-errorlog/ 错误信息1WARN: Establishing SSL connection without server’s identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn’t set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to ‘false’. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification. 什么是SSL传输层安全性协议(英语:Transport Layer Security,缩写作 TLS),及其前身安全套接层(Secure Sockets Layer,缩写作 SSL)是一种安全协议,目的是为互联网通信提供安全及数据完整性保障。网景公司(Netscape)在1994年推出首版网页浏览器,网景导航者时,推出HTTPS协议,以SSL进行加密,这是SSL的起源。IETF将SSL进行标准化,1999年公布第一版TLS标准文件。随后又公布RFC 5246 (2008年8月)与 RFC 6176 (2011年3月)。在浏览器、邮箱、即时通信、VoIP、网络传真等应用程序中,广泛支持这个协议。主要的网站,如Google、Facebook等也以这个协议来创建安全连线,发送数据。目前已成为互联网上保密通信的工业标准。SSL包含记录层(Record Layer)和传输层,记录层协议确定传输层数据的封装格式。传输层安全协议使用X.509认证,之后利用非对称加密演算来对通信方做身份认证,之后交换对称密钥作为会谈密钥(Session key)。这个会谈密钥是用来将通信两方交换的数据做加密,保证两个应用间通信的保密性和可靠性,使客户与服务器应用之间的通信不被攻击者窃听。 以上说明内容来自于维基百科 SSL是在Web服务器和Web客户机之间建立经过身份验证和加密会话的Web协议。以首先建立TCP/IP连接的握手例行程序开始。接着,通过验证服务器的公钥为客户机验证服务器。一旦通过验证,服务器即会选择客户机和服务器都支持的并在具体的国家/地区所实施的限制内的最强密码算法。下一步将生成用来对上述客户机和服务器之间的所有数据流进行加密的共享密钥。最终,一个加密的SSL,连接便建立了。 如上所述,在客户机和服务器之间发送的所有信息都经过加密,包括所有的HTTP请求和响应以及客户机请求的URL。该级别的加密可确保信用卡号、访问授权信息(用户名)以及服务器返回的敏感数据等敏感信息的保护。 因为加密需要大量的计算,所以SSL.会话通常仅用于敏感信息的传输。 目前,美国政府允许在浏览器中使用128位加密,.从而可使银行业务和金融交易获得高度的安全性。一些产品,如Microsoft的SGC(服务器控制密码技术,属SSL,的一种扩展),可支持这种更高水平的加密。此外,也有其他的交易安全协议存在,比如为商业交易提供较高安全等级的SET(安全电子交易)。 散列算法可创建随传送的数据发送并由接收者验证的消息摘要。签名还可以防止发送者否认该消息(否认曾发送过它)。SSL和证书 SSL依赖于数字证书。证书将公钥和公钥所属的个人、公司或服务器组合起来。认证机构(CA)颁发证书,用它们自己的私钥对证书签名,因此可对证书进行验证。 SSL要求Web服务器具有证书。当用户连接到Web服务器时,服务器向用户发送它的证书。用户可验证该证书是否真实,一旦得到证实,证书中的公钥即被用于加密,只有服务器使用其私钥才能解密的消息。 请注意,证书是“绑定”到Web站点的。换言之,证书言明它只对特定的II)地址(或地址范围)有效。使用证书的初衷是客户机必须知道它们被连接到真实的Web站点,而不是该站点的假冒者。证书将公钥与指名的实体绑定在一起。可将这同一证书绑定到特定的Web站点,这样,如果有人盗取该证书并企图建立新的Web站点时,该站点必须要有已分配给真实站点的II)地址,所以只要黑客试图这样做,就会发生错误。 问题解决在mysql连接字符串url中加入ssl=true或者false即可: 1jdbc:mysql://127.0.0.1:3306/service-server?useUnicode=true&characterEncoding=utf8&useSSL=false 如果使用ssl=true的话需要一系列的操作生成密钥,修改配置,开启ssl,创建用户等等,大家有需要的话可以自行操作一下。]]></content>
<categories>
<category>DB</category>
</categories>
<tags>
<tag>mysql</tag>
<tag>解决</tag>
<tag>警告</tag>
<tag>ssl</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Linux系统Mysql数据库安装及修改存储数据位置]]></title>
<url>%2F2018%2F12%2F11%2FDB%2FLinux%E7%B3%BB%E7%BB%9FMysql%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AE%89%E8%A3%85%E5%8F%8A%E4%BF%AE%E6%94%B9%E5%AD%98%E5%82%A8%E6%95%B0%E6%8D%AE%E4%BD%8D%E7%BD%AE%2F</url>
<content type="text"><![CDATA[原文:http://limingming.org/index.php/2018/12/linux-mysql-install-config/ 介绍本文介绍在centos7.2下安装mysql 5.7.13 安装 下载rpm包 1wget http://repo.mysql.com//mysql57-community-release-el7-8.noarch.rpm 安装yum Repository: 1yum -y install mysql57-community-release-el7-8.noarch.rpm 安装MySQL服务端: 1yum -y install mysql-community-server.x86_64 启动mysql服务: 1systemctl start mysqld.service 重置密码 1$ mysql -u root 出了如下错误ERROR 1045 (28000): Access denied for user ‘root‘@’localhost’ (using password: NO)查看一下/etc/my.cnf,如果你没有改配置的话应该在log-error=/var/log/mysqld.log:1vi /var/log/mysqld.log 从内容中找到“ A temporary password is generated for root@localhost: Gj.,i:o9iRgQ”;Gj.,i:o9iRgQ就是数据库密码; 12mysql -u root -p>Gj.,i:o9iRgQ 登录成功了,之后使用如下出现错误: mysql> show databases;ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.这里是因为密码不符合规则,这个与validate_password_policy的值有关。 执行: 1alter user 'root'@'localhost' identified by 'root123456'; 现在就安装成功了; 修改配置mysql数据库存储的数据逐渐变大,数据增多到原有磁盘无法容纳的情况,所以要对数据进行迁移。在安装完成数据库后最好能讲数据放到磁盘存储大的地方。 停止mysql 1systemctl stop mysqld 创建新的数据存放目录 1mkdir /home/mysql 将数据移动到新的目录如果忘记原来存储的目录可以查看/etc/my.cnf中的datadir=? 1mv /var/lib/mysql/* /home/mysql/ 还涉及到一些问题,innoDB引擎和MyISAM引擎的数据文件是不一样的,比如MyISAM引擎, 数据文件以”.frm”,”.MYD”,”*.MYI”三个文件存储于”/var/lib/mysql”目录下的对应数据库文件夹中,直接将这些文件移动到新的目录中即可 针对innoDB引擎,数据则存储在”$innodb_data_home_dir” 的ibdata1文件中(一般情况下是这样的),结构文件存在于table_name.frm中。 修改mysql数据库目录文件权限 1chown mysql:mysql -R /data/mysql/ 修改socket1234vi /etc/my.cnf # 修改内容 socket=/home/mysql/mysql.sockdatadir=/home/mysql/ vi /etc/init.d/mysqld12# 添加内容datadir=/home/mysql/ 创建一个连接文件到/var/lib/mysql/mysql.sock 1ln -s /home/mysql/mysql.sock /var/lib/mysql/mysql.sock 重启mysql服务执行 :1systemctl start mysqld 但是无法启动;报错信息:1Job for mysqld.service failed because the control process exited with error code. See "systemctl status mysqld.service" and "journalctl -xe" for details. 看到报错,第一时间想到的是查看一下日志信息,如果忘记日志文件位置,可以查看一下/etc/my.cnf ,log-error=/var/log/mysqld.log; 截取报错信息如下: 12345672018-12-11T08:29:12.795857Z 0 [ERROR] InnoDB: The innodb_system data file 'ibdata1' must be writable2018-12-11T08:29:12.795878Z 0 [ERROR] InnoDB: The innodb_system data file 'ibdata1' must be writable2018-12-11T08:29:12.795885Z 0 [ERROR] InnoDB: Plugin initialization aborted with error Generic error2018-12-11T08:29:13.396561Z 0 [ERROR] Plugin 'InnoDB' init function returned error.2018-12-11T08:29:13.396603Z 0 [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed.2018-12-11T08:29:13.396608Z 0 [ERROR] Failed to initialize builtin plugins.2018-12-11T08:29:13.396611Z 0 [ERROR] Aborting 看到这个must be writable,第一时间想到的是权限问题,所以执行了以下权限命令: 12chown -R mysql:mysql /home/mysql chmod 777 -R /home/mysql 重新启动不行,所以用命令getenforce,查看了一下selinux,修改selinux:1vi /etc/sysconfig/selinux 将SELINUX=enforcing 改为 SELINUX=permissive; 又重新启动发现还是不行,才意识到,如果一个文件是在selinux打开的时候创建的,那么即使你关闭selinux,它的权限控制还是会起作用的。可以通过chcon来改变权限; 因为我的机子没有其他应用,所以我选择了重启,重启之后就可以了 PS: 所以说如果你想要试试的话最好安装mysql前关闭selinux!!!]]></content>
<categories>
<category>DB</category>
</categories>
<tags>
<tag>mysql</tag>
<tag>安装</tag>
<tag>迁移</tag>
<tag>数据</tag>
<tag>问题</tag>
<tag>解决</tag>
</tags>
</entry>
<entry>
<title><![CDATA[通过yum安装Ansible]]></title>
<url>%2F2018%2F12%2F10%2FLinux%2F%E9%80%9A%E8%BF%87yum%E5%AE%89%E8%A3%85Ansible%2F</url>
<content type="text"><![CDATA[原文:http://limingming.org/index.php/2018/12/yum-install-ansible/ 介绍Fedora 用户可直接安装Ansible, 但RHEL或CentOS用户,需要 配置 EPEL yum安装我的是CentOS7.2: 1234567# 建议执行,如果没有subscription-manager命令先安装subscription-manager repos --enable "rhel-*-optional-rpms" --enable "rhel-*-extras-rpms"yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm# install the epel-release RPM if needed on CentOS, RHEL, or Scientific Linux$ sudo yum install ansible 创建rpm包使用 make rpm 命令创建RPM软件包. 然后可分发这个软件包或是使用它来安装Ansible.在创建之前,先确定你已安装了 rpm-build, make, and python2-devel . 12345$ yum -y install rpm-build make python2-devel$ git clone git://github.com/ansible/ansible.git$ cd ./ansible$ make rpm$ sudo rpm -Uvh ~/rpmbuild/ansible-*.noarch.rpm 补充可能你会选择用pip安装12pip install ansible --upgrade --no-index --find-links=http://10.111.24.89:81/httpfiles/pipfiles/ --trusted-host 10.111.24.89 安装过程中可能会出现: Command “python setup.py egg_info” failed with error code 1 in /tmp/pip-install-soDkws/ansible/ 解决: 1pip install --upgrade setuptools 重新安装就可以了]]></content>
<categories>
<category>Linux</category>
</categories>
<tags>
<tag>安装</tag>
<tag>ansible</tag>
<tag>yum</tag>
<tag>部署</tag>
</tags>
</entry>
<entry>
<title><![CDATA[mysql 数据库修改密码及更改远程访问权限]]></title>
<url>%2F2018%2F12%2F08%2FDB%2Fmysql-%E6%95%B0%E6%8D%AE%E5%BA%93%E4%BF%AE%E6%94%B9%E5%AF%86%E7%A0%81%E5%8F%8A%E6%9B%B4%E6%94%B9%E8%BF%9C%E7%A8%8B%E8%AE%BF%E9%97%AE%E6%9D%83%E9%99%90%2F</url>
<content type="text"><![CDATA[原文:http://limingming.org/index.php/2018/12/mysql-change-passwd-and-grant/ mysql修改密码 方式一 1set password for 'user_name'@'host_name'=password('new_pwd') 方式二使用update系统表方式 123use mysql;update user set password=password('passwd') where user='user_name';flush privileges; 补充:对于user表password类,如果不用password函数的话,导致更新后无法登陆。 也可以在用户创建后直接使用grant方式来更新用户密码 1grant usage on *.* to '用户名'@'localhost' identified by '密码'; 忘记mysql密码重制密码过程 123456789101112131415161718192021222324# 停止mysql服务 service mysql stop # 使用--skip-grant-tables选项跳过授权表验证 #获取mysqld帮助信息mysqld --help --verbose --skip-grant-tables# 使用--skip-grant-tables启动mysql服务器mysqld --skip-grant-tables --user=mysql &ps -ef | grep mysqlmysql select user,host,password from mysql.user where user='root'; --更新mysql账户密码为NULL或设定为新密码,注设定为空密码时可以直接设置update mysql.user set password='' where user='root';select user,host,password from mysql.user where user='root';exit# 再次停止mysql数据库服务器service mysql stopservice mysql startmysql #重启后再次登陆,不再需要任何密码 设置允许远程连接 开启远程访问 12grant all privileges on *.* to 'root'@'%' identified by 'password';flush privileges; 命令语句中第一个*代表数据库,可以改成允许访问的数据库名称 命令中第二个 是数据库的表名称,代表允许访问任意的表 root代表远程登录使用的用户名,可以自定义 %代表允许任意ip登录,如果你想指定特定的IP,可以把%替换成具体的IP就可以了 password代表远程登录时使用的密码,可以自定义 flush privileges;这是让权限立即生效 修改配置文件my.cnf是mysql的配置文件,路径是/etc/my.cnf如果寻找文件寻找不到的话,可以用linux搜索的命令 1find /* -name my.cnf 通过vim编辑该文件,找到bind-address = 127.0.0.1这一句,然后在前面加个#号注释掉,保存退出然后重新启动服务。 1service mysql restart 在终端输入:mysql -h 服务器ip地址 -P 3306 -u root -p 如果可以访问就证明成功了,如果还不可以,查看一下防火墙,开发3306端口。可以参考CentOS7修改防火墙配置开放端口]]></content>
<categories>
<category>DB</category>
</categories>
<tags>
<tag>mysql</tag>
<tag>修改</tag>
<tag>密码</tag>
<tag>设置</tag>
<tag>远程</tag>
<tag>访问</tag>
<tag>权限</tag>
</tags>
</entry>
<entry>
<title><![CDATA[nexus3配置yum源]]></title>
<url>%2F2018%2F12%2F08%2FLinux%2Fnexus3%E9%85%8D%E7%BD%AEyum%E6%BA%90%2F</url>
<content type="text"><![CDATA[使用在生产环境中,或者在隔离外网的服务器环境中,不能在线更新下载RPM包,所以借助有一台Linux服务器可以连接外网,剩余的服务器通过这台YUM服务器更新就可以了。 开篇以前的做法是先把包下载到内网中的YUM服务器上,然后通过createrepo命令生成本地仓库,其余服务器通过HTTP访问这个链接,这种方式比较费时费力,而且工作效率不高,在这也简要的把这种方式介绍一下,这种方式下一般应用到本地为开发环境可以联网但是开发环境并不可以的情况,如果是简单部署单个应用不是很多应用的话,这种方式还是有可取之处的。 开发环境下: 12345yum install createrepo -yyum install -y createrepo --downloadonly --downloaddir=/root/rpmcache/Packagesrm -rf /root/rpmcache/repodata/cd /root/rpmcache && createrepo . 详细的每一个命令就不一一介绍了,执行完成这些这样开发环境下我们就准备好了相关的依赖。 生产环境我们将/root/rpmcache 复制到到生产环境下 123456vi /etc/yum.repos/aaa.repo# 写入以下内容,files为路径[aaa]baseurl = files:///root/rpmcachegpgcheck = 0name = aaa 执行123yum clean allyum repolist 这样就可以使用了。 配置Nexus当然neuxs的方式更通用一些,将nexus放到能链接外网的服务器上,通过nexus暴露服务就可以了。 使用浏览器打开neuxs的网站,输入管理员密码 点击配置->Repositories->选择类型(yum proxy) 自定义一个名字,例如:yum-proxy 输入URL: http://mirrors.163.com/centos/centos可以用http://mirror.centos.org/centos/ ,可以参考yum源地址创建完成后得到源的私服地址,如果有必要的话,把用到的源统一通过group的方式暴露出来就可以了。 配置使用因为服务器无法链接内网可以将/etc/yum.repos.d/下的repo文件备份,如果有必要恢复的话,例如CentOS-Base.repo 等在/etc/yum.repos.d/下创建neuxs.repo文件写入: 123456# cat nexus.repo[nexus]name=Nexus Repositorybaseurl=http://IP:8081/repository/yum-proxy/$releasever/os/$basearch/enabled=1gpgcheck=0 在你的nexus服务URL后要加上“$releasever/os/$basearch/”执行12yum clean allyum list all 接下来就可以使用配置的yum源了。 原文:https://blog.limingming.org/2018/12/03/Maven/%E5%AE%89%E8%A3%85nexus/]]></content>
<categories>
<category>Linux</category>
</categories>
<tags>
<tag>配置</tag>
<tag>yum</tag>
<tag>源</tag>
<tag>nexus3</tag>
</tags>
</entry>
<entry>
<title><![CDATA[国内yum源地址]]></title>
<url>%2F2018%2F12%2F07%2FLinux%2F%E5%9B%BD%E5%86%85yum%E6%BA%90%E5%9C%B0%E5%9D%80%2F</url>
<content type="text"><![CDATA[原文:http://limingming.org/index.php/2018/12/yum-repo-china/ 最近公司内服务器迁移,需要配置一些能代理外网的yum源地址,以下是一些yum源的总结: 企业阿里云:https://opsx.alibaba.com/mirror搜狐开源镜像站:http://mirrors.sohu.com/ 网易开源镜像站:http://mirrors.163.com/ 大学 北京理工大学 http://mirror.bit.edu.cn (IPv4 only)http://mirror.bit6.edu.cn (IPv6 only) 北京交通大学 http://mirror.bjtu.edu.cn (IPv4 only)http://mirror6.bjtu.edu.cn (IPv6 only)http://debian.bjtu.edu.cn (IPv4+IPv6) 兰州大学 http://mirror.lzu.edu.cn/ 厦门大学http://mirrors.xmu.edu.cn/ 清华大学 http://mirrors.tuna.tsinghua.edu.cn/ (IPv4+IPv6)http://mirrors.6.tuna.tsinghua.edu.cn/ (IPv6 only)http://mirrors.4.tuna.tsinghua.edu.cn/ (IPv4 only) 天津大学 http://mirror.tju.edu.cn/ 中国科学技术大学http://mirrors.ustc.edu.cn/ (IPv4+IPv6)http://mirrors4.ustc.edu.cn/http://mirrors6.ustc.edu.cn/ 东北大学 http://mirror.neu.edu.cn/ (IPv4 only)http://mirror.neu6.edu.cn/ (IPv6 only) 电子科技大学 http://ubuntu.uestc.edu.cn/]]></content>
<categories>
<category>Linux</category>
</categories>
<tags>
<tag>国内</tag>
<tag>yum</tag>
<tag>仓库</tag>
<tag>源</tag>
</tags>
</entry>
<entry>
<title><![CDATA[mac上安装部署nginx]]></title>
<url>%2F2018%2F12%2F06%2F%E5%BC%80%E5%8F%91%E8%80%85%E6%89%8B%E5%86%8C%2Fmac%E4%B8%8A%E5%AE%89%E8%A3%85%E9%83%A8%E7%BD%B2nginx%2F</url>
<content type="text"><![CDATA[原文 介绍Nginx(发音同engine x)是异步框架的 Web服务器,也可以用作反向代理,负载平衡器 和 HTTP缓存。该软件由 Igor Sysoev 创建,并于2004年首次公开发布。同名公司成立于2011年,以提供支持。Nginx是免费的开源软件,根据类BSD许可证的条款发布。一大部分Web服务器使用Nginx,通常作为负载均衡器。 –维基百科 环境搭建 打开终端,安装brew 1usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 安装成功后,使用查看版本,验证是否安装成功1brew -v 安装ngnix 1brew install nginx 我安装完成的版本是:12$ nginx -vnginx version: nginx/1.15.6 中间安装过程中可能会出现warning,为了不必要的麻烦执行以下安装命令 1sudo xcode-select --install 会出现如下提示安装的工具,稍等几分钟就安装成功了。 启动关闭nginx 启动nginx123brew services start nginx# 或者更常用的:nginx 使用浏览器访问http://localhost:8080 ,应该可以看到 wlecom to nginx 的欢迎界面。 关闭命令:nginx -s quit 或者: 1234$ ps -ef | grep nginx 502 82708 1 0 6:22下午 ?? 0:00.02 nginx: master process /usr/local/opt/nginx/bin/nginx -g daemon off; 502 82709 82708 0 6:22下午 ?? 0:00.00 nginx: worker process 502 82712 82200 0 6:22下午 ttys000 0:00.00 grep nginx 找到它的进程号 82708 ,杀死! 1kill -QUIT 82708 kill -QUIT 15800 (慢慢停止,不会立刻停止)Kill -TERM 15800 (立刻停止)Kill -INT 15800 (和上面一样,也是立刻停止) 重启 12cd /usr/local/Cellar/nginx/1.15.6/bin./nexus reload nexus 各个参数 123456789101112131415./nginx -hnginx version: nginx/1.15.6Usage: nginx [-?hvVtTq] [-s signal] [-c filename] [-p prefix] [-g directives]Options: -?,-h : this help -v : show version and exit -V : show version and configure options then exit -t : test configuration and exit -T : test configuration, dump it and exit -q : suppress non-error messages during configuration testing -s signal : send signal to a master process: stop, quit, reopen, reload -p prefix : set prefix path (default: /usr/local/Cellar/nginx/1.15.6/) -c filename : set configuration file (default: /usr/local/etc/nginx/nginx.conf) -g directives : set global directives out of configuration file 大家可以根据自己的需要执相应的命令. 补充&强调 nginx安装文件目录 /usr/local/Cellar/nginx nginx配置文件目录/usr/local/etc/nginx config文件目录/usr/local/etc/nginx/nginx.conf 系统hosts位置/private/etc/hosts nginx常用命令 12345nginx #启动nginxnginx -V #查看版本,以及配置文件地址nginx -v #查看版本nginx -s reload|reopen|stop|quit #重新加载配置|重启|快速停止|安全关闭nginxnginx -h #帮助 卸载nginx1brew uninstall nginx]]></content>
<categories>
<category>开发者手册</category>
</categories>
<tags>
<tag>安装</tag>
<tag>部署</tag>
<tag>mac</tag>
<tag>nginx</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Maven仓库存在jar包但依旧提示无法下载]]></title>
<url>%2F2018%2F12%2F05%2FMaven%2FMaven%E4%BB%93%E5%BA%93%E5%AD%98%E5%9C%A8jar%E5%8C%85%E4%BD%86%E4%BE%9D%E6%97%A7%E6%8F%90%E7%A4%BA%E6%97%A0%E6%B3%95%E4%B8%8B%E8%BD%BD%2F</url>
<content type="text"><![CDATA[介绍最近服务器的迁移,把原来服务器的地址都更改了,所以私服的地址也改动了,原来项目下载到本地仓库的包,但是重新构建过程中竟然发现依然要提示下载,本地仓库里面明明有包,为什么还要下载? 解决去maven仓库包下面你会发现有_remote.repositories文件,下载不下来问题就是因为这个文件导致的。你可能会发现nexus=的信息在这个文件中,这个文件中已经连接不上原来的nexus私服了,所有会报错依然会生成lastUpdatedw文件,如果你可以从新的服务地址中下载,你可以选择删除掉这个包,重新下载,如果不能的话可以选择改掉nexus=的信息,改成可以连接的地址,那它就不会重新下载了,例如改成 central=,这代表从远程中央仓库下载。 结果最后当然会成功,如果不成功的话重新检查一下网络情况!]]></content>
<categories>
<category>Maven</category>
</categories>
<tags>
<tag>maven</tag>
<tag>存在</tag>
<tag>依然</tag>
<tag>报错</tag>
</tags>
</entry>
<entry>
<title><![CDATA[maven私服-Nexus]]></title>
<url>%2F2018%2F12%2F03%2FMaven%2FMaven%E7%A7%81%E6%9C%8D-Nexus%2F</url>
<content type="text"><![CDATA[什么是私服私服不是Maven的核心概念,它仅仅是一种衍生出来的特殊的Maven仓库,架设在局域网的一种特殊的远程仓库,目的是代理远程仓库及部署第三方构件。如果没有私服,我们所需的所有构件都需要通过maven的中央仓库和第三方的Maven仓库下载到本地,而一个团队中的所有人都重复的从maven仓库下载构件无疑加大了仓库的负载和浪费了外网带宽,如果网速慢的话,还会影响项目的进程。很多情况下项目的开发都是在内网进行的,连接不到maven仓库怎么办呢?开发的公共构件怎么让其它项目使用?这个时候我们不得不为自己的团队搭建属于自己的maven私服,这样既节省了网络带宽也会加速项目搭建的进程,当然前提条件就是你的私服中拥有项目所需的所有构件。 以下是有无私服的对比: Nexus下载与安装Nexus安装的先决条件不管是NexusOpen Source还是Nexus Professional,他们只有一个先决条件就是必须有一个JavaRuntime Environment,且必须是Java 5或更高。 下载NexusNexus有2个版本,Nexus Open Source 和 NexusProfessional。NexusOpen Source是可基于EPL协议免费使用修改分发的全功能仓库管理系统。Nexus Professional主要用于需要复杂大型企业或组织。 本文只介绍NexusOpen Source,下文简称Nexus。Nexus下载地址,有完整版,有war版。前者可以单独运行为一个基于jetty的服务,后者是运行在ServletConstainer的Web应用。 安装Nexus安装Nexus非常简单。解压下载的文件到任意目录,不过要小心权限问题已经Windows下带空格文件夹引起的问题。然后配置NEXUS_HOME。解压出来的目录下除了nexus外,还有一个sonatype-work文件夹。这个文件夹包含了所有nexus的仓库以及配置数据,这么做使得更加容易更新到新版的nexus。当然,这个目录的路径也能通过NEXUS_HOME/conf/nexus.properties修改 下载Nexus 官网http://www.sonatype.org/nexus/ 下载最新的Nexus。 Bundle方式安装Nexus 首先看下解压后的目录,结构:解压后存在两个文件夹:nexus-2.4.0-01(不同版本版本号不同)和sonatype-work。nexus-2.4.0-01: 该目录包含了Nexus运行所需要的文件,如启动脚本、依赖jar包等。sonatype-work:该目录包含Nenus生成的配置文件、日志文件、仓库文件等。第一个目录是运行Nexus必须的,而第二个不是必须的,Nexus会在运行的时候动态创建该目录。 运行Nexus当你运行Nexus时,你实际运行的是一个运行在0.0.0.0:8081的web server。Nexus运行在一个Jetty的servlet容器内,然后通过一个本地的封装服务Tanuki Java Service Wrapper来启动。它可以通过配置将nexus运行为一个unix或者windows的一个服务。bin目录下的nexus或者nexus.bat就是服务的起点,通过你的系统来选择对应的版本。 配置Path,启动Nexus(在windows操作系统上)首先在环境变量path下加入如下地址:C:\nexus\nexus-2.6.2-01-bundle\nexus-2.6.2-01\bin;之后在cmd下启动Nexus服务,启动成功后,可以打开打开浏览器访问http://localhost:8081/nexus 就可以看到Nexus的界面了。8081为默认的端口号,要修改端口号可进入nexus-2.1.2-bundle\nexus-2.1.2\conf\打开nexus.properties文件,修改application-port属性值就可以了,这时你可以单击界面右上角的Login进行登录,Nexus默认管理用户名和密码为admin/admin123。 在linux上切换到/opt/nexus/nexus-2.14.0-01/bin目录下,存在nexus及nexus.bat文件,可以使用./nexus start 启动nexus,这时候可能会报错。这时候提示: 123456789WARNING – NOTRECOMMENDED TO RUN AS ROOTIf you insist running as root, then set theenvironment variable RUN_AS_USER=root before running this script.``` 大概意思就是要在环境配置export RUN_AS_USER=root,临时配置,在命令行下输入: ```shellexport RUN_AS_USER=root 然后执行,就不会再提示了 1./nexus start 也可以在系统里面永久配置: 1vi /etc/profile 加入export RUN_AS_USER=root 配置Nexus为服务启动后,你就能通过浏览器访问http://localhost:8081/nexus当你把Nexus用于生产环境时,你应该将Nexus配置为一个服务,让他在后台运行以及在服务器重启后恢复服务。方法是 bin/nexus start 常用功能Nexus常用功能就是:指定私服的中央地址、将自己的Maven项目指定到私服地址、从私服下载中央库的项目索引、从私服仓库下载依赖组件、将第三方项目jar上传到私服供其他项目组使用。开启Nexus服务后访问url地址http://localhost:8081/nexus, (推荐使用自己的ip地址),之后登录系统,用户名密码分别是:admin/admin123. 仓库类别: Hosted代表宿主仓库,用来发布一些第三方不允许的组件,其中自带仓库类型中3rd一般用来发布第三方无法在中央仓库获取的jar包,比如oracle的jdbc的jar包,Releases一般存放公司内的封版的项目,Snapshots用来存放正在开发的版本。Proxy代表代理远程的仓库,最典型的就是Maven官方中央仓库、JBoss仓库等等。如果构建的Maven项目本地仓库没有依赖包,那么就会去这个代理站点去下载,那么如果代理站点也没有此依赖包,就回去远程中央仓库下载依赖,这些中央仓库就是proxy。代理站点下载成功后再下载至本机。笔者认为,其实Maven这个自带的默认仓库一般情况下已经够大多数项目使用了。group 仓库是一个“仓库组”,为开发人员便于开发设置的仓库,可以将多个已存在的其他仓库配置其中提供给大家使用,在nexus中配置的时候注意的是左侧是配置仓库组使用的仓库。 virtual仓库是用于提供中央仓库中M1格式的发布版本的构件镜像仓库,即在当此M2仓库中为M1格式的仓库构件缓存提供出来的。 maven项目索引: 下载Maven项目索引,项目索引是为了使用者能够在私服站点查找依赖使用的功能例如: 就可以检索出它的相关信息,包括怎么配置依赖信息。我们要想使用这个私服仓库,先在项目pom中配置相关私服信息 使用配置在项目POM中配置指定仓库 12345678910111213<repositories> <repository> <id>nexus</id> <name>nexus</name> <url>http://192.168.1.103:8081/nexus/content/groups/public/</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </repository> </repositories> 指定插件仓库 12345678910111213<pluginRepositories> <pluginRepository> <id>nexus</id> <name>nexus</name> <url>http://192.168.1.103:8081/nexus/content/groups/public/</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </pluginRepository> </pluginRepositories> 这样只有本项目才在私服下载组件 这样这个Maven项目构建的时候会从私服下载相关依赖,当构建项目的时候,maven会从私服将构件下载到本地仓库,当然这个配置仅仅是在此项目中生效,对于其他项目还是不起作用。如果相对Maven的其他项目也生效的话。需要修改全局的settings.xml文件。 修改settings.xml12345678910111213141516171819202122232425262728293031<profiles>……………<profile> <id>myprofile</id> <repositories> <repository> <id>central</id> <url>http://10.110.13.14:8081/nexus/content/groups/inspur-jszx/</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>central</id> <url>http://10.110.13.14:8081/nexus/content/groups/inspur-jszx/</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </pluginRepository> </pluginRepositories> </profile>……………<profiles> 追加激活profile 123<activeProfiles> <activeProfile>central</activeProfile> </activeProfiles> 之后所有本机的Maven项目就在私服下载组件。 手动上传构件用admin管理员权限用户登录,找到相应的上传配置,分别选中填写信息就最后Upload构件就可以了 deploy命令部署构件到Nexus 在POM中配置 12345678910111213141516<project> ... <distributionManagement><snapshotRepository> <id>user-snapshots</id> <name>User Project SNAPSHOTS</name> <url>http://localhost:8081/nexus/content/repositories/MyUserReposSnapshots/</url> </snapshotRepository> <repository> <id>user-releases</id> <name>User Project Release</name> <url>http://localhost:8081/nexus/content/repositories/MyUserReposRelease/</url> </repository> </distributionManagement> ...</project> settings.xml中配置认证信息,Nexus的仓库对于匿名用户是只读的。 123456789101112131415<servers> <server> <id>user-snapshots</id> <username>lb</username> <password>123456</password> </server> <server> <id>user-releases</id> <username>lb</username> <password>123456</password> </server> </servers> 注意Respository中的id一定要和server下的id一致,切记!!否则出现权限问题。 然后运行发布 1mvn clean deploy 在控制台发布成功 然后进入到私服上的仓库中,看一下确实存在刚刚发布的项目]]></content>
<categories>
<category>Maven</category>
</categories>
<tags>
<tag>介绍</tag>
<tag>nexus</tag>
<tag>私服</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Maven项目命名规范]]></title>
<url>%2F2018%2F12%2F03%2FMaven%2FMaven%E9%A1%B9%E7%9B%AE%E5%91%BD%E5%90%8D%E8%A7%84%E8%8C%83%2F</url>
<content type="text"><![CDATA[官方文档介绍Guide to naming conventions on groupId, artifactId and versiongroupId will identify your project uniquely across all projects, so we need to enforce a naming schema. It has to follow the package name rules, what means that has to be at least as a domain name you control, and you can create as many subgroups as you want. Look at More information about package names.eg. org.apache.maven, org.apache.commons A good way to determine the granularity of the groupId is to use the project structure. That is, if the current project is a multiple module project, it should append a new identifier to the parent’s groupId. eg. org.apache.maven, org.apache.maven.plugins, org.apache.maven.reporting artifactId is the name of the jar without version. If you created it then you can choose whatever name you want with lowercase letters and no strange symbols. If it’s a third party jar you have to take the name of the jar as it’s distributed.eg. maven, commons-math version if you distribute it then you can choose any typical version with numbers and dots (1.0, 1.1, 1.0.1, …). Don’t use dates as they are usually associated with SNAPSHOT (nightly) builds. If it’s a third party artifact, you have to use their version number whatever it is, and as strange as it can look.eg. 2.0, 2.0.1, 1.3.1 以上内容是maven官网文档命名约定指南 总结groupId:定义当前Maven项目隶属的实际项目,例如org.sonatype.nexus,此id前半部分org.sonatype代表此项目隶属的组织或公司,后部分代表项目的名称,如果此项目多模块话开发的话就子模块可以分为org.sonatype.nexus.plugins和org.sonatype.nexus.utils等。特别注意的是groupId不应该对应项目隶属的组织或公司,也就是说groupId不能只有org.sonatype而没有nexus。 例如:我建立一个项目,此项目是此后所有项目的一个总的平台,那么groupId应该是org.limingming.projectName,projectName是平台的名称,org.limingming是代表我个人的组织,如果以我所在的浪潮集团来说的话就应该是com.inspur.loushang。 artifactId是构件ID,该元素定义实际项目中的一个Maven项目或者是子模块,如上面官方约定中所说,构建名称必须小写字母,没有其他的特殊字符,推荐使用“实际项目名称-模块名称”的方式定义,例如:spirng-mvn、spring-core等。 推荐格式:使用实际项目名称作为artifactId的前缀,紧接着为模块名称举例:nexus-indexer、spring-mvc、hibernate-c3po……这些id都是以实际项目名称作为前缀,然后接着一个中划线,再紧跟项目的模块名称,默认情况下maven会在artifactId添加version作为最后生成的名称。例如:spirng-mvn-2.0.0.jar]]></content>
<categories>
<category>Maven</category>
</categories>
<tags>
<tag>规范</tag>
<tag>maven</tag>
<tag>命名</tag>
<tag>命名规范</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Maven多WEB模块打包排除jar包冲突的配置建议]]></title>
<url>%2F2018%2F12%2F03%2FMaven%2FMaven%E5%A4%9AWEB%E6%A8%A1%E5%9D%97%E6%89%93%E5%8C%85%E6%8E%92%E9%99%A4jar%E5%8C%85%E5%86%B2%E7%AA%81%E7%9A%84%E9%85%8D%E7%BD%AE%E5%BB%BA%E8%AE%AE%2F</url>
<content type="text"><![CDATA[前提在原有的web项目基础上拆分出了多个web项目,后台代码还是在各个web模块中,现在的需求是要合并多个web模块整合到一个war中部署。 配置建议新建打包的web模块用以合并多个web模块项目,在pom中声明合并打包的各个模块,例如要合并A模块和B模块,如下: 123456789101112131415161718192021222324252627<dependencies><dependency><groupId>com.inspur.test</groupId><artifactId>A</artifactId><version>0.0.1-SNAPSHOT</version><type>war</type></dependency><dependency><groupId>com.inspur.test</groupId><artifactId>A</artifactId><version>0.0.1-SNAPSHOT</version><type>pom</type></dependency><dependency><groupId>com.inspur.test</groupId><artifactId>B</artifactId><version>0.0.1-SNAPSHOT</version><type>war</type></dependency><dependency><groupId>com.inspur.test</groupId><artifactId>B</artifactId><version>0.0.1-SNAPSHOT</version><type>pom</type></dependency></dependencies> 我们需要在合并打包的项目中依赖要合并的各个war包和各个模块的pom。 排除各个模块的lib: 排除各个模块的lib 123456789101112131415161718192021222324252627282930<build><finalName>B</finalName><plugins> <!-- 合并多个war --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-war-plugin</artifactId><version>2.6</version><configuration><overlays> <!-- 声明合并war --><overlay><groupId>com.inspur.test</groupId><artifactId>A</artifactId><excludes><!-- 声明排除war包中的部分 --><exclude>WEB-INF/lib/*</exclude></excludes></overlay></overlays><overlays> <!-- 声明合并war --><overlay><groupId>com.inspur.test</groupId><artifactId>B</artifactId><excludes><!-- 声明排除war包中的部分 --><exclude>WEB-INF/lib/*</exclude></excludes></overlay></overlays></configuration></plugin></plugins></build> 大家有哪些多模块开发构建的规范,很希望能给出你的建议到原文评论,谢谢。]]></content>
<categories>
<category>Maven</category>
</categories>
<tags>
<tag>排除</tag>
<tag>多模块</tag>
<tag>web</tag>
<tag>合并</tag>
<tag>冲突</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Maven依赖管理]]></title>
<url>%2F2018%2F12%2F01%2FMaven%2FMaven%E4%BE%9D%E8%B5%96%E7%AE%A1%E7%90%86%2F</url>
<content type="text"><![CDATA[直接依赖和间接依赖mane最大的好处就是能够方便的声明第三方的jar包,只需要在pom中进行简单的声明就可以将此jar包依赖到项目中,那什么是直接依赖呢?就是在项目中直接声明的这些依赖: 12345<dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.1.4.RELEASE</version> </dependency> 排除依赖间接依赖是由直接依赖间接依赖到项目的那些jar包,当项目依赖于某一第三方Jar包,而这一第三方Jar包又给我们间接性的带来了大量的依赖,这种间接性的依赖,不仅浪费了磁盘空间,而且也可能带来潜在的冲突,因此我们需要将这些不需要的依赖从项目中排除,对项目进行一个瘦身,这时我们需要对Pom进行优化,再或者,通过间接性依赖获得的Jar包版本过低,而这些低版本的Jar包无法满足我们项目的需求,这时我们也需要将这些低版本的Jar包排除掉,也就是下面的exclusion标签 1234567891011121314151617181920212223242526<dependency> <groupId>net.sf.spring-json</groupId> <artifactId>spring-json</artifactId> <version>1.3.1</version> <exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> </exclusion> <exclusion> <groupId>cglib</groupId> <artifactId>cglib-full</artifactId> </exclusion> </exclusions></dependency><dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>2.5.6</version> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency> 工具筛选Maven没有任何声明排除jar包的情况下,默认是将全部jar包引入进来,有时候当前项目使用的jar包与依赖的第三方的jar包不同,会出现同个项目构建后出现一个jar包几个不同版本同时存在的问题,有时会引发jar包冲突可以通过命令或者是在IDE中查看依赖树,排查依赖关系: 1mvn dependency : list 经过Maven解析之后,就会构成一个依赖树也可以使用命令查看当前项目的依赖树: 1mvn dependency : tree 使用命令分析当前当前项目的依赖: 1mvn dependency : analyze 该命令执行结果的两个重要部分:Used undeclared dependencies: 表示项目中使用到的,但是没有显示声明的依赖Unused declared dependencies: 表示项目中未使用的,但显示声明的依赖该命令只会分析编译主代码和测试代码需要用到的依赖,一些执行测试和运行时需要的依赖它无法发现。 ps:exclusions是在某个具体依赖里面配置的,也就是说要找到需排除的jar包的依赖坐标 以下是eclipse中的通过配置工具查看依赖、删除依赖的位置: 大开pom.xml,选中下发Dependency Hierarchy,选中右侧jar包,右键排除依赖就可以了。 配置可选maven还有个可选依赖的设置,在当前项目A设置对某个依赖是可选的: 12345678<optional>true</optional><dependency> <groupId>sample.ProjectB</groupId> <artifactId>Project-B</artifactId> <version>1.0</version> <scope>compile</scope> <optional>true</optional></dependency> 这样设置后,再有个项目X依赖A时,如果X中没有B中的类路径,则不会把B依赖加进来。 依赖规则大家看到直接依赖和间接依赖之后可能会有疑问,由不同的直接依赖产生的同一jar包不同版本的jar包之间的间接依赖怎么进行排除?这就要讲到maven的规则: 第一声明者优先(对于简介依赖) 例如:A项目依赖B、C两个项目,B和C又同时依赖D项目(依赖的D项目版本可能还是不同的),那就按照第一声明者优先的规则,谁先声明就用谁的,也就是对于间接依赖,路径相同的情况下,第一声明优先。 最后声明者优先(对于同一pom中直接依赖的同一jar包的不同版本间) 在pom中声明了同一jar包的不同版本,谁声明在后面就采用谁。 最短路径优先(对于间接依赖) 从名称就可以看出对于间接依赖的jar包,谁的间接依赖的路径短就采用谁的,例如A依赖B,B依赖D,而A依赖C,C依赖E,E依赖F,F依赖D,采用最短的依赖A->B->D的依赖版本。 dependencyManagement与dependenciesMaven已经具备了面向对象的思想,面向对象的三要素就是多态、继承、封装,dependencies与dependencyManagement就涉及到的是继承的思想。 多模块项目中,各个模块一般均需要Junit测试Jar包,因此在父Pom配置文件中,我们可以将这个依赖写入: 12345678<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency></dependencies> 此模块的各个子模块就可以直接继承此jar包了。 再想想,有一些依赖,是各个子模块所特有的,如果放在父模块的POM中进行定义,那么所有继承了该父模块的子模块均会存在该依赖,这样的结果是啥,项目中存在大量冗余Jar包,不但浪费了磁盘,而且也不利于管理,所以: 12345678910111213141516171819dependencyManagement> <!-- 配置项目依赖 --> <dependencies> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>${zookeeper.version}</version> </dependency> <dependency> <groupId>org.opensymphony.quartz</groupId> <artifactId>quartz-all</artifactId> <version>${quartz.version}</version> </dependency> <dependency> <groupId>oro</groupId> <artifactId>oro</artifactId> <version>${oro.version}</version> </dependency></dependencyManagement> 我们可以这样定义jar包在父模块,这样子模块就不会继承了,如果子模块需要用到jar包就需要重新声明: 1234567<!-- 配置项目依赖 --><dependencies> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> </dependency></dependencies> 可以省略版本,这样有利于控制版本,当然也可以自己定义在子模块中版本,这样将采用子模块中的版本。]]></content>
<categories>
<category>Maven</category>
</categories>
<tags>
<tag>Maven</tag>
<tag>依赖管理</tag>
<tag>排除</tag>
<tag>依赖</tag>
<tag>方法</tag>
</tags>
</entry>
<entry>
<title><![CDATA[JDK及openJDK版本更迭]]></title>
<url>%2F2018%2F12%2F01%2FJava%2FJDK%E5%8F%8AopenJDK%E7%89%88%E6%9C%AC%E6%9B%B4%E8%BF%AD%2F</url>
<content type="text"><![CDATA[作者: 李明明http://limingming.org/index.php/2018/11/30/jdk-and-openjdk-version/ 道听途说最近浪潮公司内部除了持之以恒的宣扬“奋进者精神”之外,可能最大的一件事情就是JDK要收费了,观望着是不是要更换为openJDK,9月20多号Oracle发布了java 11,同时也发布后续更新策略,那是怎么收费的呢? 追根溯源oracle jdk 和open jdk有什么区别? Java 11授权使用BCL协议,没有个人、商业版了,也就是说,如果要使用的必须要付出代价,代价就是Money,不禁想说一句:万恶的资本主义。 Open jdk使用GPL协议 两种协议有什么区别呢?首先BCL不是开源协议,简要来介绍BCL协议的话,就是你一点也不能更改我的jdk,也不能基于我开发周边类库发布,如果基于我这个BCL开发,需要判断你是个人版还是商业版,再收钱!GPL是开源协议,JDK是可以更改的,基于这个GPL开发的东西也是属于GPL协议的,也要开源出来。 补充:由于历史原因,OpenJDK是JDK的开放源码版本,也就是上面我们说的GPL协议的,但是到了JDK7的时候OpenJDK已经为jdk的主干开发,oracle jdk是在openjdk基础上进行封板发布的,所以大部分的源代码是相同的,只不过其中有部分少量的源代码被替换掉,使用JRL发布,以上jdk7的过程中就产生了微妙的变化,openjdk 是GPL协议的,完全可以商用,但是JRL只允许个人使用不允许商用。 版本更迭大体梳理一下JDK版本更迭过程中产生了那些新特性,也借此机会梳理一下自己JAVA的知识脉络。 JDK5 泛型“ 123ArrayList list=new ArrayList()------>ArrayList<Integer>list=new ArrayList<Integer>(); 枚举 静态导入 123456789101112import static java.lang.System.out``` 3. 可变参数(Varargs)4. 内省(Introspector),主要用于操作JavaBean中的属性,通过getXxx/setXxx。一般的做法是通过类Introspector来获取某个对象的BeanInfo信息,然后通过BeanInfo来获取属性的描述器(PropertyDescriptor),通过这个属性描述器就可以获取某个属性对应的getter/setter方法,然后我们就可以通过反射机制来调用这些方法。泛型(Generic)(包括通配类型/边界类型等)5. For-Each循环 ```javai=0;i<a.length;i++------------>for(int i:a){......} 注解 协变返回类型:实际返回类型可以是要求的返回类型的一个子类型 自动装箱拆箱: 123int i=list.get(0).parseInt();-------->int i=list.get(0); 我们经常阅读的编程思想也是在jdk5的版本上进行编写的,可惜作者忙别的事情去了,没有更新了,可能觉得java更新至此也应该很全面了吧。 JDK6 AWT新增加了两个类:Desktop和SystemTray,其中前者用来通过系统默认程序来执行一个操作,如使用默认浏览器浏览指定的URL,用默认邮件客户端给指定的邮箱发邮件,用默认应用程序打开或编辑文件(比如,用记事本打开以txt为后缀名的文件),用系统默认的打印机打印文档等。后者可以用来在系统托盘区创建一个托盘程序。 使用JAXB2来实现对象与XML之间的映射,可以将一个Java对象转变成为XML格式,反之亦然 StAX,一种利用拉模式解析(pull-parsing)XML文档的API。类似于SAX,也基于事件驱动模型。之所以将StAX加入到JAXP家族,是因为JDK6中的JAXB2和JAX-WS 2.0中都会用StAX。 使用Compiler API,动态编译Java源文件,如JSP编译引擎就是动态的,所以修改后无需重启服务器。(刚知道是从这里开始可以动态编译的) 轻量级Http Server API,据此可以构建自己的嵌入式HttpServer,它支持Http和Https协议。 插入式注解处理API(PluggableAnnotation Processing API) 提供了Console类用以开发控制台程序,位于java.io包中。据此可方便与Windows下的cmd或Linux下的Terminal等交互。 对脚本语言的支持如: ruby,groovy, javascript Common Annotations,原是J2EE 5.0规范的一部分,现在把它的一部分放到了J2SE 6.0中 嵌入式数据库 Derby 增强的for循环语句 1234567Integer[] numbers = computeNumbers();for (int i=0; i < numbers.length ; i++)sum += numbers[i];||int sum = 0;for ( int number: computeNumbers() )sum += number; 监视和管理Java SE 6中对内存泄漏增强了分析以及诊断能力。当遇到java.lang.OutOfMemory异常的时候,可以得到一个完整的堆栈信息,并且当堆已经满了的时候,会产生一个Log文件来记录这个致命错误。另外,JVM还添加了一个选项,允许你在堆满的时候运行脚本。 插入式注解处理插入式注解处理API(JSR 269)提供一套标准API来处理Annotations 安全性 如果你细细想来jdk6用到的新特性的确很少 JDK7 对Java集合(Collections)的增强支持,可直接采用[]、{}的形式存入对象,采用[]的形式按照索引、键值来获取集合中的对象。如: 12345List<String>list=[“item1”,”item2”];//存Stringitem=list[0];//直接取Set<String>set={“item1”,”item2”,”item3”};//存Map<String,Integer> map={“key1”:1,”key2”:2};//存Intvalue=map[“key1”]; 在Switch中可用String 数值可加下划线用作分隔符(编译时自动被忽略) 支持二进制数字,如: 12345678910int binary= 0b1001_1001; ``` 5. 简化了可变参数方法的调用 6. 调用泛型类的构造方法时,可以省去泛型参数,编译器会自动判断。 7. Boolean类型反转,空指针安全,参与位运算 8. char类型的equals方法: ```javabooleanCharacter.equalsIgnoreCase(char ch1, char ch2) 安全的加减乘除: 1Math.safeToInt(longv); Math.safeNegate(int v); Math.safeSubtract(long v1, int v2);Math.safeMultiply(int v1, int v2); Map集合支持并发请求,注HashTable是线程安全的,Map是非线程安全的。但此处更新使得其也支持并发。另外,Map对象可这样定义: 1Map map = {name:”xxx”,age:18}; JDK8 接口的默认方法:即接口中可以声明一个非抽象的方法做为默认的实现,但只能声明一个,且在方法的返回类型前要加上“default”关键字。2.Lambda 表达式:是对匿名比较器的简化,如: 1Collections.sort(names,(String a, String b) -> { returnb.compareTo(a);}); 对于函数体只有一行代码的,你可以去掉大括号{}以及return关键字。如: 123456Collections.sort(names,(String a, String b) -> b.compareTo(a));``` 或:```javaCollections.sort(names, (a, b) -> b.compareTo(a)); 函数式接口:是指仅仅只包含一个抽象方法的接口,要加@FunctionalInterface注解 使用 :: 关键字来传递方法或者构造函数引用 多重注解 还增加了很多与函数式接口类似的接口以及与Map相关的API等 其实以上的只不过是对于各个版本功能的简要摘录,如果想要详细了解的话可以看官方文档,平时用到的就是到jdk8,从jdk5到现在用jdk8,jdk9、和10还从来没有接触过。 最后附上相关项目的地址: OpenJDK官网:http://openjdk.java.net/ OpenJDK源码库:http://hg.openjdk.java.net/ OpenJDK源码库:http://hg.openjdk.java.net/]]></content>
<categories>
<category>Java</category>
</categories>
<tags>
<tag>Java</tag>
<tag>open jdk</tag>
<tag>版本</tag>
<tag>功能</tag>
<tag>区别</tag>
</tags>
</entry>
<entry>
<title><![CDATA[mac下npm安装命令不生效]]></title>
<url>%2F2018%2F11%2F27%2F%E5%BC%80%E5%8F%91%E8%80%85%E6%89%8B%E5%86%8C%2Fmac%E4%B8%8Bnpm%E5%AE%89%E8%A3%85%E5%91%BD%E4%BB%A4%E4%B8%8D%E7%94%9F%E6%95%88%2F</url>
<content type="text"><![CDATA[介绍如果我们平时使用node进行开发的话,经常会使用node安装一些其他的命令,比如安装淘宝的cnpm(npm install -g cnpm –registry=https://registry.npm.taobao.org),安装vue(npm install vue)命令等等,按道理应该是命令可以直接使用的。 我们在mac上安装完成nodejs,node的命令是在/usr/local/bin下面,可以直接使用,但是我们通过node命令安装的其他工具是在/usr/local/Cellar/node/10.8.0/lib/node_modules/vue-cli/bin/vue,我使用的10.8.0的版本,如果使用其他版本会在其他版本号路径下面,这个安装的路径一般都会统一创建链接到/usr/local/Cellar/node/10.8.0/bin下,所以我们把这个路径添加到我们的环境变量里面就可以了。 解决办法添加到环境变量的一个方式,比如修改~/.bash_profile文件,添加: 12#node安装包下的相关命令cnpm、node等命令export PATH="$PATH:/usr/local/Cellar/node/10.8.0/bin" 执行: 1source ~/.bash_profile 就可以使用cnpm等命令了。]]></content>
<categories>
<category>开发者手册</category>
</categories>
<tags>
<tag>安装</tag>
<tag>命令</tag>
<tag>Mac</tag>
<tag>npm</tag>
<tag>不生效</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Markdown语法]]></title>
<url>%2F2018%2F11%2F27%2F%E5%BC%80%E5%8F%91%E8%80%85%E6%89%8B%E5%86%8C%2FMarkdown%E8%AF%AD%E6%B3%95%2F</url>
<content type="text"><![CDATA[作者 李明明转载请注明出处: http://limingming.org/index.php/2018/11/28/markdown-grammar/ 介绍 Markdown 是一种轻量级标记语言,它允许人们使用易读易写的纯文本格式编写文档,然后转换成格式丰富的HTML页面。 —— 维基百科;Markdown 是一种轻量级标记语言,让写作者专注于写作而不用关注样式。很多有编程基础的程序员比较喜欢使用Markdown进行编写,github项目中README.md都是markdown编写的;以下我讲述通用的语法,保留各个编辑器通用的,还有很多markdown语法是各个编辑器独有的,大家使用过程中可以注意一下,平时使用mac上的编辑器,也为大家分享一下。 语法介绍标题123# 一级标题## 二级标题### 三级标题 演示图效果: 强调 在Markdown中,可以使用 * 或 _ 来表示斜体和加粗。 使用一个*或者_来表示斜体,两个来表示加粗。1234A: *我是斜体*B: _我也是斜体_C:**我是粗体**D: __我也是粗体__ 演示图效果: 例子(摘抄于马克飞象“案例,马克飞象是一个很不错的markdown编辑器,为markdown各种类型的语法提供了一个良好的支持)12345**马克飞象**是一款专为印象笔记(Evernote)打造的Markdown编辑器,通过精心的设计与技术实现,配合印象笔记强大的存储和同步功能,带来前所未有的书写体验。特点概述: - **功能丰富** :支持高亮代码块、*LaTeX* 公式、流程图,本地图片以及附件上传,甚至截图粘贴,工作学习好帮手;- **得心应手** :简洁高效的编辑器,提供[桌面客户端][1]以及[离线Chrome App][2],支持移动端 Web;- **深度整合** :支持选择笔记本和添加标签,支持从印象笔记跳转编辑,轻松管理。 锚点markdown会针对每个标题,在解析时都会添加锚点 id,例如: 123# 介绍# 介绍1那我们就可以使用“[访问介绍标题的锚点](#介绍)”,来定义锚点 测试: 访问介绍标题的锚点; 引用Markdown 标记区块引用和 email 中用 > 的引用方式类似,只需要在整个段落的第一行最前面加上 > : 演示: 列表标记通常放在句子最左边,项目标记后面要接一个字符的空格。 无序列表:使用星号、加号或是减号作为列表标记123* 我是无序列表A + 我是无序列表B - 我是无序列表C 有序列表:使用数字接着一个英文句点1231. 我是无序列表12. 我是无序列表2 3. 我是无序列表3 3.代办列表(简书暂不支持此方式)12- [ ] 不勾选- [x] 勾选 补充如果在列表中使用引用,需要换行缩进,一般为四个空格:12345* 演示内容: > 引用部分1 > 引用部分2 > 引用部分3 > 引用部分4 代码块使用`包裹代码块,并声明代码块的语言,一般会带有相关的解析插件,对代码进行高亮处理,对代码进行着色。 超链接方括号显示说明,圆括号内显示网址, Markdown 编辑器会自动把它转成链接;123[我的博客](https://blog.csdn.net/limm33)[编程者联盟](https://github.com/limm33/ProgrammerLeague/blob/master/ProgrammerLeague.jpg)[个人博客](http://www.limingming.org) 演示: 图片图片和超连接语法比较像,可以在方括号前面加一个!就变成了引用图片了;1234![编程者联盟](url) 或者:![卡卡西](/Users/limm/Pictures/火影忍者/30381-106.jpg) 相对路径也可以(./path/*.jpg)这种形式 分割线使用 3 个以上 - 符号制作分割线:123分割线以上内容------------------分割线以下内容 演示: 表格markdown可以制作表格,方法也很简单例如:1233 | 3 | 3-|-|-3| 3| 3 以上为最基本的结构,‘3’代表你编辑的内容,第一行为表头,但是有的编辑器 - 需要多个,有的需要至少三个,所以布局可以尽量美观:123一列 | 第二列 | 第三列---------|---------------|---------- 值1 | 值2 | 值3 演示: 可以设置对齐方式,使用 :添加在列的左边左对齐,右边为右对齐,两边都添加就是中间对齐:1234一列 | 第二列 | 第三列:---------|---------------:|:----------: 值1 | 值2 | 值3 值3 | 值4 | 值5 演示: 以上为总结的markdown的语法,希望对你的编写有所帮助。 联系我原来一直在CSDN编写博客我的博客我的微信公众号:编程者联盟我的 个人博客我的QQ群:115402375]]></content>
<categories>
<category>开发者手册</category>
</categories>
<tags>
<tag>介绍</tag>
<tag>语法</tag>
<tag>markdown</tag>
<tag>怎么</tag>
<tag>如何</tag>
</tags>
</entry>
<entry>
<title><![CDATA[mac下chromium源码编译笔记]]></title>
<url>%2F2018%2F11%2F25%2F%E5%BC%80%E5%8F%91%E8%80%85%E6%89%8B%E5%86%8C%2Fmac%E4%B8%8Bchromium%E6%BA%90%E7%A0%81%E7%BC%96%E8%AF%91%E7%AC%94%E8%AE%B0%2F</url>
<content type="text"><![CDATA[作者 李明明转载请注明出处: http://limingming.org/index.php/2018/11/28/mac-compile-chromium/ 背景因为项目需要,需要对chromium进行了解,对chromium进行编译,在官网上可以通过:网址,找到各个平台相关详细的介绍,介绍文档这个是mac下编译chromium的讲解,本篇文章是针对于官方介绍文档的中文版,对其中编译过程中遇到的问题进行记录。 因为国内特殊的原因,谷歌相关的网络请求被墙掉了,所有需要配置科学上网能够翻墙的工具,我使用的是自己搭建的shadowsocks,shadowsocks搭建在这里就不细说了,由于需要chromium源码及depots_tools工具需要git命令下载,所以设置http_proxy,通过搭建好的shadowsocks可以通过下图中的方式获取到设置方式在终端中执行就行了,就可以在终端中请求被墙的网络地址了,具体设置git请求的设置和让终端走代理的设置大家可以百度一下,看一下详细的配置,自己设置一下, export http_proxy=http://127.0.0.1:1087;export https_proxy=http://127.0.0.1:1087; 系统要求:64位mac,系统版本10.11+系统版本,屏幕左上角 苹果图标 -> 关于本机 -> 概览 Xcode 7.3+在 App Store搜索下载 OSX 10.10 SDK装完Xcode以后在终端输入下面的代码,如下图所示应该就可以了 1$ ls `xcode-select -p`/Platforms/MacOSX.platform/Developer/SDKs 安装depot_tools用git复制 depot_tools 资源,如果一直下载不成功,检查一下http_proxy是否设置成功 1$ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git 把depot_tools加入路径,假设你放在/path/to/depot_tools路径下面,那么就在终端输入,不过这是临时的, 1$ export PATH="$PATH:/path/to/depot_tools" 获取代码创建一个新的chromium文件夹并进入文件夹,你可以叫它别的名字,可以放在任意的位置,但是要保证路径没有空格 1$ mkdir chromium && cd chromium 使用fetch来检出代码和依赖(这个代码我现在下大概是7.2GB,如果不想要所有的历史记录可以加–no-history,下载会快一点) 带历史记录的源码 1$ fetch chromium 不带历史记录的源码 1$ fetch --no-history chromium 会产生隐藏的.gclient的文件,如果下载失败,可以把这个文件删了重新执行 中间不会有任何的提示,请安静地等待~这种应该是下载成功了吧 然后你就会发现目录下面有src文件夹,进入文件夹,这里有提示install API keys ,但是对大多数的开发者不是必选项,所以就先跳过。在官网上没有详细介绍, 开始编译: 在编译之前要执行gclient sync和gclient runhooks,进入到src目录下,在src目录啊下编译,之前装了depot_tools,那么就可以用下面的代码开新建一个build的目录文件夹,(build可以换名字,但是out文件夹是必需的) gn gen out/build 更快地编译官网给了三个配置可以加快build,分别是is_debug,is_component_build,symbol_level,配置方式如下(关于配置的说明) 输入下面的命令行会打开一个配置文件 1gn args out/build 可以在文件里面输入配置,像下面展示的这样 123is_component_build = trueis_debug = falsesymbol_level = 0 其实他们应该保存在src/out/build/args.gn这边 输入下面的代码你能够查看所有可配置的参数以及他们的默认值 1gn args --list out/my_build 同时也可以通过install ccache ,在再次compile的时候会更快,会增量编译不会重复编译 build chromium使用Ninja来build chromium,这个过程会比较耗时,虽然很多人说等2个小时,我第一次编译用了5个小时 1$ ninja -C out/Default chrome 运行chromium输入 1$ out/Default/chrome Debugging 调试debug资料这里的意思是用图形化的环境不用在xcode里面配置Debugging in Xcode前面按照教程取消了crash的记录 最后的配置是在生成的文件夹下面找到products.xcodeproj,然后双击就会用xcode打开,然后配置scheme,第一次应该没有scheme配置,选择New Scheme,然后Info这边,Executable选择Chromium.app,‘ 然后启动chromium , Debug -》Attach to Processes -> 选择Chomium程序 首先是第一个资料推荐苹果开发者阅读的Mac OS X Debugging Magic Technote重要提醒: 在xcode里面,为了让断点生效,Debugging面板中取消Load Symbols Lazily GYP_DEFINES的fast_build如果是1的话,那么你想要的断点可能拿不到,如果你去掉它,要重新运行gyp_chromium以及rebuild禁用ReportCrash,在终端输入man ReportCrash,然后找到这一行 12launchctl unload -w /System/Library/LaunchAgents/com.apple.ReportCrash.plistsudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.ReportCrash.Root.plist 调试渲染进程XCode本身不支持多于一个的进程,对子进程的支持也不友好,有两种方法应付。 (a)单进程运行chrome(不被推荐) CCache据说是加速recompilation的,他通过存储原来的compilation,当compilations相同的时候,能够有一个显著的加速,特别是切换分支的时候。首先用brew下载在环境变量里面配置 ,下面是临时的 1Export PATH=“$PATH:/usr/local/opt/ccache/libexec ccahe” 然后要让gn配置使用配置环境变量 123export CCACHE_CPP2=yesexport CCACHE_SLOPPINESS=time_macrosexport PATH=`pwd`/third_party/llvm-build/Release+Asserts/bin:$PATH 运行 ninja ninja -C out/Release chrome 推荐大家可以看一下《webkit技术内幕》 联系我原来一直在CSDN编写博客我的博客我的微信公众号:编程者联盟我的 个人博客我的QQ群:115402375]]></content>
<categories>
<category>开发者手册</category>
</categories>
<tags>
<tag>Mac</tag>
<tag>搭建</tag>
<tag>源码</tag>
<tag>chromium</tag>
<tag>谷歌浏览器</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Mac OS下搭建Vue开发环境]]></title>
<url>%2F2018%2F11%2F23%2F%E5%BC%80%E5%8F%91%E8%80%85%E6%89%8B%E5%86%8C%2FMac-OS%E4%B8%8B%E6%90%AD%E5%BB%BAVue%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%2F</url>
<content type="text"><![CDATA[前言原来一直学习使用React,现在因为工作的需要,对Vue进行学习和使用,现在比较流行的框架React,angular,vue,正好对于vue也进行些了解。 环境搭建 打开终端,安装brew 1usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 安装成功后,使用查看版本,验证是否安装成功1brew -v 安装node.js1brew install nodejs 也可以下载安装下载地址安装成功后,使用验证123node -v``` * 给nodejs目录赋权限 sudo chmod -R 777 /usr/local/lib/node_modules/1* 安装 淘宝镜像 (npm) npm install -g cnpm –registry=https://registry.npm.taobao.org12* 安装webpack cnpm install webpack -g12* 安装vue脚手架 npm install vue-cli -g12# 开始Vue 创建一个基于 webpack 模板的新项目$ vue init webpack my-project 这里需要进行一些配置,默认回车即可This will install Vue 2.x version of the template. For Vue 1.x use: vue init webpack#1.0 my-project ? Project name my-project? Project description A Vue.js project? Author runoob test@runoob.com? Vue build standalone? Use ESLint to lint your code? Yes? Pick an ESLint preset Standard? Setup unit tests with Karma + Mocha? Yes? Setup e2e tests with Nightwatch? Yes vue-cli · Generated “my-project”. To get started: cd my-project npm install npm run dev Documentation can be found at https://vuejs-templates.github.io/webpack1进入项目,安装并运行: $ cd my-project$ cnpm install$ cnpm run dev DONE Compiled successfully in 4388ms Listening at http://localhost:8080`]]></content>
<categories>
<category>开发者手册</category>
</categories>
<tags>
<tag>Mac</tag>
<tag>搭建</tag>
<tag>Vue</tag>
<tag>开发环境</tag>
</tags>
</entry>
<entry>
<title><![CDATA[wordpress无法连接到FTP解决]]></title>
<url>%2F2018%2F11%2F23%2F%E5%BC%80%E5%8F%91%E8%80%85%E6%89%8B%E5%86%8C%2Fwordpress%E6%97%A0%E6%B3%95%E8%BF%9E%E6%8E%A5%E5%88%B0FTP%E8%A7%A3%E5%86%B3%2F</url>
<content type="text"><![CDATA[问题未能连接到FTP服务器IP:21 原因分析为了安全起见,wordpress会在安装插件或者主题时增加一层FTP验证 解决 修改wordpress 根目录下wp-config.php文件 1vi wordpress/wp-config.php 在文件最后添加一行内容 1define('FS_METHOD', "direct"); 重新试试就可以了!]]></content>
<categories>
<category>开发者手册</category>
</categories>
<tags>
<tag>解决</tag>
<tag>wordpress</tag>
<tag>无法连接</tag>
<tag>FTP</tag>
<tag>下载插件</tag>
</tags>
</entry>
<entry>
<title><![CDATA[MAC-OS无法开机问题解决]]></title>
<url>%2F2018%2F11%2F11%2F%E8%AE%A1%E7%AE%97%E6%9C%BA%2FMAC-OS%E6%97%A0%E6%B3%95%E5%BC%80%E6%9C%BA%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3%2F</url>
<content type="text"><![CDATA[作为一个自恋的程序员,我的imac升级了系统之后也变得傲娇起来,就是开机无法启动,进度条大约到五分之四的时候就卡住了,电脑也变黑屏了,之后进入了小圆圈一直转的无限循环的状态,暂时简称无限菊花状态。 问题导致原因原来mac系统为10.13.6,升级到了最新的系统之后10.14.8,虽然更新过程中没有任何问题,也能重新启动了电脑,有了新的黑色主题的imac并没有让我适应,总感觉还是原来的主题比较好,再不高兴之余骂了它的主题,顺便关了机,所以它就闹起了小脾气。 问题解决 首先想到的是“开机按住shift键进入安全模式,结果无法启动; 所以无耻的google了一下,按照说明开机无法启动的情况下,按住电源按钮十秒;钟,当然我很坚持的按住了15秒钟,隐隐若若的听到了“嗒”的一个内部的声音,感觉有什么东西被重置了的感觉,但是也是无济于事; 之后按照重置 Mac 上的系统管理控制器 (SMC),按照配置重置了smc,结果仍然不能开机; 按照重置 Mac 上的 NVRAM 或 PRAM重置了,原来电脑是静音状态,重置了之后生效了开机声音,可以听到开机声音了; 经过了以上几个步骤还是不能开机,所以我觉得应该弄点大招了,所以开机使用“command+r”的方式进入恢复模式选择磁盘工具,进行急救,修复了文件权限和磁盘,当然我没有进行任何磁盘破坏的事情,我很确信是因为升级导致的无法启动,所以磁盘急救完成重新开机竟然还是不行; 在磁盘急救不生效的情况下,用command+r进入恢复模式,重新安装系统,此种方式安装系统不会丢失任何文件和应用,可以放心安装,可能因为网络和时区的问题,导致无法正常安装,可以多试几次;但是重装覆盖系统之后还是不能开机。 在恢复模式下磁盘工具中抹掉磁盘,当然要备份好重要数据后抹掉磁盘,然后再执行安装系统,完成后就可以正常开机了。 说明以上几个步骤我在执行过程中可能没有生效,但是很多遇到这种情况的执行其中几步的时候都成功开机了,在万不得已的情况下可以抹掉磁盘重新安装系统。 联系我原来一直在CSDN编写博客我的博客,欢迎留言讨论,现在第一次更换为简书,竟然写的不是技术博客。我的微信公众号:编程者联盟 我的QQ群:115402375]]></content>
<categories>
<category>计算机</category>
</categories>
<tags>
<tag>解决</tag>
<tag>苹果电脑</tag>
<tag>无法开机</tag>
<tag>转圈</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Maven项目中WEB模块中后台代码打成jar包]]></title>
<url>%2F2016%2F12%2F03%2FMaven%2FMaven%E9%A1%B9%E7%9B%AE%E4%B8%ADWEB%E6%A8%A1%E5%9D%97%E4%B8%AD%E5%90%8E%E5%8F%B0%E4%BB%A3%E7%A0%81%E6%89%93%E6%88%90jar%E5%8C%85%2F</url>
<content type="text"><![CDATA[描述 将web模块的后台代码打成jar 包发布到target目录下(war包中正常编译的class依然存在) 123456789101112131415<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <executions> <execution> <id>make-a-jar</id> <phase>compile</phase> <goals> <goal>jar</goal> </goals> </execution> </executions> </plugin> 将web模块的后台代码打成jar包发布到WEB_INF/lib下 123456789101112131415161718192021222324<build> <finalName>manage-elasticsearch-authorization</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.6</version> <configuration> <!-- 释放将项目的类文件打成jar放到lib目录中。 打成jar的好处是:只修改class时,可以只更新jar。 --> <archiveClasses>true</archiveClasses> <webResources> <!-- src/main/resources是默认的资源目录。 当archiveClasses=true时,resources中的文件资源会被打到jar中; 当archiveClasses=false时,resources中的文件资源在war的根目录。 --> <resource> <!-- resources作为source folder,不会被打到jar中。 --> <directory>src/main/resources</directory> <targetPath>WEB-INF/classes</targetPath> <filtering>true</filtering> </resource> </webResources> </configuration> </plugin> </plugins> </build> 以上内容仅为配置后台代码生成到jar包中,一般用于发布应用。]]></content>
<categories>
<category>Maven</category>
</categories>
<tags>
<tag>后台</tag>
<tag>程序</tag>
<tag>代码</tag>
<tag>jar</tag>
<tag>lib</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Maven项目利用Tomcat插件启动运行]]></title>
<url>%2F2016%2F12%2F02%2FMaven%2FMaven%E9%A1%B9%E7%9B%AE%E5%88%A9%E7%94%A8Tomcat%E6%8F%92%E4%BB%B6%E5%90%AF%E5%8A%A8%E8%BF%90%E8%A1%8C%2F</url>
<content type="text"><![CDATA[在2016年底的时候springboot也慢慢成熟起来,并有很多进行应用,但是我们企业上还有很多的项目都还是很传统web工程,从原来Ant脚本打包再到改成Maven的工程,改成Maven工程很多项目也并没有拆分成各个模块,很多还是项目还是臃肿的war包,但是很多的部署却在这种现状下还是想有能够打成jar包或者war包也能直接启动,这种情况下诞生了一下的调研,到今天(2020年4月1号),工程大部分已经改造成了使用springboot spring cloud微服务的开发模式,但是也并不影响我们参考2016年的这个调研配置的思想 内嵌tomcat插件可执行WAR包环境要求123456789101112Unix System\windwos\macOS JDK 1.7+ Maven 3.0 or later 我测试的编译环境是:macOS10.11.6和windows10 jdk1.8/jdk1.7 Maven 3.3.9 我的本机开发环境: MacOS 10.11.6eclipse Mars.2 在pom中配置tomcat-maven-plugin123456789101112131415161718192021222324<project> ... <packaging>war</packaging> ... <build> ... <plugins> ... <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat6-maven-plugin</artifactId> <version>2.2</version> </plugin> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> </plugin> ... </plugins> ... </build> ...</project> 运行war包执行 tomcat7:run-war或者tomca6:run-war 如果想要修改其他配置可以在标签下添加如下等配置 1234567<configuration> <port>8080</port> <path>/demo</path> <uriEncoding>UTF-8</uriEncoding> <finalName>demo</finalName> <server>tomcat7</server> </configuration> 内嵌tomcat插件可执行JAR包环境要求1234567891011Unix System\windwos\macOSJDK 1.7+ tomcat7-maven-plugin version 2.1/2.0/2.0-beta-1Maven 3.0 or later #我测试的编译环境是:macOS10.11.6和windows10jdk1.8/jdk1.7Maven 3.3.9 我的本机开发环境: MacOS 10.11.6eclipse Mars.2 在pom中配置tomcat7-maven-plugin1234567891011121314151617181920212223242526272829<project> <packaging>war</packaging> <build> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <executions> <execution> <id>tomcat-run</id> <goals> <goal>exec-war-only</goal> </goals> <phase>package</phase> <configuration> <path>demo</path> <!-- optional, needed only if you want to use a preconfigured server.xml file --> <serverXml>src/main/tomcatconf/server.xml</serverXml> <!-- optional values which can be configurable --> <attachArtifactClassifier>default value is exec-war but you can customize</attachArtifactClassifier> <attachArtifactClassifierType>default value is jar</attachArtifactClassifierType> </configuration> </execution> </executions> </plugin> </plugins> </build></project> 执行构建生成jar包执行 1mvn clean install 会在target下生成相应的jar包 如果想要修改jar包名称,可以在标签中定义标签修改生成的jar包名称 执行构建出来的jar包部署应用执行构建出来的jar包: 12345678910111213141516171819202122232425 java -jar yourjar``` 其他参数: ```shellusage: java -jar [path to your exec war jar] -ajpPort <ajpPort> ajp port to use -clientAuth enable client authentication for https -D <arg> key=value -extractDirectory <extractDirectory> path to extract war content, default value: .extract -h,--help help -httpPort <httpPort> http port to use -httpProtocol <httpProtocol> http protocol to use: HTTP/1.1 or org.apache.coyote.http11.Http11Nio Protocol -httpsPort <httpsPort> https port to use -keyAlias <keyAlias> alias from keystore for ssl -loggerName <loggerName> logger to use: slf4j to use slf4j bridge on top of jul -obfuscate <password> obfuscate the password and exit -resetExtract clean previous extract directory -serverXmlPath <serverXmlPath> server.xml to use, optional -X,--debug debug 例如:如果需要改变启动容器的端口号(默认为8080) 1java -jar yourjar -httpPort 8081 PS: 在测试过程中使用到的插件版本如下:12.0、2.0-beta-1、2.1、2.2 都可以正常构建生成jar包,但是在执行启动jar包的过程中,在jdk1.8的环境下: 2.1的版本正常,可以正常执行部署,启动运行2.0和2.0-beta-1版本可以正常部署,但是启动tomcat访问中报java.io异常,和jdk执行版本有关,经过多次测试,更换为jdk1.7执行没有可以正常使用。在jdk1.8环境和jdk1.7环境下2.2版本都存在不可以正常创建webapp文件夹,也不可以将应用部署到webapp中,如果手动将jar包的相关内容部署进.extract/再次执行启动命令可以正常使用综上:可以使用2.1版本的插件。]]></content>
<categories>
<category>Maven</category>
</categories>
<tags>
<tag>Maven</tag>
<tag>构建</tag>
<tag>执行</tag>
<tag>WEB</tag>
<tag>插件</tag>
</tags>
</entry>
</search>