目录

  • 什么是日志

  • 常用日志框架

  • 日志级别详解

  • 日志的记录时机

  • 日志使用规约

  • logback 配置示例

  • loh4j2 配置示例

什么是日志?

简单的说,日志就是记录程序的运行轨迹,方便查找关键信息,也方便快速定位解决问题。我们 Java 程序员在开发项目时都是依赖 Eclipse/ Idea 等开发工具的 Debug 调试功能来跟踪解决 Bug,在开发环境可以这么做,但项目发布到了测试、生产环境呢?你有可能会说可以使用远程调试,但实际并不能允许让你这么做。所以,日志的作用就是在测试、生产环境没有 Debug 调试工具时开发、测试人员定位问题的手段。日志打得好,就能根据日志的轨迹快速定位并解决线上问题,反之,日志输出不好不能定位到问题不说反而会影响系统的性能。优秀的项目都是能根据日志定位问题的,而不是在线调试,或者半天找不到有用的日志。

常用日志框架

log4j、Logging、commons-logging、slf4j、logback,开发的同学对这几个日志相关的技术不陌生吧,为什么有这么多日志技术,它们都是什么区别和联系呢?相信大多数人搞不清楚它们的关系,下面我将一一介绍一下,以后大家再也不用傻傻分不清楚了。

Logging 【java 自带工具】

这是 Java 自带的日志工具类,在 JDK 1.5 开始就已经有了,在java.util.logging 包下。

Log4j 【框架实现】

log4j 是 Apache 的一个开源日志框架,也是市场占有率最多的一个框架。大多数没用过 Java Logging, 但没人敢说没用过 Log4j 吧,反正从我接触 Java 开始就是这种情况,做 Java 项目必有 Log4j 日志框架。注意:log4j 在 2015/08/05 这一天被 Apache 宣布停止维护了,用户需要切换到 Log4j2上面去。

下面是官方宣布原文

On August 5, 2015 the Logging Services Project Management Committee announced that Log4j 1.x had reached end of life. For complete text of the announcement please see the Apache Blog. Users of Log4j 1 are recommended to upgrade to Apache Log4j 2.

Commons-logging 【日志接口】

上面介绍的 log4j 是一个具体的日志框架的实现,而 commons-logging 就是日志门面接口,它也是 apache 最早提供的日志门面接口,用户可以根据喜好选择不同的日志实现框架,而不必改动日志定义,这就是日志门面的好处,符合面向接口抽象编程。

Slf4j 【日志接口】

全称:Simple Logging Facade for Java,即简单日志门面接口,和 Apache 的 commons-logging是一样的概念,它们都不是具体的日志框架,你可以指定其他主流的日志实现框架。Slf4j也是现在主流的日志门面框架,使用Slf4j可以很灵活的使用占位符进行参数占位,简化代码,拥有更好的可读性,这个后面会讲到。

Logback 【框架实现】

logback 是 Slf4j 的原生实现框架,同样也是出自 Log4j一个人之手,但拥有比log4j更多的优点、特性和更做强的性能,现在基本都用来代替 log4j 成为主流。

日志框架总结

  • commons-loggin、slf4j 只是一种日志抽象门面,不是具体的日志框架。
  • log4j、logback 是具体的日志实现框架。
  • 一般首选强烈推荐使用 slf4j + logback。当然也可以使用slf4j + log4j、commons-logging + log4j 这两种日志组合框架。

日志级别详解

日志的输出都是分级别的,不同的设置不同的场合打印不同的日志。下面拿最普遍用的 Log4j 日志框架来做个日志级别的说明,这个也比较全面,其他的日志框架也都大同小异。Log4j 的级别类 org.apache.log4j.Level 里面定义了日志级别,日志输出优先级由高到底分别为以下8种。

