NodeJS入门实践第二讲Express的使用

NodeJS入门实践第二讲Express的使用

NodeJs提供了的方法处理起来比较麻烦,在使用nodejs时有很多现成的框架帮助开发人员,其中最简单的一个server框架就是Express,express的安装方式有两种,一种是在项目文件夹中安装express,另外一个是通过express的generator来生成一个express的骨架,我们先从最原始的方式来了解express中的几个比较核心的概念

基于原始的方式使用express

首先创建一个项目,之后初始化为npm类型的项目,要生成node的基本项目,需要使用npm init 进行初始化,初始化会输入一些基本的项目信息,这个步骤和java的maven非常类似,等于创建了maven的pom文件,而对于node而言是创建了package.json文件。

下一步使用npm安装express,由于express仅仅只是存在在当前项目中,所以安装不用使用-g进行全局安装,但是需要增加–save的参数,这个表示会把这些信息添加到package.json的依赖中。
npm install express --save

大家会发现package.json中有了一个dependencies,添加了express的依赖。在这个文件我进行两个设置,在scripts中增加了start的脚本,该脚本使用node app.js来运行一个文件,此时app.js是我们的核心的服务器文件,添加了这个脚本之后,可以直接使用npm start 运行该脚本。

下来创建app.js来运行一个express的应用

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!!");
});

已上程序中头两行创建了express的对象,app.get(xx)这个和nodejs的路由一模一样,表示接收了get请求,之后使用function回调函数进行处理,通过resp的send方法可以输出数据到网页,app.listen(xx)表示监听端口,等于nodejs中的createServer。已上程序只要运行之后在浏览器中输入localhost:3000/hello将会显示hello express的文本在浏览器中。这就是一个简单的express的应用,注意express是一个完全基于路由的架构,下面我们来详细了解express中最核心的一个概念:中间件。

express的中间件

express是一个自上而下进行执行的运用,在具体讲解之前,我们加入一个应用包,我们现在的程序只要改动app.js都得开发人员自动关闭和启动nodejs。在npm中有一个叫做nodemon的框架,可以帮助我们自动重新启动,nodemon建议大家安装成全局类型,这样方便所有的应用都能使用,使用下面的脚本安装
npm install nodemon -g
安装完成之后只要通过nodemon app.js此时只要项目中的文件有变化它会自动启动,为了方便这个操作,我将package.json中start的脚本进行的了简单的修改

....
"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的参数,通过req可以显示这个参数。此时当我们输入路径localhost:3000/hello,express在读取代码的时候会首先匹配到,它会将hello认为是username,所以浏览器中会显示hello:hello 第二个/hello的路由就不会再被匹配了,express的执行方式就是这样的。只要匹配到一个路由,如果没有做任何特殊的处理,处理完就停止了。

上面我们提到的特殊处理就是中间件的一种形式,如果我们在第一个函数中增加一个next的参数,就能够做一些特殊处理,大家看代码

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。执行完成之后使用了next(),这表示express会继续向下执行请求,所以第二个路由/hello也会被执行,所以将会输出hello express。这就是express中间件的一个核心操作方式,用户可以通过next()来确定路由请求是否往下提交。下面我们来看express另一个重要的函数,use函数。

开始我们已经多次强调了express的所有操作都是基于路由进行的,其中get方法处理get请求,post方法处理post请求,而还有一个特殊的use方法,也是处理请求,但它的特殊性在于,它会自动匹配满足条件的所有请求,首先就刚才讲的例子来看,我们的地址如果是localhost:3000/hello/abc。此时有两个路径,express一个都不会进行匹配。
此时如果将get改成use,express会自动匹配所有/hello开头的请求

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

我们发现,只要路径是以/hello开头的所有路径都会被匹配如: /hello/abc,/hello/abc/a/b等等,这些都会被匹配。此时如果有个地址是app.use("/",function(req,resp)) 那是不是意味着所有的请求都会通过这个函数,此时如果不使用next,那意味着,请求到这个就终止了,但是我们可以通过next将请求往下执行。如果地址是/,我们可以省略第一个参数使用app.use(function(req,resp)) 来替换。

