精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

開源日志庫Logger的剖析

開源
上一篇介紹了開源日志庫Logger的使用,今天主要來分析Logger實現的原理。

上一篇介紹了開源日志庫Logger的使用,今天主要來分析Logger實現的原理。

庫的整體架構圖

 詳細剖析

我們從使用的角度來對Logger庫抽繭剝絲:

  1. String userName = "Jerry"
  2. Logger.i(userName);  

看看Logger.i()這個方法: 

  1. public static void i(String message, Object... args) {       
  2.     printer.i(message, args); 
  3.  

還有個可變參數,來看看printer.i(message, args)是啥:

  1. public Interface Printer{ 
  2.     void i(String message, Object... args); 

 是個接口,那我們就要找到這個接口的實現類,找到printer對象在Logger類中聲明的地方: 

  1. private static Printer printer = new LoggerPrinter(); 

實現類是LoggerPrinter,而且這還是個靜態的成員變量,這個靜態是有用處的,后面會講到,那就繼續跟蹤LoggerPrinter類的i(String message, Object... args)方法的實現: 

  1. @Override public void i(String message, Object... args) {   
  2.     log(INFO, null, message, args); 
  3. /**  
  4. * This method is synchronized in order to avoid messy of logs' order.  
  5. */ 
  6. private synchronized void log(int priority, Throwable throwable, String msg, Object... args) { 
  7.     // 判斷當前設置的日志級別,為NONE則不打印日志   
  8.     if (settings.getLogLevel() == LogLevel.NONE) {     
  9.         return;   
  10.     } 
  11.     // 獲取tag 
  12.     String tag = getTag();  
  13.     // 創建打印的消息 
  14.     String message = createMessage(msg, args);       
  15.     // 打印 
  16.     log(priority, tag, message, throwable); 
  17.  
  18. public enum LogLevel {   
  19.     /**    
  20.     * Prints all logs    
  21.     */   
  22.     FULL,   
  23.     /**    
  24.     * No log will be printed    
  25.     */   
  26.     NONE 
  27.  
  • 首先,log方法是一個線程安全的同步方法,為了防止日志打印時候順序的錯亂,在多線程環境下,這是非常有必要的。
  • 其次,判斷日志配置的打印級別,FULL打印全部日志,NONE不打印日志。
  • 再來,getTag(): 
    1. private final ThreadLocal<String> localTag = new ThreadLocal<>(); 
    2. /**  
    3. * @return the appropriate tag based on local or global */ 
    4. private String getTag() {   
    5.     // 從ThreadLocal<String> localTag里獲取本地一個緩存的tag 
    6.     String tag = localTag.get();   
    7.     if (tag != null) {     
    8.         localTag.remove();     
    9.         return tag;   
    10.     }   
    11.     return this.tag; 
    12.  

這個方法是獲取本地或者全局的tag值,當localTag中有tag的時候就返回出去,并且清空localTag的值,關于ThreadLocal還不是很清楚的可以參考主席的文章:http://blog.csdn.net/singwhat...

接著,createMessage方法: 

  1. private String createMessage(String message, Object... args) {  
  2.     return args == null || args.length == 0 ? message : String.format(message, args); 

 這里就很清楚了,為什么我們用Logger.i(message, args)的時候沒有寫args,也就是null,也可以打印,而且是直接打印的message消息的原因。同樣博主上一篇文章也提到了: 

  1. Logger.i("博主今年才%d,英文名是%s", 16, "Jerry"); 

像這樣的可以拼接不同格式的數據的打印日志,原來實現的方式是用String.format方法,這個想必小伙伴們在開發Android應用的時候String.xml里的動態字符占位符用的也不少,應該很容易理解這個format方法的用法。

重頭戲,我們把tag,打印級別,打印的消息處理好了,接下來該打印出來了: 

  1. @Override public synchronized void log(int priority, String tag, String message, Throwable throwable) { 
  2.     // 同樣判斷一次庫配置的打印開關,為NONE則不打印日志 
  3.     if (settings.getLogLevel() == LogLevel.NONE) {     
  4.         return;   
  5.     } 
  6.     // 異常和消息不為空的時候,獲取異常的原因轉換成字符串后拼接到打印的消息中   
  7.     if (throwable != null && message != null) {     
  8.         message += " : " + Helper.getStackTraceString(throwable);   
  9.     }   
  10.     if (throwable != null && message == null) {     
  11.         message = Helper.getStackTraceString(throwable);   
  12.     }   
  13.     if (message == null) {     
  14.         message = "No message/exception is set";   
  15.     }   
  16.     // 獲取方法數 
  17.     int methodCount = getMethodCount();  
  18.     // 判斷消息是否為空  
  19.     if (Helper.isEmpty(message)) {     
  20.         message = "Empty/NULL log message";   
  21.     }   
  22.     // 打印日志體的上邊界 
  23.     logTopBorder(priority, tag); 
  24.     // 打印日志體的頭部內容   
  25.     logHeaderContent(priority, tag, methodCount);   
  26.     //get bytes of message with system's default charset (which is UTF-8 for Android)   
  27.     byte[] bytes = message.getBytes();   
  28.     int length = bytes.length;   
  29.     // 消息字節長度小于等于4000 
  30.     if (length <= CHUNK_SIZE) {     
  31.         if (methodCount > 0) {   
  32.             // 方法數大于0,打印出分割線     
  33.             logDivider(priority, tag);     
  34.         }     
  35.         // 打印消息內容 
  36.         logContent(priority, tag, message); 
  37.         // 打印日志體底部邊界 
  38.         logBottomBorder(priority, tag);     
  39.         return;   
  40.     }   
  41.     if (methodCount > 0) {     
  42.         logDivider(priority, tag);   
  43.     }   
  44.     for (int i = 0; i < length; i += CHUNK_SIZE) {     
  45.         int count = Math.min(length - i, CHUNK_SIZE); 
  46.         //create a new String with system's default charset (which is UTF-8 for Android)     
  47.         logContent(priority, tag, new String(bytes, i, count));   
  48.     }   
  49.     logBottomBorder(priority, tag); 

 我們重點來看看logHeaderContent方法和logContent方法: 

  1. @SuppressWarnings("StringBufferReplaceableByString"
  2. private void logHeaderContent(int logType, String tag, int methodCount) {   
  3.   // 獲取當前線程堆棧跟蹤元素數組 
  4.   //(里面存儲了虛擬機調用的方法的一些信息:方法名、類名、調用此方法在文件中的行數) 
  5.   // 這也是這個庫的 “核心” 
  6.   StackTraceElement[] trace = Thread.currentThread().getStackTrace(); 
  7.   // 判斷庫的配置是否顯示線程信息   
  8.   if (settings.isShowThreadInfo()) { 
  9.       // 獲取當前線程的名稱,并且打印出來,然后打印分割線     
  10.       logChunk(logType, tag, HORIZONTAL_DOUBLE_LINE + "Thread: " + Thread.currentThread().getName());    logDivider(logType, tag);   
  11.   }   
  12.   String level = "";   
  13.   // 獲取追蹤棧的方法起始位置 
  14.   int stackOffset = getStackOffset(trace) + settings.getMethodOffset();   
  15.   //corresponding method count with the current stack may exceeds the stack trace. Trims the count   
  16.   // 打印追蹤的方法數超過了當前線程能夠追蹤的方法數,總的追蹤方法數扣除偏移量(從調用日志的起算扣除的方法數),就是需要打印的方法數量 
  17.   if (methodCount + stackOffset > trace.length) {     
  18.       methodCount = trace.length - stackOffset - 1;   
  19.   }   
  20.   for (int i = methodCount; i > 0; i--) {    
  21.       int stackIndex = i + stackOffset;     
  22.       if (stackIndex >= trace.length) {       
  23.           continue;     
  24.       }     
  25.       // 拼接方法堆棧調用路徑追蹤字符串 
  26.       StringBuilder builder = new StringBuilder();  
  27.       builder.append("║ ")         
  28.       .append(level)      
  29.       .append(getSimpleClassName(trace[stackIndex].getClassName()))  // 追蹤到的類名 
  30.       .append(".")  
  31.       .append(trace[stackIndex].getMethodName())  // 追蹤到的方法名       
  32.       .append(" ")         
  33.       .append(" (")        
  34.       .append(trace[stackIndex].getFileName()) // 方法所在的文件名 
  35.       .append(":")         
  36.       .append(trace[stackIndex].getLineNumber())  // 在文件中的行號       
  37.       .append(")");     
  38.       level += "   ";     
  39.       // 打印出頭部信息 
  40.       logChunk(logType, tag, builder.toString());  
  41.   } 

 接下來看logContent方法: 

  1. private void logContent(int logType, String tag, String chunk) {   
  2.     // 這個作用就是獲取換行符數組,getProperty方法獲取的就是"\\n"的意思 
  3.     String[] lines = chunk.split(System.getProperty("line.separator"));   
  4.     for (String line : lines) {     
  5.         // 打印出包含換行符的內容 
  6.         logChunk(logType, tag, HORIZONTAL_DOUBLE_LINE + " " + line);   
  7.     } 

 如上圖來說內容是字符串數組,本身里面是沒用換行符的,所以不需要換行,打印出來的效果就是一行,但是json、xml這樣的格式是有換行符的,所以打印呈現出來的效果就是:

 上面說了大半天,都還沒看到具體的打印是啥,現在來看看logChunk方法: 

  1. private void logChunk(int logType, String tag, String chunk) { 
  2.     // ***格式化下tag   
  3.     String finalTag = formatTag(tag);   
  4.     // 根據不同的日志打印類型,然后交給LogAdapter這個接口來打印 
  5.     switch (logType) {     
  6.         case ERROR:       
  7.             settings.getLogAdapter().e(finalTag, chunk);       
  8.         break;     
  9.         case INFO:       
  10.             settings.getLogAdapter().i(finalTag, chunk);       
  11.         break;     
  12.         case VERBOSE:       
  13.             settings.getLogAdapter().v(finalTag, chunk);       
  14.         break;     
  15.         case WARN:       
  16.             settings.getLogAdapter().w(finalTag, chunk);       
  17.         break;    
  18.         case ASSERT:       
  19.             settings.getLogAdapter().wtf(finalTag, chunk);       
  20.         break;     
  21.         case DEBUG:       
  22.             // Fall through, log debug by default     
  23.         default:             
  24.             settings.getLogAdapter().d(finalTag, chunk);       
  25.         break;   
  26.     } 
  27.  

這個方法很簡單,就是***格式化tag,然后根據不同的日志類型把打印的工作交給LogAdapter接口來處理,我們來看看settings.getLogAdapter()這個方法(Settings.java文件): 

  1. public LogAdapter getLogAdapter() {   
  2.     if (logAdapter == null) { 
  3.         // 最終的實現類是AndroidLogAdapter 
  4.         logAdapter = new AndroidLogAdapter();   
  5.     }   
  6.     return logAdapter; 
  7.  

找到AndroidLogAdapter類:

 原來繞了一大圈,最終打印還是使用了:系統的Log。

好了Logger日志框架的源碼解析完了,有沒有更清晰呢,也許小伙伴會說這個最終的日志打印,我不想用系統的Log,是不是可以換呢。這是自然的,看開篇的那種整體架構圖,這個LogAdapter是個接口,只要實現這個接口,里面做你自己想要打印的方式,然后通過Settings 的logAdapter(LogAdapter logAdapter)方法設置進去就可以。

以上就是博主分析一個開源庫的思路,從使用的角度出發抽繭剝絲,基本上一個庫的核心部分都能搞懂。畫畫整個框架的大概類圖,對分析庫非常有幫助,每一個輪子都有值得學習的地方,吸收了就是進步的開始,耐心的分析完一個庫,還是非常有成就感的。

感謝你耐心看完,以后博主還會繼續努力分析其它輪子的。

責任編輯:龐桂玉 來源: segmentfault
相關推薦

2016-09-22 19:31:30

開源日志庫Logger

2012-12-03 10:44:00

開源

2012-07-10 16:22:01

開源架構

2010-02-05 15:33:29

Android JDK

2010-02-04 11:05:56

ibmdw虛擬化

2009-10-28 13:44:40

linux庫文件路徑

2019-11-27 14:41:50

Java技術語言

2019-04-22 15:40:33

2010-02-03 11:26:28

2010-04-21 11:43:33

Oracle數據庫

2010-01-07 18:03:03

Linux動態庫

2019-01-30 18:00:21

開源Python庫

2024-10-23 16:06:50

2018-09-27 11:25:07

開源日志聚合

2021-08-10 08:52:15

微軟GCToolkit工具

2010-05-31 17:56:27

2009-06-05 09:45:44

Struts優缺點開源

2016-12-06 10:39:54

剖析建模開源工具

2010-05-20 18:05:38

2010-04-12 15:17:40

dump Oracle
點贊
收藏

51CTO技術棧公眾號

飘雪影院手机免费高清版在线观看| 免费黄色在线视频| 宅男在线观看免费高清网站| 99久久免费国产| 国产精品久久色| 久久嫩草捆绑紧缚| 红杏视频成人| 欧美日韩国产综合久久| 国产日韩亚洲欧美在线| 在线观看美女网站大全免费| 国产成人精品免费一区二区| 欧美重口另类videos人妖| 91麻豆精品成人一区二区| 韩国精品福利一区二区三区| 欧美日韩国产另类不卡| 国产偷国产偷亚洲清高网站| 午夜精品理论片| 人妻一区二区视频| 999国产精品一区| 欧美性高清videossexo| 男人添女人下部高潮视频在观看| 日韩大片在线永久免费观看网站| 成人动漫视频在线| 91日韩在线视频| 亚洲成人av影片| 尹人成人综合网| www.久久撸.com| 一区二区黄色片| 加勒比中文字幕精品| 欧美一区二区免费| 最近中文字幕一区二区| 97成人资源| 性久久久久久久| 日韩一级特黄毛片| 久草中文在线观看| 中文字幕欧美激情一区| 免费成人看片网址| 亚洲人妻一区二区| 成人性视频免费网站| 99视频国产精品免费观看| 亚洲一区 中文字幕| 日韩中文字幕不卡| 日本一区二区在线免费播放| 日韩在线观看第一页| 欧美二区视频| 超薄丝袜一区二区| 久久久久久久久久97| 欧美电影免费| 日韩图片一区| 亚洲一区二区成人在线观看| 国产对白在线播放| 黄网站在线播放| 中文字幕永久在线不卡| 影音先锋欧美资源| 黄网站免费在线播放| √…a在线天堂一区| 亚洲砖区区免费| 黄色网址在线免费播放| 成人欧美一区二区三区小说| 艳母动漫在线免费观看| 黄色网址在线免费观看| 亚洲精品国产一区二区精华液 | 亚洲国产精品三区| 欧美韩国日本| 91精品国产麻豆| 性一交一黄一片| youjizz亚洲| 亚洲精品久久久久久下一站 | 九色精品国产蝌蚪| 亚洲视频日韩精品| 91无套直看片红桃在线观看| 国产精品久久久久久影院8一贰佰 国产精品久久久久久麻豆一区软件 | 国产成人手机在线| 91丨国产丨九色丨pron| 日韩av电影免费观看| 日本免费视频在线观看| 亚洲日本韩国一区| 91精品国产91久久久久麻豆 主演| 国产精品99久久久久久成人| 成人亚洲性情网站www在线观看| 久久精品免费在线观看| 在线不卡日本| 丰满的护士2在线观看高清| 欧美色视频日本高清在线观看| 国产淫片av片久久久久久| 国产精品蜜月aⅴ在线| 日韩视频123| 国产精品毛片一区二区| 97精品中文字幕| 欧美精品第一页在线播放| 一二三区免费视频| 国产精品一区免费在线观看| 国产欧美日韩一区二区三区| 九九热视频在线观看| 亚洲图片激情小说| 能在线观看的av| 亚洲美女色播| 日韩理论片久久| 天天色影综合网| 亚洲欧美卡通另类91av| 成人福利网站在线观看11| 污污网站免费在线观看| 国产精品免费aⅴ片在线观看| 国产日韩欧美精品在线观看| 国产精品xxx| 日韩av在线网| 国产精品三区在线观看| 性色一区二区三区| 99久久国产免费免费| a黄色在线观看| 亚洲va韩国va欧美va| 久热在线视频观看| 美女久久99| 97精品在线观看| 草逼视频免费看| 国产精品久久久久影院亚瑟| 男人揉女人奶房视频60分| 亚洲一区二区免费在线观看| 日韩有码在线播放| 日韩精品一区不卡| www.欧美.com| 亚洲精品无码国产| 欧美黄色一级| 久久精品国产精品| 亚洲中文无码av在线| 99国产精品一区| 欧美高清中文字幕| 国产精品成人**免费视频| 中文字幕九色91在线| 国产伦精品一区二区三区视频网站| 粉嫩蜜臀av国产精品网站| 中文字幕乱码免费| 在线观看亚洲精品福利片| 在线看国产精品| 国产美女www| 久久久777精品电影网影网| 少妇人妻大乳在线视频| 操欧美女人视频| 欧美尺度大的性做爰视频| 国产女人高潮的av毛片| 国产精品视频麻豆| wwwwwxxxx日本| 日韩在线理论| 国产日韩中文字幕| 麻豆视频在线| 91精品国产乱码| 免费在线观看h片| 国产毛片精品视频| 日韩在线视频在线| 草莓视频一区二区三区| 午夜精品福利电影| 亚洲免费国产视频| 亚洲成人免费观看| 最近日本中文字幕| 性高湖久久久久久久久| 日本一区二区在线视频| 欧美三级网址| www国产精品视频| 国产三级小视频| 亚洲午夜三级在线| 四虎永久免费影院| 日韩精品国产欧美| 永久域名在线精品| 97久久综合精品久久久综合| 久久久久五月天| 日韩a级作爱片一二三区免费观看| 色婷婷久久99综合精品jk白丝 | 亚洲自拍都市欧美小说| 国产精品成人免费视频| 欧美成人性生活视频| 欧美一二三四区在线| 日韩欧美三级在线观看| 久久久久久一级片| www.se五月| 国内综合精品午夜久久资源| 麻豆传媒一区| 四虎视频在线精品免费网址| 欧美日韩999| 欧美视频综合| 91精品国产一区二区| 国产精品第一页在线观看| 国产日韩精品视频一区| 下面一进一出好爽视频| 久久久噜噜噜| 日韩精品第1页| 神马香蕉久久| 91最新国产视频| 天堂av中文在线观看| 精品国偷自产在线视频99| 日韩一级在线播放| 欧美精品亚洲一区二区在线播放| 国产一级特黄aaa大片| 国产精品久久久久久久裸模| 野战少妇38p| 蜜臀av性久久久久蜜臀aⅴ流畅 | 日韩视频永久免费| 日本视频免费观看| 亚洲自拍欧美精品| 国产三级aaa| 97精品视频在线观看自产线路二| 污片在线免费看| 中文精品在线| 亚洲高潮无码久久| 成人激情电影在线| 精品一区二区三区自拍图片区| 成人全视频免费观看在线看| 91sa在线看| 成人影院在线看| 中文字幕一精品亚洲无线一区| 欧洲av在线播放| 91精品国产综合久久久久久漫画| 日韩在线播放中文字幕| 亚洲一二三四在线观看| 国产精品理论在线| 久久久久免费观看| 国产肉体xxxx裸体784大胆| 夫妻av一区二区| 一级片黄色免费| 六月丁香婷婷久久| 午夜激情福利在线| 亚洲永久免费| 久在线观看视频| 尹人成人综合网| 日韩a级黄色片| 自拍日韩欧美| 精品久久免费观看| 久久综合99| 亚洲春色在线视频| 欧美一区二区三区高清视频| 乱色588欧美| 天天做夜夜做人人爱精品| 国产麻豆一区二区三区在线观看| 国产一区一区| 91情侣偷在线精品国产| 91国产精品| 成人综合网网址| 成人污污视频| 99热国产免费| 综合中文字幕| 国产美女精品久久久| 国产精品久av福利在线观看| 99c视频在线| av综合网页| 国产视频一区二区三区四区| 久久成人福利| 久久久久久国产精品一区| 欧美大胆视频| 欧美一区二视频在线免费观看| 你懂的一区二区三区| 日韩成人在线资源| 成人av动漫在线观看| 中文字幕日韩一区二区三区不卡 | 久久好看免费视频| 黄黄的网站在线观看| 欧美国产乱视频| 91白丝在线| 国产成人啪精品视频免费网| 日韩三区免费| 成人午夜一级二级三级| 麻豆视频久久| 精品一区二区国产| 欧美日韩国产高清电影| 一本久道久久综合狠狠爱亚洲精品| 国产国产精品| 国产a级黄色大片| 一本久久综合| 美女少妇一区二区| 粉嫩aⅴ一区二区三区四区| 天天插天天射天天干| 国产日产欧美一区| 日韩激情综合网| 亚洲第一搞黄网站| 无码久久精品国产亚洲av影片| 欧美精品一二三四| 五月天丁香视频| 最近更新的2019中文字幕| fc2ppv国产精品久久| 91国偷自产一区二区三区的观看方式| 欧洲一级精品| http;//www.99re视频| 国产永久精品大片wwwapp| 婷婷视频在线播放| 香蕉国产精品偷在线观看不卡| 91极品视频在线观看| www.亚洲在线| 啪啪一区二区三区| 亚洲成a人片综合在线| 中文天堂在线资源| 精品精品欲导航| sese一区| 97婷婷大伊香蕉精品视频| 久久久久毛片| 久久久久久草| 欧美涩涩网站| 男女视频在线看| 91一区二区三区在线观看| 97在线观看免费高| 都市激情亚洲色图| 精品久久久无码中文字幕| 亚洲人成自拍网站| 678在线观看视频| 成人黄色生活片| 精品国产乱码久久久久久蜜坠欲下 | 色鬼7777久久| 欧美老女人xx| 亚洲资源在线| 日韩hmxxxx| 免费日韩视频| 国产一卡二卡三卡四卡| 综合激情成人伊人| www.五月婷婷.com| 亚洲精品国产综合久久| 欧美xxxx少妇| 成人免费看片视频| 精品久久久亚洲| 能在线观看的av| 成人av影院在线| 麻豆一区产品精品蜜桃的特点| 欧美三区在线观看| 国产高清一级毛片在线不卡| 91av国产在线| 欧美久久香蕉| 欧美成人三级在线视频| 丁香网亚洲国际| 久久久久亚洲AV成人| 91.麻豆视频| 日本在线免费中文字幕| 国产精品久久久久91| 久久成人高清| 少妇高清精品毛片在线视频| 97精品国产97久久久久久久久久久久| 免费一级特黄特色大片| 日韩欧美国产综合在线一区二区三区 | 少妇一级淫片日本| 亚洲天堂av在线免费| 欧美日韩成人影院| 亚洲7777| 精品中文字幕一区二区| 乱老熟女一区二区三区| 在线综合视频播放| 粗大黑人巨茎大战欧美成人| 91在线|亚洲| 午夜日韩av| 91视频在线免费| 亚洲va韩国va欧美va| 日韩av成人| 国产成人在线视频| 日韩国产欧美一区二区| 三级av免费观看| 自拍av一区二区三区| 精品人妻一区二区三区麻豆91 | 午夜精品成人av| 日韩成人在线资源| 久久激情综合网| 成人高潮免费视频| 欧美va在线播放| 蜜桃视频在线网站| 日韩精品在在线一区二区中文| 日韩电影免费在线看| 熟女少妇a性色生活片毛片| 91麻豆精品国产自产在线观看一区| 欧美日韩xx| 丁香婷婷久久久综合精品国产| 亚洲日本欧美| 亚洲人成人无码网www国产| 欧美日韩国产小视频| 超碰porn在线| 精品国产一区二区三区免费| 丝袜亚洲另类欧美| 国产极品美女在线| 亚洲国产精品一区二区久| 欧美大胆性生话| 强伦女教师2:伦理在线观看| 懂色av一区二区三区免费观看| 在线观看亚洲天堂| 日韩中文字幕亚洲| 福利在线一区| 亚洲高清免费在线观看| 亚洲一区二区四区蜜桃| 精品亚洲综合| 7777精品伊久久久大香线蕉语言| 午夜在线一区| 日本福利片在线观看| 精品呦交小u女在线| 高清一区二区中文字幕| 欧美日韩在线一| 中文字幕亚洲在| 亚洲色图21p| 亚洲已满18点击进入在线看片 | 国产精欧美一区二区三区白种人| 亚洲国产婷婷综合在线精品| 免费日韩中文字幕| 四虎成人av| 国产精品无码专区| 欧美精品视频www在线观看| 理论不卡电影大全神| 免费观看黄色的网站| 久久综合九色综合97_久久久| va视频在线观看| 国产精品 欧美在线|