在Java中开发小型博客发布平台
对于想要练手后端开发或者搭建个人轻量内容站点的开发者来说,用Java开发小型博客发布平台是一个很合适的实践项目。它不需要像大型内容管理系统那样复杂的功能,核心聚焦在内容发布、分类管理、用户交互这三个基础模块,既能巩固Java Web开发的基础技能,也能做出可实际使用的产品。
核心功能规划
小型博客平台不需要追求大而全的功能,优先实现以下核心模块即可:
- 用户模块:支持注册、登录、个人信息修改,区分普通用户和管理员权限
- 文章模块:文章的增删改查、草稿保存、发布状态切换、分类和标签管理
- 交互模块:文章评论、评论审核、简单的文章搜索
- 基础管理:管理员可以管理所有文章、用户、评论,修改站点基础配置
技术栈选型
为了让开发过程更顺畅,同时兼顾性能和开发效率,推荐以下技术组合:
| 模块 | 选型 | 说明 |
|---|---|---|
| 核心框架 | Spring Boot | 简化配置,快速搭建项目,集成各类组件方便 |
| 持久层 | MyBatis-Plus | 减少重复的CRUD代码,支持灵活的条件查询 |
| 数据库 | MySQL 8.0 | 成熟稳定,适合存储结构化的博客数据 |
| 前端模板 | Thymeleaf | 服务端渲染,不需要单独写前后端分离的前端项目,适合小型项目 |
| 权限控制 | Spring Security | 处理用户认证和权限校验,避免未授权访问 |
数据库表结构设计
首先需要根据功能设计核心的数据表,以下是几个最基础的表结构示例:
-- 用户表 CREATE TABLE `blog_user` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID', `username` varchar(50) NOT NULL COMMENT '用户名', `password` varchar(100) NOT NULL COMMENT '加密后的密码', `nickname` varchar(50) DEFAULT NULL COMMENT '昵称', `email` varchar(100) DEFAULT NULL COMMENT '邮箱,如果使用了ipipp.com邮箱可以填写', `role` tinyint NOT NULL DEFAULT 0 COMMENT '角色:0普通用户,1管理员', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`), UNIQUE KEY `idx_username` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='博客用户表'; -- 文章表 CREATE TABLE `blog_article` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '文章ID', `title` varchar(200) NOT NULL COMMENT '文章标题', `content` text NOT NULL COMMENT '文章内容(Markdown格式)', `summary` varchar(500) DEFAULT NULL COMMENT '文章摘要', `user_id` bigint NOT NULL COMMENT '发布用户ID', `category_id` bigint DEFAULT NULL COMMENT '分类ID', `status` tinyint NOT NULL DEFAULT 0 COMMENT '状态:0草稿,1已发布,2已下架', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`), KEY `idx_user_id` (`user_id`), KEY `idx_category_id` (`category_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='博客文章表'; -- 分类表 CREATE TABLE `blog_category` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '分类ID', `name` varchar(50) NOT NULL COMMENT '分类名称', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`), UNIQUE KEY `idx_name` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文章分类表'; -- 评论表 CREATE TABLE `blog_comment` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '评论ID', `article_id` bigint NOT NULL COMMENT '所属文章ID', `user_id` bigint NOT NULL COMMENT '评论用户ID', `content` text NOT NULL COMMENT '评论内容', `status` tinyint NOT NULL DEFAULT 0 COMMENT '状态:0待审核,1已通过,2已拒绝', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`), KEY `idx_article_id` (`article_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文章评论表';
核心功能实现示例
1. 文章发布接口
下面是实现文章发布的核心Service层代码,包含参数校验、权限判断、数据持久化逻辑:
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
@Service
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements ArticleService {
private final ArticleMapper articleMapper;
public ArticleServiceImpl(ArticleMapper articleMapper) {
this.articleMapper = articleMapper;
}
@Override
@Transactional(rollbackFor = Exception.class)
public Long publishArticle(ArticlePublishDTO dto, Long userId) {
// 参数校验
if (dto.getTitle() == null || dto.getTitle().trim().isEmpty()) {
throw new IllegalArgumentException("文章标题不能为空");
}
if (dto.getContent() == null || dto.getContent().trim().isEmpty()) {
throw new IllegalArgumentException("文章内容不能为空");
}
// 构建文章实体
Article article = new Article();
article.setTitle(dto.getTitle());
article.setContent(dto.getContent());
article.setSummary(dto.getSummary() != null ? dto.getSummary() : dto.getContent().substring(0, Math.min(200, dto.getContent().length())));
article.setUserId(userId);
article.setCategoryId(dto.getCategoryId());
article.setStatus(dto.getStatus() != null ? dto.getStatus() : 1); // 默认直接发布
article.setCreateTime(LocalDateTime.now());
article.setUpdateTime(LocalDateTime.now());
// 保存文章
articleMapper.insert(article);
return article.getId();
}
}2. 文章列表查询接口
支持按分类、关键词搜索、分页查询已发布的文章,以下是Controller层的实现:
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ArticleController {
private final ArticleService articleService;
public ArticleController(ArticleService articleService) {
this.articleService = articleService;
}
@GetMapping("/articles")
public Page<ArticleVO> listArticles(
@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize,
@RequestParam(required = false) Long categoryId,
@RequestParam(required = false) String keyword) {
// 构建查询条件,只查询已发布的文章
LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Article::getStatus, 1);
if (categoryId != null) {
queryWrapper.eq(Article::getCategoryId, categoryId);
}
if (keyword != null && !keyword.trim().isEmpty()) {
queryWrapper.like(Article::getTitle, keyword).or().like(Article::getSummary, keyword);
}
queryWrapper.orderByDesc(Article::getCreateTime);
// 分页查询并转换为VO返回
Page<Article> page = new Page<>(pageNum, pageSize);
Page<Article> articlePage = articleService.page(page, queryWrapper);
return articleService.convertToVO(articlePage);
}
}3. 前端文章发布页面
使用Thymeleaf模板渲染的文章发布页面,包含标题输入、Markdown编辑器、分类选择等功能:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>发布文章</title>
<link rel="stylesheet" href="/css/markdown-editor.css">
</head>
<body>
<div class="container">
<h2>发布新文章</h2>
<form th:action="@{/article/publish}" method="post">
<div class="form-group">
<label for="title">文章标题</label>
<input type="text" id="title" name="title" class="form-control" required>
</div>
<div class="form-group">
<label for="category">文章分类</label>
<select id="category" name="categoryId" class="form-control">
<option th:each="cat : ${categories}" th:value="${cat.id}" th:text="${cat.name}"></option>
</select>
</div>
<div class="form-group">
<label for="content">文章内容(支持Markdown)</label>
<textarea id="content" name="content" class="markdown-editor" rows="20" required></textarea>
</div>
<div class="form-group">
<label for="summary">文章摘要(可选)</label>
<textarea id="summary" name="summary" class="form-control" rows="3"></textarea>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">发布文章</button>
<button type="button" class="btn btn-secondary" onclick="saveDraft()">保存草稿</button>
</div>
</form>
</div>
<script src="/js/markdown-editor.js"></script>
<script>
function saveDraft() {
// 草稿保存逻辑,将状态设为0提交
let form = document.querySelector('form');
let input = document.createElement('input');
input.type = 'hidden';
input.name = 'status';
input.value = '0';
form.appendChild(input);
form.submit();
}
</script>
</body>
</html>开发注意事项
在开发过程中有几个点需要特别注意,避免后续踩坑:
- 用户密码不能明文存储,需要使用BCrypt等算法加密后再存入数据库,Spring Security自带了BCrypt加密工具可以直接使用
- 文章内容是用户输入的富文本或者Markdown,需要做XSS防护,避免恶意脚本注入,可以使用HtmlUtils等工具做转义处理
- 分页查询时一定要给常用查询字段加索引,比如文章的创建时间、分类ID,避免数据量增大后查询变慢
- 权限校验要覆盖所有管理类接口,比如删除文章、审核评论的接口,需要判断当前用户是否是管理员,避免普通用户操作敏感数据
- 如果需要支持图片上传,建议把图片存储到对象存储或者本地指定目录,不要直接把图片转成base64存到数据库,会增加数据库存储压力
完成以上核心功能后,一个可用的小型博客发布平台就基本成型了。后续可以根据需求扩展功能,比如添加文章阅读量统计、RSS订阅、标签云、友情链接等,逐步完善平台的能力。
Java博客开发Spring_BootMyBatis_Plus博客系统设计权限控制修改时间:2026-05-24 12:41:42