使用node+mongodb搭建的论坛及后台
这是我做的第一个项目后台,如有什么不恰当之处及可修改改正之处,麻烦多多指教,此项目仅供学习参考!谢谢大家。
源代码我放到了文章最下面,有需要的可以直接去我的github上clone,希望能点个Star,给点意见和建议,你的支持是我的最大动力。
主要配置
- 服务器:node
- 框架:express
- 数据库:mongodb
- 模板引擎:art-template
- 中间件:express-art-template、art-template、express-session、body-parser、mongoose
值得解释的是中间件部分:
- express-art-template这个是用来把服务器上的数据渲染到页面上的一个模板引擎,特点是:非常快,反应很迅速;
- 而art-template则可以利用include-extend-block语法,直接在模板页写好头部和尾部,其他子页面直接继承。如下图
- body-parser则是可以解析表单post请求体
- mongoose是另一方基于官方再次开发的第三方包,当然官方也有相应的中间件mongodb的官方包,但是官方的比较麻烦,直接用mongoose比较省时省力,因此这里采用的是mongoose。
功能解说
Router
路由器Router是这个项目的骨架,因此优先设计,基本上会有首页、使用者的个别页面、注册页、登入页、并且我们也需要做注册、登入、登出、发文的操作
get请求
- 首页(论坛页):/
- 注册页面:/register
- 登录页面:/login
- 发起话题页面:/topics/new
- 用户设置界面(修改密码):/settings/admin
- 退出:/logout
- 用户设置界面:/settings/profile
- 文章展示界面:/topic/show
- 后台管理系统界面展示:/background
- 后台管理系统景点管理展示:/background/view
- 后台管理系统用户管理展示:/background/user
- 后台管理系统用户管理删除:/background/user/delete
- 后台管理文章/提问:/background/article
- 后台管理文章/提问删除:/background/article/delete
- 后台管理的评论:/background/comment
- 后台管理的评论的删除:/background/comment/delete
post请求
- 用户注册提交表单:/register
- 用户登录提交表单:/login
- 用户修改设置提交表单:/settings/profile
- 保存用户新密码:/settings/admin
- 注销用户:/settings/delete
- 发布文章:/topic/new
- 提交评论:/topic/show
中间件引入
var express = require('express')
var path = require('path')
var bodyParser = require('body-parser')
var session = require('express-session')
var router = require('./router')
var app = express();
//开放public和node_modules
app.use('/public/', express.static(path.join(__dirname, './public/')))
app.use('/node_modules/',express.static(path.join(__dirname, './node_modules/')))
//express和art-template结合使用
app.engine('html',require('express-art-template'))
// 配置解析表单 POST 请求体插件(注意:一定要在 app.use(router) 之前 )
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended:false }))
// parse application/json
app.use(bodyParser.json())
app.use(session({
// 配置加密字符串,它会在原有加密基础之上和这个字符串拼起来去加密
// 目的是为了增加安全性,防止客户端恶意伪造
secret: 'itcast',
resave: false,
saveUninitialized: false // 无论你是否使用 Session ,我都默认直接给你分配一把钥匙
}))
//把路由挂载到app中
app.use(router)
app.listen(3000,function(){
console.log('has been running 3000')
})
注册/登入
这里着重讲用户登录进去后如何得到用户信息并更改论坛首页上信息的显示
首先我们看看一开始的论坛首页
仔细看右上角,那么我们需要做的是,当用户进行登录的时候,要显示出用户登录的状态,即用户的状态名,那么我们这里就需要用到session以及art-template了,首先在用户登录的界面的登录按钮发起请求,然后服务器接收到请求之后,又向数据库发起请求,查看是否有这个用户,如果有则返回数据,然后用session记录当前用户的账户密码(不过也不安全,新手玩一下~),代码如下:
User.findOne({
username: body.username,
passwd: body.passwd
}, function (err, user) {
if (err) {
return res.status(500).json({
err_code: 500,
message: err.message
})
}
// 如果邮箱和密码匹配,则 user 是查询到的用户对象,否则就是 null
if (!user) {
console.log(body.passwd)
return res.status(200).json({
err_code: 1,
message: 'username or passwd is invalid.'
})
}
//用户存在,登录成功,记录登录状态,通过session记录登录状态
req.session.user = user
res.status(200).json({
err_code: 0,
message: 'ok '
})
返回数据以后,则用art-template模板引擎进行数据判断,如果有用户数据,则进行另一个html元素的显示,代码如下
{{ if user }}
<a class="btn btn-default navbar-btn" href="/topics/new">发起</a>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><img width="20" height="20" src="../public/img/avatar-max-img.png" alt=""> <span class="caret"></span></a>
<ul class="dropdown-menu">
<li class="dropdown-current-user">
当前登录用户: {{ user.nickname }}
</li>
<li role="separator" class="divider"></li>
<li><a href="/">主页</a></li>
<li><a href="/settings/profile">设置</a></li>
<li><a href="/logout">退出</a></li>
</ul>
</li>
{{ else }}
<a class="btn btn-primary navbar-btn" href="/login">登录</a>
<a class="btn btn-success navbar-btn" href="/register">注册</a>
{{ /if }}
不同文章不同评论
设置一个评论数据库,然后评论的时候,进的是哪个文章,就把哪个文章的题目赋值到该数据库的theme字段中,然后匹配这个字段是否与文章的theme相同,相同则显示,否则则不显示。(这里的的话我又设置了两个数据库进行数据的存放,分别是文章数据库,评论数据库)
文章数据库的设计
var mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/hsuser', {useNewUrlParser: true});
var Schema = mongoose.Schema
var articleSchema = new Schema({
theme:{
type:String,
required:true
},
username:{
type:String
},
models:{
type:String
},
//文章发表时间
atime:{
type:Date
},
//内容
content:{
type:String,
required:true
}
})
module.exports = mongoose.model('Article',articleSchema)
评论数据库的设计
var mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/hsuser', {useNewUrlParser: true});
var Schema = mongoose.Schema
var commentSchema = new Schema({
theme:{
type:String
},
nickname:{
type:String
},
content:{
type:String
},
time:{
type:Date
},
good:{
type:Number
}
})
//导出
module.exports = mongoose.model('Comment',commentSchema)
利用一个嵌套,这里先是查到了相应的文章,那么接下来就是查相应文章下相应的评论
//文章展示
router.get('/topic/show', function (req, res) {
//需要先做个判断,当用户没有登录的时候,提示用户并返回到首页
if(req.session.user == null){
return res.status(500).send('请先登录再查看喔')
}
//console.log(req.body.id)
//console.log(req.query.id)
//console.log(req.session.user.nickname)
Article.findById(req.query.id, function (err, article) {
if (err) {
console.log('失败')
return res.status(500).send('Server error.')
}
//嵌套一下,把评论的数据也读出来,放进去
//用find一定要合乎语法规范加上{theme:article.theme},这样才能有条件搜索
Comment.find({theme:article.theme},function(err,comment){
if(err){
console.log('失败')
return res.status(500).send('Server error.')
}
res.render('./topic/show.html',{
user:req.session.user,
article:article,
comment:comment
})
})
})
})
期间遇到的问题
- 用户注册登录的数据库是用同一个数据库,但是论坛就用户信息又开一个数据,那中间如何进行数据库主外键连接,因为我用的数据库又是mongodb,是nosql的,主外键这些我不是很熟,因此这里就被卡住了。
解决:在找老师进行讨论之后,老师说我数据库设计就有问题,我更多是应该把它们设计成同一个数据库,而不是分开,一般在外面做项目,用户的信息就是一个数据库,而不会像我这样设计两个数据库再进行连接。再者就算用两个数据库的话,其中在mongodb数据库里面就算不设置都是会有亿个“_id”的数据,这个id是唯一的,只要利用好这个id就可以通过这个id就是相应的数据库数据的信息连接。 - 登录界面与后台交互的ajax没有反应!数据无法同步?
解决:原来是师姐给我们的界面里面的js文件,师姐设置了当用户点击提交按钮之后,会触发师姐的条件并且return false,因此无论怎么样都走不到我的ajax的路上,所以我写的ajax无效,最后解决是,暂时把师姐的js代码注销掉,先把前端与后台数据库进行交互弄出来先。 - 当登录成功之后,如何把让页面记住用户登录并跳转到论坛界面
解决:那么我这里用了一个中间件“express-session”,让用户登录的信息保存在浏览器的session上,那么在跳转首页的时候,就可以判断session上是否有user信息,如果有信息则说明登录成功,并且显示登录成功用户的状态在论坛上方。 - 不知道如何才能实现,在论坛点击不同的文章,相应显示不同的评论。
解决:设置一个评论数据库,然后评论的时候,进的是哪个文章,就把哪个文章的题目赋值到该数据库的theme字段中,然后匹配这个字段是否与文章的theme相同,相同则显示,否则则不显示。(这里的的话我又设置了两个数据库进行数据的存放,分别是文章数据库,评论数据库)。 - 接着问题4,谈谈实现,这里是比较关键的
解决:那么毋庸置疑,在首页点击那个文章就跳转到那个具体的文章里面,那么这里利用mongoose中间件的,finById的方法,那么这个id又是通过art-template放到url上的。PS:放到url上的id这里查询的时候的话,就在我设置好的路由器上用(req.query.id);那么值得注意的是,node上获取参数的方式有三种(req.query、req.body、req.params),那么这里就不赘述了,详情可查获取参数的三种方式;然后就是比较关键的利用一个嵌套,这里先是查到了相应的文章,那么接下来就是查相应文章下相应的评论,这个评论的话就是利用mongoose中的find(theme:article.theme,function(){}),主要是这个查询的条件,这里由于我对mongoose的api不熟,导致我在这里卡了比较长时间。
把上述问题都解决完成之后,一个论坛及用户信息就完成了,那么接下来就把剩下的后台信息展示写完就完成了,这一步也比较简单,利用的是腾讯的art-template引擎,把后台mongodb的数据库渲染到相应的后台界面上即可完成。
总结
只写上面两步是因为,在这次练习的过程中,遇到稍微阻碍的就上面的两步,当然其他有时候也有问题,但是相对来说,我认为在我做这个论坛及后台较困难就以上的两步,但是其实来说都是比较基础的,最主要是要看会不会看文档,会不会用API,这是很关键的!其余的就比较简单的,就是普通利用art-template渲染,用mongoose进行CRUD的过程了;其他的细节,我放在我的github上了,红色旅游,希望能给个star,你的意见和建议是我最大的动力~谢谢!