吞枣

吞枣 查看完整档案

填写现居城市  |  填写毕业院校  |  填写所在公司/组织 tunzao.me 编辑
编辑

It works on my machine...

个人动态

吞枣 关注了标签 · 1月11日

macos

Mac OS 是一套运行于苹果Macintosh系列电脑上的操作系统,包括了 OS X、Mac OS 9、Mac OS 8 及 System vX.X 这一系列的操作系统。Mac OS 是第一个在商用领域成功的图形用户界面。

关注 76

吞枣 发布了文章 · 1月11日

Java的那些日志框架们

日志在排查线上问题、跟踪线上系统运行情况中发挥着重要作用。在Java应用的开发中,常见的日志框架有JCL(commons-logging),slf4jJUL(java.util.logging),log4jlog4j2logback等。这些日志框架大致可以分为两类,一类是日志门面(JCL、slf4j),定义日志的抽象接口;另一类是日志实现(JUL,log4j,log4j2,logback),负责真正地处理日志。为什么会有这么多的日志框架呢?从Java日志框架的发展史里大概可以一探究竟。

Java日志框架的发展历史

  • log4j是Java社区最早的日志框架,推出后一度成为Java的事实日志标准,据说Apache曾建议Sun把log4j加入到Java标准库中,但是被Sun拒绝
  • 在Java1.4中,Sun在标准库中推出了自己的日志框架java.util.logging,功能相对简陋
  • 虽然JUL相对简陋,但还是有类库采用了它,这就出现了同一个项目中同时使用log4j和JUL要维护两套配置的问题,Apache试图解决这个问题,推出了JCL日志门面(接口),定义了一套日志接口,底层实现支持log4j和JUL,但是并没有解决多套配置的问题
  • log4j的主力开发Ceki Gülcü由于某些原因离开了Apache,创建了slf4j日志门面(接口),并实现了性能比log4j性能更好的logback(如果Ceki Gülcü没有离开Apache,这应该就是log4j2的codebase了)
  • Apache不甘示弱,成立了不兼容log4j 1.x的log4j2项目,引入了logback的特性(还酸酸地说解决了logback架构上存在的问题),但目前采用率不是很高

日志框架选择

那么面对这些日志框架,该如何选择呢?如果你是在开发一个新的项目(类库)而不是维护一个上古的遗留代码,那么在打印日志时推荐使用日志门面,秉承面向接口编程的思想,与具体的日志实现框架解耦,这样日后可以很容易地切换到其他的日志实现框架。

特别是当你的代码以SDK的方式提供给别人使用时,使用日志门面能避免使用方可能出现的日志框架冲突问题。如果你的SDK里使用了log4j,而使用方的应用里使用的logback,这时使用方就不得不分别针对log4j和logback维护两套日志配置文件,来确保所有日志正常的输出(slf4j提供了冲突解决方案,稍后在下文介绍)。

在目前已有的两个日志门面框架中,slf4j规避了JCL在部分场景下因为ClassLoader导致绑定日志实现框架失败的问题;能支持以上提到的所有日志实现框架;且slf4j支持占位符功能,在需要拼接日志的情况在接口层面就比JCL有更好的性能,所以推荐使用slf4j,下面简单多介绍下slf4j。

// slf4j的占位符功能
LOGGER.info("hello {}", name);

slf4j如何实现对log4j和JUL的支持

logback因为本身就实现了slf4j-api,所以天然就能很好地支持slf4j,但是log4j和JCL不同,早在slf4j之前就已经存在,他们可不是为了实现slf4j而设计的,那么如何实现slf4j和他们的绑定呢?答案就是适配器模式。如下图,slf4j分别为log4j和JCL实现了适配层slf4-log4j12.jarslf4j-jdk14.jar,通过适配层把日志的处理转发给底层日志实现框架。

concrete-bindings

下面是使用log4j 1.x做为日志实现框架的maven依赖配置:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.26</version>
</dependency>
<!-- slf4j-log4j12 依赖了log4j,不需要再显示地依赖log4j -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.26</version>
</dependency>

slf4j解决日志实现框架冲突

由于历史原因,总会遇到依赖的多个类库使用不同日志实现框架的情况,之前也提到了,为了确保日志正常输出,需要针对多个的日志实现框架维护多个配置文件。为了解决这个问题,slf4j再次基于适配器模式提供了解决方案,针对不同的日志实现框架实现了xxx-over-slf4j适配层,把对日志实现框架的调用转发到slf4j-api,再由slf4j把日志处理转发给日志实现框架。

日志依赖冲突

上图分别展示了把log4j,logback,JUL,JCL的调用分别转换成其中一种日志实现框架的示意图。假设项目依赖的SDK分别使用了log4j、JUL和JCL,打算把日志实现框架统一成log4j,maven依赖配置如下:

<dependency>
    <groupId>me.tunzao</groupId>
    <artifactId>classloader-common</artifactId>
    <version>1.0-SNAPSHOT</version>
    <exclusions>
        <!-- 排除对jcl的依赖 -->
        <exclusion>
            <artifactId>commons-logging</artifactId>
            <groupId>commons-logging</groupId>
        </exclusion>
    </exclusions>
</dependency>

<!-- 把对jcl的请求转发给slf4j -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jcl-over-slf4j</artifactId>
    <version>1.7.26</version>
</dependency>

<!-- 把对jul的请求转发给slf4j -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jul-to-slf4j</artifactId>
    <version>1.7.26</version>