日志级别及描述

  • ERROR:系统发生了错误事件,但仍然不影响系统的继续运行。系统需要将错误或异常细节记录ERROR日志中,方便后续人工回溯解决。
  • WARN: 系统在业务处理时触发了异常流程(参数验证不过),但系统可恢复到正常态,下一次业务可以正常执行。如程序调用了一个旧版本的接口,可选参数不合法,非业务预期的状态但仍可继续处理等
  • INFO: 记录系统关键信息,旨在保留系统正常工作期间关键运行指标,开发人员可以将初始化系统配置、业务状态变化信息,或者用户业务流程中的核心处理记录到INFO日志中,方便日常运维工作以及错误回溯时上下文场景复现
  • DEBUG: 可以将各类详细信息记录到DEBUG里,起到调试的作用,包括参数信息,调试细节信息,返回值信息等。

日志优先级别标准顺序

ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF

设置级别和打印级别的关系

如果日志级别设置 INFO,只有输出级别为 INFO、WARN,后面的日志才会正常输出。

日志的记录时机

系统初始化

系统初始化时会依赖一些关键配置,根据参数不同会提供不一样的服务。将系统的启动参数记录INFO日志,打印出参数以及服务启动完成状态。

业务流程与预期不符

系统中结果与期望不符,应当记录日志。常见的合适场景包括外部参数不正确,数据处理问题导致返回码不在合理范围内等等。

系统核心的关键动作

系统中核心角色触发的业务动作是需要多加关注的,是衡量系统正常运行的重要指标,建议记录INFO级别日志,比如微服务各服务节点交互等。

捕获到异常时

这类捕获的异常是系统告知开发人员需要加以关注的,应当记录日志,根据实际情况使用warn或者error级别。

外部接口日志

这类日志涉及到与外部系统的交互,事关责任问题,建议将原始数据文件内容写入日志或数据库(如mongodb),核心处理逻辑关键业务数据也尽量写入日志。如果涉及到重发,建议将处理失败的原始数据文件日志写入数据库,以便重发执行。

日志使用规约

  • 使用@SLF4J中的API进行日志打印。
  • 日志输出必须采用UTF-8字符集,推荐打印日志时输出英文,防止中文不支持而打印出乱码的情况。
  • 不允许记录日志后又抛出异常,因为这样会多次记录日志,只允许记录一次日志,应抛出异常,顶层打印一次日志。
 try {
  // 错误
} catch (Exception e) {
  log.error("xxxxxx", e);
  throw e;
}
  • 输出Exceptions的全部堆栈信息,但是不能使用e.printStackTrace()
 // 错误例子, 丢失掉StackTrace信息
log.error(e.getMessage());
// 错误例子,丢失掉StackTrace信息
log.error(“Bad things : {}“, e.getMessage());
// 正确例子
log.error(“Bad things : {}“,e); // e.printStackTrace()的源码
public void printStackTrace() {
printStackTrace(System.err);
}
  • 禁止system.out 用于日志记录。
  • 线上必须关闭 DEBUG 级别日志。
  • 非正常的情况,需要根据情况选择打印warn 或 error 日志,不能使用错误的日志级别。
 try {
// ...
} catch (Exception e) {
// 错误LOG.info("XX 发生异常...", e);
}
// 用 info 记录 error 日志,日志输出到了 info 日志文件中了,同事拼命地在 error 错误日志文件里 面找怎么能找到呢?
  • 日志输出,必须使用占位符的方式,因为即使信息不打印,也会执行字符串拼接,造成资源浪费。
  • 日志中不允许出现计算或方法调用,防止在打印日志的时候报错。
  • 输出的POJO类必须重写toString方法,否则只输出对象的hashCode值,没有参考意义。
  • 不记录对于排查故障毫无意义的日志信息,日志信息一定要带有业务信息。
 //错误
log.error(“handle failed“);
//正确
log.error(“handle failed,id= {}“, id);
  • 禁止大量无效重复的日志输出,通常情况下在程序日志只记录一些有意义的状态数据,参考日志记录时机。
  • 不可以讲敏感业务信息记录入日志文件。
  • 严防日志占满磁盘,定期检查磁盘(确定是否有磁盘告警)。
  • 不要在千层循环中打印日志
 for(int i=0; i<2000; i++){
LOG.info("XX");
}
// 这个是什么意思,如果你的框架使用了性能不高的 Log4j 框架,那就不要在上千个 for 循环中打印日志,
// 这样可能会拖垮你的应用程序,如果你的程序响应时间变慢,那要考虑是不是日志打印的过多了。

