商城項目搭建

0.學習目標

  • 了解電商行業(yè)
  • 了解樂優(yōu)商城項目結(jié)構(gòu)
  • 能獨立搭建項目基本框架
  • 能參考使用ES6的新語法

1.了解電商行業(yè)

學習電商項目,自然要先了解這個行業(yè),所以我們首先來聊聊電商行業(yè)

1.1.項目分類

主要從需求方、盈利模式、技術(shù)側(cè)重點這三個方面來看它們的不同

1.1.1.傳統(tǒng)項目

各種企業(yè)里面用的管理系統(tǒng)(ERP挂签、HR兑凿、OA凯力、CRM、物流管理系統(tǒng)礼华。咐鹤。。圣絮。祈惶。。扮匠。)

  • 需求方:公司捧请、企業(yè)內(nèi)部
  • 盈利模式:項目本身賣錢
  • 技術(shù)側(cè)重點:業(yè)務(wù)功能

1.1.2.互聯(lián)網(wǎng)項目

門戶網(wǎng)站、電商網(wǎng)站:baidu.com棒搜、qq.com疹蛉、taobao.com、jd.com ......

  • 需求方:廣大用戶群體
  • 盈利模式:虛擬幣力麸、增值服務(wù)可款、廣告收益......
  • 技術(shù)側(cè)重點:網(wǎng)站性能、業(yè)務(wù)功能

而我們今天要聊的就是互聯(lián)網(wǎng)項目中的重要角色:電商

1.2.電商行業(yè)的發(fā)展

1.2.1.錢景

近年來克蚂,中國的電子商務(wù)快速發(fā)展闺鲸,交易額連創(chuàng)新高,電子商務(wù)在各領(lǐng)域的應(yīng)用不斷拓展和深化埃叭、相關(guān)服務(wù)業(yè)蓬勃發(fā)展摸恍、支撐體系不斷健全完善、創(chuàng)新的動力和能力不斷增強赤屋。電子商務(wù)正在與實體經(jīng)濟深度融合立镶,進入規(guī)模性發(fā)展階段壁袄,對經(jīng)濟社會生活的影響不斷增大,正成為我國經(jīng)濟發(fā)展的新引擎谜慌。

中國電子商務(wù)研究中心數(shù)據(jù)顯示然想,截止到 2012 年底,中國電子商務(wù)市場交易規(guī)模達 7.85萬億人民幣欣范,同比增長 30.83%变泄。其中,B2B 電子商務(wù)交易額達 6.25 萬億恼琼,同比增長 27%妨蛹。而 2011 年全年,中國電子商務(wù)市場交易額達 6 萬億人民幣晴竞,同比增長 33%蛙卤,占 GDP 比重上升到 13%;2012 年噩死,電子商務(wù)占 GDP 的比重已經(jīng)高達 15%颤难。

1525686041466.png

1.2.2.數(shù)據(jù)

來看看雙十一的成交數(shù)據(jù):

1525686135308.png
1525686160411.png

2016雙11開場30分鐘,創(chuàng)造每秒交易峰值17.5萬筆已维,每秒支付峰值12萬筆的新紀錄行嗤。菜鳥單日物流訂單量超過4.67億,創(chuàng)歷史新高垛耳。

1.2.3.技術(shù)特點

從上面的數(shù)據(jù)我們不僅要看到錢栅屏,更要看到背后的技術(shù)實力。正是得益于電商行業(yè)的高強度并發(fā)壓力堂鲜,促使了BAT等巨頭們的技術(shù)進步栈雳。電商行業(yè)有些什么特點呢?

  • 技術(shù)范圍廣
  • 技術(shù)新
  • 高并發(fā)(分布式缔莲、靜態(tài)化技術(shù)哥纫、緩存技術(shù)、異步并發(fā)痴奏、池化磺箕、隊列)
  • 高可用(集群、負載均衡抛虫、限流、降級简僧、熔斷)
  • 數(shù)據(jù)量大
  • 業(yè)務(wù)復(fù)雜
  • 數(shù)據(jù)安全

1.3.常見電商模式

電商行業(yè)的一些常見模式:

  • B2C:商家對個人建椰,如:亞馬遜、當當?shù)?/li>
  • C2C平臺:個人對個人岛马,如:咸魚棉姐、拍拍網(wǎng)屠列、ebay
  • B2B平臺:商家對商家,如:阿里巴巴伞矩、八方資源網(wǎng)等
  • O2O:線上和線下結(jié)合笛洛,如:餓了么、電影票乃坤、團購等
  • P2P:在線金融苛让,貸款,如:網(wǎng)貸之家湿诊、人人聚財?shù)取?/li>
  • B2C平臺:天貓狱杰、京東、一號店等

