Nodejs编程(3)

第7章 express 框架

7.1 简介

Express 是基于 Node.js 平台,快速、开放、极简的 Web 开发框架, 提供一系列强大特性帮助你创建各种Web应用。Express 不对 node.js 已有的特性进行二次抽象,我们只是在它之上扩展了Web应用所需的功能。丰富的HTTP工具以及来自Connect框架的中间件随取随用,创建强健、友好的API变得快速又简单

7.2 安装使用

就像一个普通的第三方模块一样安装即可;

npm init npm install express

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

app.get('/',(req,res)=>{
    res.send('hello world !');
})

app.listen('8000',()=>{
    console.log('127.0.0.1:8000')
})

其中 Request、Response -- API 我们需要重点关注

第8章 项目的重构

将我们之前的海贼王项目使用express框架进行重写,重写过程中,学习框架提供的各种API,并完善项目功能;

8.1 启动服务器

创建http.js

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

app.listen('8000',()=>{
    console.log('127.0.0.1:8000')
})

8.2 重写路由模块

之前我们写了一个独立的模块(luyou.js)来处理请求,而在 express 中已经帮我们写好了路由的请求处理规则,不需要我们进行判断;

路由 是指确定应用程序如何响应对特定端点的客户端请求,该请求是URI(或路径)和特定HTTP请求方法(GET,POST等)。

每个路由都可以有一个或多个处理函数,这些函数在路由匹配时执行。

8.2.1 express 中的基本路由

路径定义采用以下结构:

app.method(path, handler)

以下示例定义了简单路由。

Hello World!在主页上回复:

app.get('/', function (req, res) {
  res.send('Hello World!')
})

在根路由(/),应用程序的主页上响应POST请求:

app.post('/', function (req, res) {
  res.send('Got a POST request')
})

响应对/user路由的PUT请求:

app.put('/user', function (req, res) {
  res.send('Got a PUT request at /user')
})

响应对/user路由的DELETE请求:

app.delete('/user', function (req, res) {
  res.send('Got a DELETE request at /user')
})

8.2.2. 外置路由

设置 外置路由 rout.js

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

router.get('/',(req,res)=>{
    res.send('123');
})
router.get('/user',(req,res)=>{
    res.send('user');
})
router.post('/edit',(req,res)=>{
    res.send('post_edit');
})

// 导出 router
module.exports = router;

写好路由规则,一定要记得将 路由对象(router) 导出

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

// 引入外置路由
var rout = require('./rout');
app.use(rout); // 使用引入外置的路由

app.listen('8000',()=>{
    console.log('127.0.0.1:8000')
})

将外置路由引入后,使用 app.use() 进行加载使用;

8.2.3 使用外置路由修改项目

在 luyou.js 中,注释以前的代码,添加新代码

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

router.get('/', (req, res) => {
    yewu.getall(function (data) {
        res.end(data);
    })
})

module.exports = router;

在 http.js 中,使用 express 启动服务,并引入使用新修改的 luyou.js 模块

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

var luyou = require('./luyou');
app.use(luyou);

app.listen('8080',()=>{
    console.log('127.0.0.1:8080')
})

8.2.4 使用链式操作添加路由

luyou.js

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

// express的路由支持链式操作
router
.get('/', (req, res) => {
    yewu.getall(function (data) {
        res.end(data);
    })
})
.get('/getuser', (req, res) => {
    // req 提供了query属性获取请求参数
    var id = req.query.id;
    // 在yewu模块中封装方法,传递id参数。
    // 使用回掉函数获取数据
    yewu.getone(id, function (data) {
        res.end(data);
    });
})

module.exports = router;

8.2.5 优化路由模块

路由模块 (luyou.js) 中只负责调用,调用时,将req res 传入业务模块

router
.get('/', (req, res) => {
    yewu.getall(req,res);
    // yewu.getall(function (data) {
    //     res.end(data);
    // })
})
.get('/getuser', (req, res) => {
    yewu.getone(req,res);
    // req 提供了query属性获取请求参数
    // var id = req.query.id;
    // // 在yewu模块中封装方法,传递id参数。
    // // 使用回掉函数获取数据
    // yewu.getone(id, function (data) {
    //     res.end(data);
    // });
})

业务模块接受 req res 负责处理请求并响应数据

getall: function (req,res) {
    db.select(function (data) {
        // 利用回调函数获取数据
        var html_data = template('./index.html', { data: data });
        // console.log(html_data);
        res.end(html_data);
    });
},
getone:function(req,res){
    db.where('id='+req.query.id).select(function(data){
        var user_data = template('./users.html',{data:data});
        res.end(user_data);
    });
},

继续简化路由模块

router
.get('/',yewu.getall)
.get('/getuser',yewu.getone)

原理:

function fn(callback){
    var a = 1;
    var b = 2;
    callback(a,b);
}

var pros = function(a,b){
    console.log(a+b);
}

fn(function(a,b){
    pros(a,b);
})

// fn(pros);

8.3 重写模板引擎

art-template@4 新特性

express-art-template

安装:

