成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java 日志系列篇一 原生 Java.util.logging

tainzhi / 2002人閱讀

摘要:理解在記錄消息中的日志的不同級(jí)別是非常重要的。通常來(lái)說(shuō),當(dāng)為指定了一個(gè)該會(huì)包含當(dāng)前指定級(jí)別以及更高級(jí)別的日志。,將消息發(fā)送至單個(gè)一般文件或一個(gè)可回滾的文件集合。

本文網(wǎng)大多網(wǎng)絡(luò)整理所得,出處太多,不一一列舉

簡(jiǎn)介

Java 中的 Logging API 讓 Java 應(yīng)用可以記錄不同級(jí)別的信息,它在debug過(guò)程中非常有用,如果系統(tǒng)因?yàn)楦鞣N各樣的原因而崩潰,崩潰原因可以在日志中清晰地追溯,下面讓我們來(lái)看看 Java 原生的 Logging 功能。
從1.4.2開(kāi)始,Java 通過(guò) Java.util.logging 包為應(yīng)用程序提供了記錄消息的可能,在 API 中的核心類為 Logger 類。理解在記錄消息中的日志的不同級(jí)別是非常重要的。Java 為此定時(shí)了8個(gè)級(jí)別,它們是分別SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST 以及 ALL. 它們按照優(yōu)先級(jí)降序排列,在應(yīng)用運(yùn)行的任何時(shí)間點(diǎn),日志級(jí)別可以被更改。
通常來(lái)說(shuō),當(dāng)為 Logger 指定了一個(gè) Level, 該 Logger 會(huì)包含當(dāng)前指定級(jí)別以及更高級(jí)別的日志。舉例而言,如果 Level 被設(shè)置成了 WARNING, 所有的 warning 消息以及 SERVER 消息會(huì)被記錄。應(yīng)用可以用下列方法記錄日志:Logger.warning(), Logger.info(), Logger.config() ...

工作原理和日志處理流程 幾個(gè)重要類的說(shuō)明

Logger 對(duì)外發(fā)布的日志記錄器,應(yīng)用系統(tǒng)可以通過(guò)該對(duì)象完成日志記錄的功能

Level 日志的記錄級(jí)別

LoggingMXBean 接口對(duì)象,對(duì)外發(fā)布的日志管理器

LogRecord 日志信息描述對(duì)象

LoggerManager 日志管理器

Filter 日志過(guò)濾器,接口對(duì)象,在日志被 Handler 處理之前,起過(guò)濾作用

Handler 日志處理器,接口對(duì)象,決定日志的輸出方式

Formatter 日志格式化轉(zhuǎn)換器,接口對(duì)象,決定日志的輸出格式

工作原理

首先通過(guò)LoggerManager進(jìn)行日志框架的初始化,生成Logger的根節(jié)點(diǎn)RootLogger.?這里需要注意的是LoggerManager的初始化工作,并沒(méi)有將構(gòu)建配置文件中所有的日志對(duì)象,而僅僅是構(gòu)建了根節(jié)點(diǎn),這種方式就是我們多例模式中經(jīng)常用到的懶加載,對(duì)象只有在真正被時(shí)候的時(shí)候,再進(jìn)行構(gòu)建。?
通過(guò)Logger.getLogger(String?name)?獲取一個(gè)已有的Logger對(duì)象或者是新建一個(gè)Logger對(duì)象。Logger,日志記錄器,這就是在應(yīng)用程序中需要調(diào)用的對(duì)象了,通過(guò)Logger對(duì)象的一系列l(wèi)og方法,

Logger的大致處理流程