1.4.一些專業(yè)術(shù)語

  • SaaS:軟件即服務(wù)

  • SOA:面向服務(wù)

  • RPC:遠程過程調(diào)用

  • RMI:遠程方法調(diào)用

  • PV:(page view)厅须,即頁面瀏覽量仿畸;

    用戶每1次對網(wǎng)站中的每個網(wǎng)頁訪問均被記錄1次。用戶對同一頁面的多次訪問朗和,訪問量累計

  • UV:(unique visitor)错沽,獨立訪客

    指訪問某個站點或點擊某條新聞的不同IP地址的人數(shù)。在同一天內(nèi)眶拉,uv只記錄第一次進入網(wǎng)站的具有獨立IP的訪問者千埃,在同一天內(nèi)再次訪問該網(wǎng)站則不計數(shù)。

  • PV與帶寬:

    • 計算帶寬大小需要關(guān)注兩個指標:峰值流量和頁面的平均大小镀层。
    • 計算公式是:網(wǎng)站帶寬= ( PV * 平均頁面大辛獭(單位MB)* 8 )/統(tǒng)計時間(換算到秒)
    • 為什么要乘以8?
      • 網(wǎng)站大小為單位是字節(jié)(Byte)唱逢,而計算帶寬的單位是bit吴侦,1Byte=8bit
    • 這個計算的是平均帶寬,高峰期還需要擴大一定倍數(shù)
  • PV坞古、QPS备韧、并發(fā)

    • QPS:每秒處理的請求數(shù)量。8000/s

      • 比如你的程序處理一個請求平均需要0.1S痪枫,那么1秒就可以處理10個請求织堂。QPS自然就是10,多線程情況下奶陈,這個數(shù)字可能就會有所增加易阳。
    • 由PV和QPS如何需要部署的服務(wù)器數(shù)量?

      • 根據(jù)二八原則吃粒,80%的請求集中在20%的時間來計算峰值壓力:
      • (每日PV * 80%) / (3600s * 24 * 20%) * 每個頁面的請求數(shù) = 每個頁面每秒的請求數(shù)量
      • 然后除以服務(wù)器的QPS值潦俺,即可計算得出需要部署的服務(wù)器數(shù)量

1.5.項目開發(fā)流程

項目經(jīng)理:管人

產(chǎn)品經(jīng)理:設(shè)計需求原型

測試:

前端:大前端。node

后端:

移動端:

項目開發(fā)流程圖:

?
1525697632643.png

公司現(xiàn)狀:

?
1525697681975.png

2.樂優(yōu)商城介紹

2.1.項目介紹

  • 樂優(yōu)商城是一個全品類的電商購物網(wǎng)站(B2C)。
  • 用戶可以在線購買商品事示、加入購物車早像、下單、秒殺商品
  • 可以品論已購買商品
  • 管理員可以在后臺管理商品的上下架肖爵、促銷活動
  • 管理員可以監(jiān)控商品銷售狀況
  • 客服可以在后臺處理退款操作
  • 希望未來3到5年可以支持千萬用戶的使用

2.2.系統(tǒng)架構(gòu)

2.2.1.架構(gòu)圖

樂優(yōu)商城架構(gòu)縮略圖卢鹦,大圖請參考課前資料:

1525703759035.png

2.2.2.系統(tǒng)架構(gòu)解讀

整個樂優(yōu)商城可以分為兩部分:后臺管理系統(tǒng)、前臺門戶系統(tǒng)劝堪。

  • 后臺管理:

    • 后臺系統(tǒng)主要包含以下功能:
      • 商品管理冀自,包括商品分類、品牌幅聘、商品規(guī)格等信息的管理
      • 銷售管理凡纳,包括訂單統(tǒng)計、訂單退款處理帝蒿、促銷活動生成等
      • 用戶管理荐糜,包括用戶控制、凍結(jié)葛超、解鎖等
      • 權(quán)限管理暴氏,整個網(wǎng)站的權(quán)限控制,采用JWT鑒權(quán)方案绣张,對用戶及API進行權(quán)限控制
      • 統(tǒng)計答渔,各種數(shù)據(jù)的統(tǒng)計分析展示
    • 后臺系統(tǒng)會采用前后端分離開發(fā),而且整個后臺管理系統(tǒng)會使用Vue.js框架搭建出單頁應(yīng)用(SPA)侥涵。
    • 預(yù)覽圖:
1525704185158.png
  • 前臺門戶

    • 前臺門戶面向的是客戶沼撕,包含與客戶交互的一切功能。例如:
      • 搜索商品
      • 加入購物車
      • 下單
      • 評價商品等等
    • 前臺系統(tǒng)我們會使用Thymeleaf模板引擎技術(shù)來完成頁面開發(fā)芜飘。出于SEO優(yōu)化的考慮务豺,我們將不采用單頁應(yīng)用。
    1525704277126.png

無論是前臺還是后臺系統(tǒng)嗦明,都共享相同的微服務(wù)集群笼沥,包括:

  • 商品微服務(wù):商品及商品分類、品牌娶牌、庫存等的服務(wù)
  • 搜索微服務(wù):實現(xiàn)搜索功能
  • 訂單微服務(wù):實現(xiàn)訂單相關(guān)
  • 購物車微服務(wù):實現(xiàn)購物車相關(guān)功能
  • 用戶中心:用戶的登錄注冊等功能
  • Eureka注冊中心
  • Zuul網(wǎng)關(guān)服務(wù)
  • Spring Cloud Config配置中心
  • ...

3.項目搭建

3.1.技術(shù)選型

前端技術(shù):

  • 基礎(chǔ)的HTML奔浅、CSS、JavaScript(基于ES6標準)
  • JQuery
  • Vue.js 2.0以及基于Vue的框架:Vuetify
  • 前端構(gòu)建工具:WebPack
  • 前端安裝包工具:NPM
  • Vue腳手架:Vue-cli
  • Vue路由:vue-router
  • ajax框架:axios
  • 基于Vue的富文本框架:quill-editor

后端技術(shù):

  • 基礎(chǔ)的SpringMVC诗良、Spring 5.0和MyBatis3
  • Spring Boot 2.0.1版本
  • Spring Cloud 最新版 Finchley.RC1
  • Redis-4.0
  • RabbitMQ-3.4
  • Elasticsearch-5.6.8
  • nginx-1.10.2:
  • FastDFS - 5.0.8
  • MyCat
  • Thymeleaf

