来源:http://i7q.cn/54K3Uw

1.日志框架

日志接口(slf4j)

slf4j是对所有日志框架制定的一种规范、标准、接口,并不是一个框架的具体的实现,因为接口并不能独立使用,需要和具体的日志框架实现配合使用(如log4j、logback)

日志实现(log4j、logback、log4j2)

  • log4j是apache实现的一个开源日志组件

  • logback同样是由log4j的作者设计完成的,拥有更好的特性,用来取代log4j的一个日志框架,是slf4j的原生实现

  • log4j2是log4j 1.x和logback的改进版,据说采用了一些新技术(无锁异步、等等),使得日志的吞吐量、性能比log4j 1.x提高10倍,并解决了一些死锁的bug,而且配置更加简单灵活。

2.为什么需要日志接口,直接使用具体的实现不就行了吗?

接口用于定制规范,可以有多个实现,使用时是面向接口的(导入的包都是slf4j的包而不是具体某个日志框架中的包),即直接和接口交互,不直接使用实现,所以可以任意的更换实现而不用更改代码中的日志相关代码。

比如:slf4j定义了一套日志接口,项目中使用的日志框架是logback,开发中调用的所有接口都是slf4j的,不直接使用logback,调用是 自己的工程调用slf4j的接口,slf4j的接口去调用logback的实现,可以看到整个过程应用程序并没有直接使用logback,当项目需要更换更加优秀的日志框架时(如log4j2)只需要引入Log4j2的jar和Log4j2对应的配置文件即可,完全不用更改Java代码中的日志相关的代码logger.info(“xxx”),也不用修改日志相关的类的导入的包(import org.slf4j.Logger; import org.slf4j.LoggerFactory;)

使用日志接口便于更换为其他日志框架

log4j、logback、log4j2都是一种日志具体实现框架,所以既可以单独使用也可以结合slf4j一起搭配使用。

本文使用Log4j2作为slf4j的具体实现,引入的包如下:

<dependency>    <groupId>org.slf4jgroupId>    <artifactId>slf4j-apiartifactId>    <version>1.7.25version>dependency><dependency>    <groupId>org.apache.logging.log4jgroupId>    <artifactId>log4j-slf4j-implartifactId>    <version>2.11.0version>dependency><dependency>    <groupId>org.apache.logging.log4jgroupId>    <artifactId>log4j-coreartifactId>    <version>2.11.0version>dependency><dependency>    <groupId>org.apache.logging.log4jgroupId>    <artifactId>log4j-apiartifactId>    <version>2.11.0version>dependency>

3.log4j2日志级别

从大到小依次是: off, fatal, error, warn, info, debug, trace, all

由于我们使用的是slf4j接口包,该接口包中只提供了未标有删除线的日志级别的输出。

4.log4j2配置文件的优先级

  • Log4j will inspect the log4j.configurationFile system property and, if set, will attempt to load the configuration using the ConfigurationFactory that matches the file extension.

  • If no system property is set the properties ConfigurationFactory will look for log4j2-test.properties in the classpath.

  • If no such file is found the YAML ConfigurationFactory will look for log4j2-test.yaml or log4j2-test.yml in the classpath.

  • If no such file is found the JSON ConfigurationFactory will look for log4j2-test.json or log4j2-test.jsn in the classpath.

  • If no such file is found the XML ConfigurationFactory will look for log4j2-test.xml in the classpath.

  • If a test file cannot be located the properties ConfigurationFactory will look for log4j2.properties on the classpath.

  • If a properties file cannot be located the YAML ConfigurationFactory will look for log4j2.yaml or log4j2.yml on the classpath.

  • If a YAML file cannot be located the JSON ConfigurationFactory will look for log4j2.json or log4j2.jsn on the classpath.

  • If a JSON file cannot be located the XML ConfigurationFactory will try to locate log4j2.xml on the classpath.

  • If no configuration file could be located the DefaultConfiguration will be used. This will cause logging output to go to the console.

5.对于log4j2配置文件的理解

配置文件结构:

  1. Appdenders部分

    1. Appender

      1. Filter

      2. Layout

      3. Policies

      4. Strategy

      5. Appender

  2. Loggers部分

    1. Logger

    2. RootLogger

6.对于Appender的理解

