!22 添加依赖:添加并引入Slf4j api 与 logback作为项目日志框架,已替换项目内控制台输出,简单封装了日志工具类

Merge pull request !22 from 格物方能致知/master
This commit is contained in:
songdragon 2023-08-23 00:53:06 +00:00 committed by Gitee
commit 1cd41017b2
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
13 changed files with 258 additions and 21 deletions

19
pom.xml
View File

@ -37,7 +37,24 @@
<artifactId>gson</artifactId> <artifactId>gson</artifactId>
<version>2.10.1</version> <version>2.10.1</version>
</dependency> </dependency>
<!--log-->
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.7</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.4.11</version>
</dependency>
<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.11</version>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -1,9 +1,14 @@
module org.jcnc.jnotepad { module org.jcnc.jnotepad {
requires javafx.controls; requires javafx.controls;
// 不知道为什么不加这个日志框架在打包后的程序不起作用会报错
// Exception in thread "JavaFX Application Thread" java.lang.NoClassDefFoundError: javax/naming/NamingException
// 但我打开源代码他们的模块的确有包含这个java.naming这个没懂我干脆自己导入
requires java.naming;
requires atlantafx.base; requires atlantafx.base;
// requires cn.hutool.json;
// requires cn.hutool.core;
requires com.google.gson; requires com.google.gson;
requires org.slf4j;
requires ch.qos.logback.core;
requires ch.qos.logback.classic;
exports org.jcnc.jnotepad; exports org.jcnc.jnotepad;
exports org.jcnc.jnotepad.tool; exports org.jcnc.jnotepad.tool;
exports org.jcnc.jnotepad.Interface; exports org.jcnc.jnotepad.Interface;

View File

@ -70,7 +70,6 @@ public class LunchApp extends Application {
// 初始化菜单项和标签栏 // 初始化菜单项和标签栏
view.initTabPane(); view.initTabPane();
view.initShortcutKey(); view.initShortcutKey();
if (controller.isRelevance()) { if (controller.isRelevance()) {
// 使用线程池加载关联文件并创建文本区域 // 使用线程池加载关联文件并创建文本区域
List<String> rawParameters = getParameters().getRaw(); List<String> rawParameters = getParameters().getRaw();

View File

@ -7,7 +7,6 @@ import javafx.stage.FileChooser;
import org.jcnc.jnotepad.controller.manager.Controller; import org.jcnc.jnotepad.controller.manager.Controller;
import org.jcnc.jnotepad.ui.LineNumberTextArea; import org.jcnc.jnotepad.ui.LineNumberTextArea;
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane; import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
import org.jcnc.jnotepad.view.manager.ViewManager;
import java.io.File; import java.io.File;
@ -26,8 +25,6 @@ public class OpenFile implements EventHandler<ActionEvent> {
*/ */
@Override @Override
public void handle(ActionEvent event) { public void handle(ActionEvent event) {
// 获取ViewManager的实例
ViewManager viewManager = ViewManager.getInstance();
// 获取控制器 // 获取控制器
Controller controller = Controller.getInstance(); Controller controller = Controller.getInstance();
// 创建文件选择器 // 创建文件选择器

View File

@ -4,9 +4,9 @@ import javafx.event.ActionEvent;
import javafx.event.EventHandler; import javafx.event.EventHandler;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
import javafx.stage.FileChooser; import javafx.stage.FileChooser;
import org.jcnc.jnotepad.tool.LogUtil;
import org.jcnc.jnotepad.ui.LineNumberTextArea; import org.jcnc.jnotepad.ui.LineNumberTextArea;
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane; import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
import org.jcnc.jnotepad.view.manager.ViewManager;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.File; import java.io.File;
@ -49,7 +49,7 @@ public class SaveAsFile implements EventHandler<ActionEvent> {
selectedTab.setText(file.getName()); // 更新Tab页标签上的文件名 selectedTab.setText(file.getName()); // 更新Tab页标签上的文件名
selectedTab.setUserData(file); // 将文件对象保存到Tab页的UserData中 selectedTab.setUserData(file); // 将文件对象保存到Tab页的UserData中
} catch (IOException ignored) { } catch (IOException ignored) {
System.out.println("已忽视IO异常!"); LogUtil.info("已忽视IO异常!",this.getClass());
} }
} }
} }

View File

@ -11,6 +11,7 @@ import org.jcnc.jnotepad.controller.event.handler.NewFile;
import org.jcnc.jnotepad.controller.event.handler.OpenFile; import org.jcnc.jnotepad.controller.event.handler.OpenFile;
import org.jcnc.jnotepad.controller.event.handler.SaveAsFile; import org.jcnc.jnotepad.controller.event.handler.SaveAsFile;
import org.jcnc.jnotepad.tool.EncodingDetector; import org.jcnc.jnotepad.tool.EncodingDetector;
import org.jcnc.jnotepad.tool.LogUtil;
import org.jcnc.jnotepad.ui.LineNumberTextArea; import org.jcnc.jnotepad.ui.LineNumberTextArea;
import org.jcnc.jnotepad.ui.tab.JNotepadTab; import org.jcnc.jnotepad.ui.tab.JNotepadTab;
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane; import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
@ -98,9 +99,9 @@ public class Controller implements ControllerInterface {
if (file != null) { if (file != null) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) { try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
writer.write(newValue); writer.write(newValue);
System.out.println("正在自动保存---"); LogUtil.info("正在自动保存---",this.getClass());
} catch (IOException ignored) { } catch (IOException ignored) {
System.out.println("已忽视IO异常!"); LogUtil.info("已忽视IO异常!",this.getClass());
} }
} }
} }
@ -152,7 +153,6 @@ public class Controller implements ControllerInterface {
*/ */
@Override @Override
public void getText(File file) { public void getText(File file) {
ViewManager viewManager = ViewManager.getInstance();
LineNumberTextArea textArea = createNewTextArea(); LineNumberTextArea textArea = createNewTextArea();
try (BufferedReader reader = new BufferedReader(new FileReader(file))) { try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
StringBuilder textBuilder = new StringBuilder(); StringBuilder textBuilder = new StringBuilder();
@ -173,7 +173,7 @@ public class Controller implements ControllerInterface {
autoSave(textArea); autoSave(textArea);
}); });
} catch (IOException ignored) { } catch (IOException ignored) {
System.out.println("已忽视IO异常!"); LogUtil.info("已忽视IO异常!",this.getClass());
} }
} }

