003-log-jul,jdk自带日志服务
一、简介
java官方日志jul,位于java.util.logging包下。
1.1、POM依赖
无依赖
1.2、配置
JUL的默认配置文件是logging.properties ,在 $JAVA_HOME/jre/lib下 (Mac 在 $JAVA_HOME/lib). 当然自己也可以修改文件位置,如:-Djava.util.logging.config.file=xxxpath/logging.properties
jre(java runtime environment, 即java运行环境)的默认日志配置为jre/lib/logging.properties,
其配置如下:
############################################################ # Default Logging Configuration File # # You can use a different file by specifying a filename # with the java.util.logging.config.file system property. # For example java -Djava.util.logging.config.file=myfile ############################################################ ############################################################ # Global properties ############################################################ # "handlers" specifies a comma separated list of log Handler # classes. These handlers will be installed during VM startup. # Note that these classes must be on the system classpath. # By default we only configure a ConsoleHandler, which will only # show messages at the INFO and above levels. handlers= java.util.logging.ConsoleHandler # To also add the FileHandler, use the following line instead. #handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler # Default global logging level. # This specifies which kinds of events are logged across # all loggers. For any given facility this global level # can be overriden by a facility specific level # Note that the ConsoleHandler also has a separate level # setting to limit messages printed to the console. .level= INFO ############################################################ # Handler specific properties. # Describes specific configuration info for Handlers. ############################################################ # default file output is in user's home directory. java.util.logging.FileHandler.pattern = %h/java%u.log java.util.logging.FileHandler.limit = 50000 java.util.logging.FileHandler.count = 1 java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter # Limit the message that are printed on the console to INFO and above. java.util.logging.ConsoleHandler.level = INFO java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter # Example to customize the SimpleFormatter output format # to print one-line log message like this: # <level>: <log message> [<date/time>] # # java.util.logging.SimpleFormatter.format=%4$s: %5$s [%1$tc]%n ############################################################ # Facility specific properties. # Provides extra control for each logger. ############################################################ # For example, set the com.xyz.foo logger to only log SEVERE # messages: com.xyz.foo.level = SEVERE
在tomcat的conf下就有个logging.properties,同时注意catalina.sh 里就有这样代码
# Set juli LogManager if it is present if [ -r "$CATALINA_BASE"/conf/logging.properties ]; then JAVA_OPTS="$JAVA_OPTS -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager" LOGGING_CONFIG="-Djava.util.logging.config.file=$CATALINA_BASE/conf/logging.properties" fi
1.3、使用
import java.util.logging.Level; import java.util.logging.Logger; public class ApplicationMain { private static Logger logger = Logger.getLogger(ApplicationMain.class.getName()); public static void main(String[] args) { // 记录debug级别的信息 logger.log(Level.INFO,"This is debug message."); // 记录info级别的信息 logger.info("This is info message."); // 记录error级别的信息 logger.warning("This is warning message."); } }
二、详细说明
jul模块主要包含三个:Level、Formatter和Handler。
1.1、Level
日志级别,由高到低有:OFF/SEVERE/WARNIN/INFO/CONFIG/FINE/FINERG/FINEST/ALL,
每个级别有自己的数值,在java.util.logging.Level类中源码如下:
public static final Level OFF = new Level("OFF",Integer.MAX_VALUE, defaultBundle); public static final Level SEVERE = new Level("SEVERE",1000, defaultBundle); public static final Level WARNING = new Level("WARNING", 900, defaultBundle); public static final Level INFO = new Level("INFO", 800, defaultBundle); public static final Level CONFIG = new Level("CONFIG", 700, defaultBundle); public static final Level FINE = new Level("FINE", 500, defaultBundle); public static final Level FINER = new Level("FINER", 400, defaultBundle); public static final Level FINEST = new Level("FINEST", 300, defaultBundle); public static final Level ALL = new Level("ALL", Integer.MIN_VALUE, defaultBundle);
可自定义日志级别,继承java.util.logging.Level类即可。
1.2、Formatter
定义日志输出的格式,目前有SimpleFormatter和XMLFormatter两种格式,分别对应简单格式和xml格式。
可自定输出格式,继承抽象类java.util.logging.Formatter即可。
1.3、Handler
日志输出的目的,目前有
FileHandler:输出到文件,默认Level为INFO,Formatter为XMLFormatter;;
ConsoleHandler:输出到控制台,默认Level为INFO,流为System.err,Formatter为SimpleFormatter;
SocketHandler:输出到socket;
MemoryHandler:输出到内存;
可自定义日志级别,继承java.util.logging.Formatter类即可。
1.4、简单示例
import java.util.logging.*; public class JavaLogStudyMain { public static void main(String[] args) throws Exception { //简单格式的Formatter SimpleFormatter sf = new SimpleFormatter(); //xml格式的formatter XMLFormatter xf = new XMLFormatter(); //输出到文件的hander,指定日志输出级别为ALL FileHandler fh = new FileHandler("jul_study.log"); fh.setLevel(Level.ALL); fh.setFormatter(sf); // fh.setFormatter(xf); //输出到控制台的handler,指定日志输出级别为INFO ConsoleHandler ch = new ConsoleHandler(); ch.setLevel(Level.INFO); //获取logger实例,相同名的只能生成一个实例 Logger logger = Logger.getLogger("javaLog"); logger.addHandler(fh); //添加输出handler logger.addHandler(ch); //添加输出handler logger.setLevel(Level.ALL); //指定logger日志级别 //日志输出简写形式,有不同的级别,可带参数,其它类似 logger.log(Level.INFO, "this is a info, {0}", "p1"); logger.log(Level.WARNING, "this is a warn, {0} {1}", new Object[]{"p1", "p2"}); logger.log(Level.SEVERE, "this is a severe"); logger.log(Level.FINE, "this is a fine"); logger.log(Level.FINEST, "this is a finest"); logger.log(Level.CONFIG, "this is a config"); logger.log(Level.INFO, "this is a info", new Exception("my excep")); //带异常输出 //日志输出简写形式,有不同的级别 logger.severe("severe log"); logger.warning("warning log"); logger.info("info log"); logger.config("config log"); logger.fine("fine log"); logger.finer("finer log"); logger.finest("finest log"); } }
1.5、自定义logger
这里通过继承Level、Handler、Formatter自定义Logger,日志存在文件中,且每个不同的loggerName存不同日志文件中。
示例如下,解释请查看注释:
import org.apache.commons.lang.time.DateFormatUtils; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.Date; import java.util.logging.*; public class SelfJavaLogMain { //生成单例日志输出handler实例 private static SelfHandle sf = new SelfHandle(); /** * 根据class获取logger * * @param clazz * @return */ public static Logger getLogger(Class clazz) { return getLogger(clazz.getSimpleName()); } /** * 根据loggerName获取logger * * @param loggerName * @return */ public static Logger getLogger(String loggerName) { Logger logger = Logger.getLogger(loggerName); logger.addHandler(sf); return logger; } /** * 自定义日志格式formatter */ public static class SelfFormater extends Formatter { public static SelfFormater selfFormater = new SelfFormater(); @Override public String format(LogRecord record) { return String.format("[%s] %s %s.%s: %s\r\n", DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"), record.getLevel().getName(), record.getSourceClassName(), record.getSourceMethodName(), record.getMessage()); } public static SelfFormater getInstance() { return selfFormater; } } /** * 自定义日志level */ public static class SelfLevel extends Level { public static SelfLevel ERROR = new SelfLevel("ERROR", 910); /** * @param name 自定义级别名称 * @param value 自定义级别的权重值 */ protected SelfLevel(String name, int value) { super(name, value); } } /** * 自定义日志输出handler */ public static class SelfHandle extends Handler { /** * 日志写入的位置 * * @param record */ @Override public void publish(LogRecord record) { try { //每一个不同的loggerName分别记在不同的日志文件中 File file = new File(String.format("%s_%s.log", record.getLoggerName(), DateFormatUtils.format(new Date(), "yyyy-MM-dd"))); if (!file.exists()) { file.createNewFile(); } FileWriter fw = new FileWriter(file, true); PrintWriter pw = new PrintWriter(fw); String log = String.format("[%s] %s %s.%s: %s\r\n", DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"), record.getLevel().getName(), record.getSourceClassName(), record.getSourceMethodName(), record.getMessage()); pw.write(log); pw.flush(); } catch (IOException e) { e.printStackTrace(); } } /** * 刷新缓存区,保存数据 */ @Override public void flush() { } /** * 关闭 * * @throws SecurityException */ @Override public void close() throws SecurityException { } } public static void main(String[] args) throws Exception { //获取自定义的logger Logger logger = getLogger(SelfJavaLogMain.class); logger.info("info log"); logger.severe("severe log"); //使用自定义的logger level logger.log(SelfLevel.ERROR, "error log"); } }
水电费