简单说Appender就是一个管道,定义了日志内容的去向(保存位置)。

配置一个或者多个Filter,Filter的过滤机制和Servlet的Filter有些差别,下文会进行说明。

  • 配置Layout来控制日志信息的输出格式。

  • 配置Policies以控制日志何时(When)进行滚动。

  • 配置Strategy以控制日志如何(How)进行滚动。

7.对于Logger的理解

简单说Logger就是一个路由器,指定类、包中的日志信息流向哪个管道,以及控制他们的流量(日志级别)

8.log4j2配置文件框架

配置文件格式

<?xml  version="1.0" encoding="UTF-8"?>

<Configuration>

    <Appenders>

        <Appender>            <Filters>                <LevelRangeFilter minLevel="..." maxLevel="..." onMatch="..." onMismatch="..."/>            Filters>

            <PatternLayout pattern="..." charset="..."/>

            <Policies>                <CronTriggeringPolicy schedule="..."/>                <SizeBasedTriggeringPolicy size="..."/>                <TimeBasedTriggeringPolicy />            Policies>        Appender>

        <Appender>            // ...        Appender>

    Appenders>

    <Loggers>

        <Logger>            <AppenderRef ref="...">        Logger>

        <Root>            <AppenderRef ref="...">        Root>

    Loggers>

Configuration>

9.Appender标签的实现类

其实这些标签都是类名或者类名去掉后缀。

Appender的常用的实现类有:

  • ConsoleAppender(Console)

  • FileAppender(File)、RandomAccessFileAppender(RandomAccessFile)

  • RollingFileAppender(RollingFile)、RollingRandomAccessFileAppender(RollingRandomAccessFile)

打开这些实现类的源码,你一定会恍然大明白,括号中的是实现类在log4j2.xml配置文件中的标签名。

10.ConsoleAppender(Console)

该实现类会把日志输出到控制台中。

它有两种输出方式:

  • SYSTEM_OUT(System.out)

  • SYSTEM_ERR(System.err)

如果不配置,默认使用SYSTEM_OUT进行输出。括号中是调用的方法。

简单示例:

<?xml  version="1.0" encoding="UTF-8"?><Configuration name="baseConf" status="warn" monitorInterval="30">

    <Appenders>

        <Console name="Console" target="SYSTEM_OUT">

            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" charset="UTF-8"/>        Console>

    Appenders>

    <Loggers>

        <Root level="info">

            <AppenderRef ref="RollingFile"/>        Root>

    Loggers>

Configuration>

其它属性可以参见官方文档:

http://logging.apache.org/log4j/2.x/manual/appenders.html#ConsoleAppender

10-1.FileAppender(File)、RandomAccessFileAppender(RandomAccessFile)

相同点:写入日志信息到文件

不同点:使用的I/O实现类不同,前者使用FileOutputStream,后者使用RandomAccessFile。

官方文档说是在bufferedIO=true(默认是true)的情况下后者比前者性能提升20% ~ 200%,不明觉厉,就用后者吧。

简单示例:

<?xml  version="1.0" encoding="UTF-8"?><Configuration name="baseConf" status="warn" monitorInterval="30">

    <Appenders>

        <RandomAccessFile name="File" fileName="logs/app.log" immediateFlush="false">            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" charset="UTF-8"/>        RandomAccessFile>

    Appenders>

    <Loggers>

        <Root level="info">            <AppenderRef ref="File"/>        Root>

    Loggers>

Configuration>

常用属性:

  • fileName:来指定文件位置,文件或目录不存在则会自动创建。

  • immediateFlush:是否每次写入都要立刻刷新到硬盘中。默认true,如果使用默认值可能会影响性能。

其它属性可以参见官方文档:

http://logging.apache.org/log4j/2.x/manual/appenders.html#RandomAccessFileAppender

10-2.RollingFileAppender(RollingFile)、RollingRandomAccessFileAppender(RollingRandomAccessFile)

这一对之间的区别与上一对之间的区别是一样的。

上一对的实现类不能进行日志滚动,所谓日志滚动就是当达到设定的条件后,日志文件进行切分。

比如:工程师想让系统中的日志按日进行切分,并且按月归档。

这时候这一对的作用就体现出来了。

简单示例:

<?xml  version="1.0" encoding="UTF-8"?><Configuration name="baseConf" status="warn" monitorInterval="30">

    <Appenders>

        <RollingRandomAccessFile name="File" fileName="logs/app.log"filePattern="logs/$${date:hh-mm}/%d{hh-mm-ss}.app.%i.log" >            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" charset="UTF-8"/>

            <Policies>

                <CronTriggeringPolicy schedule="0/5 * * * * ?" />                <SizeBasedTriggeringPolicy size="10 MB"/>            Policies>

            <DefaultRolloverStrategy max="10" />

        RollingRandomAccessFile>

    Appenders>

    <Loggers>

        <Root level="info">            <AppenderRef ref="File"/>        Root>

    Loggers>

Configuration>

1.filePattern:指定了日志滚动之后的文件命名格式,至于其中的{date:hh-mm}表达式下文介绍。

2.DefaultRolloverStrategy:指定了如何(How)进行翻滚,并且指定了最大翻滚次数(影响%i参数值),超过次数之后会按照相应的规则删除旧日志。

3.Policies: 这里就是规定了何时进行滚动(When),可以有多个Policy。

  • CronTriggeringPolicy设置了每 5s 进行一次翻滚

  • SizeBasedTriggeringPolicy设置了的话,如果当前文件超过了10MB,但是文件的名字还没有进行翻滚(建立新文件),那么就会用%i的方式进行翻滚。

10-3.翻滚示例

app.log

第一次翻滚:app.log app.1.log // app.log -> app.1.log
第二次翻滚:app.log app.1.log app.2.lop // app.log -> app.2.log
第三次翻滚:app.log app.1.log app.2.lop app.3.lop // app.log -> app.3.log
第四次翻滚:app.log app.1.log app.2.lop app.3.lop app.4.lop // app.log -> app.4.log

一直到设定的翻滚次数10之后,会把旧的日志内容覆盖。

app.2.lop -> app.1.lopapp.3.lop -> app.2.lop...app.10.lop -> app.9.lopapp.log -> app.10.lop

一直这样循环下去,直到创建新文件。

11.Filters

Filters决定日志事件能否被输出。过滤条件有三个值:ACCEPT(接受),DENY(拒绝),NEUTRAL(中立)。

11-1.常用的Filter实现类有

  • LevelRangeFilter

  • TimeFilter

  • ThresholdFilter

11-2.上文中提到log4j2中的Filter与Servlet中的有差别。那么有什么差别呢?

简单说就是log4j2中的过滤器ACCEPT和DENY之后,后续的过滤器就不会执行了,只有在NEUTRAL的时候才会执行后续的过滤器。

11-3.简单示例

测试代码:

public class LogMain {

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

    public static void main(String[] args) throws Exception {

        logger.trace("trace Msg.");        logger.debug("debug Msg.");        logger.info("info Msg.");        logger.warn("warn Msg.");        logger.error("error Msg.");

    }

}

配置文件:

<?xml  version="1.0" encoding="UTF-8"?><Configuration name="baseConf" status="warn" monitorInterval="30">

    <Appenders>

        <Console name="Console">

            <Filters>

                <LevelRangeFilter minLevel="error" maxLevel="info" onMatch="ACCEPT" onMismatch="NEUTRAL" />

                <TimeFilter start="08:00:00" end="08:30:00" onMatch="ACCEPT" onMismatch="DENY" />            Filters>

            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" charset="UTF-8"/>        Console>

    Appenders>

    <Loggers>

        <Root level="info">            <AppenderRef ref="Console"/>        Root>

    Loggers>

Configuration>

输出结果:

17:51:53.546 [main] INFO  me.master.snail.log.LogMain - info Msg.17:51:53.548 [main] WARN  me.master.snail.log.LogMain - warn Msg.17:51:53.548 [main] ERROR me.master.snail.log.LogMain - error Msg.

如果当前时间不是 8点~8点半 之间,那么没有日志会输出。

这里的info Msg.、warn Msg.和error Msg.为什么会输出呢?

是因为LevelRangeFilter对它们进行了ACCEPT,而剩下的trace Msg.和debug Msg.则会经过下一个过滤器,然后依次类推。

12.PatternLayout

这是常用的日志格式化类,其它日志格式化类很少用。

关于其它日志类,可以打开PatternLayout类,找到其父类AbstractStringLayout, 看父类的实现类有哪些。

