细说Java主流日志工具库

目录

  • 概述
  •   java.util.logging (JUL)
  •   Log4j
  •   Logback
  •   Log4j vs Logback
  •   common-logging
  •   slf4j
  •   common-logging vs slf4j
  •   总结
  • 实施日志解决方案
  •   引入jar包
  •     slf4j直接绑定日志组件
  •     slf4j兼容非slf4j日志组件
  •     spring 集成 slf4j
  •     common-logging绑定日志组件
  •   配置
  •     完整的logback.xml参考示例
  •     完整的log4j.xml参考示例
  •     logback配置参数说明
  •   使用API
  •     slf4j用法
  •     common-logging用法
  • 参考

概述

在项目开发中,为了跟踪代码的运行情况,常常要使用日志来记录信息。
在Java世界,有很多的日志工具库来实现日志功能,避免了我们重复造轮子。
我们先来逐一了解一下主流日志工具。

java.util.logging (JUL)

JDK1.4开始,通过java.util.logging提供日志功能。
它能满足基本的日志需要,但是功能没有Log4j强大,而且使用范围也没有Log4j广泛。

Log4j

Log4j是apache的一个开源项目,创始人Ceki Gulcu。
Log4j应该说是Java领域资格最老,应用最广的日志工具。从诞生之日到现在一直广受业界欢迎。
Log4j是高度可配置的,并可通过在运行时的外部文件配置。它根据记录的优先级别,并提供机制,以指示记录信息到许多的目的地,诸如:数据库,文件,控制台,UNIX系统日志等。
Log4j中有三个主要组成部分:

  • loggers: 负责捕获记录信息。
  • appenders : 负责发布日志信息,以不同的首选目的地。
  • layouts: 负责格式化不同风格的日志信息。
    官网地址

Logback

Logback是由log4j创始人Ceki Gulcu设计的又一个开源日记组件,目标是替代log4j。
logback当前分成三个模块:logback-core,logback- classiclogback-access
logback-core是其它两个模块的基础模块。
logback-classic是log4j的一个 改良版本。此外logback-classic完整实现SLF4J API使你可以很方便地更换成其它日记系统如log4j或JDK14 Logging。
logback-access访问模块与Servlet容器集成提供通过Http来访问日记的功能。 
官网地址

Log4j vs Logback

Logback相比Log4j具有许多好处:
性能提升
logback在log4j基础上做了优化,使性能提高了近10倍。此外,内存开销也减少了。
更充足的测试
尽管log4j也做了测试,但是logback的测试更加充分。所以,logback应该更加稳定。
天然支持slf4j
因为Logback-classic完全实现了slf4j的接口,所以天然支持slf4j。使用slf4j,有利于你切换日志工具库,减少工作量。
自动重载配置文件
Logback-classic可以自动重载更新过的配置文件。
自动移除旧日志
通过配置文件最大数和过期时间,Logback可以控制日志文件数并自动清除过期的日志。
更灵活、更精细的配置
Logback在配置中提供更加丰富的功能来帮助你更加精细的去定制你的日志组件:
<filter>提供比log4j更丰富的过滤条件;
增加<if><then> 和 <else>这样的条件控制;
打印异常的调用栈信息
Logback在打印异常时,会打印调用栈的包装数据。
Logback-access
Logback-access支持Logback-classic的所有特性,并且它可以提供丰富的HTTP-access日志功能。
总结
以上优点摘自官方推荐理由:Reasons to prefer logback over log4j。
由于Logback的作者也是Log4j的作者,所有推荐理由应该比较靠谱。
总之,相比于Log4j,好处多多,你心动了没?

common-logging

common-logging是apache的一个开源项目。也称Jakarta Commons Logging,缩写JCL
common-logging的功能是提供日志功能的API接口,本身并不提供日志的具体实现(当然,common-logging内部有一个Simple logger的简单实现,但是功能很弱,直接忽略),而是在运行时动态的绑定日志实现组件来工作(如log4j、java.util.loggin)。
官网地址

slf4j