logback配置参考

配置说明

  • 统一使用logback.xml配置,logback.xml 文件放在 classpath 目录下。
  • 所有的jar包中不建议包含logback.xml文件,避免干扰实际的业务系统。
  • 通过在文件logback.xml中引入资源文件log.properties定义logback属性信息,log.properties根据不同的profile放置在不同位置;
<property resource="log.properties"/>
  • log.properties文件
  • 属性命名推荐使用统一使用大写,以下划线分隔,参考
 APP_NAME = yourAppName
LOG_DIR = /export/home/logs/yourSystem/yourAppName
LOG_PATTERN = [%date{yyyy-MM-dd HH:mm:ss.SSS}] %level [%mdc{invokeNo}] %C{0}:%line - %message%n
  • 注意Logger间的继承关系,推荐additivity设置false;
  1. 子logger会默认继承父logger的appender,将它们加入到自己的Appender中;除非加上了additivity="false",则不再继承父logger的appender。
  2. 子logger只在自己未定义输出级别的情况下,才会继承父logger的输出级别。
  • 将日志输出到文件当中,禁止使用FileAppender,推荐使用提供自动切换功能的RollingFileAppender Log文件位置和命名,目前Log文件的位置统一放在相同目录下面。
 
文件名 描述
/export/home/logs 默认日志路径(所有日志的根路径)
/export/home/logs/${系统名称}/${APP_NAME} log.properties中配置的日志全路径LOG_DIR
${LOG_DIR}/all.log 必选
${LOG_DIR}/ all-%d{yyyy-MM-dd}.log All历史文件命名
${LOG_DIR}/all_error.log 必选
${LOG_DIR}/sql.log 可选
  • 日志按天记录,单个日志文件最大不超过2000MB,考虑到有些bug按月规律出现,推荐历史日志保留30天。
 <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
  <fileNamePattern>${LOG_DIR}/all-%d{yyyy-MM-dd}.log</fileNamePattern>
  <maxHistory>30</maxHistory>
  <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
  <maxFileSize>2000MB</maxFileSize>
  </timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
  • 在出现问题之后,需要立即根据日志定位问题。对于INFO及以上级别的日志,要求按照一定顺序,输出以下必要的信息。参考日志格式定义
 <encoder charset="UTF-8">
  <pattern>[%date{yyyy-MM-dd HH:mm:ss.SSS}] %level
  [%mdc{invokeNo}] %C{0}:%line - %message%n</pattern>
</encoder>
  • 一个完整的Appender配置如下
 <?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <property resource="log.properties"/>
  <contextName>${APP_NAME}</contextName>   <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
    <encoder charset="UTF-8">
      <pattern>${LOG_PATTERN}</pattern>
    </encoder>
  </appender> <appender name="all" class="ch.qos.logback.core.rolling.RollingFileAppender">
  <file>${LOG_DIR}/all.log</file>
  <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    <fileNamePattern>${LOG_DIR}/all-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
    <maxHistory>30</maxHistory>
    <timeBasedFileNamingAndTriggeringPolicy
      class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
      <maxFileSize>2000MB</maxFileSize> <!-- 每个日志文件大小不超过2GB -->
    </timeBasedFileNamingAndTriggeringPolicy>
  </rollingPolicy>
  <encoder charset="UTF-8">
    <pattern>${LOG_PATTERN}</pattern>
  </encoder>
  <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
    <level>info</level>
  </filter>
