尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

JSP课程设计重构:从SQL注入到安全登录的Java Web演进

JSP课程设计重构:从SQL注入到安全登录的Java Web演进 简介这是一份面向高校Java Web初学者的JSP课程设计实践资源聚焦基础Web开发能力训练适用于JSPJavaBeanAccess技术栈的入门项目实训与课设参考。资源以简易留言本为核心功能完整呈现用户留言、UBB格式解析含头像支持、管理员登录集成图形验证码、MD5密码加密及数据库操作等典型模块代码结构清晰、部署便捷解压后可直接在Tomcat中运行无需额外配置数据源。压缩包共194个文件包含13个核心JSP页面、5个编译后的JavaBean类如MD5.class、UbbCode.class、FaceFilter.class等、5个CSS样式文件、4个Access数据库文件.mdb及大量界面资源157个GIF、1个PNG整体体积仅621KB轻量易学。目前已有157人学习下载提供从页面交互、正则表达式应用、前端过滤到后端安全处理的全流程实现细节是理解JSP三层架构与轻量级Web开发实践的优质参考样本。1. 项目背景与核心价值一个经典的JSP课程设计最近在整理旧硬盘时翻到了一个尘封已久的压缩包jspbook.rar。解压开来里面是一个典型的、用JSPJavaBeanAccess数据库实现的课程设计项目功能涵盖了用户登录、简单的信息管理。看着那些略显“复古”的代码和配置不禁感慨万千。这几乎是十多年前每个计算机相关专业学生都绕不开的“Web开发入门课”作业。虽然现在主流技术栈早已是Spring Boot、MyBatis、Vue.js的天下但回过头来剖析这样一个“古董级”项目其价值远不止于怀旧。这个项目麻雀虽小五脏俱全。它清晰地展示了早期Java Web开发Model 1架构的核心模式JSP页面负责展示JavaBean封装业务逻辑和数据JDBC直连Access数据库进行CRUD操作。对于初学者而言理解这个项目就等于理解了Web应用从浏览器请求到数据库操作再返回响应的完整数据流。更重要的是项目中潜藏着大量如今依然需要警惕的“历史遗留问题”比如原生的SQL拼接极易导致SQL注入、混乱的脚本片段JSP中混杂大量Java代码、以及Access数据库连接的各种坑。通过复现和重构这个项目我们不仅能重温技术演进的历史更能以一种“降维打击”的视角深刻理解现代框架为何要解决那些问题以及如何从底层规避安全风险。因此我决定以这个jspbook.rar项目为蓝本写一篇超详细的“考古”与“重建”指南。目标不是教大家如何原封不动地运行它而是带大家深入其肌理理解每一行代码背后的意图并亲手用更规范、更安全的方式将其重构。无论你是想了解JSP时代的历史还是想夯实Java Web基础或是单纯好奇一个登录功能背后有多少门道这篇文章都将为你提供一次绝佳的实战之旅。2. 环境搭建穿越回那个Eclipse和Access的年代要原汁原味地体验这个课程设计第一步就是搭建一个“复古”的开发环境。这不仅仅是安装软件更是理解当时技术选型约束的过程。2.1 开发工具选型为什么是它们项目原始环境很可能是Windows XP/7 JDK 1.6/1.7 Tomcat 6/7 Eclipse for Java EE Access 2003/2007。我们尽量贴近这个配置JDK 1.8选择JDK 8而非更高版本是因为它兼容性最好既能支持老旧的JSP语法和库其自身的工具链也足够现代。更高版本的JDK在运行某些非常古老的库时可能会有兼容性问题。从Oracle官网下载历史版本或使用Azul Zulu等发行版的JDK 8均可。Apache Tomcat 8.5这是一个折中的选择。Tomcat 6/7对早期的JSP规范支持最原教旨但配置相对麻烦。Tomcat 8.5是最后一个对传统JSP支持非常完善的版本且管理界面更友好。避免使用Tomcat 9及以上因为它们对JasperJSP引擎的默认配置可能对某些古老语法不友好。Eclipse IDE for Enterprise Java Developers这是最贴近原始体验的一环。虽然IntelliJ IDEA功能更强大但当年这个课程设计99%是用Eclipse完成的。Eclipse的“Dynamic Web Project”项目结构、将项目添加到Tomcat Server、以及其特有的部署方式本身就是学习的一部分。在Eclipse中你需要配置好JDK和Tomcat运行时环境。Microsoft Access数据库Access是核心“历史文物”。它不是一个服务而是一个文件.mdb或.accdb。你需要安装一个Office套件或单独安装Access运行时来创建和查看它。对于开发而言我们其实只需要它的JDBC驱动来连接。注意在Windows 11或新版macOS上直接运行旧版Access可能会遇到问题。如果无法安装替代方案是使用UCanAccess这个纯Java的JDBC驱动来操作.mdb/.accdb文件它不需要安装Access软件更适合跨平台开发环境。这是我们在重构时会采用的主流方案。2.2 项目结构与依赖解析解压jspbook.rar后你会看到一个标准的Java Web项目目录结构jspbook/ ├── WebContent/ (或 WebRoot/) │ ├── index.jsp (首页) │ ├── login.jsp (登录页面) │ ├── login_check.jsp (登录处理页面) │ ├── success.jsp (登录成功页) │ ├── error.jsp (错误页) │ └── WEB-INF/ │ ├── web.xml (部署描述符) │ └── lib/ (空或含有access驱动jar包) ├── src/ │ └── (可能有一些JavaBean源文件如 UserBean.java) └── (可能直接有 .class 文件在 WEB-INF/classes 下)关键点在于依赖的JAR包。原项目很可能缺少lib目录因为当时的环境可能将Access的JDBC驱动access.jar或Jackcess相关jar放在了Tomcat的lib文件夹下。为了项目自包含我们应该将驱动放入WEB-INF/lib。驱动准备传统方式寻找rt.jar(JDK自带) 和access.jar但后者难寻且功能有限。推荐方式UCanAccess下载UCanAccess的完整组件包通常包括ucanaccess-5.x.x.jarjackcess-3.x.x.jarhsqldb-2.x.x.jarcommons-lang3-3.8.1.jarcommons-logging-1.2.jar将这些JAR包全部复制到项目的WEB-INF/lib目录下并在Eclipse中将其添加到构建路径。2.3 数据库准备与连接原项目的Access数据库文件如jspbook.mdb可能就在项目根目录或某个资源文件夹下。我们需要检查其结构。查看数据库结构用Access软件或任何支持Access的数据库工具如DBeaver需安装Access插件打开.mdb文件。通常你会看到一张用户表例如t_user字段可能包括id,username,password,email等。请务必记下表名和字段名大小写敏感。分析原始连接代码在login_check.jsp或某个JavaBean中寻找类似以下的代码片段Class.forName(sun.jdbc.odbc.JdbcOdbcDriver); String url jdbc:odbc:driver{Microsoft Access Driver (*.mdb)};DBQC:/path/to/jspbook.mdb; Connection conn DriverManager.getConnection(url);这是经典的JDBC-ODBC桥接驱动它依赖Windows系统自带的ODBC数据源是跨平台性最差、最不推荐的方式在现代系统中基本无法工作。建立新的、可用的连接我们将使用UCanAccess驱动。假设数据库文件jspbook.mdb被我们放在WebContent/WEB-INF/db/目录下这是一个相对安全的位置外界无法直接通过URL访问。// 加载UCanAccess驱动 Class.forName(net.ucanaccess.jdbc.UcanaccessDriver); // 构造JDBC URL。注意路径这里使用getRealPath获取物理路径 String dbPath application.getRealPath(/WEB-INF/db/jspbook.mdb); String url jdbc:ucanaccess:// dbPath; Connection conn DriverManager.getConnection(url);这段代码应该放在一个独立的数据库工具类如DBUtil.java中而不是散落在各个JSP里。这是我们从“考古”迈向“重建”的第一步分离关注点。3. 核心模块深度剖析登录功能的“原始”实现与隐患登录是此课程设计的核心功能也是安全问题的重灾区。让我们先看看它最初是如何实现的并逐行分析其问题。3.1 JSP页面视图与逻辑的混沌初开典型的login.jsp可能长这样% page languagejava contentTypetext/html; charsetGBK pageEncodingGBK% html headtitle用户登录/title/head body form actionlogin_check.jsp methodpost 用户名input typetext nameusernamebr 密码input typepassword namepasswordbr input typesubmit value登录 /form /body /html这里问题不大只是一个简单的表单。字符编码是GBK这是当时中文环境的标配但现在我们应统一改为UTF-8。重头戏在login_check.jsp% page importjava.sql.* % % request.setCharacterEncoding(GBK); // 编码处理 String username request.getParameter(username); String password request.getParameter(password); Connection conn null; Statement stmt null; ResultSet rs null; try { Class.forName(sun.jdbc.odbc.JdbcOdbcDriver); String url jdbc:odbc:driver{Microsoft Access Driver (*.mdb)};DBQD:/jspbook.mdb; conn DriverManager.getConnection(url); stmt conn.createStatement(); // 致命漏洞SQL注入 String sql SELECT * FROM t_user WHERE username username AND password password ; rs stmt.executeQuery(sql); if(rs.next()) { session.setAttribute(loginUser, username); // 会话管理 response.sendRedirect(success.jsp); } else { response.sendRedirect(error.jsp?msg用户名或密码错误); } } catch(Exception e) { e.printStackTrace(); response.sendRedirect(error.jsp?msg系统错误); } finally { // 资源关闭可能不完整 try { if(rs!null) rs.close(); } catch(SQLException e) {} try { if(stmt!null) stmt.close(); } catch(SQLException e) {} try { if(conn!null) conn.close(); } catch(SQLException e) {} } %3.2 四大“考古”发现与安全隐患这段代码是早期JSP项目的“教科书式”反面案例集中体现了多个严重问题SQL注入漏洞高危String sql SELECT ... username ...这是最经典的注入点。如果用户在用户名输入admin --密码任意SQL语句会变成SELECT * FROM t_user WHERE usernameadmin -- AND passwordxxx--在Access SQL中也是注释符这意味着密码验证被完全绕过直接以admin身份登录。在热词中出现的sql注入万能密码绕过、cause: java.sql.sqlexception: sql injection violation正是此类问题的直接体现。数据库连接硬编码数据库文件路径D:/jspbook.mdb直接写在代码中。一旦部署到别的服务器路径改变程序立刻崩溃。且数据库文件暴露在非Web目录下存在被直接下载的风险。资源管理与编码资源关闭不彻底虽然有关闭操作但在复杂的异常路径下比如Class.forName失败conn可能还未创建就进入finally块导致空指针异常掩盖了原始异常。更健壮的做法是每个资源在try块外声明为null在finally中判断非空再关闭。字符编码混乱页面、请求、数据库三处的编码如果不一致GBK vs UTF-8中文必然乱码。request.setCharacterEncoding(GBK)只对POST请求体有效对GET请求无效且需要在获取参数前调用。JSP职责过重这个JSP页面承担了控制层接收参数、逻辑判断和模型层数据库操作的所有职责违反了MVC模式。这使得代码难以维护、测试和复用。3.3 JavaBean的原始形态在src目录下你可能会找到一个UserBean.javapackage bean; public class UserBean { private String username; private String password; // 可能还有其他字段如 email, phone // 无参构造器是JavaBean规范必须的 public UserBean() {} // Getter和Setter public String getUsername() { return username; } public void setUsername(String username) { this.username username; } public String getPassword() { return password; } public void setPassword(String password) { this.password password; } // 可能包含一个业务方法但通常很简陋 public boolean validate() { // 非常初级的验证比如非空检查 return username ! null !username.trim().isEmpty() password ! null !password.trim().isEmpty(); } }这个Bean只是一个简单的数据容器业务逻辑如真正的登录验证仍然被写在JSP里。它体现了“数据封装”的思想但离真正的“模型”还差得远。在JSP页面中可能会用jsp:useBean和jsp:setProperty标签来操作它但这套标签在实践中并不灵活逐渐被淘汰。4. 重构实战从“考古现场”到“现代工程”理解了原始代码的问题我们现在开始重构。目标是将这个项目改造成一个结构清晰、安全可靠、易于维护的“现代化”JSP项目虽然技术栈仍是JSP但应用了更好的实践。4.1 第一步建立分层架构与工具类我们首先摒弃JSP中写Java代码的习惯采用Model 1.5或雏形的MVC思想JSP只做显示Servlet或用JSP模拟控制器处理请求JavaBean作为模型工具类负责底层操作。创建数据库工具类DBUtil.javapackage util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class DBUtil { private static final String DRIVER net.ucanaccess.jdbc.UcanaccessDriver; private static String URL; // 需要在初始化时动态获取 static { try { Class.forName(DRIVER); } catch (ClassNotFoundException e) { throw new ExceptionInInitializerError(加载数据库驱动失败); } } // 获取数据库文件路径。通过ServletContext在应用启动时设置 public static void setDbPath(String path) { URL jdbc:ucanaccess:// path; } public static Connection getConnection() throws SQLException { if (URL null) { throw new SQLException(数据库路径未初始化请在Listener中调用DBUtil.setDbPath()); } return DriverManager.getConnection(URL); } // 通用的关闭方法处理Connection, Statement, ResultSet public static void close(AutoCloseable... closables) { if (closables ! null) { for (AutoCloseable c : closables) { if (c ! null) { try { c.close(); } catch (Exception e) { /* 记录日志通常忽略 */ } } } } } }这个工具类解决了驱动加载和资源关闭的通用问题。数据库路径需要通过一个ServletContextListener在应用启动时设置这样就能动态获取WEB-INF/db/的真实路径。创建监听器AppContextListener.javapackage listener; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; import util.DBUtil; WebListener public class AppContextListener implements ServletContextListener { Override public void contextInitialized(ServletContextEvent sce) { String dbPath sce.getServletContext().getRealPath(/WEB-INF/db/jspbook.mdb); DBUtil.setDbPath(dbPath); System.out.println(数据库路径已初始化: dbPath); } Override public void contextDestroyed(ServletContextEvent sce) {} }使用WebListener注解或web.xml配置让它在应用启动时自动运行完成DBUtil的初始化。4.2 第二步改造JavaBean与DAO模式原始的UserBean只承载数据。我们需要一个DAO (Data Access Object)来专门负责与数据库交互。增强User模型package model; public class User { private Integer id; private String username; private String password; // 注意实际应用中密码不应是明文 private String email; // 构造器、Getter、Setter省略... }创建UserDAO接口及其实现package dao; import model.User; import java.sql.SQLException; public interface UserDao { User findByUsernameAndPassword(String username, String password) throws SQLException; // 可以扩展其他方法findById, save, update等 }package dao.impl; import dao.UserDao; import model.User; import util.DBUtil; import java.sql.*; public class UserDaoImpl implements UserDao { Override public User findByUsernameAndPassword(String username, String password) throws SQLException { // 使用PreparedStatement防止SQL注入 String sql SELECT id, username, email FROM t_user WHERE username ? AND password ?; User user null; Connection conn null; PreparedStatement pstmt null; ResultSet rs null; try { conn DBUtil.getConnection(); pstmt conn.prepareStatement(sql); // 设置参数 pstmt.setString(1, username); pstmt.setString(2, password); // 暂为明文下一步会处理 rs pstmt.executeQuery(); if (rs.next()) { user new User(); user.setId(rs.getInt(id)); user.setUsername(rs.getString(username)); user.setEmail(rs.getString(email)); // 注意我们不把密码从数据库读入User对象 } } finally { DBUtil.close(rs, pstmt, conn); } return user; // 找到返回User对象没找到返回null } }核心改进使用PreparedStatement彻底杜绝SQL注入。参数用?占位通过setString等方法设置数据库驱动会负责安全的转义和处理。清晰的资源管理使用工具类统一关闭。面向接口编程便于未来更换数据库实现比如换成MySQL。4.3 第三步实现安全的登录控制器我们不直接使用JSP作为控制器而是创建一个Servlet。这是现代Java Web的标准做法。创建LoginServletpackage controller; import dao.UserDao; import dao.impl.UserDaoImpl; import model.User; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.WebServlet; import java.io.IOException; WebServlet(/login.do) // 映射到 /login.do 与原来的 login_check.jsp 区分 public class LoginServlet extends HttpServlet { private UserDao userDao new UserDaoImpl(); Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 设置字符编码统一UTF-8 request.setCharacterEncoding(UTF-8); response.setContentType(text/html; charsetUTF-8); // 2. 获取参数 String username request.getParameter(username); String password request.getParameter(password); // 3. 基本验证非空 if (username null || username.trim().isEmpty() || password null || password.trim().isEmpty()) { request.setAttribute(errorMsg, 用户名和密码不能为空); request.getRequestDispatcher(/login.jsp).forward(request, response); return; } // 4. 密码加密验证重要 // 假设数据库中存储的是MD5加密后的密码这是一个简单的示例生产环境应用更安全的如BCrypt String encryptedPassword md5(password); // 需要实现一个md5工具方法 try { // 5. 调用DAO进行验证 User user userDao.findByUsernameAndPassword(username, encryptedPassword); if (user ! null) { // 登录成功 HttpSession session request.getSession(); session.setAttribute(currentUser, user); // 存入整个用户对象而非只是名字 session.setMaxInactiveInterval(30 * 60); // 会话超时30分钟 // 重定向到成功页面避免重复提交 response.sendRedirect(request.getContextPath() /success.jsp); } else { // 登录失败 request.setAttribute(errorMsg, 用户名或密码错误); request.getRequestDispatcher(/login.jsp).forward(request, response); } } catch (Exception e) { e.printStackTrace(); // 生产环境应记录日志 request.setAttribute(errorMsg, 系统繁忙请稍后再试); request.getRequestDispatcher(/error.jsp).forward(request, response); } } private String md5(String input) { // 简化的MD5实现实际应使用MessageDigest // 此处仅为示例生产环境请使用标准库或Spring Security的PasswordEncoder try { java.security.MessageDigest md java.security.MessageDigest.getInstance(MD5); byte[] array md.digest(input.getBytes(UTF-8)); StringBuilder sb new StringBuilder(); for (byte b : array) { sb.append(String.format(%02x, b)); } return sb.toString(); } catch (Exception e) { throw new RuntimeException(e); } } }修改login.jsp表单form action${pageContext.request.contextPath}/login.do methodpost 用户名input typetext nameusernamebr 密码input typepassword namepasswordbr input typesubmit value登录 %-- 显示错误信息 --% c:if test${not empty errorMsg} div stylecolor:red;${errorMsg}/div /c:if /form注意表单提交地址改为/login.do。使用了JSTL标签c:if和EL表达式${errorMsg}来显示Servlet传递过来的错误信息。你需要在页面头部引入JSTL核心库% taglib prefixc urihttp://java.sun.com/jsp/jstl/core %。4.4 第四步处理密码安全与会话管理原始项目最大的安全漏洞之一是密码明文存储。我们必须修复它。密码加密存储首先你需要修改Access数据库中的用户表。为password字段存入加密后的值而不是明文。例如原始密码是123456你需要将MD5(123456)的结果如e10adc3949ba59abbe56e057f20f883e存入数据库。可以通过一个简单的Java程序或在线MD5工具仅用于测试数据准备来生成。在LoginServlet中用户输入的密码先用同样的MD5算法加密再与数据库中的密文比对。重要提示MD5目前已被认为不够安全易受彩虹表攻击课程设计中用于演示原理尚可。真实项目必须使用加盐的哈希算法如BCryptSpring Security的BCryptPasswordEncoder是绝佳选择。会话安全加固会话固定攻击防护在用户登录成功后调用request.getSession().invalidate();使旧会话失效然后request.getSession(true);创建一个新会话。或者至少重置会话IDrequest.changeSessionId();(Servlet 3.1)。登录状态检查在success.jsp或其他需要登录才能访问的页面顶部加入检查% page importmodel.User % % User user (User) session.getAttribute(currentUser); if (user null) { response.sendRedirect(request.getContextPath() /login.jsp); return; } % 欢迎你%user.getUsername()%退出登录提供一个logout.do的Servlet里面执行session.invalidate();然后重定向到登录页。5. 部署、调试与常见“坑点”解决将重构后的项目部署到Tomcat并运行你可能会遇到一些典型问题。这里集中梳理并给出解决方案。5.1 部署步骤与路径问题在Eclipse中部署创建一个新的“Dynamic Web Project”项目名如JspBookRefactored。将我们重构后的src源码、WebContent包含JSP、WEB-INF/lib、WEB-INF/db复制到新项目中。右键项目 - Properties - Java Build Path - Libraries - Add JARs将WEB-INF/lib下的所有jar添加进去。右键项目 - Run As - Run on Server选择配置好的Tomcat 8.5。路径问题详解数据库文件路径这是我们使用ServletContext.getRealPath()的原因。在IDE中运行时它指向的是Eclipse工作空间下.metadata里的临时部署目录如workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/JspBookRefactored/WEB-INF/db/jspbook.mdb。这确保了无论项目部署到哪里代码都能找到数据库文件。Web应用上下文路径Context Path在Eclipse中你可以在“Server”视图里双击Tomcat在模块Modules设置中修改应用的上下文路径比如从/JspBookRefactored改为/。代码中应使用request.getContextPath()来动态获取而不是硬编码这样修改上下文路径后代码无需改动。5.2 编码问题全攻略中文乱码是JSP老项目的顽疾。我们的目标是全程UTF-8。JSP页面在每个JSP页面的头部设置% page languagejava contentTypetext/html; charsetUTF-8 pageEncodingUTF-8%HTML Meta标签在head里也加上meta charsetUTF-8请求编码Servlet中在Servlet的doPost/doGet方法最开始处设置request.setCharacterEncoding(UTF-8); response.setCharacterEncoding(UTF-8); // 或通过setContentType设置 response.setContentType(text/html; charsetUTF-8);注意request.setCharacterEncoding(UTF-8)只对POST请求体有效。对于GET请求的参数在URL中Tomcat 8.5及以上版本默认是ISO-8859-1解码。需要在server.xml的Connector标签中添加URIEncodingUTF-8属性。或者更暴力的方法是在获取GET参数后手动转码new String(username.getBytes(ISO-8859-1), UTF-8)但不推荐。数据库编码Access数据库本身对UTF-8支持一般。如果从旧GBK数据库导入数据出现乱码可能需要在Java层进行转换。UCanAccess驱动会处理编码但确保你存入的数据是UTF-8字符串。5.3 典型错误与排查根据热词中反映的常见问题这里给出排查思路ClassNotFoundException: net.ucanaccess.jdbc.UcanaccessDriver原因UCanAccess的JAR包没有正确添加到项目的类路径。解决确保所有必需的JAR包都在WEB-INF/lib下并且在Eclipse的“Deployment Assembly”或“Java Build Path”中生效。对于Maven项目需在pom.xml中正确声明依赖。SQLException: 数据源名称过长或连接失败原因UCanAccess的JDBC URL路径中包含空格或特殊字符未处理。解决对文件路径进行URL编码或确保路径中没有中文和空格。可以使用java.net.URLEncoder.encode(dbPath, UTF-8)处理路径。JSP文件未找到或404错误原因web.xml中配置有误或Servlet的WebServlet注解映射路径与JSP中表单提交的路径不匹配。解决检查浏览器地址栏的URL与你的映射。使用%request.getContextPath()%来生成绝对路径避免相对路径问题。Error 404: 访问资源被禁止原因尝试直接访问WEB-INF或META-INF目录下的资源。这些目录受Servlet容器保护客户端无法直接访问。解决这是正常的安全机制。确保你的JSP页面放在WebContent根目录或其子目录下除了WEB-INF。登录后Session丢失原因可能浏览器禁用了Cookie而Session依赖Cookie中的JSESSIONID。或者Session超时时间设置过短。解决确保浏览器接受Cookie。可以通过URL重写传递Session IDresponse.encodeURL()或response.encodeRedirectURL()但较麻烦。更简单的是检查Tomcat/conf/web.xml中session-config的session-timeout或在代码中设置session.setMaxInactiveInterval()。6. 从Access迁移到更现代的数据库可选虽然UCanAccess解决了Access的跨平台问题但Access作为生产环境数据库确实力不从心。作为课程设计的延伸我们可以考虑将其迁移到MySQL或H2嵌入式Java数据库更轻量。6.1 迁移到H2数据库嵌入式最简单H2数据库是一个纯Java编写的嵌入式数据库非常适合演示和小型项目。添加依赖下载h2-1.4.200.jar版本示例放入WEB-INF/lib。修改DBUtilpublic class DBUtil { private static final String DRIVER org.h2.Driver; private static final String URL jdbc:h2:~/test;AUTO_SERVERTRUE; // 存储在用户目录下 private static final String USER sa; private static final String PASSWORD ; // ... 其余代码类似getConnection时传入USER和PASSWORD }导出导入数据使用Access将数据导出为CSV格式然后编写一个简单的Java程序使用H2的JDBC驱动和INSERT语句将CSV数据导入H2。或者使用H2的控制台java -cp h2.jar org.h2.tools.Server通过SQL文件导入。6.2 迁移到MySQL更接近生产安装MySQL创建数据库和用户表。更换驱动将依赖从UCanAccess JAR包换成mysql-connector-java-8.0.x.jar。修改DBUtil的连接参数private static final String DRIVER com.mysql.cj.jdbc.Driver; private static final String URL jdbc:mysql://localhost:3306/jspbook?useUnicodetruecharacterEncodingUTF-8serverTimezoneAsia/Shanghai; private static final String USER root; private static final String PASSWORD yourpassword;调整SQL语句Access的SQL和MySQL的SQL有细微差别如自动递增字段、日期函数。需要检查并修改UserDaoImpl中的SQL确保兼容。无论迁移到哪种数据库DAO接口保持不变只需修改实现类这正体现了面向接口编程和分层架构的优势。通过以上六个步骤我们完成了一次对传统JSP课程设计的深度“考古”与现代化“重建”。这个过程不仅让你能运行起一个老项目更重要的是你理解了每一个改进背后的“为什么”从安全漏洞到架构缺陷从编码规范到部署调试。这远比单纯学习一个新的框架更有价值因为它建立的是对Web开发本质的深刻认知。下次当你再看到任何关于JSP、JavaBean、SQL注入、Access的讨论或问题时你都能胸有成竹知其然更知其所以然。本文还有配套的精品资源点击获取
返回列表