Node.js基础(二)

1. NodeJs操作Mongodb

1.1. 连接数据库

javascript 复制代码
const mongoose = require("mongoose")
mongoose.connect("mongodb://127.0.0.1:27017/company-system")

1.2. 创建模型

javascript 复制代码
const mongoose = require("mongoose")
const Schema = mongoose.Schema

const UserType = {
    username:String,
    password:String,
    gender:Number,
    introduction:String,
    avatar:String,
    role:Number
}
const UserModel = mongoose.model("user",new Schema(UserType))
module.exports  = UserModel 

1.3. 增加数据

javascript 复制代码
UserModel.create({
    introduction,username,gender,avatar,password,role
})

1.4. 查询数据

javascript 复制代码
UserModel.find({username:"wyb"},["username","role","introduction","password"]).sort({createTime:-1}).skip(10).limit(10)

1.5. 更新数据

javascript 复制代码
UserModel.updateOne({ _id },{ introduction,username,gender,avatar })

1.6. 删除数据

javascript 复制代码
UserModel.deleteOne({_id})

2. 登录鉴权

javascript 复制代码
const express = require("express");
const session = require("express-session");
const MongoStore = require("connect-mongo");
const app = express();

app.use(
  session({
    secret: "this is session", // 服务器生成 session 的签名
    resave: true, 
    saveUninitialized: true, // 强制将为初始化的 session 存储
    cookie: {
      maxAge: 1000 * 60 * 10,// 过期时间
      secure: false, // true:只有 https 协议才能访问cookie
    },
    rolling: true, // true:超时前刷新,cookie 会重新计时;false:在超时前刷新多少次,都是按照第一次刷新开始计时。
    store: MongoStore.create({
      mongoUrl: 'mongodb://127.0.0.1:27017/kerwin_session',
      ttl: 1000 * 60 * 10 // 过期时间
  	}),
  })
);

app.use((req,res,next)=>{
  if(req.url==="/login"){
    next()
    return;
  }
  if(req.session.user){
      req.session.garbage = Date();
      next();
  } else{
   	  res.redirect("/login")   
  }
})

2.2. JSON Web Token (JWT)

  • 代码实现
javascript 复制代码
//jsonwebtoken 封装
const jsonwebtoken = require("jsonwebtoken")
const secret = "wyb- secret"
const JWT = {
    generate(value, exprires){
        return jsonwebtoken.sign(value, secret, {expiresIn: exprires})
    },
    verify(token){
        try {
            return jsonwebtoken.verify(token, secret)
        } catch(e) {
            return false
        }
    }
}
module.exports = JWT
javascript 复制代码
//node中间件校验
app.use((req,res,next)=>{
  // 如果token有效 ,next() 
  // 如果token过期了, 返回401错误
  if(req.url==="/login"){
    next()
    return;
  }

  const token = req.headers["authorization"].split(" ")[1]
  if(token) {
    const payload = JWT.verify(token)
    if(payload) {
      const newToken = JWT.generate({
        _id: payload._id,
        username: payload.username
      }, "1d")
      res.header("Authorization", newToken)
      next()
    } else {
      res.status(401).send({errCode: "-1", errorInfo: "token过期"})
    }
  }
})
javascript 复制代码
// 生成token
const token = JWT.generate({
    _id: result[0]._id,
    username: result[0].username
}, "1d")
res.header("Authorization", token)

3. 文件上传管理

Multer 是一个 node.js 中间件,用于处理 multipart/form-data 类型的表单数据,它主要用于上传文件。

  • 前端
javascript 复制代码
const params = new FormData()
params.append('wybfile', file.file)
params.append('username', this.username)
const config = {
	headers: {
		"Content-Type":"multipart/form-data"
	}
}
http.post('/api/upload', params, config).then(res => {
	this.imgpath = 'http://localhost:3000' + res.data
})	

Multer 会添加一个 body 对象 以及 filefiles 对象 到 express 的 request 对象中。 body 对象包含表单的文本域信息,filefiles 对象包含对象表单上传的文件信息。

  • 后端
