Gradle介紹

前言

構(gòu)建,軟件生命周期中重要的一環(huán),在現(xiàn)代軟件開發(fā)過程中嫡意,起著越來越重要的作用酷窥。過去在Java或類Java的世界里,Ant宾添、Maven再熟悉不過了,Maven憑借其強(qiáng)大的依賴配置戰(zhàn)勝Ant,基本上成為了Java構(gòu)建的標(biāo)準(zhǔn)滔驾。而在現(xiàn)代,系統(tǒng)日益復(fù)雜俄讹,構(gòu)建的靈活性要求越來越高哆致,比如:構(gòu)建過程中需要打包上傳到服務(wù)器,Maven無法很好地支持這種復(fù)雜的系統(tǒng)構(gòu)建患膛,所以摊阀,我選擇了Gradle,一個基于Groovy踪蹬,更靈活更強(qiáng)大的構(gòu)建系統(tǒng)胞此,能幫助我們構(gòu)建更復(fù)雜的項(xiàng)目。

為什么選擇Gradle

從框架方向來看:

 1. Gradle是很成熟的技術(shù)延曙,可以處理大規(guī)模構(gòu)建     
 2. Gradle對多語言豌鹤、多平臺有更natural的支持 
 3. Gradle關(guān)注在構(gòu)建效率上
 4. Gradle發(fā)布很頻繁,重要feature開發(fā)計(jì)劃透明化
 5. Gradle社區(qū)很活躍枝缔,并且增加迅速

從語言特性來看:

 1. 代碼很精簡
 2. Gradle基于Groovy布疙,能完成復(fù)雜系統(tǒng)的構(gòu)建任務(wù)
 3. DSL比XML更簡潔高效

Gradle在開源項(xiàng)目中的使用

現(xiàn)在使用Gradle構(gòu)建的開源項(xiàng)目很多蚊惯,我有過接觸的比如:Grails, Griffon, Groovy, Hibernate, Spring

還有很多其它開源項(xiàng)目也都在用Gradle,比如Tapestry灵临,Qi4J截型,Netflix下所有開源項(xiàng)目(python、c++儒溉、html等除外)等等宦焦。

Gradle在企業(yè)中的使用

現(xiàn)在使用Gradle來做構(gòu)建體系的公司也越來越多,linkedin就很早開始切換到Gradle顿涣。

Gradle體驗(yàn)

Gradle的安裝非常方便波闹,下載ZIP包,解壓到本地目錄涛碑,設(shè)置 GRADLE_HOME 環(huán)境變量并將 GRADLE_HOME/bin 加到 PATH 環(huán)境變量中精堕,安裝就完成了。用戶可以運(yùn)行g(shù)radle -v命令驗(yàn)證安裝蒲障,這些初始的步驟和Maven沒什么兩樣歹篓。我這里安裝的Gradle版本是1.10,詳細(xì)信息見下:

bob [10:42]  ? gradle -v
Gradle 1.10
------------------------------------------------------------
Build time:   2013-12-17 09:28:15 UTC
Build number: none
Revision:     36ced393628875ff15575fa03d16c1349ffe8bb6
Groovy:       1.8.6
Ant:          Apache Ant(TM) version 1.9.2 compiled on July 8 2013
Ivy:          2.2.0
JVM:          1.7.0_45 (Oracle Corporation 24.45-b08)
OS:           Mac OS X 10.9.2 x86_64

Gradle的Features很多揉阎,官網(wǎng)doc介紹很詳細(xì)庄撮,我這里就不多說。下面簡單介紹一下Gradle構(gòu)建相關(guān)的東西毙籽。

Gradle基礎(chǔ)

  1. Gradle有兩個最基本的概念:project和task洞斯。Gradle里面的所有東西都基于這兩個概念。project通常指一個項(xiàng)目惧财,而task指構(gòu)建過程中的任務(wù)巡扇。一次構(gòu)建可以有1到n個project,每個project有1到n個task垮衷。
  2. Gradle有一個類似Maven中pom.xml的配置文件:build.gradle厅翔。功能也基本一樣,負(fù)責(zé)當(dāng)前project的構(gòu)建定義搀突〉睹疲看一個build.gradle的簡單例子:
    bob [10:46]  ? pwd
    /Users/bob/framework/gradle-1.10/samples/userguide/tutorial/hello
    // 在你安裝的gradle根目錄下有對應(yīng)的samples目錄,里面有很多例子
    
    bob [10:46]  ? cat build.gradle
    task hello {
        doLast {
            println 'Hello world!'
        }
    }

