Springboot 日志(待續(xù))

簡(jiǎn)單的說(shuō)惫撰,日志就是記錄程序的運(yùn)行軌跡呆万,方便查找關(guān)鍵信息筹误,也方便快速定位解決問(wèn)題。
本篇文章分為三部分講解:

  • 常用日志框架
  • SpringBoot 配置Logback
  • 阿里日志規(guī)約

常用日志框架

  • Logging
    這是 Java 自帶的日志工具類躯泰,在 JDK 1.5 開(kāi)始就已經(jīng)有了,在 java.util.logging 包下华糖。
  • Log4j
    Log4j 是 Apache 的一個(gè)開(kāi)源日志框架麦向,也是市場(chǎng)占有率最多的一個(gè)框架。大多數(shù)沒(méi)用過(guò) Java Logging客叉, 但沒(méi)人敢說(shuō)沒(méi)用過(guò) Log4j 吧诵竭,反正從我接觸 Java 開(kāi)始就是這種情況,做 Java 項(xiàng)目必有 Log4j 日志框架兼搏。
  • commons-logging
    commons-logging 就是日志的門面接口卵慰,它也是 apache 最早提供的日志門面接口,用戶可以根據(jù)喜好選擇不同的日志實(shí)現(xiàn)框架佛呻,而不必改動(dòng)日志定義裳朋,這就是日志門面的好處,符合面對(duì)接口抽象編程吓著。
  • Slf4j
    全稱:Simple Logging Facade for Java鲤嫡,即簡(jiǎn)單日志門面接口,和 Apache 的 commons-logging 是一樣的概念绑莺,它們都不是具體的日志框架暖眼,你可以指定其他主流的日志實(shí)現(xiàn)框架。
  • Logback
    Logback 是 Slf4j 的原生實(shí)現(xiàn)框架纺裁,同樣也是出自 Log4j 一個(gè)人之手诫肠,但擁有比 log4j 更多的優(yōu)點(diǎn)、特性和更做強(qiáng)的性能欺缘,現(xiàn)在基本都用來(lái)代替 log4j 成為主流栋豫。

為什么 Logback 會(huì)成為主流?
無(wú)論從設(shè)計(jì)上還是實(shí)現(xiàn)上浪南,Logback相對(duì)log4j而言有了相對(duì)多的改進(jìn)笼才。
更快的執(zhí)行速度
基于我們先前在log4j上的工作,logback 重寫(xiě)了內(nèi)部的實(shí)現(xiàn)络凿,在某些特定的場(chǎng)景上面骡送,甚至可以比之前的速度快上10倍。在保證logback的組件更加快速的同時(shí)絮记,同時(shí)所需的內(nèi)存更加少摔踱。

日志框架總結(jié)

  1. commons-loggin扣泊、slf4j 只是一種日志抽象門面链患,不是具體的日志框架。
  2. log4j仰泻、logback 是具體的日志實(shí)現(xiàn)框架。
  3. 一般首選強(qiáng)烈推薦使用 slf4j + logback篮愉。當(dāng)然也可以使用slf4j + log4j腐芍、commons-logging + log4j 這兩種日志組合框架。

SpringBoot logback

Spring Boot會(huì)用Logback來(lái)記錄日志试躏,并用INFO級(jí)別輸出到控制臺(tái)猪勇。在運(yùn)行應(yīng)用程序和其他例子時(shí),你應(yīng)該已經(jīng)看到很多INFO級(jí)別的日志了颠蕴。

日志依賴

依賴 spring-boot-starter-web 默認(rèn)包含spring-boot-starter-logging
那么泣刹,我們的Spring Boot應(yīng)用將自動(dòng)使用logback作為應(yīng)用日志框架,Spring Boot啟動(dòng)的時(shí)候犀被,由org.springframework.boot.logging.Logging-Application-Listener根據(jù)情況初始化并使用椅您。

image.png

默認(rèn)配置屬性支持

Spring Boot為我們提供了很多默認(rèn)的日志配置,所以寡键,只要將spring-boot-starter-logging作為依賴加入到當(dāng)前應(yīng)用的classpath掀泳,則“開(kāi)箱即用”。 下面介紹幾種在application.properties就可以配置的日志相關(guān)屬性西轩。

