当前位置:   article > 正文

nodejs——express_express项目怎么启动

express项目怎么启动

express

基于 nodejs 平台,快速、开放、极简的 Web 开发框架。

快速搭建

官方有脚手架程序express-generator,可以快速搭建express的程序。

如果需要安装,建议全局安装:

npm install express-generator -g

使用express-generator搭建:

  1. express -h
  2. -h, --help 输出使用方法
  3. --version 输出版本号
  4. -e, --ejs 添加对 ejs 模板引擎的支持
  5. --hbs 添加对 handlebars 模板引擎的支持
  6. --pug 添加对 pug 模板引擎的支持
  7. -H, --hogan 添加对 hogan.js 模板引擎的支持
  8. --no-view 创建不带视图引擎的项目
  9. -v, --view <engine> 添加对视图引擎(view) <engine> 的支持 (ejs|hbs|hjs|jade|pug|twig|vash) (默认是 jade 模板引擎)
  10. -c, --css <engine> 添加样式表引擎 <engine> 的支持 (less|stylus|compass|sass) (默认是普通的 css 文件)
  11. --git 添加 .gitignore
  12. -f, --force 强制在非空目录下创建

搭建没有模板的项目:

express <项目名称> --no-view 

自动创建目录和基本文件,但是不包含依赖包。

安装依赖包:

npm install

执行:

  1. npm run start
  2. node ./bin/www

项目的开发启动及部署

nodemon是一个适用于开发阶段的辅助工具,它能够自动检测文件(js、json)变化,自动重启项目。

安装

npm install nodemon -g

使用,只要用nodemon替代node就可以。

例如,启动express项目:

  1. 使用,只要用nodemon替代node就可以。
  2. 例如,启动express项目:

pm2是重量级的辅助工具,除了具有nodemon的特性之外,还具有自动多线程、负载均衡、日志等等.......

安装:

npm install pm2 -g

启动项目:

pm2 start ./bin/www

查看所有管理中的项目列表:

pm2 list

操作项目:

  1. 启动一个项目
  2. pm2 start <id>
  3. 启动所有项目
  4. pm2 start all
  5. 停止一个项目
  6. pm2 stop <id>
  7. 停止所有项目
  8. pm2 stop all
  9. 重启一个项目
  10. pm2 restart <id>
  11. 重启所有项目
  12. pm2 restart all
  13. 在pm2管理器中删除某个项目
  14. pm2 delete <id>
  15. 清除所有项目
  16. pm2 delete all

启用监控:

pm2 start ./bin/www  --watch

打开实时监控画面:

pm2 monit

自建express项目

创建项目目录,并执行初始化命令:

npm init -y

建立主文件(index.js);

安装express到项目中:

npm install express

在index.js中引入express;

const express = require('express');

创建一个express实例:

const app = express();

创建第一个接口(api):

  1. app.get('/', function (req, res, next) {
  2.  res.send('你好世界!!!');
  3. })

当用户访问网站根目录时,返回字符串。

最终启动服务器:

  1. const port = 80;
  2. app.listen(port, function () {
  3.  console.log('服务器启动,监听在' + port + '端口')
  4. })

指定静态路径(网站根):

  1. app.use(
  2.  express.static('./public')
  3. )

要注意顺序问题,一般情况下,静态路径的指定要在路由之前:

  1. app.use(
  2. express.static('./public')
  3. )
  4. app.get('/index.html', function (req, res, next) {
  5. res.send('你好!!!');
  6. })

中间件

中间键是指,匹配到路径后要做事情的函数:

  1. app.use('/admin',function(req.res,next){
  2.    next();
  3. })

app.use(路径,回调函数);

路径省略或为'*',表示匹配任何路径。

  1. app.use(function(req.res,next){
  2.    next();
  3. })
  4. app.use('*',function(req.res,next){
  5.    next();
  6. })

回调函数中next表示继续向下匹配。

中间件用app调用,全局中间键,还可以在路由中使用,路由中间键

路由:

建立路由对象

const router = express.Router();

让express实例使用路由:

app.use('/users', router);

当用户请求地址是已/users开头的,则被router对象接收。

为router设置处理api:

  1. router.get('/abc',function(req,res){
  2.    res.send('135');
  3. })

表示当用户访问 http://127.0.0.1/users/abc ,向用户返回135。

通常,我们使用模块化的方式将不同的路由分别建立:

  1. //在routers文件夹下建立indexRouter.js文件
  2. const express = require('express');
  3. const router = express.Router();
  4. router.get('/abc', function (req, res) {
  5.  res.send('135')
  6. })
  7. ​module.exports = router;
我们在主文件中,引入并使用:
  1. const indexRouter = require('./routers/indexRouter');
  2. app.use('/users', indexRouter);

实际访问地址是:http://127.0.0.1/users/abc

路由的模糊匹配

正则匹配:

'ab?cd' ?匹配前面的字符{0,1}   ?前出现的字符0-1次

'ab+cd' + 匹配前面的字符{1,}   + 前面的字符最少一次

