标签:ring 其他 说明 obj 令行 dir redirect 检测 html
Express 是一个属于 Node 平台的 Web 应用开发框架,它提供了一系列的强大特性,帮助你创建各种 Web 应用。
我们可以使用 npm install express 命令进行下载安装。
●提供了方便简洁的路由定义方式
●对获取 HTTP 请求参数进行了简化处理
●对模板引擎支持程序高,方便渲染动态 HTML 页面
●提供了中间件机制,有效控制 HTTP 请求
●拥有大量第三方中间件对功能进行扩展
原始 node.js 代码:
app.on(‘request‘, (req, res) => { // 获取客户端的请求路径 let { pathname } = url.parse(req.url); // 对请求路径进行判断 不同的路径地址响应不同的内容 if (pathname == ‘/‘ || pathname == ‘/index‘) { res.end(‘欢迎来到首页‘); } else if (pathname == ‘/list‘) { res.end(‘欢迎来到列表页‘); } else if (pathname == ‘/about‘) { res.end(‘欢迎来到关于我们页‘); } else { res.end(‘抱歉,您访问的页面出错了‘); } });
express 框架代码:
// 当客户端以 get 方式访问 / 时 app.get(‘/‘, (req, res) => { // 对客户端做出响应 res.send(‘Hello Express‘); }); // 当客户端以 post 方式访问 /add 路由时 app.get(‘/add‘, (req, res) => { // 对客户端做出响应 res.send(‘使用 post 方式请求了 /add 路由‘); });
例子:
新建 framework 项目文件夹,并切换到命令行工具,输入:npm install express 下载安装框架。
新建 01.js 文件:
// 引入 express 框架 const express = require(‘express‘); // 创建网站服务器 const app = express(); app.get(‘/‘, (req, res) => { // send() 向客户端响应 // 1、send() 内部会检测响应内容的类型 // 2、send() 会自动设置 http 状态码 // 3、send() 会帮我们自动设置响应的内容类型及编码 res.send(‘hello express‘); }) // 监听端口 app.listen(3000); console.log(‘网站服务器启动成功‘);
切换到命令行工具,输入:
node 01.js
打开浏览器,输入:http://localhost:3000/ 可以看到:
在增加一个 /list:
// 引入 express 框架 const express = require(‘express‘); // 创建网站服务器 const app = express(); app.get(‘/‘, (req, res) => { // 1、send() 内部会检测响应内容的类型 // 2、send() 会自动设置 http 状态码 // 3、send() 会帮我们自动设置响应的内容类型及编码 res.send(‘hello express‘); }) app.get(‘/list‘, (req, res) => { res.send({name: ‘张三‘, age: 20}); }) // 监听端口 app.listen(3000); console.log(‘网站服务器启动成功‘);
重新运行:node 01.js
刷新页面可以看到:
中间件就是一堆方法,可以接收客户端发来的请求,可以对请求做出响应,也可以将请求继续交给下一个中间件继续处理。
中间件方法由 Express 提供,负责拦截请求,请求处理函数由开发人员提供,负责处理请求。
app.get(‘请求路径‘, ‘处理函数‘) // 接收并处理get请求 app.post(‘请求路径‘, ‘处理函数‘) // 接收并处理post请求
可以针对同一个请求设置多个中间件,对同一个请求进行多次处理。
app.get(‘/request‘, (req, res, next) => { req.name = ‘张三‘;
next() }) app.get(‘/request‘, (req, res) => { res.send(req.name); })
可以调用 next 方法将请求的控制权交给下一个中间件,直到遇到结束请求的中间件。
例子:新建 02.js 文件:
// 引入 express 框架 const express = require(‘express‘); // 创建网站服务器 const app = express(); app.get(‘/request‘, (req, res, next) => { req.name = ‘张三‘; next(); }); app.get(‘/request‘, (req, res) => { res.send(req.name); }); // 监听端口 app.listen(3000); console.log(‘网站服务器启动成功‘);
在命令行工具中输入:nodemon 02.js
回到浏览器输入:http://localhost:3000/request ,可以看到:
app.use 匹配所有的请求方式,可以直接传入请求处理函数,代表接收所有的请求。
app.use((req, res, next) => {
console.log(req.url);
next();
});
app.use 第一个参数也可以传入请求地址,代表不论什么请求方式,只要是这个请求地址就接收这个秦秋。
app.use(‘/admn‘, (req, res, next) => {
console.log(req.url);
next();
});
例子:新建 03.js 文件:
// 引入 express 框架 const express = require(‘express‘); // 创建网站服务器 const app = express(); // 接收所有请求的中间件 app.use((req, res, next) => { console.log(‘请求走了 app.use 中间件‘) next() }) // 当客户端访问 /request 请求的时候,才走当前的中间件 app.use(‘/request‘, (req, res, next) => { console.log(‘请求走了 app.use /request 中间件‘) next() }) app.get(‘/list‘, (req, res) => { res.send(‘/list‘); }) app.get(‘/request‘, (req, res, next) => { req.name = ‘张三‘; next(); }); app.get(‘/request‘, (req, res) => { res.send(req.name); }); // 监听端口 app.listen(3000); console.log(‘网站服务器启动成功‘);
在命令行工具输入:nodemon 03.js
在浏览器中输入:http://localhost:3000/request
在浏览器中输入:http://localhost:3000/list
1、路由保护,客户端在访问需要登录的页面时,可以先使用中间件判断用户登录状态,用户如果未登录,则拦截请求,直接响应,禁止用户进入需要登录的页面。
例子:新建 04.js 文件:
// 引入 express 框架 const express = require(‘express‘); // 创建网站服务器 const app = express(); app.use(‘/admin‘, (req, res, next) => { // 用户没有登录 let isLogin = false; // 如果用户登录 if (isLogin) { // 让请求继续向下执行 next() } else { // 如果用户没有登录,直接第客户端做出响应 res.send(‘您还没有登录,不能访问当前页面‘); } }) app.get(‘/admin‘, (req, res) => { res.send(‘您已经登录,可以访问当前页面‘); }) // 监听端口 app.listen(3000); console.log(‘网站服务器启动成功‘);
在命令行工具中输人:nodemon 04.js
在浏览器中输入:http://localhost:3000/admin ,可以看到:
把 isLogin 改为: let isLogin = true;,在重新刷新页面,可以看到:
2、网站维护公告,在所有路由的最上面定义接收所有请求的中间件,直接为客户端做出响应,网站正在维护中。
例子:继续编辑 04.js 文件:
// 引入 express 框架 const express = require(‘express‘); // 创建网站服务器 const app = express(); // 网站维护公告 app.use((req, res, next) => { res.send(‘当前网站正在维护中...‘); }) app.use(‘/admin‘, (req, res, next) => { // 用户没有登录 let isLogin = true; // 如果用户登录 if (isLogin) { // 让请求继续向下执行 next() } else { // 如果用户没有登录,直接第客户端做出响应 res.send(‘您还没有登录,不能访问当前页面‘); } }) app.get(‘/admin‘, (req, res) => { res.send(‘您已经登录,可以访问当前页面‘); }) // 监听端口 app.listen(3000); console.log(‘网站服务器启动成功‘);
回到浏览器中,随便输入那个请求地址,页面都显示:
3、自定义 404 页面
中间是有顺序的,如果从上到下都没有匹配成功,那么就说明用户访问的这个请求路径是不存在的。
例子:继续编辑 04.js 文件:
// 引入 express 框架 const express = require(‘express‘); // 创建网站服务器 const app = express(); // 网站维护公告 // app.use((req, res, next) => { // res.send(‘当前网站正在维护中...‘); // }) app.use(‘/admin‘, (req, res, next) => { // 用户没有登录 let isLogin = true; // 如果用户登录 if (isLogin) { // 让请求继续向下执行 next() } else { // 如果用户没有登录,直接第客户端做出响应 res.send(‘您还没有登录,不能访问当前页面‘); } }) app.get(‘/admin‘, (req, res) => { res.send(‘您已经登录,可以访问当前页面‘); }) app.use((req, res, next) => { res.send(‘当前访问的页面不存在‘); }) // 监听端口 app.listen(3000); console.log(‘网站服务器启动成功‘);
在浏览器中输入:http://localhost:3000/add 可以看到:
不过在 network 里看到的状态码是 304
要想显示为 404 的话,需要修改代码:
app.use((req, res, next) => { // 为客户端响应 404 状态码以及提示信息 // res.status(404) res.status(404).send(‘当前访问的页面不存在‘); })
刷新页面后可以看到:
在程序执行的过程中,不可避免的会出现一些无法预料的错误。比如文件读取失败,数据库连接失败等。
错误处理中间件是一个集中处理错误的地方。
代码示例:
app.use((err, req, res, next) => { res.status(500).send(‘服务器发生未知错误‘); })
例子:新建 05.js 文件:
// 引入 express 框架 const express = require(‘express‘); // 创建网站服务器 const app = express(); app.get(‘/index‘, (req, res) => { throw new Error(‘程序发生了未知错误‘) }) // 错误处理中间件 app.use((err, req, res, next) => { res.status(500).send(err.message); }) // 监听端口 app.listen(3000); console.log(‘网站服务器启动成功‘);
在命令行工具中输入:nodemon 05.js
在浏览器中输入:http://localhost:3000/index ,可以看到:
注意:错误处理中间件只能捕捉到同步代码执行出错。如果异步代码执行出错,需要手动去触发这个错误中间件。
当程序出现错误时,调用 next() 方法,并且将错误信息通过参数的形式传递给 next() 方法,即可触发错误处理中间件。
示例代码:
app.get(‘/‘, (req, res, next) => { fs.readFile(‘./file-dose-exist‘, (err, data) => { if (err) { next(err); } }) })
例子:修改 05.js 文件:
// 引入 express 框架 const express = require(‘express‘); // 创建网站服务器 const app = express(); const fs = require(‘fs‘); app.get(‘/index‘, (req, res, next) => { // throw new Error(‘程序发生了未知错误‘) // res.send(‘程序正常执行‘) fs.readFile(‘./demo.txt‘, ‘utf8‘ ,(err, result) => { if (err != null) { next(err) } else { res.end(result) } }) }) // 错误处理中间件 app.use((err, req, res, next) => { res.status(500).send(err.message); }) // 监听端口 app.listen(3000); console.log(‘网站服务器启动成功‘);
在浏览器中刷新页面,可以看到:没有找到文件
如果修改为当前目录下有的文件:
fs.readFile(‘./01.js‘, ‘utf8‘ ,(err, result) => {
刷新浏览器,可以看到:
在 node.js 中,异步 API 的错误信息都是通过回调函数获取的,支持 Promise 对象的异步 API 发生错误可以通过 catch() 方法捕获。
异步函数执行如果发生错误要如何捕获错误呢?
try catch 可以捕获异步函数以及其他同步代码在执行过程中发生的错误,但是不能捕获其他类型的 API 发生的错误。
语法:
app.get(‘/‘, (req, res, netx) => { try { await User.find({name: ‘张三‘}); } catch (ex) { next(ex); } });
例子:新建 06.js 文件:
// 引入 express 框架 const express = require(‘express‘); // 创建网站服务器 const app = express(); const fs = require(‘fs‘); const promisify = require(‘util‘).promisify; const readFile = promisify(fs.readFile); app.get(‘/index‘, async (req, res, next) => { try { await readFile(‘./aaa.js‘) } catch (ex) { next(ex); } }) // 错误处理中间件 app.use((err, req, res, next) => { res.status(500).send(err.message); }) // 监听端口 app.listen(3000); console.log(‘网站服务器启动成功‘);
刷新浏览器,可以看到:
基础代码:
const express = require(‘express‘); // 创建路由对象 const home = express.Router(); // 将路由和请求路径进行匹配 app.use(‘/home‘, home); // 在 home 路由下继续创建路由 home.get(‘/index‘, (req, res) => { // /home/index res.send(‘欢迎来到博客展示页面‘); });
例子:新建 07.js 文件:
// 引入 express 框架 const express = require(‘express‘); // 创建网站服务器 const app = express(); // 创建路由对象 const home = express.Router(); // 为路由对象匹配请求路径 app.use(‘/home‘, home); // 创建二级路由 home.get(‘/index‘, (req, res) => { res.send(‘欢迎来到博客展示页面‘); }) // 监听端口 app.listen(3000); console.log(‘网站服务器启动成功‘);
在命令行工具中输入:nodemon 07.js
在浏览器中输入:http://localhost:3000/home/index ,可以看到:
构建模块化路由代码:
// home const home = express.Router(); home.get(‘/index‘, () => { res.send(‘欢迎来到博客展示页面‘); }); module.exports = home; // admin const admin = express.Router(); admin.get(‘/index‘, () => { res.send(‘欢迎来到博客管理页面‘); }); module.exports = admin; // app.js const home = require(‘./route/home.js‘); const admin = require(‘./route/admin.js‘); app.use(‘/home‘, home); app.use(‘/admin‘, admin);
例子:在项目根目录下新建 route文件夹,并新建 home.js 和 admin.js 文件:
// home.js const express = require(‘express‘); const home = express.Router(); home.get(‘/index‘, (req, res) => { res.send(‘欢迎来到博客展示首页‘); }); module.exports = home; // admin.js const express = require(‘express‘); const admin = express.Router(); admin.get(‘/index‘, (req, res) => { res.send(‘欢迎来到博客管理首页‘); }); module.exports = admin;
新建 08.js 文件:
// 引入 express 框架 const express = require(‘express‘); // 创建网站服务器 const app = express();
const home = require(‘./route/home‘); const admin = require(‘./route/admin‘); // 为路由对象匹配请求路径 app.use(‘/home‘, home); app.use(‘/admin‘, admin); // 监听端口 app.listen(3000); console.log(‘网站服务器启动成功‘);
在命令行工具中输入:nodemon 08.js
打开浏览器输入:http://localhost:3000/home/index 和 http://localhost:3000/admin/index ,可以看到:
Express框架中使用 req.query 即可获取 GET 参数,框架内部会将 GET 参数转换为对象并返回。
示例代码:
// 接收地址栏中问号后面的参数 // 例如: http://localhost:3000/?name=zhangsan&age=30 app.get(‘/‘, (req, res) => { console.log(req.query); // {"name": "zhangsan", "age": "30"} });
例子:新建 09.js 文件:
// 引入 express 框架 const express = require(‘express‘); // 创建网站服务器 const app = express(); app.get(‘/index‘, (req, res) => { // 获取 get 请求参数 res.send(req.query); }) // 监听端口 app.listen(3000); console.log(‘网站服务器启动成功‘);
在命令行工具中输入:nodemon 09.js
在浏览器中输入:http://localhost:3000/index?name=zhangsan&age=30 ,可以看到:
Express 中接收 post 请求参数需要借助第三方包 body-parser
下载安装:npm install body-parser
示例代码:
// 引入 body-parser 模块 const bodyParser = require(‘body-parser‘); // 配置 body-parser 模块 app.use(bodyParser.urlencoded({ extended: false })); // 接收请求 app.post(‘/add‘, (req, res) => { // 接收请求参数 console.log(req.body); });
例子:
在命令行工具输入:npm install body-parser
新建 10.js 文件:
// 引入 express 框架 const express = require(‘express‘); // 引入 body-parser 模块 const bodyParser = require(‘body-parser‘); // 创建网站服务器 const app = express(); // 拦截所有的请求 // extended: false 方法内部使用 querystring 模块处理请求参数的格式 // extended: true 方法内部使用第三方模块 qs 处理请求参数的格式 app.use(bodyParser.urlencoded({ extended: false })) app.post(‘/add‘, (req, res) =>{ // 接收 post 请求参数 res.send(req.body) }) // 监听端口 app.listen(3000); console.log(‘网站服务器启动成功‘);
在命令行工具中输入:nodemon 10.js
我们通过表单的形式来发送 post 请求,新建 post.html 文件:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <form method="POST" action="http://localhost:3000/add"> <input name="username" type="text"> <input name="password" type="password"> <button type="submit">sbmit</button> </form> </body> </html>
右键点击在浏览器中打开,然后随便输入一些信息,点击提交,可以看到:
例子:新建 11.js 文件:
// 引入 express 框架 const express = require(‘express‘); // 引入 body-parser 模块 const bodyParser = require(‘body-parser‘); // 创建网站服务器 const app = express(); app.use(fn ()) function fn() { return function (req, res, next) { console.log(req.method) next() } } app.get(‘/‘, (req, res) => { res.send(‘ok‘); }) // 监听端口 app.listen(3000); console.log(‘网站服务器启动成功‘);
在命令行工具中输入:nodemon 11.js
在浏览器中输入:http://localhost:3000/ ,可以看到:
这就证明了返回的函数 fn 被调用了。
这样做的好处是:我们在调用 fn 函数的同时,向 fn 函数内部传递一些额外的参数;在请求处理函数内部,可以根据这个参数改变请求处理函数的行为。
修改 11.js 文件代码:
// 引入 express 框架 const express = require(‘express‘); // 引入 body-parser 模块 const bodyParser = require(‘body-parser‘); // 创建网站服务器 const app = express(); app.use(fn ({a: 1})) function fn(obj) { return function (req, res, next) { if ( obj.a == 1) { console.log(req.url) } else { console.log(req.method) } next() } } app.get(‘/‘, (req, res) => { res.send(‘ok‘); }) // 监听端口 app.listen(3000); console.log(‘网站服务器启动成功‘);
刷新浏览器,可以看到命令行工具中的:请求地址
如果把 app.use(fn ({a: 1})) 改为 app.use(fn ({a: 2}))
刷新浏览器,可以看到:请求方法
示例代码:
app.get(‘/find/:id‘, (req, res) => { console.log(req.params); // {id: 123} });
// 浏览器中打开 localhost:3000/find/123
例子:新建 12.js 文件:
// 引入 express 框架 const express = require(‘express‘); // 引入 body-parser 模块 const bodyParser = require(‘body-parser‘); // 创建网站服务器 const app = express(); app.get(‘/index/:id‘, (req, res) => { res.send(req.params) }) // 监听端口 app.listen(3000); console.log(‘网站服务器启动成功‘);
在命令行工具中输入:nodemon 12.js
在浏览器中输入:http://localhost:3000/index/123 ,可以看到:
如果是多个参数的话:
app.get(‘/index/:id/:name/:age‘, (req, res) => {
res.send(req.params)
})
在浏览器中输入:http://localhost:3000/index/123/zhangsan/20
通过 Express 内置的 express.static 可以方便的托管静态文件,例如 img、css、js 文件等。
app.use(express.static(‘public‘));
现在 public 目录下面的文件就可以访问了。
例子:新建 13.js 文件:
// 引入 express 框架 const express = require(‘express‘); const path = require(‘path‘); // 创建网站服务器 const app = express(); app.use(express.static(path.join(__dirname, ‘public‘))); // 监听端口 app.listen(3000); console.log(‘网站服务器启动成功‘);
在命令行工具输入:nodemon 13.js
在浏览器中可以输入相应的地址,访问静态资源。比如:
http://localhost:3000/images/1.jpg
http://localhost:3000/css/base.css
http://localhost:3000/default.html
为了使 art-template 模板引擎能够更好的和 Express 框架配合,模板引擎官方在原 art-template 模板引擎的基础上封装了 express-art-template。
同时安装这两个,使用 npm install art-template express-art-template 命令进行安装。
语法:
// 当渲染后缀为 art 的模板时,使用 express-art-template app.engine(‘art‘, require(‘express-art-template‘)); // 设置模板存放目录 app.set(‘views‘, path.join(__dirname, ‘views‘)); // 渲染模板时不写后缀,默认拼接 art 后缀 app.set(‘view engine‘, ‘art‘); app.get(‘/‘, (req, res) => { // 渲染模板 res.render(‘index‘); })
例子:
在命令行工具中下载安装:
npm install art-template express-art-template
新建 14.js 文件:
// 引入 express 框架 const express = require(‘express‘); const path = require(‘path‘); // 创建网站服务器 const app = express(); // 1、告诉 express 框架使用什么模板引擎,渲染什么后缀的模板文件 // 第1个参数是模板的后缀 // 第2个参数是使用的模板引擎 app.engine(‘art‘, require(‘express-art-template‘)); // 2、告诉 express 框架模板存放的位置是什么 app.set(‘views‘, path.join(__dirname, ‘views‘)); // 3、告诉 express 框架模板的默认后缀是什么 app.set(‘view engine‘, ‘art‘); app.get(‘/index‘, (req, res) => { // 拼接模板路径 // 拼接模板后缀、 // 那一个模板和那个数据进行拼接 // 将拼接的结果响应给客户端 res.render(‘index‘, { msg: ‘message‘ }) }) // 监听端口 app.listen(3000); console.log(‘网站服务器启动成功‘);
在项目根目录下新建 views 文件夹,创建 index.art 文件:
{{ msg }}
在命令行工具中输入:nodemon 14.js
在浏览器输入:http://localhost:3000/index ,可以看到:
修改添加如下代码:
// 引入 express 框架 const express = require(‘express‘); const path = require(‘path‘); // 创建网站服务器 const app = express(); // 1、告诉 express 框架使用什么模板引擎,渲染什么后缀的模板文件 // 第1个参数是模板的后缀 // 第2个参数是使用的模板引擎 app.engine(‘art‘, require(‘express-art-template‘)); // 2、告诉 express 框架模板存放的位置是什么 app.set(‘views‘, path.join(__dirname, ‘views‘)); // 3、告诉 express 框架模板的默认后缀是什么 app.set(‘view engine‘, ‘art‘); app.get(‘/index‘, (req, res) => { // 拼接模板路径 // 拼接模板后缀、 // 那一个模板和那个数据进行拼接 // 将拼接的结果响应给客户端 res.render(‘index‘, { msg: ‘message‘ }) }) app.get(‘/list‘, (req, res) => { res.render(‘list‘, { msg: ‘list page‘ }) }) // 监听端口 app.listen(3000); console.log(‘网站服务器启动成功‘);
在路篮球中输入:http://localhost:3000/list ,可以看到:
将变量设置到 app.locals 对象下面,这个数据在所有的模板中都可以获取到。
示例代码:
app.locals.users = [{ name: ‘张三‘, age: 20 },{ name: ‘李四‘, age: 20 }]
例子:新建 15.js 文件:
// 引入 express 框架 const express = require(‘express‘); const path = require(‘path‘); // 创建网站服务器 const app = express(); // 模板配置 app.engine(‘art‘, require(‘express-art-template‘)); app.set(‘views‘, path.join(__dirname, ‘views‘)); app.set(‘view engine‘, ‘art‘); app.locals.users = [{ name: ‘张三‘, age: 20 },{ name: ‘李四‘, age: 30 }] app.get(‘/index‘, (req, res) => { res.render(‘index‘, { msg: ‘首页‘ }) }) app.get(‘/list‘, (req, res) => { res.render(‘list‘, { msg: ‘列表页‘ }) }) // 监听端口 app.listen(3000); console.log(‘网站服务器启动成功‘);
打开 views 目录下的 index.art 和 list.art 文件,同时添加:
{{ msg }} <ul> {{each users}} <li> {{$value.name}} {{$value.age}} </li> {{/each}} </ul>
在命令行工具中输入:nodemon 15.js
在浏览器输入:http://localhost:3000/index 和 http://localhost:3000/list ,可以看到:
这就证明了 app.locals 这个对象下面的属性,我们在所有的模板中都可以拿到。所以我们可以把项目中一些公共数据,添加到 app.locals 这个对象下面。
res.redirect(‘/admin/user‘);
项目实例:博客项目
标签:ring 其他 说明 obj 令行 dir redirect 检测 html
原文地址:https://www.cnblogs.com/joe235/p/12915725.html