javascript 复制代码
router.post('/upload', upload.single('wybfile'),function(req, res, next) {
	console.log(req.file)
})

4. 操作MySQL

javascript 复制代码
const express = require('express')
const app = express()
const mysql2 = require('mysql2')
const port = 9000

app.get('/', async (req, res) => {
  const config = getDBConfig()
  const promisePool = mysql2.createPool(config).promise();
  let user = await promisePool.query('select * from students');
      if (user[0].length) {
          // 存在用户
          res.send(user[0])
      } else {
          // 不存在
          res.send( {
              code: -2,
              msg: 'user not exsit',
          })
      }      
})
app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})

function getDBConfig() {
  return {
    host: '127.0.0.1',
    user: 'root',
    port: 3306,
    password: '',
    database: 'wyb_test',
    connectionLimit: 1 // 创建一个连接池
  }
}
javascript 复制代码
查询:promisePool.query('select * from users');
插入:promisePool.query('INSERT INTO `users`(`id`,`name`,`age`, `password`) VALUES (?,?,?,?)',[null,"kerwin",100,"123456"]);
更新:promisePool.query(`UPDATE users SET name = ? ,age=? WHERE id = ?`,["xiaoming2",20,1])
删除:promisePool.query(`delete from users where id=?`,[1])

5. Socket编程

5.1. ws模块

  • 服务端
javascript 复制代码
const  WebSocket = require("ws")
WebSocketServer = WebSocket.WebSocketServer
const wss = new WebSocketServer({ port: 8080 });

wss.on('connection', function connection(ws) {
    ws.on('message', function message(data, isBinary) {
        wss.clients.forEach(function each(client) {
            if (client !== ws && client.readyState === WebSocket.OPEN) {
                client.send(data, { binary: isBinary });
            }
        });

    });
    ws.send('欢迎加入聊天室');
});
  • 客户端
javascript 复制代码
let ws = new WebSocket("ws://localhost:8080")
ws.onopen = ()=>{
    console.log("open")
}
ws.onmessage = (evt)=>{
    console.log(evt.data)
}

5.2. 授权验证

javascript 复制代码
// 前端
var ws = new WebSocket(`ws://localhost:8080?token=${localStorage.getItem("token")}`)
ws.onopen = () => {
     ws.send(JSON.stringify({
        type: WebSocketType.GroupList
     }))
}
ws.onmessage = (evt) => {
    console.log(evt.data)
}
// 后端
const WebSocket = require("ws");
const JWT = require('../util/JWT');
WebSocketServer = WebSocket.WebSocketServer
const wss = new WebSocketServer({ port: 8080 });

wss.on('connection', function connection(ws, req) {
  const myURL = new URL(req.url, 'http://127.0.0.1:3000');
  const payload = JWT.verify(myURL.searchParams.get("token"))
  if (payload) {
    ws.user = payload
    ws.send(createMessage(WebSocketType.GroupChat, ws.user, "欢迎来到聊天室"))
    sendBroadList() //发送好友列表
  } else {
    ws.send(createMessage(WebSocketType.Error, null, "token过期"))
  }
  ws.on('message', function message(data, isBinary) {
    const messageObj = JSON.parse(data)
    switch (messageObj.type) {
      case WebSocketType.GroupList:
        ws.send(createMessage(WebSocketType.GroupList, ws.user, JSON.stringify(Array.from(wss.clients).map(item => item.user))))
        break;
      case WebSocketType.GroupChat:
        wss.clients.forEach(function each(client) {
          if (client !== ws && client.readyState === WebSocket.OPEN) {
            client.send(createMessage(WebSocketType.GroupChat, ws.user, messageObj.data));
          }
        });
        break;
      case WebSocketType.SingleChat:
        wss.clients.forEach(function each(client) {
          if (client.user.username === messageObj.to && client.readyState === WebSocket.OPEN) {
            client.send(createMessage(WebSocketType.SingleChat, ws.user, messageObj.data));
          }
        });
        break;
    }

    ws.on("close",function(){
      // 删除当前用户
      wss.clients.delete(ws.user)
      sendBroadList() //发送好用列表
    })
  });
});
const WebSocketType = {
  Error: 0, //错误
  GroupList: 1,//群列表
  GroupChat: 2,//群聊
  SingleChat: 3//私聊
}
function createMessage(type, user, data) {
  return JSON.stringify({
    type: type,
    user: user,
    data: data
  });
}

