news 2026/9/30 9:34:22

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从零到一完成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 3(CDN方式)
  • 后端: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 8,Spring 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: GMT+8 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忘了加characterEncoding=utf8参数,导致数据库读写都是默认编码。修改连接字符串:

jdbc:mysql://localhost:3306/blog?useUnicode=true&characterEncoding=utf8

这行加上之后,中文显示就正常了。这个坑特别经典,十个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注入。我随手在自己的博客站点输入框里填了一段测试脚本:

<script>alert('haha')</script>

点击提交后,弹窗真的出现了。这意味着我的网站存在存储型XSS,任何用户都能通过评论框把恶意脚本存进数据库,其他用户访问时脚本就会执行。我瞬间有点后怕——如果这不是作业,而是一个真实网站,后果不堪设想。

我赶紧翻代码,发现原因是没有对用户输入做过滤,也没有在输出时转义。修复办法其实很简单:

  • 后端加一个HtmlUtils.htmlEscape()对文本内容转义。
  • 前端Vue自动转义,但要注意使用v-html会绕过,所以我改成了纯文本插值。

测试之后弹窗不再出现,我才明白,一个Web应用“能跑”和“安全”之间隔着整整一个Web安全的知识领域。

4.2 第一次接触CTF的Web题

修完漏洞后,我对Web安全产生了浓厚兴趣,开始在B站和社区找资料,第一次听说了CTF(Capture 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的人,而是真的碰过“工程”的门了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/30 9:34:22

LLM游戏主循环权限分配:工具调用与合法动作掩码实战

1. 从“收权”到“放权”&#xff1a;LLM 进入游戏主循环的底层逻辑 把大语言模型塞进游戏里&#xff0c;这件事在最近一年里从“技术演示”迅速变成了“正经玩法设计”。但真正动手做过的人都知道&#xff0c;最难的从来不是调用 API&#xff0c;而是 权限分配 ——模型到底…

作者头像 李华
网站建设 2026/9/30 9:34:03

告别手写Agent循环:Strands Agents Harness SDK生产级实战指南

1. 为什么“手写 Agent 循环”正在变成一种负债如果你最近半年在折腾 AI Agent&#xff0c;大概率写过类似这样的东西&#xff1a;一个while True循环&#xff0c;里面塞着 LLM 调用、工具解析、结果回填、终止判断&#xff0c;再配上一堆if/else处理各种边界情况。第一版跑通的…

作者头像 李华
网站建设 2026/9/30 9:33:39

游戏引擎架构设计:从团队分工到C++底层实现的核心决策

1. 从零开始理解游戏引擎架构&#xff1a;为什么团队分工决定了代码长什么样 很多人第一次接触“游戏引擎架构”这个词&#xff0c;脑子里浮现的是一堆类继承图、渲染管线、内存分配器。但我在实际带项目和跟同行交流的过程中发现一个更前置的问题&#xff1a; 引擎架构从来不…

作者头像 李华
网站建设 2026/9/30 9:33:09

Vue文件下载实战:Excel/图片/文本的Blob构造与编码避坑指南

1. 项目概述&#xff1a;为什么在 Vue 项目里“下载文件”这件事远比 console.log(hello) 复杂得多 你写完一个数据表格&#xff0c;用户点一下“导出 Excel”&#xff0c;页面却卡住两秒、弹出空白文件、或者下载下来的 Excel 打不开——这种场景&#xff0c;我在过去三年带的…

作者头像 李华
网站建设 2026/9/30 9:29:28

Otter.ai、Rows、Zapier:职场人的AI时间杠杆三件套

1. 这三个工具不是“又一个AI助手”&#xff0c;而是时间杠杆的物理支点你有没有过这种体验&#xff1a;早上打开电脑&#xff0c;邮箱里躺着27封待回复的客户邮件&#xff0c;会议纪要还没整理&#xff0c;PPT初稿卡在第三页动弹不得&#xff0c;而日历上已经标红了下午三点的…

作者头像 李华