简单示例:

"%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" charset="UTF-8"/>

授人以鱼不如授人以渔。关于pattern的格式点击

http://logging.apache.org/log4j/2.x/manual/layouts.html#PatternLayout

具体的其它属性可以看源码也可以参考官方文档。

13.Policy & Strategy

上文也说了,Policy是用来控制日志文件何时(When)进行滚动的;Strategy是用来控制日志文件如何(How)进行滚动的。

如果配置的是RollingFile或RollingRandomAccessFile,则必须配置一个Policy。

如果想按月归档,按日切分日志,然后

13-1.Policy常用的实现类:

  • SizeBasedTriggeringPolicy

  • CronTriggeringPolicy

  • TimeBasedTriggeringPolicy

13-1-1.SizeBasedTriggeringPolicy

根据日志文件的大小进行滚动。

<SizeBasedTriggeringPolicy size="10MB"/>

单位有:KB,MB,GB

13-1-2.CronTriggeringPolicy

使用Cron表达式进行日志滚动,很灵活。

<CronTriggeringPolicy schedule="0/5 * * * * ?" />

13-1-3.TimeBasedTriggeringPolicy

这个滚动策略依赖于filePattern中配置的最具体的时间单位,根据最具体的时间单位进行滚动。

这种方式比较简洁。CronTriggeringPolicy策略更强大。

简单示例:

<?xml  version="1.0" encoding="UTF-8"?><Configuration name="baseConf" status="warn" monitorInterval="30">

    <Appenders>

        <RollingRandomAccessFile name="File" fileName="logs/app.log"filePattern="logs/$${date:hh-mm}/%d{hh-mm-ss}.app.%i.log" >            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" charset="UTF-8"/>

            <Policies>

                <TimeBasedTriggeringPolicy interval="5" modulate="true"/>

                <SizeBasedTriggeringPolicy size="10 MB"/>            Policies>

            <DefaultRolloverStrategy max="10" />

        RollingRandomAccessFile>

    Appenders>

    <Loggers>

        <Root level="info">            <AppenderRef ref="File"/>        Root>

    Loggers>

Configuration>

13-2.Strategy常用的实现类

  • DefaultRolloverStrategy

  • DirectWriteRolloverStrategy

这两个Strategy都是控制如何进行日志滚动的,至于他们的区别我还是不太明白,大佬解释一下吧。

平时大部分用DefaultRolloverStrategy就可以了。

14.Logger

Logger部分就比较简单了,分为两个Logger:

  • Root(必须配置)

  • Logger

简单示例:

<?xml  version="1.0" encoding="UTF-8"?><Configuration name="baseConf" status="warn" monitorInterval="30">

    <Appenders>

        <Console name="Console">            <PatternLayout>                <Pattern>%d %p %c{1.} [%t] %m%nPattern>            PatternLayout>        Console>

    Appenders>

    <Loggers>

        <Root level="trace">            <AppenderRef ref="Console"/>            <Filters>                <LevelRangeFilter minLevel="error" maxLevel="info" onMatch="ACCEPT" onMismatch="DENY" />            Filters>        Root>

    Loggers>

Configuration>

注意:Logger中也可以加过滤器的哟~

14-1.比较重要的问题: 日志重复打印

如果Root中的日志包含了Logger中的日志信息,并且AppenderRef是一样的配置,则日志会打印两次。

注意:有两个条件

  • Root中的日志包含了Logger中的日志信息

  • 且AppenderRef是一样的配置

这时候我们需要使用一个Logger的属性来解决,那就是additivity,其默认值为true,需要配置为false。

<?xml  version="1.0" encoding="UTF-8"?><Configuration name="baseConf" status="warn" monitorInterval="30">

    <Appenders>

        <Console name="Console">            <PatternLayout>                <Pattern>%d %p %c{1.} [%t] %m%nPattern>            PatternLayout>        Console>

    Appenders>

    <Loggers>

        <Logger name="me.master.snail.log.LogMain" level="info" additivity="false">            <AppenderRef ref="Console"/>        Logger>

        <Root level="trace">            <AppenderRef ref="Console"/>            <Filters>                <LevelRangeFilter minLevel="error" maxLevel="info" onMatch="ACCEPT" onMismatch="DENY" />            Filters>        Root>

    Loggers>

