Java练习(四):Logger日志系统(.ini, .propertites, .html日志的读写)

目录

1. 要求

1.1 设计一个日志系统,能实现对不同格式日志的读写(.ini, .properties, .html)

1.2 实现效果

2. 思路

3. 代码设计

3.1 IFile类:接口

3.2 入口类:ReportEntry 和 MyMain

3.3 (重头戏!!!)HTML日志相关的类:HtmlFile, HtmlReportFormatter, HtmlUtil, RecordStore

3.4 INI日志相关的类: IniFile

3.5 Properties日志相关的类: PropertiesFile


1. 要求

1.1 设计一个日志系统,能实现对不同格式日志的读写(.ini, .properties, .html)

1.2 实现效果

2. 思路

(1)设计一个接口IFile,接口中声明多个方法:创建/读/写/关闭日志

(2)针对每种日志,设计不同的类,继承接口IFile, 根据不同日志的特性,重写接口中的方法

(3)定义报告入口类,根据Main类传进来的日志名称的后缀,创建不同的日志类的对象 (这一步类似于策略模式?)。对象再调用其所属的类的方法,来实现不同的读写等功能。

(4)日志系统的Main类,程序入口。

(5)相关工具/资料:

IDEA2020, 相关jar包(如果在maven工程中完成,则配置好pom.xml即可)

demo_report_style.css(提前准备好的html报告的样式文件)

html报告的一个模板(用于获取一些现成的前端的设计代码,在重写formatter方法时直接使用)

3. 代码设计

项目代码结构如下图

3.1 IFile类:接口

public interface IFile {
    void createLog(String p_info); //创建日志文件

    void write(String p_info);//1参数
    void write(String p_info1, String p_info2);//2参数,例如properties文件,key和value
    void write(String p_info1, String p_info2, String p_info3);//3参数,例如ini文件,section,key和value

    String read();//读文件全部内容
    String read(String p_info);//比如:读properties文件文件,通过key读value
    String read(String p_info1, String p_info2);//比如:读ini文件,通过section、key读value

    void closeLog(); //关闭日志文件
}

3.2 入口类:ReportEntry 和 MyMain

(1)ReportEntry类

public class ReportEntry {
    IFile myFile;    //声明接口

    //根据入参进来的文件后缀,判断生成哪种日志对象,然后调用对应的"创建文件"方法
    public void createLog(String p_file){
        if(p_file.endsWith(".ini")){ //如果要处理的是ini日志文件,则new一个IniFile类的对象
            myFile = new IniFile();
        }else if(p_file.endsWith(".properties")){ //同上,处理properties
            myFile = new PropertiesFile();
        }else if(p_file.endsWith(".html")){  //同上,处理html
            myFile = new HtmlFile();
        }else if(p_file.endsWith(".txt")){  //同上,处理txt
            myFile = new TxtFile();
        }else if(p_file.endsWith(".log")){  同上,处理log
            myFile = new LogFile();
        }else {
            myFile = null;
        }

        if(myFile != null){
            myFile.createLog(p_file); //调用日志对象的"创建文件"方法
        }else {
            System.out.println("不支持的文件类型");
            System.exit(0); //退出程序
        }

    }

    //调用日志对象的"写文件"方法
    public void write(String p_info){
        myFile.write(p_info);
    }

    public void write(String p_info1, String p_info2){
        myFile.write(p_info1, p_info2);
    }

    public void write(String p_info1, String p_info2, String p_info3){
        myFile.write(p_info1, p_info2, p_info3);
    }

    //调用日志对象的"读文件"方法
    public String read(String p_key){
        return myFile.read(p_key).toString();
    }

    public String read(String p_section, String p_key){
        return myFile.read(p_section, p_key);
    }

    //调用日志对象的"关闭文件"方法
    public void closeLog(){
        myFile.closeLog();
    }
}

(2)MyMain类

