Spring Boot+Vue全栈开发:高校毕业设计选题平台实战解析
1. 项目背景与技术选型
每到毕业季,高校都会面临一个共同的难题:如何高效管理数百名学生的毕业设计选题工作。传统的人工登记方式不仅效率低下,还容易出现信息错漏。这正是我们选择开发毕业设计选题管理系统的初衷——用技术手段解决实际教学管理痛点。
在技术选型上,我们采用了当前主流的全栈开发方案:
- 后端:Spring Boot 2.7 + MyBatis-Plus
- 前端:Vue 3 + Element Plus
- 数据库:MySQL 8.0
这个组合的优势非常明显:Spring Boot的自动配置让我们能快速搭建后端服务,Vue的响应式特性让前端开发事半功倍,而MyBatis-Plus则大大简化了数据库操作。记得第一次用MyBatis-Plus的Lambda查询时,我被它的简洁惊艳到了——原本需要写十几行的SQL查询,现在只需要几行Java代码就能搞定。
2. 系统架构设计
整个系统采用经典的三层架构,但我们在传统架构上做了一些优化:
前端层(Vue3)
│
├─ 展示组件
├─ 路由管理
└─ 状态管理(Pinia)
后端层(Spring Boot)
│
├─ 控制层(Controller)
├─ 服务层(Service)
└─ 数据访问层(Mapper)
数据层
│
├─ MySQL(主数据库)
└─ Redis(缓存)
权限控制是这类系统的核心难点。我们采用RBAC(基于角色的访问控制)模型,定义了三种角色:
- 管理员:拥有系统全部权限
- 教师:可以发布和管理课题
- 学生:只能申请和查看课题
在实现上,我们用了Spring Security结合JWT(JSON Web Token)的方案。这里有个小技巧:在生成Token时,我们把用户角色信息直接编码进去,这样前端就能根据Token动态渲染菜单权限。
3. 数据库设计要点
数据库设计往往决定了系统的扩展性和性能。我们的ER图包含以下几个核心表:
CREATE TABLE `user` (
`id` varchar(32) NOT NULL COMMENT '用户ID',
`username` varchar(50) NOT NULL COMMENT '用户名',
`password` varchar(100) NOT NULL COMMENT '密码',
`role` enum('ADMIN','TEACHER','STUDENT') NOT NULL COMMENT '角色',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `topic` (
`id` varchar(32) NOT NULL COMMENT '课题ID',
`title` varchar(200) NOT NULL COMMENT '课题名称',
`description` text COMMENT '课题描述',
`teacher_id` varchar(32) NOT NULL COMMENT '指导教师ID',
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '状态:0-待审核 1-已发布 2-已选定',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_teacher` (`teacher_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
特别注意这几个设计决策:
- 所有表都使用varchar(32)作为主键,而不是自增ID,这样更利于分布式部署
- 建立合适的索引(如用户名的唯一索引)
- 使用枚举类型明确角色取值范围
4. 核心功能实现
4.1 课题发布流程
教师发布课题的接口实现很有代表性:
@PostMapping("/topics")
@PreAuthorize("hasRole('TEACHER')")
public Result publishTopic(@RequestBody TopicDTO dto,
@RequestHeader("Authorization") String token) {
// 从Token中解析教师ID
String teacherId = JwtUtil.getUserId(token);
Topic topic = new Topic();
BeanUtils.copyProperties(dto, topic);
topic.setTeacherId(teacherId);
topic.setStatus(TopicStatus.PENDING_REVIEW);
if (topicService.save(topic)) {
return Result.success("课题提交成功,等待审核");
}
return Result.error("课题提交失败");
}
前端对应的Vue组件需要注意表单验证:
<template>
<el-form :model="form" :rules="rules" ref="formRef">
<el-form-item label="课题名称" prop="title">
<el-input v-model="form.title" />
</el-form-item>
<el-form-item label="课题描述" prop="description">
<el-input type="textarea" v-model="form.description" />
</el-form-item>
<el-button type="primary" @click="submit">提交</el-button>
</el-form>
</template>
<script setup>
const form = reactive({
title: '',
description: ''
});
const rules = {
title: [{ required: true, message: '请输入课题名称', trigger: 'blur' }],
description: [{ required: true, message: '请输入课题描述', trigger: 'blur' }]
};
const submit = () => {
// 调用API接口...
};
</script>
4.2 选题申请功能
学生申请课题时需要考虑并发问题——热门课题可能被多人同时申请。我们采用乐观锁来解决:
@Transactional
public boolean applyTopic(String studentId, String topicId) {
// 检查学生是否已有课题
if (applicationMapper.existsByStudentId(studentId)) {
throw new BusinessException("每位学生只能选择一个课题");
}
// 使用乐观锁更新课题状态
int updated = topicMapper.updateStatusIfNotSelected(topicId);
if (updated == 0) {
throw new BusinessException("该课题已被其他同学选择");
}
// 记录申请
Application app = new Application();
app.setStudentId(studentId);
app.setTopicId(topicId);
app.setApplyTime(LocalDateTime.now());
return applicationMapper.insert(app) > 0;
}
对应的SQL语句:
UPDATE topic
SET status = 2
WHERE id = #{topicId} AND status = 1
5. 踩坑与优化经验
在开发过程中,我们遇到过几个典型问题:
- 跨域问题:开发阶段前端访问后端API时出现CORS错误。解决方案是在Spring Boot中添加配置类:
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("*");
}
}
-
性能优化:课题列表页在数据量大的时候加载缓慢。我们通过以下措施优化:
- 添加Redis缓存热门查询
- 实现分页查询
- 使用MyBatis-Plus的QueryWrapper构建动态查询
-
文件导入功能:批量导入学生信息时,最初的做法是逐条插入,速度极慢。后来改为批量插入:
@Transactional
public void batchImportStudents(MultipartFile file) {
List<Student> students = parseExcel(file); // 解析Excel
if (!students.isEmpty()) {
// 使用MyBatis-Plus的saveBatch方法
studentService.saveBatch(students, 100); // 每批100条
}
}
6. 部署与运维
项目最终采用Docker Compose部署,docker-compose.yml配置如下:
version: '3'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: thesis
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:6
ports:
- "6379:6379"
backend:
build: ./backend
ports:
- "8080:8080"
depends_on:
- mysql
- redis
frontend:
build: ./frontend
ports:
- "80:80"
volumes:
mysql_data:
部署时需要注意:
- 确保MySQL和Redis容器先启动
- 后端应用需要等待数据库就绪后再启动(可以使用wait-for-it.sh脚本)
- 前端构建时需要配置正确的API基础地址
7. 项目扩展方向
这个基础系统还可以进一步扩展:
- 微信小程序端:方便学生随时查看选题状态
- 智能推荐:根据学生专业和兴趣推荐合适课题
- 过程管理:增加开题报告、中期检查等环节
- 查重集成:对接论文查重服务
我在实际开发中发现,使用Elasticsearch实现课题搜索功能能显著提升用户体验。只需要在Spring Boot中集成Spring Data Elasticsearch,就能轻松实现全文检索:
public interface TopicRepository extends ElasticsearchRepository<Topic, String> {
List<Topic> findByTitleOrDescription(String title, String description);
}
这个毕业设计选题平台从需求分析到最终上线历时三个月,期间遇到了各种技术挑战,但也收获满满。最让我自豪的是,系统上线后真正帮助学院简化了选题流程,老师们再也不用熬夜整理Excel表格了。如果你正在学习全栈开发,这类实战项目绝对是提升技能的绝佳选择。
更多推荐


所有评论(0)