ToB企服应用市场:ToB评测及商务社交产业平台

标题: expres搭建一个基本的web网站服务器详细步调 [打印本页]

作者: 农妇山泉一亩田    时间: 2025-2-21 09:49
标题: expres搭建一个基本的web网站服务器详细步调
前言

express是基于Nodejs平台快速开放极简的web开发框架,它可以用来搭建web网站服务器或者api接口服务器,本文将详细列出利用express搭建一个web网站服务器的利用步调,其中包含一些搭建服务器过程中涉及到的Node.js相干的底子知识,接待各人一起来学习和讨论。

一、快速创建包管理配置文件

包管理配置文件里清楚的记录项目中安装了哪些包,此文件在开发情况中是必不可少的。准备一个文件夹存放项目文件,利用开发工具vscode打开项目文件夹,打开终端运行如下代码:
1、package.json

  1. //快速创建包管理配置文件 package.json
  2. npm init -y
复制代码
2、node_modules

node_modules文件夹中存放与项目有关的所有的包,此时运行以下命令,项目中还不会生成node_modules,而是生成了 package-lock.json,后续添加项目相干包就会主动生成node_modules了。
  1. npm install
复制代码

二、创建基本的web服务器

1、安装express

安装express命令如下:
  1. npm install
  2. express
复制代码
安装完成后,项目根目录创建app.js文件,在 package.json中修改main入口文件为 app.js。如下图所示:

2、创建服务器

app.js添加代码,创建一个基本的web服务器。
  1. // 导入express
  2. const express = require('express')
  3. // 创建web服务器
  4. const app = express()
  5. // 启动web服务器
  6. app.listen(3380,()=>{
  7.     console.log('server run at http://127.0.0.1:3380');
  8. })
复制代码
3、启动服务器

打开终端运行启动服务器,命令如下:
  1. node ./app.js
复制代码

三、托管静态资源

1、调用express.static()

1.项目根目录下新建public文件夹,public文件夹下新建css(存放css相干样式文件)、images(存放图片相干)、js(存放js代码相干)文件夹 和index.html(用于启动服务器展示页)文件。
  1. //index.html
  2. <!DOCTYPE html>
  3. <html lang="en">
  4. <head>
  5.     <meta charset="UTF-8">
  6.     <meta http-equiv="X-UA-Compatible" content="IE=edge">
  7.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  8.     <title>web服务器</title>
  9. </head>
  10. <body>
  11.     <div>welcome to access web service...</div>
  12. </body>
  13. </html>
复制代码
2.app.js中调用express.static()托管静态资源
  1. // 托管静态资源
  2. app.use(express.static('./public'))
复制代码
3.项目有改动,重启服务器node ./app.js
,浏览器访问地址:http://127.0.0.1:3380/ ,页面可以看到index.html的内容,分析托管静态资源配置乐成。

2、托管多个静态资源

如果要托管多个静态资源目录,请多次调用express.static()函数,当访问静态资源文件时,express.static()函数会根据添加的顺序查找所需文件。
例如:
  1. //确保项目中有文件 public 和 upload
  2. app.use(express.static('./public'))
  3. app.use(express.static('./upload'))
复制代码
3、挂载路径前缀

如果希望在托管的静态资源访问路径之前,挂载路径前缀,则可以利用如下方式:
  1. app.use('/public',express.static('./public'))
复制代码
以上配置好之后就可以通过带有/public前缀的地址来访问public目录文件了,访问的地址示例:
http://127.0.0.1:3380/public/index.html
四、nodemon工具

1、为什么利用nodemon

nodemon可以监听项目文件的变动,当代码被修改,nodemon会主动资助我们重启项目,进步了开发效率。
2、安装nodemon

在终端中,运行如下命令,即可将nodemon安装为全局可用的工具:
  1. npm install
  2. -g nodemon
复制代码
3、利用nodemon

在没有安装nodemon之前,启动项目利用node ./app.js

如今安装了nodemon,将启动命令更换为:
  1. nodemon ./app.js
复制代码

五、 express路由

在express中,路由指的是客户端的请求与服务器处理函数之间的映射关系。express中的路由分3个部门组成,分别是请求的类型、请求的URL地址、处理函数。利用路由最基本的方式就是挂载到app身上。格式如下:
  1. app.METHOD(PATH,HANDLER)
复制代码
模块化路由

express不建议将路由直接挂载到app上,推荐将路由抽离为单独的模块。将路由抽离为单独模块的步调如下:
1.创建对应的.js路由模块文件
2.调用express.Router()创建路由对象
3.向路由对象上挂载详细的路由
4.利用module.exports向外共享路由对象
5.入口文件中利用app.use()注册路由模块
1、 创建用户路由模块