</appender> <appender name="all-error" class="ch.qos.logback.core.rolling.RollingFileAppender">
  <file>${LOG_DIR}/all-error.log</file>
  <filter class="ch.qos.logback.classic.filter.LevelFilter">
    <level>ERROR</level>
    <onMatch>ACCEPT</onMatch>
    <onMismatch>DENY</onMismatch>
  </filter>
  <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    <fileNamePattern>
      ${LOG_DIR}/all-error-%d{yyyy-MM-dd}.%i.log
    </fileNamePattern>
    <maxHistory>30</maxHistory>
    <timeBasedFileNamingAndTriggeringPolicy
      class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
      <!-- 每个日志文件大小不超过2GB -->
      <maxFileSize>2000MB</maxFileSize>
    </timeBasedFileNamingAndTriggeringPolicy>
  </rollingPolicy>
  <encoder charset="UTF-8">
    <pattern>
      [%date{yyyy-MM-dd HH:mm:ss.SSS}] %level [%mdc{invokeNo}] %C{0}:%line - %message%n
    </pattern>
  </encoder>
</appender> <root level="debug">
  <appender-ref ref="all"/>
  <appender-ref ref="all-error"/>
  <appender-ref ref="console"/>
</root>
</configuration>

Log4j2配置参考

配置说明

  • 统一使用log4j2.xml配置,log4j2.xml 文件放在 resource目录下。
  • 注意Logger间的继承关系,推荐additivity设置false:
  1. 子logger会默认继承父logger的appender,将它们加入到自己的Appender中;除非加上了additivity="false",则不再继承父logger的appender。
  2. 子logger只在自己未定义输出级别的情况下,才会继承父logger的输出级别。
  • 将日志输出到文件当中,考虑到RollingRandomAccessFile比RollingFile更灵活,推荐统一使用RollingRandomAccessFile。
  • Log文件位置和命名,目前Log文件的位置统一放在相同目录下面。
 
文件名 描述 
/export/home/logs 默认日志路径(所有日志的根路径)
/export/home/logs/${系统名称}/${APP_NAME}  log.properties中配置的日志全路径LOG_DIR
${LOG_DIR}/all.log 必选 
${LOG_DIR}/ all-%d{yyyy-MM-dd}.log All历史文件命名
${LOG_DIR}/all_error.log 必选
${LOG_DIR}/sql.log 可选 
  • 日志按天记录,单个日志文件最大不超过3000MB,考虑到有些bug按周规律出现,推荐历史日志保留14天。
 <RollingRandomAccessFile name="all-append" immediateFlush="true"
    fileName="${LOG_DIR}/all.log" filePattern="${LOG_DIR}/all-%d{yyyy-MM-dd}-%i.log">
<Policies>
<SizeBasedTriggeringPolicy size="3GB" />
<TimeBasedTriggeringPolicy interval="8" modulate="true" />
<!-- 最多备份14天以内||日志文件大小达到50GB的日志||文件数量超过20此处为策略限制,
    Delete中可以按自己需要用正则表达式编写 -->
<DefaultRolloverStrategy>
  <Delete basePath="${filePath}" maxDepth="1">
    <IfLastModified age="14d" />
    <IfAccumulatedFileSize exceeds="50 GB" />
    <IfAccumulatedFileCount exceeds="20" />
  </Delete>
</DefaultRolloverStrategy>
  • 在出现问题之后,需要立即根据日志定位问题。对于INFO及以上级别的日志,要求按照一定顺序,输出以下必要的信息。参考日志格式定义
 <PatternLayout>
  <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level [%mdc{invokeNo}] %C{2}:%L %M - %msg%n
  </Pattern>
</PatternLayout>
  • 一个完整的Appender配置如下
 <?xml version="1.0" encoding="UTF-8"?>
<!-- Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,
  你会看到log4j2内部各种详细输出。monitorInterval:Log4j能够自动检测修改配置文件和重新配置本身,
  设置间隔秒数。
-->
<configuration status="OFF" monitorInterval=”600″>
<properties>
  <property name="LOG_PATH">/export/home/logs/yourSystem/yourAppName</property>
  <property name="LOG_PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level [%mdc{invokeNo}]
         %C{2}:%L %M - %msg%n </property>
  <property name="EVERY_FILE_SIZE">3GB</property>
  <property name="OUTPUT_LOG_LEVEL">info</property>
  <property name="FILE_COUNT">20</property>
  <property name="ERROR_FILE_COUNT">3</property>