View File

@ -6,6 +6,7 @@ import com.google.gson.reflect.TypeToken;
import javafx.scene.control.MenuItem; import javafx.scene.control.MenuItem;
import javafx.scene.input.KeyCombination; import javafx.scene.input.KeyCombination;
import org.jcnc.jnotepad.Interface.ShortcutKeyInterface; import org.jcnc.jnotepad.Interface.ShortcutKeyInterface;
import org.jcnc.jnotepad.tool.LogUtil;
import org.jcnc.jnotepad.ui.menu.JNotepadMenuBar; import org.jcnc.jnotepad.ui.menu.JNotepadMenuBar;
import java.io.*; import java.io.*;
@ -33,7 +34,7 @@ public class ShortcutKey implements ShortcutKeyInterface {
jsonData.append(line); jsonData.append(line);
} }
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); LogUtil.error("读取配置失败!",e,this.getClass());
} }
} else { } else {
// todo new InputStreamReader(inputStream) 实参 'inputStream' 可能为null // todo new InputStreamReader(inputStream) 实参 'inputStream' 可能为null
@ -43,7 +44,7 @@ public class ShortcutKey implements ShortcutKeyInterface {
jsonData.append(line); jsonData.append(line);
} }
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); LogUtil.error("读取配置失败!",e,this.getClass());
} }
} }

View File

@ -0,0 +1,12 @@
package org.jcnc.jnotepad.exception;
/**
* 应用异常类
*
* @author gewuyou
*/
public class AppException extends RuntimeException {
public AppException(String message) {
super(message);
}
}

View File