function sendBroadList(){
  wss.clients.forEach(function each(client) {
    if (client.readyState === WebSocket.OPEN) {
      client.send(createMessage(WebSocketType.GroupList, client.user, JSON.stringify(Array.from(wss.clients).map(item => item.user))))
    }
  });
}

5.3. socket.io模块

  • 服务端
javascript 复制代码
const io = require('socket.io')(server);
io.on('connection', (socket) => {
  const payload = JWT.verify(socket.handshake.query.token)
  if (payload) {
    socket.user = payload
    socket.emit(WebSocketType.GroupChat, createMessage(socket.user, "欢迎来到聊天室"))
    sendBroadList() // 发送好友列表
  } else {
    socket.emit(WebSocketType.Error, createMessage(null, "token过期"))
  }
  socket.on(WebSocketType.GroupList, () => {
    socket.emit(WebSocketType.GroupList, createMessage(null, Array.from(io.sockets.sockets).map(item => item[1].user).filter(item=>item)));
  })
  socket.on(WebSocketType.GroupChat, (messageObj) => {
    socket.broadcast.emit(WebSocketType.GroupChat, createMessage(socket.user, messageObj.data));
  })
  socket.on(WebSocketType.SingleChat, (messageObj) => {
    Array.from(io.sockets.sockets).forEach(function (socket) {
      if (socket[1].user.username === messageObj.to) {
        socket[1].emit(WebSocketType.SingleChat, createMessage(socket[1].user, messageObj.data));
      }
    })
  })
  socket.on('disconnect', reason => {
     sendBroadList() // 发送好用列表
  });
});

function sendBroadList() {
  io.sockets.emit(WebSocketType.GroupList, createMessage(null, Array.from(io.sockets.sockets).map(item => item[1].user).filter(item=>item)))
}
// 最后filter,是因为 有可能存在null的值
  • 客户端
javascript 复制代码
const WebSocketType = {
    Error: 0, //错误
    GroupList: 1, //群列表
    GroupChat: 2, //群聊
    SingleChat: 3 //私聊
}
const socket = io(`ws://localhost:3000?token=${localStorage.getItem("token")}`);
socket.on("connect",()=>{
	socket.emit(WebSocketType.GroupList)
})
socket.on(WebSocketType.GroupList, (messageObj) => {
    select.innerHTML = ""
    select.innerHTML = `<option value="all">all</option>` + messageObj.data.map(item => `
    <option value="${item.username}">${item.username}</option>`).join("")
})
socket.on(WebSocketType.GroupChat, (msg) => {
	console.log(msg)
})
socket.on(WebSocketType.SingleChat, (msg) => {
	console.log(msg)
})
socket.on(WebSocketType.Error, (msg) => {
    localStorage.removeItem("token")
    location.href = "/login"
})
send.onclick = () => {
    if (select.value === "all") {
        socket.emit(WebSocketType.GroupChat,{
            data: text.value
        })
    } else {
        socket.emit(WebSocketType.SingleChat,{
            data: text.value,
            to:select.value
        })
    }
}
相关推荐
永乐春秋5 分钟前
WEB攻防-通用漏洞&文件上传&js验证&mime&user.ini&语言特性
前端
鸽鸽程序猿6 分钟前
【前端】CSS
前端·css
ggdpzhk8 分钟前
VUE:基于MVVN的前端js框架
前端·javascript·vue.js
学不会•2 小时前
css数据不固定情况下,循环加不同背景颜色
前端·javascript·html
活宝小娜5 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点5 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow5 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o5 小时前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app
开心工作室_kaic6 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
刚刚好ā6 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue