一、创建项目



二、目录结构


三、配置常用中间件

3.1 解析请求体

  • express.json()
  • express.urlencoded()

3.2 日志输出

  • morgan()

3.3 为客户端提供跨域资源请求

  • cors()

四、路由设计

本项目的接口设计参考:https://github.com/gothinkster/realworld/tree/master/api

router/index.js:

const express = require('express')const router = express.Router()router.get('/', (req, res) => {res.send('Hello World')
})// 用户相关的路由
router.use(require('./user.js'))// 用户资料相关路由
router.use(require('./profile.js'))// 文章相关的路由
router.use(require('./article.js'))// 标签相关的路由
router.use(require('./tag.js'))module.exports = router

router/user.js:

const express = require('express')
const userController = require('../controller/user.js')
const router = express.Router()// 用户登录
router.post('/users/login', userController.login)// 用户注册
router.post('/users', userController.register)// 获取当前登录用户
router.get('/user', userController.getCurrentUser)// 更新当前登录的用户资料
router.put('/user', userController.updateCurrentUser)module.exports = router

router/article.js:

const express = require('express')
const articleController = require('../controller/article.js')
const router = express.Router()// 获取文章列表
router.get('/articles', articleController.getArticles)// 获取用户关注的作者的文章列表
router.get('/articles/feed', articleController.getFeedArticles)// 获取文章
router.get('/articles/:slug', articleController.getArticle)// 创建文章
router.post('/articles',articleController.createArticle)// 更新文章
router.put('/articles/:slug', articleController.updateArticle)// 删除文章
router.delete('/articles/:slug', articleController.deleteArticle)// 为文章添加评论
router.post('/articles/:slug/comments', articleController.addComments)// 从文章中获取评论
router.get('/articles/:slug/comments', articleController.getComments)// 删除评论
router.delete('/articles/:slug/comments/:id', articleController.deleteComments)// 收藏文章
router.post('/articles/:slug/favorite', articleController.favoriteArticle)// 取消收藏文章
router.delete('/articles/:slug/favorite', articleController.unFavoriteArticle)module.exports = router

router/profile.js:

const express = require('express')
const profileController = require('../controller/profile.js')
const router = express.Router()// 获取用户个人资料
router.get('/profiles/:username', profileController.getProfile)// 关注用户
router.post('/profiles/:username/follow', profileController.followUser)// 取消关注用户
router.delete('/profiles/:username/follow', profileController.unFollowUser)module.exports = router

router/tag.js:

const express = require('express')
const tagsController = require('../controller/tag.js')
const router = express.Router()// 获取文章标签
router.get('/tags', tagsController.getTags)module.exports = router

五、提取控制器模块

controller/user.js:

const { User } = require('../model/index.js')// 用户登录
exports.login =  async (req, res, next) => {try {// 处理请求res.send('post /users/login')} catch (err) {next(err)}
}// 用户注册
exports.register =  async (req, res, next) => {try {// 1. 获取请求体数据console.log(req.body)// 2. 数据验证//  2.1 基本数据验证//  2.2 业务数据验证// 3. 验证通过,将数据保存到数据库const user = new User(req.body.user) // 构造user对象await user.save() // 保存到数据库// 4. 发送成功响应res.status(201).json({user})} catch (err) {next(err)}
}// 获取当前登录用户
exports.getCurrentUser =  async (req, res, next) => {try {// 处理请求res.send('get /user')} catch (err) {next(err)}
}// 更新当前登录的用户资料
exports.updateCurrentUser =  async (req, res, next) => {try {// 处理请求res.send('put /user')} catch (err) {next(err)}
}

controller/tag.js:

// 获取文章标签
exports.getTags =  async (req, res, next) => {try {// 处理请求res.send('get /tags 获取文章标签')} catch (err) {next(err)}
}

controller/article.js:

// 获取文章列表
exports.getArticles =  async (req, res, next) => {try {// 处理请求res.send('get /articles')} catch (err) {next(err)}
}// 获取用户关注的作者的文章列表
exports.getFeedArticles =  async (req, res, next) => {try {// 处理请求res.send('get /articles/feed')} catch (err) {next(err)}
}// 获取文章
exports.getArticle =  async (req, res, next) => {try {// 处理请求res.send('get /articles/:slug 获取文章')} catch (err) {next(err)}
}// 创建文章
exports.createArticle =  async (req, res, next) => {try {// 处理请求res.send('post /articles 创建文章')} catch (err) {next(err)}
}// 更新文章
exports.updateArticle =  async (req, res, next) => {try {// 处理请求res.send('put /articles/:slug 更新文章')} catch (err) {next(err)}
}// 删除文章
exports.deleteArticle =  async (req, res, next) => {try {// 处理请求res.send('delete /articles/:slug 删除文章')} catch (err) {next(err)}
}// 为文章添加评论
exports.addComments =  async (req, res, next) => {try {// 处理请求res.send('post /articles/:slug/comments 为文章添加评论')} catch (err) {next(err)}
}// 从文章中获取评论
exports.getComments =  async (req, res, next) => {try {// 处理请求res.send('get /articles/:slug/comments 从文章中获取评论')} catch (err) {next(err)}
}// 删除评论
exports.deleteComments =  async (req, res, next) => {try {// 处理请求res.send('delete /articles/:slug/comments/:id 删除评论')} catch (err) {next(err)}
}// 收藏文章
exports.favoriteArticle =  async (req, res, next) => {try {// 处理请求res.send('post /articles/:slug/favorite 收藏文章')} catch (err) {next(err)}
}// 取消收藏文章
exports.unFavoriteArticle =  async (req, res, next) => {try {// 处理请求res.send('delete /articles/:slug/favorite 取消收藏文章')} catch (err) {next(err)}
}

controller/profile.js:

// 获取用户个人资料
exports.getProfile =  async (req, res, next) => {try {// 处理请求res.send('get /profiles/:username')} catch (err) {next(err)}
}// 关注用户
exports.followUser =  async (req, res, next) => {try {// 处理请求res.send('post /profiles/:username/follow')} catch (err) {next(err)}
}// 取消关注用户
exports.unFollowUser =  async (req, res, next) => {try {// 处理请求res.send('delete /profiles/:username/follow')} catch (err) {next(err)}
}

六、配置错误统一处理中间件


七、用户注册 将数据保存到数据库 && 提取通用数据模型


model/index.js:

model/user.js:

model/article.js:

model/base-model.js:

八、数据验证

express-validator官方文档
安装:npm install express-validator







九、提取验证中间件模块


十、用户注册的密码加密处理

nodejs内置模块 crypto 模块提供了加密功能,实现了包括对 OpenSSL 的哈希、HMAC、加密、解密、签名、以及验证功能的一整套封装。

  • 查看 crypto 模块支持的 hash 函数:crypto.getHashes()


    在模型的password字段上进行md5加密:

关于Model模型中字段的一些属性:

  1. type:字段的类型;

  2. require:true或false,指定该字段是否必填(默认false,不是必填的);

  3. max与min:数字,只能用在Number类型,可以表示最大值与最小值是多少;

  4. maxlength与minlength:只能用于String字符串类型,表示最长或最短字符串长度;

  5. enum: [‘男’, ‘女’],可枚举类型,后边是一个数组,也就是值必须在枚举值中,并且枚举类型必须是String;

    例:sex: { type: String, enum: [ ‘男’, ‘女’ ] } sex字段的值必须在枚举值中,且必须为字符串。

  6. defalt: ‘xxx’, 默认值,如果没有传参数时,会取默认值,存入数据库。

  7. trim: true, 去除字符串两端空格(保存前对字段进行 .trim());

  8. uppercase:true , 只能用于字符串,表示把所有小写字母转为大写字母(保存前对字段进行.toUpperCase());

  9. lowercase:true , 只能用于字符串,表示把所有大写字母转为小写字母(保存前对字段进行.toLowerCase());

    例:test{ type: String, lowercase: true }。

  10. select: true/false,指定该字段在查询出的数据中是否显示,true表示查询数据过滤该字段;

  11. get: () => {} 和set:() => {},两个函数使用Object.defineProperty( ) 来定义getter、setter。

  12. validate: ()=>{ } ,为该字段添加校验。




Express接口综合案例(创建项目、配置常用中间件、路由设计、提取控制器模块、配置错误统一处理中间件、用户注册的数据验证,密码加密)相关推荐

  1. QT 基础知识一(QT安装、创建项目、常用窗口控件使用、信号与槽机制讲解)

    QT概念 Qt:Qt是一个跨平台的C++框架(C++库),Qt除了支持界面设计(GUI编程),还封装了与网络编程.多线程.数据库连接.视频音频等相关的功能. ctrl 撤销(返回上一步) 市面常见的G ...

  2. 网络拓扑配置案例练习(VRRP,浮动路由,DHCP,三层交换机配置)

    网络拓扑配置案例 网络拓扑配置案例练习 网络拓扑 需求描述 具体操作命令 交换机创建vlan,配置access.trunk口,划分vlan vrrp配置 路由配置 验证vrrp和浮动路由 DHCP配置 ...

  3. 计算机硬件选配用户需求,设计师选什么样的电脑配置?浅谈设计用电脑硬件配置的选择建议...

    设计师选什么样的电脑配置?对于这个问题,无法给一个准确的回答,主要是因为设计分为很多种,比如平面设计.3D工业设计.视频动画设计等,由于用途不一,对电脑配置的要求也不一样.下面装机之家来浅谈设计用电脑 ...

  4. 视频教程-Web前端开发仿美团/饿了吗移动App之高德地图接口对接案例-JavaScript

    Web前端开发仿美团/饿了吗移动App之高德地图接口对接案例 互联网编程行业10年开发和授课经验 曾任太极集团,外资企业等一线互联网python高级开发工程师 现任聚焦计算机技术有限公司项目组担任架构 ...

  5. 5.19 综合案例2.0-智能风扇(仅支持2.2以上版本)

    综合案例2.0-智能风扇 简介 AHT10温湿度传感器 电机模块 准备 硬件连接图 代码流程 功能实现 1.物联网平台开发 2.设备端开发 调试 3.物联网应用开发 3.1新建'普通项目' 3.2关联 ...

  6. VUE——使用VUE脚手架创建项目

    前言 vue脚手架工具,对vue项目构造做了封装,直接使用vue-cli创建项目,常用配置自动帮你完成,不用自己像使用webpack一样配置. 目录 1.安装 npm i vue 2.创建vue项目 ...

  7. 如何使用 Maven 来创建项目(一篇文章就够了)

    如何使用 Maven 来创建项目(一篇文章就够了) 1. Maven 简介 1. 简介 2. 项目构建 3. 项目构建工具 2. Maven 的四大特性 1. 依赖管理系统 版本号规范 2. 多模块构 ...

  8. 项目起步 (一) 01-项目介绍-使用技术-创建项目-调整目录结构——黑马头条移动端

    项目介绍 首先,黑马头条移动端是一个IT资讯移动web应用,有着和今日头条一样的资讯浏览体验. 主要功能:资讯列表.标签页切换,文章举报,频道管理.离线频道,文章详情.阅读记忆,关注功能.点赞功能.评 ...

  9. vue创建项目都忘记了怎么办

    公司给了一个比较特殊的项目,不需要使用编写前端,其他几乎都是纯后端,只有很少的几个前端页面,我还是用的LayUI+JQuery做的后台页面,没做多久就看到了LayUI下线的说明,有点蕾姆~~~~~,对 ...

最新文章

  1. 上海交大机试真题—最短路径(最小生成树解法)
  2. Windows核心编程的官方网站
  3. matlab绘制立体图
  4. 如何判断一个点是否在三角形内部
  5. Linux安装docker-compose 1.27.4
  6. 汇编中断知识之INT 1CH
  7. ‘仿微信发表朋友圈’项目中登录功能的业务逻辑
  8. bash 后台程序_如何向您的Bash程序添加帮助工具
  9. linux下tomcat ssl证书,Tomcat部署ssl证书(Linux)
  10. 用winformz时间格式不正确_巨峰葡萄不能膨大?错!在正确的时间,用对方法,收获优质果穗型...
  11. 冲刺秋招!离拿到心仪Offer你还差什么?
  12. java翻译数字串并打印_如何使用Java翻译字符串?
  13. JAVA_WEB程序设计教程 pdf
  14. 指标公式c语言源码下载,通达信超级全系列指标公式
  15. 喜马拉雅下载文件名批量修改
  16. 如何在家优雅地使用 Sci-Hub 免费下载外文文献
  17. 二元二次不定方程(佩尔方程)
  18. 用c++随机生成10小学生算术题的课设
  19. Linux du命令详解
  20. 一般对称性和轮换对称性

热门文章

  1. ubuntu之ufw防火墙
  2. HIVE攻略 JFK_Hive安装及使用攻略
  3. redhat虚拟机安装
  4. Windows API GetProcAddress 及demo code
  5. w3wp oracle,w3wp.exe占用CPU超过50%的处理
  6. qlabel可以选中吗_惊现凡尔赛式排版!原来微信公众号排版样式还可以“变装”?...
  7. python 编程模型
  8. caffe运行训练脚本时报错:Unknown bottom blob 'data' (layer 'conv1',bottom index 0)
  9. C++之Boost准标准库配置
  10. python知识点1