@ -1,6 +1,7 @@
package org.jcnc.jnotepad.tool; package org.jcnc.jnotepad.tool;
import javafx.application.Platform;
import org.jcnc.jnotepad.ui.LineNumberTextArea; import org.jcnc.jnotepad.ui.LineNumberTextArea;
import java.nio.charset.Charset; import java.nio.charset.Charset;
@ -36,7 +37,7 @@ public class EncodingDetector {
// 尝试常见的编码 // 尝试常见的编码
for (Charset charset : commonCharsets()) { for (Charset charset : commonCharsets()) {
if (isValidEncoding(text, charset)) { if (isValidEncoding(text, charset)) {
System.out.println("编码监测结果:" + isValidEncoding(text, charset)); Platform.runLater(()-> LogUtil.info("编码监测结果:" + isValidEncoding(text, charset),EncodingDetector.class));
return charset.name(); return charset.name();
} }
} }

View File

@ -30,7 +30,7 @@ public class FileUtil {
jsonStr = sb.toString(); jsonStr = sb.toString();
return jsonStr; return jsonStr;
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); LogUtil.error("读取配置失败!",e,FileUtil.class);
return null; return null;
} }
} }

View File

@ -0,0 +1,85 @@
package org.jcnc.jnotepad.tool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 日志工具<br>注意使用该工具的方法时如果需要在JavaFx项目中调用日志请使用Platform.runLater()调用
*
* @author gewuyou
*/
public class LogUtil {
private LogUtil() {
}
/**
* 获取日志类
*
* @param currentClass 所要记录的类
* @return org.apache.logging.log4j.Logger 日志对象
* @apiNote 传入当前需要记录的类返回记录该类的日志类也可直接使用工具类定义好的方法也可调用这个方法自定义
* @see LogUtil
*/
public static Logger getLogger(Class<?> currentClass) {
return LoggerFactory.getLogger(currentClass);
}
/**
* 日志信息打印
*
* @param message 日志信息
* @param currentClass 所要记录的类
* @apiNote 传入当前需要记录的类方便知晓是哪个位置记录的日志
*/
public static void info(String message, Class<?> currentClass) {
getLogger(currentClass).info(message);
}
/**
* 日志排错信息打印
*
* @param message 日志信息
* @param currentClass 所要记录的类
* @apiNote 传入当前需要记录的类方便知晓是哪个位置记录的日志
*/
public static void debug(String message, Class<?> currentClass) {
getLogger(currentClass).debug(message);
}
/**
* 日志警告信息打印
*
* @param message 日志信息
* @param currentClass 所要记录的类
* @apiNote 传入当前需要记录的类方便知晓是哪个位置记录的日志
*/
public static void warn(String message, Class<?> currentClass) {
getLogger(currentClass).warn(message);
}
/**
* 日志错误信息打印
*
* @param message 日志信息
* @param currentClass 所要记录的类
* @apiNote 传入当前需要记录的类方便知晓是哪个位置记录的日志
*/
public static void error(String message, Class<?> currentClass) {
getLogger(currentClass).error(message);
}
/**
* 日志错误信息打印
*
* @param message 日志信息
* @param throwable 抛出的异常
* @param currentClass 所要记录的类
* @apiNote 这个方法用来弥补当抛出异常或手动抛出异常时无法捕捉到所抛异常
*/
public static void error(String message, Throwable throwable, Class<?> currentClass) {
getLogger(currentClass).error(message, throwable);
}
}

View File

