Express 1.Express框架 基于 Node.js 平台,快速、开放、极简的 web 开发框架。 它是用于后台NodeJs的框架,与JQuery/Bootstrap/vue.js/AngularJs这类前端框架是不一样的! Express 不对 Node.js 已有的特性进行二次抽象,我们只是在它之上扩展了 Web 应用所需的基本功能。 丰富的 HTTP 快捷方法和任意排列组合的 Connect 中间件,让你创建健壮、友好的 API 变得既快速又简单。
对比原生Node.js 使用原生Node.js开发,会发现有很多问题: - 呈现静态页面很不方便,需要处理每个HTTP请求,还要考虑304缓存问题. - 路由处理代码不直观清晰,需要写很多正则表达式和字符串函数. - 开发者不能集中精力写业务,要考虑很多其他的东西.
官网:http://expressjs.com/ 中文官网:http://www.expressjs.com.cn/
2.安装 npm install express –save #即可安装最新版本的Express
Express4.x与3.x版本的差别非常大,我们使用4.x
2.1. 基本使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 // 引入express 框架 var express = require('express'); // console.log(express); // 创建 express 的 HTTP服务器 var app = express(); // 指定框架的模版引擎,无需导入 app.set('view engine', 'ejs'); // 指定静态化的目录 app.use('/static', express.static('./static')); // 设置路由规则 app.get('/', function(req, res){ // 响应输出 res.send('Hello Express~~~'); }); app.get('/test', function(req, res){ // 响应输出 res.send('这是test页面'); }); app.get('/user', function(req, res){ // 绑定并输入数据 res.render('user', { 'userlist' : [ '钢铁侠 屎大颗', '绿巨人 浩克', '美队 史蒂文', '雷神 托尔', '邪神 洛基', '蜘蛛侠 彼得帕克' ] }); }); // 设置请求监听 app.listen(3000);
2.2. 路由处理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 // 引入express 框架 var express = require('express'); // 创建 express 的 HTTP服务器 var app = express(); // 支持所有的请求方式, 实现中间件的功能 app.all('/t', function(req, res, next){ console.log(new Date().toString()); next(); }); // 设置路由规则 app.get('/', function(req, res){ // 响应输出 res.send('Hello Express~~~'); }); // GET app.get('/t', function(req, res){ // 响应输出 res.send('GET 请求'); }); // POST app.post('/t', function(req, res){ // 响应输出 res.send('POST 请求'); }); // DELETE app.delete('/t', function(req, res){ // 响应输出 res.send('DELETE 请求'); }); // 路由方法默认匹配 pathnameb部分,忽略get参数 // 对大小写不敏感 app.get('/aaa', function(req,res){ console.log(req.query); res.send('3A页面 '); }); // 路由路径 默认express path-to-regexp 匹配路由路径 // 正则路由 /stu/1234567890/tom app.get(/^\/stu\/(\d{10})\/(\w+)$/, function(req,res){ console.log(req.params); res.send('学员的学号是: '+ req.params[0]); }); // 路由参数 // :xx 表示参数占位,使用req.params读取参数 app.get('/tch/:tid', function(req,res){ console.log(req.params); res.send('老师的工号是: '+req.params.tid); }); // 多个路由参数 app.get('/goods/:name/:num', function(req,res){ // 参数限制 var name = req.params.name; var num = req.params.num; if (/\d+/.test(num)) { res.send('商品名: ' + name + ', 入库: ' + num + '件'); } else { res.send('请填写正确的数量'); } }); // 设置请求监听 app.listen(3000);
2.3. 对模版引擎的支持
2.4. 静态文件/目录处理
3.路由 3.1. 路由的访问方式
3.2. 路由路径
3.3. 响应方法 res.download() 提示下载文件。 res.end() 终结响应处理流程。 res.json() 发送一个JSON格式的响应。 res.jsonp() 发送一个支持JSONP的JSON格式的响应 res.redirect() 重定向请求。 res.render() 渲染视图模板。 res.send() 发送各种类型的响应。 res.sendFile() 以八位字节流的形式发送文件。 res.sendStatus() 设置响应状态代码,并将其以字符串形式作为响应体的一部分发送。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 var express = require('express'); var app = express(); // 路由重名 // 路由中间件 app.get('/kk',function(req,res,next){ console.log(1); next(); }); app.get('/kk',function(req,res){ console.log(2); res.send('响应完成'); }); // 匹配冲突 app.get('/:goods/:num',function(req, res, next){ // 做查询/匹配... if (false) { console.log(1); res.send('商品' + req.params.goods + '数量:'+req.params.num); } else { next(); } }); app.get('/admin/login',function(req,res){ console.log(2); res.send('登录界面'); }); app.listen(3000);
4.中间件 4.1. 中间件概念
4.2. express路由 具有的中间件特性
4.3. app.use()的特性
app.use() 就是一个中间件,与get()/post()..方法不用的是, 它的URL不是精确匹配,而是模糊匹配
4.4. app.use()使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 var express = require('express'); var app = express(); // 全局中间件 app.use(function(req, res, next){ console.log(new Date().toString()); next(); }); // 中间件 app.use('/admin',function (req, res) { res.write(req.originalUrl + '\n'); // 完整的URL res.write(req.baseUrl + '\n'); // 基础URL res.write(req.path + '\n'); // 除去基础以外的URL res.end('后台...'); }); app.listen(3000);
4.5. 静态资源服务的说明
4.6. 404 页面的说明
5.模版引擎,渲染页面 5.1. 模版引擎 的设置和使用
5.2. 原生的 end() 与express的 send() 的区别
5.3. 设置响应头 和 状态码 和 MIME类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 var express = require('express'); var app = express(); // 指定框架的模版引擎,无需导入 app.set('view engine', 'ejs'); // 提供静态资源服务 // app.use(express.static('./static')); // 默认使用 .ejs 为模版文件,目录views // app.set('views', './pages'); app.get('/', function (req,res){ // 绑定数据并渲染视图 res.render('user', { 'userlist' : [ '钢铁侠 屎大颗', '绿巨人 浩克', '美队 史蒂文', '雷神 托尔', '邪神 洛基', '蜘蛛侠 彼得帕克' ] }); }); app.get('/hh', function (req,res){ // node.js end() // express send() // 二进制 // res.send(new Buffer('HOOH~')); // str // res.send('HOOH~'); // JSON // res.send({name:"静静", sec:0}); // ARRAY res.send([15,168,19681,9681,98,986884,true]); }); app.listen(3000);
6.GET 与 POST 6.1 GET GET请求的参数在URL中. 原生node中,要想得到get参数,需要借助于url模块来识别参数字符串. 在Express中,不需要使用url模块了.可以直接使用req.query对象得到GET参数
6.2 POST GET请求的参数是隐蔽传参(在请求体中). POST请求在Express中不能直接获得,必须使用body-parser模块.使用后,将可以用req.body得到参数. 但是如果表单中含有文件上传,那么还是需要使用formidable模块.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 var express = require('express'); var bodyParser = require('body-parser'); var app = express(); // 指定框架的模版引擎,无需导入 app.set('view engine', 'ejs'); // parse application/x-www-form-urlencoded // 解析 post数据 app.use(bodyParser.urlencoded({ extended: false })); //GET参数 app.get('/', function (req,res){ console.log(req.query); res.send('GET 完成'); }); app.get('/form', function (req,res){ res.render('form'); }); // POST app.post('/', function (req,res){ console.log(req.body); res.send('POST 完成'); }); app.listen(3000);
7.Express对数据库的支持 7.1 数据库集成
7.2 连接mysql数据库
7.3 使用数据库 - 查/增/改/删
7.4 连接池
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 var express = require('express'); var mysql = require('mysql'); var app = express(); app.get('/', function(req,res){ // 连接数据库 var connection = mysql.createConnection({ host : '127.0.0.1', user : 'root', password : '123456', database : 's86' }); // 开启数据库 connection.connect(); // var sql = 'SELECT * FROM user'; var sql = 'UPDATE user SET age="19" WHERE id="1"'; connection.query(sql, function (err, result) { if (err) { console.log('执行出错: ' + err); return; } console.log(result); res.send(result); }); connection.end(); }); app.listen(3000);
8.Web Socket和Socket.IO框架 8.1. HTTP的问题 HTTP无法轻松实现 实时应用:
HTTP协议是无状态的,服务器只会响应来自客户端的请求,但是它与客户端之间不具备持续连接。(无法长时持续连接)
我们可以捕获浏览器上发生的事件(比如用户点击了button),这个事件可以产生与服务器的数据交互(比如Ajax)。 但是,反过来却是不可能的:服务器端发生了一个事件,服务器无法将这个事件的信息实时主动通知它的客户端。只有在客户端查询服务器的当前状态的时候,所发生事件的信息才会从服务器传递到客户端。(无法主动输出信息)
但是,HTTP协议也能做聊天室这种’长连接’的东西,它是这么实现的:
长轮询:客户端每隔很短的时间,都会对服务器发出请求,查看是否有新的消息,只要轮询速度足够快,例如1秒,就能给人造成交互是实时进行的印象。这种做法是无奈之举,实际上对服务器、客户端双方都造成了大量的性能浪费。
长连接:客户端只请求一次,但是服务器会将连接保持,不会返回结果(想象一下我们没有写res.end()时,浏览器的小菊花会一直转)。服务器有了新数据,就将数据发回来,又有了新数据,就将数据发回来,而一直保持挂起状态。这种做法的也造成了大量的性能浪费。
8.2. WebSocket WebSocket协议能够让浏览器和服务器全双工实时通信,互相的,服务器也能主动通知客户端了。
WebSocket的原理非常的简单:利用HTTP请求产生握手,HTTP头部中含有WebSocket协议的请求,所以握手之后,二者转用TCP协议进行交流(QQ的协议)。现在的浏览器和服务器之间,就是QQ和QQ服务器的关系了。 所以WebSocket协议,需要浏览器支持,更需要服务器支持。
支持WebSocket协议的浏览器有:Chrome 4、火狐4、IE10、Safari5
支持WebSocket协议的服务器有:Node、Apache Tomcat/7.0.27、Nginx1.3
8.3. Socket.IO 用原生Node搭建 WebSocket协议的服务 非常麻烦,我们使用写好的模块: Socket.IO 它屏蔽了所有底层细节,让顶层调用非常简单。 并且还为不支持WebSocket协议的浏览器(IE),提供了长轮询的透明模拟机制。 Node的单线程、非阻塞I/O、事件驱动机制,使它非常适合Socket服务器。
官网:http://socket.io/
chat_demo 初始化: 1 npm init | 聊天室 | index.js
安装的组件: 1 2 3 npm install express --save npm install ejs --save npm install socket.io --save
说明: 1 2 Express与Socket.IO Express框架可以和Socket.IO搭配使用,但是不能像通常的Express程序那样,用app.listen进行监听了,而是采用一种固定的模式.
官方 画板 示例:https://socket-io-whiteboard.now.sh/ 官方 聊天室 示例:https://socket-io-chat.now.sh/ 官方socket.io 仓库:https://github.com/socketio