收到應(yīng)用程序的記錄請(qǐng)求,將參數(shù)中的日志信息和運(yùn)行時(shí)的信息構(gòu)建出LogRecord對(duì)象,而后通過(guò)Logger對(duì)象本身設(shè)置的記錄級(jí)別和調(diào)用者傳遞進(jìn)來(lái)的日志級(jí)別,如果傳遞進(jìn)來(lái)的日志級(jí)別低于Logger對(duì)象本身設(shè)置的記錄級(jí)別(從語(yǔ)義上的理解,而實(shí)際上語(yǔ)義級(jí)別越高的級(jí)別其內(nèi)部用數(shù)字表示的標(biāo)志的數(shù)值越?。?,那么Logger對(duì)象將直接返回,因?yàn)樗J(rèn)為這條日志信息,在當(dāng)前運(yùn)行環(huán)境中,沒(méi)有必要記錄。?
?而滿足以上條件的日志信息,將會(huì)通過(guò)Logger對(duì)象的filter元素的過(guò)濾校驗(yàn),filter是動(dòng)態(tài)的,在運(yùn)行時(shí)是可以隨意設(shè)置的,如果有filter對(duì)象,那么將調(diào)用filter對(duì)象,對(duì)日志對(duì)象LogRecord進(jìn)行校驗(yàn),只有校驗(yàn)通過(guò)的LogRecord對(duì)象,才會(huì)繼續(xù)往下執(zhí)行。?
?通過(guò)filter校驗(yàn)后,Logger對(duì)象將依次調(diào)用其配置的處理器,通過(guò)處理器來(lái)真正實(shí)現(xiàn)日志的記錄功能,一個(gè)Logger對(duì)象可以配置多個(gè)處理器handler,所以一條日志記錄可以被多個(gè)處理器處理,同時(shí)Logger對(duì)象的實(shí)現(xiàn)是樹(shù)形結(jié)構(gòu),如果Logger對(duì)象設(shè)置其可以繼承其父節(jié)點(diǎn)的處理器(默認(rèn)),一條日志記錄還會(huì)被其父節(jié)點(diǎn)的Logger對(duì)象處理。??而handler的處理方式就會(huì)是形形色色了,但是歸根節(jié)點(diǎn),會(huì)有以下幾個(gè)大的步驟:?
1.?級(jí)別的判定和比較,決定某條具體的日志記錄是否應(yīng)該繼續(xù)處理?
2.?將日志記錄做格式化處理,以達(dá)到輸出的日志在格式上統(tǒng)一,美觀,可讀性高。?3.?資源的釋放,不管是以何種方式記錄日志,總是會(huì)消耗一些方面的資源,所以
會(huì)涉及到資源的釋放問(wèn)題。比如以文件方式記錄的日志的,在一定的時(shí)候需要做文件關(guān)閉操作,以報(bào)文方式發(fā)送日志的,在和遠(yuǎn)程通話的過(guò)程中,也需要涉及到網(wǎng)絡(luò)IO的關(guān)閉操作,或者是存儲(chǔ)在數(shù)據(jù)庫(kù)等等,資源釋放在程序開(kāi)發(fā)過(guò)程中,是個(gè)不變的主題。

從一個(gè)示例講起
public class TestLogger {
    public static void main(String[] args) {
        Logger log = Logger.getLogger("lavasoft");
        log.info("aaa");
    }
}

console output:
>>> aaa

以上簡(jiǎn)單的代碼背后發(fā)生那些事

LoggerManager 將會(huì)返回一個(gè)新的或者已經(jīng)存在的同名的 Logger , 首先會(huì)查找是否有同名 Logger 被 namedLoggers 維護(hù)有則返回, 但是在我們這個(gè)示例中大多是重新生成一個(gè) Logger,首先 LoggerManager 會(huì)讀取系統(tǒng)配置,設(shè)定一個(gè)默認(rèn)的的 INFO 級(jí)別的 Logger, 然后也許跟其他線程搶到一個(gè) Logger 后返回
tips:
默認(rèn)的Java日志框架將其配置存儲(chǔ)到一個(gè)名為 logging.properties 的文件中。
在這個(gè)文件中,每行是一個(gè)配置項(xiàng),配置項(xiàng)使用點(diǎn)標(biāo)記(dot notation)的形式。
Java在其安裝目錄的lib文件夾下面安裝了一個(gè)全局配置文件,但在啟動(dòng)一個(gè)Java程序時(shí),
你可以通過(guò)指定 java.util.logging.config.file 屬性的方式來(lái)使用一個(gè)多帶帶的日志配置文件,
同樣也可以在個(gè)人項(xiàng)目中創(chuàng)建和存儲(chǔ) logging.properties 文件。


