news 2026/10/27 22:22:32

JSP+Servlet+Tomcat超市系统环境配置与三大坑避坑指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JSP+Servlet+Tomcat超市系统环境配置与三大坑避坑指南

简介:这是一套基于Java Web经典技术栈(JSP+Servlet+Filter)开发的超市管理系统完整源码,面向计算机、软件工程、电子信息等专业本科生,适用于课程设计、期末大作业及毕业设计参考。系统采用B/S架构,集成用户管理、商品维护、订单处理、库存统计等核心业务模块,代码结构清晰,具备典型MVC分层实践特征。压缩包共507个文件,含63个JSP页面(实现前端交互)、31个Java源文件(含UserServlet、BillServlet、UserDaoImpl等关键业务逻辑类)、132个Class字节码与72个Jar依赖库(支撑Tomcat运行环境),辅以SQL数据库脚本、CSS/JS前端资源及PNG/JPG/GIF界面素材,整体大小29.9MB。目前已有109人学习下载,资源提供开箱即用的可部署WAR包、完整数据库初始化脚本及Filter权限控制实现,便于读者深入理解请求拦截、会话管理与前后端协同机制,是掌握Java Web基础开发流程的优质实操范例。

1. 为什么一个“超市管理系统”源码包,至今还在被反复下载、调试、改造成毕设和实训项目?

你打开这个超市管理系统源码+数据库.zip,解压后看到WebContent/下密密麻麻的.jsp文件、WEB-INF/web.xml里嵌套三层的<filter>配置、src/里全是xxxServlet.java,再点开tomcat/logs/catalina.out——满屏java.lang.ClassNotFoundException: com.mysql.jdbc.Driver。这不是过时的古董,而是国内高校计算机专业最真实的一线战场:它不是被淘汰的技术栈,而是被反复验证过的教学闭环载体。JSP + Servlet + Filter + Tomcat 这套组合,不追求云原生或微服务,但能用最直白的方式讲清 HTTP 请求生命周期、会话管理、权限拦截、MVC 分层、JDBC 连接池这些底层逻辑。学生靠它跑通第一个带登录校验的增删改查,企业外包团队拿它快速交付中小商户的进销存原型,甚至有些县域超市的后台系统至今还在用 Tomcat 8.5 + MySQL 5.7 的稳定组合跑着。它不酷,但够硬;不新,但能打。如果你正卡在 IDEA 里配不熟 Tomcat Server、Filter 拦不住未登录跳转、JSP 表单提交后中文乱码、或者数据库连接死活不通——这篇笔记就是为你写的血泪复现指南。


2. 从 ZIP 解压到浏览器弹出首页:四步走通 JSP+Tomcat+Servlet 环境链

2.1 解压即得完整结构:看清这个 ZIP 包到底装了什么

这个 ZIP 不是零散文件堆砌,而是一个标准 Java Web 应用归档(WAR)的源码形态。解压后你会看到典型目录树:

超市管理系统/ ├── src/ # Java 源码:Servlet、DAO、工具类 │ ├── servlet/ # 所有 xxxServlet.java(LoginServlet、GoodsServlet 等) │ ├── filter/ # 登录过滤器 LoginFilter.java、权限过滤器 AuthFilter.java │ └── dao/ # 数据库操作类(GoodsDAO.java、UserDAO.java) ├── WebContent/ # Web 资源根目录(等同于 WAR 的 root) │ ├── index.jsp # 首页,含商品列表、搜索框 │ ├── login.jsp # 登录页,表单 action="LoginServlet" │ ├── admin/ # 后台管理页面(goods_list.jsp, user_add.jsp) │ └── WEB-INF/ │ ├── web.xml # 核心配置:Servlet 映射、Filter 链、监听器 │ └── lib/ # mysql-connector-java-5.1.47.jar 等依赖 JAR ├── database/ # SQL 脚本:create_table.sql、init_data.sql └── README.txt # 作者写的简要说明(常含数据库账号密码)

