1、注册页面
const express = require('express');
const router = express.Router();
const users=[
{username:'zhangsan',password:123},
{username:'lisi',password:456},
]
/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
//设置二级路由
//登录路由
router.post('/login', function(req, res, next) {
console.log('登录的数据----',req.body)
//1、接收前端发送的数据
//post:req.body
//get: req.query
const result=users.some(function(item,index){
return item.username==req.body.username && item.password==req.body.password
})
if (result){
res.send({
message:'登录成功',
status:1
})
}else {
res.send({
message:'登录失败',
status:0
})
}
});
//注册路由
router.post('/register', function(req, res, next) {
const user=req.body
users.push(user)
console.log(users)
res.send('respond with a resource,成功进入到注册接口');
});
module.exports = router;
2、获取学生信息
1、app.js
配置获取学生信息一级路由
const studentsRouter=require('./routes/students')
app.use('/students', studentsRouter);
2、routes/students.js
获取学生信息二级路由
var express = require('express');
var router = express.Router();
const students=[
{name:'zhangsan',age:'20',gender:'male'},
{name:'lisi',age:'17',gender:'female'},
{name:'wangwu',age:'19',gender:'male'}
]
/* GET home page. */
router.get('/getStudents', function(req, res, next) {
res.send({
message:'获取学生信息成功',
status:1,
data:students
})
});
module.exports = router;
3、public/index.html
获取学生信息html页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>学生管理系统</title>
</head>
<body>
<h2>学生列表</h2>
<table>
<thead>
<tr>
<th>学生姓名</th>
<th>学生年龄</th>
<th>学生性别</th>
<th>学生操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>张三</td>
<td>20</td>
<td>男</td>
<td>
<button>修改 | 删除</button>
</td>
</tr>
</tbody>
</table>
<script src="./javascripts/jquery.min.js"></script>
<script>
getStudents()
function getStudents(){
$.ajax({
url:'/students/getStudents',
data:{},
type:'GET',
success({message,status,data }){
//进入if表示进入学生数据成功
if(status){
const str=data.map(function (item,index) {
return `
<tr>
<td>${item.name}</td>
<td>${item.age}</td>
<td>${item.gender}</td>
<td>
<button>修改 | 删除</button>
</td>
</tr>
`
}).join('')//join是拼接
$('tbody').html(str)
// let str=''
// data.forEach(item=>{
// str+=`
// <tr>
// <td>${item.name}</td>
// <td>${item.age}</td>
// <td>${item.gender}</td>
// <td>
// <button>修改 | 删除</button>
// </td>
// </tr>
// `
// })
// $('tbody').html(str)
// console.log(str)
}
}
})
}
</script>
</body>
</html>
3、删除学生信息
前端index.html
1、index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>学生管理系统</title>
</head>
<body>
<h2>学生列表</h2>
<table>
<thead>
<tr>
<th>学生姓名</th>
<th>学生年龄</th>
<th>学生性别</th>
<th>学生操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>张三</td>
<td>20</td>
<td>男</td>
<td>
<button>修改 | 删除</button>
</td>
</tr>
</tbody>
</table>
<script src="./javascripts/jquery.min.js"></script>
<script>
getStudents()
function getStudents(){
$.ajax({
url:'/students/getStudents',
data:{},
type:'GET',
success({message,status,data }){
//进入if表示进入学生数据成功
if(status){
const str=data.map(function (item,index) {
return `
<tr>
<td>${item.name}</td>
<td>${item.age}</td>
<td>${item.gender}</td>
<td>
<button>修改</button>
<button class="removeBtn" data-id="${item._id}">删除</button>
</td>
</tr>
`
}).join('')//join是拼接
$('tbody').html(str)
// let str=''
// data.forEach(item=>{
// str+=`
// <tr>
// <td>${item.name}</td>
// <td>${item.age}</td>
// <td>${item.gender}</td>
// <td>
// <button>修改 | 删除</button>
// </td>
// </tr>
// `
// })
// $('tbody').html(str)
// console.log(str)
}
}
})
}
//删除按钮使用事件委托
$('tbody').on('click','.removeBtn',function(){//on做委托,委托给父级的静态元素,第一个参数是时间,第二个参数是真正执行的那个标签(委托人),第三个参数是具体的工作
//获取当前点击的这个按钮对应的id,data('id')是获取所有(特定)属性的函数,这里的id实际就是data-id,前面加data-是一种约定俗成
const _id=$(this).data('id')
console.log(_id)
$.ajax({
url:'/students/deleteStudents',
type:'post',
data: { _id },
success (msg) {
if (msg.status){
alert('删除成功')
//重新发一次ajax请求
getStudents()
}
}
})
})
</script>
</body>
</html>
后端代码
2、students.js
var express = require('express');
var router = express.Router();
let students=[
{_id:1,name:'zhangsan',age:'20',gender:'male'},
{_id:2,name:'lisi',age:'17',gender:'female'},
{_id:3,name:'wangwu',age:'19',gender:'male'}
]
/* GET home page. */
router.get('/getStudents', function(req, res, next) {
res.send({
message:'获取学生信息成功',
status:1,
data:students
})
});
//删除学生
router.post('/deleteStudents', function(req, res, next) {
console.log(req.body)
students=students.filter(function (item,index) {
return item._id!=req.body._id//把id不相等的元素筛选出来组成新的数组
})
res.send({
message:'删除学生信息成功',
status:1,
})
});
module.exports = router;
4、通过后端代码操作mongo数据库–mongoose
mongoose是nodejs中提供的一个用于边界操作MongoDb的库
安装:
npm install mongoose --save
5、连接mongoDB连接
项目一运行就要去连接数据库,所以把代码写在app.js里
项目数据库为:
数据库名:web06
集合:students,teachers
//连接mongode
const mongoose = require('mongoose')
const dbURL = 'mongodb://localhost:27017/web06'//项目需要连接的mongobd数据库的地址
mongoose.connect(dbURL)
//mongoose事件,当数据路连接(conncet)事件发生的时候去做指定的函数逻辑
mongoose.connection.on('connect', function () {})
console.log(dbURL+'数据库连接成功')
部分情况下可能要求在connect里面额外提供两个属性
mongoose.connect(dbURL,{useNewUrlParser:true,useUnifiedTopology:true })
6、操作集合(数据库表)
以下代码,每操作一类集合(数据库表)都要设置一次,也就是要针对数据库里的每个集合做一次配置
//数据集合的相关配置
//1、定义数据集合的结构:定义集合中数据有哪些属性,属性的值是什么类型(数据库结构)
//解构出mongoose的Schema方法来,这个方法用来操作集合的
const { Schema,model }=require('mongoose')
//通过构造函数创建集合的结构
const usersSchema=new Schema({
username:String,
password:String
})
//2、定义数据集合的模型:将schema和数据库中的集合关联起来
//model需要三个参数:模型名称,schema名称,数据库中的集合名称
const usersModel=model('userModel',usersSchema,'users')
7、登录数据库版
后端app.js里设置数据库连接(因为项目一打开就要连接数据库)
1、app.js
//连接mongode
const mongoose = require('mongoose')
const dbURL = 'mongodb://localhost:27017/studentsSystem'//项目需要连接的mongobd数据库的地址
mongoose.connect(dbURL,{useNewUrlParser:true,useUnifiedTopology:true })
//mongoose事件,当数据路连接(conncet)事件发生的时候去做指定的函数逻辑
mongoose.connection.on('connect', function () {})
console.log(dbURL+'数据库连接成功')
2、后端要设置schema来操作数据库表(集合)
//数据集合的相关配置
//1、定义数据集合的结构:定义集合中数据有哪些属性,属性的值是什么类型(数据库结构)
//解构出mongoose的Schema方法来,这个方法用来操作集合的
const { Schema,model }=require('mongoose')
//通过构造函数创建集合的结构
const usersSchema=new Schema({
username:String,
password:String
})
//2、定义数据集合的模型:将schema和数据库中的集合关联起来
//model需要三个参数:模型名称,schema名称,数据库中的集合名称
const usersModel=model('userModel',usersSchema,'users')
//登录路由数据库版本
router.post('/login', async function(req, res, next) {
//接受到前端发送的用户数据
const user=req.body
const result=await usersModel.find(user)//find 是异步操作,在model里查找user记录(文档)。返回一个数组
//直接以数组长度来判断是否返回了数据,如果数组长度大于零,则说明返回了数据
if(result.length>0){
res.send({
message:'登录成功',
status:1
})
}else{
res.send({
message:'登录失败',
status:0
})
}
})
8、mongoose操作数据库流程
1、连接数据库
将express项目与mongodb服务器中的数据库连接起来,
参见上例app.js的设置部分
//连接mongode
const mongoose = require('mongoose')
const dbURL = 'mongodb://localhost:27017/studentsSystem'//项目需要连接的mongobd数据库的地址
mongoose.connect(dbURL,{useNewUrlParser:true,useUnifiedTopology:true })
//mongoose事件,当数据路连接(conncet)事件发生的时候去做指定的函数逻辑
mongoose.connection.on('connect', function () {})
console.log(dbURL+'数据库连接成功')
2、配置集合
当数据库连接成功之后,就可以操作数据库中的集合了
但,在首次操作之前,需要对要操作的集合进行相关的配置。
- 配置集合结构:定义出集合中数据有哪些属性,每个属性的值是什么数据类型
//数据集合的相关配置
//1、定义数据集合的结构:定义集合中数据有哪些属性,属性的值是什么类型(数据库结构)
//解构出mongoose的Schema方法来,这个方法用来操作集合的
const { Schema,model }=require('mongoose')
//通过构造函数创建集合的结构
const usersSchema=new Schema({
username:String,
password:String
})
- 配置集合模型:将上一步的schema结合结构和数据中的集合给管理起来,得到一个数据模型。
- 所有关于数据集合中输出操作的方法,都是模型提供的方法
//2、定义数据集合的模型:将schema和数据库中的集合关联起来
//model需要三个参数:模型名称,schema名称,数据库中的集合名称
const { Schema,model }=require('mongoose')
const usersModel=model('userModel',usersSchema,'users')
3、操作数据
- 查询、查找
按条件查找
const user=req.body
const result=await usersModel.find(user)//find 是异步操作,在model里查找user记录(文档)。返回一个数组
查询所有数据
usersModel.find()
新增数据
usersModel.creat({数据})
删除数据
usersModel.deleteOne({数据})
删除多个数据
usersModel.deleteMany({username:'zhangsan'})
修改数据
接收两个参数,一个条件,一个是修改后的数据
usersModel.updateOne({_id:1},{username:'lisi',password:'125'})
注意,以上所有的方法都是异步方法,且这些方法的返回值都是Promise对象,需要用await去等待操作结果
//登录路由数据库版本
router.post('/login', async function(req, res, next) {
//接受到前端发送的用户数据
const user=req.body
const result=await usersModel.find(user)//find 是异步操作,在model里查找user记录(文档)。返回一个数组
//直接以数组长度来判断是否返回了数据,如果数组长度大于零,则说明返回了数据
if(result.length>0){
res.send({
message:'登录成功',
status:1
})
}else{
res.send({
message:'登录失败',
status:0
})
}
})
9、三层架构
三层:表现层,服务层,持久成
最少三个文件夹
数据首先从表现层–>服务层–>持久层进行传递,也就是说从表现层提交表单数据,在服务层进行处理,在持久层存入数据库,进行了数据库操作之后,如查询,数据将从持久层–>服务层–>表现层进行传递。
10、三层架构改造登录代码
三个文件夹:
表现层:routers
服务层:service
持久层:dao(数据库访问接口)
- 1、在表现层创建routers文件夹,创建对应的users路由:
users.js
const express = require('express');
const router = express.Router();
//模拟数据库
const users=[
{username:'zhangsan',password:123},
{username:'lisi',password:456},
]
//引入服务层的方法
const {login}=require('../service/usersServices')
//登录路由数据库版本
router.post('/login', async function(req, res, next) {
//接受到前端发送的用户数据
const user=req.body
const data=await login(user)
res.send(data)
})
/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
//设置二级路由
//登录路由
// router.post('/login', function(req, res, next) {
// console.log('登录的数据----',req.body)
//
// //1、接收前端发送的数据
// //post:req.body
// //get: req.query
// const result=users.some(function(item,index){
// return item.username==req.body.username && item.password==req.body.password
// })
// if (result){
// res.send({
// message:'登录成功',
// status:1
// })
// }else {
// res.send({
// message:'登录失败',
// status:0
// })
// }
// });
//注册路由
router.post('/register', function(req, res, next) {
const user=req.body
users.push(user)
//console.log(users)
res.send({message:'注册成功',status:1});
});
//验证用户名是否存在路由
router.post('/isAccess', function(req, res, next) {
const { username }=req.body
const result=users.some(function(item,index){
return item.username==username
})
if (result){
res.send({message:'用户名已存在,不可以注册',status:0});
}else{
res.send({message:'用户名不存在,可以注册',status:1});
}
});
module.exports = router;
- 2、表现层
在服务层创建对应路由的服务文件如userServices.js
在服务层需要导入第三层持久层(dao)层的内容,并将从持久层获得的数据(data)返回给第一层表现层
userServices.js
const {login}=require('../dao/usersDao')
//在第二层服务层暴露一个属性login给第一层(表现层),并从第一层接收一个数据user到第二层
module.exports.login= async function (user) {
//调用第三层(dao层)的login,数据从第二次(服务层)传递到了第三层(dao)层
const data=await login(user)
//console.log('第二层的data',data)
if(data.length>0){
//服务层不发送res,所以要将所发送的信息返回给表现层
return {
message:'登录成功',
status:1
}
}else{
return {
message:'登录失败',
status:0
}
}
}
- 2、持久层(dao)
持久层由三部分组成
·纯数据库连接,
·数据库模型
·数据库操作逻辑
2.1数据库连接:database.js
//连接mongode
const mongoose = require('mongoose')
const dbURL = 'mongodb://localhost:27017/studentsSystem'//项目需要连接的mongobd数据库的地址
mongoose.connect(dbURL,{useNewUrlParser:true,useUnifiedTopology:true })
//mongoose事件,当数据路连接(conncet)事件发生的时候去做指定的函数逻辑
mongoose.connection.on('connect', function () {
console.log(dbURL+'数据库连接成功')
})
2.2数据库模型:userModels.js
//数据集合的相关配置
//1、定义数据集合的结构:定义集合中数据有哪些属性,属性的值是什么类型(数据库结构)
//解构出mongoose的Schema方法来,这个方法用来操作集合的
const { Schema,model }=require('mongoose')
//通过构造函数创建集合的结构
const usersSchema=new Schema({
username:String,
password:String
})
//2、定义数据集合的模型:将schema和数据库中的集合关联起来
//model需要三个参数:模型名称,schema名称,数据库中的集合名称
const usersModel=model('userModel',usersSchema,'users')
//向第三层dao层暴露model数据
module.exports.usersModel=usersModel
2.3数据库操作逻辑:userDao.js
//向第二层服务层暴露login方法,并从第二层接收数据user,
//在第三层dao层操作数据库
//引入第三层dao层的model模型,用以操作数据库
const { usersModel }=require('./models/usersModels')
module.exports.login=async function (user) {
const data=await usersModel.find(user)//find 是异步操作,在model里查找user记录(文档)。返回一个数组
//console.log('第三层的data',data)
//第三层直接返回数据给第二层,不需要做任何操作,dao层-->服务层-->表现层
return data
}
** 总体思路**
- 1、在第一层表现层,获得表单数据,req.body用user接受
- 2、导入第二层service层的login方法,将user传给第二层的login,
- 3、在第二层服务层,导入第三层的login方法,把从第二层拿到user传给第三层的login方法
- 4、在第三层导入第三层的model模型,处理从第二层拿到的user并在数据库中进行查询,返回查询到的数据data给第二层service层
- 5、在第二层服务层执行第三层的login(user)方法,得到第三层返回的data数据,并对data进行判断。根据是否获得data数据,返回向第一层(表现层)回传的数据,这个数据是一个对象,包含message和status。因为第二层(服务层,无法执行res.send())
- 6.在第一层表现层,获取第二层(服务层)login(user)得到的返回数据,用data接收后,直接send给浏览器。
- 7、1-3步表现层–>服务层–>持久层。4-6步持久层–>服务层–>表现层的循环。
11、三层架构改造注册验证代码
1、第一层user.js
//引入服务层的方法
const { login,isAcces } = require('../service/usersServices')
//验证用户名是否存在路由
router.post('/isAccess', async function (req, res, next) {
const { username } = req.body
const data=await isAcces(username)
res.send(data)
})
2、第2层usersService.js
const {login,isAcces}=require('../dao/usersDao')
module.exports.isAcces=async function (username) {
const data=await isAcces(username)
//console.log('第二层的data',data)
if (data.length>0){
return {
message:'账号已存在',
status:0
}
}else{
return {
message:'账号可使用',
status:1
}
}
}
3、第3层usersDao.js
const { usersModel }=require('./models/usersModels')
module.exports.isAcces=async function (username) {
const data=await usersModel.find({ username})
//console.log('第三层的data',data)
return data
}
12、三层架构改造注册代码
1、第一层user.js
//引入服务层的方法
const { login,isAcces,register } = require('../service/usersServices')
//注册路由
router.post('/register', async function (req, res, next) {
const user = req.body
const data=await register(user)
res.send(data)
})
2、第2层usersService.js
//引入第三层方法
const {login,isAcces,register}=require('../dao/usersDao')
//注册页面
module.exports.register=async function (user) {
const data=await register(user)
//console.log('第2层的data',data)
if(data._id){
return {
message:'注册成功',
status:1
}
}else{
return {
message:'注册失败',
status:0
}
}
}
3、第3层usersDao.js
const { usersModel }=require('./models/usersModels')
//注册添加用户逻辑
module.exports.register=async function (user) {
return await usersModel.create(user)
//console.log('第3层的data',data)
}