public class MyMain {
    
public static void main(String[] args) {

        ReportEntry re=new ReportEntry();

        //ini日志
        re.createLog("C:/log/config1.ini");
        re.write("URL", "url","www.google.com");
        System.out.println(re.read("URL", "url"));
        re.closeLog();

        //properties日志
        re.createLog("C:/log/config2.properties");
        re.write("url", "www.163.com");
        re.write("user", "Sheryl");
        System.out.println(re.read("url"));
        System.out.println(re.read("user"));
        re.closeLog();

        //html日志,会另外生成hmtl文件,在浏览器中打开,所以这里就不调用read
        re.createLog("C:/log/config3.html");
        re.write("testcase1", "nice","good");
        re.closeLog();

    }
}

3.3 (重头戏!!!)HTML日志相关的类:HtmlFile, HtmlReportFormatter, HtmlUtil, RecordStore

(1)HtmlFile类

public class HtmlFile implements IFile {
    private Logger logger = Logger.getLogger(HtmlFile.class.getName());
    private FileHandler fileHTML;

    //带两个参数的创建日志的方法,新方法,非重写
    public void createLog(String p_logName, boolean p_append){
        try {
            fileHTML = new FileHandler(p_logName, p_append);
        } catch (IOException e) {
            e.printStackTrace();
        }
        fileHTML.setFormatter(new HtmlReportFormatter()); //调用格式设置方法,传格式设置的文件实例
        logger.addHandler(fileHTML);
    }

    //带一个参数的创建日志的方法,重写
    @Override
    public void createLog(String p_logName) {
        try {
            fileHTML = new FileHandler(p_logName);
        } catch (IOException e) {
            e.printStackTrace();
        }
        fileHTML.setFormatter(new HtmlReportFormatter());
        logger.addHandler(fileHTML);
    }

    //带一个参数的写日志的方法,重写
    @Override
    public void write(String p_info) {
        logger.info(p_info);
    }

    //带二个参数的写日志的方法,重写
    @Override
    public void write(String p_info, String p_result) {
        RecordStore.result = p_result;
        logger.info(p_info);
    }

    //带三个参数的写日志的方法,重写
    @Override
    public void write(String p_info, String p_expected, String p_actual) {
        RecordStore.actual = p_actual;
        RecordStore.expected = p_expected;

        if(p_expected.equals(p_actual)){
            RecordStore.result = "Pass";
        }else {
            RecordStore.result = "Fail";
        }

        logger.info(p_info);
    }

    @Override
    public String read() {
        return null;
    }

    @Override
    public String read(String p_info) {
        return null;
    }

    @Override
    public String read(String p_info1, String p_info2) {
        return null;
    }

    @Override
    public void closeLog() {
        fileHTML.close();
        RecordStore.p_pass = 0;
        RecordStore.p_fail = 0;
        RecordStore.result = "";
        RecordStore.expected = "";
        RecordStore.actual = "";
    }
}

(2)HtmlReportFormatter类

public class HtmlReportFormatter extends Formatter {
    private int i = 0;
    private long setStartTime;
    private long setEndTime;

    private final String HTML_HEADER = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">"
            + "<html xmlns=\"http://www.w3.org/1999/xhtml\"><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">"
            + "<META HTTP-EQUIV=\"CACHE-CONTROL\" CONTENT=\"NO-CACHE\">"
            + "<META HTTP-EQUIV=\"PRAGMA\" CONTENT=\"NO-CACHE\">"
            + "<link rel=\"stylesheet\" href=\"demo_report_style.css\"/>"
            + "<html><head><title>测试报告</title></head>"
            + "<body>"
            + "<div class=\"page_title\"><center>"
            + "<h1>测试报告</h1></center></div>"
            + "<div class=\"statistics\"><table id=\"statistics_table\" class=\"sortable\" align=\"center\" border=\"0\"  style=\"width:100%;\"><tr>"
            + "<th><b>序号</b></th>"
            + "<th><b>用例描述</b></th>"
            + "<th><b>期待结果</b></th>"
            + "<th><b>实际结果</b></th>"
            + "<th><b>执行时间</b></th>" + "<th><b>状态</b></th>" + "</tr>";

    private int recordStep(){
        i = i + 1;
        return i;
    }