文件中定義了一個task:hello仰迁,task的內(nèi)容是 "println 'Hello world!'"甸昏,我們來執(zhí)行一下:

bob [10:49]  ? gradle -q hello
Hello world!

可以看到,輸出了"Hello world!"徐许,這里-q的意思是quiet模式施蜜,只輸出構(gòu)建中的必要信息。

gradle里可以定義多個task雌隅,task之間也可以有依賴關(guān)系翻默,還可以定義默認(rèn)task缸沃,看一個例子:
帶有task依賴關(guān)系:

bob [10:53]  ? cat userguide/tutorial/lazyDependsOn/build.gradle
task taskX(dependsOn: 'taskY') << {
    println 'taskX'
}
task taskY << {
    println 'taskY'
}

帶有默認(rèn)task例子:

bob [10:59]  ? cat userguide/tutorial/defaultTasks/build.gradle
defaultTasks 'clean', 'run'


task clean << {
    println 'Default Cleaning!'
}

task run << {
    println 'Default Running!'
}

task other << {
    println "I'm not a default task!"
}

看看執(zhí)行情況:

bob [10:59]  ? gradle -q
Default Cleaning!
Default Running!

bob [11:00]  ? gradle -q other
I'm not a default task!

默認(rèn)task,當(dāng)沒有task指定時修械,則會執(zhí)行默認(rèn)的task趾牧。

Gradle依賴

Gradle和Maven在依賴管理上幾乎差不多,核心的概念是一樣的肯污,只不過Gradle語法更精簡翘单,并且多了一些更靈活的自定義配置。我們先看一個例子蹦渣,Maven的pom.xml:

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
    </dependency>
</dependencies>

更換成Gradle腳本哄芜,結(jié)果是這樣:

dependencies {
    compile('org.springframework:spring-core:3.2.4.RELEASE')
    compile('org.springframework:spring-beans:3.2.4.RELEASE')
    compile('org.springframework:spring-context:3.2.4.RELEASE')
    testCompile('junit:junit:4.7')
}

代碼塊少了很多。試想柬唯,生產(chǎn)環(huán)境下的中忠烛、大型應(yīng)用如果用都用Gradle替換Maven,那勢必會大大減少配置文件代碼塊权逗,并有更強(qiáng)的可讀性,也就意味著系統(tǒng)更加穩(wěn)健冤议。

  1. Gradle在依賴配置上面斟薇,和Maven一樣,支持傳遞性依賴恕酸,然后和Maven不同的是堪滨,它還支持排除傳遞性依賴以及關(guān)閉傳遞性依賴。
  2. Gradle的依賴scope蕊温,也基本和Maven一樣袱箱,不過它是通過配置來定義,plugin來支撐和加強(qiáng)的义矛,所以除了基本的compile发笔、runtime等scope外,Gradle還可以自定義出很多配置凉翻,針對不同的配置寫不同的task來完成更復(fù)雜更靈活的構(gòu)建任務(wù)了讨。

依賴相關(guān)的倉庫配置很靈活,支持多種repository制轰,看下面repository定義例子:

bob [11:07]  ? cat userguide/artifacts/defineRepository/build.gradle

repositories {
    mavenCentral()          // 定義倉庫為maven中心倉庫
}
repositories {
    jcenter()               // 定義倉庫為jcenter倉庫
}
repositories {
    maven {
        url "http://repo.mycompany.com/maven2"      // 定義依賴包協(xié)議是maven前计,地址是公司的倉庫地址
    }
}
repositories {                              // 定義本地倉庫目錄
    flatDir {
        dirs 'lib'
    }
}
repositories {                              // 定義ivy協(xié)議類型的倉庫
    ivy {
        url "http://repo.mycompany.com/repo"
    }
}

可以看到,對于常用的maven垃杖、ivy男杈、local以及jcenter的repository都有支持,語法很簡單调俘。而且還可以通過編寫task來支持更復(fù)雜的repository伶棒,更多詳情可以查看安裝包里的對應(yīng)目錄下文件查看旺垒。

Gradle構(gòu)建

和Maven一樣,Gradle也是通過artifact來打包構(gòu)建的苞冯。得益于上述的Gradle本身的特性袖牙,artifact在Gradle里實(shí)現(xiàn)得更靈活一些【顺看一個例子:

