1. 项目概述
这个前后端分离的个人博客系统是我最近完成的一个练手项目,主要目的是实践Spring Boot全栈开发和自动化测试流程。系统采用了经典的三层架构,前端使用HTML+CSS+JavaScript实现页面交互,后端基于Spring Boot框架开发,数据库选用MySQL存储数据,最终部署在云服务器上。
作为一个轻量级的博客系统,它实现了最基础的博客管理功能:
- 用户登录/注销
- 博客文章的增删改查
- 文章列表分页展示
- 文章详情查看
虽然功能相对简单,但完整实现了从开发到测试再到部署的全流程。特别在测试环节,我重点实践了自动化测试方案,包括功能测试、接口测试和性能测试,确保系统质量的同时也提升了测试效率。
2. 技术架构设计
2.1 前端架构
前端采用传统的HTML+CSS+JavaScript技术栈,没有使用任何前端框架,主要考虑点是:
- 项目规模较小,引入框架会增加复杂度
- 纯原生实现更有利于理解浏览器工作原理
- 减少依赖,部署更简单
页面结构设计为四个核心视图:
- 登录页:处理用户认证
- 列表页:展示文章概要
- 详情页:显示完整文章内容
- 编辑页:支持文章创建和修改
2.2 后端架构
后端基于Spring Boot构建,主要技术选型如下:
| 技术组件 | 版本 | 用途说明 |
|---|---|---|
| Spring Boot | 2.7.0 | 基础框架 |
| Spring Security | 5.7.1 | 认证授权 |
| MyBatis | 2.2.2 | ORM框架 |
| MySQL | 8.0.29 | 数据存储 |
| Lombok | 1.18.24 | 简化代码 |
分层架构设计:
com.example.blog ├── config # 配置类 ├── controller # 控制器层 ├── service # 业务逻辑层 ├── mapper # 数据访问层 ├── entity # 实体类 └── util # 工具类2.3 数据库设计
数据库仅包含两张核心表:
用户表(blog_user)
CREATE TABLE `blog_user` ( `id` int NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL, `password` varchar(100) NOT NULL, `avatar` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `username` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;文章表(blog_post)
CREATE TABLE `blog_post` ( `id` int NOT NULL AUTO_INCREMENT, `title` varchar(100) NOT NULL, `content` text NOT NULL, `author_id` int NOT NULL, `create_time` datetime NOT NULL, `update_time` datetime NOT NULL, PRIMARY KEY (`id`), KEY `author_id` (`author_id`), CONSTRAINT `blog_post_ibfk_1` FOREIGN KEY (`author_id`) REFERENCES `blog_user` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;3. 核心功能实现
3.1 用户认证模块
系统采用基于Session的认证方式,主要流程:
- 用户提交用户名密码
- 后端校验凭证有效性
- 创建Session并返回认证成功响应
- 前端存储Session ID用于后续请求
关键代码实现:
@PostMapping("/login") public Result login(@RequestBody LoginDTO dto, HttpSession session) { User user = userService.getByUsername(dto.getUsername()); if(user == null || !passwordEncoder.matches(dto.getPassword(), user.getPassword())) { return Result.fail("用户名或密码错误"); } session.setAttribute("user", user); return Result.ok(); }注意:实际项目中应该使用更安全的认证方案,如JWT+HTTPS。这里为了简化实现使用了Session认证。
3.2 博客管理模块
文章管理实现了基本的CRUD操作:
新增文章
@PostMapping("/posts") public Result addPost(@RequestBody PostDTO dto, HttpSession session) { User user = (User) session.getAttribute("user"); if(user == null) { return Result.fail("请先登录"); } Post post = new Post(); post.setTitle(dto.getTitle()); post.setContent(dto.getContent()); post.setAuthorId(user.getId()); post.setCreateTime(LocalDateTime.now()); post.setUpdateTime(LocalDateTime.now()); postMapper.insert(post); return Result.ok(post); }分页查询
@GetMapping("/posts") public Result listPosts( @RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer size) { PageHelper.startPage(page, size); List<PostVO> posts = postMapper.selectWithAuthor(); PageInfo<PostVO> pageInfo = new PageInfo<>(posts); return Result.ok(pageInfo); }4. 自动化测试实践
4.1 功能测试方案
采用Selenium 4 + JUnit 5组合实现Web自动化测试,主要特点:
- 页面对象模式:每个页面封装为独立测试类
- 参数化测试:支持多账号登录验证
- 智能等待:隐式等待确保元素加载
- 测试套件:统一执行所有测试用例
测试类结构:
src/test/java ├── common │ └── AutoTestUtils.java # 公共工具类 ├── tests │ ├── BlogLoginTest.java # 登录页测试 │ ├── BlogListTest.java # 列表页测试 │ ├── BlogEditTest.java # 编辑页测试 │ └── BlogDetailTest.java # 详情页测试 └── runSuite.java # 测试套件典型测试用例示例:
@Test @Order(2) public void testLoginSuccess() { driver.findElement(By.id("username")).sendKeys("zhangsan"); driver.findElement(By.id("password")).sendKeys("123456"); driver.findElement(By.id("login-btn")).click(); // 验证跳转到列表页 String currentUrl = driver.getCurrentUrl(); assertTrue(currentUrl.contains("list.html")); // 验证用户信息显示 String username = driver.findElement(By.className("user-name")).getText(); assertEquals("张三", username); }4.2 接口自动化测试
使用RestAssured + JUnit 5实现接口测试,关键设计:
- 全局Token管理:登录后自动传递token
- 统一请求工具:封装GET/POST请求方法
- 多环境配置:支持测试/生产环境切换
- Allure报告:生成可视化测试报告
接口测试示例:
@Test @Order(1) public void testLoginSuccess() { Map<String, String> params = new HashMap<>(); params.put("username", "zhangsan"); params.put("password", "123456"); Response response = RequestUtil.post("/api/login", params); assertEquals(200, response.getStatusCode()); String token = response.jsonPath().getString("data.token"); YamlUtil.writeToken(token); // 保存token供后续使用 }4.3 性能测试实施
使用JMeter进行压力测试,主要场景:
- 登录接口:模拟多用户并发登录
- 博客发布:测试文章创建性能
- 列表查询:验证分页查询效率
测试配置参数:
- 线程组:100并发用户
- 持续时间:5分钟
- 响应超时:3秒
- 断言规则:响应码200,响应时间<1s
性能测试结果分析:
聚合报告: - 样本数:3250 - 平均响应时间:428ms - 吞吐量:10.8/sec - 错误率:0.12%5. 部署与运维
5.1 服务器环境准备
系统部署在1核2G的云服务器上,环境配置如下:
基础环境
- CentOS 7.6
- JDK 11
- MySQL 8.0
- Nginx 1.20
部署目录结构
/opt/blog ├── app # Spring Boot jar包 ├── conf # 配置文件 ├── logs # 日志文件 └── web # 前端静态资源
5.2 应用部署脚本
使用Shell脚本简化部署流程:
启动脚本(start.sh)
#!/bin/bash # 启动MySQL systemctl start mysqld # 启动后端应用 nohup java -jar /opt/blog/app/blog-api.jar \ --spring.profiles.active=prod \ > /opt/blog/logs/application.log 2>&1 & # 启动Nginx systemctl start nginx健康检查脚本(healthcheck.sh)
#!/bin/bash # 检查MySQL状态 mysql_status=$(systemctl is-active mysqld) if [ "$mysql_status" != "active" ]; then echo "MySQL is not running!" exit 1 fi # 检查应用进程 if ! pgrep -f "blog-api.jar" > /dev/null; then echo "Application is not running!" exit 1 fi # 检查端口监听 if ! netstat -tulnp | grep ':8080' > /dev/null; then echo "Application port is not listening!" exit 1 fi echo "All services are running normally" exit 06. 经验总结与优化建议
6.1 项目亮点
- 完整的自动化测试体系:从功能测试到接口测试再到性能测试,建立了全方位的质量保障
- 清晰的代码结构:严格遵循分层架构,模块职责单一
- 高效的部署方案:使用脚本实现一键部署,降低运维成本
- 详细的文档记录:测试用例、部署步骤等均有完整文档
6.2 待改进点
- 用户系统不完善:缺少注册、密码找回等功能
- 前端交互较简单:没有使用现代前端框架,体验有待提升
- 安全性不足:缺乏XSS防护、CSRF防御等安全措施
- 性能瓶颈:高并发场景下数据库连接成为瓶颈
6.3 优化方向
- 引入缓存:使用Redis缓存热点数据,减轻数据库压力
- 前端重构:采用Vue/React框架提升交互体验
- 安全加固:增加输入校验、防注入等安全措施
- 微服务化:将单体应用拆分为微服务,提高可扩展性
这个项目虽然功能简单,但完整走完了从开发到测试再到部署的全流程,让我对Spring Boot全栈开发有了更深入的理解。特别是在自动化测试方面积累了不少实战经验,这对保证项目质量至关重要。后续计划在此基础上继续迭代,将其发展为一个功能更完善的博客平台。