2014年12月

SLF4j 一些理解

  1. SLF4J 是什么?

SLF4j (Simple Logging Facade for Java) 是对常用 logging 框架进项抽象提取之后定义的一个Facade API. 当你编程的时候, 仅使用SLF4j API, 而真正部署的时候可以定义到底使用哪个具体的logging 框架. 常见的logging 框架有: java.util.logging, log4j, logback, 还有一个logging facade 叫 Jakarta Commons Logging.

  1. 如何使用SLF4j?

pom.xml (以使用maven 为例), 添加如下依赖:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.9</version>
</dependency>
  1. 为什么要用 SLF4j?

作为Application的开发者来说, 很容易定义使用哪个logging框架, 尤其是在开发的时候. 可是如果代码都开发完成了, 想改logging 框架, 就比较麻烦, 如果使用SLF4j 那么就可以在deployment的时候, 随时选择更改logging 框架, 仅仅是替换binding和logging 的框架 jar 文件.
作为Library的开发者来说, 你不能限定最终的Application的开发者使用哪个logging 框架, 所以最好使用一个SLF4j这种facade API.

  1. SLF4j 的内部是怎么实现的?

SLF4j 有三层: a) API 层, 就是这个slf4j-api-x.x.x.jar. b) binding 层, 是API和真正的logging 框架之间的adapter. c) 具体的logging 框架层.
官方的架构图如下:
请输入图片描述
logback 是 SLF4j的亲儿子, 所以它是 binding层和具体的logging 框架层合一的, 都在 logback-core 和 logback-classic 这2个jar 文件中.

  1. 其它

如果你想把现有的原代码迁移到 SLF4j, 可以使用他们提供的这个 迁移工具
如果你想把现有的二进制代码里面的使用的非SLF4j的代码也改成使用SLF, 看 这里

  1. SLF4j 和 JCL 的实现区别?

SLF4j 使用 static binding 方式, 它的binding 发现是通过 ClassLoader 查找 org.slf4j.impl.StaticLoggerBinder 类, 然后加载, 找到对应的binding. 这个类是在 api jar中定义的, 却不在这个jar 里面, 而分布在具体的binding jar 里面, 当 SLF4j 第一次初始化的时候, 它会在系统查找, 如果没有发现这个类, 就默认为是 NOP (No Operation), 如果找到一个这个类, 就使用这个binding, 如果找到多个, 就使用算法算出使用具体哪个.

另外, 它避免了JCL的 class loader issue, 提供了参数化的log msg 参数.

使用浏览器的 Javascript 进行集合对比

有时候要做些集合的对比, 比如集合A有, 集合B 没有之类的, 或者二者都有的. 浏览器的console 是一个很好的工具, 可以用Javascript 来对比.

function onlyInSet1(set1, set2) {
    var onlySet1Has = [];
    for (var i in set1) {
        if (0 > set2.indexOf(set1[i])) {
            onlySet1Has.push(set1[i]);
        }
    }
    
    return onlySet1Has;
}

function inBothSets(set1, set2) {
    var bothHave = [];
    for (var i in set1) {
        if (0 <= set2.indexOf(set1[i])) {
            bothHave.push(set1[i]);
        }
    }
    
    return bothHave;
}

function printSet(set) {
    for (var i in set) {
        console.debug(set[i]);
    }
}

var set1 = ["a", "b", "c", "d"];
var set2 = ["b", "c", "d", "e"];

var onlySet1Has = onlyInSet1(set1, set2);
var onlySet2Has = onlyInSet1(set2, set1);

console.debug("Only Set1 has: ");
printSet(onlySet1Has);

console.debug("Only Set2 has: ");
printSet(onlySet2Has);

var bothHave = inBothSets(set1, set2);
console.debug("Both have: ");
printSet(bothHave);

Windows 创建虚拟盘符

有开发人员申请一台VM, 正常的windows VM 上面是有C 盘和 D 盘的, 昨天申请一个, 却没有D盘. 以为image 出了问题. 最后的结果竟然是: 这个D盘默认都是没有的, 有的也是虚拟出来的. 其实他是C盘的一个文件夹. 那么问题来了, 怎么做呢?

cd c:/  ##进入C盘根目录
mkdir zDrive   ## 创建文件夹
subst z: c:\zDrive    ## 映射虚拟盘符

如果你不要了, 那么这么删掉

subst z: /D

Bash Pocket Reference - History

1979 年 随Unix V7 发布的 Bourne Shell变成了shell 脚本的标准, 如今许多商用 Unix 上还可以发现 /bin/sh.

因为 Berkeley C shell (csh) 提供了更多用于交互的特性, 如 command history, job control, 很长一段时间, Unix 上Bourne shell 都用作编程, Berkeley C shell 用作交互;
贝尔实验室的 David Korn 不断的给 Bourne Shell 提供增强的特性, 最后超过了 Bourne Shell 和 Berkeley C shell, 并且兼容前二者;
如今 POSIX 定义的 标准Shell 基于 Bourne Shell, 并且从 Korn Shell 中提取一部分特性;

The Free Software Foundation, in keeping with its goal to produce a complete Unix work-alike system, developed a clone of the Bourne shell, written from scratch, named “Bash,” the Bourne-Again SHell. Over time, Bash has become a POSIX-compliant version of the shell with many additional features overlapping those of the Korn shell, but Bash is not an exact Korn shell clone. Today, Bash is arguably the most widely used Bourne-derived shell.