[TOC]
>[success] # API 對接 MySQL
這個章節我們將之前 **controller 處理接口數據的文件** 里的 **假數據** ,**全部替換** 成 **真實數據** ,我們首先先從 **controller** 中根據 **sql 指令** 然后通過 **exec 方法** 從 **數據庫** 中 **取出數據** ,再 **層層往回傳遞數據**,正如標題括號中所說的那樣,**controller > router > app.js > 傳給前端** 這么一個順序,所以下面的文件就先從 **controller** 來看,看完再看 **router** ,然后再看 **app.js** 看每層都如何做的處理。
>[success] ## controller 文件(處理數據后返回給 router)
1. **博客相關文件**
**blog-1/src/controller/blog.js**
~~~
// 引入mysql工具函數
const { exec } = require('../db/mysql')
/**
* 獲取博客列表
* @param {string} author - 作者
* @param {string} keyword - 搜索關鍵字
*/
const getList = (author, keyword) => {
let sql = `select * from blogs where 1=1 ` // 注意:這里為什么寫 1=1,如果author沒有值【select * from blogs where】會報錯,如果有值就會帶上查詢條件
if(author){
sql += `and author='${author}' ` // 注意:后面有空格
}
if(keyword){
// 模糊查詢
sql += `and title like '%${keyword}%' ` // 注意:后面有空格
}
// 按照時間倒序排序
sql += `order by createtime desc`
// 返回的是 promise 對象
return exec(sql)
}
/**
* 獲取博客詳情
* @param {number} id - 博客列表 item id
*/
const getDetail = (id) => {
const sql = `select * from blogs where id='${id}'`
return exec(sql).then(rows => {
return rows[0] // 因為 sql 語句查詢出來的是個數組
})
}
/**
* 新增博客
* @param {object} blogData - blogData 是一個博客對象,包含 title content author 屬性
*/
const newBlog = (blogData = {}) => {
// 整理要插入的數據
const title = blogData.title
const content = blogData.content
const author = blogData.author
const createtime = Date.now()
// 創建 sql 語句
let sql = `
insert into blogs(title, content, author, createtime)
values('${title}', '${content}', '${author}', '${createtime}');`
return exec(sql).then(insertData => {
return {
id: insertData.insertId
}
})
}
/**
* 更新博客
* @param {number} id - 要更新的博客的id
* @param {object} blogData - blogData 是一個博客對象,包含 title content 屬性
*/
const updateBlog = (id, blogData = {}) => {
const title = blogData.title
const content = blogData.content
let sql = `update blogs set title='${title}', content='${content}' where id=${id};` // id整數型數據不需要引號包裹
return exec(sql).then(updateData => {
if(updateData.affectedRows > 0){
return true
}
return false
})
}
/**
* 刪除博客
* @param {number} id - 要刪除的博客的id
* @param {string} author - 作者身份,因為不可以越權刪除,所以要加作者
*/
const deleteBlog = (id, author) => {
const sql = `delete from blogs where id=${id} and author='${author}'`
return exec(sql).then(deldateData => {
if(deldateData.affectedRows > 0){
return true
}
return false
})
}
module.exports = {
getList,
getDetail,
newBlog,
updateBlog,
deleteBlog
}
~~~
注意:這里需要注意一下 **getList** 方法中的 **sql** 語句中的 **1=1** ,因為這里如果不這樣寫,如果 **author** 沒有值就會變成這樣: `select * from blogs where` **where** 后面 **沒有條件會報錯** 。還有一點就是 **sql** 語句后面是有 **空格** 的,一定要注意。還有 **新增功能,新增時是需要登錄人信息的,由于登陸功能目前未開發,【author】參數目前手動寫死假數據代替** ,以及 **刪除功能也同樣需要登錄人信息,暫時也使用的假數據代替** 。
2. **用戶相關文件**
**blog-1/src/controller/user.js**
~~~
// 引入mysql工具函數
const { exec } = require('../db/mysql')
/**
* 登陸
* @param {string} username - 用戶名
* @param {string} password - 密碼
*/
const login = (username, password) => {
const sql = `select username, realname from users where username='${username}' and password='${password}';`
return exec(sql).then(rows => {
return rows[0] || {}
})
}
module.exports = { login }
~~~
>[success] ## router文件(處理數據后返回給 app.js)
1. **博客路由文件**
**blog-1/src/router/blog.js**
~~~
// 從 controller 中獲取數據
const { getList,
getDetail,
newBlog,
updateBlog,
deleteBlog } = require('../controller/blog')
// 引入數據模型
const { SuccessModel, ErrorModel } = require('../model/resModel')
const handleBlogRouter = (req, res) => {
const method = req.method // GET POST
const id = req.query.id
// 獲取博客列表
if(method === 'GET' && req.path === '/api/blog/list'){
// 取得參數
const author = req.query.author || ''
const keyword = req.query.keyword || ''
// 從 controller 中獲取數據
const result = getList(author, keyword)
// 結果返回給app.js
return result.then(listData => {
// 通過數據模型加工數據返回帶有 erron 屬性的對象數據
return new SuccessModel(listData)
})
}
// 獲取博客詳情
if(method === 'GET' && req.path === '/api/blog/detail'){
const result = getDetail(id)
return result.then(data => {
return new SuccessModel(data)
})
}
// 新建一篇博客
if(method === 'POST' && req.path === '/api/blog/new'){
req.body.author = 'zhangsan' // 假數據,待開發登陸時再改成真數據,這里是根據當前登錄人角色傳過來的,目前沒有做登陸功能
const result = newBlog(req.body)
return result.then(data => {
return new SuccessModel(data)
})
}
// 更新一篇博客
if(method === 'POST' && req.path === '/api/blog/update'){
const result = updateBlog(id, req.body)
return result.then(val => {
if(val){ // 更新成功
return new SuccessModel()
} else {
return new ErrorModel('更新博客失敗')
}
})
}
// 刪除一篇博客
if(method === 'POST' && req.path === '/api/blog/delete'){
const author = 'zhangsan' // 假數據,待開發登陸時再改成真數據,這里是根據當前登錄人角色傳過來的,目前沒有做登陸功能
const result = deleteBlog(id, author)
return result.then(val => {
if(val){ // 刪除成功
return new SuccessModel()
} else {
return new ErrorModel('刪除博客失敗')
}
})
}
}
module.exports = handleBlogRouter
~~~
2. **用戶路由文件**
**blog-1/src/router/user.js**
~~~
// 從 controller 中獲取數據
const { login } = require('../controller/user')
// 引入數據模型
const { SuccessModel, ErrorModel } = require('../model/resModel')
const handleUserRouter = (req, res) => {
const method = req.method // GET POST
// 登陸
if(method === 'POST' && req.path === '/api/user/login'){
const { username, password } = req.body
const result = login(username, password)
return result.then(data => {
if(data.username){ // 登陸成功
return new SuccessModel()
} else {
return new ErrorModel('登陸失敗')
}
})
}
}
module.exports = handleUserRouter
~~~
>[success] ## app.js文件(處理數據后返回給 前端)
**blog-1/app.js**
~~~
const querystring = require('querystring')
// 引入處理路由文件
const handleBlogRouter = require('./src/router/blog')
const handleUserRouter = require('./src/router/user')
// 用于處理 post data
const getPostData = (req) => {
const promise = new Promise((resolve, reject) => {
if(req.method !== 'POST'){ // 不等于 post 請求
resolve({})
return
}
if(req.headers['content-type'] !== 'application/json'){ // 傳入的數據格式不是 application/json ,可能是form-data的參數
resolve({})
return
}
// 1. POST通過數據流方式接收數據
let postData = ''
// 2. 給req注冊data事件,當有數據提交過來就會觸發,事件的作用是接收數據,接收大量數據的時候,是分塊接收的
req.on('data', chunk => {
postData += chunk.toString()
})
// 3. 給req注冊end事件,當數據全部接收完畢,會觸發
req.on('end', () => {
if(!postData){ // 無數據返回空對象
resolve({})
return
}
resolve(
JSON.parse(postData)
)
})
})
return promise
}
const serverHandle = (req, res) => {
// 設置返回格式 JSON
res.setHeader('Content-type', 'application/json')
// 獲取 path
const url = req.url
req.path = url.split('?')[0]
// 解析query 參數
req.query = querystring.parse(url.split('?')[1])
// 處理 post data 參數
getPostData(req).then(postData => {
req.body = postData
// 處理 blog 路由
const blogResult = handleBlogRouter(req, res)
if(blogResult){
blogResult.then(blogData => {
res.end(
JSON.stringify(blogData)
)
})
return // 這里需要return,不然返回數據后還會往下走
}
// 處理 user 路由
const userResult = handleUserRouter(req, res)
if(userResult){
userResult.then(userData => {
res.end(
JSON.stringify(userData)
)
})
return
}
// 未命中路由,返回 404
res.writeHead(404, {"Content-type": "text/plain"}) // 把響應頭狀態碼設置為404,然后Content-type: text/plain是純文本,為了覆蓋上面的json類型
// 返回內容
res.write('404 Not Found\n')
res.end()
})
}
module.exports = serverHandle
~~~
- NodeJS基礎
- 什么是NodeJS
- npm
- Node.js+Express+Koa2+開發Web Server博客
- 下載和安裝node
- nodejs和js的區別
- commonjs-演示
- nodejs如何debugger
- server端與前端的區別
- 項目需求分析
- 開發接口(不使用任何框架)
- http-概述
- 處理get請求
- 處理post請求
- 處理http請求的綜合示例
- 搭建開發環境
- 初始化并且開發路由
- 開發博客項目之數據存儲
- MySql介紹
- 數據庫操作(創建和增、刪、查)
- Nodejs 操作 Mysql
- Nodejs 鏈接 mysql 做成工具
- API 對接 MySQL
- 開發博客項目之登陸
- cookie-介紹
- cookie用于登錄驗證
- cookie做限制