3.2.開發(fā)環(huán)境

為了保證開發(fā)環(huán)境的統(tǒng)一汹桦,希望每個人都按照我的環(huán)境來配置:

  • IDE:我們使用Idea 2017.3 版本
  • JDK:統(tǒng)一使用JDK1.8
  • 項目構(gòu)建:maven3.3.9以上版本即可
  • 版本控制工具:git

idea大家可以在我的課前資料中找到。另外鉴裹,使用幫助大家可以參考課前資料的《idea使用指南.md》

3.3.域名

我們在開發(fā)的過程中营勤,為了保證以后的生產(chǎn)灵嫌、測試環(huán)境統(tǒng)一。盡量都采用域名來訪問項目葛作。

一級域名:www.leyou.com

二級域名:manage.leyou.com , api.leyou.com

我們可以通過switchhost工具來修改自己的host對應(yīng)的地址,只要把這些域名指向127.0.0.1猖凛,那么跟你用localhost的效果是完全一樣的赂蠢。

switchhost可以去課前資料尋找。

3.4.創(chuàng)建父工程

創(chuàng)建統(tǒng)一的父工程:leyou辨泳,用來管理依賴及其版本虱岂,注意是創(chuàng)建project,而不是moudle

1525706200704.png

填寫項目信息:

1525707023009.png

注意:

父工程不需要代碼菠红,只是管理依賴第岖,因此我們不選擇任何SpringCloud的依賴

跳過依賴選擇。

填寫保存的位置信息:

1525706600181.png

然后將pom文件修改成我這個樣子:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.leyou.parent</groupId>
    <artifactId>leyou</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <name>leyou</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.RC1</spring-cloud.version>
        <mybatis.starter.version>1.3.2</mybatis.starter.version>
        <mapper.starter.version>2.0.2</mapper.starter.version>
        <druid.starter.version>1.1.9</druid.starter.version>
        <mysql.version>5.1.32</mysql.version>
        <pageHelper.starter.version>1.2.3</pageHelper.starter.version>
        <leyou.latest.version>1.0.0-SNAPSHOT</leyou.latest.version>
        <fastDFS.client.version>1.26.1-RELEASE</fastDFS.client.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!-- springCloud -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- mybatis啟動器 -->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis.starter.version}</version>
            </dependency>
            <!-- 通用Mapper啟動器 -->
            <dependency>
                <groupId>tk.mybatis</groupId>
                <artifactId>mapper-spring-boot-starter</artifactId>
                <version>${mapper.starter.version}</version>
            </dependency>
            <!-- 分頁助手啟動器 -->
            <dependency>
                <groupId>com.github.pagehelper</groupId>
                <artifactId>pagehelper-spring-boot-starter</artifactId>
                <version>${pageHelper.starter.version}</version>
            </dependency>
            <!-- mysql驅(qū)動 -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>
            <!--FastDFS客戶端-->
            <dependency>
                <groupId>com.github.tobato</groupId>
                <artifactId>fastdfs-client</artifactId>
                <version>${fastDFS.client.version}</version>
            </dependency>
          </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>
</project>

可以發(fā)現(xiàn)试溯,我們在父工程中引入了SpringCloud等很多以后需要用到的依賴蔑滓,以后創(chuàng)建的子工程就不需要自己引入了。

最后遇绞,刪除自動生成的LeyouApplication啟動類键袱、測試類以及application.properties文件,我們不需要摹闽。

3.5.創(chuàng)建EurekaServer

3.5.1.創(chuàng)建工程

這個大家應(yīng)該比較熟悉了蹄咖。

我們的注冊中心,起名為:ly-registry

這次我們就不Spring使用提供的腳手架了付鹿。直接創(chuàng)建maven項目澜汤,自然會繼承父類的依賴:

選擇新建module:

?
1525707765104.png

選擇maven安裝,但是不要選擇骨架:

1525707850047.png

然后填寫項目坐標舵匾,我們的項目名稱為ly-registry:

1525707949252.png

選擇安裝目錄俊抵,因為是聚合項目,目錄應(yīng)該是在父工程leyou的下面:

1525708053551.png

3.5.2.添加依賴

添加EurekaServer的依賴:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>leyou</artifactId>
        <groupId>com.leyou.parent</groupId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.leyou.common</groupId>
    <artifactId>ly-registry</artifactId>
    <version>1.0.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>
</project>

3.5.3.編寫啟動類

@SpringBootApplication
@EnableEurekaServer
public class LyRegistry {
    public static void main(String[] args) {
        SpringApplication.run(LyRegistry.class, args);
    }
}

3.5.4.配置文件

server:
  port: 10086
spring:
  application:
    name: ly-registry
eureka:
  client:
    fetch-registry: false
    register-with-eureka: false
    service-url:
      defaultZone: http://127.0.0.1:${server.port}/eureka
  server:
    enable-self-preservation: false # 關(guān)閉自我保護
    eviction-interval-timer-in-ms: 5000 # 每隔5秒進行一次服務(wù)列表清理

3.5.5.項目的結(jié)構(gòu):

目前纽匙,整個項目的結(jié)構(gòu)如圖:

1525708460522.png

3.6.創(chuàng)建Zuul網(wǎng)關(guān)

3.6.1.創(chuàng)建工程

