微服務學習筆記01

第一節(jié) SpringApplication

本文是在預習和學習后掘猿,想要盡自己所能將學到的知識以自己的理解記錄下來憾筏。當然件相,有些地方還是一知半解,所以是有很多內容是小馬哥所講所書骗污,權當引經據(jù)典,還望小馬哥見到不要怪罪沈条。

雖然今年項目上已經接觸過SpringBoot需忿,目前仍在使用,但了解到的只是常用的用法蜡歹。這篇文章主要講一下微服務的概念屋厘,以SpringApplication啟動類為切入點,講解Spring注解機制月而,SpringApplication啟動類的寫法和程序類型推斷汗洒,以及SpringBoot事件和事件監(jiān)聽。

一景鼠、微服務是什么仲翎?能做什么痹扇?

1铛漓、概念

微服務是一種細粒度(Fine-Grain)的SOA

SOA = Service-Oriented Architecture 面向服務架構

SOA的特征:

面向服務( Service-Oriented )

松耦合(Loose-Coupling)

模塊化(Modular)

分布式計算(Distributed Computing)

平臺無關性(Independent Platform)

集中管理(Center Government)

用到的技術:

Web Services

關于Web Services,小馬哥文章中講到下面一段話鲫构,因個人技術原因浓恶,暫時沒有特別讀懂,暫且放在這里供大家參考结笨,也歡迎各位大牛指點迷津包晰。

Web Services 技術演進的目的在于解決分布式計算中,統(tǒng)一異構系統(tǒng)的服務調用的通訊協(xié)議炕吸。前期的Web Services有XML-PRC伐憾、WSDL、SOAP等技術赫模,不但解決了Windows平臺COM+以及Java 平臺RMI無法跨平臺的問題树肃,而且使用了可讀性強的本文協(xié)議替代了復雜的二進制協(xié)議,如CORBA技術∑俾蓿現(xiàn)代的WebServices 技術主要代表有REST等胸嘴。

此外,還提到微服務并非等同于單體應用斩祭,我所理解的意思是單體應用只有一個核心劣像,是中心化的,任務是應用整體來完成的摧玫,有較高的耦合度耳奕。而微服務是去中心化的,多核的,將任務拆解屋群,由各個模塊分工協(xié)作完成的时迫,耦合度是較前者要低的。

2谓晌、微服務的優(yōu)勢和適用場景

優(yōu)勢:

(1)效率:應用微服務化后掠拳,變得更加輕量級,在編譯纸肉、打包溺欧、分發(fā)、部署等環(huán)節(jié)節(jié)約時間柏肪,提升效率姐刁;

(2)質量:面向持續(xù)集成友好,自動化編譯烦味、單元和集成測試用例執(zhí)行和回歸聂使,提高整體質量。

這里講的所謂“持續(xù)集成”谬俄,個人不是很清楚這個概念柏靶。

(3)穩(wěn)定:當應用大而全時,一個服務的問題可能會導致整體受到影響溃论。而微服務在服務A調用服務B出現(xiàn)問題時屎蜓,可以選擇降級或熔斷的方式進行處理,等待服務B正常運行后钥勋,恢復正常炬转。

(4)運維:微服務應用具備自動化編譯、打包算灸、分發(fā)扼劈、部署和運維的能力。

(5)成長:對新技術的適配能力菲驴,例如:Apache Kafka荐吵。在重要等級較低的微服務應用上,可以更好的做新技術的嘗試谢翎。

3捍靠、不適用微服務的應用場景

(1)場景單一:如果應用本身規(guī)模就不大,就沒必要使用微服務森逮,因為本身就是一種微服務榨婆。舉例如:一些靜態(tài)通告頁面。

(2)邏輯簡單:微服務是為了解決業(yè)務邏輯復雜性問題褒侧,因此此場景無需微服務良风。

(3)業(yè)務漸逝:如果業(yè)務將要消逝或停用谊迄,就不需要實施了。

(4)“老成持重”:老--服役三年以上的應用烟央;成--應用規(guī)模已經成型统诺;持--應用場景還需要長時間維持湾戳;重--應用屬于系統(tǒng)中較重要的模塊版述。

二、微服務用到的技術

技術上嫩痰,在阿里微服務的實踐過程中也不能免俗钞艇,基本上也是以下三個套路:

Docker

DDD

Middleware(Java)

此處雖然有所講解啄寡,但因主次問題,本文不多做介紹哩照。

大家可以做一下擴展閱讀:

《2016.11.19 微服務實踐之路(廈門) 演講稿》, 次凌均閣(小馬哥微信公眾號)

