我们在调试java程序的时候,如果不使用idea这样的开发环境,一般是如何调试呢?一般是在几个关键位置打印出我们想看到的变量和变量值或者某个关键步骤处打印进程。但是每次调试之后都需要把这些打印语句都删掉。那么有没有什么好的办法来调试程序呢,就是日志。
那么你可能会问,既然有idea,我为什么还要用日志呢?因为现场部署的系统如果出问题了,通过查看日志可以很快的定位到问题位置,但现场不一定有适合调试的环境。
记录程序执行过程的文本文件。
import java.util.logging.Level; import java.util.logging.Logger; public class Hello { public static void main(String[] args) { Logger logger = Logger.getGlobal(); logger.info("start process..."); logger.warning("memory is running out..."); logger.fine("ignored."); logger.severe("process will be terminated..."); } }
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class Main { public static void main(String[] args) { Log log = LogFactory.getLog(Main.class); log.info("start..."); log.warn("end."); } }
<?xml version="1.0" encoding="UTF-8"?> <Configuration> <Properties> <!-- 定义日志格式 --> <Property name="log.pattern">%d{MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36}%n%msg%n%n</Property> <!-- 定义文件名变量 --> <Property name="file.err.filename">log/err.log</Property> <Property name="file.err.pattern">log/err.%i.log.gz</Property> </Properties> <!-- 定义Appender,即目的地 --> <Appenders> <!-- 定义输出到屏幕 --> <Console name="console" target="SYSTEM_OUT"> <!-- 日志格式引用上面定义的log.pattern --> <PatternLayout pattern="${log.pattern}" /> </Console> <!-- 定义输出到文件,文件名引用上面定义的file.err.filename --> <RollingFile name="err" bufferedIO="true" fileName="${file.err.filename}" filePattern="${file.err.pattern}"> <PatternLayout pattern="${log.pattern}" /> <Policies> <!-- 根据文件大小自动切割日志 --> <SizeBasedTriggeringPolicy size="1 MB" /> </Policies> <!-- 保留最近10份 --> <DefaultRolloverStrategy max="10" /> </RollingFile> </Appenders> <Loggers> <Root level="info"> <!-- 对info级别的日志,输出到console --> <AppenderRef ref="console" level="info" /> <!-- 对error级别的日志,输出到err,即上面定义的RollingFile --> <AppenderRef ref="err" level="error" /> </Root> </Loggers> </Configuration>
import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Main { public static void main(String[] args) { final Logger logger = LoggerFactory.getLogger(getClass()); log.info("start..."); log.warn("end."); } }
<?xml version="1.0" encoding="UTF-8"?> <configuration> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> <charset>utf-8</charset> </encoder> <file>log/output.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> <fileNamePattern>log/output.log.%i</fileNamePattern> </rollingPolicy> <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> <MaxFileSize>1MB</MaxFileSize> </triggeringPolicy> </appender> <root level="INFO"> <appender-ref ref="CONSOLE" /> <appender-ref ref="FILE" /> </root> </configuration>
比较常见的就是在一个任务或者说方法的关键点,比如开始,结束,以及发生异常的时候,通常是打印入参,和异常信息,方便排查错误。
方法的开始结束很好理解,所以要想知道何时打印日志,还需要知道什么时候捕获异常比较好。