前言
博客系统是一个常见的 Web 应用程序,它可以让用户创建、编辑和发布文章,并与其他用户进行交流。本文将介绍如何使用 Node.js、Express 和 MongoDB 实现一个简单的博客系统。我们将使用 Express 框架来处理 HTTP 请求和响应,并使用 MongoDB 数据库来存储和检索文章和用户信息。
准备工作
在开始之前,您需要安装以下软件:
- Node.js:您可以从官方网站(https://nodejs.org/)下载并安装最新版本的 Node.js。
- MongoDB:您可以从官方网站(https://www.mongodb.com/)下载并安装最新版本的 MongoDB。
安装完成后,您可以使用以下命令检查是否已正确安装 Node.js 和 MongoDB:
node -v mongo --version
创建项目
我们将使用 Express 应用程序生成器来创建项目。使用以下命令安装 Express 应用程序生成器:
npm install -g express-generator
安装完成后,使用以下命令创建一个名为 myblog 的项目:
express --view=ejs myblog
这将创建一个名为 myblog 的新目录,并生成一个基本的 Express 应用程序。我们将使用 EJS 模板引擎来渲染页面。
安装依赖
进入 myblog 目录并使用以下命令安装所需的依赖项:
cd myblog npm install
我们需要安装以下依赖项:
- body-parser:用于解析 HTTP 请求体。
- cookie-parser:用于解析 HTTP 请求中的 cookie。
- express-session:用于管理用户会话。
- mongoose:用于连接和操作 MongoDB 数据库。
- bcrypt:用于密码哈希和验证。
使用以下命令安装这些依赖项:
npm install body-parser cookie-parser express-session mongoose bcrypt --save
配置数据库
我们需要在项目中配置 MongoDB 数据库。在 myblog 目录中创建一个名为 config 的新目录,并在其中创建一个名为 database.js 的新文件。将以下代码添加到 database.js 文件中:
// javascriptcn.com 代码示例 const mongoose = require('mongoose'); mongoose.connect('mongodb://localhost/myblog', { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true, }); mongoose.connection.on('error', (err) => { console.error(err); }); mongoose.connection.once('open', () => { console.log('Connected to MongoDB'); });
这将连接到名为 myblog 的本地 MongoDB 数据库。您可以根据需要更改数据库名称和连接字符串。
创建模型
我们需要创建两个模型:User 和 Post。在 myblog 目录中创建一个名为 models 的新目录,并在其中创建一个名为 user.js 的新文件。将以下代码添加到 user.js 文件中:
// javascriptcn.com 代码示例 const mongoose = require('mongoose'); const bcrypt = require('bcrypt'); const userSchema = new mongoose.Schema({ username: { type: String, required: true, unique: true, }, password: { type: String, required: true, }, }); userSchema.pre('save', function (next) { const user = this; if (!user.isModified('password')) return next(); bcrypt.genSalt(10, (err, salt) => { if (err) return next(err); bcrypt.hash(user.password, salt, (err, hash) => { if (err) return next(err); user.password = hash; next(); }); }); }); userSchema.methods.comparePassword = function (password, callback) { bcrypt.compare(password, this.password, (err, isMatch) => { if (err) return callback(err); callback(null, isMatch); }); }; module.exports = mongoose.model('User', userSchema);
这将定义一个 User 模型,它包含用户名和密码字段,并使用 bcrypt 库进行密码哈希和验证。
接下来,在 models 目录中创建一个名为 post.js 的新文件,并将以下代码添加到 post.js 文件中:
// javascriptcn.com 代码示例 const mongoose = require('mongoose'); const postSchema = new mongoose.Schema({ title: { type: String, required: true, }, content: { type: String, required: true, }, author: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true, }, createdAt: { type: Date, default: Date.now, }, }); module.exports = mongoose.model('Post', postSchema);
这将定义一个 Post 模型,它包含标题、内容、作者和创建时间字段。
创建控制器
我们需要创建两个控制器:userController 和 postController。在 myblog 目录中创建一个名为 controllers 的新目录,并在其中创建一个名为 userController.js 的新文件。将以下代码添加到 userController.js 文件中:
// javascriptcn.com 代码示例 const User = require('../models/user'); exports.signup = (req, res, next) => { const username = req.body.username; const password = req.body.password; const user = new User({ username: username, password: password, }); user.save((err) => { if (err) return next(err); req.session.userId = user._id; res.redirect('/'); }); }; exports.login = (req, res, next) => { const username = req.body.username; const password = req.body.password; User.findOne({ username: username }, (err, user) => { if (err) return next(err); if (!user) return res.redirect('/login'); user.comparePassword(password, (err, isMatch) => { if (err) return next(err); if (!isMatch) return res.redirect('/login'); req.session.userId = user._id; res.redirect('/'); }); }); }; exports.logout = (req, res, next) => { req.session.destroy(); res.redirect('/'); };
这将定义三个路由处理程序:signup、login 和 logout。signup 路由处理程序将创建一个新用户并将其保存到数据库中。login 路由处理程序将查找用户并验证密码。如果验证成功,它将在会话中设置用户 ID。logout 路由处理程序将销毁会话并将用户重定向到主页。
接下来,在 controllers 目录中创建一个名为 postController.js 的新文件,并将以下代码添加到 postController.js 文件中:
// javascriptcn.com 代码示例 const Post = require('../models/post'); exports.index = (req, res, next) => { Post.find() .populate('author') .sort('-createdAt') .exec((err, posts) => { if (err) return next(err); res.render('index', { posts: posts }); }); }; exports.new = (req, res, next) => { res.render('new'); }; exports.create = (req, res, next) => { const title = req.body.title; const content = req.body.content; const post = new Post({ title: title, content: content, author: req.session.userId, }); post.save((err) => { if (err) return next(err); res.redirect('/'); }); };
这将定义三个路由处理程序:index、new 和 create。index 路由处理程序将检索所有文章并将其传递给模板。new 路由处理程序将呈现一个用于创建新文章的表单。create 路由处理程序将创建一个新文章并将其保存到数据库中。
创建视图
我们需要创建三个视图:index、login 和 new。在 myblog 目录中创建一个名为 views 的新目录,并在其中创建一个名为 index.ejs 的新文件。将以下代码添加到 index.ejs 文件中:
// javascriptcn.com 代码示例 <!DOCTYPE html> <html> <head> <title>My Blog</title> </head> <body> <% if (user) { %> <p>Welcome, <%= user.username %>!</p> <a href="/logout">Logout</a> <% } else { %> <a href="/login">Login</a> <% } %> <h1>My Blog</h1> <ul> <% posts.forEach(function(post) { %> <li> <h2><%= post.title %></h2> <p><%= post.content %></p> <p>Posted by <%= post.author.username %> on <%= post.createdAt %></p> </li> <% }); %> </ul> <a href="/new">New Post</a> </body> </html>
这将呈现所有文章、当前用户和一个用于创建新文章的链接。
接下来,在 views 目录中创建一个名为 login.ejs 的新文件。将以下代码添加到 login.ejs 文件中:
// javascriptcn.com 代码示例 <!DOCTYPE html> <html> <head> <title>Login</title> </head> <body> <h1>Login</h1> <% if (message) { %> <p><%= message %></p> <% } %> <form method="post" action="/login"> <p> <label for="username">Username:</label> <input type="text" name="username" id="username" /> </p> <p> <label for="password">Password:</label> <input type="password" name="password" id="password" /> </p> <p> <input type="submit" value="Login" /> </p> </form> </body> </html>
这将呈现一个用于登录的表单。
最后,在 views 目录中创建一个名为 new.ejs 的新文件。将以下代码添加到 new.ejs 文件中:
// javascriptcn.com 代码示例 <!DOCTYPE html> <html> <head> <title>New Post</title> </head> <body> <h1>New Post</h1> <form method="post" action="/new"> <p> <label for="title">Title:</label> <input type="text" name="title" id="title" /> </p> <p> <label for="content">Content:</label> <textarea name="content" id="content"></textarea> </p> <p> <input type="submit" value="Create" /> </p> </form> </body> </html>
这将呈现一个用于创建新文章的表单。
创建路由
我们需要创建三个路由:/、/login 和 /new。在 myblog 目录中创建一个名为 routes 的新目录,并在其中创建一个名为 index.js 的新文件。将以下代码添加到 index.js 文件中:
// javascriptcn.com 代码示例 const express = require('express'); const router = express.Router(); const Post = require('../models/post'); const User = require('../models/user'); const postController = require('../controllers/postController'); const userController = require('../controllers/userController'); router.get('/', (req, res, next) => { Post.find() .populate('author') .sort('-createdAt') .exec((err, posts) => { if (err) return next(err); User.findById(req.session.userId, (err, user) => { if (err) return next(err); res.render('index', { posts: posts, user: user }); }); }); }); router.get('/login', (req, res, next) => { res.render('login'); }); router.post('/login', userController.login); router.get('/logout', userController.logout); router.get('/new', (req, res, next) => { User.findById(req.session.userId, (err, user) => { if (err) return next(err); if (!user) return res.redirect('/login'); res.render('new'); }); }); router.post('/new', postController.create); module.exports = router;
这将定义五个路由:/、/login、/logout、/new 和 /new。/路由将检索所有文章、当前用户和呈现主页。/login 路由将呈现登录页面。/logout 路由将销毁会话并将用户重定向到主页。/new 路由将呈现一个用于创建新文章的表单。/new 路由将创建一个新文章并将其保存到数据库中。
启动应用程序
现在,我们已经完成了博客系统应用程序的开发。使用以下命令启动应用程序:
npm start
这将启动应用程序并在 http://localhost:3000 上监听请求。现在,您可以在浏览器中打开 http://localhost:3000 并开始使用博客系统了。
总结
本文介绍了如何使用 Node.js、Express 和 MongoDB 实现一个简单的博客系统。我们学习了如何创建模型、控制器、视图和路由,并将它们组合在一起以创建完整的应用程序。我们还讨论了如何使用 bcrypt 库进行密码哈希和验证,并使用会话管理用户状态。这个示例项目可以帮助您了解如何使用 Node.js、Express 和 MongoDB 构建 Web 应用程序,以及如何使用这些技术来解决常见的 Web 开发问题。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6564743bd2f5e1655dde7511