</properties> <!--先定义所有的appender-->
<appenders>   <!--输出控制台的配置-->
  <Console name="console" target="SYSTEM_OUT">
    <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
    <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
    <!--输出日志的格式-->
    <PatternLayout pattern="${LOG_PATTERN}"/>
  </Console>
<!-- 打印信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,
  作为存档-->
<RollingRandomAccessFile
  name="all"
  immediateFlush="true"
  fileName="${LOG_DIR}/all.log"
  filePattern="${LOG_DIR}/all-%d{yyyy-MM-dd}-%i.log">
  <Filters>
    <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
    <ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
    <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
    <ThresholdFilter level="trace" onMatch="DENY" onMismatch="DENY"/>
  </Filters>
<PatternLayout>
  <Pattern>${LOG_PATTERN}</Pattern>
</PatternLayout>
<Policies>
  <SizeBasedTriggeringPolicy size="${EVERY_FILE_SIZE}" />
  <TimeBasedTriggeringPolicy interval="1" modulate="true" />
</Policies>
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了20 -->
<DefaultRolloverStrategy>
  <!-- 最多备14 天以内||日志文件大小达到50GB的日志||文件数量超过20此处为策略限制,Delete中可以按自
     己需要用正则表达式编写 -->
  <Delete basePath="${LOG_DIR}" maxDepth="1">
    <IfLastModified age="14d" />
    <IfAccumulatedFileSize exceeds="50 GB" />
    <IfAccumulatedFileCount exceeds="20" />
  </Delete>
</DefaultRolloverStrategy>
</RollingRandomAccessFile> <RollingRandomAccessFile
  name="all-error"
  immediateFlush="true"
  fileName="${LOG_DIR}/all-error.log"
  filePattern="${LOG_DIR}/all-error-%d{yyyy-MM-dd}-%i.log">
  <Filters>
    <ThresholdFilter level="error" onMatch="ACCEPT"onMismatch="NEUTRAL"/>
    <ThresholdFilter level="warn" onMatch="ACCEPT"onMismatch="DENY"/>
  </Filters>
  <PatternLayout>
    <Pattern>${LOG_PATTERN}</Pattern>
  </PatternLayout>
  <Policies>
    <SizeBasedTriggeringPolicy size="${EVERY_FILE_SIZE}" />
    <TimeBasedTriggeringPolicy interval="1" modulate="true" />
  </Policies>
  <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了20 -->
<DefaultRolloverStrategy max="${ERROR_FILE_COUNT}"/>
</RollingRandomAccessFile> </appenders> <!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
<loggers>
  <!--默认的root的logger-->
  <Logger name="all" level="info" additivity="false">
    <AppenderRef ref="all" />
  </Logger>
  <Logger name="all-error" level="error" additivity="false">
    <AppenderRef ref="all-error" />
  </Logger>
  <root level="${OUTPUT_LOG_LEVEL}">
    <appender-ref ref="console"/>
  </root>
</loggers> </configuration>

java日志规约及配置示例终极总结的更多相关文章

  1. log4j.xml——java日志处理组件配置简介

    (从一篇好文开始)log4j(一)——为什么要用log4j? 三:看完栗子后的感想 (1)很明显我们在编写代码的时候有各种需要打印日志的需求,比如:我们调试代码的时候:我们的应用出现了问题,我们分析. ...

  2. Java日志使用slf4j 配置log4j后,有日志文件 但日志文件内容为空

    SLF4J的全称是Simple Logging Facade for Java,即简单日志门面. SLF4J并不是具体的日志框架,而是作为一个简单门面服务于各类日志框架,如java.util.logg ...

  3. java 日志框架 pom配置

    使用log4j https://blog.csdn.net/qq_37936542/article/details/80839389[slf4j+logback实现web项目日志输出] 只需引入一个包 ...

  4. [翻译]Java日志终极指南

    本文由 ImportNew - Wing 翻译自 loggly.欢迎加入翻译小组.转载请见文末要求. Java日志基础 Java使用了一种自定义的.可扩展的方法来输出日志.虽然Java通过java.u ...

  5. Java日志终极指南

    Java日志基础 Java使用了一种自定义的.可扩展的方法来输出日志.虽然Java通过java.util.logging包提供了一套基本的日志处理API,但你可以很轻松的使用一种或者多种其它日志解决方 ...

  6. java日志框架log4j详细配置及与slf4j联合使用教程

    最后更新于2017年02月09日 一.log4j基本用法 首先,配置log4j的jar,maven工程配置以下依赖,非maven工程从maven仓库下载jar添加到“build path” <d ...

  7. springmvc 项目完整示例05 日志 --log4j整合 配置 log4j属性设置 log4j 配置文件 log4j应用

    log4j 就是log for java嘛,老外都喜欢这样子,比如那个I18n  ---internationalization  不就是i和n之间有18个字母... http://logging.a ...

  8. spring boot 日志介绍 以及 logback配置示例

    https://www.cnblogs.com/flying607/p/7827460.html 以下是springboot的一个局部依赖关系: 可以看到,java util logging(jul) ...

  9. [转载]java日志框架log4j详细配置及与slf4j联合使用教程

    一.log4j基本用法 首先,配置log4j的jar,maven工程配置以下依赖,非maven工程从maven仓库下载jar添加到“build path” 1 2 3 4 5 <dependen ...