控制臺(tái)輸出

日志級(jí)別從低到高分為TRACE < DEBUG < INFO < WARN < ERROR < FATAL开伏,如果設(shè)置為WARN,則低于WARN的信息都不會(huì)輸出遭商。 Spring Boot中默認(rèn)配置ERROR、WARN和INFO級(jí)別的日志輸出到控制臺(tái)捅伤。您還可以通過(guò)啟動(dòng)您的應(yīng)用程序–debug標(biāo)志來(lái)啟用“調(diào)試”模式(開(kāi)發(fā)的時(shí)候推薦開(kāi)啟),以下兩種方式皆可:

  • 在運(yùn)行命令后加入–debug標(biāo)志劫流,如:$ java -jar springTest.jar --debug。
  • 在application.properties中配置debug=true丛忆,該屬性置為true的時(shí)候祠汇,核心Logger(包含嵌入式容器、hibernate熄诡、spring)會(huì)輸出更多內(nèi)容可很,但是你自己應(yīng)用的日志并不會(huì)輸出為DEBUG級(jí)別。

文件輸出

默認(rèn)情況下凰浮,Spring Boot將日志輸出到控制臺(tái)我抠,不會(huì)寫(xiě)到日志文件。如果要編寫(xiě)除控制臺(tái)輸出之外的日志文件袜茧,則需在application.properties中設(shè)置logging.file或logging.path屬性菜拓。

  • logging.file,設(shè)置文件笛厦,可以是絕對(duì)路徑纳鼎,也可以是相對(duì)路徑。如:logging.file=my.log。
  • logging.path贱鄙,設(shè)置目錄劝贸,會(huì)在該目錄下創(chuàng)建spring.log文件,并寫(xiě)入日志內(nèi)容逗宁,如:logging.path=/var/log映九。

如果只配置 logging.file,會(huì)在項(xiàng)目的當(dāng)前路徑下生成一個(gè) xxx.log 日志文件疙剑。
如果只配置 logging.path氯迂,在 /var/log文件夾生成一個(gè)日志文件為 spring.log。

級(jí)別控制

所有支持的日志記錄系統(tǒng)都可以在Spring環(huán)境中設(shè)置記錄級(jí)別(例如在application.properties中) 格式為:’logging.level.* = LEVEL’

  • logging.level:日志級(jí)別控制前綴言缤,*為包名或Logger名
  • LEVEL:選項(xiàng)TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF

舉例:

  • logging.level.com.mrbird=DEBUG:com.mrbird包下所有class以DEBUG級(jí)別輸出嚼蚀。
  • logging.level.root=WARN:root日志以WARN級(jí)別輸出。

自定義日志配置

由于日志服務(wù)一般都在ApplicationContext創(chuàng)建前就初始化了管挟,它并不是必須通過(guò)Spring的配置文件控制轿曙。因此通過(guò)系統(tǒng)屬性和傳統(tǒng)的Spring Boot外部配置文件依然可以很好的支持日志控制和管理。

根據(jù)不同的日志系統(tǒng)僻孝,你可以按如下規(guī)則組織配置文件名导帝,就能被正確加載:

  • 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官方推薦優(yōu)先使用帶有-spring的文件名作為你的日志配置(如使用logback-spring.xml,而不是logback.xml)穿铆,命名為logback-spring.xml的日志配置文件您单,spring boot可以為它添加一些spring boot特有的配置項(xiàng)(下面會(huì)提到)。

上面是默認(rèn)的命名規(guī)則荞雏,并且放在src/main/resources下面即可虐秦。

如果你即想完全掌控日志配置,但又不想用logback.xml作為L(zhǎng)ogback配置的名字凤优,可以在application.properties配置文件里面通過(guò)logging.config屬性指定自定義的名字:

logging.config=classpath:logging-config.xml

雖然一般并不需要改變配置文件的名字悦陋,但是如果你想針對(duì)不同運(yùn)行時(shí)Profile使用不同的日 志配置,這個(gè)功能會(huì)很有用筑辨。