另外挺物,由于小馬哥提到Thymeleaf,所以網上查閱一些相關資料飘弧。在查閱時识藤,在知乎上發(fā)現(xiàn)了一個beetl和Thymeleaf互懟的帖子,感覺很有意思次伶。雖然只接觸過framemark和vue痴昧,以上兩種都沒有用到過,但是感覺這樣的討論能夠讓自己對一些技術有一些大致的印象学少。道理未必懂得剪个,但學習都是由淺入深,是有一個過程的版确。

三、SpringApplication是什么乎折?

SpringApplication 是 Spring Boot 驅動 Spring 應用上下文的引導類绒疗。

示例:

@SpringBootConfiguration

@EnableAutoConfiguration

@ComponentScan(excludeFilters = {

? ? ? ? @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),

? ? ? ? @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })

public @interface SpringBootApplication {

? ? ...

}

涉及到的注解:

@ComponentScan: 它是版本引入的? Spring Framework 3.1骂澄。

這里強調一種版本意識吓蘑,版本差異所帶來的問題有時是很嚴重的。

@EnableAutoConfiguration: 激活自動裝配

這里擴展了一下坟冲,由@Enable磨镶,提到@Enable 開頭的:

@EnableWebMvc: 是使用Java 注解快捷配置Spring Webmvc的一個注解。

在使用該注解后配置一個繼承于WebMvcConfigurerAdapter的配置類即可配置好Spring Webmvc健提。

通過查看@EnableWebMvc的源碼琳猫,可以發(fā)現(xiàn)該注解就是為了引入一個DelegatingWebMvcConfiguration Java 配置類。并翻看DelegatingWebMvcConfiguration的源碼會發(fā)現(xiàn)該類似繼承于WebMvcConfigurationSupport的類私痹。

其實不使用@EnableWebMvc注解也是可以實現(xiàn)配置Webmvc脐嫂,只需要將配置類繼承于WebMvcConfigurationSupport類即可统刮。

@EnableTransactionManagement: 開啟注解事務管理,等同于xml配置文件中的

@EnableAspectJAutoProxy: 表示開啟AOP代理自動配置账千。

如果配@EnableAspectJAutoProxy表示使用cglib進行代理對象的生成侥蒙;設置@EnableAspectJAutoProxy(exposeProxy=true)表示通過aop框架暴露該代理對象,aopContext能夠訪問匀奏。

從@EnableAspectJAutoProxy的定義可以看得出鞭衩,它引入AspectJAutoProxyRegister.class對象,該對象是基于注解@EnableAspectJAutoProxy注冊一個AnnotationAwareAspectJAutoProxyCreator娃善,該對象通過調用AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);注冊一個aop代理對象生成器醋旦。

@EnableAsync: 表示開啟異步調用支持,配合@Async使用会放。

@SpringBootConfiguration: 等價于 @Configuration -> Configuration Class 注解

此處提個小疑問:

以下關系饲齐,大家應該都了解。

@SpringBootApplication= (默認屬性)@Configuration+@EnableAutoConfiguration+@ComponentScan

但是咧最,我在實際項目使用中捂人,使用@SpringBootApplication注解后,無法掃描到包矢沿,還需要使用@ComponentScan注解滥搭,是因為沒有在SpringApplication后指定掃描路徑?啟動類在外層捣鲸,就算是掃描自身目錄和子包也應該可以找到瑟匆,不知道大家有沒有遇到過類似的問題。

四栽惶、Spring?注解編程模型@Component

@Component

示例:

@Service

@Component

public @interface Service {

? ? ...

}

@Repository

@Component

public @interface Repository {

? ? ...

}

@Controller

@Component

public @interface Controller {

? ? ...

}

@Configuration

@Component

public @interface Configuration {

? ? ...

}

因為注解是沒有繼承關系的愁溜,所以小馬哥講之稱為@Component的“派生性”。

五外厂、Spring?模式注解(Stereotype?Annotations)

Spring 注解驅動示例

注解驅動上下文AnnotationConfigApplicationContext冕象,Spring Framework 3.0開始引入的

示例:

@Configuration

public class SpringAnnotationDemo {

? ? public static void main(String[] args) {

? ? ? ? //? XML 配置文件驅動? ? ? ClassPathXmlApplicationContext

? ? ? ? // Annotation 驅動

? ? ? ? // 找 BeanDefinition

? ? ? ? // @Bean @Configuration

? ? ? ? AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

? ? ? ? // 注冊一個 Configuration Class = SpringAnnotationDemo

? ? ? ? context.register(SpringAnnotationDemo.class);

? ? ? ? // 上下文啟動

? ? ? ? context.refresh();

? ? ? ? System.out.println(context.getBean(SpringAnnotationDemo.class));

? ? }

}