    @Override
    public String format(LogRecord record) {
        StringBuffer buf = new StringBuffer(1000);
        // Bold any levels >= WARNING
        buf.append("<div class=\"statistics\">");
        buf.append("<tr>");
        buf.append("<td>");
        buf.append(recordStep());
        buf.append("</td>");
        buf.append("<td>");
        buf.append(formatMessage(record));  //Formatter自带的方法
        buf.append('\n');
        buf.append("</td>");
        buf.append("<td>");
        buf.append(RecordStore.expected);
        buf.append("</td>");
        buf.append("<td>");
        buf.append(RecordStore.actual);
        buf.append("</td>");
        buf.append("<td>");
        buf.append(com.report.html.HtmlUtil.getCalcDate(record.getMillis()));
        buf.append("</td>");
        buf.append("<td>");
        if (RecordStore.result.matches("Pass")||RecordStore.result.matches("PASS")) {
            RecordStore.p_pass = RecordStore.p_pass + 1;
            buf.append("<b>");
            buf.append("<font color=Green>");
            buf.append(RecordStore.result);
            buf.append("</font>");
            buf.append("</b>");
        } else if (RecordStore.result.matches("Fail")||RecordStore.result.matches("FAIL")) {
            RecordStore.p_fail = RecordStore.p_fail + 1;
            buf.append("<b>");
            buf.append("<font color=Red>");
            buf.append(RecordStore.result);
            buf.append("</font>");
            buf.append("</b>");
        }
        else{
            buf.append("<b>");
            // buf.append("<font color=Black>");
            buf.append("");
            buf.append("</b>");
        }

        buf.append("</td>");
        buf.append("</tr>");
        buf.append("</div>\n");

        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return buf.toString();
    }

    public String getHead(Handler h){
        this.setStartTime = System.currentTimeMillis();
        System.out.println("starttime: " + this.setStartTime);
        return HTML_HEADER;
    }

    public String getTail(Handler h){
        this.setEndTime = System.currentTimeMillis();
        System.out.println("endtime: " + this.setEndTime);

        String HTML_Tail;
        int p_total = RecordStore.p_pass + RecordStore.p_fail;
        if (p_total > 0)
            if (RecordStore.p_fail > 0)
                HTML_Tail = "</table></PRE>" + "<br>&nbsp;开始时间   :" + HtmlUtil.getCalcDate(this.setStartTime)
                        + "<br>&nbsp;结束时间      :"+ HtmlUtil.getCalcDate(this.setEndTime)
                        + "<br>&nbsp;运行时间      :"+ HtmlUtil.getDeltaTime(this.setEndTime, this.setStartTime)
                        + "<br>&nbsp;执行用例      :" + p_total
                        +"<br>&nbsp;用例成功         :"+ RecordStore.p_pass
                        + "<br>&nbsp;<font color=Red>用例失败      :"+ RecordStore.p_fail + "</font>"
                        + "<br>&nbsp;成功率(%) :"+ HtmlUtil.getPercnet(RecordStore.p_pass, p_total)
                        + "<br>&nbsp;<font color=Red>失败率(%) :"+ HtmlUtil.getPercnet(RecordStore.p_fail, p_total) + "</font>"
                        + "<br><br>"
                        + "</BODY></HTML>";
            else
                HTML_Tail = "</table></PRE>" + "<br>&nbsp;开始时间   :" + HtmlUtil.getCalcDate(this.setStartTime)
                        + "<br>&nbsp;结束时间   :" + HtmlUtil.getCalcDate(this.setEndTime)
                        + "<br>&nbsp;运行时间   :" + HtmlUtil.getDeltaTime(this.setEndTime, this.setStartTime)
                        + "<br>&nbsp;执行用例      :" + p_total
                        + "<br>&nbsp;用例成功      :"+ RecordStore.p_pass
                        + "<br>&nbsp;用例失败      :" + RecordStore.p_fail
                        + "<br>&nbsp;成功率(%) :" + HtmlUtil.getPercnet(RecordStore.p_pass, p_total)
                        + "<br>&nbsp;失败率(%) :" + HtmlUtil.getPercnet(RecordStore.p_fail, p_total)
                        + "<br><br>"
                        + "</BODY></HTML>";
        else
            HTML_Tail = "</table></PRE>" + "<br>&nbsp;用例执行异常!" + "<br><br>"
                    + "</BODY></HTML>";

        return HTML_Tail;

    }
}

