【JAVA】日志打印java.util.logging.*函数自定义格式,并且显示调用时行号

1、JAVA自带的这样:
代码如下:

import java.util.logging.*;
Logger logger = Logger.getLogger(MyLogger.class.toString());
logger.info("123");

显示效果:
在这里插入图片描述
这样的格式,看起来不太好看,比如:会默认添加一个换行,另外,想查看行号,会比较麻烦;随着开发代码量不断增加,因为一个函数代码量也比较大,如果知道行号,定位问题具体问题代码比较快,有点类似C语言的__LINE__宏,使用起来比较方便。

2、基于这个问题,我们需要自已实现可以显示行号的日志打印格式,通过网上查资料,知道要用到自定义日志格式设置:

        logger = Logger.getLogger(MyLogger.class.getName());logger.setUseParentHandlers(false);//如果需要将日志文件写到文件系统中,需要创建一个FileHandler对象Handler consoleHandler = new ConsoleHandler();//创建日志格式文件:本次采用自定义的FormatterconsoleHandler.setFormatter(new MyFormatter());//将FileHandler对象添加到Logger对象中logger.addHandler(consoleHandler);

在MyFormatter中实现对格式的自定义:

 @Overridepublic String format(LogRecord arg0){//创建StringBuilder对象来存放后续需要打印的日志内容StringBuilder builder = new StringBuilder();//获取时间SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");Date now = new Date();String dateStr = simpleDateFormat.format(now);builder.append("[");builder.append(dateStr);builder.append(" ");//拼接日志级别builder.append(arg0.getLevel()).append(" ");builder.append(arg0.getSourceClassName()).append(" ");//拼接方法名builder.append(arg0.getSourceMethodName()).append(" ");StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();String line = stackTrace[8].toString();String lineNumber = line.substring(line.indexOf(":") + 1, line.length() - 1);//System.out.println("stackTrace[0].toString(): " + stackTrace[0].toString());//拼接方法名builder.append(lineNumber).append("] ");//拼接日志内容builder.append(arg0.getMessage());//日志换行builder.append("\r\n");return builder.toString();}

这里边额外使用了获取当前线程的堆栈跟踪元素:Thread.currentThread().getStackTrace(),在程序执行过程中,可以把当前位置的调用栈打印出来;
如果在当前的文件,由于调用栈深度不深,代码如下:

        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();System.out.println(stackTrace.length);for (StackTraceElement s: stackTrace) {System.out.println(s.toString());}

这样打印出来是这样的:
在这里插入图片描述
3、在实际运行的代码涉及跨类的调用,代码:


/*** 可以自已定义日志打印格式,这样看起来比较方便些**/
class MyFormatter extends Formatter
{@Overridepublic String format(LogRecord arg0){//创建StringBuilder对象来存放后续需要打印的日志内容StringBuilder builder = new StringBuilder();//获取时间SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");Date now = new Date();String dateStr = simpleDateFormat.format(now);builder.append("[");builder.append(dateStr);builder.append(" ");//拼接日志级别builder.append(arg0.getLevel()).append(" ");builder.append(arg0.getSourceClassName()).append(" ");//拼接方法名builder.append(arg0.getSourceMethodName()).append(" ");StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();String line = stackTrace[8].toString();String lineNumber = line.substring(line.indexOf(":") + 1, line.length() - 1);//System.out.println("stackTrace[0].toString(): " + stackTrace[0].toString());StackTraceElement[] stackTrace2 = Thread.currentThread().getStackTrace();System.out.println(stackTrace2.length);for (StackTraceElement s: stackTrace2) {System.out.println(s.toString());}//拼接方法名builder.append(lineNumber).append("] ");//拼接日志内容builder.append(arg0.getMessage());//日志换行builder.append("\r\n");return builder.toString();}
}

这样看到的调用栈较深些:
在这里插入图片描述
这样在取我们自已代码的入口的时候,就需要从这上边往下边数,因为这里边代码是一个数组,从上图中打印也可看出来,前几个是日志打印的栈

StackTraceElement[] stackTrace2 = Thread.currentThread().getStackTrace();System.out.println(stackTrace2.length);for (StackTraceElement s: stackTrace2) {System.out.println(s.toString());}

在这里插入图片描述
从上图可以看出,我们代码在调用日志打印的时候,实际上使用的是stackTrace2数组里边第9个成员,由于我们需要取出行号,那么使用的是JAVA对字符串操作的搜索和截取操作,这样就可以达到目的:

        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();String line = stackTrace[8].toString();String lineNumber = line.substring(line.indexOf(":") + 1, line.length() - 1);

由于我们可以自定义打印日志的格式,那么我们整体按照自已的要求自定义后,代码是这样子的:

class MyFormatter extends Formatter
{@Overridepublic String format(LogRecord arg0){//创建StringBuilder对象来存放后续需要打印的日志内容StringBuilder builder = new StringBuilder();//获取时间SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");Date now = new Date();String dateStr = simpleDateFormat.format(now);builder.append("[");builder.append(dateStr);builder.append(" ");//拼接日志级别builder.append(arg0.getLevel()).append(" ");builder.append(arg0.getSourceClassName()).append(" ");//拼接方法名builder.append(arg0.getSourceMethodName()).append(" ");StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();String line = stackTrace[8].toString();String lineNumber = line.substring(line.indexOf(":") + 1, line.length() - 1);//拼接方法名builder.append(lineNumber).append("] ");//拼接日志内容builder.append(arg0.getMessage());//日志换行builder.append("\r\n");return builder.toString();}
}

最终的打印效果如下图所示:
在这里插入图片描述
自定义日志打印完成类代码如下:

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.*;/*** 可以自已定义日志打印格式,这样看起来比较方便些**/
class MyFormatter extends Formatter
{@Overridepublic String format(LogRecord arg0){//创建StringBuilder对象来存放后续需要打印的日志内容StringBuilder builder = new StringBuilder();//获取时间SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");Date now = new Date();String dateStr = simpleDateFormat.format(now);builder.append("[");builder.append(dateStr);builder.append(" ");//拼接日志级别builder.append(arg0.getLevel()).append(" ");builder.append(arg0.getSourceClassName()).append(" ");//拼接方法名builder.append(arg0.getSourceMethodName()).append(" ");StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();String line = stackTrace[8].toString();String lineNumber = line.substring(line.indexOf(":") + 1, line.length() - 1);//拼接方法名builder.append(lineNumber).append("] ");//拼接日志内容builder.append(arg0.getMessage());//日志换行builder.append("\r\n");return builder.toString();}
}public class MyLogger {static Logger logger;static  {logger = Logger.getLogger(MyLogger.class.getName());logger.setUseParentHandlers(false);//如果需要将日志文件写到文件系统中,需要创建一个FileHandler对象Handler consoleHandler = new ConsoleHandler();//创建日志格式文件:本次采用自定义的FormatterconsoleHandler.setFormatter(new MyFormatter());//将FileHandler对象添加到Logger对象中logger.addHandler(consoleHandler);}public static Logger getLogger() {return logger;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/164947.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java项目-网页聊天程序

目录 项目介绍 项目功能简介 项目创建 用户管理模块 1.数据库设计及代码实现 2.前后端交互接口的设计 3.服务器代码开发 好友管理模块 数据库设计 好友表设计的两个重要问题 设计前后端交互接口 服务器代码 会话管理模块 会话的数据库设计 获取会话信息 约定前后…

开启Linux之旅:用VMware安装CentOS7

最近我的阿里云服务器到期了,不想续费,所以就深入研究了一下虚拟机搭建Linux系统,感觉还不错,所以在这篇博客中分享一下。下面我将带领大家开启全新的Linux之旅,用VMware安装CentOS 7,具体操作步骤如下所示…

IDEA中SpringBoot项目的yml多环境配置

SpringBoot的yml多环境配置 创建多个配置文件 application.yml #主配置文件 application-dev.yml #开发环境的配置 application-test.yml #测试环境的配置在application.yml中添加多环境配置属性 spring:profiles:active: profiles.active项目启动可能不会识别&#x…

AbortController中止请求通信[模糊搜索案例]

AbortController中止请求通信[模糊搜索案例] AbortController中止请求通信(模糊搜索案例) AbortController中止请求通信(模糊搜索案例) 这里用模糊搜索来做示例,这里是调用后端模糊搜索接口 该案例的中止请求可以用于很多地方,比如取消上传/下载文件等 完…

SpringCloud链路追踪——Spring Cloud Sleuth 和 Zipkin 介绍 Windows 下使用初步

前言 在微服务中,随着服务越来越多,对调用链的分析越来越复杂。如何能够分析调用链,定位微服务中的调用瓶颈,并对其进行解决。 本篇博客介绍springCloud中用到的链路追踪的组件,Spring Cloud Sleuth和Zipkin&#xf…

Shopee买家通自养号系统可批量注册、自动下单

Shopee买家通自养号系统是一款专门针对虾皮买家号所开发的软件,目前支持菲律宾、印度尼西亚、泰国、巴西、马来西亚等国家使用,可批量注册、自动下单。 如果想拥有大量的买家号,那么可以使用批量注册账号功能,把账号所需要的资料准…

购药不烦恼:线上购药小程序的快捷方式

在这个数字化时代,线上购药小程序的快捷方式正在改变着我们购药的方式。本文将介绍如何通过使用Python和Flask框架创建一个简单的线上购药小程序的原型,为用户提供购药的便利和快捷体验。 安装和设置 首先,确保你已经安装了Python和Flask。…

《C语言图形界面-系统开发》专栏介绍 专栏目录

《C语言图形界面-系统开发》介绍及目录 基本介绍 本项目是一个基于EasyX图形库的C语言图书管理系统。 界面优美高级代码结构设计合理注释详尽清晰 本专栏是一个详尽到完全贴近C语言初学者的教程,完整代码 配套教程,完全不用担心学不会的问题。 项目展…

危险化工品出口注意事项及法规要求_箱讯科技

随着全球化工品市场的不断发展,危险化工品出口业务逐渐成为国际贸易的重要组成部分。然而,由于危险化工品具有潜在的危险性,出口过程中需严格遵守相关法规和注意事项,以确保运输安全和顺畅。本文将详细介绍危险化工品出口注意事项…

RabbitMQ入门到实战教程,MQ消息中间件,消息队列实战

消息队列是目前最常见的微服务中间件之一,而RabbitMq在全球范围内的使用率也是名列前茅。它以稳定性强、并发高、低时延的特点深受广大企业开发者的喜爱。然而市面上一致缺乏一个专门的RabbitMQ课程,所以这套课程应运而生。 微服务一旦拆分,必…

go-fastdfs安装(国产分布式文件系统)

开源协议: Unlicense官网地址: https://sjqzhang.github.io/go-fastdfs/#vision安装: wget --no-check-certificate https://github.com/sjqzhang/go-fastdfs/releases/download/v1.3.1/fileserver -O fileserver && chmod x fileserver &…

c++入门(命名空间, c++输入输出, 缺省参数)

文章目录 1. 命名空间正确的命名定义命名空间的使用 2. c输入与输出标准输入输出对象向流写入 读取数据 3. 缺省参数缺省参数分类缺省参数声明缺省参数初始值 c的简单介绍 C语言是结构化和模块化的语言,适合处理较小规模的程序。对于复杂的问题,规模较大…

【图解RabbitMQ-5】RabbitMQ Web管控台图文介绍

🧑‍💻作者名称:DaenCode 🎤作者简介:CSDN实力新星,后端开发两年经验,曾担任甲方技术代表,业余独自创办智源恩创网络科技工作室。会点点Java相关技术栈、帆软报表、低代码平台快速开…

02_diffusion_models_from_scratch_CN

从零开始的扩散模型 有时,只考虑一些事务最简单的情况会有助于更好地理解其工作原理。我们将在本笔记本中尝试这一点,从“玩具”扩散模型开始,看看不同的部分是如何工作的,然后再检查它们与更复杂的实现有何不同。 我们将学习 …

Linux篇 五、Ubuntu与Linux板卡建立NFS服务

Linux系列文章目录 一、香橙派Zero2设置开机连接wifi 二、香橙派Zero2获取Linux SDK源码 三、香橙派Zero2搭建Qt环境 四、Linux修改用户名 文章目录 Linux系列文章目录前言一、连接到局域网互ping测试 二、安装NFS服务配置NFS更新exports配置三、板卡安装NFS客户端四、板卡临时…

microcom串口调试工具使用

microcom串口助手使用介绍 microcom是一个在终端中使用的串口助手,类似平常使用SSCOM一样的东西,不过是在终端中使用而已。 使用的是busybox构建的文件系统 microcom源码路径:busybox/miscutils/microcom.c microcom 参数: [r…

伊朗相关的OilRig组织在为期8个月的网络攻击中针对中东政府

导语 伊朗相关的OilRig组织最近在中东政府中展开了一场长达8个月的网络攻击行动。这次攻击导致了文件和密码的被窃取,并且在其中一次攻击中,攻击者还使用了一种名为PowerExchange的PowerShell后门。据Symantec的威胁猎人团队称,他们在一份与T…

【软考】6.2 网络安全技术

《网络安全技术》 防火墙 一道大门,隔离内网和外网主要分隔外网的威胁,对内网的直接攻击无能为力 入侵检测系统(IDS) 位于防火墙后的第二道屏障监听设备:监控当前系统 / 用户行为,无需网络流量即可工作尽…

【分布式】入门级NCCL多机并行实践 - 02

# 背景知识 大模型和分布式训练对数据的吞吐量以及并行度都有很高的要求,NCCL就是在这个背景下诞生的。 如果你是一个只会写写Python,调用PyTorch和Horovod的算法萌新,可能对于分布式底层的东西不太了解,在下岗热潮中被主管逼着…

换低挡装置(Kickdown, ACM/ICPC NEERC 2006, UVa1588)rust解法

给出两个长度分别为n1,n2(n1,n2≤100)且每列高度只为1或2的长条。需要将它们放入一个高度为3的容器(如图3-8所示),问能够容纳它们的最短容器长度。 样例 2112112112 2212112 1012121212 2121…