作为一个长期混迹文学社区的老书虫,我一直想打造一个真正属于文学爱好者的交流空间。这次基于Node.js和Express框架开发的文学交流平台,就是想把纸质书的温度带到线上,同时保留互联网的互动优势。平台采用经典的B/S架构,前端用Vue.js实现响应式布局,后端用Express框架搭建RESTful API,数据库选用MySQL 5.7——这个版本在全文检索和JSON支持上刚好满足我们的需求。
技术选型心得:MySQL 5.7相比5.6版本新增了原生JSON支持,这对存储文学作品元数据(如章节结构、作者信息)非常友好,同时其全文检索性能比8.0版本更稳定,特别适合文学类内容的模糊查询。
平台核心解决三个痛点:
后端采用分层架构设计:
javascript复制// 典型的路由控制器示例
router.get('/novels/:id', async (req, res) => {
try {
const novel = await NovelService.getNovelById(req.params.id);
res.json({ code: 200, data: novel });
} catch (err) {
res.status(500).json({ code: 500, message: err.message });
}
});
文学作品表设计特别注意了字段扩展性:
sql复制CREATE TABLE `works` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(100) NOT NULL,
`author_id` int(11) NOT NULL,
`content` longtext NOT NULL,
`metadata` json DEFAULT NULL, -- 存储章节结构、标签等扩展信息
`view_count` int(11) DEFAULT '0',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
FULLTEXT KEY `ft_title_content` (`title`,`content`) -- 全文检索索引
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
踩坑记录:最初直接用TEXT存储章节内容,导致列表查询性能低下。后来优化为单独的内容表,列表页只查询基础信息,详情页再联表查询完整内容。
采用组合模式设计评论系统:
javascript复制// 递归获取评论树
async function getCommentTree(workId, parentId = null) {
const where = { work_id: workId };
if (parentId) where.parent_id = parentId;
const comments = await Comment.findAll({ where });
return Promise.all(comments.map(async comment => ({
...comment.get({ plain: true }),
replies: await getCommentTree(workId, comment.id)
})));
}
实现特色功能:
javascript复制// 批注保存逻辑
document.addEventListener('mouseup', () => {
const selection = window.getSelection();
if (selection.toString().length > 0) {
const range = selection.getRangeAt(0);
const rect = range.getBoundingClientRect();
showAnnotationTooltip(rect, selection.toString());
}
});
采用三级缓存架构:
javascript复制// 缓存中间件实现
const cacheMiddleware = (ttl) => {
return (req, res, next) => {
const key = req.originalUrl;
const cached = cache.get(key);
if (cached) return res.json(cached);
const originalSend = res.json;
res.json = (body) => {
cache.set(key, body, ttl);
originalSend.call(res, body);
};
next();
};
};
针对文学内容特点做的优化:
实现防XSS三重防护:
javascript复制// 安全过滤中间件
const xssProtection = (req, res, next) => {
if (req.body.content) {
req.body.content = sanitize(req.body.content);
}
next();
};
RBAC模型实现细粒度权限:
javascript复制// 权限检查中间件
function checkPermission(requiredRole) {
return (req, res, next) => {
if (!req.user.roles.includes(requiredRole)) {
return res.status(403).json({ message: '权限不足' });
}
next();
};
}
Docker-compose编排方案:
yaml复制version: '3'
services:
app:
build: .
ports:
- "3000:3000"
depends_on:
- redis
- db
redis:
image: redis:alpine
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: example
MYSQL_DATABASE: literature
采用Prometheus+Grafana监控:
实现类似Google Docs的实时协同:
javascript复制// 协同编辑核心逻辑
socket.on('text-update', (update) => {
const transformed = transform(update, buffer);
applyUpdate(transformed);
broadcast(transformed);
});
基于内容的推荐算法:
python复制# 推荐算法伪代码
def recommend(user):
liked_works = get_user_likes(user)
all_works = get_all_works()
tfidf = TfidfVectorizer()
matrix = tfidf.fit_transform([w.content for w in all_works])
user_vector = sum(matrix[i] for i in liked_works)
scores = cosine_similarity(user_vector, matrix)
return sort_by_score(all_works, scores)
使用Artillery进行场景测试:
yaml复制config:
target: "http://localhost:3000"
phases:
- duration: 60
arrivalRate: 10
scenarios:
- flow:
- get:
url: "/api/works"
- think: 3
- post:
url: "/api/comments"
json:
workId: 1
content: "测试评论"
发现的典型问题及解决方案:
经过三个月的开发和迭代,平台目前日活达到1200+,共收录文学作品3800余部。最大的技术收获是:
未来计划:
经验之谈:文学类平台要特别注意版权保护,我们采用了水印+内容指纹双保险,同时建立侵权快速响应机制。在技术之外,组建专业的审核团队同样重要。