小明:最近我在做一个宿舍信息管理系统,想了解后端是怎么做的?
李工:好的,我们可以从技术选型开始。你打算用什么语言和框架?
小明:我想用Node.js,因为它是异步非阻塞的,适合做高并发的服务。
李工:不错,Node.js确实是个好选择。那数据库呢?
小明:我考虑用MongoDB,因为宿舍数据结构比较灵活,而且是NoSQL,方便扩展。
李工:没错,MongoDB适合这种场景。接下来我们得设计数据模型。
小明:那具体怎么设计呢?比如宿舍信息应该包括哪些字段?
李工:宿舍信息通常包括宿舍编号、类型(单人间、双人间等)、床位数量、管理员、状态等。我们可以用一个集合来存储这些信息。
小明:那用户信息呢?比如学生和管理员的信息也需要管理。
李工:对,用户信息应该单独建一个集合。每个用户有姓名、学号、所属宿舍、角色(学生或管理员)等属性。
小明:明白了。那后端需要提供哪些API呢?
李工:至少要包括以下几个接口:添加宿舍、查询宿舍、更新宿舍、删除宿舍;添加用户、查询用户、更新用户、删除用户;还有登录接口。
小明:那如何处理用户权限呢?比如管理员可以操作所有宿舍,而学生只能查看自己的宿舍信息。
李工:可以通过JWT(JSON Web Token)来实现鉴权。用户登录成功后,服务器生成一个token返回给客户端,后续请求带上这个token,服务端验证token的有效性,然后根据用户角色决定是否允许访问某些资源。
小明:那具体的代码怎么写呢?有没有示例?
李工:当然有。我们可以先创建一个简单的Express项目,然后使用MongoDB进行数据存储。
小明:那我们先安装依赖吧。
李工:首先,初始化项目并安装必要的包:
npm init -y
npm install express mongoose jsonwebtoken bcryptjs cors
小明:然后创建入口文件app.js,设置基本的Express应用。
李工:没错,下面是app.js的示例代码:
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const app = express();
app.use(cors());
app.use(express.json());
// 连接MongoDB
mongoose.connect('mongodb://localhost/dormitory', {
useNewUrlParser: true,
useUnifiedTopology: true
}).then(() => console.log('Connected to MongoDB'))
.catch(err => console.error('Failed to connect to MongoDB:', err));
// 启动服务器
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
小明:看起来很基础。那我们定义宿舍的数据模型吧。
李工:好的,创建一个models/Dormitory.js文件,定义宿舍模型:
const mongoose = require('mongoose');
const DormitorySchema = new mongoose.Schema({
dormNumber: { type: String, required: true },
type: { type: String, enum: ['Single', 'Double'], required: true },
bedCount: { type: Number, required: true },
adminId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
status: { type: String, default: 'Available' }
});
module.exports = mongoose.model('Dormitory', DormitorySchema);
小明:那用户模型呢?
李工:同样在models/User.js中定义:
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const UserSchema = new mongoose.Schema({
name: { type: String, required: true },
studentId: { type: String, required: true, unique: true },
dormId: { type: mongoose.Schema.Types.ObjectId, ref: 'Dormitory' },
role: { type: String, enum: ['Student', 'Admin'], required: true },
password: { type: String, required: true }
});
// 密码加密
UserSchema.pre('save', async function(next) {
if (this.isModified('password') || this.isNew) {
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(this.password, salt);
}
next();
});
module.exports = mongoose.model('User', UserSchema);
小明:现在我们需要创建路由,比如添加宿舍的接口。
李工:是的,创建routes/dormitories.js:
const express = require('express');
const router = express.Router();
const Dormitory = require('../models/Dormitory');
// 添加宿舍
router.post('/', async (req, res) => {
try {
const { dormNumber, type, bedCount, adminId } = req.body;
const dormitory = new Dormitory({ dormNumber, type, bedCount, adminId });
await dormitory.save();
res.status(201).json(dormitory);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// 查询所有宿舍
router.get('/', async (req, res) => {
try {
const dormitories = await Dormitory.find().populate('adminId');
res.json(dormitories);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
module.exports = router;
小明:那用户注册和登录的接口呢?
李工:我们来创建用户路由,例如routes/users.js:
const express = require('express');
const router = express.Router();
const User = require('../models/User');
const jwt = require('jsonwebtoken');
// 注册
router.post('/register', async (req, res) => {
try {
const { name, studentId, role, password } = req.body;
const user = new User({ name, studentId, role, password });
await user.save();
res.status(201).json({ message: 'User registered successfully' });
} catch (err) {
res.status(400).json({ error: err.message });
}
});
// 登录
router.post('/login', async (req, res) => {
try {
const { studentId, password } = req.body;
const user = await User.findOne({ studentId });
if (!user) return res.status(404).json({ error: 'User not found' });
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) return res.status(401).json({ error: 'Invalid credentials' });
const token = jwt.sign({ id: user._id, role: user.role }, 'secret_key', { expiresIn: '1h' });
res.json({ token });
} catch (err) {
res.status(500).json({ error: err.message });
}
});
module.exports = router;
小明:那如何在主文件中引入这些路由呢?

李工:在app.js中,我们添加如下代码:
const dormitoriesRouter = require('./routes/dormitories');
const usersRouter = require('./routes/users');
app.use('/api/dorms', dormitoriesRouter);
app.use('/api/users', usersRouter);
小明:这样就完成了基本的后端功能。那如何测试这些接口呢?
李工:你可以用Postman或者curl来测试。例如,发送POST请求到http://localhost:3000/api/users/register,传递studentId、name、role、password等参数。
小明:如果我要添加一个宿舍,应该怎么操作?
李工:发送POST请求到http://localhost:3000/api/dorms,传入dormNumber、type、bedCount、adminId等字段。
小明:那管理员登录后如何获取宿舍列表?
李工:管理员登录后,拿到token,然后发送GET请求到http://localhost:3000/api/dorms,带上Authorization头为Bearer + token,就能获取宿舍列表了。
小明:看来整个后端逻辑已经清晰了。那有什么需要注意的地方吗?
李工:注意安全问题,比如密码加密、JWT的过期时间、防止SQL注入(虽然MongoDB本身是NoSQL,但也要注意输入过滤)。另外,建议使用环境变量来管理敏感信息,比如MongoDB连接字符串和JWT密钥。
小明:明白了。感谢你的讲解!
李工:不客气,有问题随时问我。