bob [13:00]  ? cat userguide/artifacts/uploading/build.gradle

## jar類型的artifact
task myJar(type: Jar)
artifacts {
    archives myJar
}
## file類型的artifact
def someFile = file('build/somefile.txt')
artifacts {
    archives someFile
}

## 根據(jù)自定義task來完成artifact
task myTask(type:  MyTaskType) {
    destFile = file('build/somefile.txt')
}
artifacts {
    archives(myTask.destFile) {
        name 'my-artifact'
        type 'text'
        builtBy myTask
    }
}

## 根據(jù)自定義task來完成artifact
task generate(type:  MyTaskType) {
    destFile = file('build/somefile.txt')
}
artifacts {
    archives file: generate.destFile, name: 'my-artifact', type: 'text', builtBy: generate
}

這樣就簡單地定義了好幾種artifact生成的定義鞭达,根據(jù)不同的場景需求,生成文本文件皇忿、jar包或者zip畴蹭,還可以再上傳到服務(wù)器上。

一般情況下鳍烁,常用的插件叨襟,比如說"Java plugin"都默認(rèn)定義了"jar"這樣的artifact task,所以一般不需要額外開發(fā)幔荒。但是糊闽,針對于一些復(fù)雜情況,或者在plugin基礎(chǔ)上增強(qiáng)的話爹梁,自定義artifact task還是非常有用的右犹。

Gradle構(gòu)建的項(xiàng)目,發(fā)布到倉庫中姚垃,也非常容易:

apply plugin: 'maven'

uploadArchives {
    repositories {
        ivy {
            credentials {
                username "username"
                password "pw"
            }
            url "http://repo.mycompany.com"
        }
    }
}

Gradle 插件

上面簡介介紹了一下Gradle的一些概念和配置念链,要用到項(xiàng)目中run起來,現(xiàn)在還還要一步积糯,就是本節(jié)介紹的Gradle插件掂墓。Gradle現(xiàn)在已經(jīng)支持很多插件,這給開發(fā)者帶來極大的便利看成,先說說Java插件吧君编。

  1. 使用Java plugin,只需要在build.gradle中加入這句話:
    apply plugin: 'java'
    
  2. 了解或設(shè)置Java project布局绍昂。Gradle和Maven一樣啦粹,采用了“約定優(yōu)于配置”的方式對Java project布局,并且布局方式是和Maven一樣的窘游,此外唠椭,Gradle還可以方便的自定義布局。在Gradle中忍饰,一般把這些目錄叫做source set贪嫂。看下官方的答案:


    Alt description

這里要注意艾蓝,每個plugin的source set可能都不一樣力崇。

同樣的斗塘,Java plugin還定義好了一堆task,讓我們可以直接使用亮靴,比如:clean馍盟、test、build等等茧吊。這些task都是圍繞著Java plugin的構(gòu)建生命周期的:

Alt description

圖中每一塊都是一個task贞岭,箭頭表示task執(zhí)行順序/依賴,比如執(zhí)行task jar搓侄,那么必須先執(zhí)行task compileJava和task processResources瞄桨。另外可以看到,Gradle的Java plugin構(gòu)建生命周期比較復(fù)雜讶踪,但是也表明了更加靈活芯侥,而且,在項(xiàng)目中乳讥,一般只使用其中常用的幾個:clean test check build 等等柱查。

gradle構(gòu)建過程中,所有的依賴都表現(xiàn)為配置云石,比如說系統(tǒng)運(yùn)行時的依賴是runtime物赶,gradle里有一個依賴配置叫runtime,那么系統(tǒng)運(yùn)行時會加載這個依賴配置以及它的相關(guān)依賴留晚。這里說的有點(diǎn)繞,可以簡單理解依賴和maven類似告嘲,只不過gradle用configuration實(shí)現(xiàn)错维,所以更靈活,有更多選擇橄唬。下圖是依賴配置關(guān)系圖以及和task調(diào)用的關(guān)系圖:

Alt description

可以看到赋焕,基本和Maven是一樣的。其實(shí)Gradle里面這些依賴(scope)都是通過configuration來實(shí)現(xiàn)的仰楚,這里就不細(xì)說隆判,有興趣的可以研究一下官方資料。

關(guān)于“約定優(yōu)于配置”僧界,還有很多東西侨嘀,這里不細(xì)說,官方doc已經(jīng)說的很詳細(xì)了捂襟。