(3)HtmlUtil类

public class HtmlUtil {
    
    public static String getPercnet(double p_numerator, double p_denominator) {
        double percent = p_numerator / p_denominator;
        NumberFormat nt = NumberFormat.getPercentInstance();
        // 设置百分数精确度2即保留两位小数
        nt.setMinimumFractionDigits(1);
        return nt.format(percent);
    }

    public static String getCalcDate(long millisecs) {
        SimpleDateFormat date_format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date resultdate = new Date(millisecs);
        return date_format.format(resultdate);
    }

    public static String formatCurrentTime(){
        SimpleDateFormat date_format = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
        Date resultdate = new Date(System.currentTimeMillis());
        return date_format.format(resultdate);
    }

    public static String getDeltaTime(long p_startTime, long p_endTime) {
        long day = (p_endTime - p_startTime) / (24 * 60 * 60 * 1000);
        long hour = ((p_endTime - p_startTime) / (60 * 60 * 1000) - day * 24);
        long min = (((p_endTime - p_startTime) / (60 * 1000)) - day * 24 * 60 - hour * 60);
        long s = ((p_endTime - p_startTime) / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);

        return day + "天" + hour + "小时" + min + "分" + s + "秒";
    }

    public static void sleep(int p_time){
        try {
            Thread.sleep(p_time*1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

(4)RecordStore类

public class RecordStore {
    static int i = 0; //记录步骤数目
    static  int p_pass=0; // Pass用例的个数
    static  int p_fail=0; // Fail用例的个数
    static  String result=""; // case结果
    static  Object expected=""; // 期待值
    static  Object actual=""; // 实际值
}

3.4 INI日志相关的类: IniFile

(1) IniFile类

public class IniFile implements IFile {
    private String fileName = null;
    HierarchicalINIConfiguration ini = null;

    @Override
    public void createLog(String p_fileName) {
        this.fileName = p_fileName;
        File file = new File(this.fileName);
        if(!file.exists()){
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {
            ini = new HierarchicalINIConfiguration(this.fileName);
            ini.load(new File(this.fileName)); //到这一步,文件已存在,这里导入需要的ini文件
        } catch (ConfigurationException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void write(String p_info) {
    }

    @Override
    public void write(String p_info1, String p_info2) {
    }

    @Override
    public void write(String section, String key, String value) {
        ini.setProperty(section + "." + key, value); //注意格式
    }

    @Override
    public String read() {
        return null;
    }

    @Override
    public String read(String p_info) {
        return null;
    }

    @Override
    public String read(String section, String key) {
        return ini.getString(section + "." + key);
    }

    @Override
    public void closeLog() {
        try {
            ini.save();
        } catch (ConfigurationException e) {
            e.printStackTrace();
        }
        this.fileName = null;
        this.ini = null;
    }
}

3.5 Properties日志相关的类: PropertiesFile

(1) Properties类

public class PropertiesFile implements IFile {
    File file;
    String filePath = null;
    PropertiesConfiguration config = new PropertiesConfiguration();

    @Override
    public void createLog(String p_filePath) {
        this.filePath = p_filePath;
        file = new File(this.filePath);
        if(!file.exists()){
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        try {
            config.load(new File(this.filePath)); // 此时文件已经存在,导入需要的properties文件
        } catch (ConfigurationException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void write(String p_info) {
    }

    @Override
    public void write(String p_key, String p_value) {
        config.setProperty(p_key, p_value);
    }

    @Override
    public void write(String p_info1, String p_info2, String p_info3) {
    }

    @Override
    public String read() {
        return null;
    }

    @Override
    public String read(String p_key) {
        return config.getProperty(p_key).toString();
    }

    @Override
    public String read(String p_info1, String p_info2) {
        return null;
    }

    @Override
    public void closeLog() {
        File f = new File(this.filePath);
        try {
            config.save(f);
        } catch (ConfigurationException e) {
            e.printStackTrace();
        }
        this.file = null;
        this.config = null;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值