'ab*cd' * 不表示量词,ab和cd中间至少有一个字符,最多不限,字符可以是任意字符。

‘ab(cd)?e’ 小括号表示整体计算,小括号不能出现在开头。

可以直接使用正则表达式来匹配:

router.get(/abc$/,function(req,res){});

动态路由匹配:

  1. router.get('/class/:classid/news/:newsid', function (req, res, next) {
  2. res.send(`classid:${req.params.classid} , newsid:${req.params.newsid}`)
  3. });

res常用方法:

res.send()  通用方法,会根据参数类型自动设置返回头。

res.download() 参数是url,向客户端返回需要下载的文件。

res.end() 用来告诉客户端,当前访问已经结束。

res.json() 向客户端返回json类型的数据。

res.jsonp()向客户端以jsonp形式发送数据

res.redirect() 重定向

res.sendFile() 发送文件到浏览器(浏览器会解析)

res.sendStatus() 发送状态码

postman

postman是一个专用于测试服务器api接口的程序。

Postmanhttps://www.postman.com/

参数的获取:

动态路由传参:

  1. //访问地址是http://127.0.0.1/api/1/2/3
  2. router.get('/api/:a/:b/:c',function(req,res){
  3. const {a,b,c} = req.params;
  4. })

请求头传参:

url ?a=1&b=2

  1. //请求的地址是http://127.0.0.1/api?a=1&b=2&c=3
  2. router.get('/api',function(req,res){
  3. const {a,b,c} = req.query;
  4. })

请求体传参:

  1. //请求的地址是http://127.0.0.1/api/123?x=1&y=2
  2. router.get('/api/:p',function(req,res){
  3. const {p} = req.params
  4. const {x,y} = req.query;
  5. const {a,b,c} = req.body;
  6. })

插件

crypto

crypto用来做加密的操作,可以使用md5、sha1等等很多方式进行加密

安装

npm install crypto

项目用,安装到项目(不安装到全局)。

使用:

  1. const crypto = require('crypto');
  2. //每个实例只能输出一次;
  3. const jiami = crypto.createHash('sha1');
  4. jiami.update('123123');
  5. //输出16进制的密文
  6. jiami.digest('hex')

multer

处理formData数据(multipart/form-data),用于上传文件。

安装

npm install multer

使用时,先注册:

const multer = require('multer');

生成实例并配置:

Multer 接受一个 options 对象,其中最基本的是 dest 属性,这将告诉 Multer 将上传文件保存在哪。如果你省略 options 对象,这些文件将保存在内存中,永远不会写入磁盘。

  1. const upload = multer({
  2.  dest: 'upload/'
  3. })
  4. router.post('/upload', upload.single('file'), function (req, res) {
  5.  res.json(req.file)
  6. })

multer不会自动生成目录,需要我们手动创建。

如果你想在上传时进行更多的控制,你可以使用 storage 选项替代 dest。Multer 具有 DiskStorage 和 MemoryStorage 两个存储引擎; 另外还可以从第三方获得更多可用的引擎。

  1. const storage = multer.diskStorage({
  2.  destination: function (req, file, cb) {
  3.    cb(null, '/tmp/my-uploads')
  4. },
  5.  filename: function (req, file, cb) {
  6.    cb(null, file.fieldname + '-' + Date.now())
  7. }
  8. })
  9. const upload = multer({ storage: storage })

destination:表示文件上传的目录,它可以是一个字符串(目录会自动创建)或函数(目录不会自动创建)。

filename:表示修改后的文件名,需要完整的文件名。

可以限制文件尺寸:

  1. const upload = multer({
  2.    storage: storage,
  3.    limits: { fileSize: maxSize }
  4. })

maxSize为字节单位。

如果上传的为多文件:

  1. app.post('/upload', upload.array('files', 12), function (req, res, next) {
  2.  // req.files 是 `files` 文件数组的信息
  3.  // req.body 将具有文本域数据,如果存在的话
  4. })

如果上传的表单元素不止一个,可以使用:

  1. const cpUpload = upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'gallery', maxCount: 8 }])
  2. app.post('/upload', cpUpload, function (req, res, next) {
  3.  // req.files 是一个对象 (String -> Array) 键是文件名,值是文件数组
  4.  //
  5.  // 例如:
  6.  // req.files['avatar'][0] -> File
  7.  // req.files['gallery'] -> Array
  8.  //
  9.  // req.body 将具有文本域数据,如果存在的话
  10. })

如果你需要处理一个只有文本域的表单,你应当使用 .none():

  1. app.post('/profile', upload.none(), function (req, res, next) {
  2.  // req.body 包含文本域
  3. })

jsonwebtoken和express-jwt

登录状态保持,早期使用的方法是session:

当用户第一次访问网站时,网站在内存中生成一个session空间,并返回session-id(内存地址),内存地址写入客户端的cookie中。

弊端:如果客户端关闭cookie功能则无法保持登录状态。多个服务器之间无法共享session。

jsonwebtoken用于生成JWT字符串

express-jwt用于将JWT字符串解析还原成JSON对象