以上操作就提供了一种方式,让我们可以让express执行我们的某个模块,这个模块我就将其称之为中间件,接下来我们自己编写一个处理静态资源文件的中间件。

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的函数,所有请求都会调用

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的处理流程已经有了一个清晰的理解了,这种中间件的方式为我们的代码带来了极大的灵活性,我们可以非常轻松的往express中添加和删除各种模块。

使用express-generator创建项目

现在我们应该已经对express有了大致的了解,下面就可以使用express-generator来生成express项目了,这将会极大的简化我们的开发操作,首先将express-generator安装到全局中。

  • npm install express-generator -g

安装完成之后使用

  • express 13_express

此时会完成express骨架的创建,首先看看package.json文件

看看scripts中的start脚本,表示服务器的启动文件不是app.js而是bin路径中的www文件,我们可以将其修改为nodemon ./bin/www,之后看看依赖包,首先body-parser用来解析http请求的,可以非常轻松的解析json数据格式;cookie-parse用来解析cookie请求,debug用来进行调试,jade就是模板引擎,可以将其修改为handlebars,morgan是日志组件,serve-favicon用来处理图标,此时这些包并没有安装到我们的项目中的,需要使用install进行安装
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());
//静态文件的处理,所有的静态文件在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;  

cookie-parser和body-parser模块

var express = require("express");
var bodyParser = require("body-parser");
// var app = require("./app");
var app = express();
app.use(bodyParser());
app.get("/",function(req,resp) {
    // resp.sendFile("index.html",{root:__dirname+"/publics"});
    resp.sendFile("index.html",{root:__dirname});
});
app.listen(3000,function (req,resp) {
   console.log("server start!");
}); 
app.post("/form",function (req,resp) {
    //使用req.body来获取name为username的值
   resp.send(req.query.hello+","+req.body.username);
   // resp.send(req.query.hello);
}); 
<!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> 

程序中通过req.query来获取浏览器的get参数,我们会发现req.query.username取不到任何值,这说明req.query仅仅只能获取get的请求参数,那该如何获取post的请求参数呢?此时就需要使用body-parser的中间件来执行。首先安装body-parser中间件

npm install body-parser --save

此时form中的内容就可以通过req.body来读取。通过这个实例大家应该清楚body-parser的作用了,接下来我们来看看如何处理cookie,cookie和jsp中的cookie是一样,我们需要cookie-parser模块支持,首先安装cookie-parser的中间件。

npm install cookie-parser --save

var express = require("express");
var bodyParser = require("body-parser");
var cookieParser = require("cookie-parser");
var session = require("express-session");
var app = express();
app.use(bodyParser());
//使用cookie-parser的中间件。
app.use(cookieParser());
app.use(session({
    secret: 'a4f8071f-c873-4447-8ee2'
}));

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


//基于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");
}); 

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

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+")");

}); 

app.listen(3000,function (req,resp) {
   console.log("server start!");
}); 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello</title>
</head>
<body>
    <form action="/login" method="post">
	  username:<input type="text" name="username"/><br/>
	  password:<input type="password" name="password"/><br/>
	  <input type="submit"/>
	</form>
</body>
</html> 

如果用户名和密码正确通过resp.cookie方法存储cookie,cookie的名称是user,存储了一个username和password的对象,有效时间是60分钟,然后是基于http请求的存储。最后通过resp.redirect("/loginOk"),这其实就是jsp中的服务器跳转。最后看看loginOk是如何读取cookie的

在这一小节结束之前我们需要再次总结req获取参数的三种方式:
1、req.params.xx 这是获取路径中的参数
2、req.query.xx 这是获取get请求的参数
3、req.body.xx 这是通过body-parser来获取form表单中的post请求。

express的session

express同样也支持session,需要express-session的支持,首先通过npm安装express-session
npm install express-session --save

secret是一个服务器端的签名,这个字符串可以随便设定,之后通过req.session来写和读取session,session的操作非常简单

通过/session的路由来设定session,在sessionOk中来读取session的值。session如果没有设定特殊的cookie的值,关闭浏览器就失效。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值