这里 用的express 5 请注意
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(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 * 假如 有两个模板 功能都是增删改查 接口都是相似的操作 就可以使用共享接口 * 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.
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.
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 返回错误