Logger 中召喚 LoggerManager 片段
---------------------------

public static Logger getLogger(String name) {
    LogManager manager = LogManager.getLogManager();
    return manager.demandLogger(name);
}


LoggerManager 中 產(chǎn)生 Logger 的片段
-----------------------------

Logger demandLogger(String name) {
    Logger result = getLogger(name);
    if (result == null) {
        Logger newLogger = new Logger(name, null);
        do {
            if (addLogger(newLogger)) {
                return newLogger;
            }
            result = getLogger(name);
        } while (result == null);
    }
    return result;
}



LoggerManager 中維護(hù)了一個(gè)有繼承關(guān)系的含有弱引用的 LoggerWeakRef
-------------------------------
private Hashtable namedLoggers = new Hashtable<>();

LoggerWeakRef 類結(jié)構(gòu)
-----------------

final class LoggerWeakRef extends WeakReference {
    private String                name;       // for namedLoggers cleanup
    private LogNode               node;       // for loggerRef cleanup
    private WeakReference parentRef;  // for kids cleanup

以上兩者維護(hù)了JVM中弱引用的 Loggers 父子結(jié)構(gòu)

log.info()

Logger 中的 info(String msg) 方法
-----------------------------

   public void info(String msg) {
 if (Level.INFO.intValue() < levelValue) {
     return;
 }
 log(Level.INFO, msg);
   }
   
   上面說(shuō)過(guò)默認(rèn) LoggerManager 產(chǎn)生的 Logger 日志級(jí)別默認(rèn)為 INFO ,所以這里默認(rèn)的
   levelValue 為 Level.INFO.intValue()
   
   如果這里 Level.INFO.intValue() 低于 levelValue 的 , 將 do nothing
   

調(diào)用 log(Level level, String msg) 方法
----------------------------------

   public void log(Level level, String msg) {
 if (level.intValue() < levelValue || levelValue == offValue) {
     return;
 }
 LogRecord lr = new LogRecord(level, msg);
 doLog(lr);
   }
   上面的 log.info 方法只是 log(Level level, String msg) 方法簡(jiǎn)單封裝,在這里日志級(jí)別
   為 Level.OFF.intValue() 也 do nothing  了,否則創(chuàng)建真正的 LogRecord 對(duì)象
   

調(diào)用 doLog(LogRecord lr) 方法
-------------------------
   private void doLog(LogRecord lr) {
 lr.setLoggerName(name);
 String ebname = getEffectiveResourceBundleName();
 if (ebname != null) {
     lr.setResourceBundleName(ebname);
     lr.setResourceBundle(findResourceBundle(ebname));
 }
 log(lr);
   }
   
   getEffectiveResourceBundleName() 將一直上溯查找有效的 resourceBundleName , 有可能返回 null
   

調(diào)用 log(LogRecord lr) 方法
-----------------------
  public void log(LogRecord record) {
 if (record.getLevel().intValue() < levelValue || levelValue == offValue) {
     return;
 }
 Filter theFilter = filter;
 if (theFilter != null && !theFilter.isLoggable(record)) {
     return;
 }

 // Post the LogRecord to all our Handlers, and then to
 // our parents" handlers, all the way up the tree.

 Logger logger = this;
 while (logger != null) {
     for (Handler handler : logger.getHandlers()) {
         handler.publish(record);
     }

     if (!logger.getUseParentHandlers()) {
         break;
     }

     logger = logger.getParent();
 }
   }
 
   在這里我們可以看到了 Filter 與 Handler 的出現(xiàn),我們可以使用 setFilter(Filter newFilter)
   與 addHandler(Handler handler) 來(lái)為 Logger 添加 Filter 與 Handler
   這里我們可以看出在 while 循環(huán)中會(huì)先對(duì)當(dāng)前所有 handler 輸出,在上溯所有父 Logger 所有 Handler
   輸出,至此兩句代碼解析結(jié)束。

話說(shuō) Filter

作為一個(gè)接口, Filter:為所記錄的日志提供日志級(jí)別控制以外的細(xì)粒度控制。

public interface Filter {