下面我們來(lái)看看一個(gè)普通的logback-spring.xml例子:

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

<!--    scan:當(dāng)此屬性設(shè)置為true時(shí)俺驶,配置文件如果發(fā)生改變,將會(huì)被重新加載棍辕,默認(rèn)值為true暮现。

    scanPeriod:設(shè)置監(jiān)測(cè)配置文件是否有修改的時(shí)間間隔,如果沒(méi)有給出時(shí)間單位楚昭,默認(rèn)單位是毫秒送矩。當(dāng)scan為true時(shí),此屬性生效哪替。默認(rèn)的時(shí)間間隔為1分鐘栋荸。

    debug:當(dāng)此屬性設(shè)置為true時(shí),將打印出logback內(nèi)部日志信息,實(shí)時(shí)查看logback運(yùn)行狀態(tài)晌块。默認(rèn)值為false爱沟。-->
<configuration  scan="true" scanPeriod="60 seconds" debug="false">

<!--    每個(gè)logger都關(guān)聯(lián)到logger上下文,默認(rèn)上下文名稱為“default”匆背。但可以使用設(shè)置成其他名字呼伸,用于區(qū)分不同應(yīng)用程序的記錄。
    一旦設(shè)置钝尸,不能修改,可以通過(guò)%contextName來(lái)打印日志上下文名稱括享。-->
    <contextName>logback</contextName>

<!--    設(shè)置變量<property> 用來(lái)定義變量值的標(biāo)簽,有兩個(gè)屬性珍促,name和value铃辖;其中name的值是變量的名稱,value的值時(shí)變量定義的值猪叙。
    通過(guò)定義的值會(huì)被插入到logger上下文中娇斩。定義變量后,可以使“${}”來(lái)使用變量穴翩。-->
    <property name="log.path" value="log" />

<!--  appender用來(lái)格式化日志輸出節(jié)點(diǎn)犬第,有倆個(gè)屬性name和class,class用來(lái)指定哪種輸出策略芒帕,常用就是控制臺(tái)輸出策略和文件輸出策略歉嗓。-->

<!--    <encoder>表示對(duì)日志進(jìn)行編碼:

    %d{HH: mm:ss.SSS}——日志輸出時(shí)間。

    %thread——輸出日志的進(jìn)程名字背蟆,這在Web應(yīng)用以及異步任務(wù)處理中很有用遥椿。

    %-5level——日志級(jí)別,并且使用5個(gè)字符靠左對(duì)齊淆储。

    %logger{36}——日志輸出者的名字。

    %msg——日志消息家浇。

    %n——平臺(tái)的換行符本砰。

    ThresholdFilter為系統(tǒng)定義的攔截器,例如我們用ThresholdFilter來(lái)過(guò)濾掉ERROR級(jí)別以下的日志不輸出到文件中钢悲。如果不用記得注釋掉点额,不然你控制臺(tái)會(huì)發(fā)現(xiàn)沒(méi)日志~-->
    <!--輸出到控制臺(tái)-->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <!-- <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
             <level>ERROR</level>
         </filter>-->
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

<!--    <fileNamePattern>${log.path}/logback.%d{yyyy-MM-dd}.log</fileNamePattern>定義了日志的切分方式——把每一天的日志歸檔到一個(gè)文件中;

    <maxHistory>30</maxHistory>表示只保留最近30天的日志莺琳,以防止日志填滿整個(gè)磁盤空間还棱。同理,可以使用%d{yyyy-MM-dd_HH-mm}來(lái)定義精確到分的日志切分方式惭等;

    <totalSizeCap>1GB</totalSizeCap>用來(lái)指定日志文件的上限大小珍手,例如設(shè)置為1GB的話,那么到了這個(gè)值,就會(huì)刪除舊的日志琳要。-->
    <!--輸出到文件-->
    <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/logback.%d{yyyy-MM-dd}.log</fileNamePattern>
        </rollingPolicy>
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

