ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于SpringBoot的毕业设计选题系统:从需求到部署的全栈实战

基于SpringBoot的毕业设计选题系统:从需求到部署的全栈实战 每到毕业季计算机相关专业的学生们都会面临一个共同的难题如何高效、公平地完成毕业设计选题。传统的线下选题方式如纸质表格、邮件沟通或简单的Excel共享常常伴随着信息不同步、选题冲突、导师协调困难、进度难以追踪等一系列痛点。本文将分享一个基于Java和SpringBoot的完整毕业设计选题系统的设计与实现从需求分析、技术选型、数据库设计到前后端代码实现提供一套可直接部署、二次开发的实战项目方案。无论你是正在寻找毕业设计课题的学生还是希望学习SpringBoot全栈开发的开发者都能从本文中获得从零到一的完整构建思路和可运行的源码。1. 系统需求分析与核心功能设计在动手编码之前明确系统的用户角色和核心功能是项目成功的关键。一个典型的毕业设计选题系统通常涉及三类用户学生、教师导师和管理员。1.1 用户角色与核心诉求学生核心诉求浏览所有可选的课题、查看课题详情包括导师信息、要求、已选人数、选择自己心仪的课题、查看自己的选题状态、与导师进行简单的在线沟通如留言。痛点解决避免信息不对称实时查看课题名额减少因沟通不畅导致的选题冲突。教师导师核心诉求发布和管理自己的课题增删改查、审核选择自己课题的学生通过/拒绝、查看最终确定的学生名单、发布任务或通知。痛点解决简化课题发布流程集中管理学生申请高效完成双向选择。管理员核心诉求管理所有用户学生、教师账户、审核教师发布的课题确保合规性、监控整个选题流程的进度如各阶段时间设置、处理系统异常如重置密码。痛点解决确保系统运行的秩序和公平性拥有最高权限进行全局调控。1.2 系统核心功能模块基于以上角色分析我们可以将系统拆解为以下几个核心功能模块用户认证与权限管理模块实现用户登录、注册通常由管理员初始化或导入、基于角色ROLE_STUDENT, ROLE_TEACHER, ROLE_ADMIN的页面访问和操作权限控制。课题信息管理模块教师端课题的创建、编辑、删除、发布与下架。学生端课题列表分页展示、多条件如导师、课题名称、状态检索、课题详情查看。管理员端课题审核审核通过后方可对学生可见。选题流程管理模块学生端提交选题申请、查看申请状态待审核、已通过、被拒绝、在允许的时间内取消申请或改选。教师端查看申请自己课题的学生列表、审核申请通过或拒绝需有理由可选。系统逻辑确保一个学生同一时间只能有一个“待审核”或“已通过”的选题确保课题人数不超过上限。通知与简单沟通模块系统站内消息通知如选题结果通知、审核通知等。可扩展为简单的留言板功能。后台管理模块管理员专属功能包括用户管理、系统公告发布、选题阶段时间节点配置如开始时间、截止时间、数据统计报表等。2. 技术选型与环境准备一个稳定、高效、易于开发和维护的技术栈是项目的基石。我们选择目前Java领域最主流的SpringBoot全家桶进行后端开发配合成熟的前后端分离方案。2.1 后端技术栈核心框架Spring Boot 2.7.x。它提供了极简的配置和快速启动能力是构建现代Java Web应用的标准选择。持久层框架MyBatis-Plus 3.5.x。它在MyBatis的基础上进行了增强提供了强大的CRUD操作和条件构造器能极大减少SQL编写工作量。安全框架Spring Security 5.7.x。用于处理用户认证登录和授权权限检查是保护系统安全的必备组件。数据库MySQL 8.0。关系型数据库用于存储用户、课题、选题记录等结构化数据。API文档Knife4j 3.0.x。基于Swagger的增强UI用于自动生成和调试后端RESTful API接口文档。项目构建Maven 3.6 或 Gradle。本文示例使用Maven。其他工具Lombok简化Java Bean编写、HutoolJava工具类库、FastjsonJSON处理。2.2 前端技术栈可选方案为了快速成型和降低前端复杂度可以选择以下两种方案之一方案A前后端不分离使用Thymeleaf模板引擎。SpringBoot原生支持适合全栈Java开发者开发速度快但前后端耦合。方案B前后端分离使用Vue.js Element UI。这是目前主流选择前后端职责清晰用户体验好。后端仅提供JSON API接口。 考虑到毕业设计项目通常需要展示完整流程且为了聚焦后端核心逻辑本文后续代码讲解将侧重于后端API的实现并假定前端采用VueElement UI方案进行交互。前端代码会提供关键页面逻辑说明。2.3 开发环境准备JDK安装JDK 8或JDK 11并配置好JAVA_HOME环境变量。IDEIntelliJ IDEA推荐或Eclipse。MySQL安装MySQL 8.0并创建一个名为graduation_topic的数据库字符集建议为utf8mb4。CREATE DATABASE IF NOT EXISTS graduation_topic DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;Maven安装Maven并配置好仓库镜像可使用阿里云镜像加速。浏览器用于测试前端如Chrome和API可使用Postman或Knife4j界面。3. 数据库设计与核心表结构良好的数据库设计是系统稳定运行的基础。以下是核心表结构设计使用MyBatis-Plus时对应的实体类将基于此设计。3.1 用户表 (sys_user)存储所有系统用户学生、教师、管理员的基础信息。CREATE TABLE sys_user ( id bigint NOT NULL AUTO_INCREMENT COMMENT 主键ID, username varchar(50) NOT NULL COMMENT 用户名学号/工号, password varchar(100) NOT NULL COMMENT 加密后的密码, real_name varchar(20) DEFAULT NULL COMMENT 真实姓名, role varchar(20) NOT NULL COMMENT 角色STUDENT, TEACHER, ADMIN, email varchar(100) DEFAULT NULL COMMENT 邮箱, phone varchar(20) DEFAULT NULL COMMENT 电话, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间, is_deleted tinyint DEFAULT 0 COMMENT 逻辑删除标志0未删1已删, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_unicode_ci COMMENT系统用户表;3.2 课题表 (topic)存储教师发布的课题信息。CREATE TABLE topic ( id bigint NOT NULL AUTO_INCREMENT COMMENT 课题ID, teacher_id bigint NOT NULL COMMENT 发布教师ID关联sys_user.id, title varchar(200) NOT NULL COMMENT 课题标题, description text COMMENT 课题详细描述和要求, max_selected int DEFAULT 1 COMMENT 最大可选人数, current_selected int DEFAULT 0 COMMENT 当前已选人数, status varchar(20) DEFAULT PENDING_REVIEW COMMENT 状态PENDING_REVIEW(待审核), APPROVED(已审核通过), REJECTED(被驳回), CLOSED(已关闭), review_comment varchar(500) DEFAULT NULL COMMENT 管理员审核意见, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间, PRIMARY KEY (id), KEY idx_teacher_id (teacher_id), KEY idx_status (status) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_unicode_ci COMMENT课题表;3.3 选题记录表 (selection_record)记录学生的选题申请和教师的审核结果。CREATE TABLE selection_record ( id bigint NOT NULL AUTO_INCREMENT COMMENT 记录ID, student_id bigint NOT NULL COMMENT 学生ID关联sys_user.id, topic_id bigint NOT NULL COMMENT 课题ID关联topic.id, status varchar(20) DEFAULT PENDING COMMENT 状态PENDING(待审核), APPROVED(已通过), REJECTED(被拒绝), apply_comment varchar(500) DEFAULT NULL COMMENT 学生申请理由, review_comment varchar(500) DEFAULT NULL COMMENT 教师审核意见, apply_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 申请时间, review_time datetime DEFAULT NULL COMMENT 审核时间, PRIMARY KEY (id), UNIQUE KEY uk_student_current (student_id, status) COMMENT 一个学生只能有一个进行中的选题, KEY idx_topic_id (topic_id), KEY idx_student_id (student_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_unicode_ci COMMENT选题记录表;注意uk_student_current唯一索引配合业务逻辑用于保证学生不能同时有多个“PENDING”或“APPROVED”状态的记录。更复杂的约束如检查status值可能需要在应用层代码中实现。4. SpringBoot后端核心代码实现接下来我们搭建SpringBoot项目并实现核心业务逻辑。项目采用经典的分层架构Controller - Service - Mapper。4.1 项目初始化与依赖配置使用Spring Initializr或IDE创建SpringBoot项目主要依赖如下pom.xml片段dependencies !-- SpringBoot Web -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- MyBatis-Plus -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3.1/version /dependency !-- MySQL驱动 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency !-- Spring Security -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-security/artifactId /dependency !-- Lombok -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency !-- Knife4j API文档 -- dependency groupIdcom.github.xiaoymin/groupId artifactIdknife4j-spring-boot-starter/artifactId version3.0.3/version /dependency !-- Hutool工具包 -- dependency groupIdcn.hutool/groupId artifactIdhutool-all/artifactId version5.8.16/version /dependency /dependencies4.2 实体类与Mapper使用MyBatis-Plus实体类与Mapper的编写非常简洁。以Topic实体为例文件路径src/main/java/com/graduation/topic/entity/Topic.javapackage com.graduation.topic.entity; import com.baomidou.mybatisplus.annotation.*; import lombok.Data; import java.time.LocalDateTime; Data TableName(topic) public class Topic { TableId(type IdType.AUTO) private Long id; private Long teacherId; private String title; private String description; private Integer maxSelected; private Integer currentSelected; private String status; // 使用枚举更佳此处简化为字符串 private String reviewComment; TableField(fill FieldFill.INSERT) private LocalDateTime createTime; TableField(fill FieldFill.INSERT_UPDATE) private LocalDateTime updateTime; }文件路径src/main/java/com/graduation/topic/mapper/TopicMapper.javapackage com.graduation.topic.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.graduation.topic.entity.Topic; import org.apache.ibatis.annotations.Mapper; Mapper public interface TopicMapper extends BaseMapperTopic { // 继承BaseMapper即拥有了基本的CRUD方法 }4.3 Service层业务逻辑Service层封装核心业务规则。以下是TopicService中发布课题和选择课题的关键方法。文件路径src/main/java/com/graduation/topic/service/TopicService.javapackage com.graduation.topic.service; import com.baomidou.mybatisplus.extension.service.IService; import com.graduation.topic.entity.Topic; import com.graduation.topic.vo.TopicVO; public interface TopicService extends IServiceTopic { /** * 教师发布新课题 * param topic 课题信息 * param teacherId 教师ID * return 是否成功 */ boolean publishTopic(Topic topic, Long teacherId); /** * 学生选择课题 * param topicId 课题ID * param studentId 学生ID * param applyComment 申请理由 * return 选择结果信息 */ String selectTopic(Long topicId, Long studentId, String applyComment); }文件路径src/main/java/com/graduation/topic/service/impl/TopicServiceImpl.javapackage com.graduation.topic.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.graduation.topic.entity.SelectionRecord; import com.graduation.topic.entity.Topic; import com.graduation.topic.mapper.SelectionRecordMapper; import com.graduation.topic.mapper.TopicMapper; import com.graduation.topic.service.TopicService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; Service public class TopicServiceImpl extends ServiceImplTopicMapper, Topic implements TopicService { Autowired private SelectionRecordMapper selectionRecordMapper; Override public boolean publishTopic(Topic topic, Long teacherId) { // 1. 基础校验 if (topic.getMaxSelected() null || topic.getMaxSelected() 0) { throw new RuntimeException(最大可选人数必须大于0); } // 2. 设置初始状态和关联教师 topic.setTeacherId(teacherId); topic.setStatus(PENDING_REVIEW); // 新课题需管理员审核 topic.setCurrentSelected(0); // 3. 保存到数据库 return this.save(topic); } Override Transactional(rollbackFor Exception.class) // 开启事务保证数据一致性 public String selectTopic(Long topicId, Long studentId, String applyComment) { // 1. 检查课题是否存在且状态为“已通过” Topic topic this.getById(topicId); if (topic null) { return 课题不存在; } if (!APPROVED.equals(topic.getStatus())) { return 该课题暂不可选; } // 2. 检查课题是否已满额 if (topic.getCurrentSelected() topic.getMaxSelected()) { return 该课题人数已满; } // 3. 检查该学生是否已有进行中的选题PENDING或APPROVED LambdaQueryWrapperSelectionRecord wrapper new LambdaQueryWrapper(); wrapper.eq(SelectionRecord::getStudentId, studentId) .in(SelectionRecord::getStatus, PENDING, APPROVED); Long count selectionRecordMapper.selectCount(wrapper); if (count 0) { return 您已有一个正在进行中的选题请先取消或等待审核结果; } // 4. 创建选题记录 SelectionRecord record new SelectionRecord(); record.setStudentId(studentId); record.setTopicId(topicId); record.setStatus(PENDING); record.setApplyComment(applyComment); record.setApplyTime(LocalDateTime.now()); selectionRecordMapper.insert(record); // 注意此时课题的 currentSelected 并未增加需教师审核通过后再增加 return 申请提交成功等待导师审核; } }4.4 Controller层API接口Controller层接收前端请求调用Service并返回统一格式的JSON数据。这里使用一个简单的Result类包装返回结果。文件路径src/main/java/com/graduation/topic/controller/TopicController.javapackage com.graduation.topic.controller; import com.graduation.topic.common.Result; import com.graduation.topic.entity.Topic; import com.graduation.topic.service.TopicService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.bind.annotation.*; import java.util.List; RestController RequestMapping(/api/topic) Api(tags 课题管理接口) public class TopicController { Autowired private TopicService topicService; GetMapping(/list) ApiOperation(分页查询课题列表学生/教师查看) public ResultListTopic listTopics(RequestParam(required false) String keyword, RequestParam(defaultValue APPROVED) String status) { // 构建查询条件这里简化处理实际应使用Page对象分页 ListTopic list topicService.lambdaQuery() .like(Topic::getTitle, keyword) .eq(Topic::getStatus, status) .orderByDesc(Topic::getCreateTime) .list(); return Result.success(list); } PostMapping(/publish) ApiOperation(教师发布课题) public ResultString publishTopic(RequestBody Topic topic) { // 从Spring Security上下文中获取当前登录用户ID假设已存储 // 实际项目中需要更完善的用户信息获取方式 Long teacherId getCurrentUserId(); boolean success topicService.publishTopic(topic, teacherId); if (success) { return Result.success(课题发布成功等待管理员审核); } else { return Result.error(课题发布失败); } } PostMapping(/select/{topicId}) ApiOperation(学生选择课题) public ResultString selectTopic(PathVariable Long topicId, RequestParam String applyComment) { Long studentId getCurrentUserId(); String resultMsg topicService.selectTopic(topicId, studentId, applyComment); if (resultMsg.contains(成功)) { return Result.success(resultMsg); } else { return Result.error(resultMsg); } } // 获取当前登录用户ID的辅助方法需结合Spring Security实现 private Long getCurrentUserId() { // 示例从SecurityContext中获取用户名再查询数据库获取ID // 实际项目可将UserDetails扩展直接存入ID String username SecurityContextHolder.getContext().getAuthentication().getName(); // 模拟返回ID 1实际应查询数据库 return 1L; } }4.5 Spring Security 安全配置安全配置是系统的门户负责登录认证和接口权限控制。文件路径src/main/java/com/graduation/topic/config/SecurityConfig.javapackage com.graduation.topic.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; Configuration EnableWebSecurity public class SecurityConfig { Bean public PasswordEncoder passwordEncoder() { // 使用BCrypt强哈希加密密码 return new BCryptPasswordEncoder(); } Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth - auth // 允许静态资源和登录接口匿名访问 .antMatchers(/css/**, /js/**, /images/**, /webjars/**).permitAll() .antMatchers(/api/auth/**, /doc.html, /swagger-resources/**, /v2/api-docs).permitAll() // 基于角色的权限控制 .antMatchers(/api/teacher/**).hasRole(TEACHER) .antMatchers(/api/student/**).hasRole(STUDENT) .antMatchers(/api/admin/**).hasRole(ADMIN) // 其他所有请求都需要认证 .anyRequest().authenticated() ) .formLogin(form - form .loginProcessingUrl(/api/auth/login) // 自定义登录处理URL .successHandler((request, response, authentication) - { // 登录成功返回JSON信息 response.setContentType(application/json;charsetUTF-8); response.getWriter().write({\code\:200, \msg\:\登录成功\}); }) .failureHandler((request, response, exception) - { response.setContentType(application/json;charsetUTF-8); response.getWriter().write({\code\:500, \msg\:\用户名或密码错误\}); }) .permitAll() ) .logout(logout - logout .logoutUrl(/api/auth/logout) .logoutSuccessHandler((request, response, authentication) - { response.setContentType(application/json;charsetUTF-8); response.getWriter().write({\code\:200, \msg\:\注销成功\}); }) ) .csrf().disable() // 禁用CSRF便于API测试生产环境需谨慎考虑 .sessionManagement().sessionFixation().newSession(); // 会话管理 return http.build(); } }5. 前端Vue.js关键页面示例前端使用Vue 3 Element Plus。这里展示学生选题页面的关键逻辑。文件路径src/views/student/TopicList.vuetemplate div classtopic-list el-card template #header div classcard-header span毕业设计课题列表/span el-input v-modelsearchKeyword placeholder搜索课题标题或导师 stylewidth: 300px; keyup.enterloadTopics template #append el-button :iconSearch clickloadTopics / /template /el-input /div /template el-table :datatopicList v-loadingloading el-table-column proptitle label课题标题 width300 / el-table-column propteacherName label发布导师 width120 / el-table-column propdescription label课题描述 show-overflow-tooltip / el-table-column label人数 width100 template #defaultscope span{{ scope.row.currentSelected }} / {{ scope.row.maxSelected }}/span /template /el-table-column el-table-column propstatus label状态 width100 template #defaultscope el-tag :typescope.row.status APPROVED ? success : info {{ scope.row.status APPROVED ? 可选 : 待审核 }} /el-tag /template /el-table-column el-table-column label操作 width180 fixedright template #defaultscope el-button sizesmall clickshowDetail(scope.row)详情/el-button el-button sizesmall typeprimary :disabledscope.row.status ! APPROVED || scope.row.currentSelected scope.row.maxSelected clickhandleSelect(scope.row) 选择 /el-button /template /el-table-column /el-table el-pagination size-changehandleSizeChange current-changehandleCurrentChange :current-pagecurrentPage :page-sizes[10, 20, 50] :page-sizepageSize layouttotal, sizes, prev, pager, next, jumper :totaltotal stylemargin-top: 20px; / /el-card !-- 选题申请对话框 -- el-dialog v-modelselectDialogVisible title申请课题 width500px el-form :modelselectForm label-width80px el-form-item label申请理由 el-input v-modelselectForm.applyComment typetextarea :rows4 placeholder请简要说明你的研究兴趣、相关技能或选择该课题的原因 maxlength500 show-word-limit / /el-form-item /el-form template #footer span classdialog-footer el-button clickselectDialogVisible false取消/el-button el-button typeprimary clicksubmitSelection提交申请/el-button /span /template /el-dialog /div /template script setup import { ref, onMounted } from vue import { Search } from element-plus/icons-vue import { ElMessage, ElMessageBox } from element-plus import axios from /utils/request // 封装了axios的请求工具 const searchKeyword ref() const topicList ref([]) const loading ref(false) const currentPage ref(1) const pageSize ref(10) const total ref(0) const selectDialogVisible ref(false) const selectForm ref({ topicId: null, applyComment: }) const currentTopic ref(null) // 加载课题列表 const loadTopics async () { loading.value true try { const params { page: currentPage.value, size: pageSize.value, keyword: searchKeyword.value, status: APPROVED // 只显示已审核通过的 } const res await axios.get(/api/topic/list, { params }) // 假设后端返回 { code: 200, data: { records: [], total: 0 } } if (res.code 200) { topicList.value res.data.records total.value res.data.total } } catch (error) { ElMessage.error(加载课题列表失败) } finally { loading.value false } } // 显示课题详情 const showDetail (topic) { ElMessageBox.alert(topic.description, 课题详情${topic.title}, { confirmButtonText: 关闭, customClass: topic-detail-box }) } // 处理选择课题 const handleSelect (topic) { currentTopic.value topic selectForm.value.topicId topic.id selectForm.value.applyComment selectDialogVisible.value true } // 提交选题申请 const submitSelection async () { if (!selectForm.value.applyComment.trim()) { ElMessage.warning(请输入申请理由) return } try { const res await axios.post(/api/topic/select/${selectForm.value.topicId}, null, { params: { applyComment: selectForm.value.applyComment } }) if (res.code 200) { ElMessage.success(res.msg || 申请提交成功) selectDialogVisible.value false loadTopics() // 刷新列表 } else { ElMessage.error(res.msg || 申请失败) } } catch (error) { ElMessage.error(网络错误提交失败) } } onMounted(() { loadTopics() }) /script6. 系统部署与运行6.1 后端启动与配置配置文件在src/main/resources/application.yml中配置数据库连接等信息。server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/graduation_topic?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: your_password # MyBatis-Plus配置 mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 控制台打印SQL生产环境关闭 global-config: db-config: logic-delete-field: isDeleted # 全局逻辑删除字段 logic-delete-value: 1 logic-not-delete-value: 0 # Knife4j配置 knife4j: enable: true setting: language: zh_cn启动类标准的SpringBoot启动类。package com.graduation.topic; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; SpringBootApplication public class GraduationTopicApplication { public static void main(String[] args) { SpringApplication.run(GraduationTopicApplication.class, args); } }运行在IDE中直接运行GraduationTopicApplication的main方法或使用Maven命令mvn spring-boot:run启动。访问http://localhost:8080/doc.html即可查看和调试所有API接口。6.2 前端启动进入前端项目目录安装依赖npm install。启动开发服务器npm run serve。默认访问地址为http://localhost:8081。修改前端项目中的axios请求基地址指向后端服务localhost:8080。6.3 初始化数据系统启动后需要手动在数据库sys_user表中插入初始管理员账户密码需使用BCrypt加密。可以使用以下Java代码生成加密密码String rawPassword admin123; BCryptPasswordEncoder encoder new BCryptPasswordEncoder(); String encodedPassword encoder.encode(rawPassword); System.out.println(encodedPassword); // 将输出结果复制到SQL中然后执行SQL插入管理员用户再通过管理员账户登录系统后台创建教师和学生用户。7. 常见问题与排查思路在开发和部署过程中你可能会遇到以下典型问题问题现象可能原因排查思路与解决方案启动报错Failed to configure a DataSource数据库连接配置错误或数据库服务未启动。1. 检查application.yml中的url,username,password。2. 确认MySQL服务已启动且graduation_topic数据库已创建。3. 检查MySQL驱动版本是否匹配。访问接口返回403 Forbidden或401 UnauthorizedSpring Security权限配置问题或用户未登录/角色不符。1. 检查请求的URL是否在Security配置的permitAll()路径中。2. 确认请求头是否携带了有效的认证Token如JWT或Session。3. 检查当前登录用户的角色是否拥有访问该接口的权限hasRole。前端调用API跨域CORS错误浏览器安全策略阻止了不同源域名、端口、协议的请求。在后端添加全局CORS配置。在Spring配置类中添加Beanpublic CorsFilter corsFilter() { ... }允许前端域名和端口。插入数据时出现重复键错误数据库唯一约束冲突如用户名重复。1. 检查插入的数据是否违反了表设计的唯一约束如uk_username。2. 在前端或后端添加数据重复性校验。教师审核通过后课题已选人数未增加业务逻辑有漏洞currentSelected字段未更新。检查SelectionRecord状态更新为APPROVED时是否同步执行了topic.setCurrentSelected(topic.getCurrentSelected() 1)并更新数据库。这是一个关键的业务逻辑点务必在事务中完成。分页查询结果不正确前端传递的分页参数与后端接收不一致或SQL分页语句有误。1. 使用MyBatis-Plus的Page对象确保current和size参数正确接收。2. 检查前端请求参数名是否为page和size或pageNum和pageSize保持前后端一致。8. 项目扩展与最佳实践建议完成基础功能后可以考虑以下方向进行扩展和优化这也能为你的毕业设计论文增加亮点引入Redis缓存将频繁访问且变化不频繁的数据如课题列表、用户基本信息缓存到Redis中显著提升查询性能减轻数据库压力。实现JWT无状态认证替换默认的Session机制使用JSON Web Token (JWT)。用户登录后获取Token后续请求在Header中携带更适合前后端分离架构和分布式部署。增加文件上传功能允许教师上传任务书、参考文献等附件学生上传开题报告、中期检查等文档。需考虑文件存储本地或OSS和在线预览。集成消息推送使用WebSocket或第三方推送服务实现选题状态变更、新通知等信息的实时推送提升用户体验。完善后台管理功能数据可视化使用ECharts等库为管理员提供选题进度统计、各导师课题数量、学生选择热度等图表。操作日志记录关键操作如发布课题、审核、用户管理便于审计和问题追溯。系统配置允许管理员在界面上动态配置选题的起止时间、每人可选课题数量等规则。代码层面的最佳实践统一异常处理使用ControllerAdvice和ExceptionHandler全局处理异常返回友好的错误信息给前端。接口参数校验使用Validated注解和JSR-303规范如NotBlank,Size对Controller入参进行校验。使用枚举类将数据库中的状态字段如topic.status,selection_record.status定义为Java枚举避免魔法字符串提高代码可读性和安全性。服务层事务管理对于涉及多表修改的操作如学生选课务必在Service方法上使用Transactional注解保证数据一致性。定期备份数据库编写脚本或使用MySQL的定时任务定期对数据库进行备份防止数据丢失。这个基于SpringBoot的毕业设计选题系统从需求到部署提供了一个完整的全栈开发范例。它不仅是一个可运行的毕业设计项目更是一个学习现代Java Web开发技术栈SpringBoot、MyBatis-Plus、Spring Security、Vue.js的绝佳实践。在实现过程中深入理解业务逻辑与数据一致性的处理、前后端分离的协作模式、以及安全认证的设计远比单纯实现功能更有价值。你可以在此基础上结合自己学校的实际流程增加或调整功能模块使其更贴合实际应用场景。
返回列表