成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

Tomcat的Logging內(nèi)部實(shí)現(xiàn)方式是什么

今天就跟大家聊聊有關(guān)Tomcat的Logging內(nèi)部實(shí)現(xiàn)方式是什么,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

“只有客戶發(fā)展了,才有我們的生存與發(fā)展!”這是創(chuàng)新互聯(lián)公司的服務(wù)宗旨!把網(wǎng)站當(dāng)作互聯(lián)網(wǎng)產(chǎn)品,產(chǎn)品思維更注重全局思維、需求分析和迭代思維,在網(wǎng)站建設(shè)中就是為了建設(shè)一個(gè)不僅審美在線,而且實(shí)用性極高的網(wǎng)站。創(chuàng)新互聯(lián)對(duì)成都做網(wǎng)站、網(wǎng)站建設(shè)、網(wǎng)站制作、網(wǎng)站開發(fā)、網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站優(yōu)化、網(wǎng)絡(luò)推廣、探索永無(wú)止境。

Tomcat的Logging實(shí)現(xiàn),是通過(guò)JDK的Log,并重寫了其Log的Handler來(lái)輸出內(nèi)容的。

下面將分析在Tomcat內(nèi)部Log的實(shí)現(xiàn),并深入源碼,了解其根據(jù)配置,創(chuàng)建

Handler等一系列過(guò)程。

初始化

Tomcat的Main-Class是BootStrap這個(gè)類,而Log的初始化也是從這個(gè)類的初始化開始的,由于BootStrap類中有如下聲明:

private static final Log log = LogFactory.getLog(Bootstrap.class)

所以在類實(shí)例化時(shí),這一字段也被初始化。

從LogFactory的工廠方法開始

