NodeJS入門實踐第二講Express的使用

NodeJs提供了的方法處理起來比較麻煩蒸其,在使用nodejs時有很多現(xiàn)成的框架幫助開發(fā)人員道盏,其中最簡單的一個server框架就是Express雕什,express的安裝方式有兩種斤儿,一種是在項目文件夾中安裝express飞盆,另外一個是通過express的generator來生成一個express的骨架,我們先從最原始的方式來了解express中的幾個比較核心的概念

基于原始的方式使用express

首先創(chuàng)建一個項目忘巧,之后初始化為npm類型的項目恒界,要生成node的基本項目,需要使用npm init 進(jìn)行初始化砚嘴,初始化會輸入一些基本的項目信息十酣,這個步驟和java的maven非常類似,等于創(chuàng)建了maven的pom文件际长,而對于node而言是創(chuàng)建了package.json文件耸采。

> npm init
About to write to E:\study\nodejs_2018\11_express\package.json:
{
  "name": "express_first",
  "version": "1.0.0",
  "description": "express init",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "konghao",
  "license": "ISC"
}

下一步使用npm安裝express,由于express僅僅只是存在在當(dāng)前項目中工育,所以安裝不用使用-g進(jìn)行全局安裝虾宇,但是需要增加--save的參數(shù),這個表示會把這些信息添加到package.json的依賴中如绸。

E:\study\nodejs_2018\11_express>npm install express --save
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN express_first@1.0.0 No repository field.

+ express@4.16.2
added 48 packages in 24.734s

{
  "name": "hello_express",
  "version": "1.0.0",
  "description": "express begin",
  "main": "app.js",
  "scripts": {
    "start": "node app.js"
  },
  "author": "konghao",
  "license": "ISC",
  "dependencies": {
    "express": "^4.16.2",
  }
}

大家會發(fā)現(xiàn)package.json中有了一個dependencies嘱朽,添加了express的依賴。在這個文件我進(jìn)行兩個設(shè)置怔接,在scripts中增加了start的腳本搪泳,該腳本使用node app.js來運行一個文件,此時app.js是我們的核心的服務(wù)器文件扼脐,添加了這個腳本之后岸军,可以直接使用npm start 運行該腳本。

下來創(chuàng)建app.js來運行一個express的應(yīng)用

var express = require("express")
var app = express();

app.get("/hello",function (req,resp) {
    resp.send("hello express!");
});

app.listen(3000,function () {
    console.log("server start!!");
});

已上程序中頭兩行創(chuàng)建了express的對象瓦侮,app.get(xx)這個和nodejs的路由一模一樣艰赞,表示接收了get請求,之后使用function回調(diào)函數(shù)進(jìn)行處理肚吏,通過resp的send方法可以輸出數(shù)據(jù)到網(wǎng)頁方妖,app.listen(xx)表示監(jiān)聽端口,等于nodejs中的createServer罚攀。已上程序只要運行之后在瀏覽器中輸入localhost:3000/hello將會顯示hello express的文本在瀏覽器中吁断。這就是一個簡單的express的應(yīng)用,注意express是一個完全基于路由的架構(gòu)坞生,下面我們來詳細(xì)了解express中最核心的一個概念:中間件。

express的中間件

express是一個自上而下進(jìn)行執(zhí)行的運用掷伙,在具體講解之前是己,我們加入一個應(yīng)用包,我們現(xiàn)在的程序只要改動app.js都得開發(fā)人員自動關(guān)閉和啟動nodejs任柜。在npm中有一個叫做nodemon的框架卒废,可以幫助我們自動重新啟動沛厨,nodemon建議大家安裝成全局類型,這樣方便所有的應(yīng)用都能使用摔认,使用下面的腳本安裝

npm install nodemon -g

安裝完成之后只要通過nodemon app.js此時只要項目中的文件有變化它會自動啟動逆皮,為了方便這個操作,我將package.json中start的腳本進(jìn)行的了簡單的修改

....
"scripts": {
    "start": "nodemon app.js"
  },
...

下面我們來修改app.js中的一些代碼

...
app.get("/:username",function(req,resp){
   resp.send("hello:"+req.params.username);
});

app.get("/hello",function (req,resp) {
    resp.send("hello express!");
});
...

第一個get表示獲取/xxx参袱,這個路徑會被解析成為username的參數(shù)电谣,通過req可以顯示這個參數(shù)。此時當(dāng)我們輸入路徑localhost:3000/hello抹蚀,express在讀取代碼的時候會首先匹配到剿牺,它會將hello認(rèn)為是username,所以瀏覽器中會顯示hello:hello 第二個/hello的路由就不會再被匹配了环壤,express的執(zhí)行方式就是這樣的晒来。只要匹配到一個路由,如果沒有做任何特殊的處理郑现,處理完就停止了湃崩。

