当前位置:   article > 正文

Logback快速实践_ch.qos.logback.core.rolling

ch.qos.logback.core.rolling

java中如何使用logback

pom.xml中引入关键的两个包

  1. <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-core -->
  2. <dependency>
  3. <groupId>ch.qos.logback</groupId>
  4. <artifactId>logback-core</artifactId>
  5. <version>1.2.3</version>
  6. </dependency>
  7. <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
  8. <dependency>
  9. <groupId>ch.qos.logback</groupId>
  10. <artifactId>logback-classic</artifactId>
  11. <version>1.2.3</version>
  12. <scope>test</scope>
  13. </dependency>

然后在resources目录下创建一个logback.xml就可以了,请参考全量的可用配置文件这个章节


日志级别

推荐使用以下几种,级别从高到低排列

Level描述
ERROR错误事件可能仍然允许应用程序继续运行
WARN指定具有潜在危害的情况
INFO指定能够突出在粗粒度级别的应用程序运行情况的信息的消息
DEBUG指定细粒度信息事件是最有用的应用程序调试

Appender级别

What is an Appender?

Appender class dependency

 

appender

 

ConsoleAppender (将日志输出到控制台)

将日志信息打印在控制台中

配置类型描述
encoderEncoder日志输出格式
targetString日志输出目标,可以是System.out或者System.err,默认是System.out
withJansiboolean默认是false,这个使用不到,好像是开启后输出的ANSI会有颜色,具体看官网介绍

sample:

  1. <configuration>
  2. <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
  3. <!-- encoders are assigned the type
  4. ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
  5. <encoder>
  6. <pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
  7. </encoder>
  8. </appender>
  9. <root level="DEBUG">
  10. <appender-ref ref="STDOUT" />
  11. </root>
  12. </configuration>

FileAppender(将日志输出到文件中)

FileAppender OutputStreamAppender的子类,将日志输出到指定文件中。如果文件已经存在,根据配置属性来判断在末尾追加或者重新生成文件

配置类型描述
appendboolean默认为true,会将日志追加到现有文件末尾
encoderEncoder日志输出格式
fileString文件名,可以带路径,如不过文件或目录不存在则会创建,例如: logs/info.log,该属性没有默认值
immediateFlushboolean一旦有日志产生立即刷新到文件,通过情况下把它设为false,以提高性能,因为会频繁的flush buffer;

sample:

  1. <configuration>
  2. <!-- 使用时间戳作为文件名 -->
  3. <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/>
  4. <appender name="FILE" class="ch.qos.logback.core.FileAppender">
  5. <file>testFile-${bySecond}.log</file>
  6. <append>true</append>
  7. <!-- set immediateFlush to false for much higher logging throughput -->
  8. <immediateFlush>true</immediateFlush>
  9. <!-- encoders are assigned the type
  10. ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
  11. <encoder>
  12. <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
  13. </encoder>
  14. </appender>
  15. <root level="DEBUG">
  16. <appender-ref ref="FILE" />
  17. </root>
  18. </configuration>

RollingFileAppender(滚动式输出)

RollingFileAppender继承于FileAppender, 按照一些特定策略生成滚动文件,例如与TimeBasedRollingPolicy策略搭配时,当文件到达指定时间,会重新生成一个新的文件,关于策略,后面章节会有具体详细介绍。

配置类型描述
appendboolean看FileAppender配置
encoderEncoder看FileAppender配置
fileString看FileAppender配置
rollingPolicyRollingPolicy日志滚动策略:配置这个选项会让日志文件按照指定策略进行滚动
triggeringPolicyTriggeringPolicy触发滚动策略:通常搭配rollingPolicy一起使用,用于设置滚动的触发条件

sample:

  1. <appender name="errorAppender" class="ch.qos.logback.core.RollingFileAppender">
  2. <file>logs/error.log</file>
  3. <!-- 设置滚动策略 TimeBasedRollingPolicy 按日期滚动 -->
  4. <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
  5. <!--设置日志命名模式-->
  6. <fileNamePattern>errorFile.%d{yyyy-MM-dd}.log</fileNamePattern>
  7. <!--最多保留30天log-->
  8. <maxHistory>30</maxHistory>
  9. </rollingPolicy>
  10. <!-- 超过150MB时,立即触发滚动策略,生成新的文件 -->
  11. <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
  12. <maxFileSize>150</maxFileSize>
  13. </triggeringPolicy>
  14. <encoder>
  15. <pattern>%d [%p] %-5level %logger - %msg%newline</pattern>
  16. </encoder>
  17. </appender>

