新闻详情

新闻详情

首页 / 资讯中心 / 详情

从零到一完成Web大作业:技术选型、踩坑与安全加固实践

发布时间:2026/9/30 9:34:25来源:尧图网络
从零到一完成Web大作业:技术选型、踩坑与安全加固实践
上周交了Web方向的第一次大作业看着成绩单上那个A我第一反应不是开心而是长舒一口气。因为这整整两周时间我几乎每天都在跟各种报错搏斗Maven依赖冲突、MySQL驱动加载失败、Nginx反向代理超时、WebSocket连接断断续续……如果你也正准备做自己的第一个Web项目或者正在被老师的Web作业折磨这篇文章就是为你准备的。我不会讲什么高大上的理论只想把这回从零到一的全过程掰开揉碎说清楚——选题、技术选型、环境配置、编码、部署还有那些只有踩进去才会懂的坑。1. 一个“简单”的Web作业为什么让我焦虑了两周1.1 作业要求只有一句话但我连做什么都没想清楚老师发的通知很简短要求每个人提交一个Web方向的第一次大作业主题自拟功能自定技术不限。当时班里很多人觉得这是送分题毕竟“Web不就做个网页嘛”。我也这么想直到真正坐下来要写需求时才发现脑子一片空白。做个人主页太简单可能拿不到高分。做一个系统什么系统用户要什么功能数据存哪里一连串问题砸下来我连第一步都没迈出去。那几天我翻了无数教学视频和博客越看越焦虑。视频里演示的都是“做个TodoList”“做一个计算器”但那是给别人演示用的不是给老师交差用的。我意识到所谓“Web第一次作业”真正的难点不在于怎么写代码而在于怎么在有限时间内定义一个合理、能完成、又能体现学习成果的项目范围。这个认知花了我两天时间比后来写代码的时间还长。1.2 从“做一个网站”到“做一个系统”的认知升级为了理思路我跑去问上一届的学长。他说的一句话点醒了我“你们老师想看的不是花哨的页面而是你对Web开发全流程的理解。”他建议我把作业定位成一个小型管理系统比如图书管理、班级管理、个人博客只要包含最基本的“增删改查”和“登录注册”就足够展示核心能力了。于是我决定做一个个人博客系统。功能不贪多游客可以注册账号、登录后发表文章、编辑自己的文章、给别人的文章留言。管理员可以管理所有用户和文章。听起来很简单但当我把这些功能拆开时才发现要写的东西密密麻麻用户表、文章表、评论表、密码加密、会话管理、前端页面、后端接口、数据库连接、参数校验……我开始意识到任何一个看起来“简单”的Web系统背后都是一整套工程逻辑。1.3 拆解后的需求清单看着像座小山我拿A4纸画了一张表格把所有需要实现的功能列出来模块功能点优先级用户模块注册、登录、注销、密码加密保存必做文章模块发布、编辑、删除、列表、详情必做评论模块发表评论、展示评论、删除评论选做管理模块后台管理用户和文章加分样式模块响应式布局、基础交互必做列完之后我给自己定了一个原则先保证必做功能完整可用再考虑加分项。因为这是第一次作业能把基础功能打磨扎实就已经很了不起了。后面的事实证明这个原则让我少加了两晚上的班。2. 技术选型的纠结每个方案都有人吹但只有亲手试过才知道2.1 前端框架我差点在Vue和React之间精神分裂确定功能之后开始选技术栈。前端我一开始在Vue和React之间纠结。网上铺天盖地都是“Vue更适合新手”“React是趋势”之类的说法。我两个都看了下官方文档最后还是选了Vue。原因很实在一来Vue的模板语法对后端思维的我更友好二来中文社区资料多遇到问题一搜就能找到答案。React的生态虽然也很成熟但JSX和Hooks的思维方式需要额外适应对一个第一次做大作业的人来说上手成本略高。当然我也没直接用脚手架而是在网页里引入CDN方式用的Vue 3。这样既能享受响应式开发的便利又不用提前纠结Node.js环境和打包配置。后来发现这个决定很明智因为让我在第一次作业里同时处理Vite、Webpack等一系列构建工具大概率会原地崩溃。2.2 后端从Servlet到Spring Boot两个方案的取舍后端我原本打算用纯Servlet写因为课程内容刚好讲到那里。但写了两天之后我发现问题特别多配置web.xml简直反人类一个简单的请求转发写一大堆代码数据库连接得自己管理参数校验要一个字段一个字段地手动写。整个人被臃肿的样板代码牵着鼻子走真正的业务逻辑反而没写几行。于是咬咬牙切到了Spring Boot。我记得在IDEA 2024版本创建Web项目时用Spring Initializr一键生成好项目结构内置Tomcat引入spring-boot-starter-web就搞定了一个能运行的应用。那种顺畅感真的让人想哭。虽然Spring Boot要理解自动配置、依赖注入这些概念刚开始有点懵但说句实话这些概念在第一次作业阶段只需要会用即可不用钻太深。关键是我把省下来的时间用在了业务逻辑上开发效率翻了一倍。2.3 数据库、服务器和部署方案怎么定数据库没悬念选了MySQL毕竟大家都在用教程多而且免费。唯一纠结的是要不要上MyBatis。后来选择用Spring Data JPA因为第一次作业的表结构简单用JPA可以少写很多SQL实体类自动映射非常省心。如果你做的是复杂查询那MyBatis更合适但对我的场景来说JPA足够。部署方案也很重要。我看了一圈从打Jar包到云服务器运行再到Nginx反向代理静态资源最终决定用本地虚拟机跑一个最小的Linux环境配上Nginx做反向代理和静态资源服务。这步当时觉得很折腾但后来面试时被问到部署经验我非常硬气地讲了半天才知道老师布置这次作业的用意之一就是逼我们把一条链路全走通。2.4 最终拍板这套技术栈最适合第一次作业我最终确定的技术栈是前端HTML CSS Vue 3CDN方式后端Spring Boot 2.7 Spring Data JPA数据库MySQL 8.0部署Nginx Ubuntu虚拟机这套组合的好处是每一层都是主流技术学完以后能直接迁移到真实项目里同时每层都有大量现成资料遇到问题不会孤立无援。我强烈建议第一次做Web作业的同学哪怕你的作业只是“做一个班级网站”也尽量用这种“正经项目”的架构来练手——它会让你在一次作业里体会到从设计到上线的完整流程价值远超那个分数。3. 开发期间的踩坑日记环境问题比代码逻辑更致命3.1 IDEA 2024创建Web项目时我卡在了第一步不得不说IDEA 2024的Spring Initializr界面已经非常傻瓜了但仍有几个隐藏雷点。第一次创建项目时我选完Java版本和依赖后点Next等待下载结果Maven一直报下载超时。折腾了半个多小时最后发现原因是IDEA默认的Maven仓库地址是国外源速度非常慢。解决办法很简单打开Maven的settings.xml把镜像换成阿里云镜像然后刷新项目。另一个常见问题是JDK版本不匹配。IDEA 2024默认推荐Java 17但我的电脑上还有老项目的Java 8Spring Boot版本又对编译级别有要求。后来我固定用Java 8 Spring Boot 2.7组合因为这组搭配经过大量验证很稳定。如果你用的是Spring Boot 3.x那最好配Java 17以上千万别混用。创建项目这一步都搞定之后我以为噩梦结束了没想到这只是开始。3.2 折腾了一整天的WebSocket配置原来只是yml里少了一行因为想给博客加一个简易的在线聊天室我决定引入WebSocket功能。网上搜到一堆教程大多是用Spring Boot集成WebSocket然后配一个config类再写一个Handler。我照着敲了一整天前端始终连不上后端控制台报Failed to connect to ws百思不得其解。后来我在日志里看到一行提示WebSocket sockjs is not enabled。原来Spring Boot集成WebSocket时需要在application.yml里显式启用SockJS或调整端点路径。我的yml配置最开始只有server: port: 8080加上WebSocket相关配置后变成server: port: 8080 spring: jackson: time-zone: GMT8 websocket: prefix: /chat我重新阅读了官方文档最终发现其实不需要spring.websocket这种配置而是注册端点时指定路径。真正的问题出在我的前端连接URL写错了应该写成ws://localhost:8080/chat/websocket而不是ws://localhost:8080/chat。就这么一个斜杠和路径的差别浪费了我整整一天。这个教训让我明白遇到连接类问题先抓握手URL再检查日志比瞎改配置快十倍。3.3 跨域、乱码和端口占用联调三连击前后端联调时又炸了。我用Vue的Axios请求后端接口控制台直接报跨域错误。第一次面对CORS问题我很慌。上网查了查解决方案其实很简单在后端加一个CrossOrigin注解或通过全局配置放行所有域。我当时图省事直接加在Controller类上RestController CrossOrigin(origins *) RequestMapping(/api) public class UserController { ... }虽然能用了但后来安全加固时才知道*放行所有域是安全隐患。自己学习没问题但提交作业时最好指定具体的域名。乱码问题也折腾了更久。页面展示中文全是问号排查半天发现是我的MySQL连接URL忘了加characterEncodingutf8参数导致数据库读写都是默认编码。修改连接字符串jdbc:mysql://localhost:3306/blog?useUnicodetruecharacterEncodingutf8这行加上之后中文显示就正常了。这个坑特别经典十个JavaWeb新手至少九个会碰见。端口占用也很搞笑有一次后端起不来提示Port 8080 was already in use。我查了任务管理器发现之前调试时开的旧进程没杀掉。用命令行关掉再启动就恢复了。这种基础问题虽然简单但如果你第一次接触会真的被吓到。我当时还差点重装IDEA幸好问了一句百度。3.4 上线一刻Nginx又给我上了一课本地跑通了我部署到虚拟机上的Nginx时又踩了连环坑。首先是Nginx配置静态资源我把打包后的前端文件丢进/var/www/html结果浏览器一直403。后来发现是目录没有权限。sudo chmod -R 755 /var/www/html改了权限才通。然后是反向代理Spring Boot的后端接口我写完proxy_pass配置后刷新页面死活拿不到接口数据。翻Nginx错误日志看到一条upstream prematurely closed connection while reading response header from upstream查了很久才发现是Spring Boot的request body大小和Nginx的proxy buffer配置不匹配。加上下面的配置就解决了location /api/ { proxy_pass http://localhost:8080; proxy_read_timeout 60s; proxy_buffering off; }说实话如果这次作业只要求“在浏览器上看到效果”我完全可以不加Nginx这一层直接用Spring Boot跑前端页面。但我就是觉得作为Web开发如果连部署都不懂以后工作会非常被动。所以这个坑踩得值。4. 从作业到Web安全一次意外的漏洞扫描打开了新世界4.1 给自己网站做了个XSS测试结果被自己网站攻破了作业快完成时我在网上看到一篇Web安全相关的文章里面提到XSS漏洞和SQL注入。我随手在自己的博客站点输入框里填了一段测试脚本scriptalert(haha)/script点击提交后弹窗真的出现了。这意味着我的网站存在存储型XSS任何用户都能通过评论框把恶意脚本存进数据库其他用户访问时脚本就会执行。我瞬间有点后怕——如果这不是作业而是一个真实网站后果不堪设想。我赶紧翻代码发现原因是没有对用户输入做过滤也没有在输出时转义。修复办法其实很简单后端加一个HtmlUtils.htmlEscape()对文本内容转义。前端Vue自动转义但要注意使用v-html会绕过所以我改成了纯文本插值。测试之后弹窗不再出现我才明白一个Web应用“能跑”和“安全”之间隔着整整一个Web安全的知识领域。4.2 第一次接触CTF的Web题修完漏洞后我对Web安全产生了浓厚兴趣开始在B站和社区找资料第一次听说了CTFCapture The Flag比赛。抱着试试看的心态去刷了几道入门题比如ctfshow的web入门和bugku的web题解。有些题看起来简单却特别锻炼思路比如加一个注释里藏着flag的信息泄漏题。URL参数回调的SSRF题。经典的SQL注入绕过题。做CTF题和做Web作业完全是两种体验。做作业时更关注让功能正常CTF则是去想开发人员哪里没做好、哪里可以钻空子。回头看自己的作业真的是漏洞百出。学了一轮安全知识后我给自己的博客补上了很多防护密码用BCrypt加密、数据库操作改用PreparedStatement、验证登录后才能访问管理接口、所有输出做HTML实体转义。这些改动不复杂但让整份作业的质量上了一个档次。4.3 修完漏洞之后我把作业升级成了小项目安全加固之后我的博客系统更像一个能上线的小项目了。我又顺手加了一个简单的日志切面记录每个接口的请求耗时用AOP实现几行代码而已但老师看了直接加分。同时我把数据库账号改成最小权限用户不再用root连库把Netty、Tomcat等服务的版本信息隐藏起来避免暴露服务指纹。这件事让我意识到第一次Web作业的正确打开方式不是“把页面写漂亮”也不是“追求酷炫的动画”而是踏踏实实把整个Web开发链路走通并且愿意在实现基本功能后往外多迈一步。安全、性能、部署、可维护性哪一项都可以成为你作业里的加分点同时也是你真正成长的起点。我甚至看到有同学在作业里写了自动化测试老师当场给满分。5. 如果再来一次我会怎么把第一次Web作业做得更好5.1 先画原型图而不是先写代码如果重新来过我会花两个小时在纸上画好每个页面的原型图标清楚按钮跳转到哪里、表单字段叫什么、权限怎么控制。有了原型图写代码时就完全不慌因为逻辑已经在脑子里过了一遍。那两周我至少因为前后端接口字段不一致而反复修改非常浪费时间。第一次做项目的同学一定不要跳过设计直接编码。5.2 学会看日志比到处百度高效一百倍调试时最容易犯的错误就是把错误信息原封不动复制到百度然后一个个试。我这次的经验是先看完整异常堆栈从最下面一行往上找定位到具体是哪个类、哪一个方法出了问题。比如有一次日志提示NoSuchBeanDefinitionException我一下子就猜到是某个Service没加Service注解直接修复根本不用搜资料。日志是导航仪搜索引擎只是加速器顺序千万别搞反。5.3 版本控制要早用不用等“以后再说”写作业第一天我就应该把项目丢到Git仓库里而不是等到过了五天改得乱七八糟才想起初始化。有一天我在改登录功能时把会话拦截器写得有问题导致所有页面无限跳转登录页。如果没有Git回滚我可能要花一个晚上找问题。用上Git之后一条git revert就把代码恢复到之前可运行的状态安心了不止一点。哪怕是一个人的作业也值得用版本管理。5.4 时间安排别高估速度别低估需求变化我前期建模和调整需求花费了大把时间本来计划五天完成开发结果实际用了快两周。如果重新排期我会第一天只确定核心功能和数据表结构第二天完成环境和脚手架第三到五天集中把后端接口写完第六到七天做前端页面第八天部署和安全加固留下两天缓冲处理字。这样即使中途遇到意外也不会拖到截止日期前熬夜通宵。5.5 向别人演示前一定要先写一份“演示剧本”最后一点小经验是我这次作业收获的真实教训。课堂演示那天我自信满满打开浏览器结果数据库服务没启动页面白屏一大片。前台补救时我只能尬笑。后来我把演示要做的每一步写成了清单先启动MySQL、再启动Spring Boot、最后确认Nginx状态同时准备了一份测试数据。再次给别人演示时全程流畅没掉链子。第一次作业最终能拿高分跟这些细节关怀有很大关系。如果你也正在为“Web第一次作业”焦头烂额请记住作业本身并不难难的是你愿不愿意沉下心走完这条完整的链路。别怕踩坑坑里踩出来的经验比老师讲十节课都值钱。这份作业做完你会发现自己不再是个只会写HTML的人而是真的碰过“工程”的门了。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

