JUL(jdk自带)
适用于小型的java项目,不需要第三方类库。
1.jul的架构如下
- Loggers:被称为记录器,应用程序通过获取Logger对象,调用其API来来发布日志信息。Logger通常时应用程序访问日志系统的入口程序。
- Appenders:也被称为Handlers,每个Logger都会关联一组Handlers,Logger会将日志交给关联Handlers处理,由Handlers负责将日志做记录。Handlers在此是一个抽象,其具体的实现决定了日志记录的位置可以是控制台、文件、网络上的其他日志服务或操作系统日志等。
- Layouts:也被称为Formatters,它负责对日志事件中的数据进行转换和格式化。Layouts决定了数据在一条日志记录中的最终形式。
- Level:每条日志消息都有一个关联的日志级别。该级别粗略指导了日志消息的重要性和紧迫,我可以将Level和Loggers,Appenders做关联以便于我们过滤消息。
- Filters :过滤器,根据需要定制哪些信息会被记录,哪些信息会被放过
2. 简单使用入门
@Test
public void test1(){
//1.获取日志记录器对象
Logger logger=Logger.getLogger("com.hncj.log.jul.JULStudy");
//2.日志输出
logger.info("hello,第一次使用日志");
//通用方法记录日志
logger.log(Level.INFO,"hello,第二次日志记录");
//通过占位符方式输出变量
String username="wangshanhe";
int age=18;
logger.log(Level.INFO,"我叫:{0},我今年{1}岁了",new Object[]{username,age});
}
输出结果
3.日志的级别(level枚举类)
- SEVERE:当我们程序出现很严重的问题,造成了程序的终止,我们可以拿severe进行记录
- WARNING:记录程序出现的一些问题,这些问题不会造成程序的终止,我们可以使用warning进行记录
- INFO:记录一些程序信息,如发送邮件、连接数据库。
- CONFIG:记录配置信息,加载配置问价,读取配置文件的信息可以拿config进行记录
- FINE、FINER、FINEST:这仨都是debug日志记录消息,记录程序运行的状态、程序执行流程,参数传递信息
- ALL和OFF都是日志开关
4.默认的日志级别是info
//日志级别
@Test
public void test2(){
//1.获取日志记录对象
Logger logger=Logger.getLogger("日志级别测试类");
//2.日志记录输出
logger.severe("server级别日志输出");
logger.warning("warning级别日志输出");
logger.info("info级别日志输出");//jul默认的日志级别是info 比info高的输出,比info低的默认过滤
logger.config("config级别日志输出");
logger.fine("fine级别日志输出");
logger.finer("finer级别日志输出");
logger.finest("finest级别日志输出");
}
输出结果
5.自定义日志输出级别
//自定义日志级别
@Test
public void test3() throws IOException {
//1.获取日志记录对象
Logger logger=Logger.getLogger("日志级别测试类");
//2.自定义配置日志级别
//关闭系统默认配置
logger.setUseParentHandlers(false);
//配置日志的级别
logger.setLevel(Level.ALL);//配置系统的日志级别
consoleHandler.setLevel(Level.ALL);//配置哪些级别的日志可以输出到控制台
//方式一:创建ConsolHandler(控制台输出)
ConsoleHandler consoleHandler=new ConsoleHandler();
//创建简单的格式转换对象
SimpleFormatter simpleFormatter=new SimpleFormatter();
//进行关联
consoleHandler.setFormatter(simpleFormatter);
logger.addHandler(consoleHandler);
//方式二:创建FileHandler(日志文件输出)
FileHandler fileHandler = new FileHandler("F:\\jul.txt");
//创建简单的格式转换对象
SimpleFormatter simpleFormatter1=new SimpleFormatter();
//进行关联
fileHandler.setFormatter(simpleFormatter1);
logger.addHandler(fileHandler);
//2.日志记录输出
logger.severe("server级别日志输出");
logger.warning("warning级别日志输出");
logger.info("info级别日志输出");//jul默认的日志级别是info 比info高的输出,比info低的默认过滤
logger.config("config级别日志输出");
logger.fine("fine级别日志输出");
logger.finer("finer级别日志输出");
logger.finest("finest级别日志输出");
}
运行结果如下:
6.logger对象的父子关系
logger对象的父子关系,默认是根据创建对象的标志对应的包的层级来判断的。且默认子包继承父包的日志级别。
//Logger对象的父子关系
@Test
public void test4(){
//1.获取日志记录对象
Logger logger=Logger.getLogger("com.hncj.log.jul.JULStudy");
Logger logger1=Logger.getLogger("com.hncj.log.jul");
Logger logger2=Logger.getLogger("com.hncj.log");
Logger logger3=Logger.getLogger("heiheih");
System.out.println("************************************************************************");
System.out.println("logger3的父对象为:"+logger3.getParent());
System.out.println("logger2的父对象为:"+logger2.getParent());
System.out.println("logger1的父对象为:"+logger1.getParent());
System.out.println(" logger的父对象为:"+logger.getParent());
System.out.println("************************************************************************");
System.out.println("logger3的父对象的名称为:"+logger3.getParent().getName());
System.out.println("logger2的父对象的名称为:"+logger2.getParent().getName());
System.out.println("logger1的父对象的名称为:"+logger1.getParent().getName());
System.out.println(" logger的父对象的名称为:"+logger.getParent().getName());
System.out.println("************************************************************************");
System.out.println("logger1的父对象是否是logger2: "+(logger1.getParent()==logger2));
System.out.println("logger的父对象是否是logger1: "+(logger.getParent()==logger1));
logger1.setUseParentHandlers(false);
ConsoleHandler consoleHandler=new ConsoleHandler();
SimpleFormatter simpleFormatter=new SimpleFormatter();
consoleHandler.setLevel(Level.ALL);
logger1.setLevel(Level.ALL);
consoleHandler.setFormatter(simpleFormatter);
logger1.addHandler(consoleHandler);
logger.severe("server级别日志输出");
logger.warning("warning级别日志输出");
logger.info("info级别日志输出");
logger.config("config级别日志输出");
logger.fine("fine级别日志输出");
logger.finer("finer级别日志输出");
logger.finest("finest级别日志输出");
}
结果如图
7.jul配置文件入门
//加载自定义配置文件
@Test
public void test06() throws Exception {
//1、读取配置文件,通过类加载器
InputStream ins = JULStudy.class.getClassLoader().getResourceAsStream("logging.properties");
//2、创建logManager对象
LogManager logManager = LogManager.getLogManager();
//3、通过logManager加载配置文件 当LogManager被加载到内存时, logManager对象就已经被创建了。
logManager.readConfiguration(ins);
//4、创建日志记录对象
Logger logger = Logger.getLogger("com.hncj.log.jul.JULStudy");
logger.severe("server级别日志输出");
logger.warning("warning级别日志输出");
logger.info("info级别日志输出");
logger.config("config级别日志输出");
logger.fine("fine级别日志输出");
logger.finer("finer级别日志输出");
logger.finest("finest级别日志输出");
}
#此时默认的处理器有两个:向控制台输出,格式是SimpleFormatter、向日志文件中输出,格式是XMLFormatter
#RootLogger 顶级父元素指定的默认处理器:ConsoleHandler
#handlers= java.util.logging.ConsoleHandler
handlers= java.util.logging.FileHandler,java.util.logging.ConsoleHandler
#顶级父元素的默认日志级别:ALL
.level= ALL
#保存到日志文件中的设置
java.util.logging.FileHandler.pattern = F:/java%u.log
#指定日志文件大小为50000条
java.util.logging.FileHandler.limit = 50000
#指定Handler对象的日志级别
java.util.logging.FileHandler.level = ALL
#指定日志文件的数量
java.util.logging.FileHandler.count = 1
#指定Handler对象日志消息格式对象
#java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
#指定以追加的方式添加日志内容
java.util.logging.FileHandler.append = true
#向控制台输出Handler对象
#指定Handler对象的日志级别
java.util.logging.ConsoleHandler.level = ALL
#指定Handler对象的消息格式对象
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
#指定handler对象字符集
java.util.logging.ConsoleHandler.encoding = UTF-8
#指定消息格式
java.util.logging.SimpleFormatter.format = %4$s: %5$s [%1$tc]%n
com.xyz.foo.level = SEVERE
8.日志原理解析
- 初始化LogManager
- LogManager加载logging.properties配置
- 添加Logger到LogManager
- 从单例LogManager获取Logger
- 设置级别Level,并指定日志记录LogRecord
- Filter提供了日志级别之外更细粒度的控制
- Handler是用来处理日志输出位置
- Formatter是用来格式化LogRecord的