'假设你已经了解什么是express框架 mongodb数据库(非关系型数据库) 那么让我们开始吧!'
Node.js的核心,通过npm下载或者自己有的包,require引入时不需要加/,
但是自己写的模块则需要加,否则找不到,Node.js使用的是commonJs的模块
化规范哦
'让我们开始吧!'
复制代码
github源码地址
项目需求
- 登陆,注册,主页,各一个界面(路由)
- 不需要静态资源,需要前后端能交互,在对应的位置提醒用户更新不同的内容
- 用户如果不登陆,是不能访问主页。如果用户在规定有效期内登陆成功过,也可以访问主页
- 用户如果登陆/注册失败,要提醒对应的全部失败原因,并且除了密码外都要保存在页面中(不让客户重复输入)
- 用户的密码在保存数据库中时,需要使用sha1的包进行加密,在查询时候也需要加密
- 用户的session_id也需要加密然后保存在数据库中
- 对用户的session_id所对应的cookie也要设定一个有效期
- ...后续可能加一些防攻击的需求,在应用型的中间件中。
所需要的下载的包
"dependencies": {
"cookie-parser": "^1.4.4", //解析cookie
"ejs": "^2.6.1", //ejs的模板渲染
"express": "^4.16.4", //express框架
"express-session": "^1.15.6", //session的处理
"mongoose": "^5.4.19" //mongoose包,处理mongodb数据库的
},
"devDependencies": {
"nodemon": "^1.18.10", //每次修改JS文件后服务器自动更新
"sha1": "^1.1.1" //对数据加密的模块
}
'直接复制我上面的json文件内容,把后面的注释删除掉即可 npm install 下载'
我们使用ejs的渲染引擎进行渲染
首先看主文件的入口
-------
ejs.js
'这里首先引入了express框架后,还引入了session的处理模块,以及自定义的uirouter、
inforrouter两个路由器路由模块 ,设置了ejs的渲染目录views,还指定了渲染
引擎为ejs(ejs的模块不需要引入,设置就好),'
const express = require('express');
const app = express();
const mongoose = require('./database');
const uirouter = require('./uirouter');
const inforouter = require('./inforouter');
const session = require('express-session');
const MongoStore = require('connect-mongo')(session);
app.set('views', 'views');
app.set('view engine', 'ejs');
app.use(session({ //设置session
secret: 'hello', //对session_id的加密
saveUninitialized: false,
resave: false,
store: new MongoStore({
url: 'mongodb://localhost:27017/user',
touchAfter: 24 * 3600
}),
cookie:{maxAge:1000*3600*24*7},
//session是基于cookie传送,cookie默认是会话存储,需要指定有效期
}))
mongoose.then(async () => { //设置路由器路由,从下往下解析
app.use(uirouter);
app.use(inforouter);
})
app.use((err, req, res, next) => { //错误机制处理路由
if (err) {
console.log(err);
}
})
app.listen(5555, err => { //监听端口号
if (!err) {
console.log('监听成功');
} else {
console.log(`监听失败${err}`);
}
});
----------------
'database.js 这个是数据库的连接模块 '
---------------------
'这里暴露的是一个promise对象,必须先连接成功数据库再走下一步,所以主模块使用了.then()'
const mongoose = require('mongoose');
module.exports = new Promise((resolve, reject) => {
mongoose.connect('mongodb://localhost:27017/user', { useNewUrlParser: true, useCreateIndex: true });
//指定连接的域名和端口号,以及数据库的名称
mongoose.connection.once('open', err => {
if (!err) {
console.log('数据库连接成功');
resolve();
} else {
console.log('数据库连接失败:' + err);
reject(err);
}
})
})
---------------------
'model.js 这个是模型对象模块, 暴露的是模型对象,可以使用它身上对数据库的CRUD操作'
const { Schema, model } = require('mongoose');
const schema = new Schema({
username: {
type: String,
unique: true,
required: true
},
password: {
type: String,
required: true
},
email: {
type: String,
required: true
}
});
const Model = model('userinfos', schema);
//指定数据库的模型对象,以及保存的集合名称为 'userinfos'
module.exports = Model;
-----
'inforrouter 这个是注册模块的文件 '
const { Router, urlencoded } = require('express');
const sha1 = require('sha1');
const router = new Router();
const model = require('./model');
router.use(urlencoded({ extended: true }));
router.post('/login', async (req, res) => {
let { username, password } = req.body;
const result = await model.findOne({ username, password: sha1(password) });
//'如果能通过用户名和加密后的密码在数据库中查找到,那么给它添加session_id然后跳转到主页'
if (result) {
req.session.userid = result.id
res.redirect('/index')
} else {
res.render('login', { err: { username: username, usernameerr: '用户名或密码错' } });
//'如果找不到,渲染login.ejs文件,并且渲染对应的err数据到页面上'
}
})
router.post('/re', async (req, res) => {
let { username, password, repassword, email } = req.body;
//ES6的解构赋值,提取post请求体中的四个对应的数值
const usernameReg = /^[A-Za-z0-9_]{5,10}$/;
const passwordReg = /^[A-Za-z0-9_]{5,12}$/;
const emailReg = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
//三个正则匹配
let err = {};
const result = await model.findOne({ username });
if (!usernameReg.test(username)) {
err.usernameerr = '用户名格式不正确';
}
if (!passwordReg.test(password)) {
err.password = '密码格式不正确';
}
if (password != repassword) {
err.repassword = '跟上次输入密码不一致';
}
if (!emailReg.test(email)) {
err.email = '邮箱格式不正确';
}
if (result) {
err.usernameerr = '用户名已存在'
}
if (err.usernameerr || err.password || err.repassword || err.emailerr) {
res.render('re', { err })
return;
//'只要有一个错误存在,那么就渲染re.ejs文件,并且渲染err这个数据'
}
model.create({
username,
password: sha1(password),
email
})
res.redirect('/index')
//'如果上面的错误都没有,那么就保存这个文档对象在数据库中,
并且跳转到index的路由上,index的路由也有处理机制'
})
module.exports = router;
------------
'uirouter.js 是处理get请求的路由文件'
----------------
const { Router } = require('express');
const model = require('./model');
const router = new Router();
router.get('/login', async (req, res) => {
res.render('login.ejs', { err: '' })
//'渲染对应的ejs文件,这里如果不写空的err渲染数据,
后期的渲染会报错,会提示err not defined'
})
router.get('/re', (req, res) => {
res.render('re.ejs', { err: "" });
})
router.get('/index', async (req, res) => {
const { userid } = req.session;
if (!userid) {
res.redirect('/login')
return;
}
const result = await model.findById({ _id: userid });
if (result) {
res.render('index');
} else {
res.redirect('/login');
}
//'如果用户成功登陆过,那么会有一个session_id文件,
如果有并且能在数据库中找到,那么就让用户去index.ejs
的渲染文件'
})
module.exports = router;
-----------------
'views文件夹,下面的三个ejs文件,是使用ejs渲染引擎的渲染文件'
'index.ejs '
"en">
"UTF-8">
"viewport" content="width=device-width, initial-scale=1.0">
"X-UA-Compatible" content="ie=edge">
Document
欢迎来到首页
"/login">登陆界面
"/re">注册界面
-------------------------
'login.ejs 是登陆文件'
"en">
"UTF-8">
"viewport" content="width=device-width, initial-scale=1.0">
"X-UA-Compatible" content="ie=edge">
Document
-------------------
're.js 是注册页面文件 '
"en">
"UTF-8">
"viewport" content="width=device-width, initial-scale=1.0">
"X-UA-Compatible" content="ie=edge">
Document
--------------------------
'在浏览器中输入的url地址访问都是get请求,所以我们把get请求也成为uirouter,但是一旦到了提交表单,
我们使用的就是post请求的路由了,同样名字的路由,但是请求方式不一样他们并不冲突,Node.js中代码
也是从上到下解析的,这里的ejs渲染模板需要多注意的是get请求的时候一定要先给一个空的渲染数据,否
则后期post请求是渲染不上去的,会提示not defined,因为肯定是先get请求看到页面后才能提交数据,这
点要格外注意,其实express框架并不难,这个版本就能用到express中最核心的所有知识点,能掌握了就能
独立开发服务器和前后端交互以及数据处理',后面我会就web的存储技术,以及koa2框架继续深入
复制代码