博客管理与文章发布系统-第三方模块及其用法Part2
上一篇写到了模板引擎的一些事,接着来看看下一个,在这之前补充一下路由模块的一些功能。
二级路由的使用。
//引入路由模块 const home = require('./route/home.js'); const admin = require('./route/admin.js'); //为路由匹配请求路径 app.use('/admin', admin); app.use('/home', home);
区别了不同功能的同名请求,把app.use第一个参数作为对象的匹配路径,将二级路径的名字写在后方。
我们把二级路径的中间件统一放在route文件夹中,这里展示一些home部分的代码
const express = require('express'); // 创建展示页面路由 const home = express.Router(); home.get('/', require('./home/index')); //将路由对象作为模块成员导出 home.get('/article', require('./home/article')); //创建评论 home.post('/comment',require('./home/comment')) module.exports = home;
把二级路由的功能js存储在route文件夹下的home中,
其他:
res.render(返回渲染过的模板)
app.get('/index', (req, res) => { // 1.拼接模板路径 // 2.拼接模板后缀 // 3.哪一个模板和哪一个数据进行拼接 // 4.将拼接结果响应给客户端 res.render('index', { msg: 'message' }); })
app.locals
将某些属性挂在app.locals下,可以导入所有的模板文件中,比如用户进行登录了之后,就把用户的信息挂在app.locals下
示例:
if (email == user.email || password == user.password) { req.session.username = user.username; //将用户的角色储存在session中 req.session.role = user.role; // req.app拿到的就是app.js里面的app req.app.locals.userInfo = user;
这里的session后面再讲使用方法.
当表单提交的文件中有客户端上传的文件的时候,我们要用另一个模块来获取参数
//引入formidable第三方模块
// bodyParser无法解析文件上传的二进制代码我们选择formidable
//1.创建表单解析对象 //2.配置上传文件的存放位置 //3.保留上传文件的后缀(默认是不保留的) //4. 解析表单 //fields保存着普通的表单数据(除了二进制以外的), //files保存着上传的文件数据 const formidable = require('formidable'); const { Article } = require('../../model/article'); const path = require('path'); module.exports = (req, res) => { var form = new formidable.IncomingForm(); form.uploadDir = path.join(__dirname, '../', '../', 'public', 'uploads'); form.keepExtensions = true; form.parse(req, async(err, fields, files) => { await Article.create({ title: fields.title, author: fields.author, publishData: fields.publishData, cover: files.cover.path.split('public')[1], content: fields.content }); res.redirect('/admin/article'); }) }
form表单的标签中我们需要添加
enctype="multipart/form-data"否则无法正常使用该模块
一.用户注册相关
1.joi验证规则:
//验证用户信息
const joi = require('joi');
const validateUser = user => { const schema = { username: joi.string().min(2).max(12).required().error(new Error('用户名不符合验证规则')), email: joi.string().email().required().error(new Error('邮箱不符合验证规则')), password: joi.string().regex(/^[a-zA-Z0-9]{3,30}$/).required().error(new Error('密码不符合验证规则')), role: joi.string().valid('normal', 'admin').required().error(new Error('角色值非法')), state: joi.number().valid(1, 0).required().error(new Error('状态值非法')) }; return joi.validate(user, schema); } module.exports = { // User: User User, validateUser: validateUser };
解释:string()类型,min()长度最小值 required(是否必要) error(new Error(出错时的报错信息),.regex(正则表达式规则),必须是xx与yy中的一个valid(xx,yy).这里我们放出原始方法的代码对比一下,
注意:这里的是之前练习写的一段代码,与上一段无关。
const articalScheam = new mongoose.Schema({ title:{ type:String, // required:true,是否必要 // minlength,maxlength字面意思 // 可以自定义报错信息 required:[true,'请传入文章标题'], minlength:[2,'文章长度最小不能小于2'], maxlength:4, // 去除字符串两侧的空格 trim:true }, publishdate:{ type:Date, // default默认 default:Date.now }, catagory:{ type:String, // 使值只在指定的内容中挑选 enum:{ // enum错误信息自定义方法 values:['html','css','javascript'], message:'内容不符合要求' } }, author:{ //validator自定义验证规则 type:String, validate:{ validator: v => { // 返回布尔值,如果是true则成功,false失败 return v && v.length >= 4; }, // 自定义错误信息 message:'传入的值不符合验证规则' } }
JOI用来验证信息比较方便我们这里传回了
joi.validate(user, schema);
try { await validateUser(req.body); } catch (ex) { // ex.message return res.redirect('/admin/user-edit?message=' + ex.message); };
同理joi在用户信息修改的时候也可引用。
try catch验证信息是否正确,错误的话直接传回错误信息,然后回到注册页面。
二.用户登录相关
const { User } = require('../../model/user'); module.exports = async(req, res) => { //接受请求参数 // 需要用到第三方模块body-parser const { email, password } = req.body; //当客户端的js验证被禁用时,需要有服务端的验证 if (email.trim().length == 0 || password.trim().length == 0) { return res.status(400).render('admin/error', { msg: '输入用户名或密码错误' }); } //异步函数的方法获取返回值 //如果查询到了用户user变量的值是对象类型,其中存储着对象信息 //如果没有查询到用户user变量为空 let user = await User.findOne({ email, password }); if (user) { //将用户端传递的密码和用户信息密码进行比对 if (email == user.email || password == user.password) { req.session.username = user.username; //将用户的角色储存在session中 req.session.role = user.role; // req.app拿到的就是app.js里面的app req.app.locals.userInfo = user; //对用户的角色进行判断 if (user.role == 'admin') { res.redirect('/admin/user'); } else { res.redirect('/home/'); } // res.end('ok'); //重定向到用户列表页面 res.redirect('/admin/user'); } } else { //没查询到 res.status(400).render('admin/error', { msg: '邮箱地址或者密码错误' }); }
这里简单的写一下session的用法(原理就不在这说了)
引入第三方模块
const session = require('express-session'); // 配置session app.use(session({ secret: 'secret key', saveUninitialized: false , cookie:{ maxAge: 24 * 60 * 60 * 1000 } }));
if (email == user.email || password == user.password) { req.session.username = user.username; //将用户的角色储存在session中 req.session.role = user.role; // req.app拿到的就是app.js里面的app req.app.locals.userInfo = user;
在登陆成功后,将用户信息挂在locals下,补充一点,即使这个时候js文件中没有导入app,但是我们可以通过req.app拿到这个locals