與上面類似务蝠,選擇maven方式創(chuàng)建Module,然后填寫項目名稱烛缔,我們命名為:ly-api-gateway

1525708626562.png

填寫保存的目錄:

1525708677719.png

3.6.2.添加依賴

這里我們需要添加Zuul和EurekaClient的依賴:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>leyou</artifactId>
        <groupId>com.leyou.parent</groupId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.leyou.common</groupId>
    <artifactId>ly-api-gateway</artifactId>
    <version>1.0.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--是springboot提供的微服務(wù)檢測接口馏段,默認對外提供幾個接口:/info-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>
</project>

3.6.3.編寫啟動類

@SpringBootApplication
@EnableDiscoveryClient
@EnableZuulProxy
public class LyApiGateway {
    public static void main(String[] args) {
        SpringApplication.run(LyApiGateway.class, args);
    }
}

3.6.4.配置文件

server:
  port: 10010
spring:
  application:
    name: api-gateway
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka
    registry-fetch-interval-seconds: 5
  instance:
    prefer-ip-address: true
    ip-address: 127.0.0.1
    instance-id: ${spring.application.name}:${server.port}
zuul:
  prefix: /api # 添加路由前綴
  retryable: true
ribbon:
  ConnectTimeout: 250 # 連接超時時間(ms)
  ReadTimeout: 2000 # 通信超時時間(ms)
  OkToRetryOnAllOperations: true # 是否對所有操作重試
  MaxAutoRetriesNextServer: 1 # 同一服務(wù)不同實例的重試次數(shù)
  MaxAutoRetries: 1 # 同一實例的重試次數(shù)
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMillisecond: 10000 # 熔斷超時時長:10000ms

3.6.5.項目結(jié)構(gòu)

目前,leyou下有兩個子模塊:

  • ly-registry:服務(wù)的注冊中心(EurekaServer)
  • ly-api-gateway:服務(wù)網(wǎng)關(guān)(Zuul)

目前践瓷,服務(wù)的結(jié)構(gòu)如圖所示:

[圖片上傳失敗...(image-2ea885-1582193266917)]

截止到這里院喜,我們已經(jīng)把基礎(chǔ)服務(wù)搭建完畢,為了便于開發(fā)晕翠,統(tǒng)一配置中心(ConfigServer)我們留待以后添加喷舀。

3.7.創(chuàng)建商品微服務(wù)

既然是一個全品類的電商購物平臺砍濒,那么核心自然就是商品。因此我們要搭建的第一個服務(wù)硫麻,就是商品微服務(wù)爸邢。其中會包含對于商品相關(guān)的一系列內(nèi)容的管理,包括:

  • 商品分類管理
  • 品牌管理
  • 商品規(guī)格參數(shù)管理
  • 商品管理
  • 庫存管理

我們先完成項目的搭建:

3.7.1.微服務(wù)的結(jié)構(gòu)

因為與商品的品類相關(guān)拿愧,我們的工程命名為ly-item.

需要注意的是杠河,我們的ly-item是一個微服務(wù),那么將來肯定會有其它系統(tǒng)需要來調(diào)用服務(wù)中提供的接口浇辜,因此肯定也會使用到接口中關(guān)聯(lián)的實體類券敌。

因此這里我們需要使用聚合工程,將要提供的接口及相關(guān)實體類放到獨立子工程中柳洋,以后別人引用的時候待诅,只需要知道坐標即可。

我們會在ly-item中創(chuàng)建兩個子工程:

  • ly-item-interface:主要是對外暴露的接口及相關(guān)實體類
  • ly-item-service:所有業(yè)務(wù)邏輯及內(nèi)部使用接口

調(diào)用關(guān)系如圖所示:

1525744281610.png

3.7.2.創(chuàng)建父工程ly-item

依然是使用maven構(gòu)建:

1525744570533.png

保存的位置:

1525744595793.png

不需要任何依賴熊镣,我們可以把項目打包方式設(shè)置為pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>leyou</artifactId>
        <groupId>com.leyou.parent</groupId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.leyou.service</groupId>
    <artifactId>ly-item</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <!-- 打包方式為pom -->
    <packaging>pom</packaging>
</project>

3.7.3.創(chuàng)建ly-item-interface

在ly-item工程上點擊右鍵卑雁,選擇new > module:

1525744768694.png

依然是使用maven構(gòu)建,注意父工程是ly-item:

1525744875078.png

注意:接下來填寫的目錄結(jié)構(gòu)需要自己手動完成轧钓,保存到ly-item下的ly-item-interface目錄中:

1525744973026.png

點擊Finish完成序厉。

此時的項目結(jié)構(gòu):

?
1525745119573.png

3.7.4.創(chuàng)建ly-item-service

ly-item-interface類似,我們選擇在ly-item上右鍵毕箍,新建module弛房,然后填寫項目信息:

1525745247195.png

填寫存儲位置,是在/ly-item/ly-item-service目錄

1525745303365.png

點擊Finish完成而柑。

3.7.5.整個微服務(wù)結(jié)構(gòu)

如圖所示:

?
1525745407047.png

我們打開ly-item的pom查看文捶,會發(fā)現(xiàn)ly-item-interface和ly-item-service都已經(jīng)稱為module了:

?
1525745475108.png

3.7.6.添加依賴

接下來我們給ly-item-service中添加依賴:

思考一下我們需要什么?

  • Eureka客戶端
  • web啟動器
  • mybatis啟動器
  • 通用mapper啟動器
  • 分頁助手啟動器
  • 連接池媒咳,我們用默認的Hykira
  • mysql驅(qū)動
  • 千萬不能忘了粹排,我們自己也需要ly-item-interface中的實體類