Configuration>

15.Lookups

这个组件类似于JSTL的EL表达式,或者类似于Spring的SpEL表达式。

具体的语法很简单,这里就不粘贴复制了,查看官方文档:

http://logging.apache.org/log4j/2.x/manual/lookups.html

相信你用半个小时就学会了。

16.示例

为了大家快速开发(方便懒惰的同学),写一些示例。

16-1.输出到控制台

<?xml  version="1.0" encoding="UTF-8"?><Configuration name="baseConf" status="warn" monitorInterval="30">

    <Appenders>

        <Console name="Console" target="SYSTEM_OUT">

            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" charset="UTF-8"/>        Console>

    Appenders>

    <Loggers>

        <Root level="info">

            <AppenderRef ref="RollingFile"/>        Root>

    Loggers>

Configuration>

16-2.输出到单个文件

<?xml  version="1.0" encoding="UTF-8"?><Configuration name="baseConf" status="warn" monitorInterval="30">

    <Appenders>

        <RandomAccessFile name="File" fileName="logs/app.log" immediateFlush="false">            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" charset="UTF-8"/>        RandomAccessFile>

    Appenders>

    <Loggers>

        <Root level="info">            <AppenderRef ref="File"/>        Root>

    Loggers>

Configuration>

16-3.按月归档日志,按日进行切分,限制单文件大小为 500MB, 一天最多生成20个文件,也就是(20 * 500)MB大小的日志

<?xml  version="1.0" encoding="UTF-8"?><Configuration name="baseConf" status="warn" monitorInterval="30">

    <Appenders>

        <RollingRandomAccessFile name="File" fileName="logs/app.log"filePattern="logs/$${date:yyyy-MM}/%d{yyyy-MM-dd}.app.%i.log" >            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" charset="UTF-8"/>

            <Policies>                <TimeBasedTriggeringPolicy interval="1" modulate="false"/>                <SizeBasedTriggeringPolicy size="500MB"/>            Policies>

            <DefaultRolloverStrategy max="20" />        RollingRandomAccessFile>

    Appenders>

    <Loggers>

        <Root level="info">            <AppenderRef ref="File"/>        Root>

    Loggers>

Configuration>

16-4.限制Spring框架日志的输出级别

<?xml  version="1.0" encoding="UTF-8"?><Configuration name="baseConf" status="warn" monitorInterval="30">

    <Appenders>

        <RollingRandomAccessFile name="File" fileName="logs/app.log"filePattern="logs/$${date:yyyy-MM}/%d{yyyy-MM-dd}.app.%i.log" >            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" charset="UTF-8"/>

            <Policies>                <TimeBasedTriggeringPolicy interval="1" modulate="false"/>                <SizeBasedTriggeringPolicy size="500MB"/>            Policies>

            <DefaultRolloverStrategy max="20" />        RollingRandomAccessFile>

    Appenders>

    <Loggers>

        <logger name="org.springframework" level="INFO"/>

        <Root level="info">            <AppenderRef ref="File"/>        Root>

    Loggers>

Configuration>



技术交流群

