数据持久化采用文件保存或mysql数据库两种方式
一、项目初始化
1、创建mybook文件夹
2、创建入口文件index.js
3、初始化项目生成package.json
npm init -y
4、安装依赖
npm install express art-template express-art-template body-parser --save
5、编辑入口文件 index.js
1)定义依赖
/**
图书管理系统入口文件
*/
const express = require('express');
const router = require('./router.js');
2)创建app对象
const app = express();
3)启动服务器,配置路由
// 启动服务器功能
// 配置路由
app.use(router);
4)监听端口
// 监听端口
app.listen(3000,()=>{
console.log('running...');
});
6、创建路由文件router.js
/*
路由模块
*/
const express = require('express');
const router = express.Router();
// 路由处理
// 渲染主页
router.get('/',(req,res)=>{
console.log('主页');
res.send('主页');
});
// 添加图书(跳转到添加图书的页面)
router.get('/addBook',(req,res)=>{
console.log('添加图书');
res.send('添加图书');
});
// 编辑图书(跳转到编辑图书信息页面)
router.get('/editBook',(req,res)=>{
console.log('编辑图书');
res.send('编辑图书');
});
module.exports = router;
7、测试
1)启动服务
node .
2)访问定义的路由
http://localhost:3000
http://localhost:3000/addBook
http://localhost:3000/editBook
二、添加模板引擎
1、引入模板引擎
1)定义依赖
在index.js中添加依赖
const template = require('art-template');
const path = require('path');
2)设置模板引擎
在index.js中添加
// 设置模板的路径
app.set('views',path.join(__dirname,'views'));
// 设置模板引擎
app.set('view engine','art');
// 使express兼容art-template模板引擎
app.engine('art', require('express-art-template'));
2、创建模板文件
1)创建views文件夹
2)创建文件views/index.art
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>图书管理系统</title>
</head>
<body>
<div>图书管理系统<a href="/addBook">添加图书</a></div>
<div>
<table cellpadding="0" cellspacing="0">
<thead>
<tr>
<th>编号</th>
<th>名称</th>
<th>作者</th>
<th>分类</th>
<th>描述</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>西游记</td>
<td>吴承恩</td>
<td>文学</td>
<td>佛教与道教的斗争</td>
<td><a href="#">修改</a>|<a href="#">删除</a></td>
</tr>
<tr>
<td>1</td>
<td>西游记</td>
<td>吴承恩</td>
<td>文学</td>
<td>佛教与道教的斗争</td>
<td><a href="#">修改</a>|<a href="#">删除</a></td>
</tr>
<tr>
<td>1</td>
<td>西游记</td>
<td>吴承恩</td>
<td>文学</td>
<td>佛教与道教的斗争</td>
<td><a href="#">修改</a>|<a href="#">删除</a></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
3)创建文件views/addBook.art
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>图书管理系统-添加图书</title>
</head>
<body>
<div>添加图书</div>
<form action="/saveBook" method="post">
名称:<input type="text" name="name"><br>
作者:<input type="text" name="author"><br>
分类:<input type="text" name="category"><br>
描述:<input type="text" name="description"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
4)创建文件views/editBook.art
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>图书管理系统-修改图书</title>
</head>
<body>
<div>修改图书</div>
<form action="/updateBook" method="post">
<input type="hidden" name="id" >
名称:<input type="text" name="name" ><br>
作者:<input type="text" name="author" ><br>
分类:<input type="text" name="category" ><br>
描述:<input type="text" name="description" ><br>
<input type="submit" value="提交">
</form>
</body>
</html>
3、调用模板
修改router.js
// 路由处理
// 渲染主页
router.get('/',(req,res)=>{
...
res.render('index');
});
// 添加图书(跳转到添加图书的页面)
router.get('/addBook',(req,res)=>{
...
res.render('addBook');
});
// 编辑图书(跳转到编辑图书信息页面)
router.get('/editBook',(req,res)=>{
...
res.render('editBook');
});
三、处理数据
1、数据列表
1)创建json数据文件data.json
[
{
"id": "1",
"name": "三国演义",
"author": "罗贯中",
"category": "文学",
"desc": "一个杀伐纷争的年代"
},
{
"id": "2",
"name": "水浒传",
"author": "施耐庵",
"category": "文学",
"desc": "108条好汉的故事"
},
{
"id": "3",
"name": "西游记",
"author": "吴承恩",
"category": "文学",
"desc": "佛教与道教的斗争"
},
{
"id": "4",
"name": "红楼梦",
"author": "曹雪芹",
"category": "文学",
"desc": "一个封建王朝的缩影"
},
{
"name": "天龙八部",
"author": "金庸",
"category": "文学",
"desc": "武侠小说",
"id": 5
}
]
2)router中引用json
const data = require('./data.json');
// 路由处理
// 渲染主页
router.get('/',(req,res)=>{
...
res.render('index', {list : data});
});
3)模板中显示数据
修改index.art
<tbody>
{{each list}}
<tr>
<td>{{$value.id}}</td>
<td>{{$value.name}}</td>
<td>{{$value.author}}</td>
<td>{{$value.category}}</td>
<td>{{$value.desc}}</td>
<td>
<a href="#">修改</a>|
<a href="#">删除</a>
</td>
</tr>
{{/each}}
</tbody>
4)重启服务测试
http://localhost:3000/
2、删除数据
1)修改index.art
<a href="/deleteBook?id={{$value.id}}">删除</a>
2)router中添加删除路由
// 删除图书
router.get('/deleteBook',(req,res)=>{
console.log('删除图书');
let id = req.query.id;
data.forEach((item,index)=>{
if(id == item.id){
// 删除数组的一项数据
data.splice(index,1);
}
});
res.redirect('/');//页面跳转
});
3)测试
3、保存数据
1)index.js中定义依赖
const bodyParser = require('body-parser');
2)引入参数处理中间件
在index.js中启动服务的代码之前添加,这里要加在开头位置。
//挂载参数处理中间件(处理post表单)
// create application/x-www-form-urlencoded parser
app.use(bodyParser.urlencoded({extended: false}));
3)router中添加保存路由和辅助方法
// 自动生成图书编号(自增)
let maxBookCode = ()=>{
let arr = [];
data.forEach((item)=>{
arr.push(item.id);
});
return Math.max.apply(null,arr);
};
// 保存图书(提交表单)
router.post('/saveBook',(req,res)=>{
console.log('添加图书(提交表单)');
let info = req.body;
console.log(info);
let book = {};
for(let key in info){
book[key] = info[key];
}
book.id = maxBookCode() + 1;
data.push(book);
res.redirect('/');//页面跳转
});
4)测试
4、根据id查询数据
1)修改index.art
<a href="/editBook?id={{$value.id}}">修改</a>
2)router中修改编辑图书的路由
// 编辑图书(跳转到编辑图书信息页面)
router.get('/editBook',(req,res)=>{
console.log('编辑图书');
// res.send('编辑图书');
let id = req.query.id;
let book = {};
data.forEach((item)=>{
if(id == item.id){
book = item;
}
});
res.render('editBook',book);
});
3)修改editBook.art页面
<form action="/updateBook" method="post">
<input type="hidden" name="id" value="{{id}}">
名称:<input type="text" name="name" value="{{name}}"><br>
作者:<input type="text" name="author" value="{{author}}"><br>
分类:<input type="text" name="category" value="{{category}}"><br>
描述:<input type="text" name="description" value="{{description}}"><br>
<input type="submit" value="提交">
</form>
4)测试
5、更新数据
1)router中添加更新路由
// 编辑图书(提交表单)
router.post('/updateBook',(req,res)=>{
console.log('编辑图书提交表单');
let info = req.body;
data.forEach((item)=>{
if(info.id == item.id){
for(let key in info){
item[key] = info[key];
}
}
});
res.redirect('/');//页面跳转
});
2)测试
四、创建服务层
1、数据列表
1)创建service.js文件
将对json数据的引入和辅助方法的定义从router.js中移植到service.js中
/*
业务模块
*/
const data = require('./data.json');
// 自动生成图书编号(自增)
let maxBookCode = ()=>{
let arr = [];
data.forEach((item)=>{
arr.push(item.id);
});
return Math.max.apply(null,arr);
};
2)在service中定义页面显示业务
// 渲染主页面
exports.showIndex = (req,res)=>{
console.log('主页');
res.render('index', {list : data});
};
// 添加图书
exports.addBook = (req,res)=>{
console.log('添加图书');
res.render('addBook');
};
3)router中引入service模块
const service = require('./service.js');
4)调用service模块中的方法
为了避免错误,先屏蔽其他的相关路由(除"/addBook"之外)
// 路由处理
// 渲染主页
router.get('/', service.showIndex);
// 添加图书(跳转到添加图书的页面)
router.get('/addBook', service.addBook);
2、编辑图书
1)在service中定义根据id查询指定图书的方法
// 编辑图书
exports.editBook = (req,res)=>{
console.log('编辑图书');
// res.send('编辑图书');
let id = req.query.id;
let book = {};
data.forEach((item)=>{
if(id == item.id){
book = item;
}
});
res.render('editBook',book);
};
2)修改router中的编辑图书的路由
// 编辑图书(跳转到编辑图书信息页面)
router.get('/editBook', service.editBook);
3、删除图书
1)在service中定义根据id删除指定图书的方法
// 删除图书
exports.deleteBook = (req,res)=>{
console.log('删除图书');
let id = req.query.id;
data.forEach((item,index)=>{
if(id == item.id){
// 删除数组的一项数据
data.splice(index,1);
}
});
res.redirect('/');//页面跳转
};
2)修改router中的删除图书的路由
// 删除图书
router.get('/deleteBook', service.deleteBook);
4、保存图书
1)在service中定义保存图书的方法
// 保存图书
exports.saveBook = (req,res)=>{
console.log('添加图书(提交表单)');
let info = req.body;
console.log(info);
let book = {};
for(let key in info){
book[key] = info[key];
}
book.id = maxBookCode() + 1;
data.push(book);
res.redirect('/');//页面跳转
};
2)修改router中的保存图书的路由
// 保存图书(提交表单)
router.post('/saveBook', service.saveBook);
5、更新图书
1)在service中定义根据id更新指定图书的方法
// 编辑图书
exports.updateBook = (req,res)=>{
console.log('编辑图书提交表单');
let info = req.body;
data.forEach((item)=>{
if(info.id == item.id){
for(let key in info){
item[key] = info[key];
}
}
});
res.redirect('/');//页面跳转
};
2)修改router中的更新图书的路由
// 编辑图书(提交表单)
router.post('/updateBook', service.updateBook);
五、将数据持久化到json文件中
1、修改service
1)添加文件相关依赖
在service.js中添加
const path = require('path');
const fs = require('fs');
2)将数据写入json
在service.js中添加writeDataToFile方法,
// 把内存数据写入文件
let writeDataToFile = (res) => {
// (data,null,4):保证数据存入的时候有换行缩进的格式
fs.writeFile(path.join(__dirname,'data.json'),JSON.stringify(data,null,4),(err)=>{
if(err){
return false; // 文件写入失败
}
return true; // 文件写入成功
});
};
3)调用写入文件的方法
在删除、保存、更新的业务方法中分别调用
writeDataToFile();
六、将数据持久化到MySQL数据中
1、初始化MySQL数据库和表
1)创建MySQL数据库 nodejs_book
CREATE DATABASE nodejs_book CHARACTER SET utf8 COLLATE utf8_general_ci;
2)创建数据库表 book
CREATE TABLE `book` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255),
`author` varchar(255),
`category` varchar(255),
`description` varchar(255),
PRIMARY KEY (`id`)
);
3)执行MySQL脚本插入数据
insert into book (name,author,category,description) values ('三国演义','罗贯中','文学','一个杀伐纷争的年代');
insert into book (name,author,category,description) values ('水浒传','施耐庵','文学','108条好汉的故事');
insert into book (name,author,category,description) values ('西游记','吴承恩','文学','佛教与道教的斗争');
insert into book (name,author,category,description) values ('红楼梦','曹雪芹','文学','一个封建王朝的缩影');
insert into book (name,author,category,description) values ('天龙八部','金庸','文学','武侠小说');
2、引入mysql模块
1)安装模块
npm install mysql --save
2)创建db.config.js文件
//配置链接数据库参数
module.exports = {
host : 'localhost',
port : 3306,
database : 'nodejs_book',
user : 'root',
password : '123456'
};
3)定义通用的db.js
/*
定义数据库query函数
*/
var mysql = require('mysql');
var databaseConfig = require('./db.config.js'); //引入数据库配置模块中的数据
//向外暴露方法
module.exports = {
base : (sql,params,callback) => {
// 创建数据库连接
const connection = mysql.createConnection(databaseConfig);
// 执行连接操作
connection.connect();
// 操作数据库(数据库操作也是异步的)
connection.query(sql,params, function(error, results, fields) {
if (error) throw error;
callback(results);
});
// 关闭数据库
connection.end();
}
};
3、修改service
1)在service中引用db模块
const db = require('./db.js');
2)主页列表
// 渲染主页面
exports.showIndex = (req,res)=>{
console.log('主页');
let sql = 'select * from book';
db.base(sql,null,(result)=>{
res.render('index',{list : result});
});
};
3)编辑图书(根据id选择)
// 编辑图书
exports.editBook = (req,res)=>{
console.log('编辑图书');
// res.send('编辑图书');
let id = req.query.id;
let sql = 'select * from book where id=?';
let data = [id];
db.base(sql,data,(result)=>{
res.render('editBook',result[0]);
});
};
4)删除图书
// 删除图书
exports.deleteBook = (req,res)=>{
console.log('删除图书');
let id = req.query.id;
let sql = 'delete from book where id=?';
let data = [id];
db.base(sql,data,(result)=>{
if(result.affectedRows == 1){
res.redirect('/');
}
});
};
5)保存图书
exports.saveBook = (req,res)=>{
console.log('添加图书(提交表单)');
let info = req.body;
let book = {};
for(let key in info){
book[key] = info[key];
}
let sql = 'insert into book set ?';
db.base(sql,book,(result)=>{
if(result.affectedRows == 1){
res.redirect('/');
}
});
};
6)更新图书
exports.updateBook = (req,res)=>{
console.log('编辑图书提交表单');
let info = req.body;
let sql = 'update book set name=?,author=?,category=?,description=? where id=?';
let data = [info.name,info.author,info.category,info.description,info.id];
db.base(sql,data,(result)=>{
if(result.affectedRows == 1){
res.redirect('/');
}
});
};