這里 用的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 返回錯誤