ARTICLE DETAIL

资讯详情

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

JSP+Access网上购物系统开发:从ODBC配置到部署迁移全攻略

JSP+Access网上购物系统开发:从ODBC配置到部署迁移全攻略 简介这是一套基于JSP与Access数据库的网上购物系统完整项目采用浏览器/服务器模式覆盖商品浏览、购物车、订单生成等主要业务流程是Java Web课程设计或毕业设计的常见选题。面向需要完整体验项目开发过程、希望获得可运行范例的学生及开发者尤其适合正在准备相关项目设计、课程作业或答辩的场景。压缩包约1.9MB内部包含项目全套源码和完整说明文档主要文件类型有JSP页面、后端Java类、Access数据库文件以及系统设计文档除运行代码外还提供需求分析、模块说明和数据库设计等材料目录划分清楚便于按功能模块查找与复用。目前已有290人学习下载属于较受欢迎的设计参考。所有源码均经过测试校正能够稳定运行文档则对系统结构、数据表设计和关键流程做了整理可直接用于二次开发或撰写设计报告能显著节省从零搭建的时间。1. 为什么 2025 年还有人要做 JSPAccess 的网上购物系统打开招聘网站JSP 早不是主流Access 更不是但每年毕业设计选题清单里“基于 JSPAccess 的网上购物系统设计与实现”还是稳稳占着一席。原因很现实很多高校的 Java Web 课程还在讲 JSPServlet题目直接指定“必须用 Access”目的就是让学生把精力放在 Java 代码和系统设计上而不是耗费在数据库运维。这套组合适合两类人一是需要交付可运行系统加设计文档的在校生二是接手维护十年老系统的从业者。它的坑也很集中——JDK 版本、ODBC 驱动位数、Access 文件锁三样里任何一样出错系统就跑不起来而且这些报错信息对排查毫无帮助。这篇笔记按调试顺序来写先环境、再表结构、再功能最后是避坑和迁移方案照着做能少走很多弯路。2. 先跑通数据源JSPAccess 的环境搭建与 ODBC 配置2.1 技术选型不是复古这套组合对课程设计有多友好JSPAccess 常被选中不是因为性能而是因为省事。Access 是文件型数据库一个 .accdb 文件就是一个完整库不需要像 MySQL 那样安装服务、配置账号、管理权限。对“能跑、能演示、有文档”就够的课程设计来说这套组合在机房环境里迁移成本极低整套项目拷到另一台电脑改一个数据源名称就能接着演示。文件型数据库的代价是并发能力几乎为零多个人同时写同一个文件就会锁冲突所以它适合单机演示不适合真实上线。如果题目没有指定数据库我一般建议直接上 MySQL半天迁移成本换来后续省心但如果题目已经写死“必须使用 Access”那就把精力放在 JSP/Servlet 和 DAO 层的代码组织上这是老师真正给分的地方。课程设计里常见的另一个误区是试图给 Access 配连接池、配分布式之类的东西完全没必要一个 DSN 一个连接就够把时间花在核心功能上比什么都值。2.2 JDK、Tomcat、ODBC 驱动最小环境清单与版本约束动手写代码之前先把版本对齐这步能省下大量排错时间。我常用的组合是这样的JDK 1.864 位JDK 1.8 是 JDBC-ODBC 桥还能完整工作的最后一个主要版本。再往上这个桥被移除Class.forName(sun.jdbc.odbc.JdbcOdbcDriver) 会直接抛 ClassNotFoundException。Tomcat 8.5 或 9.0和 JDK 1.8 兼容稳定对 JSP 2.3 / Servlet 3.1 支持完全够用。不建议在这个项目上追 Tomcat 10Jakarta 命名空间迁移会让人把时间全耗在改 import 上。Access 2016 或更高版本用来建表和设计库文件。运行时不需要 Access 常驻只要 ODBC 驱动和数据文件在就行。机器没装 Office 时缺的是驱动本身去微软官方下载 Access Database Engine Redistributable 即可位数必须和 JDK 一致。ODBC 数据源64 位 JDK 配 64 位数据源这是最容易翻车的一环。很多人配置数据源时习惯在“运行”里敲 odbcad32但这个命令在不同系统里打开的管理器位数不确定。64 位管理器在 %windir%\System32\odbcad32.exe32 位在 %windir%\SysWOW64\odbcad32.exe。JDK 是 64 位却配了 32 位数据源连接时会报“未发现数据源名称”这句报错对新手完全没有指向性十有八九会让人怀疑是代码写错了。这种问题我见过太多次先把位数对齐再谈别的。提示JDBC-ODBC 桥在 JDK 1.8 中虽然能用官方早已标记为废弃。课程设计和维护老系统用它没问题做企业项目请走 MySQL 或 UCanAccess 这类纯 Java 驱动方案。2.3 配置 ODBC 数据源并写通第一条查询环境装好之后第一步不是写 JSP 页面而是写一个十行左右的 Java 小程序验证数据库能连通。这样做能把环境问题和代码问题彻底分开之后所有页面写起来才有底气。配置数据源的步骤启动 64 位 ODBC 数据源管理器切到“系统 DSN”页签。这里建议用系统 DSN 而不是用户 DSN因为 Tomcat 服务可能运行在不同账户下用户 DSN 会访问不到。然后点“添加”选择 “Microsoft Access Driver (*.mdb, *.accdb)”数据源名填 shop_dsn数据库路径指向已经建好的 shopping.accdb测试连接通过后保存。接着写最小可运行的测试程序import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class AccessTest { public static void main(String[] args) throws Exception { // 加载 JDBC-ODBC 桥驱动JDK 1.8 内置无需额外 jar Class.forName(sun.jdbc.odbc.JdbcOdbcDriver); // jdbc:odbc: 后面跟的是 ODBC 数据源名DSN String url jdbc:odbc:shop_dsn; Connection conn DriverManager.getConnection(url); Statement stmt conn.createStatement(); // 查询 Access 系统表验证驱动真正能读到库结构 ResultSet rs stmt.executeQuery(SELECT Name FROM MSysObjects WHERE Type1); while (rs.next()) { System.out.println(rs.getString(1)); } conn.close(); } }这段代码有两个关键点JDBC URL 的格式是 jdbc:odbc: 加数据源名称不需要用户名密码通过查询 MSysObjects 表来验证驱动真的能解析库结构。如果这段跑通说明 JDK、ODBC、Access 文件三个环节都没问题后面的业务代码出错就纯粹是代码问题。如果跑不通根据异常信息基本能定位ClassNotFoundExceptionJDK 版本高于 1.8换 JDK 或改用纯 Java 的 Access 驱动。未发现数据源名称DSN 没建好或者位数不匹配按 2.2 的路径重新建。文件正在使用Access 软件里开着同一个文件关掉再跑。这个测试类建议保留下来每次换机器部署时先跑一遍再启动 Tomcat比反复重启试错要快。如果机房机器装的是 32 位 Office 又必须配 64 位 JDK装 64 位 Access Database Engine 之前要先卸掉 32 位 Office这一步很多人会卡住。更省心的方式是直接用 UCanAccess 替代 JDBC-ODBC 桥它不依赖 ODBC 数据源连接 URL 直接指向文件路径位数问题彻底消失但题目明确要求 JDBC-ODBC 桥时还是按上面的标准配置走。3. 数据表设计是成败关键Access 表结构、自增主键与 DAO 层写法网上购物系统的核心链路是“用户—商品—购物车—订单”数据表设计比写页面更能拉开分数差距。很多人翻车不是代码写不出来而是表结构没设计好下单时发现缺字段、查订单不知道关联哪张表、改需求时表对不上。课程设计虽然数据量小但表关系必须完整这一章把表结构和 DAO 层一次讲透。3.1 用户、商品、订单、购物车四张核心表的字段设计最低限度需要五张表users、goods、orders、orderdetail外加可选的 cart 表。购物车数据放 Session 更安全见 4.2但如果题目明确要求购物车落库就留一张 cart 表。基本结构如下表名字段说明usersuserid, username, password, realname, address, phone, regtime用户信息username 唯一goodsgoodsid, goodsname, price, number, image, description, addtime商品表number 为库存ordersorderid, userid, business_no, totalprice, orderdate, status订单主表status 用数字orderdetailid, orderid, goodsid, buyprice, buynumber订单明细记录下单时价格cartid, userid, goodsid, number购物车表可选主键统一用“自动编号”类型外键字段用数字类型。Access 的表设计器里“自动编号”和“数字”长得像很容易把外键也设成自动编号插入数据时会报“不能将自动编号字段设置为外键”。我的固定写法是主键字段永远叫 xxxid类型选自动编号外键字段叫 userid / goodsid / orderid类型选“数字长整型”。几个容易忽略的细节。第一users 表的 username 必须唯一注册时先查重否则两个同名账号登录后台订单都分不清是谁下的。第二goods 表的 price 用“数字双精度”不要用文本否则金额排序和结算会出各种怪问题。第三orders 和 orderdetail 一定要拆两张表不能把一次购买的所有商品塞进一个文本字段否则“查订单里的商品”会变成字符串处理地狱而且第三范式的问题在答辩时一问就露馅。第四status 状态约定成数字字典0 待付款、1 已付款、2 已发货、3 已收货、4 已取消在 Java 里建一个 OrderStatus 常量类统一管理别把魔法数字散落在 Servlet 里。3.2 Access 的“自动编号”与主键生成策略写 DAO 层之前先解决一个关键问题插入一条记录后怎么拿到新生成的自动编号主键MySQL 的驱动支持 getGeneratedKeys()但 JDBC-ODBC 桥对这个方法支持不完整很多同学在这里拿到 null下单流程直接断掉。常见做法是在 INSERT 之后立刻用同一个连接查询 SELECT IDENTITY它返回当前连接最后一次插入的自动编号值。注意是连接级的如果中间新建了连接查到的就是别的值了。public int insertOrder(Connection conn, Order order) throws SQLException { String sql INSERT INTO orders(userid, business_no, totalprice, status) VALUES(?, ?, ?, 0); PreparedStatement ps conn.prepareStatement(sql); ps.setInt(1, order.getUserid()); ps.setString(2, order.getBusinessNo()); ps.setDouble(3, order.getTotalprice()); ps.executeUpdate(); ps.close(); Statement stmt conn.createStatement(); ResultSet rs stmt.executeQuery(SELECT IDENTITY); int orderId 0; if (rs.next()) { orderId rs.getInt(1); } rs.close(); stmt.close(); return orderId; }关键点是 executeUpdate 和 SELECT IDENTITY 必须共用一个 Connection。很多教程只写前半段插入和后半段按 orderid 插明细中间新建了连接去查结果永远拿到 0。另外如果插入订单后在同一个连接上又插过别的自动编号表IDENTITY 就变成那条记录的值了所以要在插入订单后立刻查询中间不要插入任何其他表。还有一个细节是业务订单号。直接把自增 orderid 当订单号展示别人能从数字增长猜出你的订单量。常见做法是拼接时间戳和用户 id例如 SimpleDateFormat(yyyyMMddHHmmss) 加 userId插入时存进 business_no 字段对外展示用 business_noorderid 留在内部当主键。Access 的自动编号删除后不回填这是正常的不用想办法让订单号连续。3.3 DAO 层连接代码与类型映射的细节DAO 层建议用一个 DBUtil 类统一管理连接。每次从 DriverManager 获取连接用完即关。这条规范在 Access 场景下是必须做到的——Access 是文件型数据库连接不释放会直接表现为 .ldb 锁文件残留后续所有操作全部阻塞。public class DBUtil { // 数据源名称建议从配置文件读取这里用常量方便演示 private static String odbcName shop_dsn; public static Connection getConnection() throws SQLException { try { Class.forName(sun.jdbc.odbc.JdbcOdbcDriver); } catch (ClassNotFoundException e) { throw new SQLException(JDBC-ODBC 桥驱动加载失败请确认 JDK 版本); } String url jdbc:odbc: odbcName; return DriverManager.getConnection(url); } public static void close(Connection conn, Statement stmt, ResultSet rs) { if (rs ! null) { try { rs.close(); } catch (SQLException e) {} } if (stmt ! null) { try { stmt.close(); } catch (SQLException e) {} } if (conn ! null) { try { conn.close(); } catch (SQLException e) {} } } }类型映射上要留心三点。第一Access 的“是/否”类型底层在 ODBC 里是数字 0 和 -1不是 0 和 1用 rs.getInt() 读会读出 -1建议用 getBoolean() 再按需转换。第二日期时间类型读取用 getTimestamp() 没问题插入时必须包成 java.sql.Timestamp直接传 java.util.Date 会报类型不匹配。第三image 字段用普通文本存相对路径就够不要用 Access 的“超级链接”类型后者带格式读出来还要解析。分页方面Access 没有 LIMIT常见写法是 TOP 加子查询。比如取第二页十条先查出第一页的 goodsid再用 NOT IN 排除。课程设计的数据量通常很小不分页直接全量展示反而省事如果老师明确要求分页按 TOP 子查询方式实现并能在答辩时讲清楚原理就够了。记住一个边界Access 没有存储过程业务逻辑全部集中在 Java 层所以 DAO 层的 SQL 要尽量简洁复杂查询拆成多次简单查询来做比写一条超长 SQL 好维护得多。4. 把核心功能跑起来登录、购物车、下单与后台管理表结构定好之后功能页面其实都是固定套路JSP 负责表单展示和提交Servlet 负责接收参数、调用 DAO、返回结果JavaBean 存数据。课程设计里最容易丢分的地方反而不是代码逻辑而是跳转关系、权限控制、状态流转这些平时不太注意的细节。下面把三段关键流程完整走一遍。4.1 登录与权限控制Session 的用法和页面跳转登录逻辑本身不难难在登录成功之后怎么办。很多人直接 sendRedirect 到首页结果用户从购物车点结算被带到登录页登录完又回首页购物车里的东西全丢了体验很差。我一般会在登录页接收一个 redirect 参数登录成功跳回来源页面。protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(UTF-8); String username request.getParameter(username); String password request.getParameter(password); User user userDao.findByUsernameAndPassword(username, password); if (user ! null) { HttpSession session request.getSession(); session.setAttribute(loginUser, user); String redirect request.getParameter(redirect); response.sendRedirect(redirect null ? goods_list.jsp : redirect); } else { request.setAttribute(errorMsg, 用户名或密码错误); request.getRequestDispatcher(login.jsp).forward(request, response); } }这里有两个习惯值得保留。第一登录失败用 forward 而不是 sendRedirect这样 request 里的 errorMsg 在 login.jsp 里用 ${errorMsg} 能直接取到地址栏也干净。第二登录成功后的跳转地址来自 redirect 参数用户从购物车点去结算时被带到登录页登录完还能回到购物车。这个参数在课程设计里经常被忽略但它是 jsp 个人信息展示页面做得顺不顺的关键——登录后的个人中心、购物车、订单页都要读 session 里的 loginUser 来展示session 里没有值就该统一跳登录页。权限控制不建议在 JSP 里手写判断。写一个 Filter 拦截 /cart/、/admin/路径session 里没有 loginUser 就跳登录页否则放行。public class LoginFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpSession session request.getSession(false); if (session null || session.getAttribute(loginUser) null) { HttpServletResponse response (HttpServletResponse) resp; response.sendRedirect(login.jsp?redirect request.getRequestURI()); return; } chain.doFilter(req, resp); } }在 web.xml 里注册这个 Filter 时url-pattern 写成 /cart/* 和 /admin/*不要拦截全部请求。如果拦截了 login.jsp 本身会出现重复跳转的死循环这是新手写 Filter 最常见的翻车点。拦截到未登录请求时把原始 URI 拼到 redirect 参数里登录后还能回到原来想去的页面。4.2 购物车与下单会话级购物车不落库也能跑购物车有两种实现存在 Access 表里或者存在 Session 里。课程设计场景下我强烈建议用 Session。Access 文件锁扛不住多用户同时写购物车而且购物车本来就是临时数据Session 在浏览器关闭时自动清空正好符合语义。Session 里放一个 MapInteger, CartItemkey 是商品 idvalue 是商品和数量。public void addToCart(HttpServletRequest request, int goodsId, int number) { HttpSession session request.getSession(); // 购物车是 session 级数据首次访问时初始化 MapInteger, CartItem cart (MapInteger, CartItem) session.getAttribute(cart); if (cart null) { cart new HashMapInteger, CartItem(); session.setAttribute(cart, cart); } CartItem item cart.get(goodsId); if (item null) { // 第一次加购从数据库读商品信息和价格快照 Goods goods goodsDao.findById(goodsId); item new CartItem(goods, 0); cart.put(goodsId, item); } item.setNumber(item.getNumber() number); }设计上要注意 CartItem 保存的是下单时刻的价格快照。课程设计阶段不一定做改价功能但建议字段里就带 buyPrice否则以后加了促销功能购物车里的老价格会跟着数据库变结算金额对不上。下单流程是先写 orders 主表拿到 orderid再循环购物车写 orderdetail 明细最后减库存。订单表插入和明细插入之间如果失败会出现只有主表没有明细的脏数据课程设计里通常不做事务补偿但要意识到这个瑕疵。Access 没有行级锁两个用户同时买最后一件商品时两边都能查到库存大于 0这是文件型数据库的边界答辩时能讲清楚就行。4.3 后台商品管理图片路径、库存与订单状态后台管理是老师重点翻的部分。商品管理的核心痛点不在增删改查而在图片上传和路径处理。文件上传用 commons-fileupload 是常见做法但上传文件保存路径千万不要写死成 D:/upload换机器部署立刻失效。我一般保存到项目的 upload 目录用 request.getServletContext().getRealPath(/upload) 动态获取路径。image 字段只存文件名页面展示用相对路径拼接img srcupload/${goods.image} alt${goods.goodsname} width120 height120 /页面里经常需要缩略图jsp 图片如何对坐标定位这类问题其实不用去改图片本身。常见做法是用 CSS 的 object-fit 统一裁剪显示区域或者在后台另存一个缩略图文件而不是在 JSP 里做坐标计算——后者既难维护又把页面写得很重。编辑商品时如果上传了新图记得把磁盘上的旧图删掉否则答辩时老师打开项目目录看到一堆没人引用的 test1.jpg、test2.jpg观感很差。订单管理后台需要订单列表和订单明细。订单列表按下单时间倒序显示订单号、用户名、总金额、状态。状态操作就两个发货和取消。发货把 status 从 1已付款改成 2已发货取消把 status 改成 4已取消并恢复库存。最容易被忽略的是“取消订单要恢复库存”很多人只改了状态库存没加回去演示到第三轮就没货可卖。恢复库存的逻辑要独立成方法比如 goodsDao.increaseStock(goodsId, buynumber)在发货取消、取消订单这些状态流转处统一调用不要写在某一个 Servlet 里否则后面加功能时会漏。后台页面的权限控制同样走 Filter建议单独写一个 AdminFilter检查 session 里的 loginUser 是否具有管理员标记。最粗暴但有效的做法是在 users 表加一个 is_admin 字段管理员账号值为 1Filter 里读出来判断不要单独建一张权限表——课程设计不需要为两个角色建一套权限系统那是给自己找麻烦。5. 部署运行避坑指南乱码、驱动丢失、文件锁与路径写死前四章把系统搭起来了但真正决定能不能顺利交付的是部署运行阶段的几个坑。这些坑一半查不到资料一半是经验换来的报错信息一个比一个迷惑不看提示根本不知道错在哪。我按出现频率从高到低整理成五条每条都按“现象 → 原因 → 解决”来写。5.1 中文乱码问题一个字符集配置漏掉就全乱现象登录页输入中文用户名页面上显示正常但提交后存进数据库变成“???”或者从数据库读出来再展示变成乱码。原因很多人觉得乱码是玄学其实就是 JSP 页面编码、请求编码、响应编码三层没对齐。常见的是只设置了 JSP 的 pageEncoding没设置 request 编码POST 请求里的中文按默认 ISO-8859-1 解码到 Java 里就乱了。解决统一所有环节为 UTF-8。JSP 页面头部写 pageEncodingUTF-8Servlet 里在读取任何参数之前调用 request.setCharacterEncoding(UTF-8)更省事的方式是在 web.xml 里配置一个 CharacterEncodingFilter全局生效不用在几十个 Servlet 里重复写。filter filter-nameencoding/filter-name filter-classcom.shop.filter.CharacterEncodingFilter/filter-class init-param param-nameencoding/param-name param-valueUTF-8/param-value /init-param /filter如果是 GET 请求乱码光靠 setCharacterEncoding 没用需要在 Tomcat 的 conf/server.xml 里给 Connector 加 URIEncodingUTF-8。Tomcat 8.5 之后默认 URI 编码就是 UTF-8但如果用的是旧版 Tomcat建议主动写上。Access 文件本身没有字符集概念数据进去是 UTF-8 就是 UTF-8这点比 MySQL 省心不用改库字符集。5.2 驱动加载失败JDK 版本和 ODBC 位数不匹配现象Class.forName(sun.jdbc.odbc.JdbcOdbcDriver) 报 ClassNotFoundException或者驱动加载成功但 getConnection 报“未发现数据源名称”。原因JDBC-ODBC 桥在 JDK 9 之后被移除版本不对必报 ClassNotFoundException。另一种情况更隐蔽ODBC 数据源分 32 位和 64 位JDK 是 64 位但配置数据源时打开的是 32 位管理器或者装的是 32 位 Access 驱动。解决统一成 64 位。运行 %windir%\System32\odbcad32.exe 打开 64 位管理器删除旧数据源重新添加。验证方法是在管理器里点“测试”通过再用第 2 章的 AccessTest 跑一遍两步都过就说明环境没问题。如果机器只有 32 位 Office需要先卸载再装 64 位 Access Database Engine Redistributable装完重启 ODBC 管理器。这个坑非常隐蔽因为 32 位驱动在管理器里也能看到 Microsoft Access Driver但 64 位 JDK 根本加载不了它。5.3 Access 文件被锁定.ldb 并发冲突现象系统跑了一会儿所有页面开始报“文件正在使用中”或“不能锁定文件”重启 Tomcat 也没用直到关掉 Access 软件或删除 .ldb 文件才恢复。原因Access 是多用户文件型数据库连接时会生成 .ldb 锁文件.accdb 对应 .laccdb。如果某个连接异常退出没有关闭锁文件一直残留后续所有操作被阻塞。最常见的触发场景是代码里 getConnection 之后 try 块抛了异常close 没执行。解决DAO 层所有方法按“finally 里关连接”的规范写异常路径也要关。同时注意调试时不要一边开着 Access 软件看数据一边跑 TomcatAccess 软件和 ODBC 驱动同时打开同一个文件锁冲突是必然的。public Goods findById(int id) { Connection conn null; PreparedStatement ps null; ResultSet rs null; try { conn DBUtil.getConnection(); ps conn.prepareStatement(SELECT * FROM goods WHERE goodsid?); ps.setInt(1, id); rs ps.executeQuery(); return rs.next() ? mapRow(rs) : null; } catch (SQLException e) { throw new RuntimeException(e); } finally { // 异常路径也要关闭连接防止锁文件残留 DBUtil.close(conn, ps, rs); } }锁文件已经残留时先停掉 Tomcat删除项目目录下所有 .ldb / .laccdb 文件再重启。注意同一时间只启动一个 Tomcat 实例多个实例共享同一个 Access 文件必然冲突。5.4 Access 数据库密码看着安全实际是摆设现象为了显得专业给 Access 文件设了数据库密码结果连接时处理密码很麻烦偶尔还报“无效的参数字段”之类的奇怪错误。原因Access 的数据库密码加密强度很低用常见的 Access 密码恢复工具几秒钟就能去掉它防不住任何人拷走文件。设了密码之后ODBC 数据源里还要额外配置配置错了连接直接失败调试成本翻倍。解决课程设计项目不建议给 Access 文件加数据库密码。真正要防的是别人直接下载 .accdb 文件就能看到全部表结构和数据这比猜密码容易多了。更实际的保护是把数据库文件放进 WEB-INF 目录下浏览器无法直接访问后台页面用 Filter 拦截。这比数据库密码靠谱得多而且不会增加连接配置的复杂度。如果老师要求数据必须加密那是另一个课题靠 Access 密码根本解决不了。5.5 路径写死换机器就找不到文件现象自己电脑上一切正常拷到老师电脑演示时图片全部加载不出来日志里全是找不到文件的异常。原因代码里有 D:/upload、/root/shop/data/shopping.accdb 这类写死的绝对路径。自己机器能跑换一台机器立刻失效。最常写死的有两处图片上传保存路径、Access 数据库文件路径。解决图片路径用相对部署目录的方式获取数据库文件如果打包在项目里就从 classpath 拼出路径。可变的配置全部抽到一个 config.properties 文件里换机器只改这一个文件。odbc.nameshop_dsn upload.dir/upload page.size10DBUtil 里读取配置InputStream in DBUtil.class.getClassLoader().getResourceAsStream(config.properties); Properties p new Properties(); p.load(in); odbcName p.getProperty(odbc.name);这样换机器部署时只需要确认 DSN 名称和上传目录是否存在五分钟能搞定不会在老师面前手忙脚乱。路径问题属于典型的一次踩坑长期受益的类型项目里凡是涉及路径的代码都要养成“绝不写绝对路径”的习惯。6. 验证与改造半小时跑通验收 从 Access 迁移到 MySQL6.1 验收清单手工测试的用例设计系统做完最后一步是照清单验一遍别在答辩现场才发现主链路断了。下面这张表覆盖核心交易链路每一项都是演示时一定会被点到的用例操作预期结果注册登录新用户注册再登录成功且页面跳转正确商品浏览打开列表和详情图片正常、价格库存显示购物车先加 2 件再加 3 件数量累加总价正确结算拦截未登录点结算跳登录页登录后回购物车下单确认结算生成订单库存减少后台发货操作订单状态状态流转正常越权访问未登录访问 admin 页面被 Filter 拦回登录页跑清单时用浏览器无痕窗口清掉旧 session避免登录态残留造成误判。每个用例最好能说清“做了什么操作、系统返回什么、对应哪段代码”答辩被追问时才有底气。6.2 从 Access 迁移到 MySQL 的三个步骤如果想把这套系统升级成能真实部署的项目迁移到 MySQL 是性价比最高的改造核心只要三步。第一步用 Access 的“外部数据”导出每张表为 SQL 脚本或 CSV再导入 MySQL。注意类型转换自动编号对应 AUTO_INCREMENT是/否对应 TINYINT(1)日期时间对应 DATETIME。第二步改连接层把 DBUtil 里的桥驱动换成 MySQL 驱动Class.forName(com.mysql.jdbc.Driver); String url jdbc:mysql://localhost:3306/shop?useUnicodetruecharacterEncodingUTF-8serverTimezoneAsia/Shanghai; Connection conn DriverManager.getConnection(url, root, your_password);驱动、URL、账号密码一变所有 DAO 调用点都不用动。第三步改 SQL 方言。Access 的分页用 TOPMySQL 用 LIMIT查询自增主键从 SELECT IDENTITY 改成 getGeneratedKeys()字符串函数和日期函数也都有差异。改完后把“登录—加购—下单—发货”完整跑一遍DAO 里返回值类型变了编译不一定报错但运行时一定暴露。6.3 安全加固与代码组织建议代码组织至少拆成 JavaBean、DAO、Servlet 三层JSP 里不写 JDBC这是我接手这类项目的第一原则。防注入只有一个原则所有用户输入走 PreparedStatement 参数绑定包括登录框、搜索框、后台状态值。Access 对注入的容忍度很低早期 ASP 时代大量注入案例都出自这类数据库字符串拼接 SQL 的习惯必须杜绝。后台管理用 Filter 拦截 admin 路径数据库文件放进 WEB-INF 目录防止下载。我自己调试这类系统的习惯是每次改数据库前先复制一份 .accdb 文件或者直接用 git 管理整个项目目录改坏了有后悔药。调试顺序上永远先跑通数据源再写页面环境问题不解决后面写再多界面都是白搭。这套流程走了很多遍最大的教训是多数时间都耗在了环境和激进的优化上而不是真正的业务逻辑。顺着这条路把基础打牢剩下的功夫花在把功能做完整上更值得。希望这篇笔记能帮你少踩几个坑把时间留给真正该写的代码。本文还有配套的精品资源点击获取
返回列表