這些依賴,我們在頂級父工程:leyou中已經(jīng)添加好了涩澡。所以直接引入即可:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>ly-item</artifactId>
        <groupId>com.leyou.service</groupId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.leyou.service</groupId>
    <artifactId>ly-item-service</artifactId>
    <version>1.0.0-SNAPSHOT</version>

    <dependencies>
        <!--Eureka客戶端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--web啟動器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- mybatis啟動器 -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>${mybatis.starter.version}</version>
        </dependency>
        <!-- 通用Mapper啟動器 -->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>${mapper.starter.version}</version>
        </dependency>
        <!-- 分頁助手啟動器 -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>${pageHelper.starter.version}</version>
        </dependency>
        <!-- mysql驅(qū)動 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>
        <dependency>
            <groupId>com.leyou.service</groupId>
            <artifactId>ly-item-interface</artifactId>
            <version>${leyou.latest.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>
</project>

ly-item-interface中需要什么我們暫時不清楚顽耳,所以先不管。

整個結(jié)構(gòu):

1525747398193.png

3.7.7.編寫啟動和配置

在整個ly-item工程中妙同,只有ly-item-service是需要啟動的射富。因此在其中編寫啟動類即可:

@SpringBootApplication
@EnableDiscoveryClient
public class LyItemService {
    public static void main(String[] args) {
        SpringApplication.run(LyItemService.class, args);
    }
}

然后是全局屬性文件:

server:
  port: 8081
spring:
  application:
    name: item-service
  datasource:
    url: jdbc:mysql://localhost:3306/heima
    username: root
    password: 123
    hikari:
      maximum-pool-size: 30
      minimum-idle: 10
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka
  instance:
    lease-renewal-interval-in-seconds: 5 # 每隔5秒發(fā)送一次心跳
    lease-expiration-duration-in-seconds: 10 # 10秒不發(fā)送就過期
    prefer-ip-address: true
    ip-address: 127.0.0.1
    instance-id: ${spring.application.name}:${server.port}

3.8.添加商品微服務(wù)的路由規(guī)則

既然商品微服務(wù)已經(jīng)創(chuàng)建桨啃,接下來肯定要添加路由規(guī)則到Zuul中障涯,我們不使用默認的路由規(guī)則努咐。

zuul:
  prefix: /api # 添加路由前綴
  retryable: true
  routes:
    item-service: /item/** # 將商品微服務(wù)映射到/item/**

3.9.啟動測試

我們分別啟動:ly-registry暗膜,ly-api-gateway,ly-item-service

1525749186008.png

查看Eureka面板:

1525749215954.png

3.10.測試路由規(guī)則

為了測試路由規(guī)則是否暢通泽篮,我們是不是需要在item-service中編寫一個controller接口呢悍汛?

其實不需要宣旱,Spring提供了一個依賴:actuator

只要我們添加了actuator的依賴,它就會為我們生成一系列的訪問接口:

  • /info
  • /health
  • /refresh
  • ...

添加依賴:

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

重啟后訪問Eureka控制臺:

鼠標懸停在item-service上赠群,會顯示一個地址:

1525749683060.png

這就是actuator提供的接口羊始,我們點擊訪問:

1525749711606.png

因為我們沒有添加信息,所以是一個空的json乎串,但是可以肯定的是:我們能夠訪問到item-service了店枣。

接下來我們通過路由訪問試試,根據(jù)路由規(guī)則叹誉,我們需要訪問的地址是:

http://127.0.0.1:10010/api/item/actuator/info

1525749803191.png

3.11.通用工具模塊

有些工具或通用的約定內(nèi)容,我們希望各個服務(wù)共享闷旧,因此需要創(chuàng)建一個工具模塊:ly-common

使用maven來構(gòu)建module:

1526046318620.png

位置信息:

1526046349379.png

結(jié)構(gòu):

1526046432347.png

目前還不需要編碼长豁。

4、ES6 語法指南

后端項目搭建完畢忙灼,接下來就是前端頁面了匠襟。不過在這之前需要一些準備工作。我們需要學習ES6的語法標準该园。

什么是ES6酸舍?就是ECMAScript第6版標準。

4.1.什么是ECMAScript里初?

來看下前端的發(fā)展歷程:

web1.0時代:

  • 最初的網(wǎng)頁以HTML為主啃勉,是純靜態(tài)的網(wǎng)頁。網(wǎng)頁是只讀的双妨,信息流只能從服務(wù)的到客戶端單向流通淮阐。開發(fā)人員也只關(guān)心頁面的樣式和內(nèi)容即可。

web2.0時代:

  • 1995年刁品,網(wǎng)景工程師Brendan Eich 花了10天時間設(shè)計了JavaScript語言泣特。
  • 1996年,微軟發(fā)布了JScript挑随,其實是JavaScript的逆向工程實現(xiàn)状您。
  • 1997年,為了統(tǒng)一各種不同script腳本語言兜挨,ECMA(歐洲計算機制造商協(xié)會)以JavaScript為基礎(chǔ)膏孟,制定了ECMAscript標準規(guī)范。JavaScript和JScript都是ECMAScript的標準實現(xiàn)者暑劝,隨后各大瀏覽器廠商紛紛實現(xiàn)了ECMAScript標準骆莹。

所以,ECMAScript是瀏覽器腳本語言的規(guī)范担猛,而各種我們熟知的js語言幕垦,如JavaScript則是規(guī)范的具體實現(xiàn)丢氢。

4.2.ECMAScript的快速發(fā)展

而后,ECMAScript就進入了快速發(fā)展期先改。

  • 1998年6月疚察,ECMAScript 2.0 發(fā)布。

  • 1999年12月仇奶,ECMAScript 3.0 發(fā)布貌嫡。這時,ECMAScript 規(guī)范本身也相對比較完善和穩(wěn)定了该溯,但是接下來的事情岛抄,就比較悲劇了。

  • 2007年10月狈茉。夫椭。。氯庆。ECMAScript 4.0 草案發(fā)布蹭秋。

    這次的新規(guī)范,歷時頗久堤撵,規(guī)范的新內(nèi)容也有了很多爭議仁讨。在制定ES4的時候,是分成了兩個工作組同時工作的实昨。

    • 一邊是以 Adobe, Mozilla, Opera 和 Google為主的 ECMAScript 4 工作組洞豁。
    • 一邊是以 Microsoft 和 Yahoo 為主的 ECMAScript 3.1 工作組。

    ECMAScript 4 的很多主張比較激進屠橄,改動較大族跛。而 ECMAScript 3.1 則主張小幅更新。最終經(jīng)過 TC39 的會議锐墙,決定將一部分不那么激進的改動保留發(fā)布為 ECMAScript 3.1礁哄,而ES4的內(nèi)容,則延續(xù)到了后來的ECMAScript5和6版本中

  • 2009年12月溪北,ECMAScript 5 發(fā)布桐绒。

  • 2011年6月,ECMAScript 5.1 發(fā)布之拨。

  • 2015年6月茉继,ECMAScript 6,也就是 ECMAScript 2015 發(fā)布了蚀乔。 并且從 ECMAScript 6 開始烁竭,開始采用年號來做版本。即 ECMAScript 2015吉挣,就是ECMAScript6派撕。

4.3.ES5和6的一些新特性

我們這里只把一些常用的進行學習婉弹,更詳細的大家參考:阮一峰的ES6教程

4.3.1.let 和 const 命令

var

之前,js定義變量只有一個關(guān)鍵字:var

var有一個問題终吼,就是定義的變量有時會莫名奇妙的成為全局變量镀赌。

例如這樣的一段代碼:

for(var i = 0; i < 5; i++){
    console.log(i);
}
console.log("循環(huán)外:" + i)

你猜下打印的結(jié)果是什么?

1526107278999.png

let

let所聲明的變量际跪,只在let命令所在的代碼塊內(nèi)有效商佛。

我們把剛才的var改成let試試:

for(let i = 0; i < 5; i++){
    console.log(i);
}
console.log("循環(huán)外:" + i)

結(jié)果:

1526107347275.png

const

const聲明的變量是常量,不能被修改

1526107425000.png

4.3.2.字符串擴展

新的API

ES6為字符串擴展了幾個新的API:

  • includes():返回布爾值姆打,表示是否找到了參數(shù)字符串良姆。
  • startsWith():返回布爾值,表示參數(shù)字符串是否在原字符串的頭部幔戏。
  • endsWith():返回布爾值歇盼,表示參數(shù)字符串是否在原字符串的尾部。

實驗一下:

1526107640349.png

字符串模板

ES6中提供了`來作為字符串模板標記评抚。我們可以這么玩:

1526108070980.png

在兩個`之間的部分都會被作為字符串的值,不管你任意換行伯复,甚至加入js腳本

鍵盤是的1的左側(cè)慨代,tab的上側(cè),esc的正下方

4.3.3.解構(gòu)表達式

數(shù)組解構(gòu)

比如有一個數(shù)組:

let arr = [1,2,3]

我想獲取其中的值啸如,只能通過角標侍匙。ES6可以這樣:

const [x,y,z] = arr;// x,y叮雳,z將與arr中的每個位置對應(yīng)來取值
// 然后打印
console.log(x,y,z);

結(jié)果:

1526109778368.png

對象解構(gòu)

例如有個person對象:

const person = {
    name:"jack",
    age:21,
    language: ['java','js','css']
}

我們可以這么做:

// 解構(gòu)表達式獲取值
const {name,age,language} = person;
// 打印
console.log(name);
console.log(age);
console.log(language);

結(jié)果:

1526109984544.png

如過想要用其它變量接收想暗,需要額外指定別名:

1526110159450.png
  • {name:n}:name是person中的屬性名,冒號后面的n是解構(gòu)后要賦值給的變量帘不。

4.3.4.函數(shù)優(yōu)化

函數(shù)參數(shù)默認值

在ES6以前说莫,我們無法給一個函數(shù)參數(shù)設(shè)置默認值,只能采用變通寫法:

    function add(a , b) {
        // 判斷b是否為空寞焙,為空就給默認值1
        b = b || 1;
        return a + b;
    }
    // 傳一個參數(shù)
    console.log(add(10));

現(xiàn)在可以這么寫:

function add(a , b = 1) {
    return a + b;
}
// 傳一個參數(shù)
console.log(add(10));

箭頭函數(shù)

ES6中定義函數(shù)的簡寫方式:

一個參數(shù)時:

var print = function (obj) {
    console.log(obj);
}
// 簡寫為:
var print2 = obj => console.log(obj);

多個參數(shù):

// 兩個參數(shù)的情況:
var sum = function (a , b) {
    return a + b;
}
// 簡寫為:
var sum2 = (a,b) => a+b;

代碼不止一行储狭,可以用{}括起來

var sum3 = (a,b) => {
    return a + b;
}

對象的函數(shù)屬性簡寫

比如一個Person對象,里面有eat方法:

let person = {
    name: "jack",
    // 以前:
    eat: function (food) {
        console.log(this.name + "在吃" + food);
    },
    // 箭頭函數(shù)版:
    eat2: food => console.log(person.name + "在吃" + food),// 這里拿不到this
    // 簡寫版:
    eat3(food){
        console.log(this.name + "在吃" + food);
    }
}

箭頭函數(shù)結(jié)合解構(gòu)表達式

比如有一個函數(shù):

const person = {
    name:"jack",
    age:21,
    language: ['java','js','css']
}

function hello(person) {
    console.log("hello," + person.name)
}

如果用箭頭函數(shù)和解構(gòu)表達式

var hi = ({name}) =>  console.log("hello," + name);

4.3.5.map和reduce

數(shù)組中新增了map和reduce方法捣郊。

map

map():接收一個函數(shù)辽狈,將原數(shù)組中的所有元素用這個函數(shù)處理后放入新數(shù)組返回。

舉例:有一個字符串數(shù)組呛牲,我們希望轉(zhuǎn)為int數(shù)組

let arr = ['1','20','-5','3'];
console.log(arr)

arr = arr.map(s => parseInt(s));

console.log(arr)
1526110796839.png

reduce

reduce():接收一個函數(shù)(必須)和一個初始值(可選)刮萌,該函數(shù)接收兩個參數(shù):

  • 第一個參數(shù)是上一次reduce處理的結(jié)果
  • 第二個參數(shù)是數(shù)組中要處理的下一個元素

reduce()會從左到右依次把數(shù)組中的元素用reduce處理,并把處理的結(jié)果作為下次reduce的第一個參數(shù)娘扩。如果是第一次着茸,會把前兩個元素作為計算參數(shù)壮锻,或者把用戶指定的初始值作為起始參數(shù)

舉例:

const arr = [1,20,-5,3]

沒有初始值:

[圖片上傳失敗...(image-864e30-1582193266917)]

指定初始值:

[圖片上傳失敗...(image-51b1bd-1582193266917)]

4.3.6.promise

所謂Promise,簡單說就是一個容器元扔,里面保存著某個未來才會結(jié)束的事件(通常是一個異步操作)的結(jié)果躯保。從語法上說,Promise 是一個對象澎语,從它可以獲取異步操作的消息途事。Promise 提供統(tǒng)一的 API,各種異步操作都可以用同樣的方法進行處理擅羞。

感覺跟java的Future類很像啊尸变,有木有!

我們可以通過Promise的構(gòu)造函數(shù)來創(chuàng)建Promise對象减俏,并在內(nèi)部封裝一個異步執(zhí)行的結(jié)果召烂。

語法:

const promise = new Promise(function(resolve, reject) {
  // ... 執(zhí)行異步操作

  if (/* 異步操作成功 */){
    resolve(value);// 調(diào)用resolve,代表Promise將返回成功的結(jié)果
  } else {
    reject(error);// 調(diào)用reject娃承,代表Promise會返回失敗結(jié)果
  }
});