下面抽离用户路由模块的示例:
根目录下新建用户路由模块/router/user.js 示例代码如下:
  1. // 导入express
  2. const express = require('express')
  3. // 创建路由对象
  4. const router = express.Router()
  5.   
  6. // 导入路由处理函数
  7. const userRouterHandler = require('../router_handler/user')
  8. // 获取用户列表的路由
  9. router.get('/userlist',userRouterHandler.getUserListHandle)
  10. // 更新用户信息的路由
  11. router.put('/userinfo',userRouterHandler.updateUserInfoHandle)
  12. // 向外导出路由对象
  13. module.exports = router
复制代码
根目录下新建用户路由处理函数 /router_handler/user.js 示例代码如下:
  1. // 获取用户信息路由处理函数
  2. exports.getUserListHandle = (req,res)=>{
  3.     // 相关逻辑...
  4.     res.send('ok')
  5. }
  6. // 更新用户信息路由处理函数
  7. exports.updateUserInfoHandle = (req,res)=>{
  8.     // 相关逻辑...
  9.     res.send('ok')
  10. }
复制代码
在入口文件app.js导入并注册用户路由模块,示例代码如下:
  1. // 导入并注册用户路由模块
  2. const userRouter = require('./router/user')
  3. //根据需求配置路由前缀 /api
  4. app.use('/api',userRouter)
复制代码
2、启动测试

nodemon ./app.js
启动项目
利用api接口测试工具(这里利用Postman) 测试接口 :
http://127.0.0.1:3380/api/userlist
http://127.0.0.1:3380/api/userinfo
下图展示Postman测试接口:

3、项目目录截图


六、全局见效的中间件

客户端发起的任何请求,到达服务器之后,都会触发中间件,叫做全局见效中间件。
通过app.use(中间件函数),即可定义一个全局见效的中间件,中间件本质上是一个function处理函数。
1、express内置的中间件

express.json() 解析JSON格式的请求体数据
express.urlencoded() 解析URL-encoded格式的请求体数据
app.js入口文件,所有路由之前注册这两个中间件:
  1. // 处理post数据
  2. app.use(express.json())
  3. //处理xxx-www-urlencoded数据
  4. app.use(express.urlencoded({ extended:false }))
复制代码
2、解析token中间件(JWT相干)

1.JWT认证机制相干
什么是JWT:目前最流行的跨域认证解决方案。
JWT原理:用户的信息通过Token字符串的形式,保存在客户端浏览器中,服务器通过还原Token字符串的形式来认证用户的身份。
JWT组成三部门:Header(头部)、Payload(有效荷载)、Signature(署名)
JWT推荐利用方式:把JWT放在HTTP请求头的Authorization字段中,格式:Authorization:Bearer <token>
2.安装
jsonwebtoken 用于生成JWT字符串
express-jwt 用于将JWT字符串解析还原成JSON对象
  1. //安装npm install
  2. jsonwebtoken@8.5.1 express-jwt@5.3.3
复制代码
3.配置中间件
根目录下新建config.js文件,代码如下:
  1. module.exports = {
  2.     jwtSecretKey:'pet_web_poppop No1.**', //密钥
  3.     expiresIn:'10h' //token有效期
  4. }