log4j配置_是时候了解一下log4j2各种配置的含义了!相关推荐

  1. 华为交换机ipv6默认路由配置_静态路由和默认路由的配置

    一.静态路由的配置 下边实验对该拓扑图进行配置 实验目标:配置静态路由,实现全网互通 1.配置路由器R1 进入接口f0/0,配置IP,并开启. 进入接口f0/1,配置IP,并开启. 设置静态路由. c ...

  2. ssm 返回json配置_摆脱困境:将运行时配置作为JSON返回

    ssm 返回json配置 如果需要确定部署到远程服务器的Spring Web应用程序的运行时配置,则需要读取从远程服务器找到的属性文件. 这很麻烦. 幸运的是,有更好的方法. 这篇博客文章描述了我们如 ...

  3. jboss as安装配置_书评:JBoss AS 7:配置,部署和管理

    jboss as安装配置 我热切地接受Packt Publishing邀请复审JBoss AS 7:配置,部署和管理,因为自从我上次使用JBoss已有数年了,我很想了解有关JBoss AS 7的更多信 ...

  4. 交华为换机access配置_华为交换机Hybrid接口及基础配置

    一.回顾VLAN VLAN基本概念 VLAN即虚拟局域网,是将一个物理的LAN在逻辑上划分成多个广播域(多个VLAN)的通信技术.VLAN内的主机间可以直接通信,而VLAN间不能直接互通,从而将广播报 ...

  5. java 连接池配置_【Java】java数据库连接池配置的几种方法

    今天遇到了关于数据源连接池配置的问题,发现有很多种方式可以配置,现总结如下,希望对大家有所帮助:(已Mysql数据库为例) 一,Tomcat配置数据源: 方式一:在WebRoot下面建文件夹META- ...

  6. ac6005直连ap 如何配置_【无线】无线瘦AP配置如何进行AC直连AP配置

    适用场景说明 当无线网络中的AP数量众多,而且需要统一管理和配置. 优点:通过AC(AP控制器)统一配置和管理AP.包括配置下发.升级.重启等 缺点:需要增加网络设备AC,增加有线网络的配置,不同厂商 ...

  7. centos ip配置_在虚拟机(Vmware)中配置centos7系统静态ip,就是如此简单

    1 背景 使用vmware或virtualbox安装了centos操作系统后,下一步要做的要做的就是设置网络.通常linux系统是用来做服务器的,也很少使用(安装)桌面版的系统.服务器通常是放在服务运 ...

  8. feignclient多个配置_@FeignClient同一个name使用多个配置类的解决方案

    Feign有一个局限性,即对于同一个service-id只能使用一个配置类,如果有多个@FeignClient注解使用了相同的name属性,则注解的configuration参数会被覆盖.至于谁覆盖谁 ...

  9. sw标准件不能配置_思科设备与华为设备在配置Telnet,有啥不一样呢?

    在工作中,可能我们会遇到思科的设备或者华为的,所以,我们需要不断的补充自己的知识,慢慢从小白走向大神之路.今天来看看思科与华为设备在配置Telnet有啥不一样的 思科路由器2901配置Telnet远程 ...

最新文章

  1. websocket+netty实时视频弹幕交互功能(Java版)
  2. [C++] 指向常量的指针 VS 指针类型的常量
  3. python基础教程书籍推荐-初学者python入门必看书籍推荐(上)
  4. 问题描述 给定一个由n行数字组成的数字三角形如下图所示。试设计一个算法,计算出从三角形的顶至底的一条路径,使该路径经过的数字总和最大。 对于给定的由n行数字组成的数字三角形,计算从三角形的顶至底
  5. Silverlight在IIS中的配置
  6. Points角点halcon算子,持续更新
  7. C语言编程快速入门黎明,何用C语言模拟键盘输入?
  8. 人间不值得?250000条数据分析李诞是不是被骂火的
  9. 织梦生成的html路径,织梦dedecms安装在子目录网页生成在根目录如何设置
  10. AI 算法在 FPGA 芯片上还有这种操作?
  11. 如何搭建测试平台?理清思路很重要
  12. 阿里架构师:​程序员必须掌握的几项核心能力
  13. 对HTML5标签的认识(三)
  14. 只做正确的事情,并持续输出价值
  15. html图片原始比例_html图片如何按屏幕大小等比例缩放?
  16. matlab中floor函数,floor函数
  17. 2_Gui_Tkinter(python标准库)
  18. 4.4 给单元格快速添加斜线 [原创Excel教程]
  19. bzoj4444: [Scoi2015]国旗计划(线段树+倍增)
  20. html a标签发微信,a标签的特殊和文本的样式

热门文章

  1. 文献学习(part23)--双向聚类方法综述
  2. 机器学习中的不平衡分类方法(part4)--朴素贝叶斯分类器
  3. android 图片气泡,android图片上显示气泡消息
  4. SAP Spartacus UI Duplicated keys has been found in the config of i18n chunks
  5. 如何让 Visual Studio Code 里显示 Cypress 的 intelligent code suggestion
  6. Rxjs debounce 操作符在 SAP Spartacus 函数节流中的一个实际使用例子
  7. 什么是 SAP UI5 的 Component-preload.js, 什么是Minification和Ugification
  8. 试图用Session Administration删除某用户的session时报错
  9. SAP HANA CLOUD和aws一个实际项目中的性能比较
  10. SAP ABAP SICF事务码和SAP Hybris的链式过滤器filter chain