Jul全称java.util.Logging,它是java的原生日志框架,使用时不需要另外引用第三方的类库,相对其他的框架更小型灵活,主要使用在小型应用中
1. JUL的组件
JUL的重要组件:
1)Logger:记录器
应用程序通过获取Logger对象,记录其API来发布日志信息,它是访问日志系统的入口程序
2)Handler:处理器
每个Logger都会关联一个或一组Handler,Logger会将日志交给关联的Handler去处理,比如:实现日志记录后输出的位置,可以输出到控制台或文件中等等
2)Filter:过滤器
根据需要定制哪些信息会被记录,哪些信息需要被忽略
3)Formatter:格式化组件
它负责对日志的数据和信息进行格式化,它决定日志的最终输出形式
4)Level:日志级别
一组可用于控制日志输出的标准日志记录级别,每条消息都有关联的级别,根据我们输出级别的设置,用来展示最终所呈现的日志信息
JUL的其他组件:
- Logmanager:有一个全局LogManager对象用于维护关于日志记录器和日志服务的一组共享状态
Handler子组件:
- ConsoleHandler:将日志输出到控制台,类似于System.err
- FileHandler:将日志输出到文件
- SocketHandler:将日志网络传输记录
- StreamHandler:将日志基于流进行传输记录
Formatter子组件:
- SimpleFormatter:通用的格式化打印,可读性强
- XMLFormatter:xml格式打印
2. JUL入门案例
步骤:
- 定义日志的入口logger
- 输出日志
日志的两种输出方式:
- 直接调用日志级别相关的方法, 方法中传递日志输出信息
- 调用通用的log方法, 然后头歌Leven指定日志的级别, 传递输出信息
例:
public static void main(String[] args) { /* * 日志程序的入口 java.util.logging.Logger * */ //创建Logger对象,参数为当前类的全路径字符串 Logger log = Logger.getLogger("logtest.loggingTest"); //1.直接调用info日志输出方法 log.info("输出info日志"); //2.指定日志级别输出 log.log(Level.WARNING,"输出warning日志"); }
输出内容:
十一月 01, 2022 11:42:54 上午 logtest.loggingTest main 信息: 输出info日志 十一月 01, 2022 11:42:54 上午 logtest.loggingTest main 警告: 输出warning日志
3. Level日志级别
3.1 日志级别的说明
Level类定义了一组可用于控制日志输出的标准日志记录级别。 记录级别对象被排序并且由有序整数指定。 在给定级别启用日志记录还可以在所有更高级别进行日志记录
客户端应通常使用预定义的Level常量,如Level.SEVERE
日志的级别:
- SEVERE:错误 (最高级的日志级别)
- WARNING:警告
- INFO:消息 (默认级别)
- CONFIG:配置
- FINE:详细信息(少)
- FINER:详细信息(中)
- FINEST:详细信息(多),最低级的日志级别
两个特殊级别:
- OFF:可用来关闭日志记录
- ALL:启用所有消息的日志记录
每一个日志级别都绑定了一个数值:
- OFF:Integer.MAX_VALUE
- SEVERE:1000
- WARNING:900
- INFO:800
- CONFIG:700
- FINE:500
- FINER:400
- FINEST:300
- ALL:Integer.MIN_VALUE
数值的意义在于做判断依据,如果我们设置的日志级别是INFO -- 800那么最终展示的日志信息,必须是数值大于800的所有的日志信息
3.2 默认日志级别展示
演示:默认日志级别演示
public static void main(String[] args) { Logger log = Logger.getLogger("logtest.DefaultLogLevelPrint"); log.setLevel(Level.CONFIG); log.severe("输出错误信息!"); log.warning("输出警告信息!"); log.info("输出信息!"); log.config("输出配置信息!"); log.fine("输出fine信息!"); log.finer("输出finer信息!"); log.finest("输出finest信息!"); }
结果:
十一月 01, 2022 6:03:31 下午 logtest.DefaultLogLevelPrint main 严重: 输出错误信息! 十一月 01, 2022 6:03:31 下午 logtest.DefaultLogLevelPrint main 警告: 输出警告信息! 十一月 01, 2022 6:03:31 下午 logtest.DefaultLogLevelPrint main 信息: 输出信息!
仅仅只输出了Info和比Info级别高的日志信息,证明Info是默认的日志级别,比Info低的没有被输出。通过设置日志级别,打印信息也不会改变
日志级别的设置需要和Handler共同使用才能生效
3.3 自定义日志级别
自定义日志级别的步骤:
- 关闭默认日志打印
- 定义格式组件
- 定义处理器,并设置格式化组件
- 同时设置处理器和logger的日志级别
演示:
public static void main(String[] args) { //1. 定义日志入口 Logger log = Logger.getLogger("logtest.MyLogLevelPrint"); //2. 将默认的日志打印方式关闭 //参数设置为flase,日志打印方式就不会按照父Logger默认的方式进行 log.setUseParentHandlers(false); //3. 定义SimpleFormatter格式化组件 SimpleFormatter simpleformatter = new SimpleFormatter(); //4. 定义ConsoleHandle格式化处理器 ConsoleHandler consolehandler = new ConsoleHandler(); //5.为处理设置格式化组件 consolehandler.setFormatter(simpleformatter); //6. 为Logger设置处理器 log.addHandler(consolehandler); //7. 设置log和处理器的日志级别 consolehandler.setLevel(Level.CONFIG); log.setLevel(Level.CONFIG); log.severe("输出错误信息!"); log.warning("输出警告信息!"); log.info("输出信息!"); log.config("输出配置信息!"); log.fine("输出fine信息!"); log.finer("输出finer信息!"); log.finest("输出finest信息!"); }
结果:
十一月 01, 2022 7:20:15 下午 logtest.MyLogLevelPrint main 严重: 输出错误信息! 十一月 01, 2022 7:20:15 下午 logtest.MyLogLevelPrint main 警告: 输出警告信息! 十一月 01, 2022 7:20:15 下午 logtest.MyLogLevelPrint main 信息: 输出信息! 十一月 01, 2022 7:20:15 下午 logtest.MyLogLevelPrint main 配置: 输出配置信息!
4. Handler的使用
Handler有四种,但其中使用最多的是ConsoleHandler(日志控制台处理)和FileHandler(日志文件处理)
4.1 将日志输出到文件
日志输出到文件,使用FileHandler处理器
例:
public static void main(String[] args) throws SecurityException, IOException { Logger log =Logger.getLogger("logtest.FileHandlerLog"); log.setUseParentHandlers(false); //文件处理器 FileHandler handler = new FileHandler("D:\\filehandler.log"); //格式化输出 SimpleFormatter simpler = new SimpleFormatter(); handler.setFormatter(simpler); //log添加处理器 log.addHandler(handler); //设置日志级别 log.setLevel(Level.ALL); handler.setLevel(Level.ALL); log.severe("输出错误信息!"); log.warning("输出警告信息!"); log.info("输出信息!"); log.config("输出配置信息!"); log.fine("输出fine信息!"); log.finer("输出finer信息!"); log.finest("输出finest信息!"); }
结果:
4.2Logger添加多处理器
在使用FileHandler时,日志记录被输出到文件中,控制台就无法显示。但Logger可以添加多个处理器,同时输出到文件和控制台
例:Logger同时添加FileHandler和ConsoleHandler
public static void main(String[] args) throws SecurityException, IOException { Logger log =Logger.getLogger("logtest.FileHandlerLog"); log.setUseParentHandlers(false); //文件和控制台处理器 FileHandler handler = new FileHandler("D:\\filehandler.log"); ConsoleHandler console = new ConsoleHandler(); //格式化输出 SimpleFormatter simpler = new SimpleFormatter(); handler.setFormatter(simpler); console.setFormatter(simpler); //log添加处理器 log.addHandler(handler); log.addHandler(console); //设置日志级别 log.setLevel(Level.ALL); handler.setLevel(Level.ALL); console.setLevel(Level.ALL); log.severe("输出错误信息!"); log.warning("输出警告信息!"); log.info("输出信息!"); log.config("输出配置信息!"); log.fine("输出fine信息!"); log.finer("输出finer信息!"); log.finest("输出finest信息!"); }
控制台输出:
十一月 01, 2022 9:36:23 下午 logtest.FileHandlerLog main 严重: 输出错误信息! 十一月 01, 2022 9:36:23 下午 logtest.FileHandlerLog main 警告: 输出警告信息! 十一月 01, 2022 9:36:23 下午 logtest.FileHandlerLog main 信息: 输出信息! 十一月 01, 2022 9:36:23 下午 logtest.FileHandlerLog main 配置: 输出配置信息! 十一月 01, 2022 9:36:23 下午 logtest.FileHandlerLog main 详细: 输出fine信息! 十一月 01, 2022 9:36:23 下午 logtest.FileHandlerLog main 较详细: 输出finer信息! 十一月 01, 2022 9:36:23 下午 logtest.FileHandlerLog main 非常详细: 输出finest信息!
5. Logger的父子关系
在底层存储中Logger是树结构存储,所以Logger存在"父子"关系,每个Logger节点都有自己的父节点和子节点
1)默认节点关系是按包路径来划分的,同样的包,路径越短的节点就为父节点,其他的为子节点
Logger log1 = Logger.getLogger("logtest"); Logger log2 = Logger.getLogger("logtest.ParentsonLogin"); System.out.print(log2.getParent() == log1);
Logger log1 = Logger.getLogger("logtest"); Logger log2 = Logger.getLogger("logtest.ParentsonLogin"); System.out.println("Log1的父类信息:"+log1.getParent()+"\t"+log1.getParent().getName()); System.out.print("Log2的父类信息:"+log2.getParent()+"\t"+log2.getParent().getName());
输出:
Log1的父类信息:java.util.logging.LogManager$RootLogger@33909752 Log2的父类信息:java.util.logging.Logger@55f96302 logtest
3)父子关系的作用
Logger log1 = Logger.getLogger("logtest"); Logger log2 = Logger.getLogger("logtest.ParentsonLogin"); log1.setUseParentHandlers(false); //log1设置handler和formatter ConsoleHandler consol = new ConsoleHandler(); consol.setFormatter(new SimpleFormatter()); //设置log1和的日志级别 log1.setLevel(Level.ALL); consol.setLevel(Level.ALL); log1.addHandler(consol); //对log2子节点进行日志输出 log2.severe("输出错误信息!"); log2.warning("输出警告信息!"); log2.info("输出信息!"); log2.config("输出配置信息!"); log2.fine("输出fine信息!"); log2.finer("输出finer信息!"); log2.finest("输出finest信息!");
父节点所设置的内容(如handler处理器/格式化组件/日志等级)都可以被子节点继承
输出:
十一月 02, 2022 11:22:59 上午 logtest.ParentsonLogin main 严重: 输出错误信息! 十一月 02, 2022 11:22:59 上午 logtest.ParentsonLogin main 警告: 输出警告信息! 十一月 02, 2022 11:22:59 上午 logtest.ParentsonLogin main 信息: 输出信息! 十一月 02, 2022 11:22:59 上午 logtest.ParentsonLogin main 配置: 输出配置信息! 十一月 02, 2022 11:22:59 上午 logtest.ParentsonLogin main 详细: 输出fine信息! 十一月 02, 2022 11:22:59 上午 logtest.ParentsonLogin main 较详细: 输出finer信息! 十一月 02, 2022 11:22:59 上午 logtest.ParentsonLogin main 非常详细: 输出finest信息!
log2对象继承了Log1的日志配置信息
6. 配置文件解析
java默认日志配置文件位置:JDK\JDK1.8\jre\lib\logging.properties
#RootLogger的日志级别 #默认情况下,这是全局的日志级别,如果不手动配置其他的日志级别,则默认输出下述配置的级别以及更高的级别 .level= INFO #默认的处理器 handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler #文件处理器属性配置 #输出日志文件的路径和文件名 java.util.logging.FileHandler.pattern = %h/java%u.log #输出日志文件的限制(50000字节) java.util.logging.FileHandler.limit = 50000 #设置日志文件的数量 java.util.logging.FileHandler.count = 1 #输出日志的格式 #默认是以XML的方式进行输出 java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter #控制台处理器属性设置 java.util.logging.ConsoleHandler.level = INFO #设置控制台处理器的格式化 java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter #将日志级别设置到具体的某个包下 #com.xyz.foo.level = SEVERE
例:读取自定义的配置文件
① 配置文件(testlog.properties)
.level= INFO handlers= java.util.logging.FileHandler java.util.logging.FileHandler.pattern = %h/java%u.log java.util.logging.FileHandler.limit = 50000 java.util.logging.FileHandler.count = 1 java.util.logging.FileHandler.Level= CONFIG java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter #追加文件(默认是覆盖) java.util.logging.FileHandler.append = true
② 读取自定义配置文件
//创建配置文件流 InputStream input = new FileInputStream("D:\\testlog.properties"); //取地日志管理器对象 LogManager logManager = LogManager.getLogManager(); //管理器读取配置文件 logManager.readConfiguration(input); //日志入口 Logger log = Logger.getLogger("logtest.MyReadLogProperties"); log.setUseParentHandlers(false); log.severe("输出错误信息!"); log.warning("输出警告信息!"); log.info("输出信息!"); log.config("输出配置信息!");
7. 其他
7.1 日志信息动态传递数据
创建数据类:
public class logbean { String logmessage; int logLeval; public logbean() { } public logbean(String logmessage, int logLeval) { super(); this.logmessage = logmessage; this.logLeval = logLeval; } public String getLogmessage() { return logmessage; } public void setLogmessage(String logmessage) { this.logmessage = logmessage; } public int getLogLeval() { return logLeval; } public void setLogLeval(int logLeval) { this.logLeval = logLeval; } }
传递动态数据的两种方式:
- 传统的字符串拼接
- log提供的动态数据传递
① 字符串拼接
public static void main(String[] args) { logbean logmes = new logbean("字符串拼接", 1); Logger log = Logger.getLogger("logtest.logdynamicstatePrint"); log.log(Level.INFO, "消息:"+logmes.getLogmessage()+"\t"+"级别"+logmes.getLogLeval()); }
输出:
十一月 01, 2022 5:20:08 下午 logtest.logdynamicstatePrint main 信息: 消息:字符串拼接 级别1
拼接弊端:
- 程序效率低
- 可读性不高
- 维护成本高
② 动态传递数据
public static void main(String[] args) { logbean logmes = new logbean("字符串拼接", 1); Logger log = Logger.getLogger("logtest.logdynamicstatePrint"); log.log(Level.INFO,"消息:{0} 级别:{1}",new Object[]{logmes.getLogmessage(),logmes.getLogLeval()}); }
- {}:占位符
- 通过数组中的元素进行占位
输出:
十一月 01, 2022 5:23:57 下午 logtest.logdynamicstatePrint main 信息: 消息:字符串拼接 级别1
JUL的操作流程总结:
- 初始化LogManager,LogManager加载Logging.properies配置文件
- 从单例的LogManager获取Logger
- 设置日志级别Level,在打印的过程中使用到日志记录的LogRecord类
- Filter作为过滤器提供了日志级别之外细粒度的控制
- Handler日志处理器,决定日志的输出位置或者控制台等等
- Formatter用来格式化输出
Comments | NOTHING
Warning: Undefined variable $return_smiles in /www/wwwroot/wql_luoqin_ltd/wp-content/themes/Sakura/functions.php on line 1109