2D开发实战:从基准选取到碰撞检测与物理回滚 2026/9/30 10:26:13

2D开发实战:从基准选取到碰撞检测与物理回滚

1. “终于是2D的了”:2D技术为什么依然值得投入 1.1 标题里的梗与技术现实 “大型纪录片《终于是2D的了,就只冲这一点也要狠狠支持》持续为您播出!”这个标题在游戏玩家圈里经常出现,往往是某个系列作品从 3D 回归 2D&#xff0c…

阅读更多 →
同一个点位换了三次商品组合,销售额才涨上去~YH 2026/9/30 10:26:13

同一个点位换了三次商品组合,销售额才涨上去~YH

2026年Q1,一个运营商在写字楼点位部署了一台设备。首月销售额只有1200元,低于预期。换了三次商品组合后,销售额涨到2800元。以下是三次调整的复盘。一、第一次调整:从“全品类”到“写字楼适配”初始配置:饮料&#xf…

阅读更多 →
决策分析中的灵敏度分析:以“猜球问题”为例 2026/9/30 10:26:13

决策分析中的灵敏度分析:以“猜球问题”为例

在管理科学和统计学中,决策者常常需要在充满不确定性的环境下做出最优选择。然而,现实中的概率往往是基于历史数据或主观估计得出的。如果这些概率发生微小变化,我们原本认为的“最优方案”是否依然是最优的?这就是**灵敏度分析(Sensitivity Analysis)**的核心意义。 本…

阅读更多 →
Windows字体替换实操:用苹方和SF Pro替代微软雅黑 2026/9/30 10:26:13

Windows字体替换实操:用苹方和SF Pro替代微软雅黑

之前做 Windows 个性化定制时,最常被吐槽的就是系统默认的微软雅黑在部分屏幕上显示发虚、笔画边缘不够干净,尤其换了高分屏或者外接显示器之后,字体模糊问题会被进一步放大。后来尝试把 macOS 上的 SF Pro 和苹方字体移植到 Windows&#xf…

阅读更多 →
8GB显存硬跑35B大模型:量化卸载调参全实录 2026/9/30 10:26:06

8GB显存硬跑35B大模型:量化卸载调参全实录

少废话,先上结论:8GB显存的消费级显卡跑35B参数的大模型,不是玄学,是实打实能落地的工程方案。这篇文章是我连续两周用一张8GB显存卡折腾出来的完整实录,涉及量化、CPU卸载、上下文显存计算、Ollama调参这一整套链路。…

阅读更多 →
8GB显存跑35B大模型实测:量化与层拆分部署指南 2026/9/30 10:26:06

8GB显存跑35B大模型实测:量化与层拆分部署指南

消费级显卡跑本地大模型,这个话题我前后折腾了挺久。最近群里好几个人都在问同一个问题:8GB显存到底能不能跑35B模型?按常识想,35B参数光权重就好几十GB,8GB显存连零头都塞不下,但实测下来,还真…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