上面我們提到的特殊處理就是中間件的一種形式,如果我們在第一個函數(shù)中增加一個next的參數(shù)接箫,就能夠做一些特殊處理攒读,大家看代碼

app.get("/:username",function(req,resp,next){
    // resp.send("hello:"+req.params.username);
    console.log(req.params.username);
    next();
});

app.get("/hello",function (req,resp) {
    resp.send("hello express!");
});

此時第一個不使用send,而是使用console.log輸出了一下username列牺。執(zhí)行完成之后使用了next()整陌,這表示express會繼續(xù)向下執(zhí)行請求,所以第二個路由/hello也會被執(zhí)行瞎领,所以將會輸出hello express泌辫。這就是express中間件的一個核心操作方式,用戶可以通過next()來確定路由請求是否往下提交九默。下面我們來看express另一個重要的函數(shù)震放,use函數(shù)珍坊。

開始我們已經(jīng)多次強調(diào)了express的所有操作都是基于路由進(jìn)行的恤浪,其中g(shù)et方法處理get請求千扔,post方法處理post請求沸毁,而還有一個特殊的use方法勿璃,也是處理請求杖狼,但它的特殊性在于充石,它會自動匹配滿足條件的所有請求榛臼,首先就剛才講的例子來看耳峦,我們的地址如果是localhost:3000/hello/abc恩静。此時有兩個路徑,express一個都不會進(jìn)行匹配。

此時如果將get改成use驶乾,express會自動匹配所有/hello開頭的請求

app.use("/hello",function (req,resp) {
    resp.send("hello express!");
});

我們發(fā)現(xiàn)邑飒,只要路徑是以/hello開頭的所有路徑都會被匹配如: /hello/abc,/hello/abc/a/b等等,這些都會被匹配级乐。此時如果有個地址是app.use("/",function(req,resp)) 那是不是意味著所有的請求都會通過這個函數(shù)疙咸,此時如果不使用next,那意味著风科,請求到這個就終止了撒轮,但是我們可以通過next將請求往下執(zhí)行。如果地址是/丐重,我們可以省略第一個參數(shù)使用app.use(function(req,resp)) 來替換腔召。

以上操作就提供了一種方式,讓我們可以讓express執(zhí)行我們的某個模塊扮惦,這個模塊我就將其稱之為中間件臀蛛,接下來我們自己編寫一個處理靜態(tài)資源文件的中間件。

var express = require("express");
var url = require("url");
var fs = require("fs");
var app = express();

// app.get("/:username",function(req,resp){
//    resp.send("hello:"+req.params.username);
// });

function handleStatic(req,resp,next) {
    var pathname = url.parse(req.url).pathname;
    if(pathname=="/") pathname = "index.html";
    fs.readFile("./publics/"+pathname,null,function (err,data) {
       if(err) {
           //文件不在崖蜜,直接next到后面的請求
           next();
       }  else {
           resp.writeHead(200,{"Content-type":"text/html;charset=utf-8"});
           resp.write(data);
           resp.end();
       }
    });
}

app.use(handleStatic);//啟動handleStatic的函數(shù)浊仆,所有請求都會調(diào)用

app.get("/:username",function(req,resp,next){
    // resp.send("hello:"+req.params.username);
    console.log(req.params.username);
    next();
});

app.use("/hello",function (req,resp) {
    resp.send("hello express!");
});

app.listen(3000,function () {
    console.log("server start!!");
});

handleStatic就等于一個我們自定義的中間件。通過這個例子我相信大家對express的處理流程已經(jīng)有了一個清晰的理解了豫领,這種中間件的方式為我們的代碼帶來了極大的靈活性抡柿,我們可以非常輕松的往express中添加和刪除各種模塊。下面我們來看視圖渲染等恐。

視圖渲染之pug

express默認(rèn)提供的視圖是jade洲劣,現(xiàn)在已經(jīng)變成了pug,我們首先安裝pug的依賴

npm install pug --save

此時會在package.json中加入pug的依賴

"dependencies": {
    "express": "^4.16.2",
    "pug": "^2.0.0-rc.4"
  }

pug是nodejs默認(rèn)的視圖引擎课蔬,我們只要進(jìn)行簡單的配置即可使用

