ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Java Web少儿编程网站源码部署、二次开发与安全加固实战

Java Web少儿编程网站源码部署、二次开发与安全加固实战 简介基于Java Web的少儿编程网站源码以MVC模式组织未引入框架适合Java Web初学者、毕业设计学生作为学习与二次开发参考尤其适合在无框架环境下理解Servlet、JSP与MySQL的协作方式。项目围绕儿童编程学习场景实现用户注册登录、密码修改、账号删除管理员对用户的统一管理以及笔记创建、查看、删除反馈提交与管理员查看等完整业务闭环前端使用HTML、CSS和JavaScript后端基于Servlet与JSP并以MySQL作为数据存储。压缩包共71个文件其中Java源文件与class编译文件对应后端逻辑12个JSP页面与7个CSS负责前端展示18张PNG作为界面与流程图片外加XML配置、JAR依赖库与README说明整体仅3.69MB源码目录按src与WebContent分层结构一目了然可直接导入IDE部署。包内同时附有E-R图、流程图和目录结构图可从数据模型、业务流程、项目模块三个角度辅助理解代码逻辑目前已有67人浏览学习适合课程设计、毕业设计或Java Web入门实战练习。1. 少儿编程网站源码到手后先弄清楚 Java Web 这套东西能撑起什么拿到一份“基于 Java Web 的少儿编程网站”源码 ZIP第一次解压的人大多会去找 README但 README 通常只写部署步骤不负责回答“这套技术现在还能不能接住在线编程教学的需求”。先说结论JSP/Servlet 确实不算新但少儿编程这类项目制教学场景核心需求是课程上传、作业提交、代码判分和作品展示业务边界清晰、并发量不大正好落在 Java Web 传统架构最稳的区间里。这篇文章是写给两类人的一类是刚入行的 Java 工程师想拿真实工程练手另一类是机构内部的技术负责人想把源码改成自己机构能用的教学平台。你要的不是重新发明架构而是知道它怎么跑、改哪里、踩哪些坑。2. 源码架构先立住JSP/Servlet 三层模型与数据库设计的读码顺序2.1 少儿编程站点的功能盘面教、学、练、展四条线拿到源码别急着启动先把业务盘清楚。少儿编程网站和普通 CMS 的本质区别在于CMS 管的是“文章和用户”而少儿编程网站管的是“课程、作业、作品”这条完整的教学闭环。按常见的工程结构功能可以拆成四条线。第一条是课程线。管理端要能发布课程包括课程标题、适用年龄段、难度等级、章节内容内容里既要有图文说明又要有视频或课件附件。学生端按列表查看课程点进去看详情这部分在源码里对应的通常是 CourseServlet 和 course.jsp。第二条是作业线。老师发布作业学生在线提交。提交形式有两种一种是写一段文字或上传文件另一种是直接贴一段代码。后一种对在线判题有要求也是少儿编程网站区别于普通教育网站的关键点后面我会专门讲实现。第三条是作品线。少儿编程课上学生做出来的 Scratch 项目、Python 小游戏需要一个展示区。这个模块容易被人忽略但它恰恰是家长续费时最愿意看的东西——孩子学了一个学期到底做出了什么。源码里一般叫 works 或 portfolio包含上传、列表和点赞/评论这些基本操作。第四条是用户线。学员、教师、管理员三种角色对应不同的页面权限。学员能看到自己的作业和作品教师能批改作业管理员管课程上下架和用户禁用。这条线会牵出一个项目里最容易出问题的点权限校验是写死在每个 Servlet 里还是抽成了统一的过滤器。读码时先找有没有 Filter没有的话后续加功能就必须自己补否则任何人都能访问管理页面。把这四条线映射到源码目录上你会发现结构和业务是一一对应的。解压 ZIP 后典型的目录长这样src/ ├─ com/edu/platform/ │ ├─ controller/ # Servlet 控制器层 │ ├─ service/ # 业务逻辑层 │ ├─ dao/ # 数据访问层 │ └─ model/ # JavaBean 实体类 ├─ web/ │ ├─ WEB-INF/ │ │ ├─ web.xml │ │ └─ jsp/ # 放在 WEB-INF 下的页面无法直接 URL 访问 │ ├─ css/js/images/ │ └─ index.jsp └─ sql/ # 建库脚本和演示数据我一般会让接手的人先画一张“请求流程图”浏览器发出请求 → web.xml 找到对应的 Servlet → Servlet 调 Service → Service 调 DAO → DAO 拼 SQL 查 MySQL → 结果一层层往回传 → 最后 forward 到 JSP 渲染。这张图画完源码你就读懂了一半。2.2 读码主线从 web.xml 到 Controller、Service、DAO传统 Java Web 项目没有 Spring Boot 那种“约定优于配置”的自动化所有路由入口都集中在 web.xml 里。打开 web.xml优先看两个地方一是 servlet-mapping它告诉你每个 URL 对应哪个类二是 filter 配置它决定登录校验和编码处理是否拦截了所有请求。一段常见的 Servlet 代码大致长这样WebServlet(/course/detail) public class CourseDetailServlet extends HttpServlet { private CourseService courseService new CourseService(); Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String idStr req.getParameter(id); if (idStr null || !idStr.matches(\\d)) { resp.sendError(400, 参数不合法); return; } Course course courseService.getCourseById(Integer.parseInt(idStr)); req.setAttribute(course, course); req.getRequestDispatcher(/WEB-INF/jsp/course_detail.jsp) .forward(req, resp); } }这里参数 id 先用正则\\d校验再转 int是为了挡住 SQL 注入和 NumberFormatException。你拿到源码后可以全局搜一下getParameter看看每个参数后面有没有类似的校验。没有校验的就是安全改造时要在第 6 章清单里记一笔的地方。JSP 页面放在 WEB-INF 下有一个好处用户不能通过浏览器直接输入 URL 访问必须经过 Servlet 转发这层间接保护在少儿网站这种带学员信息的管理系统里很必要。如果源码首页 index.jsp 只是跳转入口那就符合这个设计如果所有 JSP 直接暴露在根目录后面的权限改造工作量会大很多。2.3 数据库表设计学员、课程、作业、作品四类表的关联与外键陷阱业务盘清楚后看 SQL 脚本。少儿编程网站的库表数量不多核心是四张用户表、课程表、作业表、作品表。常见的建表语句长这样CREATE TABLE sys_user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(100) NOT NULL, real_name VARCHAR(50), role TINYINT NOT NULL COMMENT 1-管理员 2-教师 3-学员, grade INT COMMENT 学员所在年级教师/管理员可空, avatar VARCHAR(255), create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE course ( id INT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(100) NOT NULL, category VARCHAR(50), difficulty TINYINT COMMENT 1-入门 2-进阶 3-高级, content TEXT, video_url VARCHAR(255), teacher_id INT, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE homework ( id INT PRIMARY KEY AUTO_INCREMENT, course_id INT NOT NULL, title VARCHAR(100) NOT NULL, description TEXT, deadline DATETIME, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE student_work ( id INT PRIMARY KEY AUTO_INCREMENT, student_id INT NOT NULL, homework_id INT NOT NULL, work_type TINYINT COMMENT 1-代码 2-Scratch作品 3-文档, content TEXT COMMENT 代码文本或作品描述, file_url VARCHAR(255), score INT, teacher_comment VARCHAR(500), submit_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这套设计里有两个容易踩的坑。第一个坑是外键约束你会发现四张表里只有逻辑关联没有FOREIGN KEY物理外键。这是老项目常见的实践——外键在数据量小的时候显得“规范”但少儿网站后续要接在线判题、要做作品批改高频写入 student_work 表物理外键会拖慢插入速度还会让删课程时被关联异常卡住。所以源码里清一色用普通索引或干脆不加索引关联关系交给 Service 层去判断。第二个坑是密码字段。VARCHAR(100) 说明源码很可能做了加盐哈希而不是明文存储。如果拿到源码发现 password 是 VARCHAR(32)那多半只是 MD5如果是 60 位左右那大概率是 BCrypt。这个区别决定了你上线前要不要重写登录逻辑我放在最后的安全章节展开。另外注意字符集统一用 utf8mb4。少儿编程网站的学生作品里经常有 Emoji、特殊符号utf8mb4 才能存得下。如果建库脚本里混着 utf8 或 gbk后面乱码问题会反复折磨你。3. 一套能落地的本地运行环境JDK/Tomcat/MySQL 怎么配才不翻车3.1 环境版本匹配JDK 8 与 Tomcat 8.5 的搭配逻辑很多新人拿到源码后第一件事是装最新的 JDK 17、Tomcat 10结果一启动全是报错就跑来问是不是源码有问题。九成情况不是源码问题而是版本匹配翻车了。传统 JSP/Servlet 项目的代码里全是javax.servlet这个包名而 Tomcat 10 开始把命名空间换成了jakarta.servlet源码导出的 WAR 包在 Tomcat 10 下连编译都过不去。所以最稳的组合是JDK 8 Tomcat 8.5 MySQL 5.7。JDK 8 还在被大量企业项目使用Tomcat 8.5 完整支持javax.servlet规范配 5.7 的 MySQL 是因为老代码里的 JDBC 驱动通常写的是com.mysql.jdbc.Driver这个类在 MySQL 5.7 的官方驱动里存在到了 MySQL 8 就改名成了com.mysql.cj.jdbc.Driver。如果你机器上已经装了 MySQL 8不一定要卸掉重装。改两处就能跑第一处是把连接字符串里的驱动类改成新类名第二处是加时区和 SSL 参数后面第 5 章我会给完整的 JDBC URL。但如果你想让源码“零修改跑通”装 5.7 还是最省事。3.2 导入 IDEA 与 Tomcat 部署三个容易漏掉的配置点现在假设你已经解压了 ZIP用 IDEA 打开项目。如果源码带 pom.xml说明这是 Maven 工程IDEA 会自动识别依赖如果没有 pom.xml 只有一堆 jar 包放在 lib 目录那就是普通 Web 工程需要手动把 lib 加入依赖。不管哪种情况配置 Tomcat 部署时有三个点特别容易漏。第一个是 Artifacts 类型必须选Web Application Exploded不要选 Archive。选错的话 IDEA 每次部署都重新打包启动慢且容易出缓存问题。第二个是 Output Layout 里必须把 lib 下的 jar 包全部拖进WEB-INF/lib。这一步漏掉的话IDEA 部署时不会打包依赖启动后浏览器一访问就报 ClassNotFoundException。第三个是 Deployment 里的 Application context 要写成/这样访问入口是http://localhost:8080/。很多源码里写了相对路径跳转如果你的 context 是/eduwebsite页面里的hrefindex.jsp会跳到/index.jsp而不是/eduwebsite/index.jsp一登录就 404这种错非常坑人。如果源码带的是 Tomcat 配置模板打开conf/server.xml找到 Connector 节点确认端口是 8080编码是 UTF-8Connector port8080 protocolHTTP/1.1 connectionTimeout20000 redirectPort8443 URIEncodingUTF-8 /URIEncodingUTF-8这一行是关键。不加的话Tomcat 8 默认用 ISO-8859-1 解析 URL 里的中文参数课程名或者搜索关键词传过去全是乱码。3.3 初始化数据库脚本导入顺序与字符集SQL 脚本通常在 ZIP 的 sql 目录下。我的习惯是先建库再建表最后灌演示数据。用命令行执行最直接mysql -uroot -p -e CREATE DATABASE kidcode DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci; mysql -uroot -p kidcode sql/01_schema.sql mysql -uroot -p kidcode sql/02_data.sql我的做法是把建表和演示数据分开跑这样哪一步失败能立即定位。01_schema.sql是建表语句02_data.sql是初始化数据。如果脚本里没有分文件那就按 SQL 文件里的注释段落手动分隔执行。导入时有两个参数要盯紧。第一个是--default-character-setutf8mb4特别是 Windows 的 CMD 下默认编码可能是 gbk直接导入会把中文注释和演示数据搞乱。完整写法是在 mysql 命令里加上这个参数。第二个是表名大小写敏感问题Linux 下 MySQL 默认区分大小写老源码里如果查询语句写Course而建表语句写course就会报 table doesnt exist。最快的修法是在/etc/my.cnf的 mysqld 段加一行[mysqld] lower_case_table_names1加完重启 MySQL 再重新导入。Windows 下默认就是 1所以很多人在 Windows 上跑得好好的一部署到 Linux 服务器就翻车都是这个参数闹的。3.4 启动自检登录、首页、后台管理三个入口怎么验证环境配好、数据导入后用浏览器访问可能有缓存干扰我一般直接用 curl 做接口自检能省不少时间curl -I http://localhost:8080/ curl -I http://localhost:8080/login curl -I http://localhost:8080/admin/index逐个看 HTTP 状态码。首页返回 200 说明 Tomcat 部署成功/login 返回 200 说明登录页可达/admin/index 如果返回 302 跳转说明权限拦截器在工作。如果这三个入口都正常再用浏览器登录一遍完整流程学生账号登录 → 查看课程 → 提交作业 → 查看作品区。这一步要特别留意 Tomcat 命令行窗口有没有输出中文乱码。出现乱码是控制台编码问题不影响业务不用管真正要关注的是SEVERE级别的异常堆栈。如果日志里出现Unable to load class或者Communications link failure那就是依赖没打包或者数据库连接参数不对按第 5 章的排查清单处理。4. 二次开发路线课程管理、在线判题与 Scratch 作品区怎么改4.1 课程管理模块富文本编辑器与文件上传的替换方案源码里课程内容的录入方式决定了你后期维护成本。老项目常见的做法是页面里放一个textarea课程介绍以纯文本或简单 HTML 保存。能跑但老师录入课程时体验很差。我的改法是引入富文本编辑器前端换成 TinyMCE 或 wangEditor后端不动只接收 HTML 字符串。如果你对前后端联调还不熟这个改造的工作量集中在两处。第一处在编辑页把 textarea 换成编辑器初始化脚本第二处在展示页用c:out标签输出内容时注意转义问题。课程内容是管理端录入的属于半信任内容HTML 标签可以放行但script标签必须过滤。用 wangEditor 时它自带白名单过滤如果用的是老版本的 UEditor就需要额外做服务端过滤否则保存进去一段带 script 的课程介绍每个学生打开页面都会中招。文件上传是课程模块另一个常见改造点。源码里如果用的是commons-fileupload组件注意web.xml里有没有配置上传大小限制multipart-config max-file-size20971520/max-file-size max-request-size41943040/max-request-size file-size-threshold1048576/file-size-threshold /multipart-config这三项分别对应单个文件 20MB、整请求 40MB、超过 1MB 先落临时文件。视频课件经常超过 20MB你可以酌情调大但一定要设上限否则学生批量上传垃圾文件会把磁盘写满。我建议视频不直接传服务器而是走 OSS 或者对象存储数据库只存 URL这样网站源码放哪台机器都不怕磁盘爆炸。4.2 在线判题模块提交、编译、沙盒执行的实现与安全边界少儿编程网站在线判题是最高价值也最危险的模块。业务上学生提交一段 Java 或 Python 代码系统要在服务器上把它跑起来给个运行结果。技术实现上Java 代码可以用javax.tools.JavaCompiler编译再通过Runtime启动子进程运行这是老源码里最常见也最朴素的实现路径。看一段源码里典型的判题逻辑public String compileAndRun(String sourceCode) throws IOException { File sourceFile new File(/tmp/judge/StudentMain.java); FileOutputStream fos new FileOutputStream(sourceFile); fos.write(sourceCode.getBytes(StandardCharsets.UTF_8)); fos.close(); JavaCompiler compiler ToolProvider.getSystemJavaCompiler(); int compileResult compiler.run(null, null, null, sourceFile.getPath()); if (compileResult ! 0) { return 编译失败请检查语法错误; } Process process Runtime.getRuntime().exec( new String[]{java, -cp, /tmp/judge, -Xmx64m, StudentMain}); process.waitFor(5, TimeUnit.SECONDS); // 超时 5 秒 if (!process.isAlive()) { return 运行超时; } return readProcessOutput(process.getInputStream()); }逻辑不复杂但有两处必须说明。第一处是超时控制waitFor(5, TimeUnit.SECONDS)规定进程 5 秒内必须结束防止学生代码里有死循环把服务器 CPU 跑满。第二处是-Xmx64m限制子进程最多用 64MB 内存。这两个参数是判题模块的保命底线没有它们一个while(true){}就能让网站卡死。但我要直接说把学生代码放在服务器上裸跑本身就是高风险操作。学生提交的代码如果有文件删除、端口扫描、读取系统环境变量的操作Runtime.exec完全没有拦截能力。如果是给内部学员用、信任度较高这套逻辑够用如果要对外开放就必须加一层操作系统级的沙盒比如用 Docker 容器跑判题进程并且容器里不挂载任何宿主机目录。第 4 章提到这个模块不是为了让你立刻重写而是提醒你读源码时先确认三个问题判题进程有没有超时、有没有内存限制、能不能限制文件系统权限。三个答案都是“否”的话这个模块只能用于演示不能上线。4.3 Scratch 作品区上传目录映射与访问鉴权Scratch 作品和普通图片上传不一样。Scratch 3.0 作品是一个.sb3压缩包里面是项目 JSON 和资源文件浏览器端可以解析但无法直接预览。机构网站上常见做法是学生上传 .sb3 文件后端解压拿到项目缩略图图片展示在作品列表页点击后跳转到播放页用 Scratch 官方组件加载。源码里的作品区如果只是普通文件上传那你要补两个点。第一点是上传目录的隔离作品文件不能和课程附件混在一个目录里否则权限没法区分。第二点是访问路径的映射Tomcat 默认只能访问 webapps 目录下的文件作品传到服务器某个非 webapps 路径后浏览器 URL 是打不开的。常见的改法是在conf/server.xml的 Host 里加虚拟目录映射Context path/works docBase/data/kidcode_works reloadablefalse /这里/works是浏览器访问的虚拟路径/data/kidcode_works是磁盘上的真实存储目录。配完之后上传的文件存在/data/kidcode_works/xxx.sb3浏览器通过http://localhost:8080/works/xxx.sb3就能访问。但这里有个安全坑CPU 直接暴露所有作品文件学生可以猜到别人的文件名批量下载。正确做法是存文件名时用 UUID 重命名原始文件名只保存在数据库里展示时通过一个 DownloadServlet 做权限校验后转发。文件名改成无规律的 UUID 串你基本就绕过了这个坑。5. 常见问题排查从 404/500 到乱码和内存溢出的踩坑记录5.1 启动即 ClassNotFoundWeb 应用未打齐依赖现象Tomcat 启动没报错浏览器访问首页 HTTP 500控制台抛出ClassNotFoundException: com.mysql.jdbc.Driver或NoClassDefFoundError。原因IDEA 的 Artifacts 输出目录里WEB-INF/lib缺少 Third-party jar 包。很多人依赖在 Project Structure 里能看见但部署时没打进 Artifact。这个坑在“非 Maven 工程”里尤其高发。解决打开File → Project Structure → Artifacts选中你的 Web 工程在Output Layout标签里把右侧Available Elements下的依赖 jar 全部右键Put into /WEB-INF/lib然后重新构建并重启。如果是 Maven 工程执行一次mvn clean package后再让 IDEA 重新加载 Artifact。5.2 JSP 页面中文乱码三处编码不一致现象页面菜单是中文浏览器显示成“?????????”或“测试”这类乱码。原因请求参数、JSP 页面、数据库连接三处编码没统一。最常见的是 JSP 文件头声明的是ISO-8859-1而浏览器按 UTF-8 解析反过来也常见。解决第一处所有 JSP 文件第一行统一为% page contentTypetext/html; charsetUTF-8 pageEncodingUTF-8 %。第二处在 web.xml 里加一个编码过滤器强制所有请求和响应走 UTF-8filter filter-nameencodingFilter/filter-name filter-classorg.apache.catalina.filters.SetCharacterEncodingFilter/filter-class init-param param-nameencoding/param-name param-valueUTF-8/param-value /init-param /filter filter-mapping filter-nameencodingFilter/filter-name url-pattern/*/url-pattern /filter-mapping第三处数据库连接 URL 里加上characterEncodingutf8。三处统一后乱码基本消失。有极少数情况是项目源码里硬编码了 new String(bytes, iso-8859-1)这种要全局替换属于导演故意埋雷只能逐个文件排查。5.3 数据库连接失败驱动类与时区参数现象启动后第一个请求数据库的页面报Communications link failure或者Unknown database kidcode。原因两种。一种是驱动不匹配Java 6 的com.mysql.jdbc.Driver在较新的 MySQL 驱动里已删除换成com.mysql.cj.jdbc.Driver才行。另一种是 MySQL 8 对连接串有严格校验jdbc:mysql://localhost:3306/kidcode这种写法会缺少时区参数导致连接失败。解决把db.properties或 JDBC URL 改完整jdbc:mysql://localhost:3306/kidcode?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8allowPublicKeyRetrievaltrueallowPublicKeyRetrievaltrue是 MySQL 8 用 caching_sha2_password 认证时必需的不加会报 Public Key Retrieval is not allowed。serverTimezoneAsia/Shanghai解决时间字段差 8 小时的问题。如果不想改代码就在 MySQL 配置文件里加default-time-zone08:00然后重启。5.4 上传后访问不到图片或作品虚拟目录映射漏了现象文件上传提示成功数据库里有路径记录但浏览器打开图片 URL 返回 404。原因文件被存到 Tomcat 应用目录之外而 URL 直接在 Tomcat 默认 webapps 下找文件找不到当然 404。没有四节说的Context docBase映射路径自然指向不存在。解决检查server.xml里有没有配置虚拟目录。没有的话两个方案一是按 4.3 节加上 Context 映射二是把上传物理路径改到 webapps 的 uploads 目录下。方案二在重部署或清理 Tomcat 时会丢文件服务器重启也要重新丢一次所以虚拟目录才是正解。5.5 Tomcat 内存溢出JVM 参数与永久代设置现象运行一段时间后控制台报java.lang.OutOfMemoryError: PermGen space或者Java heap space随后网站无响应。原因老版本 JDK 8 的 PermGen 空间不够用。JSP 页面多、每次修改 JSP 后 Tomcat 会重新编译类加载器不断创建类PermGen 默认只有几十 MB很容易打满。解决修改 Tomcat 的bin/catalina.sh或setenv.sh加上 JVM 参数JAVA_OPTS-Xms512m -Xmx1024m -XX:MaxPermSize256mJDK 8 之后 PermGen 被 Metaspace 取代参数改为-XX:MaxMetaspaceSize256m。如果是已经频繁 OOM 的生产环境还要在 catalina.sh 里加上-XX:HeapDumpOnOutOfMemoryError和-XX:HeapDumpPath/data/logs这样下次再挂能留一个堆转储文件用 MAT 打开就能看到底是哪个类占用内存。6. 上线前的安全验收与改造方向把源码从课堂 demo 变成可用系统源码跑通只是第一步真把它放上公网前我建议你按下面这个清单过一遍。这套清单是我当年把一个课程管理系统改上线时踩出来的比任何 README 都管用。第一是密码存储。登录功能如果用的是 MD5 明文哈希立刻改掉。MD5 撞库成本太低少儿网站里存的是学员和家长信息被拖库的后果不只是丢账号还有法律责任。改造方案是引入 BCrypt 加盐哈希Spring Security 的BCryptPasswordEncoder可以直接用几十行代码替换的事。改完之后老密码全部作废让用户走一遍“忘记密码”流程。第二是 SQL 注入。全局搜 DAO 层代码看有没有用字符串拼接 SQLString sql SELECT * FROM sys_user WHERE username name ;只要出现这种写法百分百可以注入。统一改成 PreparedStatement 占位符PreparedStatement ps conn.prepareStatement( SELECT * FROM sys_user WHERE username?); ps.setString(1, name);少儿编程网站的学员数据量不大改 PreparedStatement 对性能无感但它能把一类攻击直接堵死。第三是上传安全。4.3 节提到文件名改成 UUID这里再补一条必须校验文件扩展名白名单。只允许.jpg .png .sb3 .zip .pdf这些其他一律拒绝。有的老代码只看 Content-Type 判断文件类型Content-Type 是客户端可伪造的不能信。第四是权限校验。全局搜 Servlet 里的WebServlet(/admin)确认有没有对应的过滤器拦截/admin/*。如果没有管理端所有接口全部暴露这是比 SQL 注入还严重的洞。补一个最简单的过滤器检查 session 里有没有 admin 标记没有就重定向到登录页。最后一个改造方向是技术栈升级。这套 JSP/Servlet 源码短期能跑但长远看维护成本在上升。我的建议不是推翻重写而是把你二次开发最多的模块提取出来用 Spring Boot 重写保持数据库不变、业务不变老模块继续跑。比如在线判题单独拆成一个服务课程管理先留在老工程。渐进式重构比一次性推倒重来稳得多既保住了源码里已经验证过的业务逻辑也让你逐步脱离 JSP 的束缚。这套源码是我见过比较典型的 Java Web 教学项目结构不花哨但该有的模块都在。把它从头到尾读懂、跑通、改过一遍之后你对传统 Java Web 的理解会上一个台阶往后去看 Spring Boot、Spring Cloud你会发现它们本质上就是把 web.xml、Filter、Servlet 这些概念做成了自动化配置。技术框架一直在换底层那套请求-处理-响应的模型二十年没变过。我自己最开始接触这类源码时也走了不少弯路最深的教训就是别急着敲代码先把 web.xml 和数据库脚本啃明白后面能省出好几倍的返工时间。希望这篇文章能帮你在同样的路上少踩几个坑。本文还有配套的精品资源点击获取
返回列表