    /**
     * Check if a given log record should be published.
     * @param record  a LogRecord
     * @return true if the log record should be published.
     */
    public boolean isLoggable(LogRecord record);

}
我們可以實(shí)現(xiàn)一個(gè) Filter 接口的的對(duì)象來(lái)使用,下面是示例代碼

public class MyFilter implements Filter {
    public boolean isLoggable(LogRecord record) {
        // TODO: 在這里我們可以添加自己的一些邏輯進(jìn)去
        return false;
        // 返回 false 則不被記錄日志, true 則被記錄日志
    }
}

然后我們?yōu)?Logger 對(duì)象設(shè)定 Filter 對(duì)象

Filter filter = new MyFilter();
logger1.setFilter(filter); 

或者我們也可以為 Handler 對(duì)象設(shè)定 Filter 對(duì)象

Filter filter = new MyFilter();
ConsoleHandler consoleHandler = new ConsoleHandler();
consoleHandler.setLevel(Level.ALL);
consoleHandler.setFilter(filter);
話說(shuō) Handler

先上一張 java.util.logging 包中有關(guān) Handler 的類圖

Handler負(fù)責(zé)從Logger中取出日志消息并將消息發(fā)送出去,比如發(fā)送到控制臺(tái)、文件、網(wǎng)絡(luò)上的其他日志服務(wù)或操作系統(tǒng)日志等。
Handler也具有級(jí)別概念,用于判斷當(dāng)前Logger中的消息是否應(yīng)該被發(fā)送出去,可以使用定義好的各種日志級(jí)別(如Level.OFF表示關(guān)閉等)。
除了級(jí)別概念,一個(gè)Handler還可以具有自己的過(guò)濾器(Filter)、格式化器(Formatter)、錯(cuò)誤管理器(ErrorManager)以及編碼字符集等,這些屬性借助LogManager中的配置信息進(jìn)行設(shè)置。
Handler是一個(gè)抽象類,需要根據(jù)實(shí)際情況創(chuàng)建真正使用的具體Handler(如ConsoleHandler、FileHandler等),實(shí)現(xiàn)各自的publish、flush以及close等方法。
對(duì)幾種具體實(shí)現(xiàn) Handler 類的類做簡(jiǎn)單說(shuō)明

MemoryHandler,將當(dāng)前日志信息寫入內(nèi)存緩沖區(qū)中同時(shí)丟棄緩存中以前的內(nèi)容。將內(nèi)存緩沖區(qū)中的信息轉(zhuǎn)發(fā)至另一個(gè)Handler

StreamHandler所有基于I/O流的Handler的基類,將日志信息發(fā)送至給定的java.io.OutputStream中

ConsoleHandler,將消息發(fā)送至System.err(而非System.out),默認(rèn)配置與其父類StreamHandler相同。

FileHandler,將消息發(fā)送至單個(gè)一般文件或一個(gè)可回滾的文件集合??苫貪L文件集中的文件依據(jù)文件大小進(jìn)行回滾,久文件名稱通過(guò)當(dāng)前文件名附加編號(hào)0、1、2等方式依次進(jìn)行標(biāo)示。默認(rèn)情況下日志信息都存放在I/O緩沖中,但如果一條完整的日志信息會(huì)觸發(fā)清空緩沖的動(dòng)作。與其父類StramHandler不同的是,F(xiàn)ileHandler的默認(rèn)格式器是java.util.logging.XMLFormatter:

SocketHandler,負(fù)責(zé)將日志信息發(fā)送至網(wǎng)絡(luò),默認(rèn)情況下也采用java.util.logging.XMLFormatter格式。

關(guān)于 MemoryHandler

MemoryHandler 使用了典型的“注冊(cè) - 通知”的觀察者模式。MemoryHandler 先注冊(cè)到對(duì)自己感興趣的 Logger 中(logger.addHandler(handler)),在這些 Logger 調(diào)用發(fā)布日志的 API:log()、logp()、logrb() 等,遍歷這些 Logger 下綁定的所有 Handlers 時(shí),通知觸發(fā)自身 publish(LogRecord)方法的調(diào)用,將日志寫入 buffer,當(dāng)轉(zhuǎn)儲(chǔ)到下一個(gè)日志發(fā)布平臺(tái)的條件成立,轉(zhuǎn)儲(chǔ)日志并清空 buffer。