日志文件策略 *Policy(常用)

TimeBasedRollingPolicy(按日期滚动策略)

TimeBasedRollingPolicy 可能是logback最受欢迎的滚动策略,基于时间的滚动,可以是一天也可以是一个月,这个较为常用,通常我们可以设置一天生成一个新的文件,很好归纳,统计

配置类型描述
fileNamePatternStringlog文件命名规则,通常使用%d来按天或按月输出,例如errorFile.%d{yyyy-MM-dd}.log,生成出来的文件类似于errorFile.2018-10-09.log,带上日期后这样每天生成的文件就不会名字重复了,这个还支持选择时区,例如%d{yyyy-MM-dd,UTC}
maxHistoryint日志保留天数,超过该天数的历史日志文件将会被logback异步删除
totalSizeCapint归档文件的总大小,优先应用maxHistory的策略。
cleanHistoryOnStartboolean默认为false,触发归档文件立即删除的动作。

滚动输出支持自动压缩,文件名以.gz或者.zip结尾即可,例如:/wombat/foo.%d.gz

sample:

  1. <configuration>
  2. <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
  3. <file>logFile.log</file>
  4. <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
  5. <!-- daily rollover -->
  6. <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>
  7. <!-- keep 30 days' worth of history capped at 3GB total size -->
  8. <maxHistory>30</maxHistory>
  9. <totalSizeCap>3GB</totalSizeCap>
  10. </rollingPolicy>
  11. <encoder>
  12. <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
  13. </encoder>
  14. </appender>
  15. <root level="DEBUG">
  16. <appender-ref ref="FILE" />
  17. </root>
  18. </configuration>

SizeAndTimeBasedRollingPolicy(按大小和时间滚动策略)

这个应该是最常用的吧,按照指定时间和文件大小的策略来滚动日志。废话不多说看下面的例子

  1. <configuration>
  2. <appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
  3. <file>mylog.txt</file>
  4. <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
  5. <!-- rollover daily -->
  6. <fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
  7. <!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
  8. <maxFileSize>100MB</maxFileSize>
  9. <maxHistory>60</maxHistory>
  10. <totalSizeCap>20GB</totalSizeCap>
  11. </rollingPolicy>
  12. <encoder>
  13. <pattern>%msg%n</pattern>
  14. </encoder>
  15. </appender>
  16. <root level="DEBUG">
  17. <appender-ref ref="ROLLING" />
  18. </root>
  19. </configuration>

请注意除“%d”之外的“%i”转换标记。 %i%d令牌都是强制性的。 每当当前日志文件在当前时间段结束之前达到maxFileSize时,它将以增加的索引存档,从0开始


FixedWindowRollingPolicy(以固定的算法策略生成滚动文件 不常用)

这个策略不常用,咱就不多bb了,属性和其他滚动策略是一样的,通常文件命名规范是这样的:tests.%i.log,当到达条件触发滚动时会生成文件test1.log,test2.log,test3.log ...


SizeBasedTriggeringPolicy(根据大小触发滚动的策略)

这个标签里的配置,用来触发滚动时间的,例如文件大小到了指定值,就是触发滚动

sample:

  1. <configuration>
  2. <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
  3. <file>test.log</file>
  4. <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
  5. <fileNamePattern>test.%i.log.zip</fileNamePattern>
  6. <minIndex>1</minIndex>
  7. <maxIndex>3</maxIndex>
  8. </rollingPolicy>
  9. <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
  10. <maxFileSize>5MB</maxFileSize>
  11. </triggeringPolicy>
  12. <encoder>
  13. <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
  14. </encoder>
  15. </appender>
  16. <root level="DEBUG">
  17. <appender-ref ref="FILE" />
  18. </root>
  19. </configuration>

fileNamePatten的一些规则(例子,按年,月,日,天,时,分,秒滚动)