全称为Simple Logging Facade for Java,即java简单日志门面。
什么,作者又是Ceki Gulcu!这位大神写了Log4j、Logback和slf4j,专注日志组件开发五百年,一直只能超越自己。
类似于Common-Logging,slf4j是对不同日志框架提供的一个API封装,可以在部署的时候不修改任何配置即可接入一种日志实现方案。但是,slf4j在编译时静态绑定真正的Log库。使用SLF4J时,如果你需要使用某一种日志实现,那么你必须选择正确的SLF4J的jar包的集合(各种桥接包)。
官网地址

common-logging vs slf4j

slf4j库类似于Apache Common-Logging。但是,他在编译时静态绑定真正的日志库。这点似乎很麻烦,其实也不过是导入桥接jar包而已。
slf4j一大亮点是提供了更方便的日志记录方式:
不需要使用logger.isDebugEnabled()来解决日志因为字符拼接产生的性能问题。slf4j的方式是使用{}作为字符串替换符,形式如下:

logger.debug("id: {}, name: {} ", id, name);

总结

综上所述,使用slf4j + Logback可谓是目前最理想的日志解决方案了。
接下来,就是如何在项目中实施了。

实施日志解决方案

使用日志解决方案基本可分为三步:

  1. 引入jar包
  2. 配置
  3. 使用API
    常见的各种日志解决方案的第2步和第3步基本一样,实施上的差别主要在第1步,也就是使用不同的库。

引入jar包

这里首选推荐使用slf4j + logback 的组合。
如果你习惯了common-logging,可以选择common-logging+log4j。
强烈建议不要直接使用日志实现组件(logback、log4j、java.util.logging),理由前面也说过,就是无法灵活替换日志库。
还有一种情况:你的老项目使用了common-logging,或是直接使用日志实现组件。如果修改老的代码,工作量太大,需要兼容处理。在下文,都将看到各种应对方法。
注:据我所知,当前仍没有方法可以将slf4j桥接到common-logging。如果我孤陋寡闻了,请不吝赐教。

slf4j直接绑定日志组件

slf4j + logback
添加依赖到pom.xml中即可。
logback-classic-1.0.13.jar 会自动将 slf4j-api-1.7.21.jar 和 logback-core-1.0.13.jar 也添加到你的项目中。

<dependency> <groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.0.13</version>
</dependency>

slf4j + log4j
添加依赖到pom.xml中即可。
slf4j-log4j12-1.7.21.jar 会自动将 slf4j-api-1.7.21.jar 和 log4j-1.2.17.jar 也添加到你的项目中。

<dependency> <groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.21</version>
</dependency>

slf4j + java.util.logging
添加依赖到pom.xml中即可。
slf4j-jdk14-1.7.21.jar 会自动将 slf4j-api-1.7.21.jar 也添加到你的项目中。

<dependency> <groupId>org.slf4j</groupId><artifactId>slf4j-jdk14</artifactId><version>1.7.21</version>
</dependency>

slf4j兼容非slf4j日志组件

在介绍解决方案前,先提一个概念——桥接
什么是桥接呢
假如你正在开发应用程序所调用的组件当中已经使用了common-logging,这时你需要 jcl-over-slf4j.jar把日志信息输出重定向到 slf4j-api,slf4j-api再去调用slf4j实际依赖的日志组件。这个过程称为桥接。
下图是官方的slf4j桥接策略图:

从图中应该可以看出,无论你的老项目中使用的是common-logging或是直接使用log4j、java.util.logging,都可以使用对应的桥接jar包来解决兼容问题。

slf4j兼容common-logging

<dependency><groupId>org.slf4j</groupId><artifactId>jcl-over-slf4j</artifactId><version>1.7.12</version>
</dependency>

slf4j兼容log4j

<dependency><groupId>org.slf4j</groupId><artifactId>log4j-over-slf4j</artifactId><version>1.7.12</version>
</dependency>

slf4j兼容java.util.logging

<dependency><groupId>org.slf4j</groupId><artifactId>jul-to-slf4j</artifactId><version>1.7.12</version>
</dependency>

spring 集成 slf4j

做java web开发,基本离不开spring框架。很遗憾,spring使用的日志解决方案是common-logging + log4j。
所以,你需要一个桥接jar包:logback-ext-spring

<dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.1.3</version>
</dependency>
<dependency><groupId>org.logback-extensions</groupId><artifactId>logback-ext-spring</artifactId><version>0.1.2</version>
</dependency>
<dependency><groupId>org.slf4j</groupId><artifactId>jcl-over-slf4j</artifactId><version>1.7.12</version>
</dependency>