這里講解了兩種Spring注解驅動方式,XML配置文件驅動和Annotation注解驅動汁蝶,現(xiàn)在用的比較多的是Annotation驅動渐扮,經常聽到XML配置方式被群里的大佬們詬病。感覺小項目使用XML配置還可以掖棉,如果項目規(guī)模較大墓律,一堆配置文件就會很頭疼了。

@SpringBootApplication 標注當前一些功能

下列列出的好像是層級關系幔亥,這里記的有些不清楚耻讽。

@SpringBootApplication

@SpringBootConfiguration

@Configuration

@Component

下面看一下 SpringApplication 也就是 Spring Boot 應用的引導方法。

基本寫法

SpringApplication springApplication = new SpringApplication(MicroservicesProjectApplication.class);

? ? ? ? Map properties = new LinkedHashMap<>();

? ? ? ? properties.put("server.port",0);

? ? ? ? springApplication.setDefaultProperties(properties);

? ? ? ? springApplication.run(args);

SpringApplicationBuilder

new SpringApplicationBuilder(MicroservicesProjectApplication.class) // Fluent API

? ? ? ? ? ? ? ? // 單元測試是 PORT = RANDOM

? ? ? ? ? ? ? ? .properties("server.port=0")? // 隨機向 OS 要可用端口

? ? ? ? ? ? ? ? .run(args);

小馬哥提到了兩種書寫風格紫谷,其中一種叫做Fluent API風格齐饮,另外一種沒有聽清捐寥。有沒有大佬知道上面寫法的名稱?

六祖驱、Spring?Boot?引導過程

示例:

@SpringBootApplication

public class MicroservicesProjectApplication {

? ? public static void main(String[] args) {

? ? ? ? SpringApplication springApplication = new SpringApplication(MicroservicesProjectApplication.class);

? ? ? ? Map properties = new LinkedHashMap<>();

? ? ? ? properties.put("server.port",0);

? ? ? ? springApplication.setDefaultProperties(properties);

? ? ? ? ConfigurableApplicationContext context = springApplication.run(args);

? ? ? ? // 有異常握恳?

? ? ? ? System.out.println(context.getBean(MicroservicesProjectApplication.class));

? ? }

}

這個示例運行結果是正常的,springApplication.run(args)和context.getBean(MicroservicesProjectApplication.class)并不會有沖突異常捺僻。

如果沒有記錯乡洼,通過控制臺可以看出,運行了兩次匕坯。實際結果束昵,有條件后運行一下代碼再下定論。

調整示例為 非 Web 程序

示例:

@SpringBootApplication

public class MicroservicesProjectApplication {

? ? public static void main(String[] args) {

? ? ? ? SpringApplication springApplication = new SpringApplication(MicroservicesProjectApplication.class);

? ? ? ? Map properties = new LinkedHashMap<>();

? ? ? ? properties.put("server.port", 0);

? ? ? ? springApplication.setDefaultProperties(properties);

? ? ? ? // 設置為 非 web 應用

? ? ? ? springApplication.setWebApplicationType(WebApplicationType.NONE);

? ? ? ? ConfigurableApplicationContext context = springApplication.run(args);

? ? ? ? // 有異常葛峻?

? ? ? ? System.out.println(context.getBean(MicroservicesProjectApplication.class));

? ? ? ? // 輸出當前 Spring Boot 應用的 ApplicationContext 的類名

? ? ? ? System.out.println("當前 Spring 應用上下文的類:" + context.getClass().getName());

? ? }

}

輸出結果:

當前 Spring 應用上下文的類:org.springframework.context.annotation.AnnotationConfigApplicationContext

配置 Spring Boot 源

SpringAppliation 類型推斷

當不加以設置 Web 類型锹雏,那么它采用推斷:

->SpringAppliation()->deduceWebApplicationType() 第一次推斷為WebApplicationType.SERVLET

WebApplicationType.NONE: 非 Web 類型

Servlet 不存在

Spring Web 應用上下文ConfigurableWebApplicationContext不存在

spring-boot-starter-web不存在

spring-boot-starter-webflux不存在

WebApplicationType.REACTIVE: Spring WebFlux

DispatcherHandler

spring-boot-starter-webflux存在

Servlet 不存在

spring-boot-starter-web不存在

WebApplicationType.SERVLET: Spring MVC

spring-boot-starter-web存在

人工干預 Web 類型

設置 webApplicationType 屬性 為WebApplicationType.NONE

七、SpringBoot事件

Spring 事件

(1)Spring 內部發(fā)送事件

事件發(fā)布:

ContextRefreshedEvent

ApplicationContextEvent

ApplicationEvent

refresh() ->finishRefresh()->publishEvent(new ContextRefreshedEvent(this));

事件關閉:

ContextClosedEvent

ApplicationContextEvent

ApplicationEvent

close()->doClose()->publishEvent(new ContextClosedEvent(this));

(2)自定義事件

PayloadApplicationEvent

Spring 事件 都是ApplicationEvent類型

發(fā)送 Spring 事件通過ApplicationEventMulticaster#multicastEvent(ApplicationEvent, ResolvableType)

Spring 事件的類型ApplicationEvent

Spring 事件監(jiān)聽器ApplicationListener

Spring 事件廣播器ApplicationEventMulticaster

實現(xiàn)類:SimpleApplicationEventMulticaster

Spring 事件理解為消息

ApplicationEvent相當于消息內容

ApplicationListener相當于消息消費者术奖、訂閱者

ApplicationEventMulticaster相當于消息生產者礁遵、發(fā)布者

注意:不能只發(fā)布事件,沒有監(jiān)聽采记。否則佣耐,啟動程序是獲取不到任何事件的。

這里提到了“監(jiān)聽者模式”唧龄,大家應該都會聯(lián)想到“觀察者模式”兼砖,兩者很相似,所以我去查閱了一些參考資料:

設計模式之監(jiān)聽模式(觀察者模式與監(jiān)聽模式區(qū)別)

設計模式之觀察者模式, 個人感覺相當?shù)闹匾?七)

個人理解:

監(jiān)聽者模式包含事件源既棺、事件和監(jiān)聽器讽挟,像是半自動化的監(jiān)聽,需要手動或者說是人工對事件源和事件做處理援制,然后提供給監(jiān)聽器戏挡;觀察者模式包含觀察者和被觀察者(也就是事件),像是自動化監(jiān)聽晨仑,只需要對事件負責即可。

監(jiān)聽者模式更加靈活拆檬,比較適用于需要自我把控的場景洪己,比如底層框架的實現(xiàn):spring框架的ApplicationEvent,ApplicationListener。

觀察者模式更加輕便竟贯,比較適用于約束比較固定的場景答捕,比如前臺按鈕的點擊事件,至于屑那,后臺用到觀察者模式的場景暫時沒有想到拱镐。

Spring Boot 事件監(jiān)聽示例

示例:

@EnableAutoConfiguration

public class SpringBootEventDemo {

? ? public static void main(String[] args) {

? ? ? ? new SpringApplicationBuilder(SpringBootEventDemo.class)

? ? ? ? ? ? ? ? .listeners(event -> { // 增加監(jiān)聽器

? ? ? ? ? ? ? ? ? ? System.err.println("監(jiān)聽到事件 : " + event.getClass().getSimpleName());

? ? ? ? ? ? ? ? })

? ? ? ? ? ? ? ? .run(args)

? ? ? ? ? ? ? ? .close();

? ? ? ? ; // 運行

? ? }

}

通過運行程序可知艘款,事件的運行順序(括號中是官方文檔中標注的順序,好像官方文檔中只提到了Application開頭的事件沃琅,沒有啟動過程中看到的Context和Servlet事件):

ApplicationStartingEvent(1) 啟動

ApplicationEnvironmentPreparedEvent(2) 環(huán)境配置

ApplicationPreparedEvent(3) 這里應該是

ContextRefreshedEvent 創(chuàng)建上下文context

ServletWebServerInitializedEvent

ApplicationStartedEvent(4)

ApplicationReadyEvent(5)

ContextClosedEvent

ApplicationFailedEvent (特殊情況)(6)

最后一種是啟動失敗的情況哗咆,所以做了特殊標注。

此外益眉,這里提到了lambda表達式:

event -> { // 增加監(jiān)聽器

? ? ? ? ? ? ? ? ? ? System.err.println("監(jiān)聽到事件 : " + event.getClass().getSimpleName());

? ? ? ? ? ? ? ? }

之前沒有接觸過晌柬,在此貼上兩篇文章:

Java中Lambda表達式的使用

Lambda表達式詳細總結

Spring Boot 事件監(jiān)聽器

org.springframework.context.ApplicationListener=\

org.springframework.boot.ClearCachesApplicationListener,\

org.springframework.boot.builder.ParentContextCloserApplicationListener,\

org.springframework.boot.context.FileEncodingApplicationListener,\

org.springframework.boot.context.config.AnsiOutputApplicationListener,\

org.springframework.boot.context.config.ConfigFileApplicationListener,\

org.springframework.boot.context.config.DelegatingApplicationListener,\

