Skip to content

Commit ae57cb6

Browse files
author
yangjingjing
committed
init blog
1 parent a085e64 commit ae57cb6

File tree

54 files changed

+12647
-982
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+12647
-982
lines changed
Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@ categories: Maven
44
description: none
55
keywords: Maven
66
---
7-
# Maven简介
8-
Maven 翻译为"专家"、"内行",是 Apache 下的一个纯 Java 开发的开源项目基于项目对象模型(缩写:POM)概念,Maven利用一个中央信息片断能管理一个项目的构建、报告和文档等步骤
7+
# Maven入门
8+
`Maven`这个词可以翻译为“知识的积累”,也可以翻译为“专家”或“内行”。作为`Apache`组织中的一个纯`Java`开发的开源项目基于项目对象模型(POM)概念,Maven主要服务于基于Java平台的项目构建、依赖管理和项目信息管理
99

10-
Maven 是一个项目管理工具,可以对 Java 项目进行构建、依赖管理。
10+
# Maven简介
11+
`Maven`能够帮我们自动化构建过程,从清理、编译、测试到生成报告,再到打包和部署。Maven不仅是构建工具,还是一个依赖管理工具和项目信息管理工具。它提供了中央仓库,能帮我们自动下载构件。
1112

12-
Maven 也可被用于构建和管理各种项目,例如 C#,Ruby,Scala 和其他语言编写的项目。Maven 曾是 Jakarta 项目的子项目,现为由 Apache 软件基金会主持的独立 Apache 项目。
13+
Maven是可以对 Java 项目进行构建、依赖管理。Maven 也可被用于构建和管理各种项目,例如 C#,Ruby,Scala 和其他语言编写的项目。Maven 曾是 Jakarta 项目的子项目,现为由 Apache 软件基金会主持的独立 Apache 项目。
1314

1415
maven并不是市场上唯一的项目构建工具,但是是目前最流行的项目构建工具。
1516

@@ -20,7 +21,6 @@ maven并不是市场上唯一的项目构建工具,但是是目前最流行的
2021
| Gradle | 目前比较新颖的项目构建工具,相对Maven在进行大项目管理时性能更好 |
2122

2223
## Maven 功能
23-
2424
Maven 能够帮助开发者完成以下工作:
2525