common-logging绑定日志组件

common-logging + log4j
添加依赖到pom.xml中即可。

<dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version>
</dependency>
<dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version>
</dependency>

配置

日志配置文件大同小异,需要注意的是:logback.xml和log4j.xml都需要放在classpath路径下

完整的logback.xml参考示例

在下面的配置文件中,我为自己的项目代码(根目录:org.zp.notes.spring)设置了五种等级:
TRACE、DEBUG、INFO、WARN、ERROR,优先级依次从低到高。
因为关注spring框架本身的一些信息,我增加了专门打印spring WARN及以上等级的日志。

<?xml version="1.0" encoding="UTF-8" ?><!-- logback中一共有5种有效级别,分别是TRACE、DEBUG、INFO、WARN、ERROR,优先级依次从低到高 -->
<configuration scan="true" scanPeriod="60 seconds" debug="false"><property name="DIR_NAME" value="spring-helloworld"/><!-- 将记录日志打印到控制台 --><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>%d{HH:mm:ss.SSS} [%thread] [%-5p] %c{36}.%M - %m%n</pattern></encoder></appender><!-- RollingFileAppender begin --><appender name="ALL" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 根据时间来制定滚动策略 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${user.dir}/logs/${DIR_NAME}/all.%d{yyyy-MM-dd}.log</fileNamePattern><maxHistory>30</maxHistory></rollingPolicy><!-- 根据文件大小来制定滚动策略 --><triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"><maxFileSize>30MB</maxFileSize></triggeringPolicy><encoder><pattern>%d{HH:mm:ss.SSS} [%thread] [%-5p] %c{36}.%M - %m%n</pattern></encoder></appender><appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 根据时间来制定滚动策略 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${user.dir}/logs/${DIR_NAME}/error.%d{yyyy-MM-dd}.log</fileNamePattern><maxHistory>30</maxHistory></rollingPolicy><!-- 根据文件大小来制定滚动策略 --><triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"><maxFileSize>10MB</maxFileSize></triggeringPolicy><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>ERROR</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter><encoder><pattern>%d{HH:mm:ss.SSS} [%thread] [%-5p] %c{36}.%M - %m%n</pattern></encoder></appender><appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 根据时间来制定滚动策略 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${user.dir}/logs/${DIR_NAME}/warn.%d{yyyy-MM-dd}.log</fileNamePattern><maxHistory>30</maxHistory></rollingPolicy><!-- 根据文件大小来制定滚动策略 --><triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"><maxFileSize>10MB</maxFileSize></triggeringPolicy><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>WARN</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter><encoder><pattern>%d{HH:mm:ss.SSS} [%thread] [%-5p] %c{36}.%M - %m%n</pattern></encoder></appender><appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 根据时间来制定滚动策略 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${user.dir}/logs/${DIR_NAME}/info.%d{yyyy-MM-dd}.log</fileNamePattern><maxHistory>30</maxHistory></rollingPolicy><!-- 根据文件大小来制定滚动策略 --><triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"><maxFileSize>10MB</maxFileSize></triggeringPolicy><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>INFO</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter><encoder><pattern>%d{HH:mm:ss.SSS} [%thread] [%-5p] %c{36}.%M - %m%n</pattern></encoder></appender><appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 根据时间来制定滚动策略 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${user.dir}/logs/${DIR_NAME}/debug.%d{yyyy-MM-dd}.log</fileNamePattern><maxHistory>30</maxHistory></rollingPolicy><!-- 根据文件大小来制定滚动策略 --><triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"><maxFileSize>10MB</maxFileSize></triggeringPolicy><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>DEBUG</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter><encoder><pattern>%d{HH:mm:ss.SSS} [%thread] [%-5p] %c{36}.%M - %m%n</pattern></encoder></appender><appender name="TRACE" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 根据时间来制定滚动策略 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${user.dir}/logs/${DIR_NAME}/trace.%d{yyyy-MM-dd}.log</fileNamePattern><maxHistory>30</maxHistory></rollingPolicy><!-- 根据文件大小来制定滚动策略 --><triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"><maxFileSize>10MB</maxFileSize></triggeringPolicy><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>TRACE</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter><encoder><pattern>%d{HH:mm:ss.SSS} [%thread] [%-5p] %c{36}.%M - %m%n</pattern></encoder></appender><appender name="SPRING" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 根据时间来制定滚动策略 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${user.dir}/logs/${DIR_NAME}/springframework.%d{yyyy-MM-dd}.log</fileNamePattern><maxHistory>30</maxHistory></rollingPolicy><!-- 根据文件大小来制定滚动策略 --><triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"><maxFileSize>10MB</maxFileSize></triggeringPolicy><encoder><pattern>%d{HH:mm:ss.SSS} [%thread] [%-5p] %c{36}.%M - %m%n</pattern></encoder></appender><!-- RollingFileAppender end --><!-- logger begin --><!-- 本项目的日志记录,分级打印 --><logger name="org.zp.notes.spring" level="TRACE" additivity="false"><appender-ref ref="STDOUT"/><appender-ref ref="ERROR"/><appender-ref ref="WARN"/><appender-ref ref="INFO"/><appender-ref ref="DEBUG"/><appender-ref ref="TRACE"/></logger><!-- SPRING框架日志 --><logger name="org.springframework" level="WARN" additivity="false"><appender-ref ref="SPRING"/></logger><root level="TRACE"><appender-ref ref="ALL"/></root><!-- logger end --></configuration>