复制代码
app.js文件中,路由之前配置中间件,代码如下:
  1. // 导入 config.js 配置文件
  2. const config = require('./config')
  3. // 导入解析token中间件
  4. const expressJWT = require('express-jwt')
  5. //expressJWT({secret:config.jwtSecretKey}) 用来解析token的中间件
  6. //unless({path:[/^\/api\//]}) 用来指定哪些接口不需要访问权限
  7. app.use(expressJWT({secret:config.jwtSecretKey}).unless({path:[/^\/api\//]} ))
复制代码
4.利用JWT (在登录乐成后生成JWT字符串)
调用 jsonwebtoken 包提供的 sign() 方法,将用户信息加密成JWT字符串,相应给客户端。
留意:千万不要把密码加密到token字符串中
代码如下:
  1. // router/user.js
  2. // 导入路由处理函数
  3. const userRouterHandler = require('../router_handler/user')
  4. // 登录
  5. router.post('/login',userRouterHandler.userLoginHandle)
  6. // /router_handler/user.js
  7. // 导入jwt 相关包
  8. const jwt = require('jsonwebtoken')
  9. //  登录处理函数
  10. exports.userLoginHandle = (req,res)=>{
  11.         let userinfo = req.body
  12.     // 登录失败情况下的代码省略....
  13.     // 用户登录成功后,生成JWT 字符串,通不过token属性响应给客户端
  14.     res.send({
  15.         status:200,
  16.         message:'登录成功!',
  17.         token:jwt.sign({username:userinfo.username},config.jwtSecretKey,{
  18.             expiresIn:config.expiresIn
  19.         })
  20.     })
  21. }
复制代码
3、优化res.send()

res.send()方法用于发送相应数据给客户端,我们在app.js入口文件封装优化它,
必要留意:除了错误级别的中间件在所有路由之后配置 其他的中间件都要在路由之前配置。
  1. // 应用级别的中间件(全局中间件)
  2. app.use((req,res,next)=>{
  3.     res.an = (err,status=1)=>{
  4.         res.send({
  5.             status,
  6.             // 判断err是错误对象还是字符串
  7.             message: err instanceof Error ? err.message : err
  8.         })
  9.     }
  10.     next()
  11. })
复制代码
4、封装错误级别的中间件

错误级别的中间件作用:专门用来捕捉整个项目标异常错误,从而防止项目异常瓦解题目。我们在app.js入口文件封装它,留意:错误级别的中间件必须注册在所有路由之后!
  1. //全局错误级别的中间件 捕获验证失败的错误
  2. app.use((err,req,res,next)=>{
  3.         //...
  4.     if(err.name === 'UnauthorizedError') return res.an('身份认证失败!',401)
  5.     // 未知错误
  6.     res.an(err)
  7. })
复制代码
七、 配置cors跨域

1、安装

  1. npm i cors@2.8.5
复制代码
2、配置

app.js入口文件中注册 cors中间件为全局中间件
  1. //导入中间件
  2. const cors = require('cors')
  3. //将cors 注册为全局中间件
  4. app.use(cors())
复制代码
八、优化表单数据验证

在实际开发中,前后端都必要对表单的数据进行合法性的验证,而且后端作为数据合法性验证的末了一个关口,在拦截非法数据方面,起到了至关重要的作用。利用第三方数据校验模块,来降低出错率,进步验证的效率与可维护性。
1、安装

  1. //joi 定义验证规则npm install
  2. joi// @escook/express-joi 实现主动对表单数据进行验证npm i @escook/express-joi
复制代码
2、利用

新建 / validate/user.js 用户信息验证规则模块 并初始化代码如下:
  1. //导入joi 验证规则
  2. const joi = require('joi')
  3. /**
  4. * string() 值必须是字符串
  5. * aiphanum() 值只能是包含a-zA-Z0-9的字符串
  6. * min(length) 最小长度
  7. * max(length)最大长度
  8. * required() 值是必填项 不能为undefined
  9. * pattern(正则表达式) 值必须符合正则表达式的规则
  10. * **/
  11. // 用户名验证规则
  12. const username = joi.string().alphanum().min(1).max(10).required()
  13. //密码验证规则
  14. const password = joi.string().pattern(/^[\S]{6,12}$/).required()
  15. // 注册和登录表单的验证规则对象
  16. exports.reg_login_validate = {
  17.     // 表示需要对 req.body 中的数据进行验证
  18.     body:{
  19.         username,
  20.         password
  21.     }
  22. }
复制代码
在/router/user.js 路由模块中进行验证,代码如下:
  1. const expressJoi = require('@escook/express-joi')
  2. const {reg_login_validate} = require('../validate/user')
  3. // 登录
  4. router.post('/login',expressJoi(reg_login_validate),userRouterHandler.userLoginHandle)
复制代码
入口文件app.js中在全局错误级别的中间件配置捕捉验证失败的错误,代码如下:
  1. // 导入验证规则
  2. const joi = require('joi')
  3. app.use((err,req,res,next)=>{
  4.     // 验证表单数据,捕获失败错误
  5.      if(err instanceof joi.ValidationError) return res.an(err)
  6.     if(err.name === 'UnauthorizedError') return res.an('身份认证失败!',401)
  7.     // 未知错误
  8.     res.an(err)
  9. })
复制代码
九、 安装并配置mysql模块

1、安装

  1. npm i mysql@2.18.1
复制代码
2、配置

在项目根目录下新建 /db/index.js ,并初始化代码如下:
  1. // 导入mysql模块
  2. const mysql = require('mysql')
  3. // 创建数据库连接对象
  4. const db = mysql.createPool({
  5.     host:'127.0.0.1', //数据库地址
  6.     user:'root',   //数据库用户名
  7.     password:'123456', //数据库密码
  8.     database:'my_database' //数据库名称
  9. })
  10. // 向外共享 db 数据库连接对象
  11. module.exports = db
复制代码
3、利用示例

在用户路由处理函数模块中 router_handler/user.js 导入数据库毗连对象,获取数据库用户信息
  1. // 导入数据库连接对象
  2. const db = require('../db/index')
  3. exports.getUserListHandle = (req,res)=>{
  4.     // 定义查询用户的 sql 语句 首先确保你的数据库创建了user表
  5.     const sql = 'select * from user where is_delete=0'
  6.     db.query(sql,(err,results)=>{
  7.         // 错误处理
  8.         if(err) return res.an(err)
  9.         // 查询成功处理
  10.         res.send({
  11.             status:200,
  12.             message:'获取用户信息成功!',
  13.             data:results
  14.         })
  15.     })
  16. }
复制代码
十、对密码进行加密处理bcryptjs

为了保证密码的安全性,不建议在数据库以明文的形式保存用户密码,下面介绍利用bcryptjs对密码进行加密处理。
1、安装

  1. npm i bcryptjs@2.4.3
复制代码
2、利用

在用户注册时对密码进行加密,再将信息保存到数据库中。
或者用户登录时检测输入的密码与数据库的密码是否同等。示例代码如下:
  1. // router_hadler/user.js
  2. //导入加密包 对密码加密
  3. const bcrypt = require('bcryptjs')
  4. //用户注册处理函数
  5. exports.userRegisterHandle = (req,res)=>{
  6.                     const userinfo = req.body
  7.                 // 此处省略注册逻辑代码...
  8.                 //使用bcryptjs对密码进行加密处理
  9.                 console.log('加密之前密码:',userinfo.password);
  10.                userinfo.password = bcrypt.hashSync(userinfo.password,10)
  11.                console.log('加密之后密码:',userinfo.password);
  12.                //...
  13.     })
  14. }
  15. //用户登录判断输入密码是否与数据中的密码一致
  16. exports.userLoginHandle = (req,res)=>{
  17.                 //登录逻辑省略...
  18.                 const compareResults = bcrypt.compareSync(输入的密码数据,数据库密码数据)
  19.         if(!compareResults) return res.cc('登录失败!')
  20.         //...
  21.     })
  22. }
