做了几年毕业设计指导,也带过不少学生落地类似的系统,每次看到“SSM+Vue管理系统”这类题目,总有一种亲切感。这套技术栈虽然看着传统,但胜在结构规整、资料丰富、找工作面试也能讲出东西。这次要拆解的项目是“基于SSM+Vue的科研成果管理系统设计与实现”,属于高校里特别常见的选题,理工科的老师基本都认。它解决的问题很实在:高校教师和学生的论文、专利、软著、获奖等成果数据分散在个人手里,学院和科研处要汇总统计全靠Excel来回传,效率低还容易错。这个系统就是把这些成果统一管起来,从录入、审核到统计、导出,做成一整套线上流程。
这个项目特别适合三类人参考:正在准备毕业设计的计算机专业学生,想练手SSM+Vue前后端分离项目的初学者,以及需要快速交付一套管理系统给客户做演示的开发者。下面我按照自己的实际开发习惯,把这个系统的完整设计思路、核心实现、论文写作要点和踩坑经验全部拆开讲,争取让照着做的人少走弯路。
1. 项目定位与功能拆解
1.1 科研成果管理系统的核心需求
动手写代码之前,先把业务搞清楚。科研成果管理系统听起来宽泛,落到高校场景里其实就几件事:成果登记、成果审核、成果统计、成果导出。
成果登记解决的是“数据从哪来”。教师和学生登录系统后,把自己的论文、专利、软著、获奖、课题等信息填进去。这里的难点在字段设计,不同成果类型的属性差异很大:论文有期刊名、影响因子、收录情况(SCI、EI、核心),专利有专利号、授权日期、发明人排序,获奖有颁奖单位、获奖等级。如果只建一张大表,会有大量空字段,统计时还要用if-else判断类型。我做过多个类似项目后,比较推荐的做法是“主表存公共字段 + 扩展字段用JSON存”,或者按类型分表。毕设级别用主表加type字段区分类型,再加一个detail字段存JSON就够了,简单直观,论文里也好讲清楚。
成果审核解决的是“数据可信不可信”。学校对科研成果认可有流程要求,一般分两级:先由学院科研秘书初审,再由校科研处终审。这个流程必须在系统里固化成状态机:待提交、待审核、审核通过、审核驳回。驳回一定要填写原因,否则用户不知道改哪里。很多学生做这个功能时只给一个审核状态字段,被驳回后用户一头雾水,这种细节在答辩时很容易被老师追问。
成果统计和导出是管理员的刚需。按学院、按年度、按成果类型统计数量,生成柱状图或饼图展示,还要支持把结果导出成Excel。这里有个容易忽略的点:导出的数据必须是审核通过的,带出草稿和驳回数据会出大问题。统计维度上,建议至少支持:学院维度、年度维度、成果类型维度、教职工个人维度这四种,基本覆盖学校科研管理的大部分场景。
1.2 为什么选SSM+Vue这套组合
技术选型直接决定了后面几个月的开发体验,也决定了论文能不能写够篇幅、答辩时有没有东西可讲。SSM(Spring + SpringMVC + MyBatis)加Vue的组合,放在2026年来看依然有它的合理性。
从教学和答辩的角度讲,SSM是Java Web开发里最经典的“教科书式”组合。Spring负责管理对象依赖,SpringMVC负责处理请求路由,MyBatis负责数据库操作。每一层都有明确职责,论文里可以展开写的内容非常多,改起来也容易定位问题。相比Spring Boot的“脚手架式”开发,SSM需要手动配置更多东西,但这恰恰是好事:答辩时老师问“Spring IoC的原理”“MyBatis的#{}和${}有什么区别”,你能讲出应用场景和配置过程,而不是只说“框架自动处理了”。
前端用Vue的理由更实际。Vue对新手友好,模板语法贴近传统HTML开发习惯,学习曲线比React平缓不少。用Vue CLI或Vite创建项目后,配合Element UI组件库,管理后台的表格、表单、弹窗、分页、菜单布局都能快速搭出来,不必自己写一堆CSS。系统是前后端分离的,Vue负责页面渲染和数据交互,后端只提供JSON接口,这也符合目前企业主流开发模式,放到简历上不丢人。
另外说句实在话,Vue和SSM的社区资料非常丰富。遇到问题在搜索平台基本都能找到现成解决方案,这对毕设选手来说太重要了。真遇到冷门框架,卡一个Bug可能就是一星期。技术选型求稳不吃亏,别在毕设里追求标新立异。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 数据库设计与后端核心实现
2.1 数据库表结构设计
数据库是管理系统的地基。我之前见过不少学生上来就写代码,做到一半发现表结构存不下业务数据,又回头改表,连带前端接口一起推翻,心态直接爆炸。表结构设计花一天时间,后面能省一周的返工时间。
科研成果管理系统我建议至少设计这几张表:
- user(用户表):id、username、password、real_name、role(学生/教师/科研秘书/管理员)、college_id、phone、email、create_time。密码不要明文存储,用MD5加盐或BCrypt加密,这个是毕设加分项。
- college(学院表):id、name、code。用户表关联学院表,方便按学院维度统计。
- result(成果表):id、user_id、type(论文/专利/软著/获奖/课题)、title、status(草稿/待初审/待终审/通过/驳回)、reject_reason、publish_date、detail(JSON扩展字段)、create_time、update_time。
- audit_record(审核记录表):id、result_id、auditor_id、audit_level(初审/终审)、action(通过/驳回)、comment、create_time。保留完整的审核历史,答辩时可展示的数据更多。
- announcement(公告表):id、title、content、publisher_id、create_time。科研处发通知用,属于锦上添花但很实用的功能。
给个具体的建表参考,成果主表的核心字段大致是这样:
sql复制CREATE TABLE `result` (
`id` int NOT NULL AUTO_INCREMENT,
`user_id` int NOT NULL COMMENT '所属用户',
`type` varchar(20) NOT NULL COMMENT '成果类型:paper/patent/software/award/project',
`title` varchar(255) NOT NULL COMMENT '成果名称',
`status` tinyint NOT NULL DEFAULT '0' COMMENT '0草稿 1待初审 2待终审 3通过 4驳回',
`reject_reason` varchar(500) DEFAULT NULL COMMENT '驳回原因',
`detail` json DEFAULT NULL COMMENT '类型扩展字段',
`publish_date` date DEFAULT NULL COMMENT '发表日期/授权日期',
`create_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
特别注意,字符集一定要用utf8mb4而不是utf8。原因很简单,utf8在MySQL里是utf8mb3的别名,存不了emoji和一些特殊字符。做系统时如果用户在备注里填了生僻字或特殊符号,查询出来变成乱码“???”,排查起来非常痛苦。为了这点细节踩坑,非常不值。
2.2 后端分层架构与核心接口
后端代码的包结构建议严格按照分层来组织,既方便自己维护,也符合论文中“系统设计”章节的写法。标准的分层是:
- controller层:接收请求,参数校验,返回统一结果
- service层:业务逻辑处理
- mapper层:MyBatis接口,操作数据库
- entity层:实体类,对应数据库表
- common层:统一返回结果封装、全局异常处理、工具类
统一返回结果非常关键。我见过太多前后端联调时因为返回格式不一致扯皮的例子。推荐定义一个Result对象,格式为:
json复制{
"code": 200,
"message": "success",
"data": {}
}
前端根据code判断请求状态,成功取data,失败弹message。所有接口都走这个统一格式,Axios的响应拦截器里做统一处理,代码量能减三分之一。
核心接口按功能模块划分:
- 登录认证接口:POST /api/login,接收用户名密码,校验后返回Token和用户信息。
- 成果管理接口:GET /api/result/list(分页查询,支持按类型、状态、标题模糊搜索)、POST /api/result/add、PUT /api/result/update、DELETE /api/result/delete、GET /api/result/detail/{id}。
- 审核接口:POST /api/audit/submit(用户提交审核)、POST /api/audit/review(审核人处理)。
- 统计接口:GET /api/stats/byCollege、GET /api/stats/byType、GET /api/stats/byYear。
写Controller的代码很简单,但有一个细节我认为很值得注意:Controller内部不要堆业务逻辑,它只做参数接收和结果转发,所有业务判断放在Service里。比如提交审核这个操作,Controller接收到请求后,Service里要判断:成果是否存在、状态是否为草稿、当前用户是否为成果所属人。这些判断如果写在Controller里,时间长了代码会乱成一团,后面加权限控制时根本无从下手。
2.3 登录鉴权与角色权限
权限控制是毕设答辩时老师最爱问的模块。最简单的方案是使用拦截器加Token。登录成功后,后端生成一个Token(可以用UUID加用户ID拼接,或更规范地用JWT),返回给前端。前端每次请求在Header里带上这个Token,后端拦截器统一校验。
拦截器实现很直接,写一个HandlerInterceptor的类,preHandle方法里从请求头取出Token,查Redis或数据库验证有效性,有效就放行,无效返回401状态码。配置WebMvcConfigurer注册拦截器,并设置excludePathPatterns放行登录接口。
java复制@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/api/login", "/api/register");
}
}
角色权限建议用注解加拦截器的方式实现。定义一个@RequireRole注解,标注在需要特定角色才能访问的接口上,拦截器里校验当前用户角色是否匹配。比如审核接口只允许科研秘书和管理员访问,那就给审核Controller加@RequireRole({"admin", "secretary"})。这种方式写代码省事,论文里也能讲出一套“基于注解的权限控制机制”,听上去比在if-else里判断角色高级得多。
实际开发中,需要特别注意Token过期处理。前端Axios统一封装时,要在响应拦截器里判断返回的code是不是401。如果是401,清除本地Token并跳转登录页。不然用户Token过期后还停留在页面,点击任何按钮都报错,体验非常差。还有一点是我的经验之谈:接口层面不要只靠前端隐藏按钮来控制权限,恶意用户完全可以绕过前端直接调接口。后端一定要做校验,这个在答辩时主动讲出来,老师会认为你安全意识到位。
3. 前端Vue实现与前后端联调
3.1 Vue项目搭建与环境配置
前端环境配置是不少刚开始接触Vue的人第一个拦路虎,我在这里踩过的坑比后端多得多。简单梳理一下一套可用的环境配置过程。
安装Node.js和npm是第一步。版本选择上,Vue CLI项目建议Node 16以上,Vite项目建议Node 18以上。安装完成后在命令行验证一下:
bash复制node -v
npm -v
然后创建Vue项目。Vue CLI的方式是:
bash复制npm install -g @vue/cli
vue create research-frontend
Vite的方式是:
bash复制npm create vite@latest research-frontend -- --template vue
这里我建议用Vite,启动速度快很多,配置也更简单。Vite创建的项目结构更干净,Vue CLI官方已经处于维护模式,新项目没必要执着于它。创建完成后进入项目目录安装依赖和Element UI:
bash复制cd research-frontend
npm install
npm install element-plus axios vue-router pinia
npm install时有个常见问题:下载速度慢或者直接卡住。解决办法是切换到国内镜像源:
bash复制npm config set registry https://registry.npmmirror.com
配好之后安装速度会快一个数量级。
3.2 前端页面与核心组件实现
管理系统的页面结构一般分三块:左侧菜单栏、顶部导航栏、右侧内容区。Vue里用路由嵌套实现这个布局,父路由渲染布局组件,子路由渲染具体页面。用Vue Router配置时,大概长这样:
javascript复制const routes = [
{
path: '/',
component: Layout,
redirect: '/dashboard',
children: [
{ path: 'dashboard', component: Dashboard },
{ path: 'result/list', component: ResultList },
{ path: 'result/add', component: ResultAdd },
{ path: 'audit/list', component: AuditList },
{ path: 'stats', component: Stats },
{ path: 'system/user', component: UserManage }
]
},
{ path: '/login', component: Login }
]
左侧菜单根据当前用户角色动态生成,管理员能看到系统管理菜单,普通教师只能看到成果管理和统计信息。这个动态渲染逻辑在侧边栏组件里用v-if配合路由meta信息实现。
核心页面里,成果列表页最值得花心思。用Element UI的el-table展示成果数据,配合el-pagination做分页。查询条件区域放成果类型下拉框、状态下拉框、标题搜索框和查询按钮。关键参数是每页条数,建议固定为10或20,不要给用户选择每页50条的选项,数据量大时接口压力大,页面渲染也会变卡。
成果新增和编辑页面用el-form。切换成果类型时,动态展示对应字段:选中“论文”时出现期刊名、收录情况、影响因子的输入项;选中“专利”时出现专利号、授权日期、发明人列表。这里用动态表单实现,一个页面通吃所有类型的录入。实现方法是表单里根据type字段用v-if判断渲染哪些表单项。需要注意的一点是表单校验规则要同步调整,比如选中“论文”时期刊名是必填,切到“专利”后这项就取消验证。给el-form的model属性里配置rules,在切换类型后重新计算rules对象。
3.3 前后端联调与跨域处理
前后端分离开发中,联调环节最容易出问题,核心就是跨域。后端接口跑在8080端口,前端开发服务器跑在5173端口,浏览器默认会拦截跨域请求。解决办法有两个:后端配置CORS,或前端配置代理。
后端配置CORS最简单,加一个配置类即可:
java复制@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOriginPattern("*");
config.addAllowedMethod("*");
config.addAllowedHeader("*");
config.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
注意addAllowedOriginPattern("")别忘了,如果只写addAllowedOrigin(""),和allowCredentials(true)同时使用时会报错,这也是一个常见的坑。
开发环境我更推荐用Vite代理,前端代码不需要做任何修改,请求绕过浏览器限制。在vite.config.js里配置:
javascript复制export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true
}
}
}
})
这样前端请求 /api/login 时,Vite开发服务器会转发到后端的8080端口,前后端接口路径保持一致。部署到生产环境时,再用Nginx配置反向代理,把同一个域名下的 /api 路径转发到后端服务,完美解决跨域。
联调过程中强烈建议先在浏览器Network面板里确认请求是否真的发出去了,再看状态的返回结果。我之前带过一个学生,后端接口明明没启动,他一直在前端代码里找问题,浪费了大半天。联调的基本顺序应该自下而上:先确认后端接口在Postman或Apifox里能调通,再确认前端请求能发出且路径正确,最后才排查代码逻辑问题。
4. 论文撰写重点与答辩准备
4.1 论文结构安排
毕设论文有一套约定俗成的结构,老师评阅时看重的是逻辑完整性,不要求语言多么华丽。科研成果管理系统的论文建议按以下章节组织:
第一章绪论写研究背景和意义、国内外研究现状、论文主要工作。研究现状这里很多学生写得像百度百科的堆砌,正确的写法是分国外和国内两条线,找几篇近几年的相关系统设计论文或技术方案,概括它们在“科研成果管理”或“信息系统开发”方面做了什么、存在什么不足,然后再引出你的系统如何弥补这些不足。
第二章相关技术介绍写SSM框架、Vue框架、MySQL数据库、前端技术等。这章最容易被写成一堆名词解释,写得好的都是结合项目来讲。比如介绍MyBatis时,不要只写“MyBatis是一个半自动ORM框架”,再加一句“本系统中使用MyBatis的注解和XML两种方式完成数据库操作,利用动态SQL实现成果列表的多条件组合查询”,这样技术介绍就和项目绑定了。
第三章系统分析写可行性分析和需求分析。需求分析要画出用例图,列出功能需求和非功能需求。用例图用Visio或draw.io画,包含学生、教师、科研秘书、管理员四个角色,以及每个角色可执行的功能。
第四章系统设计写总体架构设计、功能模块设计、数据库设计。数据库设计要有ER图和主要表结构说明,每张表列出字段名、类型、约束、说明。这章是论文中容易拿分的部分,表结构设计得合理,画图规范,基本分就稳了。
第五章系统实现是重点,篇幅最大。按功能模块逐块截图加核心代码片段,配合文字说明实现思路。注意代码不要贴太多,每个模块选3到5段关键代码即可,重点是解释代码的逻辑。
第六章系统测试写测试环境、测试用例、测试结果。测试用例要覆盖每个功能模块的正常流程和异常流程,比如登录测试要包含“用户名密码正确”“用户名不存在”“密码错误”“账号被禁用”四个用例。测试结果用表格展示,包括用例编号、测试项、操作步骤、预期结果、实际结果、是否通过。
4.2 系统测试怎么做才显得专业
测试章节写得薄弱的论文太多了,很多学生就写一句“系统经过测试,功能正常,性能良好”,这种内容老师看到会很反感。系统测试要想写得专业,至少要做三件事。
第一,功能测试用例设计要成体系。拿成果管理模块来说,测试用例至少要覆盖:新增成果(填写完整信息)、新增成果(缺少必填项)、修改成果、删除成果、条件查询、分页查询、导出Excel。每个用例都要给出输入数据和预期输出。
第二,要有接口测试的说明。用Postman或Apifox对关键接口做测试,展示请求参数和返回结果。比如测试登录接口,分别用正确密码、错误密码、空用户名三组数据,记录接口返回的code和message,把截图放进论文。
第三,非功能测试也要提。并发访问测试可以用JMeter或简单的脚本,模拟50个用户同时登录查看是否存在响应超时。兼容性测试至少要说明在Chrome和Edge浏览器下页面显示正常。这些内容写进论文后,整体工作量和专业度直接上一个台阶。
4.3 答辩临场发挥的技巧
答辩环节老师问的问题有很强的规律性,提前准备好答案能化解大部分压力。
第一个大概率会被问的是“你怎么理解SSM框架的分层思想”。回答思路:表现层(SpringMVC)接收请求并返回视图,业务层(Spring)管理业务逻辑和事务,持久层(MyBatis)操作数据库。每一层只关注自己的职责,层与层之间通过接口交互。你的项目中Controller、Service、Mapper就是按这个思路组织的。
第二个高频问题是“数据库表之间的关联关系是怎么设计的”。用你实际的表结构回答:用户表与成果表是一对多,成果表与审核记录表是一对多,学院表与用户表是一对多。同时说明外键关联或逻辑关联的实现方式。
第三个常见问题是“项目有哪些难点,你怎么解决的”。这是一个展示深度的机会。建议提前准备两个:一个是审核流程的状态机设计,如何保证状态流转不出现非法跳转,比如“待初审”的成果不能被直接删除;另一个是跨域和Token鉴权如何配合,怎么让前端请求自动携带Token,后端如何校验。
答辩时不要试图隐瞒自己不会的领域。老师问到没准备好的问题,诚实说明“这块我还没有深入,后面会继续研究”,态度诚恳的认错远好过不懂装懂。
5. 常见问题与在线排查机制
5.1 开发环境常见问题处理
环境问题出现在项目开始的概率高,而且解决起来有时毫无头绪。收集几个我见过多次的案例供参考。
端口被占用几乎人人会遇到。Spring Boot项目启动时提示端口8080被占用,解决方法是命令行执行netstat -ano | findstr 8080查看占用端口的PID,然后在任务管理器杀掉对应进程。如果是自己电脑上有其他Java程序在跑,直接改server.port换一个端口比如8081。Vue项目启动时提示端口5173被占用,Vite会自动跳到5174,不影响使用但如果你有固定的代理配置,还是要手动调整代理端口。
npm安装依赖失败的原因千奇百怪,最常见的是网络问题。先切换镜像源再重试,还不行就删除node_modules目录和package-lock.json后重新安装。不要在一棵树上吊死,第二次安装时建议使用npm install --registry=https://registry.npmmirror.com显式指定镜像。
数据库连接失败要分类排查。Spring的报错信息里如果是Access denied for user,说明账号密码或权限有问题:确认MySQL里是否创建了对应账号并授权。如果是Unknown database,说明数据库还没创建,执行CREATE DATABASE命令即可。如果是Communications link failure,大概率是MySQL服务没启动,Windows服务管理器里启动MySQL服务就行。
5.2 业务逻辑常见Bug与修复
业务逻辑层的Bug比环境问题更隐蔽,这里列出我和学生们经常被坑的几个场景。
第一个是成果列表分页数据重复或丢失。原因是MySQL的LIMIT语句偏移量计算错误。当前页是pageNum,每页大小是pageSize,那么LIMIT的起始位置是(pageNum - 1) * pageSize。有很多新人直接写LIMIT pageNum * pageSize,第一页没事,从第二页开始数据就乱了。
第二个是日期类型导致的JSON格式化问题。后端返回的java.util.Date对象,前端收到的可能是时间戳或格式不对的字符串。解决办法是加配置:
properties复制spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
这样全局日期格式就能统一。
第三个是文件上传异常。如果系统里有上传附件功能,前端传文件时一定要设置Content-Type为multipart/form-data,同时后端SpringMVC配置multipart解析器并设置最大上传大小。不然默认限制1MB,传一个大点的文件就报错。在application.properties里调整限制:
properties复制spring.servlet.multipart.max-file-size=50MB
spring.servlet.multipart.max-request-size=50MB
第四个是事务失效问题,这是隐藏最深的一个坑。Service层方法标注了@Transactional,按理说发生异常会自动回滚,但实际没有。核心原因一般有两个:方法内部调用同类中的另一个方法,事务注解不会生效;或者异常被try-catch吞掉了,事务管理器感知不到。解决办法是确保@Transactional修饰的方法从外部调用,并且不捕获异常或捕获后重新throw新的RuntimeException。
第四个是删除数据时外键约束报错。如果成果表设置了外键关联用户表,删除一个已有成果的用户时会报“Cannot delete or update a parent row”。处理方案有两种:表结构上设置ON DELETE CASCADE让数据库自动删,或者业务层先检查该用户名下是否有成果数据,有则提示“请先处理该用户名下的成果记录”。后者更安全,不会误删数据。
5.3 前后端分离项目的部署方案
部署是另一个容易踩坑的环节。系统写完后要部署演示或上线,很多新手在这一步被卡住。前后端分离项目的部署有两种主流方式,选一种适合自己的即可。
第一种是打包前端后由后端托管。前端执行npm run build生成dist目录,里面是静态文件。后端项目里加一个静态资源映射,把dist目录指向Spring的静态资源路径。请求同一端口,前端资源由Spring默认静态资源处理器处理,接口由Controller处理,跨域问题自然不存在。
第二种是用Nginx做反向代理。前端dist目录交给Nginx托管,后端打成jar包运行在某个端口。Nginx配置里把 /api 开头的请求转发到后端端口,其他请求指向前端静态文件。通常这样配置:
nginx复制server {
listen 80;
server_name your-domain.com;
location / {
root /var/www/research-frontend/dist;
index index.html;
try_files $uri $uri/ /index.html;
}
location /api/ {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
注意try_files这行配置不能少,不然刷新非首页路径会出现404。Vue Router开启history模式后,直接刷新 /result/list 页面,如果Nginx没有配置回退到index.html,浏览器就会报404。这个问题项目上线时经常遇到,务必提前处理好。
后端打包同样有讲究。SSM项目一般用Maven打包成war包部署到Tomcat,或配置成Spring Boot形式打成jar包直接运行。如果打包后报Spring配置文件找不到或Bean创建失败,检查target目录下的classes文件夹是否包含配置文件,大多时候是build配置漏了资源文件。
6. 实际开发经验与避坑清单
踩过的坑多了,自然积累出一些经验。这里放一份我做同类项目时的检查清单,开发时对照着过一遍,能少走不少弯路。
- 数据库表名和字段名统一用下划线命名法;Java代码统一用驼峰命名法;前端变量用驼峰命名。命名不一致时,用MyBatis的map-underscore-to-camel-case配置把snake_case自动映射为驼峰字段。
- 日期字段在数据库用datetime类型,Java实体类用Date,前端展示时统一格式化。不要三种格式混用,否则调试时间格式问题会折腾很久。
- 所有列表查询接口务必做分页,数据量大了以后不分页的查询会让服务器响应越来越慢。MyBatis分页推荐用PageHelper,配置一行就生效。
- 密码加密别偷懒。明文存储密码在答辩时会被老师直接质疑安全性。至少做到MD5加盐或使用Spring Security的BCryptPasswordEncoder。
- 系统里所有操作时间用create_time、update_time字段记录,不要依赖数据库的默认值,代码里显式设置日期,方便后期排查问题。
- 接口路径统一以/api开头,分组时后面加模块名,如/api/result、/api/audit、/api/stats。有清晰的路径规范,联调和别人阅读代码时能省很多时间。
- 前端路由和菜单要配合后端权限做双重控制,前端隐藏菜单只是体验层面的限制,后端拦截器才是真正的安全防线。
- 表述“模糊查询”时用MyBatis的LIKE CONCAT('%', #{keyword}, '%'),绝对不要手动拼接字符串。使用${}做字符串拼接会有SQL注入风险,这一点在论文安全和设计章节可以展开讲。
按这个清单开发下来的系统,基本已经具备一个合格毕设作品该有的完整度和专业度。如果再能加上一两个亮点功能,比如按学年度的成果趋势图、批量导入Excel、到期提醒等,答辩时就有更多拿得出手的东西。
最后说一句个人体会,这类管理系统真正花时间的往往不是代码逻辑本身,而是需求不清晰导致的反复返工。把模块功能边界、状态流转规则、权限划分在上手前想清楚,后面每一步都会顺利不少。至于技术上的细节问题,多写多查,踩过坑就会了。