//說明的視圖的路徑是根路徑加上views文件夾
app.set("views",path.join(__dirname,"views"));
//說明視圖引擎的文件名稱的后綴名是pug,注意囱稽,有些模板是jade。pug就是新版的jade
app.set("view engine","pug");

app.get("/test",function(req,resp){
    var users = [{"username":"foo",age:12}
        ,{"username":"bar",age:33}
    ];
    //傳入了兩個參數(shù)
    resp.render("test",{title:"hello pug",users:users});
});

上面的代碼設(shè)定了視圖引擎是pug二跋。它會自動在views目錄中找xx.pug來渲染战惊,/test這個路由使用的方法是resp.render() 這就表示會渲染給一個視圖"test.pug"文件,并且傳遞了title和users兩個數(shù)據(jù)扎即,接下來看看pug的編寫方法吞获,這個比較特殊,它是使用tab的縮進(jìn)來表示html內(nèi)容谚鄙,這里只是簡單的介紹各拷,大家如果有興趣可以花點時間去研究一下,視圖的研究無非就是從幾個點入手(如何傳數(shù)據(jù)闷营,如何展示成html烤黍,如何寫選擇,如何寫循環(huán),宏定義)蚊荣。下面的代碼我們定義了模板layout.pug。將其他模板繼承l(wèi)ayout.pug可以比較方便的實現(xiàn)基本模塊莫杈。

doctype html
html
    head
        title #{title}
    body
        h1 pug的基本例子
        block content
        hr
        p(style="text-align:center") copyright

已上代碼定義了模板文件互例,注意block content 就是要在其他地方嵌套的內(nèi)容,下面看看test.pug的操作

extends layout
block content
    ul
        each u,i in users
            li=i+"."+u.username+"---"+u.age

test.pug中繼承了layout筝闹,并且將block content中的內(nèi)容替換為一個無序列表媳叨,使用了each來遍歷users這個渲染視圖的參數(shù)。

關(guān)于pug大家可以自行學(xué)習(xí)关顷,也非常簡單糊秆。下面我們會介紹另外一個視圖模板引擎handlebars。

視圖模板引擎handlebars

pug引擎的寫法和我們熟悉的html非常不一樣议双,node提供了多種模板引擎痘番,handlebars就是其中一個基于html格式的引擎,下面我們看看如何使用平痰,首先卸載pug引擎

npm remove pug --save

下面安裝handlebars汞舱,我們安裝的是支持express的版本,這個和express整合起來要簡單一些宗雇,如果不使用express昂芜,可以直接安裝handlebars。

npm install express-handlebars --save

之后需要在app.js中注冊這個模板引擎赔蒲,由于handlebars不是node的默認(rèn)引擎泌神,所以需要程序員注冊這個引擎

//注冊hbs引擎,說明引擎的后綴名是hbs舞虱,默認(rèn)的模板名稱是layout.hbs欢际,目錄在views中的layouts中
app.engine("hbs",hbs({extname:"hbs",defaultLayout:"layout",layoutDir:__dirname+"/views/layouts"}))
//說明的視圖的路徑是根路徑加上views文件夾
app.set("views",path.join(__dirname,"views"));
//說明視圖引擎的文件名稱的后綴名是pug,注意,有些模板是jade砾嫉。pug就是新版的jade
app.set("view engine","hbs");

接下來看看layout.hbs的寫法幼苛,這個和html如出一轍

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>{{title}}</title>
</head>
<body>
    <h1>{{title}}</h1>
    {{{body}}}
    <hr>
    <p>copyright</p>
</body>
</html>

需要注意的是兩個{{}}的,表示獲取傳過來的值焕刮,而三個{{{}}}表示引入具體的內(nèi)容舶沿,而且解析html。這里的{{{body}}}表示具體的模板內(nèi)容配并,我們也可以在app.js中設(shè)置不使用模板resp.render("test",{title:"hello handlebars",users:users,layout:false}); 這就表示不使用layout括荡。下面看看test.hbs文件的寫法

