1. 为什么选择SpringBoot开发个人博客
第一次用SpringBoot搭建个人博客时,我踩了不少坑。记得当时为了配置一个简单的分页功能,折腾了整整两天。但现在回头看,SpringBoot确实是Java开发者搭建个人项目的最佳选择。
SpringBoot最大的优势就是开箱即用。你不用再为各种XML配置头疼,内置的Tomcat服务器让部署变得异常简单。我实测过,从零开始搭建一个基础博客框架,用SpringBoot只需要15分钟,而传统Spring MVC至少需要半天。
对于个人博客这种中小型项目,SpringBoot提供了恰到好处的功能组合:
- 内嵌数据库支持(H2/SQLite开发阶段特别方便)
- 自动化的依赖管理(starter系列依赖真香)
- 完善的文档生态(遇到问题99%能在Stack Overflow找到答案)
2. 项目架构设计
2.1 技术选型心得
去年帮学弟调试他的毕业设计时,发现很多初学者最容易犯的错误就是技术堆砌。明明是个个人博客,非要上Spring Cloud全家桶。我的建议是:用最合适的技术解决最核心的需求。
这是我的技术选型方案:
- 核心框架:SpringBoot 2.7.x(LTS版本更稳定) - 模板引擎:Thymeleaf(比JSP优雅,支持HTML原型) - 数据库:MySQL 8.0(开发版可用MariaDB替代) - ORM:MyBatis-Plus(省去80%的CRUD代码) - 前端组件:Semantic UI + jQuery(轻量够用)特别提醒:新手常忽略的版本兼容性问题。比如SpringBoot 2.7.x默认集成的MyBatis版本是3.5.9,如果手动引入3.4.0就会冲突。建议用Maven的dependency:tree命令检查依赖树。
2.2 模块划分技巧
我把博客系统拆分成这几个模块:
blog-core/ # 核心实体类 │ ├── entity/ │ ├── dto/ │ └── vo/ blog-admin/ # 后台管理 │ ├── controller/ │ ├── service/ │ └── mapper/ blog-web/ # 前端展示 │ ├── controller/ │ └── templates/ config/ # 配置类 │ ├── WebMvcConfig.java │ └── MyBatisConfig.java这种结构的好处是:
- 功能边界清晰,改后台代码不会影响前端展示
- 便于后期扩展(比如想加API模块直接新建blog-api)
- 多人协作时冲突少(不同人负责不同模块)
3. 核心功能实现
3.1 用户认证方案对比
我试过三种登录方案:
- 原生Session:最简单但集群部署会出问题
- JWT:无状态但注销机制复杂
- Spring Security:功能强大但学习曲线陡峭
最终选择Session+拦截器的方案,代码量最少且够用:
// 登录拦截器示例 public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (request.getSession().getAttribute("user") == null) { response.sendRedirect("/admin/login"); return false; } return true; } }在WebMvcConfig中配置拦截路径:
@Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) .addPathPatterns("/admin/**") .excludePathPatterns("/admin/login"); }3.2 博客编辑器的坑
Markdown编辑器我对比过:
- Editor.md:功能全但体积大(800KB+)
- SimpleMDE:已停止维护
- Toast UI Editor:韩国产品,中文文档少
最终选择了TinyMCE,虽然要付费但基础版免费够用。集成时要注意:
// 初始化配置要加这行,否则中文会乱码 tinymce.init({ language: 'zh_CN', plugins: 'image code link', toolbar: 'undo redo | link image | code' });上传图片需要单独处理:
@PostMapping("/upload") @ResponseBody public Map<String, Object> upload(@RequestParam("file") MultipartFile file) { String url = fileService.upload(file); return Map.of("location", url); // TinyMCE要求的返回格式 }4. 部署实战经验
4.1 打包优化技巧
默认的SpringBoot打包会包含所有依赖,jar包往往50MB+。通过配置可以瘦身:
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build>4.2 服务器配置
最低配置建议:
- 1核CPU
- 2GB内存
- 40GB SSD
关键配置项:
# 设置JVM参数 JAVA_OPTS="-Xms512m -Xmx1024m -XX:MaxPermSize=256m" # 启动命令 nohup java -jar blog.jar --spring.profiles.active=prod > log.out 2>&1 &遇到过最头疼的问题是内存泄漏,后来用Arthas定位到是分页查询没关闭连接。推荐用Docker部署,资源隔离更安全:
FROM openjdk:8-jdk-alpine VOLUME /tmp COPY target/blog.jar app.jar ENTRYPOINT ["java","-jar","/app.jar"]5. 性能优化方案
5.1 缓存策略
我的三级缓存方案:
- 本地缓存(Caffeine):高频访问的博客详情
- Redis缓存:分类列表、热门文章
- 数据库缓存:MySQL查询缓存
配置示例:
@Configuration @EnableCaching public class CacheConfig { @Bean public CacheManager cacheManager() { CaffeineCacheManager manager = new CaffeineCacheManager(); manager.setCaffeine(Caffeine.newBuilder() .expireAfterWrite(10, TimeUnit.MINUTES) .maximumSize(1000)); return manager; } }5.2 数据库优化
给博客表加索引的教训:
-- 原来查询要2s SELECT * FROM articles WHERE category_id = 5; -- 加上组合索引后200ms ALTER TABLE articles ADD INDEX idx_category_status (category_id, status);慢查询日志中发现分页是大坑:
// 错误写法(性能差) PageHelper.startPage(1, 10); List<Blog> list = blogMapper.selectAll(); // 正确写法(先分页再关联) PageHelper.startPage(1, 10); List<Blog> list = blogMapper.selectWithComments();6. 常见问题排查
6.1 跨域问题
前端报错"Access-Control-Allow-Origin"时,后端要配置:
@Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("GET", "POST"); } }6.2 静态资源404
SpringBoot默认静态资源路径是:
- classpath:/static/
- classpath:/public/
如果放在resources/templates下会访问不到。建议统一管理:
spring: mvc: static-path-pattern: /assets/**7. 扩展功能实现
7.1 评论楼中楼
用parent_id实现层级关系:
public class Comment { private Long id; private Long articleId; private Long parentId; // 父评论ID private String content; private List<Comment> replies; // 子评论 }查询时使用递归:
<select id="selectByArticle" resultMap="commentTree"> WITH RECURSIVE cte AS ( SELECT * FROM comment WHERE article_id=#{articleId} AND parent_id=0 UNION ALL SELECT c.* FROM comment c JOIN cte ON c.parent_id=cte.id ) SELECT * FROM cte </select>7.2 音乐播放器
前端用APlayer插件:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css"> <div id="player"></div> <script> const ap = new APlayer({ container: document.getElementById('player'), audio: [{ name: '晴天', artist: '周杰伦', url: '/music/sunny.mp3' }] }); </script>8. 项目演进建议
当博客访问量破万后,可以考虑:
- 动静分离:Nginx处理静态资源
- CDN加速:图片等大文件走CDN
- 读写分离:MySQL主从架构
- 消息队列:异步处理邮件通知
最简单的升级方案是改用Spring Cloud Alibaba,但个人博客其实用不上微服务。我的经验是:不要过度设计,等真正遇到性能瓶颈再优化。