這里的 buffer 是 MemoryHandler 自身維護(hù)一個(gè)可自定義大小的循環(huán)緩沖隊(duì)列,來(lái)保存所有運(yùn)行時(shí)觸發(fā)的 Exception 日志條目。同時(shí)在構(gòu)造函數(shù)中要求指定一個(gè) Target Handler,用于承接輸出;在滿足特定 flush buffer 的條件下,如日志條目等級(jí)高于 MemoryHandler 設(shè)定的 push level 等級(jí)(實(shí)例中定義為 SEVERE)等,將日志移交至下一步輸出平臺(tái)。從而形成如下日志轉(zhuǎn)儲(chǔ)輸出鏈:

MemoryHandler 使用方式

以上是記錄產(chǎn)品 Exception 錯(cuò)誤日志,以及如何轉(zhuǎn)儲(chǔ)的 MemoryHandler 處理的內(nèi)部細(xì)節(jié);接下來(lái)給出 MemoryHandler 的一些使用方式。

直接使用 java.util.logging 中的 MemoryHandler

// 在 buffer 中維護(hù) 5 條日志信息
// 僅記錄 Level 大于等于 Warning 的日志條目并
// 刷新 buffer 中的日志條目到 fileHandler 中處理
int bufferSize = 5; 
f = new FileHandler("testMemoryHandler.log"); 
m = new MemoryHandler(f, bufferSize, Level.WARNING); 
myLogger = Logger.getLogger("com.ibm.test"); 
myLogger.addHandler(m); 
myLogger.log(Level.WARNING, “this is a WARNING log”);

自定義(反射)
思考自定義 MyHandler 繼承自 MemoryHandler 的場(chǎng)景,由于無(wú)法直接使用作為父類私有屬性的 size、buffer 及 buffer 中的 cursor,如果在 MyHandler 中有獲取和改變這些屬性的需求,一個(gè)途徑是使用反射。清單 5 展示了使用反射讀取用戶配置并設(shè)置私有屬性。

 int m_size; 
  String sizeString = manager.getProperty(loggerName + ".size"); 
  if (null != sizeString) { 
         try { 
          m_size = Integer.parseInt(sizeString); 
          if (m_size <= 0) { 
             m_size = BUFFER_SIZE; // default 1000 
          } 
 // 通過(guò) java 反射機(jī)制獲取私有屬性
          Field f; 
          f = getClass().getSuperclass().getDeclaredField("size"); 
          f.setAccessible(true); 
          f.setInt(this, m_size); 
          f = getClass().getSuperclass().getDeclaredField("buffer"); 
          f.setAccessible(true); 
          f.set(this, new LogRecord[m_size]); 
         } catch (Exception e) { 
         } 
  }

自定義(重寫)
直接使用反射方便快捷,適用于對(duì)父類私有屬性無(wú)頻繁訪問(wèn)的場(chǎng)景。思考這樣一種場(chǎng)景,默認(rèn)環(huán)形隊(duì)列無(wú)法滿足我們存儲(chǔ)需求,此時(shí)不妨令自定義的 MyMemoryHandler 直接繼承 Handler,直接對(duì)存儲(chǔ)結(jié)構(gòu)進(jìn)行操作,可以通過(guò)清單 6 實(shí)現(xiàn)。

 public class MyMemoryHandler extends Handler{ 
  // 默認(rèn)存儲(chǔ) LogRecord 的緩沖區(qū)容量
  private static final int DEFAULT_SIZE = 1000; 
  // 設(shè)置緩沖區(qū)大小
  private int size = DEFAULT_SIZE; 
  // 設(shè)置緩沖區(qū)
  private LogRecord[] buffer; 
  // 參考 java.util.logging.MemoryHandler 實(shí)現(xiàn)其它部分
  ... 
 }

logging.properties 文件

默認(rèn)的 logging.properties 存放在 jre/lib/logging.properties,截取有效的配置項(xiàng)