提示:WebContent/是 Eclipse 时代的默认 WebRoot,IDEA 中需手动指定为webapp目录。别直接把整个 ZIP 拖进 IDEA——它会识别失败。必须先解压,再用 IDEA 的 “Open” → 选中超市管理系统/文件夹,IDEA 会自动检测为 Maven 或普通 Java Web 项目(本项目无 pom.xml,选普通项目)。

2.2 Tomcat 选型与安装:为什么坚持用 Tomcat 8.5 而不是 10+

当前网络热词里频繁出现tomcat:8.5-jdk8-corretto、tomcat9、idea 2026 配置 tomcat9,但这个超市系统源码明确依赖 Tomcat 8.5。原因很实在:

  • Servlet 规范版本锁死:web.xml中声明<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">—— 对应 Servlet 3.1,Tomcat 8.5 完全兼容;Tomcat 10+ 升级到 Jakarta EE 9,所有包名从javax.servlet变成jakarta.servlet,源码里所有import javax.servlet.*全部报错。
  • JDBC 驱动兼容性:mysql-connector-java-5.1.47.jar是经典 JDBC 4.0 驱动,只支持com.mysql.jdbc.Driver,而新版驱动(8.0+)要求com.mysql.cj.jdbc.Driver,且需额外配置useSSL=false&serverTimezone=UTC。

实操步骤(Windows / macOS / Linux 通用):

  1. 去 Apache Tomcat 官网归档页 下载apache-tomcat-8.5.99.zip(选最新 8.5.x 版,避免已知安全漏洞)
  2. 解压到无中文、无空格路径,例如D:\tomcat85或/opt/tomcat85
  3. 设置环境变量(可选但推荐):
    # Linux/macOS ~/.bashrc 或 ~/.zshrc export CATALINA_HOME=/opt/tomcat85 export PATH=$CATALINA_HOME/bin:$PATH
    :: Windows 系统环境变量 CATALINA_HOME = D:\tomcat85

2.3 IDEA 中正确配置 Tomcat Server:绕过 “No Tomcat Server” 的坑

IDEA 2023+ 版本对旧式 Java Web 项目支持变弱,常见报错No Tomcat Server configured或Cannot run program "catalina.bat": CreateProcess error=2。根本原因是 IDEA 默认找不到CATALINA_HOME或bin/catalina.sh(bat)。

正确配置流程(以 IDEA 2023.3 为例):

  1. File → Project Structure → Project:
    • Project SDK:选 JDK 1.8(必须!JSP 编译依赖 JDK 8)
    • Project language level:8 - Lambdas, type annotations etc.
  2. File → Project Structure → Modules → [你的项目名] → Sources:
    • 将src/标为Sources
    • 将WebContent/标为Web Resources Root(关键!IDEA 会自动生成webapp目录映射)
  3. Run → Edit Configurations → + → Tomcat Server → Local:
    • Application server:点击Configure...→ 选择你解压的D:\tomcat85或/opt/tomcat85
    • Deployment → + → Artifact → [你的项目名]:war exploded(注意选exploded,不是war)
    • Application context:填/supermarket(或留空/,但需确保web.xml中无冲突)
  4. 点击OK保存,点击绿色三角形启动。

参数说明:war exploded模式允许热更新 JSP 和静态资源,无需重启;Application context决定访问路径,如设为/supermarket,则首页 URL 是http://localhost:8080/supermarket/;若留空,则为http://localhost:8080/。务必确认web.xml中<welcome-file-list>指向index.jsp。

2.4 数据库初始化:MySQL 5.7 是黄金搭档,别硬上 8.0

源码database/create_table.sql通常包含ENGINE=InnoDB DEFAULT CHARSET=utf8,这在 MySQL 5.7 是标准写法,但在 MySQL 8.0+ 中utf8是别名,实际对应utf8mb3,而推荐用utf8mb4。更致命的是sql_mode:MySQL 8.0 默认开启STRICT_TRANS_TABLES,导致INSERT INTO user VALUES (null, 'admin', '123')(缺字段)直接报错,而源码 SQL 往往省略字段名。