public Log getInstance(String name) {
   if (discoveredLogConstructor == null) {
       return DirectJDKLog.getInstance(name);
   }
  return discoveredLogConstructor.newInstance(name);

默認(rèn)情況,Tomcat使用的是DirectJDKLog,因此,后續(xù)的過(guò)程都交給了

DirectJDKLog來(lái)處理。該類內(nèi)部則是直接對(duì)JDK的logging調(diào)用

public DirectJDKLog(String name ) {
   logger=Logger.getLogger(name);
}

而整個(gè)Logger其實(shí)還是會(huì)交給一個(gè)LogManager來(lái)管理,上一篇文章中我們也看到Tomcat也指定了自定義的LogManager,

這個(gè)類是ClassLoaderLogManager。

在Logger獲取LogManager的過(guò)程中,就會(huì)涉及到讀取logging.properties的過(guò)程,此時(shí)由于ClassLoaderLogManager繼承了LogManager,這個(gè)readConfiguration方法由子類實(shí)現(xiàn)了,此時(shí)Tomcat的自定義讀取方式如下:

URL logConfig = ((URLClassLoader)classLoader).findResource("logging.properties");

即在當(dāng)前的classLoader中查找名為logging.properties的資源。如果當(dāng)前classLoader中不存在會(huì)使用JDK自帶的logging.properties,找到文件之后,會(huì)直接把這個(gè)properties文件load進(jìn)來(lái),之后對(duì)文件中的properties解析。

如同下面的代碼,我們看到解析handlers,同時(shí)會(huì)解析自定義的帶有prefix的handler。

// Create handlers for the root logger of this classloader
String rootHandlers = info.props.getProperty(".handlers");
String handlers = info.props.getProperty("handlers");
Logger localRootLogger = info.rootNode.logger;
if (handlers != null) {
   StringTokenizer tok = new StringTokenizer(handlers, ",");
   while (tok.hasMoreTokens()) {
       String handlerName = (tok.nextToken().trim());
       String handlerClassName = handlerName;
       String prefix = "";
       if (handlerClassName.length() <= 0) {
           continue;
       }
     if (Character.isDigit(handlerClassName.charAt(0))) {
           int pos = handlerClassName.indexOf('.');
           if (pos >= 0) {
               prefix = handlerClassName.substring(0, pos + 1);
               handlerClassName = handlerClassName.substring(pos + 1);}}
       try {
           this.prefix.set(prefix);
           Handler handler =
               (Handler) classLoader.loadClass(handlerClassName).newInstance(); //解析prefix和handlerClass后設(shè)置,在newInstance后,其實(shí)執(zhí)行了許多操作,包含設(shè)置和初始化具體的Handler,打開輸出流等。上篇文章提到的設(shè)置Log文件的操作就在這一步。
           this.prefix.set(null);
           info.handlers.put(handlerName, handler);
           if (rootHandlers == null) {
               localRootLogger.addHandler(handler);} //解析完畢后,將handler和logger綁定。
       } catch (Exception e) {}

而在loadClass(handlerClassName).newInstance中,還有比較關(guān)鍵的一個(gè)地方,在初始化AsynFileHandler時(shí),類內(nèi)初始化的代碼包含這樣兩行

protected static final LoggerThread logger = new LoggerThread();
static {
   logger.start();
}

這個(gè)Logger線程,則會(huì)在后面不停止的處理log,其run方法是這個(gè)樣子:

while (run) {
   try {
       LogEntry entry = queue.poll(LOGGER_SLEEP_TIME, TimeUnit.MILLISECONDS);//log出隊(duì)列
       if (entry!=null) entry.flush();
   } catch (InterruptedException x) {
       // Ignore the attempt to interrupt the thread.
   } catch (Exception x) {
       x.printStackTrace();
   }
}
 

記一個(gè)Log

而我們一般在記錄log時(shí),會(huì)直接使用log.info(xxx)這種形式,Tomcat內(nèi)部也是這樣的。

例如要用log記一個(gè)log.warn,這個(gè)時(shí)候,調(diào)用執(zhí)行的代碼是這樣一個(gè)過(guò)程:

首先會(huì)調(diào)用到上面提到的DirectJDKLog中,其對(duì)應(yīng)的方法會(huì)設(shè)置Log的Level等,方法是這個(gè)樣子:

public final void warn(Object message) {
   log(Level.WARNING, String.valueOf(message), null);
}

這行代碼,會(huì)調(diào)用到Logger中的如下代碼,會(huì)根據(jù)配置的Handler來(lái)進(jìn)行l(wèi)og輸出

for (Handler handler : loggerHandlers) {
   handler.publish(record);
}

我們定義的Handler中包含F(xiàn)ileHandler和ConsoleHandler,這個(gè)時(shí)候,F(xiàn)ileHandler的publish方法執(zhí)行的操作是將Log添加到一個(gè)阻塞隊(duì)列中,即上面的LogThread在wait的隊(duì)列,

public void publish(LogRecord record) {
  LogEntry entry = new LogEntry(record,this);
   boolean added = false;
   try {
       while (!added && !queue.offer(entry)) {...}

logThread在queue不為空時(shí),會(huì)輸出LogEntry。

我們看,這個(gè)輸出Log的具體操作方式如下,會(huì)使用到上一篇文章提到的Formatter,

public void publish(LogRecord record) {
   Timestamp ts = new Timestamp(System.currentTimeMillis());
   String tsString = ts.toString().substring(0, 19);
   String tsDate = tsString.substring(0, 10);

   try {
       // If the date has changed, switch log files
       if (rotatable && !date.equals(tsDate)) {
           try {
               // Make sure another thread hasn't already done this
               if (!date.equals(tsDate)) {
                   closeWriter();
                   date = tsDate;
                   openWriter();
               }}}

       String result = null;
       result = getFormatter().format(record); //格式化,注意
         if (writer!=null) {
               writer.write(result); //這里使用初始化時(shí)創(chuàng)建的Writer
               if (bufferSize < 0) {
                   writer.flush();
               }

看完上述內(nèi)容,你們對(duì)Tomcat的Logging內(nèi)部實(shí)現(xiàn)方式是什么有進(jìn)一步的了解嗎?如果還想了解更多知識(shí)或者相關(guān)內(nèi)容,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。

新聞名稱:Tomcat的Logging內(nèi)部實(shí)現(xiàn)方式是什么
文章來(lái)源:http://jinyejixie.com/article22/ppjdcc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站營(yíng)銷網(wǎng)站制作、網(wǎng)站導(dǎo)航、標(biāo)簽優(yōu)化、自適應(yīng)網(wǎng)站、域名注冊(cè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站建設(shè)