一、为什么要选这个题目
在写实验Lab4的时候,里面有要求去使用日志记录信息,并且用SpotBug对错误进行排除。
二、日志
此处以java.util.logging.Logger,作为介绍。
在调试程序时,我们在找bug的时候通常会用System.out.print来打印值。而如果使用了日志,就可以更方便地对程序内部的运行过程有一个全面的了解。
首先Java 日志 API 由以下三个核心组件组成:
Loggers:Logger 负责捕捉事件并将其发送给合适的 Appender。
Appenders:也被称为 Handlers,负责将日志事件记录到目标位置。在将日志事件输出之前, Appenders 使用Layouts来对事件进行格式化处理。
Layouts:也被称为 Formatters,它负责对日志事件中的数据进行转换和格式化。Layouts 决定了数据在一条日志记录中的最终形式。
这三个组件在接下来的例子中会用到。
然后介绍一下日志的级别:
SEVERE (HIGHEST LEVEL)
WARNING
INFO
CONFIG
FINE
FINER
FINEST (LOWEST LEVEL)
从上至下,事件的严重性依次降低。
接着我们开始创建日志。
首先我们用getLogger方法创建日志,传入的String参数作为日志的名称。
创建一个文件,用于将日志记录的信息存入至此文件中。setUseParentHandlers传入的参数是Boolean型的,传入false代表传进去的日志信息不打印在控制台上。
打开一个文件,这里设置true是以追加的形式写入文件,即打开的时候不是以覆写的形式对文件写入。
这是用来对我传入的信息进行格式匹配,即传入的Myformatter()对象是我指定的格式。
然后我们看一下Myformatter的形式,可以看到我们返回的是当前的时间,以及日志等级,日志名和日志得到的信息。
再返回Test文件,我们对这个测试一下,对于用户输入的choice,如果是1就以严重的形式写入读取文件错误,若为2就以记录信息的形式写入“写入文件”,否则记录“退出”的信息,然后跳出循环。
最终再对fh和scanner进行关闭。
在我们进行实时输入的时候,发现log文件并没有进行更新。
而一旦输入了3,即退出循环后,日志文件就立马更新了。
后来我发现,只有对fh进行关闭后,log文件才会实时更新。故在switch判断中我们需要记录日志后立马关闭,然后下一个循环在打开,这样就可以在循环中实时查看日志。我们把原日志信息删光后继续测试一下。
可以看到现在已经做到了可以实时更新了。并且可以看到对应的case1显示的事件等级是SEVERE,case2显示的事件等级是INFO。
而我在运行的时候发现一件很奇怪的事情,即有时候会出现这种lck文件。并且出现这种文件会导致我原来的log文件突然不更新了。后来去论坛查答案发现是fh没有及时关掉接着又打开了,就会出现这种错误情况。并且我也发现出现这种情况也和我一个坏习惯有关,有时候我退出程序不会按照程序正常退出(比如说这里输入3会退出),而是直接点击run再运行一遍,这样也会导致这种情况。
接下来附上测试的代码,Test.java和Myformatter.java的,大家可以试一下一遍加深对日志的理解。
//Test.java
import java.io.IOException;
import java.util.Scanner;
import java.util.logging.FileHandler;
import java.util.logging.Logger;
public class Test {
public static void main(String[] args) {
Logger log = Logger.getLogger("Test");
Scanner scanner = new Scanner(System.in);
boolean flag = true;
FileHandler fh = null;
log.setUseParentHandlers(false);
if(flag!=false)
;
while (flag) {
try {
fh = new FileHandler("src\\testlog.txt", true);
} catch (SecurityException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
fh.setFormatter(new Myformatter());
log.addHandler(fh);
int choice = scanner.nextInt();
switch (choice) {
case 1:
log.severe("读取文件错误");
fh.close();
break;
case 2:
log.info("写入文件");fh.close();
break;
default:
flag = false;
log.info("退出");
break;
}
}
fh.close();
scanner.close();
}
}
//Myformatter.java
import java.util.Date;
import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.TimeZone;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;
public class Myformatter extends Formatter{
@Override
public String format(LogRecord record) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
formatter.setTimeZone(TimeZone.getTimeZone("GMT+8"));
Date currTime = new Date();
String sDate = new String(formatter.format(currTime));
return "[" + sDate + "]" + "[" + record.getLevel() + "]"
+ record.getLoggerName() +" "+ record.getMessage() + "\n";
}
}
三、SpotBugs
在Help里点Install New Software。
点击Add后输入网址和名称,就可以下载成功了。
首先介绍一下:SpotBugs 是FindBugs的继任者,使用静态分析来查找Java代码中bug。可以帮你分析一些细小的错误。
在Windows的Preferences里可以对检测的代码等级进行调试,这里我们就以默认的15来说好了。数字越大的错误代表是越细微的错误。所以如果你希望自己写的程序能尽可能的准确,可以把等级调大最大,20.
右键选中希望的包或者文件夹,就可以发现错误了。