用koa写项目接口超简单,易学,新手快速上手

359 阅读3分钟

这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战

在之前我们写好了登录和注册两个接口,并颁发了令牌,接下来我们今天做发表文章(增删改查)

详细请看这篇文章:第二篇文章

大致的流程是这样的

image.png

1. 创建文章表

CREATE TABLE IF NOT EXISTS `moment`(
	id INT PRIMARY KEY AUTO_INCREMENT,
	content VARCHAR(1000) NOT NULL,
	user_id INT NOT NULL,
	createAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
	updateAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
	FOREIGN KEY(user_id) REFERENCES user(id)
);

2. 创建moment路由

    moment.router.js
    
const Router = require('koa-router')

const momentRouter = new Router({prefix: '/moment'})

const {
    create
} = require('../controller/moment.controller')

// 发表动态
momentRouter.post("/",)

module.exports = momentRouter
    moment.controller.js

class MomentController {
    async create(ctx, next) {
        ctx.body = "发表评论成功"
    }
}

module.exports = new MomentController()

实现验证是否登录的中间件verifyAuth,属于auth.middleware.js


const jwt = require("jsonwebtoken");    //之前登录用的私钥加密的,我们现在要来用公钥来解密
const { PUBLIC_KEY } = require("../app/config");    //公钥

// 验证是否登录
const verifyAuth = async (ctx, next) => {
  const authorization = ctx.headers.authorization;

  // 获取token
  if (!authorization) {
    const error = new Error(errorTypes.UNAUTHORIZATION);
    return ctx.app.emit("error", error, ctx);
  }
  const token = authorization.replace("Bearer ", "");

  // 验证token
  try {
    const result = jwt.verify(token, PUBLIC_KEY, {
      algorithms: ["RS256"],
    });
    ctx.user = result;

    await next();
  } catch (err) {
    const error = new Error(errorTypes.UNAUTHORIZATION);
    ctx.app.emit("error", error, ctx);
  }
};

module.exports = {
  verifyAuth
};

当验证成功后,进入我们发表文章中间件create

image.png

const momentService = require("../service/moment.service");

async create(ctx, next) {
    // 获取数据(user_id, content)
    const userId = ctx.user.id;
    const content = ctx.request.body.content;

    // 数据插入到数据库
    const result = await momentService.create(userId, content);
    ctx.body = result;
  }
const connection = require("../app/database");

class MomentService {
    //将获取到的评论内容插入到数据中
    async create(userId, content) {
        const statement = `INSERT INTO moment (content, user_id) VALUES (?, ?);`;
    
        const [result] = await connection.execute(statement, [content, userId]);
    
        return result;
      }
}

module.exports= new MomentService()

测试

image.png

查询动态(单)

//moment.router.js

const {
    detail
} = require('../controller/moment.controller')

// 查询动态(单)
momentRouter.get("/:momentId", detail)

image.png

//moment.controller.js

class MomentController {
    async detail(ctx, next) {
          const momentId = ctx.params.momentId      

          ctx.body = momentId //2
      }
}

module.exports = new MomentController();

获取到要查询的文章id后,我们进入数据开始查询(返回的数据有,文章,用户id, 发表时间, 更新时间)

//moment.service.js

const connection = require("../app/database");

class MomentService {
    async getMomentById(id) {
        //这里也可以用tyrcatch来捕获一下,以后出错了方便查找
        const statement = `
        SELECT 
          m.id id, m.content content, m.createAt createTime, m.updateAt updateTime,
          JSON_OBJECT('id', u.id, 'name', u.name) author
        from moment m 
        LEFT JOIN user u ON m.user_id = u.id
        WHERE m.id = ?
        `

        const [result] = await connection.execute(statement, [id])

        return result
      }
}
module.exports= new MomentService()

将结果返回给用户

//moment.controller.js

const momentService = require("../service/moment.service");

class MomentController {
    async detail(ctx, next) {
    // 获取id
    const momentId = ctx.params.momentId;

    // 根据id去查询
    const result = await momentService.getMomentById(momentId);

    ctx.body = result;
  }
}

module.exports = new MomentController();

查询动态(多)流程和查询单个的差不多,唯一不同的就是数据库查询

// moment.router.js

const {
    list
} = require('../controller/moment.controller')