例子描述
/wombat/foo.%d按天滚动,格式 年-月-日,都生成在一个文件夹中
/wombat/%d{yyyy/MM}/foo.txt按月滚动,每个月生成一个相同的文件,在不同的月份文件夹中,例如first: /wombat/2018/09/foo.txt,next: /wombat/2018/10/foo.txt
/wombat/foo.%d{yyyy-ww}.log每周生成一次,每周的第一天开始重新生成
/wombat/foo%d{yyyy-MM-dd_HH}.log每小时生成一次
/wombat/foo%d{yyyy-MM-dd_HH-mm}.log每分钟生成一次
/wombat/foo%d{yyyy-MM-dd_HH-mm, UTC}.log按指定时区每分钟生成一次
/foo/%d{yyyy-MM,aux}/%d.log每天生成一次,按照年和月区分,例如,/foo/2018-09/中存在一个月的log,log名是每天的日期

pattern配置(日志输出格式化)

例子

下面会介绍一些常用的配置规则。

  1. <encoder>
  2. <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
  3. </encoder>
  • %-4relative: 将输出日志记录的时间,进行左对齐,宽度为4.
  • %thread: 将输出记录日志的线程号
  • %-5level: 输出5个日志级别,进行左对齐。
  • %logger{35}: 输出日志记录的logger名通常为类名,长度为35。
  • %msg%n: 输出应用程序提供的信息,并换行。

注意:所有关键字在使用的时候必须带上%,如上,-为对其标志

pattern表格

关键字描述
c{length}
lo{length}
输出logger所属的类目,通常就是所在类的全名,参数为logger名保留长度,默认不填为全名.
%loggercom.util.StringUtilscom.util.StringUtils
%logger{0}com.util.StringUtilsStringUtils
%logger{10}com.util.StringUtilsc.u.StringUtils
C{length}
class{length}
和上面用法类似,输出调用者的全名,性能较差,不推荐配置。
contextName
cn|
输出上下文名称
d{pattern}
date{pattern}
输出日志的打印时间,和java中的日期格式化类似
%d2019-02-12 18:00:00,000
%date2019-02-12 18:00:00,000
%date{ISO8601}2019-02-12 18:00:00,000
%date{HH:mm:ss,SSSS}18:00:00,000
%date{yyyy-MM-dd HH:mm:ss,SSSS}2019-02-12 18:00:00,000
caller{depth}输出日志调用者的调用栈深度信息,值越大,输出的栈信息越多
%caller{2}[main]-[INFO]: log test
Caller+0 at com.util.StringUtil.subString(StringUtil.java :22)
Caller+1 at com.util.Main.exec(Main.java :17)
L
line
输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。如不考虑性能问题,可以使用
m
msg
message
应用程序提供的信息
M
method
输出执行日志记录的方法名性能较差,如不考虑性能问题,可以使用
n输出一个回车换行符,Windows平台为“/r/n”,Unix平台为“/n”
p
le
level
输出日志级别,即DEBUG,INFO,WARN,ERROR,FATAL
t
thread
输出打印日志的线程名
replace(msg){r,t}msg为日志内容,r是正则表达式,将msg中符合r的内容替换成t。
例如:%replace(%msg){'\s',""}
r
relative
输出自应用启动到输出该log信息耗费的毫秒数

配置:

  1. <configuration>
  2. <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
  3. <encoder>
  4. <!-- 日期 [线程] [class类]-[日志级别] log内容 回车符号 -->
  5. <pattern>%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n</pattern>
  6. </encoder>
  7. </appender>
  8. <!-- 输出INFO及以上的日志 -->
  9. <root level="INFO">
  10. <!-- 让自定义的appender生效 -->
  11. <appender-ref ref="STDOUT"/>
  12. </root>
  13. </configuration>

控制台输出:

  1. 2018-10-09 14:27:55 [main] [org.springframework.web.servlet.handler.SimpleUrlHandlerMapping]-[INFO] Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
  2. 2018-10-09 14:27:55 [main] [org.springframework.jmx.export.annotation.AnnotationMBeanExporter]-[INFO] Registering beans for JMX exposure on startup
  3. 2018-10-09 14:27:55 [main] [org.apache.coyote.http11.Http11NioProtocol]-[INFO] Starting ProtocolHandler ["http-nio-6677"]
  4. 2018-10-09 14:27:55 [main] [org.apache.tomcat.util.net.NioSelectorPool]-[INFO] Using a shared selector for servlet write/read
  5. 2018-10-09 14:27:55 [main] [org.springframework.boot.web.embedded.tomcat.TomcatWebServer]-[INFO] Tomcat started on port(s): 6677 (http) with context path ''
  6. 2018-10-09 14:27:55 [main] [com.xj.plugins.Springboot2AnalyzeApplication]-[INFO] Started Springboot2AnalyzeApplication in 2.014 seconds (JVM running for 3.949)