安装:

npm install jsonwebtoken express-jwt

导入:

  1. const jwt = require('jsonwebtoken')
  2. const expressJWT = require('express-jwt')

定义秘钥:

const secretKey = 'hello';

在登录成功之后,调用 jwt.sign() 方法生成 JWT 字符串。并发送给客户端

const tokenStr = jwt.sign({ username: userinfo.username }, secretKey, { expiresIn: '30s' })

客户端收到后存储,在请求需要登录后才能访问的url中加入token:

xhr.setRequestHeader('Authorization','Bearer '+token);

服务器通过express-jwt组件来验证,可以全局验证(注册到全局中间键),也可以单独对一个或几个api做验证。

  1. api做验证时:

  1. const { expressjwt } = require('express-jwt');
  2. router.get(
  3.  '/abc',
  4.  expressjwt({
  5.    secret: 'key',
  6.    algorithms: ['HS256']
  7. }
  8. ),
  9.  function (req, res, next) {
  10.    res.json({
  11.      username: req.auth.username
  12.   })
  13. });
1、路由中间键:
  1. const { expressjwt } = require('express-jwt');
  2. app.use(expressjwt({
  3.   secret: 'key',//密钥
  4.   algorithms: ['HS256']//jwt的加密算法
  5. }).unless({ path: ['/users/login', /^\/images/] }))

secret:解密秘钥(与加密秘钥相同)。

express-jwt会自动将解密后的内容放入req.auth 。

如果解密失败,则会返回一个403错误。

登录:

判断是否登录成功:jsonwebtoken.sign()生成token。返回给客户端。客户端保存token。

通常,当token验证不通过时,客户端需要得到一个明确的指示,而不是一个简单的错误提示。

我们使用自定义中间键来拦截token错误,固定向客户端返回401错误。

  1. app.use(function (err, req, res, next) {
  2. if (err.name === "UnauthorizedError") {
  3. res.status(401).send("invalid token...");
  4. } else {
  5. next(err);
  6. }
  7. });

app.js的全局中间键后。

通常与全局中间键写在一起

  1. app.use(expressjwt({
  2. secret: 'key',//密钥
  3. algorithms: ['HS256']//jwt的加密算法
  4. })
  5. //排除,token验证时,排除'/users/login', '/users/reg'路由地址
  6. .unless({ path: ['/users/login', '/users/reg'] }));
  7. //拦截token错误,固定向客户端返回401错误,错误的内容可以自己定制。
  8. app.use(function (err, req, res, next) {
  9. if (err.name === "UnauthorizedError") {
  10. res.status(401).send("invalid token...");
  11. } else {
  12. next(err);
  13. }
  14. });

用户登录及登录保持

用户登录成功后,需要保持登录状态。需要在服务端及客户端都记录一些数据来表示处于已登录状态。

http协议是短链接,访问结束后,访问状态消失,下次访问服务器时,服务器会将客户端当做全新的来看待。

曾经采用的解决方案:

cookie(session)方案

session(会话),application(应用)

会话状态,当我们访问服务器时,服务器会为我们本次访问单独建立一个作用域,访问结束(关掉与服务器的所有连接)时,作用域消失。例如:当我们要访问某个网站时,第一次打开网站的任意一个网页(请求)时,产生本次访问的会话状态,当前访问不结束,再次访问时,与上次的会话状态共享。直到所有的访问全部结束,会话状态结束。

登录成功时,服务器产生一个session,每个session都有一个独立的sessionID。服务器将这个sessionID和登录状态一起存储在客户端的cookie中。当客户端再次访问服务器时,服务器会尝试读取客户端的sessionID,看看在服务器中,这个sessionID对应的session是否还存在,如果不存在了,则表示登录超时,如果还存在,进一步读取登录状态,来判断是否还处于登陆中。

这种判断过程,对于单服务器比较完美,还要看客户端是否禁用了cookie。

改进的方案:token方案

1、当用户登录成功后,服务器生成一个加密的字符串,这个字符串包含三部分内容:第一部分是存储加密头信息、第二部分存储过期时间、第三部分是存储我们需要额外存储的信息。独一无二的。服务器对应的也会存储秘钥用于解密。

2、服务器将这个token发送给客户端,客户端存储这个token。

3、当客户端需要再次访问服务器时,在参数中将这个token发送给服务器。

4、服务器判断当前请求有没有附加token信息,如果没有,那就表示没有登录,如果有,则用秘钥解密token,得到过期时间,看当前时间是否处于过期时间,处于过期时间内则表示还处于登录状态,超出过期时间则表示登录超时。

在需要登录后才能访问的api中做登录验证。

客户端在发送请求(get、post)时,需要携带token(请求头)。

服务器接收到请求时,用express-jwt去获取客户端携带的token,解密(还原)。

是否可以还原,如果可以还原再判断过期时间。都通过则将加密的数据保存在req.auth中,next();

如果任何一步出错了,则不再继续,返回401错误。

验证时:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/120289?site
推荐阅读
相关标签
  

闽ICP备14008679号