Log4j-2-does-not-write-to-file.md

问题: 使用log4j2, 控制台可以正常输出日志,但是log4j2日志文件为空?

配置文件log4j2.xml配置如下:

<!-- log4j2.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>  
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </Console>
        <File name="MyTestLog" fileName="MyTestLog.txt" immediateFlush="false" append="true">
            <PatternLayout pattern="%d{yy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </File>
    </Appenders>
    <Loggers>
        <Logger name="org.apache.log4j.xml" level="debug">
            <AppenderRef ref="MyTestLog"/>
        </Logger>
        <Root level="error">
            <AppenderRef ref="Console" level="error"/>
        </Root>
    </Loggers>
</Configuration>

Java文件名为 Log4jDemo.java , 代码如下:

// Log4jDemo.java
import org.apache.logging.log4j.*;
public class Log4jDemo {
    static Logger logger = LogManager.getLogger(Log4jDemo.class.getName());
    public static void main(String[] args) {
        System.out.println("=> Hello Log4jDemo...");
        logger.trace("trace level");
        logger.debug("debug level");
        logger.info("info level");
        logger.warn("warn level");
        logger.error("error level");
        logger.fatal("fatal level");

网上搜了好多资料都没能看明白,只看看到这段文字:

It is not writing to your file because the Logger you are using to log is named log4j2Demo.LogDemo but the logger you have configured is named “a.demo.of.log4j2”.
Since the names don’t match it will use the root logger, which you have configured to log to the console.

解决办法1:

重新修改配置文件,将Loggers中Logger的name改成”Log4jDemo”, 与java类文件同名:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>  
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </Console>
        <File name="MyTestLog" fileName="MyTestLog.txt" immediateFlush="false" append="true">
            <PatternLayout pattern="%d{yy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </File>
    </Appenders>
    <Loggers>
        <Logger name="Log4jDemo" level="debug">
            <AppenderRef ref="MyTestLog"/>
        </Logger>
        <Root level="all">
            <AppenderRef ref="Console" level="error"/>
        </Root>
    </Loggers>
</Configuration>

解决办法2:

Loggers里Root下配置两个AppenderRef,一个指向Console,一个指向MyTestLog:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>  
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </Console>
        <File name="MyTestLog" fileName="MyTestLog.txt" immediateFlush="false" append="true">
            <PatternLayout pattern="%d{yy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </File>
    </Appenders>
    <Loggers>
        <Root level="all">
            <AppenderRef ref="Console" level="error"/>
            <AppenderRef ref="MyTestLog" level="info" />
        </Root>
    </Loggers>
</Configuration>

控制台输出:

=> Hello Log4jDemo...
18-01-24 15:57:09.547 [main] ERROR Log4jDemo - error level
18-01-24 15:57:09.547 [main] FATAL Log4jDemo - fatal level

查看日志文件,已经有内容了:

$ tail MyTestLog.txt
18-01-24 15:57:09.544 [main] INFO  Log4jDemo - info level
18-01-24 15:57:09.547 [main] WARN  Log4jDemo - warn level
18-01-24 15:57:09.547 [main] ERROR Log4jDemo - error level
18-01-24 15:57:09.547 [main] FATAL Log4jDemo - fatal level

注意到,控制台和日志文件中的内容并不一样,这是因为我们配置的日志级别不同,Console配置的是error, MyTestLog配置的是info

解决办法3: AsyncAppender with Console and File

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>  
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </Console>
        <File name="MyTestLog" fileName="MyTestLog.txt" immediateFlush="false" append="true">
            <PatternLayout pattern="%d{yy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </File>
        <Async name="ASYNC">
            <AppenderRef ref="MyTestLog"/>
            <AppenderRef ref="Console"/>
            </Async>
    </Appenders>
    <Loggers>
        <Root level="all">
            <AppenderRef ref="ASYNC"/>
        </Root>
    </Loggers>
</Configuration>

https://logging.apache.org/log4j/2.x/manual/migration.html
https://codedump.io/share/UwYEUh9AtRfg/1/log4j2-output-not-written-to-log-file
https://stackoverflow.com/questions/25118993/log4j-2-doesnt-write-to-file

[END]

Log4j-2-does-not-write-to-file.md问题: 使用log4j2, 控制台可以正常输出日志,但是log4j2日志文件为空?配置文件log4j2.xml配置如下: &amp;lt;!-- log4j2.xml --&amp;gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;&amp;lt;Configuration&amp;gt; ... package org.apache.logging.log4j; private static final Logger logger = LogManager.getLogger(); 附xml配置 <?xml version="1.0" encoding="UTF-8"?> <configuration status="warn"...
快速记录器 用于登录多个提供程序的Delphi(Delphi XE6-Delphi 10.4 Sydney)/ Freepascal(trunk)/。NET(Windows / Linux / Android / MACOSX / IOS)库: 休息服务器 Windows事件日志 Redis服务器 IDE调试 带有ADODB的MSSQL,MSAcces等。 系统日志 Logstash InfluxDB 灰色日志 受控和未处理的异常挂钩 2020年5月30日:支持RAD Studio 10.4 2020年5月2日: Twilio提供程序 2020年4月25日:自定义输出格式和自定义标签支持 2020年4月24日:哨兵提供者 2019年9月14日:包括新的可选日志信息:ThreadId。 2019年9月11日:现在包含在RAD Studio GetIt程序包管理器中。 2019年3月28日:未处理的异常钩 2019年3月28日:改进的异常信息 2019年3月16日: GrayLog提供程序 JS的发展史: 1、1992年 Nombas 开发了一款语言 ScriptEase 2、1995年 Netscape(网景) 开发了一款语言 LiveScript,更名为 Javascript 3、1996年 Microsoft(微软) 开发了一款语言 JScript 4、1997年 网景 将Javascript 1.1 提供给了ECMA(欧洲计算机制造商联合会),ECMA 获取了 JS 的核心,称之为 ECMA Script (ES) 完整的JS组成: 1、核心(ES) 2、文档对象模型(Document Object Model) - DOM 允许让 JS 与 HTML 文档打交道 3、浏览器对象模型(Browser Object Model) - BOM 允许让 JS 与 浏览器进行交互 JS是一款基于对象的编程语言 2、JS的基础语法 1、浏览器内核 内核负责页面内容的渲染,由以下两部分组成: 1、内容排版引擎 - 解析HTML/CSS 2、脚本解释引擎 - 解析Javascript 2、搭建JS运行环境(重点) 1、独立安装的JS解释器 - NodeJS console.log("Hello World"); console.log('Hello World'); 2、使用浏览器中的内核(JS解释引擎) 1、在浏览器的控制台(Console)中,输入脚本并执行 2、将JS脚本代码嵌入在HTML页面中执行 1、采用HTML元素事件执行JS代码 1、onclick 当元素被点击时执行的操作 ex: 当按钮被点击时,在控制台输出 Hello World 2、将JS脚本编写在 [removed][removed] 并嵌入在HTML文档的任何位置 [removed] console.log("... ..."); [removed]("Hello Wolrd"); [removed] 3、将JS脚本编写在外部独立的JS脚本文件中(***.js) 1、编写JS脚本文件 2、在HTML中引入脚本文件 [removed][removed] 1、先创建一个 base.js 的文件 2、在文件中执行以下代码 console.log(" .... ... "); [removed](" ... ... "); window.alert("这是在外部脚本文件中的内容"); 3、在 html 文档中,引入 base.js 文件 3、JS调试 当代码编写出现错误时,在运行的时候,在错误位置会停止 碰到错误代码,会终止当前语句块的执行,但不影响后续块的执行 [removed][removed] 为一块 4、JS语法 1、语句 - 可以被JS引擎执行的最小单元 由表达式、关键字、运算符 来组成的 严格区分大小写 :name 和 Name 所有的语句都是以 ; 来表示结束 所有的标点符号都是英文的 ; 和 ; . 和 。 : 和 : " 和 “ ' 和 ‘ () 和 () [] 和 【】 {} 和 {} 单行注释: // 多行注释: /* */ 3、变量 与 常量 1、什么是变量 用来存储数据的一个容器 2、声明变量(重点) 1、声明变量 var 变量名; 2、为变量赋值 变量名=值; 3、声明变量并赋初始值 var 变量名=值; 1、变量在声明时没有赋值的话,那么值为 undefined 2、声明变量允许不使用var关键字,但并不推荐 1、创建一个网页 04-variable.html 2、声明一对 [removed][removed],并完成以下变量的声明 1、声明一个变量用于保存用户的姓名,并赋值为 "张三丰"; 2、声明一个变量用于保存用户的年龄,赋值 68 3、如何 将变量的数据 打印在控制台上?? 4、一条语句中声明多个变量 var 变量名1=值,变量名2=值,变量名3; 3、变量名命名规范 1、由字母,数字,下划线以及 $ 组成 var user_name; 正确 var user-name; 错误 var $uname; 正确 2、不能以数字开头 var 1name;错误 3、不能使用JS中的关键字 和 保留关键字 4、变量名不能重复 5、可以采用"驼峰命名法",小驼峰命名法使用居多 6、最好见名知意 var a; var uname; 4、变量的使用 1、为变量赋值 - SET操作 只要变量出现在 赋值符号(=)的左边一律是赋值操作 var uname="张三丰"; uname="张无忌"; 2、获取变量的值 - GET操作 只要变量没有出现在赋值符号(=)的左边,一律是取值操作 var uname="wenhua.li";//赋值操作 console.log(uname); var new_name = uname; new_name 是赋值操作 uname 是取值操作 uname = uname + "bingbing.fan"; 赋值符号出现的话,永远都是将右边的值,赋值给左边的变量(从右向左运算) 1、什么是常量 在程序中,一旦声明好,就不允许被修改的数据 2、声明常量 const 常量名=值; 常量名在命名时采用全大写形式 1、声明一个变量 r ,来表示一个圆的半径,并赋值 2、声明一个常量PI ,来表示圆周率3.14 3、通过 r 和 PI 来计算 该圆的周长,保存在变量l中 周长 = 2 * π * 半径 4、通过 r 和 PI 来计算 该圆的面积,保存在变量s中 面积 = π * r * r; 5、在控制台中打印输出 半径为 * 的圆的周长是 * 半径为 * 的圆的面积是 * 1、定义一个函数 change ,该函数中接收两个参数(a,b) 2、在函数体中,如果 a 大于 b的话,则交换两个数字的位置,再打印输出结果 3、通过一个按钮调用函数,并且将 两个数字传递给函数 4、常用带参函数 parseInt(变量); parseFloat(变量); Number(变量) console.log(""); 3、带返回值的函数 var result = parseInt("35.5"); 1、什么是返回值 由函数体内 带到 函数体外的数据,叫做"返回值" function 函数名(参数列表){ return 值; 允许通过一个变量来接收调用函数后的返回值 var 变量名 = 函数名(实参列表); 定义一个可以接收三个Number参数的方法(名称为getMax),在该方法中,计算并返回 最大的数值 3、作用域 1、什么事作用域 指的是变量和函数的可访问范围,作用域分为以下两类 1、函数作用域 只在定义的函数内允许访问变量 和 函数 2、全局作用域 一经定义,在任何位置处都能访问 2、函数作用域中的变量 在某个函数中声明的变量,就是函数作用域中的变量,也可以称之为 "局部变量"。 function calSum(){ var a = 3; var b = 5; console.log(a,b); // 输出 3 5 console.log(a,b); //错误,因为 a ,b已经出了它的定义范围 1、定义一个 函数calSum,声明两个变量a,b,并赋值,并且在函数内打印两个变量 2、定义一个 函数calMax,直接打印输出 a,b,观察结果 3、全局作用域中的变量 一经声明了,任何位置都能使用。也称为 "全局变量" 声明方式: 1、将变量声明在最外层,所有的function之外 [removed] var a = 15; var b = 18; function showMsg(){ console.log(a); console.log(b); [removed] 2、声明变量时,不使用var关键字,一律是全局变量,但有风险 全局变量 ,尽量都声明在 所有的 function 之外 声明变量时,也一律都使用 var 关键字 4、声明提前 function show(){ console.log(num);//报错 1、什么是声明提前 JS程序在正式执行前,会将所有var声明的变量以及function声明的函数,预读到所在作用域的顶端。但赋值还保留在原位置上 最好将变量的声明 和 函数的声明都集中到所在作用域的最顶端 5、按值传递 function change(a,b){ a ^= b; b ^= a; a ^= b; console.log("在change函数中"); console.log(a,b); function testChange(){ var a = 15; var b = 18; console.log("调用前:"); console.log(a,b);//15 18 change(a,b); console.log("调用后:"); console.log(a,b);//15 18 1、什么是按值传递 基本数据类型的数字在做参数传递时,实际上时传递的实参的副本到函数中,原始数据并未发生过改变 基本数据类型的数据在做参数传递时,尽量不要在函数中修改,因为即便修改,也不会影响原数据的 6、局部函数 将函数 再声明在某个函数内,就是局部函数 [removed] function show(){ function inner(){ console.log("show 中的 inner 函数"); inner();//正确 inner(); // 错误,inner 是局部函数,只能在 show中被调用 [removed] 7、全局函数 ECMAScript预定义的全局函数,可供用户直接使用 1、paseInt(); 2、parseFloat(); 3、Number(); 4、isNaN(); 5、encodeURI() URL:Uniform Resource Locator :统一资源定位符/器 URI:Uniform Resource Identifier : 统一资源标识符 对统一资源标识符格式的字符串进行编码,并返回编码后的字符串 编码:将多字节的字符,编译成多个单字节的字符 6、decodeURI() 对已编码的URI进行解码(将已编码内容再转换回中文) 7、encodeURIComponent() 在 encodeURI 基础之上,允许将 特殊符号(:,/,...) 进行编码 8、decodeURIComponent() 9、eval() 作用:计算并执行以字符串方式表示的JS代码 var msg = "console.log('Hello World');"; eval(msg);//将 msg 作为 JS代码去执行 1、创建页面,通过弹框,输入一段JS代码 2、通过 eval() ,将输入的JS代码执行一次 3、递归调用 1、什么是递归 递归指的是在一个函数中,又一次的调用了自己 2、递归的实现 1、边界条件 2、递归前进 - 继续调自己 3、递归返回 - 向上返回数据 3、解决问题 1、计算某个数字的阶乘 5!=5*4*3*2*1 5! = 5 * 4! 4! = 4 * 3! 3! = 3 * 2! 2! = 2 * 1! 1! = 1 /*计算 n 的阶乘*/ function f(n){ ... ... 已知下列数列 (菲波那切数列) 1,1,2,3,5,8,13,21,34,55,... ... 已知 第一个数为1,第二个数为1 从第三个数开始,每个数字等于前两个数之和 问题:通过一个函数,求某个位置上的数字(用递归实现) 1、使用 continue ,打印输出 1-100之间所有偶数的和 2、让用户循环从弹框录入信息,并将信息打印在控制台上,直到用户输入 exit 为止 输入数据:sanfeng.zhang sanfeng.zhang 输入数据:wuji.zhang wuji.zhang 输入数据:exit 3、猜数字游戏 1、随机生成一个 1-100 之间的数字 Math.random() 返回 0-1 之间的小数 var r = parseInt(Math.random()*100)+1; 2、要求用户输入一个整数 若比生成的随机数大,则输出 “猜大了” 若比生成的随机数小,则输出 “猜小了” 直到用户 猜对为止 3、如果用户输入exit ,也可以退出游戏 用户从弹框中输入年,月,日,判断该日是星期几? 1900年1月1日 是星期1 推荐思路: 从1900年1月1日 到 输入的年月日 共有多少天求出来,与 7 取余 1、通过一个循环计算从1900年 到输入年前一年有多少天? 2、再从1月,到输入月份的前一个月共有多少天? 3、再累加 输入的日 4、用整体结果 与7取余,给出提示 附加作业: 将 输入的月份的日历打印输出 2017年8月 日 一 二 三 四 五 六 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 4、有一对兔子,从出生后的第3个月起都生一对兔子,小兔子长到第3个月后每个月又生一对兔子,假如兔子都不死的话,打印输出 前10个月,每个月有多少对兔子 n1 n2 n1 n2 n1 n2 1 , 1 , 2 , 3 , 5 , 8 , 13 , 21 , 34 , 55 2、三个表达式的特殊用法 1、for(;;) 三个表达式可以任意的省略,不推荐省略 2、for 第一个 和 第三个表达式的多样化 for(var i=1,j=2;i=1;i++,j--){ console.log(i+"+"+j+"="+(i+j)); 3、嵌套循环 在一个循环的内部又出现一个循环 for(var i=0;i<10;i++){ // 外层循环 for(var j=0;j<10;j++){ // 内层循环 外层循环执行一次,内层循环要执行一轮 1、控制台输出下面的图形 ****** ****** ****** ****** ****** ***** ***** ******* ********* 1、什么是数组 数组,即一组数据,使用一个变量来存放多个数据 数组中的元素是按照"线性"书序来排列的,所以也可以称之为是一个 "线性表" 2、声明数组 1、声明一个空数组变量 var 数组名 = []; 2、声明数组并赋初始值 var 数组名 = [数据1,数据2,数据3,... ...]; 3、声明一个空数组变量 var 数组名 = new Array(); 4、声明一个数组并赋初始值 var 数组名 = new Array(数据1,数据2,... ...); 1、创建一个函数,分别用两种不同的方式创建数组(arr1,arr2) arr1保存 :张三丰,张翠山,张无忌 arr2保存 :金花婆婆,殷素素,赵敏 2、直接将数组打印在控制台上 3、数组是引用类型的对象 引用类型的对象,是将数据保存在 "堆" 中的 在"栈"中,会对 "堆" 中数据的地址进行引用 1、将数组赋值给其它变量时,实际赋的是数组的地址 1、创建一个数组 arr1 ,包含"张无忌","赵敏" 2、将 arr1 赋值给 arr2 3、将 arr2 的第一个元素更改为 "金花婆婆",打印输出 arr1 和 arr2 中的所有元素 2、数组在做参数的时候,传递进去的实际上是地址(按引用传递 即 按地址传递) 1、创建一个数组array,保存"张无忌","赵敏"俩元素 2、创建一个函数change,接收一个数组作为参数,在函数体内,将第一个元素更改为"金花婆婆" 3、调用change函数,并将array数组作为参数,调用完成后,打印array的值,观察结果 4、修改change函数,在函数体内,将传递进来的数组重新new一个Array("孙悟空","猪八戒") 5、重复步骤三,观察结果 3、null 表示的是让引用类型的对象不再指向任何空间.一般用于主动释放对象的空间 //让 array 指向数组的地址 var array = ["wuji.zhang","zhaomin"]; //释放 array空间,不再指向任何地址 array = null; 4、访问数组的元素 赋值,取值,都是使用 下标 来完成的 1、为数组的元素赋值 数组名[下标] = 值; var array = ["张无忌","赵敏"]; array[1] = "周芷若"; array[2] = "小昭";//增加一个新元素,在第3个位置处 array[5] = "灭绝师太"; 2、获取数组中的值 数组名[下标]; 3、length属性 作用:获取数组的长度(数组中元素的个数) 1、允许将数组的length属性值设置为0,来完成数组元素的清空操作 2、配合循环 做数组的循环遍历操作 var array = ["张无忌","赵敏"]; 第1名 :张无忌 第2名 :赵敏 for(var i=0;i"sanfeng.zhang"]; 用字符串做下标,就是关联数组 var array = []; //声明一个空数组 array["西游记"] = "古代神话故事"; array["红楼梦"] = ["贾宝玉","林黛玉","刘姥姥"]; Q : array.length 1、关联数组是不算做数组内容的,不记录到 length 中 2、关联数组只能通过 字符串 做下标取值 3、允许通过 for...in 来循环遍历关联数组的字符串下标(也能遍历出内容的数字下标) 3、冒泡排序 [23,9,78,6,45] -> [6,9,23,45,78] 冒泡排序:车轮战,两两比较,小的靠前 1、轮数 :共比较了 length - 1 轮 2、每轮中比较的次数 :随着轮数的增加,次数反而减少 双层循环表示整个排序的过程 1、外层循环 :控制比较的轮数,从1开始,到length-1(能取到)结束 2、内层循环 :控制每轮中比较的次数,并且也要表示参与比较的元素的下标,从0开始,到 length-1-i(轮数变量) [23,9,78,6,45] 共5个元素 外层:从 1 开始,到 4 结束 第一轮 第一次:从 0 开始 ,到 3 结束 第二轮 第一次:从 0 开始 ,到 2 结束 ... ... 2、数组的常用方法 1、toString() 将一个数组转换为字符串 语法:var str = 数组对象.toString(); 2、join() 作用:将数组中的元素通过指定的分隔符连接到一起,并返回连接后的字符串 语法:var str = 数组对象.join("&"); 练习:(10分钟) 1、使用数组实现由 * 组成的三角形 直角三角形,等腰三角形 ***** 2、使用数组实现 九九乘法表 3、连接数组 函数:concat() 作用:拼接两个或更多的数组,并返回拼接后的结果 语法:var result=arr1.concat(arr2,arr3,arr4); 1、concat不会改变现有数组,而是返回拼接后的 2、每个参数不一定非是数组,也可以是普通的数据 1、声明两个全局数组,分别保存一些国家的名称 数组1:选中的国家 sel = ["中国","美国","俄罗斯","日本"]; 数组2:备选国家 unsel=["朝鲜","越南","老挝","柬埔寨"]; 2、将 备选国家 全部移入到 入选国家中,打印数据 sel = ["中国","美国","俄罗斯","日本","朝鲜","越南","老挝","柬埔寨"]; unsel=[]; 4、获取子数组 函数:slice() 作用:从指定数组中,截取几个连续的元素组成的新数组 语法:arr.slice(start,[end]); start:从哪个下标处开始截取,取值为正,从前向后取,取值为负,从后向前算位置。 0 1 2 3 var arr=["中国","美国","日本","英国"]; -4 -3 -2 -1 end : 指定结束处的下标(不包含),该参数可以省略,如果省略的话,就是从start一直截取到结束 1、该函数不会影响现有数组,会返回全新的数组 var arr=["中国","美国","日本","英国"]; 取出 美国 和 日本 组成的一个子数组 5、修改数组 函数:splice() 作用:允许从指定数组中,删除一部分元素,同时再添加另一部分元素 arr.splice(start,count,e1,e2,... ...); start:指定添加或删除元素的起始位置/下标 count:要删除的元素个数,取值为0表示不删除 e1,e2,... ... : 要增加的新元素,允许多个 返回值:返回一个由删除元素所组成的数组 注意:splice 会改变现有数组 在 sel 和 unsel 的基础上完成下列操作 1、从备选国家中(unsel),选择一个国家移入到 选中的国家(sel) 推荐步骤: 1、用户输入 :越南 从 unsel 中将越南移除 再将 越南 sel 的末尾处 2、用户输入 :墨西哥 提示:国家不存在 6、数组的反转 作用:颠倒数组中元素的顺序 语法:arr.reverse(); 注意:该函数会改变当前数组的内容 1、声明一个整数数组 2、倒序打印输出内容(使用reverse()) 7、数组排序 函数:sort(); 语法:arr.sort(排序函数); 作用:默认情况下,按照元素的Unicode码大小按升序排列 特殊:允许自己指定排序函数,从而实现对数字的升序和降序的排列 语法:arr.sort(排序函数); var arr = [12,6,4,72,115,89]; //排序函数(升序) function sortAsc(a,b){ return a-b; arr.sort(sortAsc); 1、指定排序函数 如 sortAsc,定义 两个参数,如 a 和 b。数组会自动传递数据到 sortAsc 里面去,如果返回值是>0的数,则交换两个数的位置,否则不变 使用匿名函数完成排序: arr.sort(function(a,b){return a-b;}); 1、声明一个整数数组,随意定义数字 2、页面上添加两个按钮,一个"升序"按钮,一个"降序"按钮 3、点击 升序 按钮时,数组按升序排序,并打印 4、点击 降序 按钮时,数组按降序排序,并打印 8、进出栈操作 JS是按照标准的"栈式操作"访问数组的 所有的"栈式操作"的特点都是"后进先出" "栈式操作"讲究的"入栈"和"出栈" 1、push() 入栈,在栈顶(数组的尾部)添加指定的元素,并返回新数组的长度 var arr = [10,20,30]; //向栈顶增加新数据 40 var len = arr.push(40); //len 保存的是 40 入栈后 arr 的长度,值是4 2、pop() 出栈,删除并返回栈顶的(数组尾部)元素 var arr = [10,20,30]; var r1 = arr.pop();//arr = [10,20] var r2 = arr.pop();//arr = [10] ============================== arr : r1 : 30 r2 : 20 3、shift() 删除数组头部的(第一个)元素并返回 var arr = [10,20,30]; var r1 = arr.shift(); ============================ arr : [20,30] r1 : 10 4、unshift() 作用:在数组的头部(第一个)元素位置处,增加新元素 var arr = [10,20,30]; arr.unshift(40); arr : [40,10,20,30] 3、二维数组 1、什么是二维数组 一个数组中的元素又是一个数组,也可以称之为:数组的数组 2、创建二维数组 var names=[ ["孙悟空","猪八戒","沙悟净"], ["潘金莲","西门庆","武大郎"], ["贾宝玉","刘姥姥","林黛玉"], ["貂蝉","貂蝉","貂蝉"] //获取猪八戒 console.log(names[0][1]); //获取林黛玉 console.log(names[2][2]); 1、通过 进出栈 操作,完成 十进制对二进制的转换 1、创建一个函数 decode2bin,接收一个十进制的数字做参数 2、函数体中,将参数 拆成二进制数字,保存在一个数组中 3、将数组的元素使用""连接,并返回 十进制 转 二进制 :除2取余法 num : 5 num % 2 : 结果为 1 num = parseInt(num / 2) : 结果 2 num % 2 : 结果为 0 num = parseInt(num / 2) : 结果 1 num % 2 : 结果为 1 num = parseInt(num / 2) : 结果 0 结果为 0 时则不用再继续 %2 2、根据省份信息,查询城市列表 1、创建一个全局数组,保存几个省份名称 2、创建一个全局二维数组,保存不同省份中的城市信息(数据要与省份数组中的数据对应的上) 3、创建一个函数,接收一个省份名称做参数,打印该省份中对应的所有的城市信息
文章目录1.slf4j使用依赖包2.与log4j集成3.在src目录中创建log4j.properties (如果是maven项目,在src/main/resources目录中创建log4j.properties) log4j.properties SLF4J的全称是Simple Logging Facade for Java,即简单日志门面。 SLF4J并不是具体的日志框架,而是作为一个简单门面...
1.日志文件里只输出了启动的日志,看log4j2.xml配置是没问题的,按道理是因为生效的。 2.控制台里的有对应的业务日志,info ,error都有。 3.最后打断点排查,发现logger实现的是logback包里的类,而不是我们需要的log4j2包。 最后在maven依赖图里,发现是我引入spring-boot-test-starter的时候,会自动引入logback,因为spr...
Log4j 2 同时输出日志控制台文件。方案给同一个 logger 绑定一个 console appender 和一个 file appender。即类似于这样的形式:rootLogger.appenderRef.stdout.ref = STDOUT rootLogger.appenderRef.file.ref = LOGFILE实例源码:https://github.com 3Log4j简单的配置文件 4编写demo 刚学习log4j2日志,对于里面的root和logger的继承关系比较迷惑,遂有此文使用控制台输出不同级别的日志,并定义日志的继承关系测试附上demo地址 示例项目使用maven作依赖管理github源码地址:https://github.com/fizzm
最近遇到一个问题,使用slf4j和log4j2日志框架时,需要将请求的id放入到打印日志中。因为MDC和ThreadContext是跟线程绑定的,所以遇到了子线程无法读取父线程MDC和ThreadContext的问题,网上搜了很多,有各种各样的答案,折腾了一天,总算搞定了,今天花点时间把答案总结梳理一下,希望大家能少走弯路。 问题现象:在父线程中使用了MDC.put("key","value")或者ThreadContext.put("key","value"),在子线程中使用MDC.get("key")
今天添加了一个日志文件,写在了logger.py中,主要是控制台输出日志日志文件中保存的内容。没有用类函数,也没有实例化对象,对,就是偷懒,简单的日志参数赋值,实现这两个点。 but,在我写完之后,脚本用例编好,执行时,出现了问题。1.直接执行logger模块,没问题,控制台输出info,文件生成了没内容。2.用例中执行,控制台输出文件生成。原因在于,没有调用。我给忽略了。 !注意,没有类对象的模块,在被其他模块执行时,一定不要忘记导入文件、导入模块。 from xx. xx import log
C编译报错: implicit declaration of function xxx is invalid in C99 [-Wimplicit-function-declaration] 39328 <version>0.1.0</version> <scope>system</scope> <systemPath>${pom.basedir}/libs/waltid-siwe-0.1.0.jar</systemPath> <exclusions> <!-- 解决日志覆盖的问题 --> <exclusion> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> </exclusion> <exclusion> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> </exclusion> </exclusions> </dependency> Go语言-使用Bcrypt实现加密或验证密码 红烧肉诱点甜: 启动Redis警告:WARNING overcommit_memory is set to 0 Background save may fail under low memory condition 蓝脖鸡泥~你干嘛: 没有这个文件sysctl.conf ,sysctl这个命令也用不了,怎么搞 C编译报错: implicit declaration of function xxx is invalid in C99 [-Wimplicit-function-declaration] clang89 99 11都不能编译安装python源代码 Angular报错问题:Can't bind to 'formGroup' since it isn't a known property of 'form' 解决问题no解决代码问题: 把这个也加进文章中吧