控制台输出的log配置颜色

格式描述
%black黑色
%red红色
%green绿色
%yellow黄色
%blue蓝色
%magenta品红
%cyan青色
%white白色
%gray灰色
%highlight高亮色
%bold更鲜艳色颜色,强化以上所有的颜色,例如%boldRed,%boldBlack

例子:

  1. <configuration>
  2. <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
  3. <encoder>
  4. <!-- 日期 [线程] [class类]-[日志级别] log内容 回车符号 -->
  5. <pattern>%blue(%d{yyyy-MM-dd HH:mm:ss,SSS}) [%cyan(%t)] [%yellow(%c)]-[%highlight(%p)] %m%n</pattern>&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;
  6. </encoder>
  7. </appender>
  8. <!-- 输出INFO及以上的日志 -->
  9. <root level="INFO">
  10. <!-- 让自定义的appender生效 -->
  11. <appender-ref ref="STDOUT"/>
  12. </root>
  13. </configuration>

配置过后的控制台输出

 

增加色彩输出

 


日志定向输出

logback.xml中如何需要将某中日志输出到文件中可以使用过滤器,类似于以下这个例子

xml配置过滤器,例如将error日志输出到error.log中

  1. <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
  2. <encoder>
  3. <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] [%c]-[%p] %m%n</pattern>
  4. </encoder>
  5. <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
  6. <!-- rollover daily -->
  7. <fileNamePattern>${LOG_HOME}/error-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
  8. <!-- 文件最大30MB,保留60天,总大小20GB -->
  9. <maxFileSize>30MB</maxFileSize>
  10. <maxHistory>60</maxHistory>
  11. <totalSizeCap>20GB</totalSizeCap>
  12. </rollingPolicy>
  13. <!-- 过滤器,只写入error级别log -->
  14. <filter class="ch.qos.logback.classic.filter.LevelFilter">
  15. <level>ERROR</level>
  16. <onMatch>ACCEPT</onMatch>
  17. <onMismatch>DENY</onMismatch>
  18. </filter>
  19. </appender>

如果有需要特殊log需要定向输出的话可以重写 Filter方法

  1. public class MyLogFilter extends Filter<ILoggingEvent> {
  2. @Override
  3. public FilterReply decide(ILoggingEvent event) {
  4. if(event.getMessage() != null
  5. && (event.getMessage().startsWith("test")
  6. || event.getMessage().startsWith("demo"))) {
  7. return FilterReply.ACCEPT;
  8. } else {
  9. return FilterReply.DENY;
  10. }
  11. }
  12. }

然后将filter加入到你的appender中

  1. <!-- 过滤器,写入test和demo开头的日志 -->
  2. <filter class="xx.xxx.xxxx.MyLogFilter" />

关闭类中某个级别的log输出

在logback.xml中加入以下配置

OFF表示全部关闭,可以配置指定级别如INFO,DEBUG...

<logger name="xx.xx.class" level="OFF" />

logback.xml读取环境变量

logback.xml支持两种读取方式,从系统环境中读取,从spring配置文件中读取

读取系统环境变量 通过${envName}方式获取

  1. <!-- 从系统环境变量读取日志输出目录 -->
  2. <property name="LOG_HOME" value="${log.dir}"/>

读取spring配置文件的方式

  1. <!-- 从context中读取所以不需要使用${}获取 -->
  2. <springProperty scope="context" name="LOG_HOME" source="logback.dir"/>

默认值设置

如果在环境变量中没有取到LOG_HOME 的值,则会使logs作为默认值,和Shell语法中设置默认值类似

<file>${LOG_HOME:-logs}/test/test-info.log</file>

-

全量的可用配置文件