<!--    root節(jié)點(diǎn)是必選節(jié)點(diǎn)寡具,用來(lái)指定最基礎(chǔ)的日志輸出級(jí)別,只有一個(gè)level屬性稚补,
    用來(lái)設(shè)置打印級(jí)別童叠,大小寫(xiě)無(wú)關(guān):TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,不能設(shè)置為INHERITED或者同義詞NULL课幕。-->
    <root level="info">
        <appender-ref ref="console" />
        <appender-ref ref="file" />
    </root>

<!--    <logger>用來(lái)設(shè)置某一個(gè)包或者具體的某一個(gè)類的日志打印級(jí)別厦坛、以及指定<appender>。<logger>僅有一個(gè)name屬性乍惊,一個(gè)可選的level和一個(gè)可選的addtivity屬性杜秸。-->
    <!-- logback為java中的包 -->
    <logger name="top.lconcise.controller.HelloController"/>

<!--    name:用來(lái)指定受此logger約束的某一個(gè)包或者具體的某一個(gè)類。

    level:用來(lái)設(shè)置打印級(jí)別污桦,大小寫(xiě)無(wú)關(guān):TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF亩歹,還有一個(gè)特俗值INHERITED或者同義詞NULL,
    代表強(qiáng)制執(zhí)行上級(jí)的級(jí)別凡橱。如果未設(shè)置此屬性小作,那么當(dāng)前l(fā)ogger將會(huì)繼承上級(jí)的級(jí)別。

    addtivity:是否向上級(jí)logger傳遞打印信息稼钩。默認(rèn)是true顾稀。-->
    <!--logback.LogbackDemo:類的全路徑 -->
    <logger name="top.lconcise.controller.HelloController2" level="WARN" additivity="false">
        <appender-ref ref="console"/>
    </logger>
</configuration>

阿里日志規(guī)約

1.【強(qiáng)制】應(yīng)用中不可直接使用日志系統(tǒng)(Log4j、 Logback) 中的 API坝撑,而應(yīng)依賴使用日志框架
SLF4J 中的 API静秆,使用門面模式的日志框架,有利于維護(hù)和各個(gè)類的日志處理方式統(tǒng)一巡李。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(A.class);

2.【強(qiáng)制】日志文件推薦至少保存 15 天抚笔,因?yàn)橛行┊惓>邆湟浴爸堋睘轭l次發(fā)生的特點(diǎn)。

3.【強(qiáng)制】應(yīng)用中的擴(kuò)展日志(如打點(diǎn)侨拦、臨時(shí)監(jiān)控殊橙、訪問(wèn)日志等) 命名方式:
appName_logType_logName.log。 logType:日志類型狱从,推薦分類有
stats/desc/monitor/visit 等膨蛮; logName:日志描述。這種命名的好處:通過(guò)文件名就可知
道日志文件屬于什么應(yīng)用季研,什么類型敞葛,什么目的,也有利于歸類查找与涡。
正例: mppserver 應(yīng)用中單獨(dú)監(jiān)控時(shí)區(qū)轉(zhuǎn)換異常惹谐,如:
mppserver_monitor_timeZoneConvert.log
說(shuō)明: 推薦對(duì)日志進(jìn)行分類持偏, 如將錯(cuò)誤日志和業(yè)務(wù)日志分開(kāi)存放,便于開(kāi)發(fā)人員查看豺鼻,也便于
通過(guò)日志對(duì)系統(tǒng)進(jìn)行及時(shí)監(jiān)控综液。

4.【強(qiáng)制】對(duì) trace/debug/info 級(jí)別的日志輸出,必須使用條件輸出形式或者使用占位符的方式儒飒。
說(shuō)明:

 logger.debug("Processing trade with id: " + id + " and symbol: " + symbol);

如果日志級(jí)別是 warn谬莹,上述日志不會(huì)打印,但是會(huì)執(zhí)行字符串拼接操作桩了,如果 symbol 是對(duì)象附帽,會(huì)執(zhí)行 toString()方法,浪費(fèi)了系統(tǒng)資源井誉,執(zhí)行了上述操作蕉扮,最終日志卻沒(méi)有打印。
正例: (條件)