// 查询动态(多)
momentRouter.get("/", list)

image.png

获取传入的query,然后传入数据库进行查询

const momentService = require("../service/moment.service");

class MomentController {
    async list(ctx, next) {
      // 获取数据(offset, size)
    const { offset, size } = ctx.query;

    const result = await momentService.getMomentList(offset, size);

    ctx.body = result;
   }
}  

module.exports = new MomentController();
const connection = require("../app/database");

class MomentService {
    async getMomentList(offset, size) {
            const statement = `
            SELECT 
              m.id id, m.content content, m.createAt createTime, m.updateAt updateTime,
              JSON_OBJECT('id', u.id, 'name', u.name) author
            FROM moment m
            LEFT JOIN user u ON m.user_id = u.id
            LIMIT ?, ?;
            `

            const [result] = await connection.execute(statement, [offset, size])

            return result
          }
}      
      module.exports= new MomentService()

修改动态

graph TD
必须登录 --> 要修改的动态是属于登录的那个人 --> 修改成功/修改失败

封装验证权限中间件verifyPermission

//auth.middleware.js

// 通过闭包来实现
const verifyPermission = (tableName) => {     //要查询的表
  return async (ctx, next) => {
    // 取数据
    const {commentId} = ctx.params   //获取文章的id
    const { id } = ctx.user;         //用户的id

    // 查询
    const isPermission = await authService.checkResoure(
      tableName,
      commentId,
      id
    );
  
    // 判断是否具备,如果不具备就抛出异常
    if (!isPermission) {
      const error = new Error(errorTypes.UNPERMISSION);
      return ctx.app.emit("error", error, ctx);
    }
  
    await next();
  };
}

module.exports = {
  verifyPermission
};
// auth.service.js

const connection = require("../app/database");

//根据要查询的表,id,用户id来查询他是否存在
class AuthService {
  async checkResoure(tableName, resourceId, userId) {
    const statement = `SELECT * from ${tableName} WHERE id = ? AND user_id = ?`;

    const [result] = await connection.execute(statement, [resourceId, userId]);

    return result.length === 0 ? false : true;
  }
}

module.exports = new AuthService();

当具备后,拿到修改的内容,去数据库里进行修改并提示成功

// moment.router.js

const {
    update
} = require('../controller/moment.controller')

const {
    verifyAuth,
    verifyPermission
} = require('../middleware/auth.middleware.js')

// 修改动态
momentRouter.patch("/:momentId", verifyAuth, verifyPermission(moment), update)
// moment.controller

const momentService = require("../service/moment.service");

class MomentController {
    async update(ctx, next) {
        const { momentId } = ctx.params;
        const { content } = ctx.request.body;

        const result = await momentService.update(content, momentId);

        ctx.body = result;
      }
}

module.exports = new MomentController();
// moment.service.js

const connection = require("../app/database");

class MomentService {
    async update(content, momentId) {
            try {
              const statement = `UPDATE moment SET content = ? WHERE id = ?`;

              const [result] = await connection.execute(statement, [content, momentId]);

              return result;
            } catch (error) {
              console.log(error);
            }
          }
}

module.exports= new MomentService()

删除动态

graph TD
必须登录 --> 要删除的动态是属于登录的那个人 --> 删除成功/删除失败
// moment.router.js

const {
    remove
} = require('../controller/moment.controller')

const {
    verifyAuth,
    verifyPermission
} = require('../middleware/auth.middleware.js')

// 删除动态
momentRouter.delete("/:momentId", verifyAuth, verifyPermission(moment), remove)
//moment.controller.js

const momentService = require("../service/moment.service");

class MomentController {
    async remove(ctx, next) {
        const { momentId } = ctx.params;

        const result = await momentService.remove(momentId);

        ctx.body = result;
      }
}

module.exports = new MomentController();
// moment.service.js

const connection = require("../app/database");

class MomentService {
    async remove(momentId) {
        try {
          const statement = `DELETE FROM moment WHERE id = ?`;
    
          const [result] = await connection.execute(statement, [momentId]);
    
          return result;
        } catch (error) {
          console.log(error);
        }
      }
}

module.exports= new MomentService()

好了,动态的增删改查做完了哦,项目地址欢迎下载学习哦