這樣奏夫,在promise中就封裝了一段異步執(zhí)行的結(jié)果。

如果我們想要等待異步執(zhí)行完成历筝,做一些事情酗昼,我們可以通過promise的then方法來實現(xiàn),語法:

promise.then(function(value){
    // 異步執(zhí)行成功后的回調(diào)
});

如果想要處理promise異步執(zhí)行失敗的事件,還可以跟上catch:

promise.then(function(value){
    // 異步執(zhí)行成功后的回調(diào)
}).catch(function(error){
    // 異步執(zhí)行失敗后的回調(diào)
})

示例:

const p = new Promise(function (resolve, reject) {
    // 這里我們用定時任務(wù)模擬異步
    setTimeout(() => {
        const num = Math.random();
        // 隨機返回成功或失敗
        if (num < 0.5) {
            resolve("成功梳猪!num:" + num)
        } else {
            reject("出錯了麻削!num:" + num)
        }
    }, 300)
})

// 調(diào)用promise
p.then(function (msg) {
    console.log(msg);
}).catch(function (msg) {
    console.log(msg);
})

結(jié)果:

1526113115887.png
1526113140074.png

4.3.7.set和map(了解)

ES6提供了Set和Map的數(shù)據(jù)結(jié)構(gòu)。

Set春弥,本質(zhì)與數(shù)組類似呛哟。不同在于Set中只能保存不同元素,如果元素相同會被忽略匿沛。跟java很像吧扫责。