2626
- 构建
@@ -72,4 +72,6 @@ Apache Maven [https://maven.apache.org/](https://maven.apache.org/)
7272

7373
Maven Getting Started Guide [https://maven.apache.org/guides/getting-started/index.html](https://maven.apache.org/guides/getting-started/index.html)
7474

75-
mvnrepository [https://mvnrepository.com/](https://mvnrepository.com/)
75+
mvnrepository [https://mvnrepository.com/](https://mvnrepository.com/)
76+
77+
Maven实战

_posts/2014-03-04-Maven仓库.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ categories: Maven
44
description: none
55
keywords: Maven
66
---
7-
# Maven 仓库
7+
# Maven坐标和依赖
8+
Maven的一大功能是管理项目依赖。为了能自动化地解析任何一个Java构件,Maven就必须将它们唯一标识,这就依赖管理的底层基础——坐标。
9+
10+
11+
812
构件:任何一个依赖、插件或者项目构件的输出,都可以成为构件。任何一个构件都有一组坐标唯一标示。
913
得益于坐标机制,任何Maven项目使用任务一个构件的方式都是一致的。在此基础上,Maven可以在某个位置统一存储所有Maven项目共享的构件,这个统一的位置就是仓库。实际的Maven项目将不再各自存储其依赖文件。它们只需要声明这些依赖的坐标,在需要的时候,Maven会自动根据坐标找到仓库中的构件,使用它们。
1014
为了实现重用,项目构建完毕后生成的构件也可以安装或者部署到仓库中,供其他项目使用。

_posts/2015-01-13-Java日志.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
layout: post
3+
categories: [Java]
4+
description: none
5+
keywords: Java
6+
---
7+
# Java日志
8+
9+
## 日志野史
10+
- System.out java 1995
11+
- Log4J Apache/Ceki Gülcü 2001
12+
- JUL(Java Util Logging) java1.4 2002.2
13+
- JCL(Jakarta Commons Logging) Apache 2002.8
14+
- Slf4j(Simple Logging Facade for Java) Ceki Gülcü 2005
15+
- Logback Ceki Gülcü 2006
16+
- Log4j2 Apache 2012
17+
18+
最早大家都用System.out或error来打印日志,但错误严重性有高有低,无法区分。 1996年,一个欧盟赞助的 SEMPER项目打算记录操作API的行为,以便于追溯问题。N. Asokan、Ceki Gülcü 和 Michael Steiner 就提出了分层记录器的想法,这也就是日志级别的由来。
19+
历史总是会留下某个人,然后其他人就没有然后了,哈哈。这个叫切基古尔库的哥们跟他同事一起开发了第一个日志框架Log4j,分层记录的思想是Log4j的核心。
20+
21+
2001年,切基古尔库公开了Log4j,拉开了大战的序幕,Log4j加入Apache,切基古尔库也成为了Apache中的一员,大树下面好乘凉,Log4j迅猛发展。
22+
这时的Java还没有自己的日志系统,Apache盯上了Java,建议Sun把Log4j加入到Java体系中。Sun当然拒绝了,卧榻之侧,岂容他人鼾睡,Sun早就坐不住了,在2002年2月发布了Java1.4,在util加入了自己的Logging,JUL腾空出世,想与Log4J一比高下,奈何JUL功效上稍逊三分,无法干掉Log4j,但是依托java庞大的用户群,还是吸引了一些流量。
23+
24+
此时的Apache心急如焚,眼看着大把的流量被切走,为了捍卫自己的江湖地位,于2002年8月推出一套interface,Jakarta Commons Logging开始面世,JCL可以让使用者在Log4J和JUL之间来回切换。
25+
26+
JCL面世以后,网友猜测,切基古尔库越来越难以掌控Log4j这个项目,加上Log4j使用不规范导致的一些效能问题,还有一些历史遗留问题难以推动解决,他在2005年离开了Apache,并且自立门户,随即推出了另一款Interface,也就是鼎鼎大名的Simple Logging Facade for Java,Slf4j是一套接口的规范,现在不都讲究面向接口编程嘛。
27+
28+
切基古尔库先拿JCL开刀,为了让JCL的使用者方面使用这套Slf4j,他来了个狸猫换太子,开发了jcl-over-slf4j.jar,接着为了方便Log4j的使用者,把Log4j当做Slf4j的实现类,他加了一层适配器,实现了Slf4j-log4j12.jar。
29+
到现在为止,一共有两套接口(JCL和Slf4j),两套实现(Log4j和JUL),为了一统江湖,切基古尔库又开发了log4j-over-slf4j.jar,可以用来替换掉log4j这个实现,进而改为自己的实现。
30+
JUL虽比不过log4j,但是那又怎能放过,2008年的时候,他也在JUL上加了一层适配器,实现了slf4j-jdk14.jar。
31+
32+
Slf4j只是一套接口规则,想要胜出,还是要拿出实际的东西来,切基古尔库深谙这个理儿,从2006年开始,他就着手开发一套属于Slf4j自己的实现,自己亲自开发Log4j,对于其不合理和遗留的问题他太熟悉了,第三套实现Logback也顺理成章的出世了,关键功效上比Log4j更胜一筹
33+
34+
Slf4j和Logback大行其道,Apache也不会坐以待毙,既然你想靠一个Slf4j称霸,那我也搞一个东西出来一统江湖,2012年Log4j2终于问世,但是Log4j2也算是Log4j的直接升级版,但这两的架构相差甚远。但Log4j2的分层方式又能看到Logback的影子。
35+
至此,java世界的Log之争暂时先告一段落。
36+
37+
## 关于日志选型
38+
JCL和Slf4j是接口,log4j、log4j2、logback都是实现,日常开发一般会选择接口+实现的方式来作为项目日志的集成方式,网上很多关于log4j2与logback各种性能参数的对比,大都是基于特定的版本,这也从侧面告诉我们,在实际开发过程中,要结合自己项目,在确定jdk或者spring版本的基础上,再去选择对比各日志性能的优劣。
39+
40+
41+
42+
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
---
2+
layout: post
3+
categories: [Java]
4+
description: none
5+
keywords: Java
6+
---
7+
# Logback日志实战
8+
logback 用于日志记录,可以将日志输出到控制台、文件、数据库和邮件等,相比其它所有的日志系统,logback 更快并且更小,包含了许多独特并且有用的特性。
9+
10+
## Logback优点
11+
Logback和log4j非常相似,优点如下:
12+
- Logback的内核重写,在一些关键执行路径上性能提升10倍以上。同时,初始化内存加载也更小。
13+
- Logback经过数年的测试,这是简单重要的原因选择logback而不是log4j。
14+
- 因为logback-classic非常自然地实现了SLF4J,所以切换到log4j非常容易,只需要提供另一个jar包就OK,不需要去动通过SLF4JAPI实现的代码。
15+
- 非常充分的文档
16+
- 当配置文件修改了,Logback-classic能自动重新加载配置文件。扫描过程快且安全,它并不需要另外创建一个扫描线程。
17+
- Lilith是log事件的观察者,和log4j的chainsaw类似。而lilith还能处理大数量的log数据 。
18+
- 在谨慎模式下,多个FileAppender实例跑在多个JVM下,能够安全地写到同一个日志文件。RollingFileAppender会有些限制。Logback的FileAppender和它的子类包括 RollingFileAppender能够非常友好地从I/O异常中恢复。
19+
- 开发人员经常需要判断不同的Logback配置文件在不同的环境下(开发,测试,生产)。而这些配置文件仅仅只有一些很小的不同,可以通过,来实现,这样一个配置文件就可以适应多个环境。
20+
- 有些时候,需要诊断一个问题,需要打出日志。在log4j,只有降低日志级别,不过这样会打出大量的日志,会影响应用性能。在Logback,你可以继续保持那个日志级别而除掉某种特殊情况,如alice这个用户登录,它的日志将打在DEBUG级别而其他用户可以继续打在WARN级别。要实现这个功能只需加4行XML配置。可以参考MDCFIlter 。
21+
- 它可以用来分割日志文件根据任何一个给定的运行参数。如,SiftingAppender能够区别日志事件跟进用户的Session,然后每个用户会有一个日志文件。
22+
- RollingFileAppender在产生新文件的时候,会自动压缩已经打出来的日志文件。压缩是个异步过程,在压缩过程中应用不会受任何影响。
23+
- Logback在打出堆栈树日志时,会带上包的数据。
24+
- 通过设置TimeBasedRollingPolicy或者SizeAndTimeBasedFNATP的maxHistory属性,你可以控制已经产生日志文件的最大数量。
25+
26+
## logback的加载
27+
我们简单分析一下logback加载过程,当我们使用logback-classic.jar时,应用启动,那么logback会按照如下顺序进行扫描:
28+
- 在系统配置文件System Properties中寻找是否有logback.configurationFile对应的value
29+
- 在classpath下寻找是否有logback.groovy(即logback支持groovy与xml两种配置方式)
30+
- 在classpath下寻找是否有logback-test.xml
31+
- 在classpath下寻找是否有logback.xml
32+
33+
以上任何一项找到了,就不进行后续扫描,按照对应的配置进行logback的初始化,具体代码实现可见ch.qos.logback.classic.util.ContextInitializer类的findURLOfDefaultConfigurationFile方法。当所有以上四项都找不到的情况下,logback会调用ch.qos.logback.classic.BasicConfigurator的configure方法,构造一个ConsoleAppender用于向控制台输出日志,默认日志输出格式为"%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"。
34+
35+
## logback的configuration
36+
logback的重点应当是Appender、Logger、Pattern,在这之前先简单了解一下logback的,只有三个属性:
37+
scan:当scan被设置为true时,当配置文件发生改变,将会被重新加载,默认为truescanPeriod:检测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认为毫秒,当scan=true时这个值生效,默认时间间隔为1分钟debug:当被设置为true时,将打印出logback内部日志信息,实时查看logback运行信息,默认为false
38+
39+
### logger
40+
logger用来设置某一个包或者具体某一个类的日志打印级别、以及指定**
41+
42+
可以包含零个或者多个元素,标识这个appender将会添加到这个logger。
43+
44+
仅有一个name属性、一个可选的level属性和一个可选的additivity属性:
45+
- name:用来指定受此logger约束的某一个包或者具体的某一个类
46+
- level:用来设置打印级别,五个常用打印级别从低至高依次为TRACE、DEBUG、INFO、WARN、ERROR,如果未设置此级别,那么当前logger会继承上级的级别
47+
- additivity:是否向上级logger传递打印信息,默认为true
48+
49+
也是元素,但是 它是根logger,只有一个level属性,因为它的name就是ROOT ,源码在LoggerContext中:
50+
```
51+
public LoggerContext() {
52+
super();
53+
this.loggerCache = new ConcurrentHashMap<String, Logger>();
54+
this.loggerContextRemoteView = new LoggerContextVO(this);
55+
this.root = new Logger(Logger.ROOT_LOGGER_NAME, null, this);
56+
this.root.setLevel(Level.DEBUG);
57+
loggerCache.put(Logger.ROOT_LOGGER_NAME, root);
58+
initEvaluatorMap();
59+
size = 1;
60+
this.frameworkPackages = new ArrayList<String>();
61+
}
62+
```
63+
看到第一个参数就是Root的name,而这个Logger.ROOT_LOGGER_NAME的定义为 final public String ROOT_LOGGER_NAME = "ROOT" ,由此可以看出节点的name就是"ROOT"。
64+
65+
## 引入依赖
66+
logback 天然的支持 slf4j,不需要像其他日志框架一样引入适配层(如 log4j 需引入 slf4j-log4j12 )。logback 只是将适配相关代码放入了 logback-classic。
67+
```xml
68+
<dependencies>
69+
<dependency>
70+
<groupId>junit</groupId>
71+
<artifactId>junit</artifactId>
72+
<version>4.12</version>
73+
<scope>test</scope>
74+
</dependency>
75+
<!-- logback+slf4j -->
76+
<dependency>
77+
<groupId>org.slf4j</groupId>
78+
<artifactId>slf4j-api</artifactId>
79+
<version>1.7.28</version>
80+
<type>jar</type>
81+
<scope>compile</scope>
82+
</dependency>
83+
<dependency>
84+
<groupId>ch.qos.logback</groupId>
85+
<artifactId>logback-core</artifactId>
86+
<version>1.2.3</version>
87+
<type>jar</type>
88+
</dependency>
89+
<dependency>
90+
<groupId>ch.qos.logback</groupId>
91+
<artifactId>logback-classic</artifactId>
92+
<version>1.2.3</version>
93+
<type>jar</type>
94+
</dependency>
95+
</dependencies>
96+
```
97+
98+
99+
100+

_posts/2015-01-13-Logback源码.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
---
2+
layout: post
3+
categories: [Java]
4+
description: none
5+
keywords: Java
6+
---
7+
# Logback日志源码
8+
logback 用于日志记录,可以将日志输出到控制台、文件、数据库和邮件等,相比其它所有的日志系统,logback 更快并且更小,包含了许多独特并且有用的特性。
9+
10+
## logback模块
11+
logback 被分成三个不同的模块:logback-core,logback-classic,logback-access。
12+
- logback-core 是其它两个模块的基础。
13+
- logback-classic 模块可以看作是 log4j 的一个优化版本,它天然的支持 SLF4J。
14+
- logback-access 提供了 http 访问日志的功能,可以与 Servlet 容器进行整合,例如:Tomcat、Jetty。
15+
16+
## slf4j是如何实现门面模式的
17+
slf4j 使用的是门面模式,不管使用什么日志实现,项目代码都只会用到 slf4j-api 中的接口,而不会使用到具体的日志实现的代码。slf4j 到底是如何实现门面模式的?接下来进行源码分析:
18+
19+
在我们的应用中,一般会通过以下方式获取 Logger 对象,我们就从这个方法开始分析吧:
20+
```
21+
Logger logger = LoggerFactory.getLogger(LogbackTest.class);
22+
```
23+
进入到 LoggerFactory.getLogger(Class<?> clazz)方法,如下。在调用这个方法时,我们一般会以当前类的 Class 对象作为入参。当然,logback 也允许你使用其他类的 Class 对象作为入参,但是,这样做可能不利于对 logger 的管理。通过设置系统属性-Dslf4j.detectLoggerNameMismatch=true,当实际开发中出现该类问题,会在控制台打印提醒信息。
24+
```
25+
public static Logger getLogger(Class<?> clazz) {
26+
// 获取Logger对象,后面继续展开
27+
Logger logger = getLogger(clazz.getName());
28+
// 如果系统属性-Dslf4j.detectLoggerNameMismatch=true,则会检查传入的logger name是不是CallingClass的全限定类名,如果不匹配,会在控制台打印提醒
29+
if (DETECT_LOGGER_NAME_MISMATCH) {
30+
Class<?> autoComputedCallingClass = Util.getCallingClass();
31+
if (autoComputedCallingClass != null && nonMatchingClasses(clazz, autoComputedCallingClass)) {
32+
Util.report(String.format("Detected logger name mismatch. Given name: \"%s\"; computed name: \"%s\".", logger.getName(),
33+
autoComputedCallingClass.getName()));
34+
Util.report("See " + LOGGER_NAME_MISMATCH_URL + " for an explanation");
35+
}
36+
}
37+
return logger;
38+
}
39+
```
40+
进入到LoggerFactory.getLogger(String name)方法,如下。在这个方法中,不同的日志实现会返回不同的ILoggerFactory实现类:
41+
```
42+
public static Logger getLogger(String name) {
43+
// 获取工厂对象,后面继续展开
44+
ILoggerFactory iLoggerFactory = getILoggerFactory();
45+
// 利用工厂对象获取Logger对象
46+
return iLoggerFactory.getLogger(name);
47+
}
48+
```
49+
进入到getILoggerFactory()方法,如下。INITIALIZATION_STATE代表了初始化状态,该方法会根据初始化状态的不同而返回不同的结果。
50+
51+
52+
53+

_posts/2015-03-02-并发编程基础.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,3 +552,14 @@ A computer program is a collection of instructions that performs a specific task
552552
### 死锁(Deadlock)、饥饿(Starvation)和活锁(Livelock
553553

554554

555+
# 参考资料
556+
Java并发编程之美
557+
Java高并发编程详解:多线程与架构设计
558+
Java并发实现原理
559+
多线程与架构设计姊妹篇
560+
Java并发编程的艺术
561+
Java编程的逻辑
562+
七周七并发模型
563+
实战Java高并发程序设计
564+
精通Java并发编程
565+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
layout: post
3+
categories: JUC
4+
description: none
5+
keywords: JUC
6+
---
7+
# 并发编程原子类
8+
9+
10+
11+

0 commit comments

Comments
 (0)