大纲
学习链接: Express/Node入门
Node
大纲
什么是Node
使用 JavaScript 创建各种服务器端工具和应用程序
此运行时主要用于浏览器上下文之外(即可以直接运行于计算机或服务器操作系统上)
NPM
node package manager
** 提供了数十万个可重用的工具包。它还提供了一流的依赖解决方案,可实现自动化工具链构建。**
好处
专为web应用而生,npm,js,可移植
实例
// 调用 HTTP 模块
const http = require("http");
// 创建 HTTP 服务器并监听 8000 端口的所有请求
http.createServer((request, response) => {
// 用 HTTP 状态码和内容类型来设定 HTTP 响应头
response.writeHead(200, {'Content-Type': 'text/plain'});
// 发送响应体 "Hello World"
response.end('Hello World\n');
}).listen(8000);
// 在控制台打印访问服务器的 URL
console.log('服务器运行于 http://127.0.0.1:8000/');
做了什么?
创建一个sever——>sever监听请求并发送响应
再次对应Node功能:用js创建各种服务器端工具和应用程序
Express
大纲
什么是Express
Node框架
HelloWorld Express
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(3000, () => {
console.log('示例应用正在监听 3000 端口!');
});
导入Express模块,创建一个Express应用(它可以进行路由 HTTP 请求、配置中间件、渲染 HTML 视图、注册模板引擎以及修改 应用程序设置 等操作,从而控制应用的行为(例如,环境模式,路由定义是否为区分大小写等)。)
app.get()
导入和创建模块
模块是什么?
js库或文件
怎么导入?
Node的require()
自建模块的需求
让对象暴露于模块之外
exports.area = width => { return width * width; };
exports.perimeter = width => { return 4 * width; };
导入+调用
const square = require('./square');
// 这里 require() 了文件名,省略了 .js 扩展名(可选)
console.log('边长为 4 的正方形面积为 ' + square.area(4));
相对路径,绝对路径,名字 √
导出属性,对象…
module.exports = {
area: width => { return width * width; },
perimeter: width => { return 4 * width; }
};
exports和module.exports
创建路由处理器
路由处理函数
处理http请求
app.get('/', (req, res) => {
res.send('Hello World!');
});
处理对根目录的HTTP GET请求
- 什么是回调函数 callback
- 回调函数的参数:请求,响应对象(始终是,合理命名:req,res)
- send() 等
许多响应方法
Express应用为其他所有HTTP动词定义路由处理器的方法
checkout(), copy(), delete(), get(), head(), lock(), merge(), mkactivity(), mkcol(), move(), m-search(), notify(), options(), patch(), post(), purge(), put(), report(), search(), subscribe(), trace(), unlock(), unsubscribe().
特殊:app.all( )
它可以在响应任意 HTTP 方法时调用。用于在特定路径上为所有请求方法加载中间件函数。
栗子:
app.all('/secret', (req, res, next) => {
console.log('访问私有文件 ...');
next(); // 控制权传递给下一个处理器
});
路由器!
创建路由
express.Router中间件
- 定义和使用单独的路由模块
// wiki.js - 维基路由模块
const express = require('express');
const router = express.Router();
// 主页路由
router.get('/', (req, res) => {
res.send('维基主页');
});
// “关于页面”路由
router.get('/about', (req, res) => {
res.send('关于此维基');
});
module.exports = router;
路由模块 vs 具体的路由
2. 引入路由模块
const wiki = require('./wiki.js');
// ...
app.use('/wiki', wiki);
要在主应用中使用该路由模块,首先应 require 它(wiki.js),然后对 Express 应用对象调用 use()(指定路径‘/wiki’),即可将其添加到中间件处理路径。
路由函数
Router.get()
callback有三个参数:req,res,next(中间件链中的下一个函数)
注:路由函数就是 Express 中间件,这意味着它们必须(通过响应)结束请求,否则必须调用链中的 next 函数。上述示例使用send() 完成了请求,所以没有使用 next 参数(参数表中将其省略)。
上述路由函数只需要一个回调,可以根据需要指定任意数量的回调参数,或一个回调函数数组。每个函数都将加入中间件链,并且将按添加顺序调用(若有回调完成请求则中止当前周期)。
路由路径
定义可请求的端点
精准的字符串&字符串模式(String Pattern)&javascript正则表达式
可用部分正则表达式语法来定义端点的模式
- ?:问号之前的一个字符只能出现零次或一次。例如,路由路径 ‘/ab?cd’ 路径匹配端点 acd 或 abcd。
- +:加号之前的一个字符至少出现一次。例如,路径路径 ‘/ab+cd’ 匹配端点 abcd、abbcd、abbbcd,等。
- :星号可以替换为任意字符串。例如,路由路径 ‘ab*cd’ 匹配端点 abcd、abXcd、abSOMErandomTEXTcd,等。
- ():将一个字符串视为一体以执行 ?、+、* 操作。例如。 ‘/ab(cd)?e’ 将对 (cd) 进行匹配,将匹配到 abe 和 abcde。
注意:连字符( -)和点(.)在字符串路径中解释为字面量,不能做为正则表达式
注意: 正则表达式路径不再用引号 “…” 括起来,而是正则表达式语法 /…/。
路由参数
路径参数是命名的 URL 段,用于捕获在 URL 中的位置指定的值。命名段以冒号为前缀,然后是名称(例如 /:your_parameter_name/。捕获的值保存在 req.params 对象中,键即参数名(例如 req.params.your_parameter_name)。
总结
路由器可以匹配 URL 中特定的字符串模式,并从 URL 中提取一些值作为参数传递给路由处理程序(作为请求对象的属性)。
可以为站点的特定部分提供一组路由处理器(使用公共路由前缀进行组合)。(比如对于一个有 维基(Wiki)内容的站点,可以把所有 Wiki 相关的路由放在同一个文件里,使用路由前缀 ‘/wiki/’ 访问它们)。
使用中间件
中间件在 Express 应用中得到了广泛使用,从提供错误处理静态文件、到压缩 HTTP 响应等等。路由函数可以通过向 HTTP 客户端返回一些响应来结束 HTTP “请求 - 响应”周期,而中间件函数通常是对请求或响应执行某些操作,然后调用“栈”里的下一个函数,可能是其它中间件或路由处理器。中间件的调用顺序由应用开发者决定
注:中间件可以执行任何操作,运行任何代码,更改请求和响应对象,也可以结束“请求 - 响应”周期。如果它没有结束循环,则必须调用 next() 将控制传递给下一个中间件函数(否则请求将成为悬挂请求)。
使用第三方中间件来简化常见的web开发任务
- 用npm下载
- Express应用对象调用use(middleware)将该中间件添加到栈
注意:中间件和路由函数是按声明顺序调用的。一些中间件的引入顺序很重要(例如,如果会话中间件依赖于 cookie 中间件,则必须先添加 cookie 处理器)。绝大多数情况下要先调用中间件后设置路由,否则路由处理器将无法访问中间件的功能。
中间件函数 vs 路由处理回调
唯一区别:中间件函数3个参数 req res ,next(在中间件不会结束请求周期时应调用这个 next(它包含中间件函数调用后应调用的下一个函数)
如何添加中间件
const express = require('express');
const app = express();
// 示例中间件函数
const a_middleware_function = (req, res, next) => {
// ... 进行一些操作
next(); // 调用 next() ,Express 将调用处理链中下一个中间件函数。
};
// 用 use() 为所有的路由和动词添加该函数
app.use(a_middleware_function);
// 用 use() 为一个特定的路由添加该函数
app.use('/someroute', a_middleware_function);
// 为一个特定的 HTTP 动词和路由添加该函数
app.get('/', a_middleware_function);
app.listen(3000);