構(gòu)造函數(shù):

// Set構(gòu)造函數(shù)可以接收一個數(shù)組或空
let set = new Set();
set.add(1);// [1]
// 接收數(shù)組
let set2 = new Set([2,3,4,5,5]);// 得到[2,3,4,5]

普通方法:

set.add(1);// 添加
set.clear();// 清空
set.delete(2);// 刪除指定元素
set.has(2); // 判斷是否存在
set.keys();// 返回所有key
set.values();// 返回所有值
set.entries();// 返回鍵值對集合
// 因為set沒有鍵值對,所有其keys俺祠、values公给、entries方法返回值一樣的。
set.size; // 元素個數(shù)蜘渣。是屬性淌铐,不是方法。

map蔫缸,本質(zhì)是與Object類似的結(jié)構(gòu)腿准。不同在于,Object強制規(guī)定key只能是字符串。而Map結(jié)構(gòu)的key可以是任意對象吐葱。即:

  • object是 <string,object>集合
  • map是<object,object>集合

構(gòu)造函數(shù):

// map接收一個數(shù)組街望,數(shù)組中的元素是鍵值對數(shù)組
const map = new Map([
    ['key1','value1'],
    ['key2','value2'],
])
// 或者接收一個set
const set = new Set([
    ['key1','value1'],
    ['key2','value2'],
])
const map2 = new Map(set)
// 或者其它map
const map3 = new Map(map);