完整的log4j.xml参考示例

log4j的配置文件一般有xml格式或properties格式。这里为了和logback.xml做个对比,就不介绍properties了,其实也没太大差别。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"><log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'><appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"><layout class="org.apache.log4j.PatternLayout"><param name="ConversionPattern"value="%d{yyyy-MM-dd HH:mm:ss,SSS\} [%-5p] [%t] %c{36\}.%M - %m%n"/></layout><!--过滤器设置输出的级别--><filter class="org.apache.log4j.varia.LevelRangeFilter"><param name="levelMin" value="debug"/><param name="levelMax" value="fatal"/><param name="AcceptOnMatch" value="true"/></filter></appender><appender name="ALL" class="org.apache.log4j.DailyRollingFileAppender"><param name="File" value="${user.dir}/logs/spring-common/jcl/all"/><param name="Append" value="true"/><!-- 每天重新生成日志文件 --><param name="DatePattern" value="'-'yyyy-MM-dd'.log'"/><!-- 每小时重新生成日志文件 --><!--<param name="DatePattern" value="'-'yyyy-MM-dd-HH'.log'"/>--><layout class="org.apache.log4j.PatternLayout"><param name="ConversionPattern"value="%d{yyyy-MM-dd HH:mm:ss,SSS\} [%-5p] [%t] %c{36\}.%M - %m%n"/></layout></appender><!-- 指定logger的设置,additivity指示是否遵循缺省的继承机制--><logger name="org.zp.notes.spring" additivity="false"><level value="error"/><appender-ref ref="STDOUT"/><appender-ref ref="ALL"/></logger><!-- 根logger的设置--><root><level value="warn"/><appender-ref ref="STDOUT"/></root>
</log4j:configuration>

logback配置参数说明

logback基本兼容log4j的配置,并提供更多的功能。
这里奉献一张本人整理的logback配置思维导图,高清无码。

使用API

slf4j用法

使用slf4j的API很简单。使用LoggerFactory初始化一个Logger实例,然后调用Logger对应的打印等级函数就行了。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class App {private static final Logger log = LoggerFactory.getLogger(App.class);public static void main(String[] args) {String msg = "print log, current level: {}";log.trace(msg, "trace");log.debug(msg, "debug");log.info(msg, "info");log.warn(msg, "warn");log.error(msg, "error");}
}

common-logging用法

common-logging用法和slf4j几乎一样,但是支持的打印等级多了一个更高级别的:fatal
此外,common-logging不支持{}替换参数,你只能选择拼接字符串这种方式了。

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;public class JclTest {private static final Log log = LogFactory.getLog(JclTest.class);public static void main(String[] args) {String msg = "print log, current level: ";log.trace(msg + "trace");log.debug(msg + "debug");log.info(msg + "info");log.warn(msg + "warn");log.error(msg + "error");log.fatal(msg + "fatal");}
}

