十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

SSM+Vue农业技术学习平台毕设全解析:设计、实现与部署

SSM+Vue农业技术学习平台毕设全解析:设计、实现与部署 每年的毕设季总能看到两类人一类被微服务、高并发这些词裹挟把毕业设计做成了技术大杂烩功能没做完还把自己累够呛另一类老老实实用SSM Vue这种经典组合把一个题目踏踏实实抠到底最后论文有内容、答辩有底气、代码也经得起问。2026年如果你拿到的是农业技术学习平台这类题目我推荐你走第二条路。这个项目看着普通但背后的业务逻辑、前后端交互、权限控制、学习进度记录这些点足够撑起一篇合格的毕业论文也能让评审老师看到你确实掌握了完整的开发链路。本文我把这套系统的设计思路、数据库建模、后端SSM实现、前端Vue联调以及论文和部署的经验一次性讲透照着做能省下不少排查时间。1. 选题与技术站队农业技术学习平台为什么用SSMVue而不是Spring Boot1.1 为什么是农业技术这个切口很多同学选毕业设计题目时会陷入两个极端要么太抽象比如在线教育平台这种大而全的题做完别人也只当你是个低配版慕课要么太冷门连指导老师都不知道该怎么评。农业技术学习平台这个切口其实卡得很准它本质上是一个垂直领域的学习系统但又有足够清晰的用户边界和业务场景。农业技术的受众非常具体普通农户想学大棚种植、病虫害防治、施肥技术农技站专家有课程资源和答疑需求管理员要维护课程内容和用户数据。这意味着系统天然包含三类角色、三套操作界面、三种权限层级不用你硬造功能去凑篇幅。而且农业技术学习本身就是国家鼓励的方向论文里的研究意义、社会价值部分一写一个准评审老师不会质疑课题背景。从数据层面看这类平台也逃不开课程、文档、视频、问答、收藏、学习进度这几个维度的数据关系恰好覆盖了MySQL建表、外键关联、多表联查这些必须展示的数据库考点。选题选得好后面的系统设计和论文写作都会顺很多。1.2 SSM不是老旧而是毕设场景下的最优解我知道你肯定纠结过现在企业里用Spring Boot的居多为什么还要用SSM这里要分清楚企业开发用什么和毕业设计用什么是两码事。SSM的完整称呼是Spring SpringMVC MyBatis它和Spring Boot并不矛盾Spring Boot只是把Spring生态的配置做了自动化封装底层核心依然是Spring。毕设用SSM有三个实打实的好处。第一是配置过程本身就是教学考核点web.xml、spring-context.xml、spring-mvc.xml、mybatis-config.xml四个配置文件弄明白你对Java Web的整体认知会瞬间清晰而这恰恰是很多直接上手Spring Boot的学生最薄弱的环节。第二是规避过度封装导致说不清原理的尴尬答辩时老师问Spring Boot自动配置的原理是什么你如果没准备很容易卡壳但SSM的东西每个Bean是怎么装配的、Mapper接口是怎么代理的、DispatcherServlet怎么分发请求你都能指着配置文件和源码讲出来。第三是兼容性好很多学校的实验环境、老的JDK版本、机房电脑上运行的IDEA版本跑SSM项目比跑最新版Spring Boot 3要稳得多不会出现JDK 17版本不兼容这种节外生枝的坑。1.3 前端放弃JSP改Vue的权衡传统的SSM毕设通常会搭配JSPJSTL服务端渲染页面。但到了2026年如果还在用JSP写页面论文里的系统实现章节会非常难看截图界面也拿不出手。视觉上主动放弃JSP、改走前端分离正是这个项目的优势所在。Vue在这一层扮演的角色是轻量、易上手、生态成熟配合Element UI或Element Plus组件库两天时间就能把后台管理界面的壳子搭好。更重要的是前后端分离模式下后端只负责提供JSON接口前端通过axios调用这种交互方式本身就是当前Web开发的主流形态论文里的架构设计章节可以画一张清晰的前后端交互图技术水平显得更贴近实际生产。而且Vue的学习曲线相对平缓即使你之前只写过HTML和原生JavaScript也能在两周内达到能独立开发项目的水平。这里需要提前想清楚一个点前后端分离以后SSM后端返回的不再是ModelAndView而是统一封装的JSON结构。很多第一次做分离开发的同学会在这里犯迷糊——Controller方法上记得加ResponseBody或者直接在方法上标注RestControllerSpring 4之后支持这个意识要提前建立起来。2. 功能拆解与角色设计一个学习平台必须有这几样2.1 三类角色与各自的核心诉求我把系统的用户角色定为管理员、农业专家、普通农户三类每类角色的核心诉求完全不同这直接决定了功能菜单的设计逻辑。普通农户是平台的主要使用者他们要的是能看、能学、能问。具体来说游客状态下可以浏览课程列表、查看农业资讯但一旦要观看完整视频、下载技术文档、发表评论就必须登录登录后可以学习课程并记录学习进度下次再打开视频自动续播遇到不懂的问题可以去问答板块提问也可以收藏对自己有用的课程和技术文章个人中心里能看到自己学了多少课程、累计了多少学习时长、获得了什么等级称号。农业专家是内容生产者区别于普通农户的部分是多了内容管理权限可以发布课程、上传视频和配套文档、发布农业技术文章、在问答区回答问题。专家在前端看到的是普通用户的所有功能再加一门我的创作后台。管理员则只管平台运行不关心具体内容用户管理禁用/启用账号、课程审核与下架、资讯审核、问答板块的内容审核、公告发布、以及基础的数据统计每日新增用户、课程播放量Top榜等。这种三角色设计的好处是权限边界清晰开发实现时用一张额外添加role字段的用户表就足够不用引入Spring Security这种重量级框架自己写一个拦截器就能搞定。下面是我梳理的功能模块清单开发时可以照着拆任务公共模块登录注册、首页轮播、课程分类浏览、资讯列表、课程搜索 农户模块课程播放、学习进度记录、收藏、评论、提问、个人中心 专家模块课程发布与管理、技术文章发布、回答用户提问 管理员模块用户管理、课程审核、资讯管理、问答管理、公告管理、数据统计 系统模块文件上传图片/视频/文档、统一异常处理、分页查询2.2 核心业务流程课程学习和问答的流转有了功能模块以后下一步是画用例图和时序图。很多同学在这块直接照抄网上的模板结果跟自己的系统对不上答辩时被问住。我建议你自己静下心来画一遍核心流程其实就那么几条。课程学习的主流程是这样的农户登录后进入课程详情页看到课程基本信息、所属章节列表、学习进度条。点击某个章节的视频前端先向后端发送一条增加学习记录的请求后端判断是新增还是更新播放过程中前端每隔一段时间比如15秒上报一次学习时长后端更新最近学习位置字段播放完成或用户手动点击标记已完成时进度字段标记为已完成。这个流程里最核心的表是学习记录表它决定了你能否实现视频续播这个亮点功能。问答模块的流程更简单农户在问答区发帖选择所属的农业分类如蔬菜种植、果树管理、病虫害防治管理员先审核是否合规审核通过后展示在列表页专家可以回答问题提问者可以选择一个最佳答案并将其置顶展示。这个流程不需要太复杂的业务规则但可以加一个积分奖励机制——每天首次登录加5分发布一个提问加2分回答被采纳加10分。积分体系虽然小但能让系统显得更完整论文里也能多写一两个接口设计。2.3 从用例图到开发任务拆解用例图很多同学画得乱七八糟核心原因是没有把角色-功能对应起来。我整理了一张自己项目里用的角色与权限对照表你可以直接参考这个思路去画图功能游客农户专家管理员浏览课程/资讯是是是是观看视频/下载文档否是是是收藏/评论/提问否是是是发布课程/文章否否是否审核内容否否否是用户管理否否否是数据统计否否否是这张表画清楚以后后端的Controller层接口列表基本就出来了登录注册接口、课程分类查询接口、课程列表分页接口、课程详情接口、学习进度上报接口、收藏接口、评论接口、提问与回答接口、专家发布课程接口、管理员审核接口、用户管理接口、数据统计接口。每个接口对应后端一个Controller方法、一个Service方法、一个Mapper查询开发任务颗粒度一下子就清晰了。3. 数据库建模六张核心表扛起整个平台的业务3.1 用户表与角色表数据库设计这块我直接把我总结出来的核心表结构分享出来你根据实际需求微调即可。首先是用户表字段不需要太多但有一个细节要注意不要单独建角色表直接在用户表里加一个role字段值为tinyint类型1普通农户、2农业专家、3管理员简化关联查询。CREATE TABLE user ( id INT NOT NULL AUTO_INCREMENT, username VARCHAR(50) NOT NULL COMMENT 登录账号, password VARCHAR(100) NOT NULL COMMENT MD5加密后密码, nickname VARCHAR(50) DEFAULT NULL COMMENT 昵称, phone VARCHAR(20) DEFAULT NULL COMMENT 手机号, role TINYINT NOT NULL DEFAULT 1 COMMENT 1农户 2专家 3管理员, avatar VARCHAR(255) DEFAULT NULL COMMENT 头像地址, status TINYINT NOT NULL DEFAULT 1 COMMENT 1正常 0禁用, score INT DEFAULT 0 COMMENT 积分, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;密码用MD5加密就够了不要用明文存数据库这个细节在论文的系统安全设计部分能当一个小亮点写。加盐的问题看你自己毕设阶段不做加盐也不会有人深究但建议你用MD5(密码 固定盐值)这种简单方式体现安全意识。3.2 课程与章节表课程表是内容核心字段比较多。因为课程要支持分类展示所以我单独建了一张category分类表来维护一级分类粮食作物、蔬菜种植、果树园艺、病虫害防治、畜牧养殖、水产养殖等课程表通过category_id关联分类。课程和专家的关系是一对多也就是一个专家可以发布多个课程课程表里存expert_id外键。章节表的设计要稍微多想一步一个课程下会挂多个章节每个章节是一个独立的视频。为了让学习进度记录有明确的锚点学习记录表必须同时记录course_id和chapter_id否则你没法知道用户学到哪一集。CREATE TABLE course ( id INT NOT NULL AUTO_INCREMENT, title VARCHAR(200) NOT NULL COMMENT 课程标题, cover VARCHAR(255) DEFAULT NULL COMMENT 封面图URL, category_id INT DEFAULT NULL COMMENT 所属分类, expert_id INT DEFAULT NULL COMMENT 发布专家ID, intro TEXT COMMENT 课程简介, difficulty TINYINT DEFAULT 1 COMMENT 难度 1入门 2进阶 3高级, total_hours INT DEFAULT 0 COMMENT 总时长(分钟), status TINYINT DEFAULT 0 COMMENT 0待审核 1已发布 2已下架, view_count INT DEFAULT 0 COMMENT 浏览数, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;我在最初设计时犯过一个错误——把课程内容直接做成一个大字段存HTML或视频地址结果导致课程列表加载特别慢、评论和进度都绑不到具体章节上。后来重新设计了course_chapter章节表把课程基本信息和课程学习内容彻底分离问题才解决。每个章节包含标题、视频URL、章节序号、预计学习时长和文档附件地址这是一个典型的一对多关系也是后面学习进度记录表的外键来源。3.3 学习记录、收藏与评论表这三张表是这个平台的互动灵魂它们承担了系统里最多的连表查询。学习记录表learning_record是功能亮点表字段设计为userId、courseId、chapterId、progress0到100的整数、watch_duration累计学习秒数、last_position上次播放位置秒数、completed是否完成、update_time。判断新增还是更新的逻辑在后端先按userId和chapterId查是否存在记录存在则UPDATE不存在则INSERT。为了保证这个查询的效率建议给(user_id, chapter_id)建一个联合唯一索引。收藏表favorite最简单三个字段userId、targetType1课程2文章、targetId、createTime同样建议建联合唯一索引前端红心收藏状态通过查询是否存在该记录来判断。评论表comment需要注意父子回复的问题。为了省事很多同学只做一级评论用户只能留言不能互相回复这样业务代码确实简单但交互体验比较空。我建议做成支持二级回复的评论表加一个parent_id字段为0的时候是根评论不为0的时候指向某条根评论的ID表示回复。评论模块的查询逻辑变成先查全部根评论再按parent_id查出每条根评论下的回复组装的活放在前端做后端只需要提供按课程ID查所有评论这一个大接口。3.4 资讯、问答与公告表资讯表article的结构和课程表类似区别是少了章节关联。字段包含标题、封面、内容长文本、分类、发布专家ID、浏览数、状态、发布时间。问答表question包含提问者ID、标题、内容、所属分类、状态待审核/已通过/已关闭、浏览数、回答数、最佳回答ID。回答表answer关联question_id和专家用户ID外加内容与回答时间。公告表就更简单了标题、内容、管理员ID、置顶标记、发布时间。六张核心表加上辅助表总共不到十二张表覆盖了平台的所有业务。画ER图的时候建议分组展示用户域用户/评论/问答/回答、内容域课程/章节/资讯/分类、行为域学习记录/收藏/公告每组画一张局部ER图答辩时比一张密密麻麻的全量ER图好讲得多。4. 后端SSM实现配置整合、权限拦截与学习进度记录4.1 SSM整合配置最容易出错的三个文件SSM整合的配置文件是毕设阶段第一个拦路虎我代码没看一行先跟这三个文件搏斗了三天。先把标准结构放在这里src/main/java com.agri.admin // 后台管理相关Controller com.agri.api // 前端接口Controller com.agri.entity // 实体类 com.agri.mapper // MyBatis Mapper接口 com.agri.service // Service接口 com.agri.service.impl// Service实现类 com.agri.interceptor // 拦截器 com.agri.util // 工具类 src/main/resources jdbc.properties // 数据库连接配置 spring-context.xml // Spring核心配置 spring-mvc.xml // SpringMVC配置 mybatis-config.xml // MyBatis配置 src/main/webapp WEB-INF/web.xml // 部署描述文件第一个容易出错的点是web.xml中DispatcherServlet的配置。这里有一个很隐蔽的坑如果DispatcherServlet的url-pattern配成/*它会拦截所有请求包括静态资源和JSP导致页面加载不出样式配成/则表示除JSP外的所有请求都交给SpringMVC处理这是正确的配法。同时记得把CharacterEncodingFilter放在DispatcherServlet前面不然POST请求的中文参数必乱码。第二个易错点是spring-context.xml和spring-mvc.xml的责任划分。很多同学把所有Bean都塞进spring-mvc.xml导致启动时Service和Mapper互相找不到。标准的做法是spring-context.xml负责扫描除Controller外的所有组件context:component-scan base-packagecom.agricontext:exclude-filter typeannotation expressionorg.springframework.stereotype.Controller//context:component-scan并配置数据源、SqlSessionFactoryBean和Mapper扫描spring-mvc.xml只负责扫描Controller、配置注解驱动和视图解析器。第三个易错点是Mapper接口和XML文件的映射关系。接口和XML要么放在同一个包下要么在mybatis-config.xml里明确指定mapper-locations路径否则会报Invalid bound statement异常。我习惯把它们分开放接口放java目录XML放resources下的mapper目录然后在spring-context.xml里写死property namemapperLocations valueclasspath:mapper/*.xml/稳定不出错。4.2 登录鉴权与角色权限控制不用Spring Security自己写拦截器SSM项目里引入Spring Security确实能让权限控制正规化但对毕设来说学习成本太高、配置太繁琐。自己手写一个登录拦截器效果一样而且答辩时能讲得头头是道。首先在登录接口中校验用户名密码通过后用UUID生成一个随机token把token作为key、用户信息JSON作为value写入Redis同时把token返回给前端。前端收到后存到localStorage里每次axios请求都在请求头带上token字段。后端写一个LoginInterceptor实现HandlerInterceptor接口public class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 放行登录注册接口 // 检查Header中token是否存在且有效 // 有效则把userId放入request域并放行 // 无效则设置响应状态401并返回JSON错误提示 return true; } }在spring-mvc.xml里配置拦截路径时要注意用mvc:exclude-mapping把登录、注册、课程列表、课程详情、资讯列表这些匿名可访问的路径排除掉。这里有一个我踩过的坑很多同学只写了include-mapping没写exclude-mapping结果前端页面频繁提示未登录排查半天才发现是拦截器把静态资源和公开接口全部拦了。更进一步可以在拦截器里解析token后拿到用户role再结合Controller方法上自定义的RequireRole注解做细粒度权限控制比如专家发布课程接口只允许role2访问管理员审核接口只允许role3访问。但考虑到毕设体量这个可以写成加分项不作为核心功能。我在项目里只做了未登录禁止访问一层拦截管理员和普通用户的菜单差异由前端根据本地存的role值来控制后端关键接口再加一层简单的角色判断即可。4.3 学习进度上报Service层的设计思路视频进度上报这个功能后端有几种设计思路我采用的是前端定时上报后端增量更新的方案。前端播放器组件里设置一个定时器每15秒调用一次上报接口把当前播放位置秒数、当前章节ID、已观看时长作为参数传给后端。后端的Service方法按这个逻辑写public void reportProgress(Long userId, Long courseId, Long chapterId, Integer position, Integer watchDuration) { LearningRecord record learningRecordMapper.selectByUserAndChapter(userId, chapterId); if (record null) { // 首次学习插入一条记录 record new LearningRecord(); record.setUserId(userId); record.setCourseId(courseId); record.setChapterId(chapterId); record.setLastPosition(position); record.setWatchDuration(watchDuration); record.setProgress(calculateProgress(position, totalSecond)); recordMapper.insert(record); } else { // 已存在更新last_position和watch_duration record.setLastPosition(position); record.setWatchDuration(record.getWatchDuration() delta); record.setProgress(calculateProgress(position, totalSecond)); recordMapper.updateById(record); } }这里有一个业务细节watch_duration的增量计算不能依赖前端传的值因为网络抖动可能丢数据正确的做法以后端为准——前端上报时把当前播放位置传过来后端用本次position减去数据库里已有的last_position得到增量。加一个判断如果增量为负或大于300秒可能是用户拖动了进度条则按0处理。4.4 MyBatis动态SQL与分页查询MyBatis的动态SQL是SSM项目的核心考点课程列表页和问答列表页的筛选功能都靠它实现。比如课程列表要支持按分类ID、难度、标题关键字搜索还要支持按浏览量排序select idselectCourseByCondition resultTypecom.agri.entity.Course SELECT * FROM course where if testcategoryId ! null and categoryId ! 0 AND category_id #{categoryId} /if if testdifficulty ! null and difficulty ! 0 AND difficulty #{difficulty} /if if test keyword ! null and keyword ! AND title LIKE CONCAT(%, #{keyword}, %) /if AND status 1 /where ORDER BY view_count DESC LIMIT #{offset}, #{pageSize} /select这里的where标签会自动去掉多余的ANDif标签实现了条件拼接。分页查询不建议自己手写PageHelper或者自己算offset直接在SQL里拼LIMIT就是最清晰的方式。特别提醒前端列表页通常有一个排序选择最新/最热这个排序字段也通过参数传给后端后端用ORDER BY create_time DESC和ORDER BY view_count DESC分别处理。5. 前端Vue落地路由守卫、Axios封装与视频播放细节5.1 项目初始化与目录规划前端用Vue 2 Element UI还是Vue 3 Element Plus我个人建议如果学校没硬性要求直接上Vue 3 Vite Element Plus因为2026年的技术栈里Vue 2已经进入维护尾声。但要注意如果后端同学更熟Vue 2也不必强行升级两者在毕设层面没有质的差别。初始化用命令一把梭npm create vitelatest agri-vue -- --template vue cd agri-vue npm install npm install axios vue-router4 element-plus element-plus/icons-vue npm install vue-video-player # 视频播放组件 npm run dev目录结构可以这样设计src/ api/ // 按模块拆分接口请求函数 assets/ // 静态资源 components/ // 通用组件如分页组件、课程卡片 router/ // 路由配置 store/ // Pinia或Vuex状态管理 views/ admin/ // 管理后台页面 expert/ // 专家创作页面 user/ // 农户端页面 Home.vue Login.vue Register.vue5.2 路由守卫与Token状态管理前端所有页面中游客能直接访问的只有首页、课程列表、课程详情、资讯列表、登录注册页其余页面都要登录态。在Vue Router的全局前置守卫中做判断是最优雅的方式router.beforeEach((to, from, next) { const token localStorage.getItem(token); const userInfo JSON.parse(localStorage.getItem(userInfo) || {}); if (to.meta.requiresAuth !token) { next(/login); } else if (to.meta.role to.meta.role ! userInfo.role) { next(/403); // 角色不符跳转无权限页 } else { next(); } });这里有一个小技巧路由配置里给需要权限的页面加meta字段meta: { requiresAuth: true, role: 2 }守卫里统一做判断。不要每个页面都去判断权限那样会写大量重复代码。5.3 Axios封装与跨域处理axios封装是前端面试也常问的点。我习惯把baseURL配置成环境变量按照接口调用统一加上tokenimport axios from axios; const request axios.create({ baseURL: /api, timeout: 10000 }); // 请求拦截器 request.interceptors.request.use(config { const token localStorage.getItem(token); if (token) { config.headers[token] token; } return config; }); // 响应拦截器 request.interceptors.response.use( response { const res response.data; if (res.code 401) { localStorage.removeItem(token); router.push(/login); return Promise.reject(new Error(登录已过期)); } return res; }, error { return Promise.reject(error); } ); export default request;跨域问题的标准解法是在spring-mvc.xml里配置CORS跨域过滤器不推荐在前端用proxy解决。代码实现上可以写一个CorsFilter实现Filter接口在response头添加Access-Control-Allow-Origin: *、Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS、Access-Control-Allow-Headers: Content-Type,token等并在web.xml注册。我当年被这个跨域卡了整整一天后来发现是自己写的Filter没注册到web.xml白白浪费了时间。5.4 视频播放与进度上报的联动视频播放的细节决定了这个项目的完整度。在课程详情页中我使用vue-video-player组件展示视频左侧是章节列表右侧是播放器。当用户点击某个章节时先向后端查询该章节的学习记录如果存在last_position且progress100则把播放器当前时间设为last_position实现继续学习的体验。进度上报的代码放在播放器的timeupdate事件里这个事件会每250毫秒触发一次如果每次都发请求后端会被打爆。我采用节流思路每15秒上报一次且只在本次播放位置与上次上报位置差值超过10秒时才发送请求。这样既保证数据不丢失也避免并发请求堵塞带宽。视频文件存储是另一个头痛的问题。毕设阶段最好不要自己存大文件到服务器推荐用本地路径加OSS代替。如果学校不给配OSS也可以用FFmpeg把大视频压缩后放服务器或者干脆用外链转码好的MP4测试。至于课程封面图、文档附件走普通的文件上传接口即可在spring-mvc.xml里配置CommonsMultipartResolver处理multipart/form-data请求。6. 论文写作、服务器部署与答辩演示的实操清单6.1 论文框架与图表绘制的实用建议论文写作建议从系统的核心功能倒推章节。标准六章结构是绪论选题背景与意义、国内外研究现状、论文主要工作、相关技术介绍SSM、Vue、MySQL、前后端分离、需求分析功能性需求、非功能性需求、用例图、系统设计总体架构设计、功能模块设计、数据库设计、系统实现每个模块的页面截图核心代码片段文字说明、系统测试测试环境、功能测试用例、测试结论、总结与展望。写论文时最常见的错误是把代码整段贴上去三页纸全是代码老师看得头疼。正确做法是只贴关键代码片段比如核心SQL语句、拦截器、进度上报方法每段代码后面跟3到5行文字说明这段代码解决了什么问题、核心设计思路是什么。图表方面用例图、时序图、ER图、系统架构图、功能结构图这五张图足够了画清楚即可不需要堆砌。6.2 服务器部署的通用流程毕设答辩前把项目部署到云服务器上让老师远程访问现场演示比本地跑更有说服力。部署流程并不复杂约等于几件事买一台轻量云服务器高校学生认证通常有优惠、装JDK 8、装MySQL、装Tomcat 9、装Nginx。后端打成war包丢到Tomcat的webapps目录启动后访问http://服务器IP:8080/api能通就算成功。前端执行npm run build生成dist目录用Nginx托管server { listen 80; server_name _; root /usr/share/nginx/html/dist; index index.html; location /api/ { proxy_pass http://localhost:8080/api/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # 前端路由history模式需要配置 location / { try_files $uri $uri/ /index.html; } }这个Nginx配置里有三个关键点location /api/的反向代理把前端的接口请求转发到Tomcattry_files解决Vue Router history模式刷新404的问题root指向dist目录的位置要和你上传的路径一致。我当年刚部署时API请求全是404就是忘了配反向代理前端页面能打开但数据一概加载不出来。6.3 答辩演示的避坑清单答辩演示是整个毕设最后也是最容易翻车的一关。我总结几次辅导学生答辩的教训列一个实操清单数据要提前铺好在数据库里至少预置5门课程、每门课程3个章节、20条资讯、10个问答、3个专家账号、1个管理员账号视频用短小的MP4文件保证点击就能播放不要现场等加载。准备两个演示路径主路径是游客→注册→农户登录→浏览课程→播放视频→上报进度→收藏→提问备选路径是管理员登录→审核课程→用户管理→数据统计万一主路径出问题马上切换备选路径。不要现场改代码哪怕评审老师提出这里应该怎么优化也先说这个点我考虑到了目前实现是xxx确实可以进一步迭代不要举起键盘就在编辑器里敲代码十有八九要翻车。提前测试网络如果演示用的是云服务器先确认服务器外网带宽够视频能流畅播放如果你在教室这种网络环境不好的场景演示可以提前把视频下载到本地用localhost演示。论文中的测试部分也要提前设计好测试用例表包含模块、测试步骤、预期结果、实际结果、是否通过这几列至少写15个以上的用例覆盖正常流程、异常流程和边界值场景答辩时老师翻到这一页对格式会很满意。最后说一个我在实际辅导中反复强调的点千万不要为了显得系统高级就把答辩PPT和论文里塞满慕课网、极客时间上的专业术语结果被评委老师一句话问穿。老老实实把SSM这些配置细节学通、把业务代码自己一行行敲完答辩的底气自然就有了。农业技术学习平台这个题的稳在于技术本身不炫技、代码量适中、业务有真实应用场景。把这些内容吃透2026年的毕业设计你完全来得及做出一套拿得出手的完整系统。
返回列表