Gradle 其它不錯的特性

  1. 所有聲明都是一等公民
  2. 多project構(gòu)建
  3. 引用外部/通用構(gòu)建腳本
  4. Gradle wrapper

小結(jié)

  1. Gradle非常簡潔咬腕,項(xiàng)目本身的配置代碼非常少。
  2. Gradle在外部project構(gòu)建也支持很好葬荷,整體構(gòu)建簡單涨共,并且通過公用外部構(gòu)建腳本纽帖,讓配置內(nèi)容盡量沒有冗余。
  3. Gradle很靈活举反,可以方面的增加和修改構(gòu)建過程懊直。而Maven卻需要開發(fā)插件來支持。
  4. Gradle是基于Groovy的火鼻,也就是說配置中可以編寫自定義代碼室囊,能適應(yīng)更復(fù)雜的場景,能完成更強(qiáng)大的功能凝危,比如說:自動上傳波俄、分發(fā)、部署等等蛾默。

項(xiàng)目實(shí)戰(zhàn)

Gradle介紹了那么多懦铺,可以看出,gradle是非常靈活的支鸡,可以適應(yīng)各種復(fù)雜環(huán)境冬念。建議各位從架構(gòu)角度考慮gradle構(gòu)建,而不僅僅把它當(dāng)作一個構(gòu)建工具牧挣。下面來說說我們實(shí)際項(xiàng)目中的Gradle改造工作急前。

背景:

我們的項(xiàng)目經(jīng)過一個半Q的迅速發(fā)展,整個項(xiàng)目已經(jīng)由1個簡易后臺變成4個系統(tǒng)+若干腳本任務(wù)了瀑构,項(xiàng)目中存在很多冗余代碼和重復(fù)配置裆针。我們使用上面介紹的方法對項(xiàng)目進(jìn)行了改造,以解決這兩個問題寺晌。

步驟:

要解決冗余代碼和通用配置的問題世吨,最簡單的做法就是抽取出共同部分,作為其它所有項(xiàng)目的parent/common項(xiàng)目呻征。方法:

1. 使用git submodule

將所有系統(tǒng)中公共的類庫和通用的配置耘婚,放到獨(dú)立的倉庫Common中。因?yàn)槲覀冇胓it來管理代碼陆赋,而git本身提倡多branch沐祷,多倉庫,所以采用git submodule方式攒岛,其它項(xiàng)目需要添加Common這個submodule:

git submodule add yourGitRepo deps/Common

最后的"deps/Common"是自定義的赖临,意思就是在當(dāng)前的deps目錄下用Common名字來當(dāng)作submodule的clone。

如果你clone別的帶有submodule的項(xiàng)目時灾锯,默認(rèn)情況下思杯,當(dāng)前的project并不會把submodule的代碼都clone下來,可以執(zhí)行:

git submodule foreach git pull

以下這段一般大家經(jīng)常會遇到:
當(dāng)你clone項(xiàng)目時,submodule會以最新的master分支上的commit id作為本次的tag下載色乾,類似一個副本誊册,因?yàn)橐话愦蠹叶际怯胹ubmodule,而不是修改它暖璧。所以當(dāng)你的submodule需要更新的時候案怯,需要先執(zhí)行這段代碼:

git submodule foreach git checkout master

讓submodule切換到master分支了,然后就可以用上面的submodule pull來更新了澎办。

2. gradle構(gòu)建:

鑒于上文對gradle優(yōu)點(diǎn)的描述嘲碱,我們采用gradle來構(gòu)建。我們的項(xiàng)目最初都是基于maven來構(gòu)建的局蚀,從maven切換到gradle很簡單麦锯,在項(xiàng)目根目錄下,先執(zhí)行(假設(shè)你的機(jī)器已經(jīng)安裝了gradle環(huán)境琅绅,一般負(fù)責(zé)構(gòu)建的人首次需要安裝扶欣,開發(fā)人員可以不安裝):

gradle init wrapper

這樣,就會自動生成相關(guān)的gradlew千扶,build.gradle料祠,settings.gradle等文件和相關(guān)目錄,并會自動下載對應(yīng)版本的gradle binary包(所以以后不需要安裝)澎羞。Gradle會自動識別Maven里的配置髓绽,并相應(yīng)的導(dǎo)入進(jìn)來,有少量部分配置可能需要修改妆绞。

注:在已有的gradle項(xiàng)目里顺呕,盡量使用生成的gradlew這個wrapper,因?yàn)樗鼤詣酉螺d對應(yīng)版本的Gradle括饶,也就是說團(tuán)隊(duì)合作的其他人開發(fā)機(jī)上是不需要手動安裝Gradle的塘匣,并且wrapper也讓大家的Gradle版本一致,避免問題巷帝。

3. gradle腳本修改

上面執(zhí)行完之后,環(huán)境已經(jīng)準(zhǔn)備好了扫夜,現(xiàn)在要做的就是修改構(gòu)建腳本:
因?yàn)橐呀?jīng)通過git submodule把公共項(xiàng)目放到獨(dú)立目錄(deps/Common)了楞泼,并且它本身也是獨(dú)立可構(gòu)建的項(xiàng)目,那么也就是說當(dāng)前有兩個項(xiàng)目了笤闯,一個是當(dāng)前project堕阔,一個是Common項(xiàng)目,要做的就是告訴gradle颗味,要多項(xiàng)目構(gòu)建超陆,編輯settings.gradle,增加項(xiàng)目配置:

include "deps:Common"

以上就是把Common引入到當(dāng)前項(xiàng)目了。
根據(jù)項(xiàng)目的不同时呀,然后對應(yīng)修改build.gradle张漂,就大功告成了〗髂龋看一個例子:

// 這一段主要是把公共庫Common的構(gòu)建腳本引入航攒,因?yàn)橐话銜型ㄓ玫呐渲迷诶锩?def userGradleScript = file("deps/Common/build.gradle")
if (userGradleScript.exists()) {
    apply from: userGradleScript
}
// 使用war插件,這樣就默認(rèn)引入了java插件
apply plugin: 'war'
// for jetty
apply plugin: 'jetty'
stopKey = 'yourStopKey' // 自定義的stopkey
stopPort = xxxx     // 停止端口
httpPort = xxxx     // 啟動http端口

// 項(xiàng)目屬性
group = 'yourApp'
version = '1.0.0'
description = """這里描述你的項(xiàng)目"""


// checkstyle config文件地址
checkstyle {
    configFile = file("deps/Common/config/checkstyle/checkstyle.xml")
}
// lib依賴
dependencies {
    // 依賴公共庫Common趴梢,compile是和maven里的compile scope一樣
    compile project(':deps:Common')
    compile 'commons-validator:commons-validator:1.4.0'
    compile('javax.servlet.jsp.jstl:jstl-api:1.2') {
        exclude(module: 'servlet-api')      // 防止版本沖突
    }
    compile 'javax.persistence:persistence-api:1.0.2'
    runtime 'mysql:mysql-connector-java:5.1.26'
    providedCompile 'org.apache.tomcat:tomcat-servlet-api:7.0.30'
    // providedCompile 這個conf在java插件里是報錯的漠畜,war里是正確的
    providedCompile 'javax.servlet.jsp:jsp-api:2.1'
    ...
}

我們再來簡單看下公共項(xiàng)目Common的構(gòu)建腳本:

// 定義一堆基礎(chǔ)插件
apply plugin: 'java'
apply plugin: 'maven'
apply plugin: "jacoco"
apply plugin: 'checkstyle'
apply plugin: 'pmd'
apply plugin: 'findbugs'
apply plugin: 'eclipse'
apply plugin: 'idea'
// 定義項(xiàng)目屬性
group = 'Common'
version = '1.0.0'
description = """Giant common library"""

// 定義依賴倉庫
repositories {
    mavenCentral()
}
// project的額外屬性,這里用于定義profile屬性坞靶,模擬maven的profile
ext {
    if (project.hasProperty('profile')) {
        profile = project['profile']
    } else {
        profile = "dev"
    }
    println "profile:" + profile
}
// 額外增加source path
sourceSets {
    main {
        resources {
            srcDir "src/main/profiles/${profile}"
        }
    }
}
// project依賴
dependencies {
    compile 'ch.qos.logback:logback-core:1.0.13'
    compile 'ch.qos.logback:logback-classic:1.0.13'
    compile 'ch.qos.logback:logback-access:1.0.13'
    compile 'commons-io:commons-io:2.0.1'
    compile 'commons-lang:commons-lang:2.6'
    compile 'joda-time:joda-time:1.6.2'
    compile 'org.testng:testng:6.8.7'
    compile 'com.googlecode.jmockit:jmockit:1.5'
    ...
}
// task配置
checkstyle {
    ignoreFailures = true
    sourceSets = [sourceSets.main]
}
findbugs {
    ignoreFailures = true
    sourceSets = [sourceSets.main]
}
pmd {
    ruleSets = ["basic", "braces", "design"]
    ignoreFailures = true
    sourceSets = [sourceSets.main]
}
jacocoTestReport {
    reports {
        xml.enabled true
        html.enabled true
        csv.enabled false
    }
    sourceSets sourceSets.main
}
tasks.withType(Compile) {
    options.encoding = "UTF-8"
}
test {
    useTestNG()
    jacoco {
        excludes = ["org.*"]
    }
}