以下配置会生成三个日志文件,具体的策略是:每天会生成一个新的文件,当天日志文件达到指定大小会自动压缩,并且生成新的文件进行记录。

  • main.log(只记录info级别及以上的日志输出)
  • warn.log(只记录warn级别的日志输出)
  • error.log(只记录error级别的日志输出)
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <configuration debug="false">
  3. <!-- 从spring中获取配置,如获取不到会使用默认值 -->
  4. <springProperty scope="context" name="LOG_HOME" source="logging.path"/>
  5. <springProperty scope="context" name="LOG_LEVEL" source="logging.output.level"/>
  6. <springProperty scope="context" name="LOG_MAX_SIZE" source="logging.file.max-size"/>
  7. <springProperty scope="context" name="LOG_TOTAL_SIZE_CAP" source="logging.file.total-size-cap"/>
  8. <springProperty scope="context" name="LOG_MAX_HISTORY" source="logging.file.max-history"/>
  9. <!-- 输出样式 -->
  10. <property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] [%logger{10}]-[%p] %m%n"/>
  11. <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
  12. <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
  13. <pattern>%blue(%d{yyyy-MM-dd HH:mm:ss.SSS}) [%cyan(%t)] [%yellow(%logger{10})]-[%highlight(%p)] %m%n</pattern>
  14. </encoder>
  15. </appender>
  16. <appender name="Main-Log" class="ch.qos.logback.core.rolling.RollingFileAppender">
  17. <file>${LOG_HOME:-logs}/logback/main.log</file>
  18. <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
  19. <FileNamePattern>${LOG_HOME:-logs}/logback/main-%d{yyyy-MM-dd}_%i.log.zip</FileNamePattern>
  20. <MaxHistory>${LOG_MAX_HISTORY:-30}</MaxHistory>
  21. <MaxFileSize>${LOG_MAX_SIZE:-10MB}</MaxFileSize>
  22. <totalSizeCap>${LOG_TOTAL_SIZE_CAP:-10GB}</totalSizeCap>
  23. </rollingPolicy>
  24. <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
  25. <pattern>${pattern}</pattern>
  26. </encoder>
  27. </appender>
  28. <appender name="Error-Log" class="ch.qos.logback.core.rolling.RollingFileAppender">
  29. <file>${LOG_HOME:-logs}/logback/error.log</file>
  30. <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
  31. <FileNamePattern>${LOG_HOME:-logs}/logback/error-%d{yyyy-MM-dd}_%i.log.zip</FileNamePattern>
  32. <MaxHistory>${LOG_MAX_HISTORY:-30}</MaxHistory>
  33. <MaxFileSize>${LOG_MAX_SIZE:-10MB}</MaxFileSize>
  34. <totalSizeCap>${LOG_TOTAL_SIZE_CAP:-10GB}</totalSizeCap>
  35. </rollingPolicy>
  36. <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
  37. <pattern>${pattern}</pattern>
  38. </encoder>
  39. <filter class="ch.qos.logback.classic.filter.LevelFilter">
  40. <level>ERROR</level>
  41. <onMatch>ACCEPT</onMatch>
  42. <onMismatch>DENY</onMismatch>
  43. </filter>
  44. </appender>
  45. <appender name="Warn-Log" class="ch.qos.logback.core.rolling.RollingFileAppender">
  46. <file>${LOG_HOME:-logs}/logback/warn.log</file>
  47. <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
  48. <FileNamePattern>${LOG_HOME:-logs}/logback/warn-%d{yyyy-MM-dd}_%i.log.zip</FileNamePattern>
  49. <MaxHistory>${LOG_MAX_HISTORY:-30}</MaxHistory>
  50. <MaxFileSize>${LOG_MAX_SIZE:-10MB}</MaxFileSize>
  51. <totalSizeCap>${LOG_TOTAL_SIZE_CAP:-10GB}</totalSizeCap>
  52. </rollingPolicy>
  53. <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
  54. <pattern>${pattern}</pattern>
  55. </encoder>
  56. <!-- log filter -->
  57. <filter class="ch.qos.logback.classic.filter.LevelFilter">
  58. <level>WARN</level>
  59. <onMatch>ACCEPT</onMatch>
  60. <onMismatch>DENY</onMismatch>
  61. </filter>
  62. </appender>
  63. <!-- 关闭类中某个级别的输出 OFF全部关闭 , INFO,DEBUG ...
  64. <logger name="x.x.Constants">
  65. <level value="OFF"/>
  66. </logger>
  67. -->
  68. <!-- log output level -->
  69. <root level="${LOG_LEVEL:-INFO}">
  70. <appender-ref ref="STDOUT"/>
  71. <appender-ref ref="Main-Log"/>
  72. <appender-ref ref="Warn-Log"/>
  73. <appender-ref ref="Error-Log"/>
  74. </root>
  75. </configuration>

 


 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/595072
推荐阅读
相关标签
  

闽ICP备14008679号