<ul>
{{#each users}}
    <li>{{this.username}}---{{this.age}}</li>
{{/each}}
</ul>

通過each遍歷了users。使用handlebars是不是要熟悉一些呢溉旋?

使用express-generator創(chuàng)建項目

現(xiàn)在我們應(yīng)該已經(jīng)對express有了大致的了解畸冲,下面就可以使用express-generator來生成express項目了,這將會極大的簡化我們的開發(fā)操作,首先將express-generator安裝到全局中邑闲。

npm install express-generator -g

安裝完成之后使用

express 13_express

此時會完成express骨架的創(chuàng)建算行,首先看看package.json文件

{
  "name": "13-express",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www"
  },
  "dependencies": {
    "body-parser": "~1.18.2",
    "cookie-parser": "~1.4.3",
    "debug": "~2.6.9",
    "express": "~4.15.5",
    "jade": "~1.11.0",
    "morgan": "~1.9.0",
    "serve-favicon": "~2.4.5"
  }
}

看看scripts中的start腳本,表示服務(wù)器的啟動文件不是app.js而是bin路徑中的www文件苫耸,我們可以將其修改為nodemon ./bin/www州邢,之后看看依賴包,首先body-parser用來解析http請求的褪子,可以非常輕松的解析json數(shù)據(jù)格式量淌;cookie-parse用來解析cookie請求,debug用來進(jìn)行調(diào)試嫌褪,jade就是模板引擎呀枢,可以將其修改為handlebars,morgan是日志組件笼痛,serve-favicon用來處理圖標(biāo)裙秋,此時這些包并沒有安裝到我們的項目中的,需要使用install進(jìn)行安裝

npm install

之后移除jade晃痴,可以安裝pug

npm remove jade --save
npm install pug --save

看看最重要的app.js

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

//定義了兩個路由模塊
var index = require('./routes/index');
var users = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
//靜態(tài)文件的處理残吩,所有的靜態(tài)文件在public中
app.use(express.static(path.join(__dirname, 'public')));

//路由處理,/會交給index模塊處理
app.use('/', index);
// users開頭的會交給user模塊處理
app.use('/users', users);

//異常處理
// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

我們能夠找到一些熟悉的身影倘核,如模板引擎泣侮,我們可以注意到它已經(jīng)幫我們處理了靜態(tài)文件,在public文件夾中紧唱。而路由引擎是由兩個獨立的模塊來實現(xiàn)的而在router的文件夾活尊,簡單看看路由文件index.js

var express = require('express');
var router = express.Router();

/* 此處沒有使用use而是使用get */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});

module.exports = router;

注意路由中使用的是get,這樣只會捕獲根目錄的信息漏益∮济蹋可以在這些js文件中專門增加自己的路由信息。至于其他模塊绰疤,大家在使用中自然而然就會了铜犬。關(guān)鍵是主要的思路,下面我們會給大家介紹session和表單的validate的模塊轻庆。

cookie-parser和body-parser模塊

首先看一個實例癣猾,通過表單提交一個post請求,首先新建一個項目余爆,導(dǎo)入express的模塊纷宇,編寫如下的代碼:

var express = require("express");

var app = express();

app.get("/",function(req,resp) {
    resp.sendFile("index.html",{root:__dirname+"/publics"});
});


app.listen(3000,function (req,resp) {
   console.log("server start!");
});

在app的get方法中,用了一個新的方法resp.sendFile蛾方,該方法類似于fs.readFile方法像捶,該方法會渲染根目錄下的publics中的index.html文件上陕,該文件中創(chuàng)建了一個表單

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello</title>
</head>
<body>
    Hello app!
    <form action="/form?hello=abc" method="post">
        <input type="text" name="username"/><br/>
        <input type="submit"/>
    </form>
</body>
</html>

form的action中通過get傳遞了一個參數(shù)hello,表單是通過post的請求提交的拓春,接下來看看處理的代碼

app.post("/form",function (req,resp) {
   resp.send(req.query.hello+","+req.query.username);
});

程序中通過req.query來獲取瀏覽器的get參數(shù)释簿,我們會發(fā)現(xiàn)req.query.username取不到任何值,這說明req.query僅僅只能獲取get的請求參數(shù)硼莽,那該如何獲取post的請求參數(shù)呢辕万?此時就需要使用body-parser的中間件來執(zhí)行。首先安裝body-parser中間件

E:\study\nodejs_2018\15_body>npm install body-parser --save
npm WARN 15_body@1.0.0 No description
npm WARN 15_body@1.0.0 No repository field.
+ body-parser@1.18.2
updated 1 package in 3.891s

看看源代碼沉删,和原來的差不多,但是需要引入body-parser的中間件

var express = require("express");
var bodyParser = require("body-parser");
app.use(bodyParser());
app.post("/form",function (req,resp) {
    //使用req.body來獲取name為username的值
   resp.send(req.query.hello+","+req.body.username);
});

此時form中的內(nèi)容就可以通過req.body來讀取醉途。通過這個實例大家應(yīng)該清楚body-parser的作用了矾瑰,接下來我們來看看如何處理cookie,cookie和jsp中的cookie是一樣隘擎,我們需要cookie-parser模塊支持殴穴,首先安裝cookie-parser的中間件。