参考

slf4官方文档
logback官方文档
log4j官方文档
commons-logging官方文档
http://blog.csdn.net/yycdaizi/article/details/8276265

作者:静默虚空
欢迎任何形式的转载,但请务必注明出处。
限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。

转载于:https://www.cnblogs.com/wangchaoyuana/p/7507485.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/257457.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SQL2008使用json.net实现XML与JSON互转

借助CLR&#xff0c;首先实现字符串的互转&#xff0c;然后使用存储过程实现JSON2table public class JsonFunction { /// <summary> /// XML转JSON /// </summary> /// <param name"xml"></param> /// <returns></returns> ///…

黑胡桃木php,揭秘美国黑胡桃木的美

家具是艺术和文化的载体&#xff0c;人们对木的喜爱&#xff0c;是一种与生俱来的情怀。好的木材淳厚质朴、温润坚定&#xff0c;有着不动声色的力量。美国黑胡桃木(亦称黑核桃木)便是如此&#xff0c;“身体”中散发着让人无法抗拒的魅力&#xff01;美国黑胡桃木体现的是“深…

c mysql备份还原数据库,MySQL数据库备份与恢复方法

常有新手问我该怎么备份数据库&#xff0c;下面介绍3种备份数据库的方法&#xff1a;(1)备份数据库文件MySQL中的每一个数据库和数据表分别对应文件系统中的目录和其下的文件。在Linux下数据库文件的存放目录一般为/var/lib/mysql。在Windows下这个目录视MySQL的安装路径而定&a…

第四篇:白话tornado源码之褪去模板外衣的前戏

加班程序员最辛苦&#xff0c;来张图醒醒脑吧&#xff01; ... ... ... 好了&#xff0c;醒醒吧&#xff0c;回归现实看代码了&#xff01;&#xff01; 执行字符串表示的函数&#xff0c;并为该函数提供全局变量 本篇的内容从题目中就可以看出来&#xff0c;就是为之后剖析tor…

生活常识

雷雨天野外要关手机 温汉华介绍&#xff0c;雷雨天&#xff0c;山顶空旷处容易遭雷电袭击。 他同时提醒&#xff0c;若游客在山上游览时&#xff0c;遭遇到电闪雷鸣的暴雨天气时&#xff0c;一定要注意以下事项&#xff1a; 其一&#xff0c;关停自己的手机。 其二&#xff0c;…

主程序分析法MATLAB编程,专题五  概率统计问题的Matlab求解

【实验目的及要求】I&#xff0e;熟练掌握Matlab编程中常见概率分布的概率密度、概率分布、逆分布、均值和方差等语句的调用格式&#xff0c;学会用Matlab对服从各种分布的样本进行参数估计和假设检验。对实际问题&#xff0c;能够进行样本的分析&#xff0c;得出服从哪种分布的…

LFS(Linux From Scratch)学习

一、环境准备 使用Debian平台&#xff0c;需做如下环境检查&#xff1a; 1、检查各个需要的工具及内核版本号&#xff0c;看看是否符合lfs7.7的列表要求 2、检查需要用到的库&#xff0c;一共有三个&#xff0c;gmp, mpfr和mpc 工具检查脚本如下&#xff1a; #filename:check_e…

腾讯云 Centos 配置 JDK Tomcat Mysql

配置JDK 从 oracle 官网下载 rpm 版本的 jdk 包,官方链接:点击此处跳转。下载jdk的时候记得看一看自己的系统是 64 位还是 32 位的&#xff0c;下对应的版本。下载好以后上传到腾讯云服务器中,命令格式为 scp &#xff3b;文件路径] &#xff3b;云主机用户名ip地址]:[服务器上…

php 取url根域名,php中取得URL的根域名的代码