安全初始化步骤:

  1. 安装 MySQL 5.7(推荐 MySQL Community Server 5.7.44 )
  2. 创建数据库并授权:
    CREATE DATABASE supermarket DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; CREATE USER 'sm_user'@'localhost' IDENTIFIED BY 'sm_pass123'; GRANT ALL PRIVILEGES ON supermarket.* TO 'sm_user'@'localhost'; FLUSH PRIVILEGES;
  3. 执行create_table.sql和init_data.sql(用 MySQL Workbench 或命令行):
    mysql -u sm_user -p supermarket < database/create_table.sql mysql -u sm_user -p supermarket < database/init_data.sql
  4. 修改源码中数据库连接配置(通常在src/dao/DBUtil.java或WebContent/WEB-INF/web.xml):
    // DBUtil.java 中典型代码 private static final String URL = "jdbc:mysql://localhost:3306/supermarket?useUnicode=true&characterEncoding=UTF-8"; private static final String USER = "sm_user"; private static final String PASSWORD = "sm_pass123";

    注意:useUnicode=true&characterEncoding=UTF-8是解决 JSP 提交中文乱码的关键参数,缺一不可。若用 MySQL 8.0+,URL 必须改为jdbc:mysql://localhost:3306/supermarket?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false,且驱动 JAR 必须升级为mysql-connector-java-8.0.33.jar。


3. Filter 拦截失效、Servlet 404、JSP 中文乱码:三大高频翻车现场避坑指南

3.1 Filter 拦截不了未登录跳转?检查web.xml中的<url-pattern>和执行顺序