随机推荐

  1. CloseHandel(_beginthreadex): 只是关闭了线程句柄对象,并不会结束线程。

    今天在测试程序的时候,在[任务管理器]中发现进程序的句柄随着多线程的不断运行,会不断的 +1. 发现原来在我的代码中,启动线程后都没有显式的调用 CloseHandle() 来关闭线程句柄. 当我准备 ...

  2. Quartz C#使用

    参考:https://www.cnblogs.com/lazyInsects/p/8075487.htmlQuartz是一款比较好用的定时任务执行工具类,虽然我们平时也可以自己写代码实现定时执行,但是 ...

  3. 五十一、进程间通信——System V IPC 之进程信号量

    51.1 进程信号量 51.1.1 信号量 本质上就是共享资源的数目,用来控制对共享资源的访问 用于进程间的互斥和同步 每种共享资源对应一个信号量,为了便于大量共享资源的操作引入了信号量集,可对所有信 ...

  4. Java CAS 比较并且更换值

    原文:Java中CAS详解 作者:jayxu无捷之径 在JDK 5之前Java语言是靠synchronized关键字保证同步的,这会导致有锁 锁机制存在以下问题: (1)在多线程竞争下,加锁.释放锁会 ...

  5. 关于MySQL中的8个 character_set 变量

    https://blog.csdn.net/sun8112133/article/details/79921734 本篇会简单介绍在 MySQL 中关于 8个 character_set 变量的基本作 ...

  6. 《css网站布局实录》(李超)——读书札记

    1.web表现层技术 2.HTML链接设计思想 3.对信息进行合理的分析.分类与处理来创造商业价值. 4.头部描述浏览器所需信息,主体包含所需要展现的具体内容. 5.HTML(XHTML)XML 6. ...

  7. 记事本 HTML

    又学了一遍HTML,感觉轻松了好多,个人感觉HTML和画画差不多,只要有了想法,画出来其实并不难. 头部信息<head> 头部信息并不是给我们看的,而是给浏览器看的,当浏览器看到之后,才好 ...

  8. 【听大佬rqy分享有感】

    rqy,一个神奇的名字,一个神奇的物种. 初三自学高等数学,无师自通:获得了大大小小的oi奖项:是也一直是山东省信息学的“红太阳”:今天听了他的分享,真的很有帮助. 1.  不必太较真:遇到不会的高数 ...

  9. mysql-8.0.11安装步骤

    1.下载好安装包:mysql-8.0.11-winx64.zip 2.解压到合适的目录,例如:C:\XQ\Soft\mysql-8.0.11-winx64 3.在目录下创建my.ini文件,配置bas ...

  10. 写给自己看的vue

    学习过程:自学(个人demo驱动),论坛,qq群多少听到vue,react(很抱歉只弄了hello world demo 虚拟dom 也是概念 到目前也没弄清楚)这类框架(工作经历前后端都折腾,老板指 ...