Web基础之日志

  日志在企业开发中有着不可或缺的作用,它可以用以记录用户操作、系统运行状态和错误信息。日志记录的好坏直接关系到系统出现问题时定位的速度。

  最开始的日志一般使用log4j,后来sun公司心有不甘,在jdk 1.4中加入了一个叫java.util.logging的日志包,简称jul。两种日志的api肯定是不同的,此时日志就出现了混乱。log4j的作者Ceki Gülcü就写了一个叫Jakarta Commons Logging的接口,简称jcl,来共同管理log4j和jul,并且jcl中提供了一个日志实现simplelog。接着又改良了下log4j,写出了logback。再后来Ceki Gülcü觉得jcl不好用(的确用问题),然后写了一个新的接口slf4j,来共同管理这些日志系统。接着呢Ceki Gülcü又觉得logj4性能不够了,又写了一个log4j2,。真是专注日志100年啊。

  所以他们之间的关系是这样的:

  其中slf4j并不提供日志实现,而是使用外观模式创建了一个接口,来统一这些日志的api。

  这也是为什么阿里规范上强制使用slf4j的原因:

【强制】应用中不可直接使用日志系统(Log4j、Logback)中的 API,而应依赖使用日志框架SLF4J 中的 API,使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

private static final Logger logger = LoggerFactory.getLogger(Test.class);

slf4j + log4j / log4j2

  认识了之后接下来就是使用了,首先在maven中导入依赖:

<!-- log4j依赖,好像不更新了,我看版本还是12年的 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- slf4j的依赖 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.28</version>
</dependency>
<!-- 告诉slf4j使用log4j,也就是绑定 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.28</version>
<scope>test</scope>
</dependency>

  如果使用log4j2的话这么配:

<!-- log4j2的核心 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.12.1</version>
</dependency>
<!-- log4j2的api -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.12.1</version>
</dependency>
<!-- slf4j绑定log4j2 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.12.1</version>
</dependency>
<!-- slf4j的依赖 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.28</version>
</dependency>

  这里我将使用log4j2的xml和properties两种方式来简单配置。


  在resources目录下创建log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<!-- 输出源的配置:日志输出的目的地 -->
<Appenders>
<!--
Console标签;指定这是一个控制台输出源。
name:名称,需要在被引用才会生效
target: 控制台字体的颜色
SYSTEM_ERR:红色字体
SYSTEM_OUT:黑色字体
PatternLayout:布局,输出到控制台日志的格式。
-->
<Console name="myConsole" target="SYSTEM_ERR">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %5level %logger{36} - %msg%n"/>
</Console> <!-- 文件输出源
fileName:指定保存日志的文件的名字和位置。
一般写绝对路径。
-->
<File name="myFile" fileName="D://demo.log">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
</File> <!--
多文件输出源:
fileName:实时记录日志的文件名和位置
filePattern : 文件封存的位置和格式
-->
<RollingFile name="rollingFile" fileName="D://demo2.log" filePattern="D://logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
<!-- 多文件拆分的规则 -->
<Policies>
<!-- 基于时间的 此处interval属性值的单位是由filePattern属性中文件名时间精确的单位 决定的。 -->
<TimeBasedTriggeringPolicy interval="1" />
<!-- 基于文件大小的 -->
<SizeBasedTriggeringPolicy size="512 MB"/>
</Policies>
</RollingFile> </Appenders>
<Loggers>
<!-- 配置日志输出的级别的
将当前级别以及比当前级别高的消息进行输出。
-->
<Root level="trace">
<AppenderRef ref="myConsole"/>
<!-- 可以同时多种方式输出日志 -->
<AppenderRef ref="MyFile"/>
<AppenderRef ref="RollingFile"/> </Root>
</Loggers>
</Configuration>

  log4j使用properties方式:

# 配置输出源的   log4j.appender.输出源名=输出源的实现类
# 属性的配置 log4j.appender.输出源名.属性名=属性值
log4j.appender.a=org.apache.log4j.ConsoleAppender
log4j.appender.a.Target=System.out
log4j.appender.a.layout=org.apache.log4j.PatternLayout
log4j.appender.a.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=D:/mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n ### log4j.rootLogger=输出级别,输出源1,输出源2....
log4j.rootLogger=debug,a,file

log4j2的properties(参考):

status = warn
name = MyApp appender.console.type = Console
appender.console.name = consoleLogDemo
appender.console.filter.threshold.type = ThresholdFilter
appender.console.filter.threshold.level = debug
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = %m%n
appender.console.target = System_out appender.rolling.type = File
appender.rolling.name = fileLogDemo
appender.rolling.filter.threshold.type = ThresholdFilter
appender.rolling.filter.threshold.level = error
appender.rolling.layout.type = PatternLayout
appender.rolling.layout.pattern = %d-%m%n
appender.rolling.append = true
appender.rolling.fileName = e:\\propertiesTest.log rootLogger.level = debug
rootLogger.appenderRef.consolelogdemo.ref = consoleLogDemo
rootLogger.appenderRef.filelogdemo.ref = fileLogDemo

输出格式参数为:

%p:输出日志信息的优先级,即DEBUG,INFO,WARN,ERROR,FATAL
%d:输出日志时间点的日期或时间,默认格式为ISO8601,可以指定格式如:%d{yyyy/MM/dd HH:mm:ss,SSS}
%r:输出自应用程序启动到输出该log信息耗费的毫秒数
%t:输出产生该日志事件的线程名
%l:输出日志事件的发生位置,相当于%c.%M(%F:%L)的组合,包括类全名、方法、文件名以及在代码中的行数
%c:输出日志信息所属的类目,通常就是类全名
%M:输出产生日志信息的方法名
%F:输出日志消息产生时所在的文件名
%L:输出代码中的行号
%m:输出代码中指定的具体日志信息
%n:输出一个回车换行符,Windows平台为"rn",Unix平台为"n"
%x:输出和当前线程相关联的NDC(嵌套诊断环境)
%%:输出一个"%"字符

  这是几种常用的配置,如果觉得不够的话可以查看官方文档

  顺便这里推荐个讲的很详细的博客

打日志

在log4j2中可以这么用:

public class MyApp {
private static final Logger logger = LoggerFactory.getLogger(MyApp.class); public static void main(String[] args) {
logger.warn("Hello, {}","slf4j");
}
}

使用{}作为占位符,性能要比log4j直接字符串拼接性能好(毕竟字符串拼接的底层原理是创建StringBuilder)


至于一大堆jar包的关系如下:



关于log4j2的如下:

参考关于slf4j log4j log4j2的jar包配合使用的那些事

Web基础之日志的更多相关文章

  1. 20145215《网络对抗》Exp8 Web基础

    20145215<网络对抗>Exp8 Web基础 基础问题回答 什么是表单? 表单是一个包含表单元素的区域,表单元素是允许用户在表单中(比如:文本域.下拉列表.单选框.复选框等等)输入信息 ...

  2. 20155201 网络攻防技术 实验八 Web基础

    20155201 网络攻防技术 实验八 Web基础 一.实践内容 Web前端HTML,能正常安装.启停Apache.理解HTML,理解表单,理解GET与POST方法,编写一个含有表单的HTML. We ...

  3. 20155202《网络对抗》Exp8 Web基础

    20155202<网络对抗>Exp8 Web基础 基础问题回答 什么是表单? 表单是一个包含表单元素的区域,表单元素是允许用户在表单中(比如:文本域.下拉列表.单选框.复选框等等)输入信息 ...

  4. 2017-2018 Exp8 Web基础 20155214

    目录 Exp8 Web基础 实验内容 建站过程 SQL注入 知识点 Exp8 Web基础 实验内容 实验环境 主机 Kali 靶机 Kali 实验工具 后台语言 'PHP' 服务器 'Apache' ...

  5. 20155318 《网络攻防》 Exp9 Web基础

    20155318 <网络攻防> Exp9 Web基础 基础问题 SQL注入攻击原理,如何防御 就是通过把SQL命令插入到"Web表单递交"或"输入域名&quo ...

  6. 20145220韩旭飞《网络对抗》Exp8 Web基础

    20145220韩旭飞<网络对抗>Exp8 Web基础 Web前端:HTML基础 首先,我们的Web开发是基于Apache服务器进行的,所以对于Apache的基本操作我们是应该要掌握的,对 ...

  7. Nginx web基础入门

    目录 Nginx web基础入门 如何升级nginx或者添加功能 使用systemd管理nginx nginx相关配置文件 nginx的配置文件详解 日志格式 game日志记录实战 日志切割 手写虚拟 ...

  8. 2018-2019-2 《网络对抗技术》Exp8 Web基础 20165326

    Web基础 实验要求 本实践的要求: Web前端HTML,能正常安装.启停Apache.理解HTML,理解表单,理解GET与POST方法,编写一个含有表单的HTML. Web前端javascipt.理 ...

  9. Web基础之http协议

    第6章 Web基础之http协议 第6章 Web基础之http协议一.http协议介绍 1.1)什么是超文本 1.2)什么是URL 1.3)什么是超文本传输协议二.访问网站分析三.页面请求信息解析(仅 ...

随机推荐

  1. 利用Session实现三天免登陆

    什么是Session Session:在计算机中,尤其是在网络应用中,称为“会话控制”.(百度百科) Session:服务器端的数据存储技术. Session要解决什么问题 一个用户的不同请求(重定位 ...

  2. [Linux] day07——查看及过滤文本

    查看及过滤文本 =====================================cat      concatenate         -n 添加行号------------------- ...

  3. 《React后台管理系统实战 :四》产品分类管理页:添加产品分类、修改(更新)产品分类

    一.静态页面 目录结构 F:\Test\react-demo\admin-client\src\pages\admin\category add-cate-form.jsx index.jsx ind ...

  4. js正则 - 限制用户名只能中文、字母和数字 , 不能包含特殊字符

    /^[\u4E00-\u9FA5A-Za-z0-9]+$/   

  5. 「CF161B」Discounts

    传送门 Luogu 解题思路 贪心地想一想,我们肯定要让凳子去给价格越高的商品打半价,那么我们就先按照价格排序,但是要优先把凳子排在前面. 然后我们发现一条凳子肯定只能给价格小于等于它本身的物品打半价 ...

  6. 071、Java面向对象之使用private封装属性

    01.代码如下: package TIANPAN; class Book { // 定义一个新的类 private String title; // 书的名字 private double price ...

  7. 5.7 Nginx 其他模块

  8. php 投票系统

    1.投票主界面(问题界面) <?php$db = new Mysqli("localhost","root","root"," ...

  9. 神奇的URL Schemes大全

    微信: 打开微信 wechat:// 微信扫一扫 weixin://scanqrcode 支付宝: 蚂蚁庄园 alipays://platformapi/startapp?appId=66666674 ...

  10. 吴裕雄--天生自然JAVAIO操作学习笔记:RandomAccessFile

    import java.io.File ; import java.io.RandomAccessFile ; public class RandomAccessFileDemo01{ // 所有的异 ...