node express基本使用(一)

这里 用的express 5 请注意

1. 创建一个新的路由器对象。

const router = express.Router([options])
mergeParams  // 保留来自父路由器的req.params值。如果父对象和子对象具有冲突的参数名,则以子对象的值为准。
caseSensitive //     启用区分大小写。 默认情况下禁用,将“ / Foo”和“ / foo”视为相同。
strict // 启用严格路由。 默认情况下禁用,路由器将“ / foo”和“ / foo /”视为相同。

路由规则是app.use(path,router)定义的,router代表一个由express.Router()创建的对象,在路由对象中可定义多个路由规则。可是如果我们的路由只有一条规则时,可直接接一个回调作为简写,也可直接使用app.get或app.post方法。即
当一个路径有多个匹配规则时,使用app.use()

// 很麻烦这样写
app.get("/home",callback)
app.get("/home/one",callback)
app.get("/home/second",callback)

// 可以创建一个router.js 专门用来一个路由匹配多个子路由
var router = express.Router()
router.get("/",(req,res)=>{
    res.send("/")
})
router.get("/one",(req,res)=>{
    res.send("one")
})
router.get("/second",(req,res)=>{
    res.send("second")
})
module.exports = router;

// 在app.js中导入router.js
var express = require('express')
var router = require("./router")
var app = express()
app.use('/home',router) //router路由对象中的路由都会匹配到"/home"路由后面

2.  app.use用法

app.use(path,callback)中的callback既可以是router对象又可以是函数
app.get(path,callback)中的callback只能是函数

// 中间件也可以使用多级 callback   anth()中要调用next() 否则不会往下走 
// callback中定义的const let 在下一个callback中是无法访问的 要挂载到 req 或者 res 中
app.use('/admin/api/rest/:resourse', anth(), (req, res, next) => {
  const MODEL_NAME = require('inflection').classify(req.params.resourse)
  // const model = require(`../../models/${MODEL_NAME}`);
  // 为什么不使用 const   router 会访问不到model 所以挂载到req上
  req.model = require(`../../models/${MODEL_NAME}`);
  next()
}, router)

3. 加载静态资源

const path = require('path')
app.use('/uploads', express.static(path.join(__dirname, 'uploads')))

// 为了提供对静态资源文件(图片,css,js文件)的服务,请使用Express内置的中间函数express.static
uploads文件中静态资源通过 http://localhost:3000/uploads/6abe1df86915ae97a3ee28537a5f8cfa 来访问 

// 为了给静态资源文件创建一个虚拟的文件前缀(文件系统中不存在),可以使用express.static函数指定一个虚拟的静态目录
app.use('/static', express.static('public'))
// 使用‘/static’作为前缀来加载public文件夹下的文件了

4. 不同模块的接口分模块开发

module.exports = (app) => {
const express = require('express')
const router = express.Router({
mergeParams: true // 保留来自父路由器的req.params值。如果父对象和子对象具有冲突的参数名,则以子对象的值为准。
}) // 创建express 的子路由, 分模块存储接口
router.get('/', async(req, res) => {
const items = await req.model.find().limit(10) // find 相当于select 进行查询操作
res.send(items)
})
app.use('/admin/api/rest/:resourse', router)
} // 在这个文件里你可以拿到app

// 在 index.js 中引入
require('./routes/admin')(app)

5.  使用CRUD 共工接口

/**
 * 共享接口 CRUD
 * 假如 有两个模板 功能都是增删改查 接口都是相似的操作 就可以使用共享接口
 * app.use('/admin/api/rest/:resourse', router)
 * 需要自己加一个 rest 防止接口冲突
 * 后面是动态的参数  也就是自己的模型名 数据库表名 == 接口名
 * req.params.resourse  可以拿到动态参数 也就是表名  resourse 是自己定义的 也可以是别的
 * 然后 在接口里面 引入参数对应的模型名  
 
 */
 module.exports = (app) => {
    const express = require('express')
    const anth = require('../../utils/auth')
    const router = express.Router({
            mergeParams: true // 保留来自父路由器的req.params值。如果父对象和子对象具有冲突的参数名,则以子对象的值为准。
        }) // 创建express 的子路由, 分模块存储接口
    router.post('/', async(req, res) => {
        const model = await req.model.create(req.body) // 往mongoodb添加数据
        res.send(model)
    })
    router.get('/', async(req, res) => {
        // populate 方法 返回关联对象id 转换成 对象 
        const queryOption = {}
        if (req.model.modelName == 'Category') {
            queryOption.populate = 'parent'
        }
        if (req.model.modelName == 'Article') {
            queryOption.populate = 'categories'
        }
        const items = await req.model.find().setOptions(queryOption).limit(10) // find 相当于select  进行查询操作 populate 查找绑定对象
        res.send(items)
    })
    router.get('/:id', async(req, res) => {
        const model = await req.model.findById(req.params.id) // find 相当于select  进行查询操作
        res.send(model)
    })
    router.put('/:id', async(req, res) => {
        const model = await req.model.findByIdAndUpdate(req.params.id, req.body) // find 相当于select  进行查询操作
        res.send({ msg: '修改成功' })
    })
    router.delete('/:id', async(req, res) => {
        await req.model.findByIdAndDelete(req.params.id) // find 相当于select  进行查询操作
        res.send({ msg: '删除成功' })
    })

    //  使用 rest 防止接口冲突 加上私有前缀
    //  /admin/api/rest/:resourse 中 /:resourse 绑定动态名称  resourse 是自己定义的 也可以是别的
    //  前台传得 http://localhost:3000/admin/api/rest/items
    //  req.params.resourse  可以拿到动态参数 也就是表名 也就是前台接口中items
    app.use('/admin/api/rest/:resourse', (req, res, next) => {
    
        // *inflection插件   inflection.classify( 'message_bus_properties' );//=== 'MessageBusProperty'  会把单词 复数 转换成 单数 因为mongoose中表名是单数  而接口中都是复数  转一下子
        const MODEL_NAME = require('inflection').classify(req.params.resourse)
        
        // const model = require(`../../models/${MODEL_NAME}`);
        // 为什么不使用 const   router 会访问不到 model 所以挂载到req上
        req.model = require(`../../models/${MODEL_NAME}`);
        next()
    }, router)
}

6. 图片文件上传 中间件multer

const multer = require('multer')
// dest 目标地址  文件存放在哪里
const upload = multer({ dest: __dirname + '/../../uploads' })
// upload.single() 接受名称为的单个文件fieldname。单个文件将存储在中req.file。
app.post('/admin/api/upload', upload.single('file'), async(req, res) => {
  const file = req.file
  // 如果想让前台查看上传图片要拼接文件路径返给前台 file.filename就是存储的文件名 uploads是存储的文件夹
  file.url = `http://localhost:3000/uploads/${file.filename}`
  res.send(file)
})

7. 对存储用户密码进行加密解密操作 bcryptjs

const bcryptjs = require('bcryptjs')
// val 要加密的数据 也就是密码   10 就要加密的等级 最好是10-12之间 12以后加密跟解密性能慢 但是安全度高
var pwd = bcryptjs'.hashSync(val, 10)
// 然后存到数据库表中

// 登陆的时候 先根据前台传的 name 去数据库中那条数据   name 一般是唯一的 然后在取出密码
// 密码校验的操作  password 是用户传来的密码  user.password 是数据库存储的加密的密码
var flag = bcryptjs.compareSync(password, user.password) // 返回 true 和 false
// true 返回正确 false 返回错误

 

posted @ 2020-04-22 22:03  大橙爱吃大橙子  阅读(1347)  评论(0编辑  收藏  举报