npm install cookie-parser --save

首先需要引入cookie-parser货葬,并且引入cookie-parser采幌,編寫一個login的路由

var cookieParser = require("cookie-parser");
//使用cookie-parser的中間件。
app.use(cookieParser());

//基于get請求的login
app.get("/login",function(req,resp){
   resp.sendFile("form.html",{root:__dirname+"/publics"});
});

這是get請求震桶,訪問login會直接訪問form.html

<form action="/login" method="post">
  username:<input type="text" name="username"/><br/>
  password:<input type="password" name="password"/><br/>
  <input type="submit"/>
</form>

通過post請求提交給/login的路由

//基于post請求的login
app.post("/login",function (req,resp) {
   var username = req.body.username;
   var password = req.body.password;
   if(username=="admin"&&password=="123") {
       //存儲了cookie休傍,時間是60分鐘
       resp.cookie("user",{username:username,password:password},{maxAge:600000,httpOnly:true});
   }
   resp.redirect("/loginOk");
});

如果用戶名和密碼正確通過resp.cookie方法存儲cookie,cookie的名稱是user蹲姐,存儲了一個username和password的對象磨取,有效時間是60分鐘,然后是基于http請求的存儲柴墩。最后通過resp.redirect("/loginOk")忙厌,這其實就是jsp中的服務(wù)器跳轉(zhuǎn)。最后看看loginOk是如何讀取cookie的

app.get("/loginOk",function (req,resp) {
   var cookies = req.cookies.user;
   if(cookies) {
       resp.send("hello:"+cookies.username);
   } else {
       resp.send("no cookies found!");
   }
});

通過req來讀取cookies的信息江咳。

在這一小節(jié)結(jié)束之前我們需要再次總結(jié)req獲取參數(shù)的三種方式:

1逢净、req.params.xx 這是獲取路徑中的參數(shù)

2、req.query.xx 這是獲取get請求的參數(shù)

3歼指、req.body.xx 這是通過body-parser來獲取form表單中的post請求爹土。

express的session

express同樣也支持session,需要express-session的支持东臀,首先通過npm安裝express-session

npm install express-session --save

在app.js中引入這個中間件并且創(chuàng)建session

var session = require("express-session");
app.use(session({
    secret: 'a4f8071f-c873-4447-8ee2'
}));

secret是一個服務(wù)器端的簽名着饥,這個字符串可以隨便設(shè)定,之后通過req.session來寫和讀取session惰赋,session的操作非常簡單

app.get("/session",function (req,resp) {
   req.session.username = "admin";
   req.session.nickname = "超級管理員";
   resp.redirect("/sessionOk");
});

app.get("/sessionOk",function (req,resp) {
   resp.send("session ok:"+req.session.username+"("+req.session.nickname+")");

});

通過/session的路由來設(shè)定session宰掉,在sessionOk中來讀取session的值呵哨。session如果沒有設(shè)定特殊的cookie的值,關(guān)閉瀏覽器就失效轨奄。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末孟害,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子挪拟,更是在濱河造成了極大的恐慌挨务,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件玉组,死亡現(xiàn)場離奇詭異谎柄,居然都是意外死亡,警方通過查閱死者的電腦和手機惯雳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門朝巫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人石景,你說我怎么就攤上這事劈猿。” “怎么了潮孽?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵揪荣,是天一觀的道長。 經(jīng)常有香客問我往史,道長仗颈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任椎例,我火速辦了婚禮揽乱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘粟矿。我一直安慰自己凰棉,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布陌粹。 她就那樣靜靜地躺著撒犀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪掏秩。 梳的紋絲不亂的頭發(fā)上或舞,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天,我揣著相機與錄音蒙幻,去河邊找鬼映凳。 笑死,一個胖子當(dāng)著我的面吹牛邮破,可吹牛的內(nèi)容都是我干的诈豌。 我是一名探鬼主播仆救,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼矫渔!你這毒婦竟也來了彤蔽?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤庙洼,失蹤者是張志新(化名)和其女友劉穎顿痪,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體油够,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡蚁袭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了石咬。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片撕阎。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖碌补,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情棉饶,我是刑警寧澤厦章,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站照藻,受9級特大地震影響袜啃,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜幸缕,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一群发、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧发乔,春花似錦熟妓、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至译仗,卻和暖如春抬虽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背纵菌。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工阐污, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人咱圆。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓笛辟,卻偏偏與公主長得像功氨,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子隘膘,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,614評論 2 353

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