org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\

org.springframework.boot.context.logging.LoggingApplicationListener,\

org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener

ConfigFileApplicationListener監(jiān)聽ApplicationEnvironmentPreparedEvent事件從而加載 application.properties 或者 application.yml 文件。

Spring Boot 很多組件依賴于 Spring Boot 事件監(jiān)聽器實現(xiàn)郭脂,本質是 Spring Framework 事件/監(jiān)聽機制年碘。

SpringApplication利用:

Spring 應用上下文(ApplicationContext)生命周期控制 注解驅動 Bean

Spring 事件/監(jiān)聽(ApplicationEventMulticaster)機制加載或者初始化組件

擴展問題:

q1:webApplicationType分為三種,都有什么實用地方

個人鄙見:

類型為SERVLET時展鸡,就是常用的web服務屿衅,受眼界所限,我了解的大部分項目都可以使用這種類型莹弊。是不是因為常用涤久,所以才會將SERVLET設置為默認類型?

類型為NONE時箱硕,意味著該應用啟動后拴竹,不會加載任何東西。是不是在啟動時需要做情況判斷的時候可以用到剧罩?

類型為REACTIVE時栓拜,支持響應式編程,響應式編程是基于異步和事件驅動的非阻塞程序惠昔。

響應式編程技術上有RxJava等幕与,可以提高代碼的抽象程度,讓開發(fā)者能夠更加專注于業(yè)務邏輯镇防。我覺得響應式編程可以將業(yè)務拆解成細粒度的事件啦鸣,一方面代碼維護性好(專注于業(yè)務邏輯,忽略具體實現(xiàn))来氧,另一方面能夠更好地應對業(yè)務邏輯的更改(有可能只需要改變部分環(huán)節(jié)的事件邏輯)诫给。

參考資料:

響應式編程介紹

響應式編程,是明智的選擇

響應式設計的優(yōu)勢有哪些啦扬?

Rxjava(3.響應式編程好處)

q2:框架底層的事件是單線程么中狂?業(yè)務實現(xiàn)是否可以使用事件去實現(xiàn)?如果使用事件實現(xiàn)是不是會有性能問題扑毡?

public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {

? ? @Nullable

? ? private Executor taskExecutor;

? ? ...

}

個人鄙見:

從SpringBoot事件運行示例來看胃榕,是單線程、順序執(zhí)行瞄摊。至于使用事件來實現(xiàn)業(yè)務勋又,這方面確實不甚清楚苦掘。

總結

本人野生碼農一枚,今日新手上路楔壤,不敢太過造次鹤啡,也不想因自己不知所謂的看法誤導大家。文中的問題挺邀,待我證實以后揉忘,再做修改。

謹此端铛,止筆泣矛。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市禾蚕,隨后出現(xiàn)的幾起案子您朽,更是在濱河造成了極大的恐慌,老刑警劉巖换淆,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哗总,死亡現(xiàn)場離奇詭異,居然都是意外死亡倍试,警方通過查閱死者的電腦和手機讯屈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來县习,“玉大人涮母,你說我怎么就攤上這事≡暝福” “怎么了叛本?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長彤钟。 經常有香客問我来候,道長,這世上最難降的妖魔是什么逸雹? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任营搅,我火速辦了婚禮,結果婚禮上梆砸,老公的妹妹穿的比我還像新娘剧防。我一直安慰自己,他們只是感情好辫樱,可當我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著俊庇,像睡著了一般狮暑。 火紅的嫁衣襯著肌膚如雪鸡挠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天搬男,我揣著相機與錄音拣展,去河邊找鬼。 笑死缔逛,一個胖子當著我的面吹牛备埃,可吹牛的內容都是我干的。 我是一名探鬼主播褐奴,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼按脚,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了敦冬?” 一聲冷哼從身側響起辅搬,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎脖旱,沒想到半個月后堪遂,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡萌庆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年溶褪,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片践险。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡猿妈,死狀恐怖,靈堂內的尸體忽然破棺而出捏境,到底是詐尸還是另有隱情于游,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布垫言,位于F島的核電站贰剥,受9級特大地震影響,放射性物質發(fā)生泄漏筷频。R本人自食惡果不足惜蚌成,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望凛捏。 院中可真熱鬧担忧,春花似錦、人聲如沸坯癣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至惩猫,卻和暖如春芝硬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背轧房。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工拌阴, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人奶镶。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓迟赃,卻偏偏與公主長得像,于是被迫代替她去往敵國和親厂镇。 傳聞我的和親對象是個殘疾皇子纤壁,可洞房花燭夜當晚...
    茶點故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內容