</dependency>

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.26</version>
</dependency>

<!-- slf4j-log4j12 依赖了log4j,不需要再显示地依赖log4j -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.26</version>
</dependency>

需要注意的是log4j-over-slf4j.jar 和 slf4j-log4j12.jar 不能同时出现在classpath下,否则就会因为循环调用而堆栈溢出,同理jul-to-slf4j.jar和slf4j-jdk14.jar、jcl-over-slf4j.jar和slf4j-jcl.jar亦不能同时出现。

原文

查看原文

赞 0 收藏 0 评论 0

吞枣 回答了问题 · 2019-08-16

解决mysql JDBC驱动程序放在哪里?怎么用?

如果对IDE这么有偏见的话,建议你放弃java吧。

关注 3 回答 4

吞枣 发布了文章 · 2019-08-16

Proxy Jump

为了安全起见,线上机器一般不会允许用户通过ssh直接登录,而是需要通过堡垒机(跳板机)跳转到目标线上机器,这样方便对权限控制的管理和访问操作的审计。不知道公司用的是哪款堡垒机产品,选择目标机器的过程异常繁琐。查看ssh的手册(manual)看到了-J选项,可以通过该选项指定ProxyJump然后直接登录到目标机器,命令如下:

ssh -J user@jump.tunzao.me:80 user2@a.tunzao.me

不过要scp文件到目标机器上就有点困难了(可以通过-o选项指定ssh_option,但是还没弄明白怎么指定),而且每次登录都输这么长一串字符串实在是难以忍受,减少敲击次数的一个方案是alias,另一个方案是编辑~/.ssh/config文件配置ProxyJump,指定某些机器通过堡垒机登录,格式如下:

### 堡垒机
Host jump
  HostName jump.tunzao.me
  Port 80
  User user

### 目标机器,通过堡垒机登录
Host a
  HostName a.tunzao.me
  ProxyJump  jump

这样就能通过 ssh user2@a 登录 a.tunzao.me 了,同时也能通过 scp afile.txt user2@a:~ 拷贝文件到 a.tunzao.me 上。Host指令后的 jump 同时可以用作ssh的别名,如果要使用用户 user 登录到 jump.tunzao.me 直接执行 ssh jump 即可。

原文

查看原文

赞 0 收藏 0 评论 0

吞枣 发布了文章 · 2019-08-15

长大后我就成了你

第一次接触Chrome是在大学寝室里龙哥的电脑上,那时候IE6还霸占者绝对的浏览器市场份额,装着IE内核、披着华丽外衣的国产浏览器也正春笋般崛起,真是有点被那蓝色简洁的窗体给惊讶到了,但是并没有让我从Firefox转战到Chrome,这么简单的一款产品在功能性和扩展性上怎么能和插件丰富的Firefox相比,于是我坚守在Firefox的阵地,同时鄙视、谩骂着IE。

后来Chrome支持了扩展功能、有了自己的Web Store,而且没有Firefox向后兼容的历史包袱,交互和体验上都做的比Firefox要好,真正让我忍受不了Firefox而转向Chrome的原因竟是vim插件,由于Firefox的限制vimperator插件不支持Ctrl+[,而且f键给链接贴上的数字按钮巨丑,而Chrome的Vimium在这两方面都比Firefox做的要好,于是狠心抛弃了Firefox。

在Firefox Quantum发布后不久,Vimium插件被成功的移植到Firefox,我又换回了Firefox。vim插件不是再次转换阵营的主要原因,更多是被Firefox的关于页给“洗脑”,为了保护隐私,为了自由, you name it。

Firefox is designed by Mozilla, a global community working to keep the Web open, public and accessible to all.

十年后的如今Chrome占据着浏览器市场的绝对份额,也有些网站从只兼容IE变成了只兼容Chrome。独占鳌头的Chrome会慢慢地自定义web标准吗?会成为下一个IE吗?

原文

查看原文

赞 0 收藏 0 评论 3

吞枣 赞了回答 · 2016-08-16

Maven项目怎么读取resources配置文件?

ClassLoader classloader = Thread.currentThread().getContextClassLoader();
InputStream is = classloader.getResourceAsStream("generatorConfig.xml");

关注 4 回答 3

吞枣 关注了问题 · 2016-08-03

解决phpstorm如何开启相对行号显示?

我是使用了ideavim这个插件的,所以在写代码的时候,都是用vim的方式来操作的。
因为vim中的大量操作是需要计算相对行号的,但是我找不到phpstorm中开启相对行号的配置?
求助一下!!谢谢!

关注 2 回答 4

吞枣 回答了问题 · 2016-08-03

解决phpstorm如何开启相对行号显示?

既然你都用上ideavim了,那就在~/.ideavimrc里设置显示行号就是了:

set nu
set relativenumber

关注 2 回答 4

吞枣 关注了问题 · 2016-07-29

大家都用什么工具管理mysql数据库?

最近在做数据库管理产品,调查一下各位一般都用什么工具管理mysql数据库

关注 27 回答 28

吞枣 回答了问题 · 2016-07-29

大家都用什么工具管理mysql数据库?

MySQLWorkbench
拒绝盗版

关注 27 回答 28

认证与成就

  • 获得 27 次点赞
  • 获得 17 枚徽章 获得 1 枚金徽章, 获得 5 枚银徽章, 获得 11 枚铜徽章

擅长技能
编辑

(゚∀゚ )
暂时没有

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2012-11-11
个人主页被 677 人浏览