今天看到json-parser,正好想复习一下node的知识,做了个实现。
用到的包就两个,express和body-parser。
package.json
{
"name": "json-server2",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.19.0",
"express": "^4.17.1"
}
}
db.json
其中的每一个key为url的路径,value为返回值。
{
"posts": [
{
"id": 1,
"title": "json-server",
"author": "typicode"
},
{
"id": 2,
"title": "json-server2",
"author": "typicode2"
}
],
"comments": [
{
"id": 1,
"body": "some comment",
"postId": 1
}
],
"profile": {
"name": "typicode"
}
}
index.js
入口文件
const express = require('express');
const {dbJson} = require('./fileOperate');
const home = 'http://localhost:3000/';
const bodyParser = require('body-parser');
const {homePageHandler,restlessHandler,getRestful,postRestful,putRestful,deleteRestful} = require("./appHandler");
const app = express();
/**
* 设置bodyParser
*/
app.use(bodyParser.json({limit:'1mb'}));
app.use(bodyParser.urlencoded({extend:true}));
/**
* 设置全局跨域响应头
*/
app.all('*',function(req,res,next){
res.header('Access-Control-Allow-Origin', '*');//的允许所有域名的端口请求(跨域解决)
res.header('Access-Control-Allow-Headers', 'Content-Type');
res.header('Access-Control-Allow-Methods', '*');
next();
});
/**
* 遍历json数据生成对应风格的接口
*/
Object.entries(dbJson).forEach(entry => {
let key = entry[0];
let targetArr = entry[1];
console.log(home+key);
/**
* 普通风格get
*/
app.get('/'+key,(req,res) => {
restlessHandler(req,res,targetArr);
});
/**
* rest风格get
*/
app.get('/'+key+'/:id',(req,res) => {
getRestful(req,res,targetArr);
});
/**
* rest风格post
*/
app.post('/'+key,(req,res)=>{
postRestful(req,res,targetArr);
});
/**
* rest风格post
*/
app.put('/'+key+'/:id',(req,res)=>{
putRestful(req,res,targetArr);
});
/**
* rest风格delete
*/
app.delete('/'+key+'/:id',(req,res)=>{
deleteRestful(req,res,targetArr);
});
});
console.log('Resources');
//请求主页
app.get('/',(req,res) => {
homePageHandler(req,res);
});
//主页请求数据
app.get('/data',(req,res) => {
res.json(dbJson);
});
//默认监听3000端口
app.listen(3000,()=>{
console.log('\nHome');
console.log(home);
});
appHandler.js
处理各种请求
const { writeToDb,readHomePage,dbJson} = require('./fileOperate');
/**
* 根据id查找对象
* @param arr
* @param resp
* @param id
*/
function getResponseObjById(arr,resp,id) {
const obj = arr.find(o => o.id === id);
if(obj) {
resp.send(obj);
}else {
resp.status(500).send('没找着呢亲,再看一眼db.json');
}
}
/**
* 主页处理
* @param req
* @param res
*/
function homePageHandler(req,res) {
res.set({'Content-Type':'text/html'});
const content = readHomePage();
res.send(content);
}
/**
* 普通风格get处理
* @param req
* @param res
* @param targetArr
*/
function restlessHandler(req,res,targetArr) {
if(req.query.id) {
getResponseObjById(targetArr,res,parseInt(req.query.id));
}else {
res.json(targetArr);
}
}
/**
* get风格处理
* @param req
* @param res
* @param targetArr
*/
function getRestful(req,res,targetArr) {
getResponseObjById(targetArr,res,parseInt(req.params.id));
}
/**
* post风格处理
* @param req
* @param res
* @param targetArr
*/
function postRestful(req,res,targetArr) {
//找到数组最后一个对象
let lastObj = targetArr[targetArr.length -1];
//请求参数对象
const obj = req.body;
//id +1
obj.id = lastObj.id+1;
//新增对象
targetArr.push(obj);
writeToDb(dbJson);
res.json(obj);
}
/**
* put风格处理
* @param req
* @param res
* @param targetArr
*/
function putRestful(req,res,targetArr) {
//从url参数中获取id
const id = parseInt(req.params.id);
//根据id找到对应的对象
let targetObj = targetArr.find(item => item.id === id);
if(targetObj) {
Object.keys(req.body).forEach(objKey => {
//更新属性值
targetObj[objKey] = req.body[objKey];
});
writeToDb(dbJson);
res.json(targetObj);
}else {
res.send('没有找到id为'+id+'的对象');
}
}
/**
* delete风格处理
* @param req
* @param res
* @param targetArr
*/
function deleteRestful(req,res,targetArr) {
//从url参数中获取id
const id = parseInt(req.params.id);
//根据id找到对应的对象索引值
let index = targetArr.findIndex(item => item.id === id);
if(index === -1) {
res.send('不存在的哦');
}else {
//删除对象
targetArr.splice(index,1);
writeToDb(dbJson);
res.json({});
}
}
module.exports = {homePageHandler,restlessHandler,getRestful,postRestful,putRestful,deleteRestful};
fileOperate.js
封装各种文件操作
const fs = require('fs');
/**
* 从db文件中读取json数据
* @returns {object}
*/
function readFromDb() {
let buffer = fs.readFileSync('./db.json','utf-8');
return JSON.parse(buffer.toString());
}
/**
* 将json数据写入到db文件中
* @param jsonData
*/
function writeToDb(jsonData) {
fs.writeFileSync('./db.json',
JSON.stringify(jsonData,null,'\t'));
}
/**
* 读取主页
* @returns {string}
*/
function readHomePage() {
let buffer = fs.readFileSync('./index.html');
return buffer.toString();
}
module.exports = {dbJson: readFromDb(), writeToDb,readHomePage};
index.html
默认主页
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="urls">
<h1>Resources</h1>
</div>
<script>
(function() {
let home = 'http://localhost:3000/';
let urls = document.querySelector('#urls');
fetch(home+'data').then(res=> {
return res.json();
}).then(dbObj => {
console.log(dbObj);
Object.entries(dbObj).forEach(entry => {
let divElement = document.createElement('div');
let aElement = document.createElement('a');
aElement.setAttribute('href',home+entry[0]);
aElement.textContent = '/'+entry[0];
divElement.appendChild(aElement);
urls.appendChild(divElement);
})
})
})();
</script>
</body>
</html>
demo.html
axios测试页
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Axios测试页面</title>
</head>
<body>
<div>
<button onclick="testGet()">GET请求</button>
<button onclick="testPost()">POST请求</button>
<button onclick="testPut()">PUT请求</button>
<button onclick="testDelete()">DELETE请求</button>
</div>
<script src="https://cdn.bootcss.com/axios/0.19.0/axios.js"></script>
<script>
function testGet() {
axios.get('http://localhost:3000/posts?id=1').then(response=> {
console.log('/posts get',response.data);
})
}
function testPost() {
axios.post('http://localhost:3000/posts',{"title": "json-server3", "author": "typicode3" }).then(response=> {
console.log('/posts post',response.data);
})
}
function testPut() {
axios.put('http://localhost:3000/posts/3',{"title": "json-server...", "author": "typicode..." }).then(response=> {
console.log('/posts put',response.data);
})
}
function testDelete() {
axios.delete('http://localhost:3000/posts/3').then(response=> {
console.log('/posts delete',response.data);
})
}
</script>
</body>
</html>
启动时控制台输出
主页显示
axios测试页
请求做过跨域处理,所以这个页面可以单独打开,不要求同源