方法:

1526114799767.png

4.3.8.模塊化

4.3.8.1.什么是模塊化

模塊化就是把代碼進行拆分,方便重復(fù)利用弟跑。類似java中的導包:要使用一個包灾前,必須先導包。

而JS中沒有包的概念孟辑,換來的是 模塊哎甲。

模塊功能主要由兩個命令構(gòu)成:exportimport

  • export命令用于規(guī)定模塊的對外接口饲嗽,
  • import命令用于導入其他模塊提供的功能炭玫。

4.3.8.2.export

比如我定義一個js文件:hello.js,里面有一個對象:

const util = {
    sum(a,b){
        return a + b;
    }
}

我可以使用export將這個對象導出:

const util = {
    sum(a,b){
        return a + b;
    }
}
export util;

當然貌虾,也可以簡寫為:

export const util = {
    sum(a,b){
        return a + b;
    }
}

export不僅可以導出對象吞加,一切JS變量都可以導出。比如:基本類型變量尽狠、函數(shù)衔憨、數(shù)組、對象袄膏。

當要導出多個值時巫财,還可以簡寫。比如我有一個文件:user.js:

var name = "jack"
var age = 21
export {name,age}

省略名稱

上面的導出代碼中哩陕,都明確指定了導出的變量名,這樣其它人在導入使用時就必須準確寫出變量名赫舒,否則就會出錯悍及。

因此js提供了default關(guān)鍵字,可以對導出的變量名進行省略

例如:

// 無需聲明對象的名字
export default {
    sum(a,b){
        return a + b;
    }
}

這樣接癌,當使用者導入時心赶,可以任意起名字

4.3.8.3.import

使用export命令定義了模塊的對外接口以后,其他 JS 文件就可以通過import命令加載這個模塊缺猛。

例如我要使用上面導出的util:

// 導入util
import util from 'hello.js'
// 調(diào)用util中的屬性
util.sum(1,2)

要批量導入前面導出的name和age:

import {name, age} from 'user.js'

console.log(name + " , 今年"+ age +"歲了")

但是上面的代碼暫時無法測試缨叫,因為瀏覽器目前還不支持ES6 的導入和導出功能。除非借助于工具荔燎,把ES6 的語法進行編譯降級到ES5耻姥,比如Babel-cli工具

我們暫時不做測試,大家了解即可有咨。

4.3.9.對象擴展

ES6給Object拓展了許多新的方法琐簇,如:

  • keys(obj):獲取對象的所有key形成的數(shù)組
  • values(obj):獲取對象的所有value形成的數(shù)組
  • entries(obj):獲取對象的所有key和value形成的二維數(shù)組。格式:[[k1,v1],[k2,v2],...]
  • assian(dest, ...src) :將多個src對象的值 拷貝到 dest中(淺拷貝)座享。
1527210872966.png

4.3.10.數(shù)組擴展

ES6給數(shù)組新增了許多方法:

  • find(callback):把數(shù)組中的元素逐個傳遞給函數(shù)callback執(zhí)行婉商,如果返回true似忧,則返回該元素
  • findIndex(callback):與find類似,不過返回的是品牌到的元素的索引
  • includes(callback):與find類似丈秩,如果匹配到元素盯捌,則返回true,代表找到了蘑秽。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末饺著,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子筷狼,更是在濱河造成了極大的恐慌瓶籽,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件埂材,死亡現(xiàn)場離奇詭異塑顺,居然都是意外死亡,警方通過查閱死者的電腦和手機俏险,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進店門严拒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人竖独,你說我怎么就攤上這事裤唠。” “怎么了莹痢?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵种蘸,是天一觀的道長。 經(jīng)常有香客問我竞膳,道長航瞭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任坦辟,我火速辦了婚禮刊侯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘锉走。我一直安慰自己滨彻,他們只是感情好,可當我...
    茶點故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布挪蹭。 她就那樣靜靜地躺著亭饵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪梁厉。 梳的紋絲不亂的頭發(fā)上冬骚,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天,我揣著相機與錄音,去河邊找鬼只冻。 笑死庇麦,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的喜德。 我是一名探鬼主播山橄,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼舍悯!你這毒婦竟也來了航棱?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤萌衬,失蹤者是張志新(化名)和其女友劉穎饮醇,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體秕豫,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡朴艰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了混移。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片祠墅。...
    茶點故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖歌径,靈堂內(nèi)的尸體忽然破棺而出毁嗦,到底是詐尸還是另有隱情,我是刑警寧澤回铛,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布狗准,位于F島的核電站,受9級特大地震影響茵肃,放射性物質(zhì)發(fā)生泄漏驶俊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一免姿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧榕酒,春花似錦胚膊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至辑舷,卻和暖如春喻犁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工肢础, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留还栓,地道東北人。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓传轰,卻偏偏與公主長得像剩盒,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子慨蛙,可洞房花燭夜當晚...
    茶點故事閱讀 44,947評論 2 355