這樣憔狞,就可以在公共項(xiàng)目里配置好一堆基礎(chǔ)的task,dependencies等等彰阴,而使用這個公共項(xiàng)目的其它項(xiàng)目則可以直接使用瘾敢,無需再額外配置。

4. run

腳本修改完了硝枉,就可以開始構(gòu)建了(不需要安裝gradle廉丽,直接使用生成的gradlew就行):

./gradlew build

// 基于profile構(gòu)建
./gradlew -Pprofile=dev build

常用構(gòu)建命令:

  • clean:清除之前的構(gòu)建
  • test:執(zhí)行測試
  • compileJava:編譯java
  • check:在test之后做一個check,一般代碼檢查插件妻味,都是在這個階段做的
  • build:構(gòu)建打包

總結(jié)

隨著公司業(yè)務(wù)的發(fā)展正压,軟件系統(tǒng)變得日益復(fù)雜和龐大,這就要求有更靈活责球、更高效的構(gòu)建系統(tǒng)來支撐〗孤模現(xiàn)代構(gòu)建系統(tǒng)Gradle提供了強(qiáng)大的功能、簡潔的語法雏逾、靈活的配置嘉裤,能適應(yīng)各種復(fù)雜的構(gòu)建環(huán)境。利用多project構(gòu)建栖博,讓整個系統(tǒng)模塊化屑宠,管理更高效。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末仇让,一起剝皮案震驚了整個濱河市典奉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌丧叽,老刑警劉巖卫玖,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異踊淳,居然都是意外死亡假瞬,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來脱茉,“玉大人剪芥,你說我怎么就攤上這事÷樱” “怎么了粗俱?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長虚吟。 經(jīng)常有香客問我寸认,道長,這世上最難降的妖魔是什么串慰? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任偏塞,我火速辦了婚禮,結(jié)果婚禮上邦鲫,老公的妹妹穿的比我還像新娘灸叼。我一直安慰自己,他們只是感情好庆捺,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布古今。 她就那樣靜靜地躺著,像睡著了一般滔以。 火紅的嫁衣襯著肌膚如雪捉腥。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天你画,我揣著相機(jī)與錄音抵碟,去河邊找鬼。 笑死坏匪,一個胖子當(dāng)著我的面吹牛拟逮,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播适滓,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼敦迄,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了凭迹?” 一聲冷哼從身側(cè)響起罚屋,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蕊苗,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體沿彭,經(jīng)...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡朽砰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瞧柔。...
    茶點(diǎn)故事閱讀 40,567評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡漆弄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出造锅,到底是詐尸還是另有隱情撼唾,我是刑警寧澤,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布哥蔚,位于F島的核電站倒谷,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏糙箍。R本人自食惡果不足惜渤愁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望深夯。 院中可真熱鬧抖格,春花似錦、人聲如沸咕晋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽掌呜。三九已至滓玖,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間站辉,已是汗流浹背呢撞。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留饰剥,地道東北人殊霞。 一個月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像汰蓉,于是被迫代替她去往敵國和親绷蹲。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,585評論 2 359

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理顾孽,服務(wù)發(fā)現(xiàn)祝钢,斷路器,智...
    卡卡羅2017閱讀 134,702評論 18 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,859評論 6 342
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,302評論 25 707
  • 微博每隔一段時間就能爆出娛樂圈誰誰誰出軌了若厚,然后原配拦英、小三甚至是之前出過軌被唾罵的明星們紛紛進(jìn)了熱門頭...
    鱈零kelsey閱讀 249評論 0 0
  • 游綠城廣場,學(xué)瑞鵬精神 2017年7月5日肖靜 天氣相較于前幾日氣溫有所下降测秸,今天疤估,我們小紅旗實(shí)踐隊(duì)來到了綠城廣場...
    我想靜靜_24d6閱讀 269評論 0 0