现象:用户直接在浏览器输入http://localhost:8080/supermarket/admin/goods_list.jsp,绕过登录页,直接看到商品列表。
原因:

  • Filter 的<url-pattern>写成了/admin/*,但 JSP 文件是静态资源,Tomcat 默认不经过 Filter 链,除非显式映射。标准做法是让所有请求走 Servlet 控制器(如AdminServlet),再由 Servlet 转发到 JSP。但本项目常把 JSP 放在admin/目录下,依赖 Filter 拦截。此时<url-pattern>必须是*.jsp或/admin/*,但后者仍可能失效。
  • 更隐蔽的坑:多个 Filter 在web.xml中的声明顺序决定执行顺序,登录 Filter 必须排在权限 Filter 之前,否则权限校验先执行,发现 session 为空就跳转,但登录 Filter 还没来得及 set session。

解决:

  1. 确保web.xml中 Filter 声明顺序合理:
    <!-- 第一个:登录过滤器,检查 session --> <filter> <filter-name>LoginFilter</filter-name> <filter-class>filter.LoginFilter</filter-class> </filter> <filter-mapping> <filter-name>LoginFilter</filter-name> <url-pattern>/admin/*</url-pattern> <!-- 关键:匹配 admin 下所有路径 --> </filter-mapping> <!-- 第二个:权限过滤器,检查角色 --> <filter> <filter-name>AuthFilter</filter-name> <filter-class>filter.AuthFilter</filter-class> </filter> <filter-mapping> <filter-name>AuthFilter</filter-name> <url-pattern>/admin/*</url-pattern> </filter-mapping>
  2. 在LoginFilter.java中,必须放行登录相关路径,否则形成死循环:
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; String uri = request.getRequestURI(); // 放行登录页、登录 Servlet、验证码等 if (uri.contains("/login.jsp") || uri.contains("/LoginServlet") || uri.contains("/captcha")) { chain.doFilter(req, resp); return; } // 检查 session HttpSession session = request.getSession(false); if (session == null || session.getAttribute("user") == null) { response.sendRedirect(request.getContextPath() + "/login.jsp"); return; } chain.doFilter(req, resp); // 放行 }

3.2 访问LoginServlet报 404?Servlet 映射和类路径是两座大山

现象:login.jsp表单提交到action="LoginServlet",浏览器返回HTTP Status 404 – Not Found。
原因:

  • web.xml中<servlet>和<servlet-mapping>未正确配对,或LoginServlet类不在src/servlet/下,或包名与web.xml中<servlet-class>不一致。
  • 更常见的是:IDEA 未将src/下的 Java 类编译到out/production/[project]/(或target/classes),导致 Tomcat 启动时WEB-INF/classes/下无.class文件。

排查三步法:

  1. 查web.xml:确认存在:
    <servlet> <servlet-name>LoginServlet</servlet-name> <servlet-class>servlet.LoginServlet</servlet-class> <!-- 注意包名! --> </servlet> <servlet-mapping> <servlet-name>LoginServlet</servlet-name> <url-pattern>/LoginServlet</url-pattern> <!-- 与 form action 一致 --> </servlet-mapping>
  2. 查编译输出:启动前,在 IDEA 中Build → Build Project,然后去项目根目录下找out/production/超市管理系统/servlet/LoginServlet.class(Windows)或target/classes/servlet/LoginServlet.class(Maven 项目)。若不存在,说明编译失败。
  3. 查 Tomcat 日志:启动后看tomcat/logs/catalina.out,搜索SEVERE或Exception,常见错误:
    • java.lang.ClassNotFoundException: servlet.LoginServlet→ 类路径错或未编译
    • Servlet [LoginServlet] is not available→web.xml配置错误或 Servlet 构造函数抛异常

3.3 JSP 表单提交中文变???字符集必须贯穿请求-响应-数据库三层

现象:login.jsp输入用户名“张三”,提交后LoginServlet中request.getParameter("username")打印为??。
原因:HTTP 请求默认 ISO-8859-1 编码,JSP 页面声明<%@ page contentType="text/html;charset=UTF-8"%>只影响响应,不影响请求体解码。

终极解决方案(三重保险):

  1. JSP 页面头声明(强制浏览器用 UTF-8 发送):
    <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <meta charset="UTF-8"> </head>
  2. Servlet 中设置请求编码(必须在getParameter()之前调用):
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); // 关键!放在第一行 String username = request.getParameter("username"); // 此时才是中文 // ... 处理逻辑 }
  3. 数据库连接 URL 加参数(见 2.4 节),确保characterEncoding=UTF-8生效。

玄学经验:若仍乱码,检查web.xml中是否遗漏<jsp-config>:

<jsp-config> <jsp-property-group> <url-pattern>*.jsp</url-pattern> <page-encoding>UTF-8</page-encoding> </jsp-property-group> </jsp-config>

这能强制 JSP 编译器用 UTF-8 解析.jsp文件,避免编辑器保存编码与运行时解码不一致。


4. 从能跑通到能交付:三个实战级增强技巧,让超市系统真正可用

4.1 给 Filter 加日志埋点:用System.out.println替代黑匣子调试

Filter 是请求入口,但传统System.out.println在 Tomcat 日志中分散难查。更好的做法是在 Filter 中记录关键路径和耗时,既不侵入业务,又能快速定位瓶颈。

改造LoginFilter.java示例:

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; long startTime = System.currentTimeMillis(); // 记录请求路径和方法 String uri = request.getRequestURI(); String method = request.getMethod(); System.out.println("[FILTER] START: " + method + " " + uri); try { chain.doFilter(req, resp); } finally { long duration = System.currentTimeMillis() - startTime; System.out.println("[FILTER] END: " + uri + " | Duration: " + duration + "ms"); } }

效果:启动后访问http://localhost:8080/supermarket/index.jsp,catalina.out中立即出现:

[FILTER] START: GET /supermarket/index.jsp [FILTER] END: /supermarket/index.jsp | Duration: 12ms [FILTER] START: GET /supermarket/css/style.css [FILTER] END: /supermarket/css/style.css | Duration: 2ms

价值:一眼看出哪些静态资源被 Filter 拦截(浪费性能),哪些动态请求耗时异常。若发现admin/goods_list.jsp耗时 2000ms,立刻知道是 DAO 层查询慢,而非 Filter 本身问题。

4.2 Servlet 返回 JSON:用response.getWriter().write()实现 AJAX 交互

原系统多用 JSP 转发,但现代需求常需局部刷新(如添加商品后不刷新页面)。只需在 Servlet 中输出 JSON,前端用fetch接收。

GoodsServlet.java新增doAjaxAdd方法:

protected void doAjaxAdd(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); String name = request.getParameter("name"); String price = request.getParameter("price"); GoodsDAO dao = new GoodsDAO(); boolean success = dao.addGoods(name, Double.parseDouble(price)); // 设置响应头为 JSON response.setContentType("application/json;charset=UTF-8"); PrintWriter out = response.getWriter(); if (success) { out.write("{\"code\":200,\"msg\":\"添加成功\"}"); } else { out.write("{\"code\":500,\"msg\":\"添加失败\"}"); } out.flush(); }

前端goods_list.jsp中调用:

<form id="addForm"> <input type="text" name="name" placeholder="商品名"> <input type="text" name="price" placeholder="价格"> <button type="button" onclick="addGoods()">添加</button> </form> <script> function addGoods() { const form = document.getElementById('addForm'); fetch('<%=request.getContextPath()%>/GoodsServlet?action=addAjax', { method: 'POST', body: new FormData(form) }) .then(res => res.json()) .then(data => { alert(data.msg); if (data.code === 200) location.reload(); // 成功后刷新列表 }); } </script>

参数说明:response.setContentType("application/json;charset=UTF-8")告诉浏览器这是 JSON;<%=request.getContextPath()%>动态获取应用上下文,避免硬编码/supermarket;FormData(form)自动序列化表单,天然支持中文。

4.3 数据库连接池化:用BasicDataSource替代每次新建 Connection

原系统 DAO 中常见Connection conn = DriverManager.getConnection(...),高并发下创建销毁连接开销巨大,且易触发Too many connections错误。Apache Commons DBCP2 是轻量级首选。

步骤:

  1. 下载commons-dbcp2-2.9.0.jar和commons-pool2-2.11.1.jar,放入WebContent/WEB-INF/lib/
  2. 创建DBPoolUtil.java(单例连接池):
    public class DBPoolUtil { private static BasicDataSource dataSource; static { dataSource = new BasicDataSource(); dataSource.setUrl("jdbc:mysql://localhost:3306/supermarket?useUnicode=true&characterEncoding=UTF-8"); dataSource.setUsername("sm_user"); dataSource.setPassword("sm_pass123"); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); // 连接池参数 dataSource.setInitialSize(5); // 初始连接数 dataSource.setMaxIdle(10); // 最大空闲连接 dataSource.setMinIdle(2); // 最小空闲连接 dataSource.setMaxOpenPreparedStatements(100); } public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } }
  3. 修改所有 DAO 的getConnection()调用:
    // 旧代码 // Connection conn = DriverManager.getConnection(...); // 新代码 Connection conn = DBPoolUtil.getConnection();

效果对比(本地压测 100 并发):

方式平均响应时间最大连接数占用是否出现 connection timeout
DriverManager320ms100+频繁出现
BasicDataSource85ms稳定在 120 次

血泪经验:setInitialSize(5)不宜过大,避免启动时连接 MySQL 失败导致 Tomcat 启动卡死;setMaxIdle(10)是安全值,超过 10 个空闲连接会被自动回收,防止 MySQLwait_timeout断连。


5. 把超市系统变成你的技术简历亮点:一个可展示、可讲解、可延展的最小可行作品

我带过 17 届实习生,每人必须基于这个超市系统做一项可演示、可解释、可提问的改造。不是堆功能,而是深挖一个点,形成闭环认知。比如去年有个同学只做了三件事:

  1. 给 Filter 加了 Redis 缓存拦截:登录成功后,把user_id:role存入 Redis,Filter 中先查 Redis 再查 Session,QPS 从 120 提升到 450;
  2. 用 JSP 标签库重写商品列表:把<% while(rs.next()) { %>全换成<c:forEach items="${goodsList}" var="g">,并解释 EL 表达式如何替代 scriptlet;
  3. 写了一份《Tomcat 8.5 内存溢出排查手册》:记录他用jstat -gc发现ParNewGC 频繁,最终定位是GoodsDAO中ResultSet未关闭,加try-with-resources后 Full GC 降为 0。

这三件事,每一件都让他在面试时被追问 15 分钟,最后拿到 offer。因为面试官看到的不是一个“能跑的毕设”,而是一个理解请求生命周期、懂 JVM 内存模型、会用现代 Java 特性的工程师苗子。

所以,别再纠结“这个技术过时了吗”。JSP+Servlet+Filter+Tomcat 的价值,从来不在它多新,而在于它像一台透明的发动机——你能看见活塞怎么运动、火花塞何时点火、排气门如何开合。当你把LoginFilter的doFilter方法逐行 debug 过三次,当你在catalina.out里 grep 出org.apache.catalina.core.ApplicationFilterChain的调用栈,当你亲手把web.xml里的<filter-mapping>顺序调换后观察拦截失效……你就拿到了进入 Java Web 世界的钥匙。

这个 ZIP 包不是终点,而是起点。它不承诺高薪,但保证让你第一次真正“看见” HTTP 请求从浏览器发出,到数据库返回结果,中间每一层发生了什么。这种确定性,比任何框架文档都珍贵。

希望帮到你。

本文还有配套的精品资源,点击获取

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

ponytail插件收束方案:轻量编排零散模块的实践指南

1. 从“ponytail”这个词说起&#xff1a;它到底是什么第一次看到“ponytail”这个词&#xff0c;大多数人脑子里蹦出来的画面是发型——马尾辫。但在技术圈和工具链语境里&#xff0c;ponytail 已经悄悄变成了一个有意思的代号&#xff0c;指向的是一类“把零散资源收束成一股…

作者头像 李华
网站建设 2026/10/27 22:21:00

Servlet Cookie 全链路:属性、编码与删除排查

Servlet里有一类对象&#xff0c;你天天在用&#xff0c;但很少认真翻过它的文档&#xff0c;Cookie算一个。多数人第一次接触javax.servlet.http.Cookie&#xff0c;是在做登录功能的时候&#xff1a;跟着教程敲三行代码&#xff0c;new 一个、setMaxAge、addCookie&#xff0…

作者头像 李华
网站建设 2026/10/27 22:20:07

扩散模型对抗攻击与防御:原理、方法与实践

1. 扩散模型与对抗样本基础概念解析在计算机视觉和生成模型领域&#xff0c;扩散模型(Diffusion Models)已经成为当前最强大的生成框架之一。这类模型通过定义前向扩散过程和逆向去噪过程&#xff0c;能够从随机噪声中逐步生成高质量的图像样本。然而&#xff0c;就像其他深度学…

作者头像 李华
网站建设 2026/10/27 22:19:38

中文分词算法演进:从BPE到WordPiece与ULM

1. 分词算法概述&#xff1a;从基础概念到现代演进第一次接触NLP的朋友往往会被"分词"这个概念难住——为什么好端端的文本非要切分成碎片&#xff1f;这得从计算机处理自然语言的底层逻辑说起。人类阅读"我爱自然语言处理"时能自动识别词语边界&#xff0…

作者头像 李华
网站建设 2026/10/27 22:16:44

OpenMontage 深度拆解:配置驱动的开源媒体内容重组工具设计与实现

1. 项目缘起与核心定位第一次看到“OpenMontage”这个名字&#xff0c;我脑子里蹦出来的第一个画面是电影剪辑台上的蒙太奇——把一堆零散的镜头素材&#xff0c;按照某种节奏和逻辑拼在一起&#xff0c;最后形成一段有表达力的画面。这个项目取这个名字&#xff0c;大概率是想…

作者头像 李华
网站建设 2026/10/27 22:16:40

操作系统存储管理实验:地址转换、内存分配与页面置换

存储管理这个实验&#xff0c;是操作系统课程里最容易被做成"填空作业"的一节。我帮人看过不少版本&#xff1a;页表数组开好&#xff0c;地址转换函数里一行除法一行取模写完&#xff0c;置换算法套个 while 循环&#xff0c;跑出来的数字往报告里一贴&#xff0c;看…

作者头像 李华