if (logger.isDebugEnabled()) {
logger.debug("Processing trade with id: " + id + " and symbol: " + symbol);
}

正例: (占位符)

logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol);

5.【強(qiáng)制】避免重復(fù)打印日志颗圣,浪費(fèi)磁盤空間喳钟,務(wù)必在 log4j.xml 中設(shè)置 additivity=false。
正例: <logger name="com.taobao.dubbo.config" additivity="false">
6.【強(qiáng)制】異常信息應(yīng)該包括兩類信息:案發(fā)現(xiàn)場(chǎng)信息和異常堆棧信息在岂。如果不處理奔则,那么通過(guò)
關(guān)鍵字 throws 往上拋出。
正例: logger.error(各類參數(shù)或者對(duì)象 toString + "_" + e.getMessage(), e);

7.【推薦】謹(jǐn)慎地記錄日志蔽午。生產(chǎn)環(huán)境禁止輸出 debug 日志易茬; 有選擇地輸出 info 日志; 如果使
用 warn 來(lái)記錄剛上線時(shí)的業(yè)務(wù)行為信息及老,一定要注意日志輸出量的問(wèn)題抽莱,避免把服務(wù)器磁盤
撐爆,并記得及時(shí)刪除這些觀察日志骄恶。
說(shuō)明: 大量地輸出無(wú)效日志食铐,不利于系統(tǒng)性能提升,也不利于快速定位錯(cuò)誤點(diǎn)僧鲁。 記錄日志時(shí)請(qǐng)
思考:這些日志真的有人看嗎虐呻?看到這條日志你能做什么?能不能給問(wèn)題排查帶來(lái)好處悔捶?

8.【參考】可以使用 warn 日志級(jí)別來(lái)記錄用戶輸入?yún)?shù)錯(cuò)誤的情況,避免用戶投訴時(shí)单芜,無(wú)所適
從蜕该。注意日志輸出的級(jí)別, error 級(jí)別只記錄系統(tǒng)邏輯出錯(cuò)洲鸠、異常等重要的錯(cuò)誤信息堂淡。如非必
要馋缅,請(qǐng)不要在此場(chǎng)景打出 error 級(jí)別。

測(cè)試源碼:https://github.com/lbshold/springboot/tree/master/Spring-Boot-Log
參考文章:https://mrbird.cc/Spring-Boot-logback.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末绢淀,一起剝皮案震驚了整個(gè)濱河市萤悴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌皆的,老刑警劉巖覆履,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異费薄,居然都是意外死亡硝全,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門楞抡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)伟众,“玉大人,你說(shuō)我怎么就攤上這事召廷〉氏幔” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵竞慢,是天一觀的道長(zhǎng)先紫。 經(jīng)常有香客問(wèn)我,道長(zhǎng)梗顺,這世上最難降的妖魔是什么泡孩? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮寺谤,結(jié)果婚禮上仑鸥,老公的妹妹穿的比我還像新娘。我一直安慰自己变屁,他們只是感情好眼俊,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著粟关,像睡著了一般疮胖。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上闷板,一...
    開(kāi)封第一講書(shū)人閱讀 51,165評(píng)論 1 299
  • 那天澎灸,我揣著相機(jī)與錄音,去河邊找鬼遮晚。 笑死性昭,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的县遣。 我是一名探鬼主播糜颠,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼汹族,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了其兴?” 一聲冷哼從身側(cè)響起顶瞒,我...
    開(kāi)封第一講書(shū)人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎元旬,沒(méi)想到半個(gè)月后榴徐,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡法绵,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年箕速,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片朋譬。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡盐茎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出徙赢,到底是詐尸還是另有隱情字柠,我是刑警寧澤,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布狡赐,位于F島的核電站窑业,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏枕屉。R本人自食惡果不足惜常柄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望搀擂。 院中可真熱鬧西潘,春花似錦、人聲如沸哨颂。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)威恼。三九已至品姓,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間箫措,已是汗流浹背腹备。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留斤蔓,地道東北人植酥。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像附迷,于是被迫代替她去往敵國(guó)和親惧互。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353