npm install --save art-template
npm install --save express-art-template

官方示例:

var express = require('express');
var app = express();
app.engine('art', require('express-art-template'));
app.set('view options', {
    debug: process.env.NODE_ENV !== 'production'
});

app.get('/', function (req, res) {
    res.render('index.art', {
        user: {
            name: 'aui',
            tags: ['art', 'template', 'nodejs']
        }
    });
});

修改 http.js 将 express-art-template 注册为express框架的模板引擎,并设置模板后缀为 html

在项目中新建views目录,将所有静态页面放入views目录

8.4 利用 Express 托管静态文件

http://www.expressjs.com.cn/starter/static-files.html

在项目中新建 public 文件夹并将bootstrap.css移入, 修改 index.html 加载 css 静态文件 ,在http.js中引入并设置静态资源加载路径:

如果要使用多个静态资源目录,请多次调用 express.static 函数:

app.use(express.static('public'))
app.use(express.static('files'))

访问静态资源文件时,express.static 函数会根据目录的添加顺序查找所需的文件。

8.5 完成项目重构

修改所有路由及业务模块代码

luyou.js

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

router
.get('/',yewu.getall)
.get('/getuser',yewu.getone)
.get('/upuser',yewu.upuser_get)
.post('/upuser',yewu.upuser_post);

module.exports = router;

yewu.js

// var linkdb = require('./linkdb');
var db = require('./db');
var querystring = require('querystring');
// template.defaults.root = './';

module.exports = {
    getall: function (req, res) {
        db.select(function (data) {
            res.render('index.html', { data: data });
        });
    },
    getone: function (req, res) {
        db.where('id=' + req.query.id).select(function (data) {
            res.render('./users.html', { data: data });
        });
    },
    upuser_get: function (req, res) {
        db.where('id=' + req.query.id).select(function (data) {
            res.render('./upuser.html', { data: data });
        });
    },
    upuser_post: function (req, res) {
        var data = '';
        req.on('data', function (che) {
            data += che;
        })
        // 绑定end事件,监听数据接受完成
        req.on('end', function () {
            // console.log(data);
            // 获取Post传输的数据
            var post_data = querystring.parse(data);

            // 调用数据模块修改用户信息
            db.where('id=' + req.query.id).update(post_data, function (changedRows) {
                // http服务器相应要求必须是字符串
                res.json(changedRows);
            })
        })
    }
}

8.6 展示用户头像

8.7 修改用户头像

8.7.1 测试文件上传

创建服务器:

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

app.post('/upfile',(req,res)=>{
    var data = '';
    req.on('data', function (che) {
        data += che;
    });
    req.on('end',()=>{
        // 直接打印post传过来的数据
        console.log(data);
    })
})

app.listen('8000',()=>{
    console.log('127.0.0.1:8000')
})

使用postman工具上传文件:

8.7.2 借助第三方插件处理文件上传

https://www.npmjs.com/package/formidable

安装模块 `npm install formidable`

var express = require('express');
var formidable = require('formidable');
var fs = require('fs');
var app = express();

app.post('/upfile', (req, res) => {
    var form = new formidable.IncomingForm();
    
    // form.uploadDir = './img'; // 设置上传路径
    // form.keepExtensions = true; // 保留文件扩展名

    form.parse(req, function (err, fields, files) {
        var times = new Date().getTime();
        // 组装上传路径
        var file_path = './img/'+times+files.imgs.name;
        // 将缓存文件移动至制定目录
        fs.rename(files.imgs.path,file_path,(err)=>{
            console.log(file_path);
        });
        res.end();
    });
})

app.listen('8000', () => {
    console.log('127.0.0.1:8000')
})

8.7.3 在项目中实现文件上传

修改 upuser.html

修改业务模块 yewu.js 使用 formidable 获取 post 数据,实现文件上传

upuser_post: function (req, res) {
    var form = new formidable.IncomingForm();

    form.parse(req, function (err, fields, files) {
        var times = new Date().getTime();
        // 组装上传路径
        var file_path = './public/img/' + times + files.imgs.name;
        // 将缓存文件移动至指定的public目录
        fs.rename(files.imgs.path, file_path, (err) => {
            if(!err){
                // 因为设置静态资源时,已经时public文件夹,写入数据库时,不要加public
                fields.img = './img/' + times + files.imgs.name;
                db.where('id=' + req.query.id).update(fields, function (changedRows) {
                    // http服务器相应要求必须是字符串
                    res.json(changedRows);
                })
            }else{
                console.log('文件上传失败'+err);
            }
        });
    });
}

8.8 用户登陆

8.8.1 登陆逻辑及cookie-session 的使用

express官方资源中,为我们提供了一个中间件,cookie-session

npm install cookie-session

测试代码:

var express = require('express');
var cookieSession = require('cookie-session')
var app = express();

// 注册中间件 
app.use(cookieSession({
    name: 'session', // 客户端cookie的名称
    keys: ['ss'] // 用于加密的关键字
}))

