Nodejs项目创建

1. 初始化node项目

创建一个文件夹,在这个文件夹下打开命令行窗口

// 1. 初始化一个package.json文件
npm init -y
// 2.. 安装express
pnpm i express
// 3. 安装热更新库
pnpm i nodemon
// 4. 安装mysql数据库插件
pnpm i mysql
// 5. 安装cors跨域插件
pnpm i cors
// 6. 安装生成token的jwt插件
pnpm i jsonwebtoken
// 7. 安装解析token的jwt插件
pnpm i express-jwt
// 8. 安装日期插件
pnpm i dayjs

基本目录结构

基本目录结构

2. 启动服务器

  • 在根目录下创建app.js文件作为后端服务启动入口

app.js

// 导入express库
const express = require("express");
const app = express();
// 设置端口号
const port = process.env.PORT || 1800;
// 导入解析token的库
const expressjwt = require("express-jwt");
// 导入解决跨域库
const cors = require("cors");
// 导入配置文件
const config = require("./config");

// 把跨域模块注册到app实例上
app.use(cors());
// 托管静态资源
app.use(express.static("public"));
// 配置解析post数据的中间件,这个中间件只能解析application/json格式的数据
app.use(express.json());
// 配置解析post数据的中间件,这个中间件只能解析application/x-www-form-urlencoded格式的表单数据
app.use(express.urlencoded());

// 导入注册、登录路由模块
const userRouter = require("./router/user");

// 定义全局错误中间件,必须在路由之前定义
app.use((req, res, next) => {
  // 在res对象上挂载一个自定义处理错误的函数,status(0:成功,1:失败)
  res.myErr = (err, status = 1) => {
    res.send({
      status,
      message: err instanceof Error ? err.message : err,
    });
  };
  next();
});

// 一定要定义在路由之前来解析token
app.use(expressjwt.expressjwt({ secret: config.jwtKey, algorithms: ["HS256"] }).unless({ path: [/^\/api\//] }),);

// 把路由模块注册到app实例上,/api是注册登录路由模块的前缀,可以跳过身份验证
app.use("/api", userRouter);

// 定义中间件、路由、连接数据库……
app.use((err, req, res, next) => {
  // 验证失败导致的错误
  if (err instanceof joi.ValidationError) return res.myErr(err);

  // 捕获身份认证失败的错误
  if (err.name === "UnauthorizedError") return res.myErr("身份认证失败!");

  // 未知错误
  res.myErr(err);
});

// 监听服务器的启动
app.listen(port, () => {
  console.log(port + "端口服务启动成功!! ");
});

自定义config.js文件

// 配置文件

// 导入日期解析包
const dayjs = require("dayjs");

module.exports = {
  // 生成token的密钥
  jwtKey: "onepiece//",
  // token的过期时间
  expirytime: "10000h",
  // 获取系统当前时间
  nowTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
};

3. 创建路由

  • 在根目录router文件中,根据不同的功能,创建不同的路由文件,以注册、登录为例

router/user.js

// 首页注册、登录路由模块

// 导入express
const express = require("express");
// 实例化路由
const router = express.Router();
// 导入路由处理函数模块
const userHandler = require("../router_handler/user");

// 定义路由
// 注册用户
router.post("/register", userHandler.register);

// 登录
router.post("/login", userHandler.login);

//向外暴露路由
module.exports = router;

4. 连接mysql数据库

  • 在根目录下创建db/index.js文件

db/index.js

// 导入mysql数据库模块
const mysql = require("mysql");

// 创建数据库连接对象
const db = mysql.createPool({
  // 数据库连接地址
  host: "127.0.0.1",
  // 数据库用户名
  user: "root",
  // 数据库密码
  password: "123456",
  // 连接的数据库名,需要存在一个onepiece数据库
  database: "onepiece",
});

// 向外共享db数据库连接对象
module.exports = db;

5. 开发路由逻辑

  • 在router_handler文件中,创建不同模块的路由逻辑,以注册、登录为例

router_handler/user.js

/**
 * 注册、登录路由处理函数模块
 * @type {{}}
 */

// 导入数据库连接
const db = require("../db/index");
// 导入密码加密库
const bcrypt = require("bcryptjs");
// 导入生成token的库
const jwt = require("jsonwebtoken");
// 导入配置文件
const config = require("../config");

// 注册用户
exports.register = (req, res) => {
  // 获取用户传递application/x-www-form-urlencoded的参数
  const userInfo = req.body;

  // 定义用户表查询sql语句
  const selectSql = "select * from user where username=?";
  // 判断用户是否存在用户表中
  db.query(selectSql, userInfo.userName, (err, results) => {
    // 查询出错
    if (err) return res.myErr(err);

    // 用户名存在
    if (results.length > 0) return res.myErr("用户名已被占用!");

    // 密码加密
    userInfo.password = bcrypt.hashSync(userInfo.password, 10);

    // 定义用户表插入sql语句
    const insertSql = "insert into user set ?";
    // 把用户信息插入到用户表中
    db.query(
      insertSql,
      {
        userName: userInfo.userName,
        password: userInfo.password,
        createTime: config.nowTime,
        updateTime: config.nowTime,
      },
      (err, result) => {
        // 查询出错
        if (err) return res.myErr(err);

        // 判断是否注册成功
        if (result.affectedRows !== 1)
          return res.myErr("用户注册失败,请稍后重试!");

        // 注册成功
        res.send({ status: 0, message: "用户注册成功!" });
      },
    );
  });
};

// 登录
exports.login = (req, res) => {
  // 获取用户传递application/x-www-form-urlencoded的参数
  const userInfo = req.body;

  // 定义用户表查询sql语句
  const selectSql = "select * from user where username=?";
  // 判断用户是否存在用户表中
  db.query(selectSql, userInfo.userName, (err, results) => {
    // 查询出错
    if (err) return res.myErr(err);

    // 用户名不存在
    if (results.length !== 1) return res.myErr("用户名或密码不正确");

    // 验证客户提交密码与数据库存储的密码是否一致
    const passwordResult = bcrypt.compareSync(
      userInfo.password,
      results[0].password,
    );
    if (!passwordResult) return res.myErr("用户名或密码不正确");

    // 使用jwt生成token,一般是用用户的id用于生成token,敏感信息不建议放在token信息中
    const user = { ...results[0], password: "", userPic: "" };

    // 根据用户id+token密钥+过期时间来生成token
    const tokenStr = jwt.sign(user, config.jwtKey, {
      expiresIn: config.expirytime,
    });

    res.send({ status: 0, message: "登录成功!", token: "Bearer " + tokenStr });
  });
};
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容