SpringBoot2.x整合logback日志框架(1)

JAVA && Spring && SpringBoot2.x — 学习目录

SLF4J——Simple Logging Facade For Java,他是一个针对各类java日志框架的统一Facade(门面)抽象。Java日志框架众多——常用的有java.util.logging、log4j、logback、commons-logging。而SLF4J定义了统一的日志抽象接口,而真正的日志实现实际上是在运行时决定的——它提供了各类日志框架的binding。

1. 项目中如何使用

1.1 引入maven依赖

1. SpringBoot引入依赖:

实际上spring-boot-starter-web依赖中已经引用了该日志的依赖,我们无需在引用下面的依赖了。

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-logging</artifactId>
 </dependency>

2. JAVA项目引入依赖

        <!--Begin LogBack Log-->
        <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>
        <!--End LogBack Log-->

「辅助接口」也可以引入lombok依赖:

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.0</version>
        </dependency>

1.2 引入配置文件

<?xml version="1.0" encoding="UTF-8"?>

<configuration scan="true" scanPeriod="60 seconds" debug="false">

    <contextName>logback</contextName>
    <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
    <property name="log.path" value="E:\\log\\logback.log" />

    <!--输出到控制台-->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
        <encoder>
            <!--<pattern>%d %p (%file:%line\)- %m%n</pattern>-->
            <!--格式化输出:%d:表示日期    %thread:表示线程名     %-5level:级别从左显示5个字符宽度  %msg:日志消息    %n:是换行符-->
            <pattern>控制台-%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger - %msg%n</pattern>
            <charset>GBK</charset>
        </encoder>
    </appender>

    <!--输出到文件-->
    <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logback.%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>30</maxHistory>
            <totalSizeCap>1GB</totalSizeCap>
        </rollingPolicy>
        <encoder>
            <!--格式化输出:%d:表示日期    %thread:表示线程名     %-5level:级别从左显示5个字符宽度  %msg:日志消息    %n:是换行符-->
            <pattern>文件记录-%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
            <charset>GBK</charset>
        </encoder>
    </appender>

    <root level="info">
        <appender-ref ref="console" />
        <appender-ref ref="file" />
    </root>

    <logger name="com.sxd.controller"/>
    <logger name="com.sxd.util.LogTestController" level="WARN" additivity="false">
        <appender-ref ref="console" />
    </logger>
</configuration>

引入的配置文件应该叫什么名字呢?

1.2.1 配置文件存放的位置

放在src/main/resources下面即可。

1.2.2 加载文件的优先级

logback 在启动时,根据以下步骤寻找配置文件:

  1. 在 classpath 中寻找 logback-test.xml文件
  2. 如果找不到 logback-test.xml,则在 classpath 中寻找logback.groovy文件
  3. 如果找不到 logback.groovy,则在 classpath 中寻找logback.xml文件
  4. 如果上述的文件都找不到,则 logback 会使用 JDK 的 SPI 机制查找 META-INF/services/ch.qos.logback.classic.spi.Configurator 中的 logback 配置实现类,这个实现类必须实现 Configuration 接口,使用它的实现来进行配置。【实际寻找的是logback-spring.xml文件】。
  5. 如果上述操作都不成功,logback 就会使用它自带的 BasicConfigurator 来配置,并将日志输出到console

当然,在Spring环境中,也可以自定义配置logback-xxx.xml的名字。需要在application.properties中使用logging.config=classpath:logging-自定义.xml进行配置。

文章引用...

1.2.3 Spring推荐的命名方式

  • Logback:logback-spring.xml,logback-spring.groovy,logback.xml,logback.groovy

  • Log4j:log4j-spring.properties,log4j-spring.xml,log4j.properties,log4j.xml

  • Log4j2:log4j2-spring.xml,log4j2.xml

  • JDK(java Util Logging):logging.properties

注:Spring Boot官方推荐优先使用带有-spring的文件名作为日志配置(如使用logback-spring.xml而不是使用logback.xml)命名为logback-spring.xml的日志配置文件,Spring Boot可以为它添加一些Spring Boot特有的配置项【例如:spring boot的profile多环境配置】。

1.2.4 Spring如何实现多环境配置

  1. 日志配置文件名应定义为logback-spring.xml。
  2. 在日志配置文件中,使用<springProfile name="dev"></springProfile>标签来包住这种环境下使用的配置。
<springProfile name="dev">
  <root>
     <appender-ref ref="consoleAppender"/>
  </root>
</springProfile>

若是多个环境,使用,号隔开

<!--测试环境+开发环境,多个使用逗号隔开-->
<springProfile name="test,dev">
  <logger name="com.tellme.controller" level="info"/>
</springProfile>
<springProfile name="prod">
  <logger name="com.tellme.controller" level="debug"/>
</springProfile>
<!--注:这里一定要放到springProfile中,否则本机执行的时候还是会去寻找对应的文件-->
<springProfile name="dev">
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
      <encoder>
          <pattern>[%t] [%X{traceRootId}] (%file:%line\): %m%n</pattern>
                <!-- 控制台也要使用UTF-8,不要使用GBK,否则会中文乱码 -->
          <charset>UTF-8</charset>
      </encoder>
  </appender>
</springProfile>
  1. 在application.properties配置文件中,选中激活哪一种或哪几种环境。
#激活开发资源文件
spring.profiles.action=dev
#叠加多个资源文件
spring.profiles.include=dev,test,pro

1.2.5 logback.xml如何读取application.properties的配置

  1. <springProperty>标签允许我们从Spring中显示属性,以便在logback中使用。
  2. 若是需要一个后备值,以防该属性未配置,则可以使用defaultvalue属性。
<configuration>
    <springProperty scope="context" name="logPath" source="log.out.path" defalutValue="/app/test.log"/>
</configuration>

在application.properties的配置

log.out.path="/app/test.log"

2. Spring的application.properties配置日志打印信息

2.1 日志的输出级别

日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出。

2.2. 控制台输出

Spring Boot中默认将ERROR、WARN、INFO级别的日志输出到控制台。可以在application.properties中配置:

debug=true

那么核心Logger(包含嵌入式容器、hibernate、spring)会输出更多的内容,但是应用的日志并不会输出为DEBUG级别。

2.3. 文件输出

默认情况下,Spring Boot将日志输出到控制台,不会写到日志文件。如果要编写除控制台之外的日志文件,则需要在application.properties中设置logging.file或logging.path属性。

logging.file=my.log
logging.path=/var/log
  • logging.file,设置文件,可以是绝对路径,也可以是相对路径,并写入日志内容。
  • logging.path,设置目录,会在该目录下创建一个spring.log文件,并写入日志内容。

注:两者不能同时使用,如若同时使用,则只有logging.file生效。

(1)默认情况下,日志文件的大小到达10MB时会切分一下,产生新的日志文件。
(2)默认级别为:ERROR、WARN、INFO。

2.4 日志级别控制

可以在application.properties中配置日志级别。

logging:
  level:
    com.tellme.mapper: DEBUG
  • logging.level:日志级别前缀,*为包名或Logger名。
  • LEVEL:选项为TRACE,DEBUG,INFO,WARN,ERROR,FATAL,OFF。

注:即使在logback-spring.xml设置的打印级别是info,但是在配置文件中配置的打印级别是debug,则按照配置文件执行。

3. logback-spring.xml参数解析

<?xml version="1.0" encoding="UTF-8"?>

<configuration scan="true" scanPeriod="60 seconds" debug="false">

    <contextName>logback</contextName>
    <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
    <property name="log.path" value="E:\\log\\logback.log" />

    <!--输出到控制台-->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
        <encoder>
            <!--<pattern>%d %p (%file:%line\)- %m%n</pattern>-->
            <!--格式化输出:%d:表示日期    %thread:表示线程名     %-5level:级别从左显示5个字符宽度  %msg:日志消息    %n:是换行符-->
            <pattern>控制台-%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger - %msg%n</pattern>
            <charset>GBK</charset>
        </encoder>
    </appender>

    <!--输出到文件-->
    <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logback.%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>30</maxHistory>
            <totalSizeCap>1GB</totalSizeCap>
        </rollingPolicy>
        <encoder>
            <!--格式化输出:%d:表示日期    %thread:表示线程名     %-5level:级别从左显示5个字符宽度  %msg:日志消息    %n:是换行符-->
            <pattern>文件记录-%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
            <charset>GBK</charset>
        </encoder>
    </appender>

    <root level="info">
        <appender-ref ref="console" />
        <appender-ref ref="file" />
    </root>

    <logger name="com.sxd.controller"/>
    <logger name="com.sxd.util.LogTestController" level="WARN" additivity="false">
        <appender-ref ref="console" />
    </logger>



</configuration>

3.1 根节点<Configuration>包含的属性

  • scan:当此属性设置为true时,配置文件如果发生改变,将会重新加载,默认值是true。
  • scanPeriod:[皮锐德]设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒,当scan为true时,此属性生效,默认时间是1分钟。
  • debug:当属性设置为true时,将打印logback内部日志信息,事实查看logback运行状态,默认值为false。

根节点<configuration>的子节点:
<configuration>下面共有2个属性,3个子节点,分别是:

属性一:设置上下文名称<contextName>

每个logger都关联到logger上下文,默认上下文名称为“default”。但可以使用<contextName>设置成其他名字,用来区分不同应用程序的记录。一旦设置不可修改,可以通过%contextName来打印日志上下文名称。一般来说我们不用这个属性,可有可无

<contextName>logback</contextName>

3.1 定义变量

3.1.1 定义logback.xml的变量

property标签——可以定义变量

用来定义变量的标签,<property>有两个属性:name和value,其中name的值是变量的名称,value的值是定义变量的值。通过<property>定义的值会被插入到logger上下文中。定义变量后,可以使用"${}"来使用变量。

<!--定义变量-->
<property name="contextName" value="logback">
<!--后续就可以使用变量-->
<contextName>${contextName}</contextName>

3.1.2 读取Spring配置文件的变量

springProperty标签—读取Spring的变量

在application.properties的配置

log.out.path="/app/test.log"

若是需要一个后备值,以防该属性未配置,则可以使用defaultvalue属性。

<springProperty scope="context" name="logPath" source="log.out.path" defalutValue="/app/test.log"/>

3.2 定义输出的类型

appender用来格式化日志输出节点,有两个属性name和class,class用来指定哪种输出策略,常用的就是控制台输出和文件输出策略。

3.2.1 控制台输出ConsoleAppender

concole[肯扫]

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
       <encoder>
            <pattern>%d %p [%t] (%file:%line\): %m%n</pattern>
                <!-- 控制台也要使用UTF-8,不要使用GBK,否则会中文乱码 -->
            <charset>UTF-8</charset>
        </encoder>
</appender>

<encoder>表示对日志进行编码:

  • %d ——日志输出时间
  • %p ——日志级别
  • %t ——输出日志的进程的名字
  • %file ——输出日志的文件名
  • %line ——输出日志的行数
  • %m ——日志消息
  • %n ——平台的换行符

3.2.2 文件输出RollingFileAppender

另一种常见的日志输出到文件,随着应用时间越来越长,日志也会增长的越来越多,将他们输出到同一文件并非一个好方法。RollingFileAppender用于切分文件日志。

<appender name="cleanLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>log/catalina.out</File>
        <!-- rollingPolicy:当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名。 -->
        <!-- TimeBasedRollingPolicy: 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 活动文件的名字会根据fileNamePattern的值,每隔一段时间改变一次 -->
            <!-- 文件名:log/demo.2017-12-05.0.log -->
            <fileNamePattern>${logPath}/log/catalina.out.%d{yyyy_MM_dd_HH}</fileNamePattern>
            <!-- 每产生一个日志文件,该日志文件的保存期限为30天 -->
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder>
            <!-- pattern节点,用来设置日志的输入格式 -->
            <pattern>
                %d %p [%t]  (%file:%line\): %m%n
            </pattern>
            <!-- 记录日志的编码:此处设置字符集 - -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>

<File></Fille>推荐使用绝对路径,若是相对路径的话,本质上是相对于启动的bin目录。

其中重要的是rollingPolicy的定义:
<fileNamepattern>logback.%d{yyyy-MM-dd}.log</fileNamepattern>定义了日志的切分方式:按天将日志归档到一个文件中。

同理:%d{yyyy_MM_dd_HH}来定义精确到小时的日志切分方式。

<totalSizeCap>1GB</totalSizeCap>用来指定日志文件的上限大小,例如设置1GB的话,那么到了这个值,就会删除旧的日志。

<fileNamePattern>${logPath}/log/catalina.out.%d{yyyy_MM_dd_HH}.gz</fileNamePattern>配置,文件滚动时,会进行压缩。

https://blog.csdn.net/iamlihongwei/article/details/62430994

1. 如何设置日志级别,只输出Error日志

<appender name="cleanLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
       <level>ERROR</level>
    </filter>
</appender >

2. 如何避免输出ERROR日志

<appender name="cleanLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
       <level>ERROR</level>
       <!--匹配到ERROR级别就 禁止 输出--> 
       <onMatch>DENY</onMatch>
      <!--若不是ERROR 级别的就输出-->
       <onMismatch>ACCEPT</onMismatch>
    </filter>
</appender >

需要注意的是,只是避免输出ERROR级别的日志,若是只想输出INFO级别的,存在一些问题:因为不能排除WARN级别的日志。

3. 如何只输出INFO级别的日志

<filter class="ch.qos.logback.classic.filter.LevelFilter">
     <!--过滤 INFO-->
     <level>INFO</level>
     <!--匹配到INFO就允许-->
     <onMatch>ACCEPT</onMatch>
     <!--除INFO都禁止输出-->
     <onMismatch>DENY</onMismatch>
</filter>

3.3 定义appender的日志级别

root节点是必选节点——用来指定最基础的日志输出级别,只有一个level属性。

  • level:用来设置打印级别,大小写无关,默认DEBUG。
  • appender-ref:标识这个appender将会添加到这个logger。
  • ref:是 <appender>的name属性。
 <root level="info">
        <appender-ref ref="console" />
        <appender-ref ref="file" />
    </root>

logger节点是可选节点——设置一个包或者具体的某一个类的日志打印级别

<logger>用来设置一个包或者具体的某一个类的日志打印级别,以及指定<appender>。<logger>仅有一个name属性,一个可选的level和一个可选的addtivity属性。

  • name:用来指定受此logger约束的某一个包或者具体的一个类。
  • level:用于设置打印级别。如果未设置此属性,那么当前logger将会继承上级级别。
  • addtivity:是否向上级logger传递打印信息,默认是true。
    <logger name="com.sxd.controller"/>
    <logger name="com.sxd.util.LogTestController" level="WARN" additivity="false">
        <appender-ref ref="console" />
    </logger>

1. 带有logger配置,不指定level,不指定appender-ref

  <logger name="com.sxd.controller"/>

因为没有设置addivity,默认为true,将该logger的打印信息向上传递(<root level="info">将root的打印级别设置为info,并且指定了appender-ref,那么将会在控制台和文件中打印。)没有设置appender-ref,此<logger>标签不会打印信息。

2.带有logger配置,指定级别level,指定appender-ref

 <logger name="com.sxd.util.LogTestController" level="WARN" additivity="false">
        <appender-ref ref="console" />
 </logger>

打印级别是WRAN。additivity属性是false,表示此<logger>的打印信息**只会打印到控制台**不再向上级传递。

  1. 若是additivity="true"的话,则会打印两次,因为打印信息会向上级传递,logger本身打印一次,root接着会打印一次,此时file中也会有日志。

4. 分析日志输出的信息

默认情况下,SpringBoot会使用Logback来记录日志,并且INFO级别输出到控制台。

  1. 时间日期:精确到毫秒。
  2. 日志级别:ERROR> WARN>INFO>DEBUG > TRACE  优先级如前面,默认情况下是INFO,则INFO以及优先级更高的WARN和ERROR会被显示。
  3. 进程ID:就是PID。
  4. 分割符:---标识实际日志的开始。
  5. 线程名:方括号括起来(可能会截断控制台的输出)。
  6. Logger名:通常使用源代码的类名。
  7. 日志内容。
logging输出格式

5. 导入(include)其他项目配置的logback.xml文件

可以在sdk包中定义好logback.xml的配置,而后通过“导入”的方式给其他项目来使用。

定义logback的xml配置:

<?xml version="1.0" encoding="UTF-8"?>
    <included>
    <appender name="ASYNC_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>/var/log/xx/cloud/trail/async/error.log.%d{yyyy-MM-dd}.log</FileNamePattern>
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder
                class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <!-- 日志输出编码 -->
            <layout class="ch.qos.logback.classic.PatternLayout">
                <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
                </pattern>
            </layout>
        </encoder>
        <!--日志文件最大的大小-->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>10MB</MaxFileSize>
        </triggeringPolicy>
    </appender>

    <appender name="AOP_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>/var/log/xx/cloud/trail/aop/error.log.%d{yyyy-MM-dd}.log</FileNamePattern>
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder
                class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <!-- 日志输出编码 -->
            <layout class="ch.qos.logback.classic.PatternLayout">
                <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
                </pattern>
            </layout>
        </encoder>
        <!--日志文件最大的大小-->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>10MB</MaxFileSize>
        </triggeringPolicy>
    </appender>


    <!--需要将日志单独输出的包路径-->
    <logger name="com.xx.cloud.trail.client.async" level="ERROR" additivity="false">
        <appender-ref ref="ASYNC_LOG"/>
    </logger>
    <!--需要将日志单独输出的包路径-->
    <logger name="com.xx.cloud.trail.client.aop" level="ERROR" additivity="false">
        <appender-ref ref="AOP_LOG"/>
    </logger>
    </included>

导入到其他项目中

<include resource="logback-trail.xml"/>

文件参考

【spring boot】8.spring boot的日志框架logback使用

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342