复制代码
十一、利用svg-captcha和 cookie-parser生成图形验证码并保存到cookie中

svg-captcha 用于生成svg格式的验证码图片
cookie-parser 是express的一个中间件,用来实现对cookie的解析
1、 安装

  1. npm install
  2. cookie-parsernpm install
  3. svg-captcha
复制代码
2、注册 cookie-parser为全局中间件

app.js中代码:
  1. // 导入包
  2. const cookieParase = require('cookie-parser')
  3. //注册
  4. app.use(cookieParase())
复制代码
  1. // router/user.js
  2. // 导入路由处理函数
  3. const userRouterHandler = require('../router_handler/user')
  4. //获取图形验证码
  5. router.get('/getcode',userRouterHandler.getCode)
  6. // /router_handler/user.js
  7. //获取生成的图形验证码处理函数
  8. exports.getCode = (req,res)=>{
  9.     let captcha = svgCaptcha.create({
  10.          // 翻转颜色
  11.          inverse:false,
  12.          // 字体大小
  13.          fontSize:36,
  14.          // 噪声线条数
  15.          noise:2,
  16.          // 宽度
  17.          width:80,
  18.          // 高度
  19.          height:30,
  20.      })
  21.      // 保存到session 忽略大小
  22.      req.session = captcha.text.toLowerCase()
  23.      console.log(req.session);
  24.      // 保存到cookie 方便前端调用验证
  25.       res.cookie('captcha',req.session)
  26.       res.setHeader('ContentType','image/svg+xml')
  27.       res.write(String(captcha.data))
  28.      res.end()
  29. }
复制代码
十二、multer解析表单数据(用于文件上传)

单文件上传 以及 多文件上传

用户路由模块中处理上传用户头像操作,代码如下:
  1. // router/user.js
  2. // 导入multer
  3. const multer = require('multer')
  4. // 设置存储引擎
  5. const storage = multer.diskStorage({
  6.         //文件存储路径
  7.     destination: function (req, file, cb) {
  8.             //保证项目中有此文件
  9.         cb(null, './public/upload');
  10.     },
  11.     //存储的文件名处理
  12.     filename: function (req, file, cb) {
  13.         cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
  14.     }
  15. });
  16. const upload = multer({ storage:storage})
  17. // 导入路由处理函数
  18. const userRouterHandler = require('../router_handler/user')
  19. //,upload.single() 单文件上传
  20. //上传用户头像  user_pic 保存用户头像的字段
  21. router.put('/updateuser',upload.single('user_pic').userRouterHandler.updateUserInfo)
  22. //上传相册 upload.array(数据库相册的字段,限制上传大小)
  23. router.put('/userpicture',upload.array('user_pics',12).userRouterHandler.updateUserPicture)
  24. //router_handler/user.js 用户路由处理函数模块
  25. //上传用户头像处理函数
  26. exports.updateUserInfo = (req,res)=>{
  27.         //req.file 上传的图片信息
  28.         console.log(req.file)
  29.         //处理图片操作...
  30. }
  31. //上传相册 处理函数
  32. exports.updateUserPicture = (req,res)=>{
  33.         //使用req.files接收 上传的图片信息
  34.         console.log(req.files)
  35.         //处理图片操作...
  36. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4