handlers= java.util.logging.ConsoleHandler
.level= INFO
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
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
com.xyz.foo.level = SEVERE

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/65349.html

相關(guān)文章

  • Java 日志系列篇二 slf4

    摘要:的橋接器這個(gè)橋接器將所有日志委派給的原生實(shí)現(xiàn),直接實(shí)現(xiàn)了的接口,因此使用與的搭配也暗示了嚴(yán)格的零內(nèi)存計(jì)算溢出未完待補(bǔ)充 起手式 忘了什么時(shí)候聽(tīng)老師說(shuō)過(guò),牛逼的公司只管定義接口,屌絲廠商實(shí)現(xiàn)接口,類似 JDBC 的實(shí)現(xiàn)便是如此,用在 slf4j, 總覺(jué)得有些類似,本來(lái) SUN 有機(jī)會(huì)在需求產(chǎn)生之前設(shè)計(jì)一套漂亮的日志框架來(lái)一統(tǒng)天下,可惜偏偏要拖到 JDK1.4, 而這套原生的日志框架也沒(méi)有...

    maybe_009 評(píng)論0 收藏0
  • Java日志那些事

    摘要:但是考慮到各不相同,所以出現(xiàn)了等日志框架。日志框架只是統(tǒng)一的,其底層的具體的日志記錄工作還是由等承擔(dān)。如何選擇和搭配日志系統(tǒng)目前來(lái)說(shuō),新應(yīng)用使用是首選,一些老系統(tǒng)中很可能使用的是等。所以若日志沖突時(shí),使用的三方庫(kù)只需要相應(yīng)的實(shí)現(xiàn)庫(kù)即可。 日志系統(tǒng)的發(fā)展 我們?nèi)粘=佑|到的日志系統(tǒng)有很多種,log4j,JUL(jdk自帶),logback等,我們可以直接根據(jù)對(duì)象的日志API進(jìn)行使用。但是考...

    GeekQiaQia 評(píng)論0 收藏0
  • Java深入學(xué)習(xí)系列】之那些年我們用過(guò)的日志框架

    摘要:深入學(xué)習(xí)系列三那些年我們用過(guò)的日志框架目前常見(jiàn)的日志框架和中文似乎不太好翻譯有一下幾種即其中,為同一個(gè)作者所寫。如前面所述,在才被引入,在這之前,并沒(méi)有官方的日志庫(kù)供開(kāi)發(fā)者使用。 title: 【Java深入學(xué)習(xí)系列】三. 那些年我們用過(guò)的日志框架date: 2016-10-16 15:32:50 category: java 目前常見(jiàn)的Java日志框架和facades(中文似乎不太好...

    233jl 評(píng)論0 收藏0
  • java日志框架

    摘要:一日志概述領(lǐng)域存在多種日志框架,目前常用的日志框架包括,,,,,。開(kāi)銷更高三與其他日志組件調(diào)用關(guān)系包名說(shuō)明版本的橋接器,你需要將加入。的橋接器,原生日志框架。 一、Java日志概述 java領(lǐng)域存在多種日志框架,目前常用的日志框架包括Log4j 1,Log4j 2,Commons Logging,Slf4j,Logback,Jul。 Commons Logging和Slf4j是日志...

    dendoink 評(píng)論0 收藏0
  • java.util.logging Example(譯)

    摘要:所有低于級(jí)別的消息記錄將會(huì)被忽略。構(gòu)造函數(shù),創(chuàng)建一個(gè)與有關(guān)的構(gòu)造函數(shù),創(chuàng)建一個(gè),記錄消息到指定文件。這個(gè)構(gòu)造函數(shù)用來(lái)創(chuàng)建一個(gè)對(duì)象這個(gè)方法來(lái)自類,通過(guò)它設(shè)置。該對(duì)象是全局的,用來(lái)維護(hù)一組共享狀態(tài)和日志服務(wù)。 原文鏈接原作者:Rohit Joshi譯者:smallclover個(gè)人翻譯,水平有限,如有錯(cuò)誤歡迎指出,謝謝! Jdk Logging 解析 在本文中,我們將討論關(guān)于Java的日志(...

    yzd 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<