@ -5,6 +5,7 @@ import javafx.scene.Scene;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane; import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox; import javafx.scene.layout.HBox;
import org.jcnc.jnotepad.exception.AppException;
import org.jcnc.jnotepad.ui.menu.JNotepadMenuBar; import org.jcnc.jnotepad.ui.menu.JNotepadMenuBar;
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane; import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
@ -35,8 +36,6 @@ public class ViewManager {
private static ViewManager instance = null; private static ViewManager instance = null;
public Label getEnCodingLabel() { public Label getEnCodingLabel() {
return enCodingLabel; return enCodingLabel;
} }
@ -47,7 +46,6 @@ public class ViewManager {
* @return int 标签页索引 * @return int 标签页索引
* @apiNote ++tabIndex * @apiNote ++tabIndex
*/ */
public int selfIncreaseAndGetTabIndex() { public int selfIncreaseAndGetTabIndex() {
return ++tabIndex; return ++tabIndex;
} }
@ -83,7 +81,7 @@ public class ViewManager {
if (instance != null) { if (instance != null) {
return instance; return instance;
} else { } else {
throw new RuntimeException("ViewManager的实例未初始化!"); throw new AppException("ViewManager的实例未初始化!");
} }
} }

View File

@ -0,0 +1,122 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- scan属性未true时如果配置文档发生改变将会进行重新加载 -->
<!-- scanPeriod属性设置监测配置文件修改的时间间隔默认单位为毫秒在scan为true时才生效 -->
<!-- debug属性如果为true时会打印出logback内部的日志信息 -->
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 定义参数常量 -->
<!-- 日志级别TRACE<DEBUG<INFO<WARN<ERROR其中常用的是DEBUG、INFO和ERROR -->
<property name="log.level" value="debug"/>
<!-- 文件保留时间 -->
<property name="log.maxHistory" value="30"/>
<!-- 日志存储路径 -->
<property name="log.filePath" value="logs"/>
<!-- 日志的显式格式 -->
<property name="log.pattern"
value="时间:[%d{yyyy-MM-dd HH:mm:ss.SSS}] 线程:[%thread] 日志级别:[%-5level] 调用位置:[%logger{50} [%L]] - 日志信息:[%msg]%n">
</property>
<!-- 用于说明输出介质,此处说明控制台输出 -->
<appender name="consoleAppender"
class="ch.qos.logback.core.ConsoleAppender">
<!-- 类似于layout除了将时间转化为数组还会将转换后的数组输出到相应的文件中 -->
<encoder>
<!-- 定义日志的输出格式 -->
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- DEBUG表示文件随着时间的推移按时间生成日志文件 -->
<appender name="debugAppender"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 文件路径 -->
<file>${log.filePath}/debug.log</file>
<!-- 滚动策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 设置文件名称 -->
<fileNamePattern>
${log.filePath}/debug/debug.%d{yyyy-MM-dd}.log.gz
</fileNamePattern>
<!-- 设置最大保存周期 -->
<MaxHistory>${log.maxHistory}</MaxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<!-- 过滤器,过滤掉不是指定日志水平的日志 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 设置日志级别 -->
<level>DEBUG</level>
<!-- 如果跟该日志水平相匹配,则接受 -->
<onMatch>ACCEPT</onMatch>
<!-- 如果跟该日志水平不匹配,则过滤掉 -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- INFO表示文件随着时间的推移按时间生成日志文件 -->
<appender name="infoAppender"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 文件路径 -->
<file>${log.filePath}/info.log</file>
<!-- 滚动策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 设置文件名称 -->
<fileNamePattern>
${log.filePath}/info/info.%d{yyyy-MM-dd}.log.gz
</fileNamePattern>
<!-- 设置最大保存周期 -->
<MaxHistory>${log.maxHistory}</MaxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<!-- 过滤器,过滤掉不是指定日志水平的日志 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 设置日志级别 -->
<level>INFO</level>
<!-- 如果跟该日志水平相匹配,则接受 -->
<onMatch>ACCEPT</onMatch>
<!-- 如果跟该日志水平不匹配,则过滤掉 -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- ERROR表示文件随着时间的推移按时间生成日志文件 -->
<appender name="errorAppender"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 文件路径 -->
<file>${log.filePath}/error.log</file>
<!-- 滚动策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 设置文件名称 -->
<fileNamePattern>
${log.filePath}/error/error.%d{yyyy-MM-dd}.log.gz
</fileNamePattern>
<!-- 设置最大保存周期 -->
<MaxHistory>${log.maxHistory}</MaxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<!-- 过滤器,过滤掉不是指定日志水平的日志 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 设置日志级别 -->
<level>ERROR</level>
<!-- 如果跟该日志水平相匹配,则接受 -->
<onMatch>ACCEPT</onMatch>
<!-- 如果跟该日志水平不匹配,则过滤掉 -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 用于存放日志对象同时指定关联的package位置 -->
<!-- name指定关联的package -->
<!-- level表明指记录哪个日志级别以上的日志 -->
<!-- appender-ref指定logger向哪个文件输出日志信息 -->
<!-- additivity为true时logger会把根logger的日志输出地址加入进来但logger水平不依赖于根logger -->
<logger name="org.jcnc.jnotepad" level="${log.level}" additivity="true">
<appender-ref ref="debugAppender"/>
<appender-ref ref="infoAppender"/>
<appender-ref ref="errorAppender"/>
</logger>
<!-- 特殊的logger根logger -->
<root lever="info">
<!-- 指定默认的日志输出 -->
<appender-ref ref="consoleAppender"/>
</root>
</configuration>