Express.js 框架是node.js后端框架之一, 相当于jQuery和js之间的关系;
Express 不对 Node.js 已有的特性进行二次抽象,我们只是在它之上扩展了 Web 应用所需的基本功能;
安装express:
- 进入应用目录
- npm init 命令为你的应用创建一个 package.json 文件
- 安装 Express 并将其保存到依赖列表中
npm install express --save - 如果只是临时安装 Express,不想将它添加到依赖列表中,只需略去 --save 参数即可
npm install express
通过应用生成器工具 express 可以快速创建一个应用的骨架。
- 安装
npm install express-generator -g - 常用操作
express -h
-h 选项可以列出所有可用的命令行选项
安装所有依赖包
npm install q - 设置视图模板
express --view=ejs demo1 - 启动应用
MacOS 或 Linux 平台
DEBUG=myapp npm start
Windows 平台
set DEBUG=myapp & npm start
在浏览器中打开 http://localhost:3000/ 网址就可以看到这个应用了
通过 Express 应用生成器创建的应用一般都有如下目录结构:
// 1. 引入
const express = require('express');
// 2. 调用 express() 方法,得到一个 app 实例接口对象
//(类似于 http.createServer 得到的 server 实例)
const app = express();
// 3. 通过 app 根据路径处理 get 和 post 请求
app.get('/', (req, res)=>{
res.write('<h1>hello</h1>');
res.end()
});
app.get('/itlike', (req, res)=>{
res.end('<h1>hello, itLike</h1>')
});
// 4. 开启监听,启动服务器
app.listen(3000, () => {
console.log('服务已经启动!')
});
2.中间件
概念:
- 用来处理 http 请求的一个具体的环节(可能要执行某个具体的处理函数)
- 中间件一般都是通过修改 req 或者 res 对象来为后续的处理提供便利的使用
- 任何请求进来都会执行对应的处理函数
- 不关心当前请求的具体请求方法和请求路径
中间件分类:
- use(‘请求路径’, (req, res, next)=>{})
- get(‘请求路径’, (req, res, next)=>{})
- post(‘请求路径’, function (req, res, next) {})
实操:
let express = require('express');
let app = express();
//此时不会进入到下一步骤 因为没有书写next
/*app.use((req,res,next)=>{
console.log(123);
});*/
//此时会进入到下一步骤 因为书写了next
app.use((req,res,next)=>{
console.log(123);
next()
});
//此时访问localhost:3000会打印123,如果访问localhost:3000/1会打印123和111
//说明不写第一个路径时会匹配全局
app.use('/1',(req,res,next)=>{
console.log(111);
next()
});
//中间件会根据不同的地址进入到不同的区域
app.get('/',(req,res)=>{
res.write('<h1>Hello World!</h1>')
res.end();
});
//如果此时含有end将不会进行到下一步 helloworld3333不会打印
/*
app.get('/1',(req,res)=>{
res.write('<h1>Hello World!111</h1>')
res.end();
});
*/
//如果将end修改为next将会继续执行下去
app.get('/1',(req,res,next)=>{
res.write('<h1>Hello World!111</h1>')
next();
});
app.get('/1',(req,res)=>{
res.write('<h1>Hello World!3333</h1>')
res.end();
});
app.listen(3000);
//总结:中间件只要匹配到了都会进入 ,如果添加end就会结束下去,如果添加next就会进入下一步,如果每添加就会卡死在那里
3.静态资源访问
- app.use(’/public’, express.static(‘开放目录的路径’))
- 在 use 方法中,如果指定了第一个路径参数,则通过 req.path 获取到的是不包含该请求路径的字符串,例如当前请求路径是 /public/test.jpg, 则通过 req.path 拿到的就是 test.jpg
- 1,2不推荐 官方使用的是:app.use(express.static(‘开放目录的路径’))
使用
app.use(’/static’, express.static(path.join(__dirname, ‘static’))) 或 app.use(express.static(path.join(__dirname, ‘static’)))
const express = require('express');
const path = require('path');
const app = express();
//读取本地静态资源写法(不添加前面参数代表默认地址为/:http://localhost:3000 添加后为:访问http://localhost:3000/1233时为访问01/public/zhongyi.index)
app.use('/1233',express.static(path.join(__dirname,'01/public/zhongyi')));
app.use((req,res,next)=>{
console.log(path.join(__dirname, '01/public/zhongyi'));
res.end()
});
//如果是404的话..显示404图片
/*app.use((req,res,next)=>{
console.log(path.join(__dirname, '01/public/zhongyi'));
fs.readFile('./01/public/zhongyi/images/bg_03.png',(err,data)=>{
if(!err){
res.end(data)
}
})
});*/
app.listen(3000,()=>{
console.log('成功');
});
4.使用模板引擎
1.简单使用(实际案例中应该不会出现):
const express = require('express');
const path = require('path');
const app = express();
const fs = require('fs');
//直接写入
/*app.set("views",path.join(__dirname,'views'));
app.set('view engine','ejs');
app.get('/',(req,res,next)=>{
res.render('test',{'lists':['张三','2',3,4,5]})
});
app.listen(3000);*/
2.读取外部文件(实际案例中使用):
//读取外部文件
app.set('views',path.join(__dirname,'views'));
app.set('view engine', 'ejs');
//读取外部文件数据
app.get('/',(req,res,next)=>{
getDataJson((data)=>{
res.render('list',data)
})
});
//读取外部资源data函数
const getDataJson = (callBack)=>{
fs.readFile('./model/data.json',(err,data)=>{
if(!err){
callBack(JSON.parse(data))
}else {
throw err;
}
})
};
app.listen(3000);
5.错误处理
const express = require('express');
const fs = require('fs');
const app = express();
app.get('/', (req, res, next)=>{
try {
const data = JSON.parse('{name:');
res.json(data);
}catch (e) {
next(e);
}
});
app.get('/b', (req, res, next)=>{
fs.readFile('./cswfwefd', (err, data)=>{
if(err){
next(err);
}
})
});
app.get('/a', (req, res, next)=>{
res.end('hello');
});
/*
统一处理各种错误, 记入日志
*/
app.use((err, req, res, next)=>{
const error_log = `
=====================================
错误名: ${err.name},\n
错误消息: ${err.message}, \n
错误时间: ${new Date()}, \n
错误堆栈: ${err.stack}
=====================================
\n
`;
fs.appendFile('./err_log.txt', error_log, err =>{
res.writeHead(500, {"Content-Type": "text/html;charset=utf-8"});
res.end('500 服务器内部错误')
});
});
// 404
app.use((req, res, next)=>{
res.writeHead(404, {"Content-Type": "text/html;charset=utf-8"});
res.end('您当前访问的页面不存在!!!!');
});
app.listen(3000, ()=>{
console.log('running.....') ;
});