ARTICLE DETAIL

资讯详情

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

计算机学习网站开发全流程:从需求分析到上线部署实战

计算机学习网站开发全流程:从需求分析到上线部署实战 每年这时候都有不少朋友来问毕设选题尤其是计算机科学与技术方向十个里有六七个想做学习类网站。这个方向确实讨巧需求清晰、技术栈通用、演示效果直观但正因为做的人多反而容易做成一堆功能堆砌的课程列表页。我前段时间刚完成一个编号为m248的项目——计算机科学与技术学习网站的设计与开发从需求分析到部署上线完整走了一遍有些经验值得拿出来聊聊。这个网站的核心定位不是做一个放视频的课件站而是把课程检索、学习路线、在线练习、个人笔记几个环节串起来让一个刚接触计算机的新手或者想系统补基础的同学能沿着一条明确路径往前走。整个开发周期大约六周技术栈选了Spring Boot加Vue的前后端分离方案数据库用的MySQL另外用Redis做缓存和会话管理。这篇文章会把设计思路、模块实现、踩过的坑、以及上线后的运营细节都摊开讲适合正在做类似毕设、或者想自己搭一个学习站点的同学参考。1. 这个学习网站到底解决什么问题从用户痛点倒推需求动手写第一行代码之前最该想清楚的是网站给谁用、解决什么具体问题。我见过太多同类项目一上来就堆课程分类、视频播放、论坛讨论最后界面长得像低配版慕课网但用户根本不知道从哪里开始学。做学习网站最核心的价值不是提供资源而是提供路径。1.1 目标用户画像与核心痛点我做需求分析时把目标用户分成三类各自的痛点非常不一样计算机专业低年级本科生大一、大二刚接触编程学校课程按学期推进但很多人在数据结构、操作系统这类核心课上跟不上需要课外补充学习资料。他们的痛点是资料太多、不知道按什么顺序看。转码自学者非科班出身想通过自学进入开发行业。这类人往往不缺学习资源和教程缺的是系统性的路线图和能检验学习效果的练习题。课程设计/期末复习人群需要快速查找特定知识点比如二叉树遍历HTTP状态码希望有精准的搜索结果和精简的总结。三类人群交集明显都需要结构化内容 可验证的学习成果。所以我把网站定位为学习路径 内容检索 在线练习三位一体的工具型站点而不是又一个视频点播平台。1.2 功能需求收敛砍掉哪些、留住哪些初期我列了十多个功能点包括视频弹幕、论坛、积分商城、在线聊天后来全部砍掉。保留下来并且最终做出来的只有五个模块模块解决的问题关键功能课程中心知识获取课程分类、关键词检索、章节内容浏览学习路线学习路径按阶段展示路线节点、节点进度标记在线评测学习效果验证精选练习题目、代码提交、自动判题学习笔记知识沉淀个人笔记写、改、删、按课程归类后台管理内容维护课程/题目/路线图的增删改查、用户管理砍功能的原则很简单每一项功能必须能回答用户使用它的频率有多高和没有它会不会影响核心体验。视频弹幕这种功能做出来热闹但和学习效率这个核心价值没有强关联反而是在线评测这种看起来不显眼的功能对学习效果的提升是实打实的。事实证明最后演示的时候评委最感兴趣的也是自动判题这个模块。2. 技术选型的取舍逻辑一个人开发也要考虑未来有人维护技术选型是这类项目最容易纠结的环节。选太热门的怕烂大街选太冷门的怕出问题没人帮忙。我的结论是在成熟生态里挑一套自己最熟悉的组合比追求技术新颖更重要。2.1 前后端方案对比与最终选择主选方案是Spring Boot 3 Vue 3 MySQL 8备选方案是Python Flask/Django Vue SQLite/MySQL。两者的取舍我做了个简单对比对比维度Java Spring Boot方案Python方案上手成本中高需要理解Bean、依赖注入等概念低Flask几十行能跑起服务生态成熟度高企业级应用广泛遇到问题容易搜到答案高但偏脚本场景重型业务少代码执行/判题支持多语言编译执行方便javac/gcc等进程管理成熟执行子进程也方便但并发和资源隔离要小心答辩友好度高评审普遍认可Spring全家桶中视评审老师偏好而定部署成本稍高要装JDK、打jar包低pip依赖装完就能跑最终选了Spring Boot主要是因为毕设场景下可预测性优先。Java的生态太庞大了遇到前端跨域、Redis连接、文件上传这类问题网上随便一搜就是完整的解决方案不太会在环境层面卡住。另外在线评测模块需要调用外部编译器比如javac、gcc、pythonJava在管理子进程、限制资源占用比如超时、内存上限方面的做法更成熟这一点在后面的开发中确实省了很多事。2.2 关键依赖组件清单除了主框架我还选了几个配套组件这里列一下选型和理由Redis 6.x做登录会话缓存、课程点击量缓存。逻辑上Session原来可以放服务器内存但考虑到将来可能部署到多实例用Redis属于现在麻烦一点、以后少改架构的决策。MySQL 8 Nginx数据持久化和静态资源/CDN入口。MySQL的全文索引ngram parser在搜索功能里帮了大忙这个后面细说。MyBatis-Plus数据访问层。比纯MyBatis少写很多CRUD样板代码尤其在后台管理的增删改查上效率提升明显。前端用Vite构建 Element Plus组件库Element Plus的后台表格、表单、树形控件都是现成的能保住开发进度。提示选型阶段一定要写一个简单的技术选型说明文档把每个组件用来解决什么问题写清楚。答辩的时候老师几乎必问为什么用Redis为什么不用MongoDB提前准备好理由比到时候现想强得多。3. 核心功能模块设计与实现顺序先做骨架再填血肉功能实现顺序我建议按用户主路径来排先让他能浏览课程内容再给他路线图和练习最后才是个人笔记和后台管理。这样每一步做完都能跑起来看到效果不会出现开发两个月、联调才崩的窘境。3.1 数据库设计五张核心表一张路线表数据库设计是这类项目的地基。我建的核心表如下字段设计考虑了扩展性表名核心字段作用usersid, username, password_hash, role用户认证与权限区分categoriesid, name, parent_id, sort_order课程分类树coursesid, category_id, title, summary, cover_url课程基本信息course_chaptersid, course_id, title, content_html, sort_order章节内容problemsid, title, description, input_desc, output_desc, difficulty练习题目描述learning_path_nodesid, title, description, order_index, link_type, link_id学习路线节点judge_recordsid, user_id, problem_id, code, language, status, execute_time提交与判题记录notesid, user_id, course_id, title, content_markdown个人学习笔记这里想特别说一下learning_path_nodes这张表的设计。学习路线本质上是一个有向无环图节点之间有依赖关系比如学完数据结构再学算法。我最初想用邻接表存节点关系后来发现对学习路线来说线性序列 阶段分组就够用了。每个节点存一个order_index前端按这个排序渲染时间线后台调整顺序只需要改这个字段。真要做复杂的课程依赖判断比如必须先修完课程A才能解锁课程B再用单独的依赖表也不迟前期不做过度设计。3.2 课程中心搜索是门面分类树是骨架课程中心是整个网站访问量最大的页面实现上分两部分分类浏览和关键词搜索。分类浏览用两级分类就够了一级是编程语言数据结构操作系统计算机网络数据库这样的大类二级是具体课程或专题。前端渲染分类树用递归组件数据一次从后端取完不搞懒加载减少请求次数。搜索是重点也是坑点。刚开始我用的是 MySQL 的LIKE %关键词%课程少的时候没问题但数据量上来之后有两个问题一是性能差不能走索引全表扫描二是匹配不聪明搜二分查找匹配不到标题为Binary Search 算法详解的课程。后来改成 MySQL 全文索引配合 ngram 解析器ALTER TABLE courses ADD FULLTEXT INDEX ft_course_title (title) WITH PARSER ngram;查询时用MATCH(title) AGAINST(二分查找 IN NATURAL LANGUAGE MODE)中英文混合的内容也能正确匹配。课程数量级在几万条以内MySQL全文索引完全够用没必要上Elasticsearch运维成本高不少。课程详情页除了展示章节内容我还加了一个相关课程推荐的逻辑按同一分类下点击量排序取前五条。这个功能虽然简单但对用户体验的提升很明显让用户在看完一节课之后有地方可以去而不是关掉页面。3.3 在线评测最费心也是最有亮点的一块在线评测模块是整个网站技术含量最高的部分也是答辩时老师问得最多的地方。核心流程是用户提交代码 → 后端调用相应语言的编译器/解释器 → 在受控环境中运行 → 比对输出 → 返回结果。整个流程我简化成四个环节第一代码执行。后端接收入参后把代码写入临时文件调用javac、gcc、python等命令编译执行。判题用例放在受限目录运行时把用户程序的输出重定向到临时文件然后和答案文件比对。第二资源限制。这是必须做的否则一个恶意死循环就能把服务器拖垮。我用了两层防护外层在调用层设置超时一般单用例 3 秒内层用操作系统的资源限制功能限制进程 CPU 时间和内存subprocess.run( [command, code_file, input_file], capture_outputTrue, timeout10, preexec_fnlimit_resources )Java端也有对应的方案用ProcessBuilder起子进程配合destroyForcibly()做超时兜底。第三安全隔离。说实话让用户提交任意代码在服务器上执行还是有风险的。演示环境里我用 Docker 容器做隔离每个判题请求起一个临时容器跑完直接销毁。虽然资源开销大但安全性能保证。如果实在不想引入Docker至少要做到禁止用户提交Shell脚本、限制可执行文件路径白名单、以低权限用户运行判题进程。第四结果反馈。判题结果不只是通过/不通过我会给用户展示编译错误信息、运行超时提示、第一个不匹配的用例的期望输出和实际输出。这一步对学习体验很重要——用户看到具体的失败原因才知道怎么改代码。3.4 学习路线图用JSON配置而非硬编码学习路线图我最初想在前端写死节点后来发现每次调整路线都要改前端代码、重新打包发布太麻烦了。改成运行时可配置的方案路线图数据存数据库前端从接口拉取按阶段和时间线渲染。简化版的路线JSON结构类似{ 阶段1: [编程语言入门, 计算机基础], 阶段2: [数据结构, 算法设计], 阶段3: [操作系统, 计算机网络, 数据库原理], 阶段4: [实践项目, 专项进阶] }前端对每个节点渲染卡片用户点击某个节点可以跳转到对应的课程或练习。学习进度标记就存user_id node_id is_finished逻辑简单但很实用。线路图的数据内容我花了不少心思。参考了几所高校的教学计划把CS核心课程按照依赖关系排了一遍高等数学、离散数学作为前置基础然后才是数据结构、计算机组成原理再往后是操作系统、编译原理、计算机网络。这个依赖关系虽然不是绝对正确但对新手来说是一个非常友好的引导。4. 踩坑实录开发途中真正浪费时间的五个问题这个项目前后踩了不少坑挑五个最典型的写出来每一个都是在搜索引擎上绕了很久才搞定的希望后来的同学少走弯路。4.1 富文本编辑器的XSS注入问题学习笔记模块一开始我用的是富文本编辑器用户可以输入任意HTML。结果测试时发现一个大问题用户可以在笔记里插入script标签或者恶意事件属性比如img srcx onerroralert(1)。如果不做处理别人浏览到这篇笔记时就会执行这段脚本典型的存储型XSS漏洞。解决思路是前端渲染前过滤 后端入库前直接拒绝危险内容。后端用Jsoup框架做白名单过滤只允许正常的p、a、img、code、pre等标签所有on*属性和script标签一律清除。笔记内容从Markdown源文本保存渲染成HTML时才过滤双保险。4.2 课程搜索搜不到和搜不准并存没上全文索引之前搜索有两个毛病。搜动态规划能出结果但搜dp就匹配不到任何内容因为标题里写的是中文全称反过来搜Java会把JavaScript的课程也搜出来因为LIKE %Java%子串匹配的粒度太粗了。后来用了ngram全文索引情况好了很多但还有一个细节要处理全文索引默认按相关性排序相关性评分受词频影响课程标题字段短、关键词密度高评分反而合理。另外我在搜索接口上加了一个简单的中文分词步骤把用户输入的查询短语按常规分隔符空格、逗号拆开再拼接成MATCH ... AGAINST的布尔模式SELECT * FROM courses WHERE MATCH(title) AGAINST(Java 并发 IN BOOLEAN MODE)这样Java 并发可以被精确匹配而不是被当成一个完整长词匹配效果肉眼可见地变好。4.3 Vue Router History模式部署后刷新404前端用的History路由模式本地开发一切正常打包部署到Nginx之后访问首页没问题但在/courses/12这样的详情页按F5刷新直接404。原因很简单Nginx默认在找不到对应文件时才走不到前端路由因为生产环境没有/courses/12这个真实路径。解决办法是在Nginx配置里加一个回退逻辑location / { try_files $uri $uri/ /index.html; }所有非静态文件的请求都回退到index.html由前端路由接管。这个坑我记得特别清楚因为排查时一度怀疑是Vue Router版本问题调了很久最后发现就是一行Nginx配置的事。4.4 在线评测的隐藏扣分项运行时错误信息不完整判题模块在测试时发现用户代码如果出现数组越界、空指针、除以零这类异常只能看到一个笼统的运行时错误具体哪一行出错、错误信息是什么完全看不到。对学习者来说这种反馈基本等于没有。后来改成了捕获并记录异常堆栈在Java判题场景里用户代码的异常信息会打印到标准错误输出流判题进程把stderr的内容捕获下来如果判题结果是RERuntime Error就把堆栈的前几行返回给前端展示。注意这里要做好信息截断只显示异常类型和行号不暴露服务器内部路径和敏感信息。4.5 跨域问题差点让前端联调崩掉前后端分离开发时前端跑在localhost:5173后端跑在localhost:8080必然会遇到跨域问题。一开始我在后端加了CrossOrigin注解能解决一部分GET请求但带自定义Header的POST请求依然报跨域错误。正确的做法是在后端写一个全局的CORS配置类允许指定的前端来源、请求方法、请求头和携带凭证registry.addMapping(/**) .allowedOrigins(http://localhost:5173) .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .allowCredentials(true);这里有一个小坑allowedOrigins(*)和allowCredentials(true)不能同时使用浏览器会直接拒绝必须写明确的前端域名。联调阶段这个配置帮我省了一整天的排查时间。5. 数据从哪来种子内容准备与内容安全底线网站功能写完只是第一步更费时间的是让网站看起来有内容。一个空荡荡的学习网站再好的功能也没人愿意用。我给自己定了一个目标上线时至少要有一套完整的课程内容和100道可判题的练习。5.1 种子数据的来源与版权处理课程内容这块我的做法是引用公开资料 整理原创讲义而不是直接搬运别人的课程视频或文档。具体来源包括公开课程大纲参考国内外知名高校公开的课程页面吸收他们的知识点组织方式自己重新编写摘要和章节结构。经典教材目录比如数据结构、操作系统这类经典教材的章节顺序本身就是很好的知识组织框架据此设计课程分类。网络公开的OJ题目很多OJ平台有开放题目集自己重新改写题目描述和测试用例标注题目来源不能原样复制。这里要特别提醒一句毕设源码和内容都要注意版权边界。直接从慕课网、B站把别人的视频嵌进来虽然演示时方便但存在侵权风险。我的方案是以图文讲义和代码示例为主视频只是补充版权上稳妥得多。5.2 在线题目的打磨测试用例比描述更重要练习题准备中我最大的体会是一道题值的不是题目描述而是测试用例。一道判断回文数的题目测试用例至少要包含正例1211221、负例12310、边界值0负数、溢出情况。原本我以为写完题目描述就完事了后来测试时发现用户提交的代码五花八门边界用例不充分判题结果非常不稳定。后面我每道题至少配8到10个用例3个公开示例用例前端显示 5个以上隐藏用例判题时使用。隐藏用例的意义在于用户就算看到了示例也不能只针对示例写死答案必须真正理解算法。5.3 内容安全底线UGC内容不能裸奔学习笔记和用户昵称是用户生成内容UGC这部分必须有审核机制。我的做法是三层过滤第一层前端输入限制。昵称长度、笔记字数、图片上传格式先在前端拦住。第二层后端内容过滤。引入敏感词库做关键词匹配命中直接拒绝提交或者把内容标记为待审核状态。第三层运营后台审核。后台管理列表里加一个笔记审核页签管理员可以查最近一周产生的笔记一键下架违规内容。这个设计在答辩时很加分因为能体现安全意识和隐私保护意识而很多同类项目完全没考虑这些问题。6. 部署上线与运营细节从毕设到真正可使用的学习站点功能开发完成后我部署在一台轻量云服务器上2核4G配置系统用的Ubuntu 22.04环境是Nginx MySQL Redis Spring Boot jar包。整个部署过程比较标准说几个值得注意的细节。6.1 前后端分开部署与Nginx配置前端打包后的静态文件放在/var/www/html后端jar包用systemd管理服务设置开机自启和崩溃自动重启。Nginx这里配置一个反向代理把/api/前缀的请求转发到后端服务server { listen 80; server_name your-domain.com; root /var/www/html; index 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; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location / { try_files $uri $uri/ /index.html; } }如果服务器带宽不高建议Nginx开启压缩图片资源做一下瘦身网页首屏加载速度会有显著提升。为了省流量我的封面图统一用了WebP格式比JPG大概小30%左右。6.2 用HTTPS保护用户会话登录功能上线后HTTP明文传输用户的账号密码肯定不行。我申请了免费的HTTPS证书在Nginx里配置443端口和证书路径同时把80端口请求301重定向到HTTPS。这一步看起来不起眼但它保证了登录会话的安全性也避免部分浏览器对非HTTPS页面的不安全警告劝退用户。6.3 冷启动让网站真正被用起来网站上线后最尴尬的是没有用户。冷启动阶段我做了三件事拉身边人试用找了十来位同学、朋友注册体验收集了一轮真实反馈。印象最深的是有人反馈学习路线图很清晰但点击节点跳转后不知道该怎么回来于是我在路线图页面加了面包屑导航。SEO基础配置给每个课程页面配置合理的title和meta description提交搜索引擎收录。虽然学习网站不是靠搜索流量起家的但别让搜索引擎完全抓不到。定期更新题目上线后每周更新5到10道新题保持在线评测模块的活跃度。网站不怕小怕的是放着不管。6.4 备份最后的保命手段数据备份是最容易被忽略的环节。我配置了一个简单的定时任务每天凌晨用mysqldump备份数据库保留最近七天的备份文件。另外用户上传的图片和笔记附件单独打包备份到对象存储。毕设答辩结束、网站不维护了数据备份依然有价值——至少交出去的时候还能恢复给下一届同学或者作为代码仓库的一部分。最后说点实在的做这个计算机科学与技术学习网站我最深的感受是写代码的时间只占三分之一剩下三分之二是需求梳理、数据准备和排坑。尤其是学习路线和在线评测这两个模块前者要理解教学逻辑后者要保证判题安全都是纯CRUD页面体现不了的能力。如果让我重做一次我会把在线评测的沙箱方案从Docker改成更轻量级的多进程隔离减少每次判题的资源开销提高并发能力。另外后台管理界面我会提前两周开始做别拖到最后通宵赶工——后台的CRUD页面虽然逻辑不复杂但表单字段多、列表筛选条件多工作量比想象中大不少。最后分享一个小技巧把学习路线图的配置数据单独抽成一个JSON文件放在前端资源目录里开发时先不用接数据库直接读JSON渲染页面等UI确定了再切换到后端接口。这样前端开发和后端开发在路线图模块上完全解耦是这次项目里节奏最顺的一个模块。
返回列表