app.get('/', (req, res) => {
    // 获取并判断session
    if(req.session.sess_data){
        res.send('已经登陆')
    }else{
        // 如果没有session,跳转到登陆页面
        res.send('<script>alert("没登陆");window.location.href="/up"</script>');
    }
})
app.get('/up', (req, res) => {
    // 展示登陆页面,获取用户数据并写入session 
    req.session.sess_data = {name:12,age:89};
    res.send('已写入session');
});

8.8.2 完成项目登陆功能

修改http模块,注册 cookie-session 中间件;

var express = require('express');
var app = express();
var cookieSession = require('cookie-session');

// 注册中间件 
app.use(cookieSession({
    name: 'session', // 客户端cookie的名称
    keys: ['xilingzuishuai'] // 用于加密的关键字
}))

在业务模块 (yewu.js) 中 添加逻辑判断,只有登陆后才能展示首页:

getall: function (req, res) {
    // 获取并判断session
    if (req.session.sess_data) {
        db.select(function (data) {
            res.render('index.html', { data: data });
        });
    } else {
        // 如果没有session,跳转到登陆页面
        res.send('<script>alert("没登陆");window.location.href="/upload"</script>');
        // res.send('没登陆');
    }
},

在路由模块(luyou.js) 中添加以下两个路由,get 展示静态登陆页面,post 获取用户提交的数据并写入 session ,写入成功后,跳转到首页;在业务模块(yewu.js)中添加响应的方法

.get('/upload',yewu.upload_get) .post('/upload',yewu.upload_post)

upload_get: (req, res) => {
    // 展示登陆页面
    res.render('./upload.html', {});
},

upload_post: (req, res) => {
    var form = new formidable.IncomingForm();
    form.parse(req, function (err, fields, files) {
        // console.log(fields);
        // 获取用户提交数据,判断用户名密码是否正确
        if (fields.userName == "admin" && fields.pwd == "123") {
            // 数据正确,写入session
            req.session.sess_data = fields;
            res.send('<script>alert("登陆成功");window.location.href="/"</script>');
        }else{
            // 数据错误,重新跳回登陆页面
            res.send('<script>alert("登陆失败");window.location.href="/upload"</script>');
        }
    })
}

第9章 Express的中间件

9.1 什么是中间件

在一个整体的流程中的某个环节,因为某些原因加入了额外的处理环节;

9.2   中间件的使用

9.2.1 应用中间件

语法:

  • app.use()

  • app.use(function(){})

无论发送任何请求都会执行的中间件

  • app.use('/path', function(){})

只要在请求path路由时才会执行的中间件(无论GET/POST)

  • app.method()

  • app.get()

在get请求时会执行的中间件

  • app.post()

在post请求时会执行的中间件

app.use() 的用法

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

// 在中间件之前,不受中间件影响
app.get('/',function(req,res){
    console.log(123);
})

// 应用中间件
// 请求 '/user' 时,会先调用中间件
app.use(function (req, res, next) {
    console.log(req);
    next();
});

// 调用之前先调用中间件
app.get('/user',function(req,res){
    console.log('user');
})

app.listen('8000', () => {
    console.log('127.0.0.1:8000')
})

app.method() 的用法

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

// 在中间件之前,不受中间件影响
app.get('/',function(req,res){
    console.log(123);
})

// 应用中间件
// 只有在 post 请求user 时才起作用
app.post('/user',function (req, res, next) {
    console.log(req);
    next();
});

// 调用之前先调用中间件
// 接受所有请求方式请求user
app.all('/user',function(req,res){
    console.log('user');
})

app.listen('8000', () => {
    console.log('127.0.0.1:8000')
})

9.2.2 路由中间件

路由器层中间件的工作方式与应用层中间件基本相同,差异之处在于它绑定到 express.Router() 的实例。

使用 router.use()router.METHOD() 函数装入路由器层中间件;

我们之前项目的代码,就是在使用路由中间件:

var router = express.Router();

router
.get('/',yewu.getall)
.get('/getuser',yewu.getone)
.get('/upuser',yewu.upuser_get)
.post('/upuser',yewu.upuser_post)

.get('/upload',yewu.upload_get)
.post('/upload',yewu.upload_post)
;

9.2.3 内置中间件

express.static 外,先前 Express 随附的所有中间件函数现在以单独模块的形式提供:中间件函数的列表

Express 中唯一内置的中间件函数是 express.static。此函数基于 serve-static,负责提供 Express 应用程序的静态资源。

对于每个应用程序,可以有多个静态目录:

app.use(express.static('public'));
app.use(express.static('uploads'));
app.use(express.static('files'));

9.2.4 第三方中间件

使用第三方中间件向 Express 应用程序添加功能。

安装具有所需功能的 Node.js 模块,然后在应用层或路由器层的应用程序中将其加装入。

var cookieSession = require('cookie-session');

// 注册中间件 
app.use(cookieSession({
    name: 'session', // 客户端cookie的名称
    keys: ['xilingzuishuai'] // 用于加密的关键字
}))

猜你喜欢

转载自blog.csdn.net/qq_31784189/article/details/114411659