/*** 取得根域名** author lonely* create 2011-3-11* version 0.1* lastupdate lonely* package Sl*/class Sl_RootDomain{private static $self;private $domainnull;private $hostnull;private $state_domain;private $top_domain;/*** 取得域名分析实例* Enter description…

如何创建sequence

我用的是在oracle中的方法&#xff0c;在oracle中sequence就是所谓的序列号&#xff0c;每次取的时候它会自动增加&#xff0c;一般用在需要按序列号排序的地方。 1、Create Sequence 你首先要有CREATE SEQUENCE或者CREATE ANY SEQUENCE权限&#xff0c; CREATE SEQUENCE SI_E…

简易版jQuery——mQuery

前面的话 虽然jQuery已经日渐式微&#xff0c;但它里面的许多思想&#xff0c;如选择器、链式调用、方法函数化、取赋值合体等&#xff0c;有的已经变成了标准&#xff0c;有的一直影响到现在。所以&#xff0c;jQuery是一个伟大的前端框架。前端世界日新月异&#xff0c;由于实…

LaTeX 安装配置 OSX

LaTeX 安装配置 OSX官方网站&#xff1a;http://www.latex-project.orghttp://www.tug.org/mactex/http://pages.uoregon.edu/koch/BasicTeX.pdf完整的Tex超过2G&#xff0c;一般用户没必要&#xff0c;可以先安装BasicTeX&#xff0c;当有需要时include必要的库即可1.安装Basi…

php 正三角塔,PHP 环境塔建与数据类型转换

手动塔建PHP开发环境安装php c:\apps\php安装apache c:\apps\apache1.配制apache配制c:\apps\apache\conf\httpd.confDocumentRoot"c:/apps/www" //指定工作目录,WWW为自已创健Directoryindex index.php index.html // 加入:loadModule php5_module "c:\apps\PH…

C/C++基础知识:函数指针和指针函数的基本概念

【函数指针】 在程序运行中&#xff0c;函数代码是程序的算法指令部分&#xff0c;它们和数组一样也占用存储空间&#xff0c;都有相应的地址。可以使用指针变量指向数组的首地址&#xff0c;也可以使用指针变量指向函数代码的首地址&#xff0c;指向函数代码首地址的指针…

告警系统邮件引擎

2019独角兽企业重金招聘Python工程师标准>>> 20.23-20.25 告警系统邮件引擎 创建发邮件的脚本——mail.py [rootlocalhost mail]# pwd /usr/local/sbin/mon/mail[rootlocalhost mail]# vim mail.py #!/usr/bin/env python #-*- coding: UTF-8 -*- import os,sys rel…

【HTTP 2】简介(Introduction)

前情提要 在上一篇文章《【HTTP 2.0】 序言》中&#xff0c;我们简要介绍了 HTTP 2 协议的概要和协议状态。 在本篇文章中&#xff0c;我们将会了解到 HTTP 2 协议简介&#xff08;Introduction&#xff09;部分的内容。 简介&#xff08;Introduction&#xff09; 超文本传输协…

java测试类生成对象,java编写student类 用Java编写一段测试程序,生成student类的两个对象,并输出每个对象基本信息?...

java中怎么创建对象数组&#xff1f;比如我创建了一个学生类Student&#xff0c;怎么用这个类创建一个对象数组&#xff0c;麻烦给个例子&#xff1f;学生类&#xff1a;classA{privateStringnameprivateintagepublicStringgetName(){returnname}publicvoidsetName(Stringname)…

iOS -- SKScene类

SKScene类 继承自SKEffectNode:SKNode:UIResponder:NSObject符合NSCoding(SKNode)NSCopying(SKNode)NSObject(NSObject)框架 /System/Library/Frameworks/SpriteKit.framework可用性可用于iOS 7.0或者更晚的版本声明于SKScene.h参考指南Sprite Kit Progamming Guide概览 重要提…

SSD硬盘 全盘安全擦除

此文From http://ssd.zol.com.cn/575/5753057.html 在SSD固态硬盘的使用过程中&#xff0c;部分用户可能会碰到计算机意外掉电或死机并强行断电后&#xff0c;系统出现异常&#xff0c;扫描SSD后发现坏块&#xff0c;然后一着急一跺脚甚至想返厂维修。 其实掉电后固态硬盘出现坏…

php中等3秒再跳转,跳转和重定向

页面跳转在应用开发中&#xff0c;经常会遇到一些带有提示信息的跳转页面&#xff0c;例如操作成功或者操作错误页面&#xff0c;并且自动跳转到另外一个目标页面。系统的ThinkController类内置了两个跳转方法success和error&#xff0c;用于页面跳转提示&#xff0c;而且可以支…