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. Laravel 6.X + Vue.js 2.X + Element UI +vue-router 配置

    Laravel 版本:6.X Vue 版本:2.X Laravel配置: Laravel使用的是Laragon安装 选择Laravel:接下来弹出框,输入项目名,laravel会自动创建一个数据库,数 ...

  2. vue-element-admin 引入高德地图并做海量点标记

    第一步: 首先在index.html入口文件中添加引入高德地图的js,并填写自己在官网申请的key.如果没有申请不填写也是可以的. plugin:项目中如果有需要引入插件则使用没有直接去掉就行. &l ...

  3. Codeforces Round #579 (Div. 3)D(字符串,思维)

    #include<bits/stdc++.h>using namespace std;char s[200007],t[200007];int last[200007][27],nxt[2 ...

  4. Android编程实现点击链接打开APP功能示例

    本文实例讲述了Android编程实现点击链接打开APP功能.分享给大家供大家参考,具体如下: 在Android中点击链接打开APP是一个很常见的需求.例如,电商为用户发送优惠券之后经常会下发一条短信: ...

  5. Java Reflection (JAVA反射) --转载

    对于软件开发人员来说,单元测试是一项必不可少的工作.它既可以验证程序的有效性,又可以在程序出现 BUG 的时候,帮助开发人员快速的定位问题所在.但是,在写单元测试的过程中,开发人员经常要访问类的一些非 ...

  6. 「Luogu P3680 凸轮廓线」

    一道神奇的计算几何题 前置芝士 正三角形,正方形,圆:什么,您都会,那真是太好了. 三角函数的运用:因为我不是很想在这一块写太多,具体可以自行百度. 推导公式 对于一串是圆和正方形开头和结尾时是十分好 ...

  7. MongoDB基础篇2:数据库/用户/数据集合的增删改

    一.数据库操作 创建并进入数据库: 命令:use DATABASE_NAME 示例:use tms   查看所有数据库: 命令:show dbs   注意: (1)新创建的数据库在show dbs命令 ...

  8. PHP中的异常知识

    一.绪 首先明确一点:异常和错误不是一回事. 一个异常(Exception)是一个程序执行过程中出现的一个例外或是一个事件,它中断了正常指令的运行,跳转到其他程序模块继续执行. 基本格式: try { ...

  9. 基于IntelliJ IDEA的代码评审插件 Code Review Plugin

    一.阿里规范公约 1.左上角 File -> Settings -> Plugins -> 搜索:Alibaba Java Coding Guidelines,安装插件并重启IDEA ...

  10. 如何解决ajax跨域请求?

    1.什么是跨域? a.域名不同 b.域名相同,端口不同 注:只有域名相同,端口相同时,才可以访问数据 可以使用jsonp解决ajax跨域请求的问题. 2.什么是jsonp? Jsonp其实就是一个跨域 ...