简介:面向初学Java Web开发者的JSP与ACCESS数据库连接入门教程,重点讲解在小型项目与学习场景下,如何通过JDBC-ODBC桥驱动完成数据库连接、SQL查询与结果展示。资源以doc文档形式呈现,共1个文件,压缩包仅31KB,结构紧凑、便于快速查阅,目前已有238人学习浏览,适合作为高校课程实验或自主学习的参考资料。文档按完整实操流程展开:先创建test.mdb数据库及username表的uid、pwd字段,再将数据库文件部署至TOMCAT指定目录,最后给出JDBCAccess.jsp完整示例代码并演示运行效果。代码逐行解析加载驱动、建立连接、执行查询、遍历结果集与关闭资源等关键步骤,同时说明连接字符串参数含义、字符编码设置及常见报错排查思路。整体内容对理解JDBC原理、掌握JSP基础数据交互很有帮助,也可为后续迁移至MySQL、SQL Server等主流数据库打下良好基础。
1. JSP 连接 ACCESS 数据库:先讲清楚这条老路为什么还能走
JSP 连 ACCESS 数据库,放在十年前是 Java Web 课设的标准开场,放在今天仍然有人翻车后回来找答案。原因很简单:ACCESS 文件型数据库不需要单独装服务,拷贝一个 .mdb 文件就能跑,配合 JSP 做小型管理系统、课程设计、毕业设计绰绰有余。但这条路的坑也不少,驱动选型、数据库文件位置、ODBC 数据源配置、64 位系统兼容,每一个环节都可能让页面直接报错。这篇文章以你手上的 JSP 连接 ACCESS 数据库资源为主线,把从建库、放文件、写代码到排错的全过程拆开讲,适合正在做 JSP 课设、毕设或者维护老项目的开发者。你不需要提前懂太多 JDBC 原理,跟着步骤走就能把数据读出来,但我会把每一步为什么这么做也讲清楚,免得你换了个环境就不知道怎么办。
2. 驱动与连接原理:为什么选 JDBC-ODBC 桥,以及它的边界在哪
2.1 JDBC-ODBC 桥的工作原理
JSP 本身不直接认识 ACCESS 数据库文件,它需要通过 JDBC 驱动发出 SQL 请求,再由驱动把请求转成 ACCESS 能理解的格式。这套资源里用的驱动是sun.jdbc.odbc.JdbcOdbcDriver,它属于 JDBC-ODBC 桥驱动,原理是让 Java 程序通过 JDBC API 调用 ODBC 接口,再由 ODBC 去访问 ACCESS 数据库。你可以把它理解成一个翻译官:JSP 说 JDBC 语言,ODBC 说 Windows 数据库通用语言,ACCESS 说自己的方言,桥驱动在中间做两层转换。
JSP 页面 → JDBC API → JDBC-ODBC 桥驱动 → ODBC 驱动管理器 → Access ODBC Driver → test.mdb这种方案的优点是配置简单,不需要额外下载第三方驱动 JAR 包,JDK 1.8 以前的版本自带桥驱动类。缺点是性能一般,而且 JDK 1.8 之后 Oracle 移除了这个桥驱动,这一点后面会在避坑章节详细讲。至于代码里的Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"),它的作用是让 JVM 加载驱动类到内存中注册,这样DriverManager.getConnection()才能识别到可用的驱动。
2.2 连接字符串参数逐个拆解
连接字符串是整段代码里最需要理解的部分,资源里给出的写法是:
String url = "jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=" + dbpath;这里的参数含义分别是:
| 参数 | 值 | 作用 |
|---|---|---|
jdbc:odbc: | 固定前缀 | 告诉 DriverManager 走 JDBC-ODBC 桥 |
Driver={Microsoft Access Driver (*.mdb)} | ODBC 驱动名称 | 指定 Windows 自带的 ACCESS 驱动 |
DBQ= | 数据库物理路径 | 指定 .mdb 文件的绝对路径 |
注意Driver=后面的花括号不能省略,而且驱动名称严格遵守,*.mdb里的星号也是固定写法,不能写成*.mdb或者去掉星号,否则 ODBC 驱动管理器找不到对应的驱动。另外,DBQ参数后面跟的是数据库文件的物理磁盘路径,不是相对路径,这就是为什么资源里要用application.getRealPath(spath)把相对路径转换成物理路径。
这里有一个容易混淆的点:有的教程让你在 ODBC 数据源管理器里先建立一个系统 DSN,然后把连接字符串写成jdbc:odbc:test这种形式。那是另一种连接方式,本资源用的是 DSN-less 连接,好处是不需要预先配置数据源,直接把驱动名称和数据库路径写进连接字符串里,换一台机器部署时少一个配置步骤,但代价是路径硬编码在代码中,迁移时要同步修改。
2.3 JDK 版本与驱动可用性的硬边界
JDBC-ODBC 桥驱动从 JDK 1.2 开始提供,到 JDK 8 仍然能用,但从 JDK 9 开始被移除。如果你用的是 JDK 8 或更早版本,Class.forName("sun.jdbc.odbc.JdbcOdbcDriver")可以正常执行;如果你用的是 JDK 9 以上,运行时会直接抛出ClassNotFoundException: sun.jdbc.odbc.JdbcOdbcDriver,这不是你代码写错了,而是 JDK 里根本没有这个类了。
配套的 Tomcat 版本也需要匹配。资源里写的是 Tomcat 6.0,那个年代主流搭配是 JDK 1.5 或 1.6。如果你手头是 Tomcat 9 + JDK 8,代码还能跑,但要注意 Tomcat 9 要求 JDK 8 及以上,而 JDK 8 又恰好是最后一个自带桥驱动的版本,所以这个组合是当前条件下能跑通的老方案天花板。更高版本的组合就不建议尝试了,除非你换用第三方驱动,这部分在最后一章会给出替代方案。
3. 建库与部署:从 test.mdb 到 Tomcat data 目录的完整操作
3.1 创建 ACCESS 数据库和 username 表
打开 Microsoft Access,新建一个空白数据库,命名为test.mdb,保存到你能找到的任意位置,稍后要拷贝到 Tomcat 目录下去。数据库创建好之后,需要建立一张名为username的表。在 Access 里选择「创建」→「表设计」,进入表结构设计视图,添加两个字段:
| 字段名 | 数据类型 | 说明 |
|---|---|---|
| uid | 文本 | 用户名,长度建议设为 20 |
| pwd | 文本 | 密码,长度建议设为 20 |
两个字段都是文本型,这是资源正文里明确要求的。注意 Access 默认会生成一个ID主键字段,如果你不需要可以删掉,也可以保留,不影响查询。保存表时命名为username,Access 会提示是否创建主键,选「否」即可,因为uid和pwd本身没有唯一性约束的要求。
建完表之后,随手录入几条测试数据,比如:
uid=admin, pwd=123456 uid=test, pwd=abc123这一步很重要,不然 JSP 页面查询出来是空结果,你还要纠结是代码错了还是表里没数据。
3.2 数据库文件放置位置的逻辑
资源里要求把test.mdb放到 Tomcat 安装目录下的webapps\ROOT\data文件夹中,例如C:\Program Files\Apache Software Foundation\Tomcat 6.0\webapps\ROOT\data。为什么是这个位置?因为 Tomcat 默认把webapps\ROOT作为根 Web 应用的发布目录,放在它下面的文件可以通过 URL 直接访问,而 JSP 代码里application.getRealPath("data/test.mdb")拿到的物理路径就是相对于这个根目录解析的。
webapps\ROOT\ ├── index.jsp ├── JDBCAccess.jsp └── data\ └── test.mdb如果你把数据库文件放在webapps\ROOT之外,比如放在 D 盘某个目录,那么application.getRealPath()就解析不到这个路径,必须在代码里硬编码绝对路径,类似String dbpath = "D:/test.mdb"。这样做不是不行,但会降低部署时的灵活性,换一台机器就要改代码。
实操步骤是:先在webapps\ROOT下新建一个data文件夹,再把刚才创建的test.mdb文件复制进去。如果你的 Tomcat 安装路径跟资源里不一致,不要照抄,找到你自己的 Tomcat 根目录就行。这一步有一个常见翻车点:有人把数据库文件放到了webapps\ROOT\WEB-INF下面,以为更安全,实际上application.getRealPath("data/test.mdb")按相对路径找文件时只认webapps\ROOT\data这种目录结构,放了别处就要改代码路径,完全没必要自找麻烦。
3.3 Access 数据库文件锁与并发注意
ACCESS 是文件型数据库,JSP 程序通过 ODBC 读取 .mdb 文件时,Access 引擎会对文件加锁。如果此时你刚好在 Access 软件里打开了同一个数据库文件,JSP 程序读数据时可能会报「文件正被另一用户使用」或者「无法打开数据库」。这不是代码问题,是文件级并发冲突。
规范做法是:测试阶段,确认 Access 软件里已经关闭了test.mdb,再启动 Tomcat 访问 JSP 页面。生产环境更不应该让 Access 软件直接打开正在被 Web 程序使用的数据库文件,这只会在并发读写时制造更多麻烦。另外,.ldb文件是 Access 的锁文件,你会在 data 目录下看到它自动生成,属正常现象,别手贱去删它——删了之后 Tomcat 里的程序正在持有连接时,可能导致数据库状态异常。
4. JSP 代码逐段拆解:每一行的作用你都该知道
4.1 完整代码与分块说明
资源里提供了完整的JDBCAccess.jsp文件,我们把它按功能块拆开来看。第一段是页面指令和编码声明:
<%@ page contentType="text/html; charset=gb2312" language="java" import="java.sql.*"%> <meta http-equiv="Content-Type" content="text/html; charset=gb2312">这一行的import="java.sql.*"导入了 JDBC 所需的全部接口和类,包括Connection、Statement、ResultSet、DriverManager,没有这个导入,后面所有数据库相关代码都会报编译错误。contentType设置页面输出编码为gb2312,这是老项目的典型写法,适合中文 Windows 环境。但要注意,如果你的 JSP 文件本身是以 UTF-8 编码保存的,这里却声明成 gb2312,页面输出中文时可能乱码。保持一致的原则是:文件保存编码 = 页面声明编码。我一般建议新建文件时就用 gb2312 编码保存,或者全部改成 UTF-8,别混搭。
第二段是连接初始化代码,也就是整个资源的核心:
try { String spath = "data/test.mdb"; String dbpath = application.getRealPath(spath); String user = ""; String url = "jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=" + dbpath; Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); Connection conn = DriverManager.getConnection(url); Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);这段代码的顺序是固定的:先确定数据库路径,再拼连接字符串,然后加载驱动,最后建立连接。你可能会问user和密码为什么是空的,因为 ACCESS 数据库文件本身可以不设用户名密码,ODBC 驱动也不做认证,所以DriverManager.getConnection(url)只需要一个参数就够了。如果你在 Access 里给数据库设置了密码,连接字符串要改成Driver={Microsoft Access Driver (*.mdb)};DBQ=路径;PWD=密码这种形式,但 ODBC 方式下密码机制比较脆弱,建议测试环境就别折腾了。
conn.createStatement里的两个参数值得解释一下。ResultSet.TYPE_SCROLL_SENSITIVE表示结果集支持来回滚动,ResultSet.CONCUR_UPDATABLE表示结果集可以更新,这是最灵活但也是开销最大的组合。对于你现在只是查询数据来说,这两个参数完全多余,反而在某些 ODBC 驱动版本下会触发「结果集类型不受支持」的异常。更稳妥的写法是:
Statement stmt = conn.createStatement();参数缺省时是TYPE_FORWARD_ONLY和CONCUR_READ_ONLY,性能更好,兼容性也更好。这是资源里第一个值得你动手改的地方,改成这样至少能避开一部分奇怪报错。
第三段是查询与输出:
String sql = "select * from username"; ResultSet rs = stmt.executeQuery(sql); while(rs.next()) { out.print("用户名:" + rs.getString("uid")); out.print(" 密码:" + rs.getString("pwd") + "<br>"); } out.print("<br>恭喜你!数据库连接成功!"); rs.close(); stmt.close(); conn.close();这段逻辑不复杂:executeQuery执行查询并返回结果集,while(rs.next())循环逐行读取,getString("uid")取出当前行的 uid 字段值。关闭顺序是从结果集到语句再到连接,倒着关回去,这个顺序不能乱。资源里没有处理如果username表不存在的情况,异常会直接跳转到 catch 块打印错误信息,这在你调试时反而是好事,能看到具体报错内容。
第四段是异常处理:
} catch(Exception e) { out.print("数据库连接错误!,错误信息如下:<br>"); out.print(e.getMessage()); }这里有一个体验问题:出错时页面只显示异常消息,不显示堆栈信息。调试阶段建议临时改成e.printStackTrace(),把完整堆栈输出到 Tomcat 控制台,排查起来方便得多。定位完问题之后再改回来或者直接保留 printStackTrace 也没问题,反正老项目也不讲究优雅降级。
4.2 部署与访问步骤
把JDBCAccess.jsp文件保存到webapps\ROOT目录下,确保文件名后缀是.jsp,大小写不影响 Tomcat 识别。然后启动 Tomcat,打开浏览器访问:
http://localhost:8080/JDBCAccess.jsp如果一切正常,页面会先输出 username 表中的所有记录,然后输出「恭喜你!数据库连接成功!」。如果数据库文件放错位置或者表名不对,页面会显示「数据库连接错误!」以及具体异常信息。这一步能跑通,就说明整条链路是通的:Tomcat 能读到 JSP 文件,JSP 能加载桥驱动,ODBC 能识别 ACCESS 文件,SQL 查询能正常返回。
4.3 路径解析的两种常见写法
资源里用application.getRealPath(spath)把相对路径转成物理路径,这是 JSP 内置对象application的常见用法。还有一种等价写法是application.getRealPath("/data/test.mdb"),路径前面多一个斜杠,表示从 Web 应用根目录开始解析。两种写法解析出来的物理路径一模一样,但如果你在路径前面漏了斜杠,某些 Tomcat 版本下解析结果会出现偏差。
另外一个容易出问题的地方是路径分隔符。Windows 下物理路径是C:\Program Files\Apache Software Foundation\Tomcat 6.0\webapps\ROOT\data\test.mdb,但 Java 字符串里反斜杠需要转义,写成"C:\\Program Files\\..."太罗嗦,而且application.getRealPath()返回的路径已经自带正确分隔符,你不需要手工拼路径。连接字符串里DBQ=后面直接拼这个返回值即可,拼接时用加号连接字符串:
String url = "jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=" + dbpath;注意DBQ=后面没有空格,路径中间如果出现空格(比如Program Files),ODBC 驱动能够正常处理,不需要加引号包裹——这一点跟某些老教程里说的「路径含空格要加引号」不一样,实测过不加引号也能跑通。
5. 避坑与常见问题:JSP 连 ACCESS 的十个典型翻车现场
5.1 现象:ClassNotFoundException: sun.jdbc.odbc.JdbcOdbcDriver
原因:JDK 9 及以上版本移除了 JDBC-ODBC 桥驱动,Class.forName()加载不到这个类。解决:换用 JDK 8 或更早版本运行 Tomcat,或者改用 UCanAccess 第三方 JDBC 驱动替代桥驱动。从 Tomcat 的启动脚本catalina.bat里能看到当前使用的 JAVA_HOME,确认一下是不是指向了 JDK 9+。
5.2 现象:[Microsoft][ODBC 驱动程序管理器] 未发现数据源名称并且未指定默认驱动程序
原因:连接字符串里的驱动名称写错了,或者当前系统是 64 位,而 Tomcat 是 32 位。解决:检查Driver={Microsoft Access Driver (*.mdb)}是否完全一致,特别注意花括号和星号。64 位系统上,如果 Tomcat 是 32 位的,ODBC 驱动管理器加载的是 32 位版本的驱动,而 Access 驱动可能是 64 位的,两边对不上就会报这个错。解决方向是保持 Tomcat 位数和 Access 驱动位数一致,或者确认系统里确实安装了对应的 Access Database Engine 驱动。
5.3 现象:java.sql.SQLException: [Microsoft][ODBC Microsoft Access Driver] 找不到文件
原因:DBQ=后面拼出来的路径不对,application.getRealPath()返回 null 或者指向了不存在的位置。解决:在代码里临时加上out.print(dbpath),把实际解析出来的完整路径打印到页面上,看看这个路径指向的文件是否真实存在。最常见的情况是data文件夹没有创建,或者test.mdb没有真正放到webapps\ROOT\data下面。
5.4 现象:页面中文乱码
原因:JSP 文件保存编码和contentType声明的编码不一致。解决:如果文件用 UTF-8 保存而声明是gb2312,中文输出必定乱码。把页面声明改成 UTF-8,或者把文件另存为 ANSI/gb2312 编码,二选一,保持一致即可。
5.5 现象:ResultSet.TYPE_SCROLL_SENSITIVE不被支持
原因:部分 ODBC Access 驱动对可滚动、可更新的结果集支持不完整,导致createStatement时抛异常。解决:直接用conn.createStatement()不带参数,让结果集使用默认的前向只读模式,查询功能不受任何影响。
5.6 现象:Tomcat 已经启动但访问页面提示 404
原因:JSP 文件没有放在webapps\ROOT下,而是放到了别的 Web 应用目录里。解决:确认浏览器访问的 URL 和应用实际部署的目录一致。如果放在了webapps\demo\JDBCAccess.jsp,访问路径就应该是http://localhost:8080/demo/JDBCAccess.jsp。
5.7 现象:数据库文件被占用导致无法访问
原因:Access 软件打开了同一个.mdb文件,文件级锁冲突。解决:关闭 Access 软件,或者确认没有其他进程持有该数据库文件的句柄。Windows 下可以打开任务管理器查看是否有MSACCESS.EXE进程在运行。
5.8 现象:application.getRealPath()返回 null
原因:Tomcat 的部署方式导致没有解压后的真实目录。比如使用 WAR 包部署时,Tomcat 可能直接用压缩包运行,getRealPath就无法正确解析。解决:改用绝对路径硬编码,或者把数据库文件放到 Tomcat 公共目录下,配合外部路径访问。
5.9 现象:页面提示「未找到可加载的驱动程序」
原因:Class.forName()这行代码没有被执行到,或者驱动类名拼写错误。解决:检查sun.jdbc.odbc.JdbcOdbcDriver拼写是否完整,注意大小写敏感,O 和 D 都是大写。
5.10 现象:Tomcat 启动正常但页面访问极慢
原因:ODBC 桥驱动性能本身有限,加上每次请求都重新建立物理连接,耗时明显。解决:如果只是课设或 Demo 范围,可以接受这个性能;如果要提高响应速度,最简单的做法是减少数据库连接次数,比如把多条操作合并到一次连接里完成,或者考虑切换到其他数据库方案。
6. 验证与进阶:如何确认连接可靠,以及往新 JDK 迁移的两条出路
6.1 从抓取错误到参数调优的验证路径
当页面报错时,第一件事不是改代码,而是把错误信息完整抓出来。把 catch 块里的out.print(e.getMessage())临时改成e.printStackTrace(),然后去看 Tomcat 的logs\catalina.out或控制台输出,堆栈信息里能精确指出是哪一行代码出错、底层异常是什么。这是排查 JSP 连接数据库问题最直接的手段。
连接成功后,可以用一个简单方法验证数据库操作的完整性:在页面上追加一个插入操作,往username表里写入一条新记录,然后刷新页面查询,看是否能读回这条数据。这个验证能确认不只是查询可用,写入同样可用,对后续做增删改查功能有参考价值。代码结构如下:
String insertSql = "insert into username (uid, pwd) values ('hello', 'world')"; stmt.executeUpdate(insertSql);注意这里要用executeUpdate而不是executeQuery,后者只处理 select 查询。执行完后去 Access 里打开表,可以看到新记录。
6.2 老方案的新代餐:UCanAccess 驱动的迁移路线
如果你的机器上没有 JDK 8,或者不想被sun.jdbc.odbc的兼容性问题卡住,可以改用 UCanAccess 驱动,它在 Maven 中央仓库里有现成的ucanaccess依赖,配合commons-lang和hsqldb两个辅助 JAR 包。连接字符串变成:
String url = "jdbc:ucanaccess://" + dbpath; Class.forName("net.ucanaccess.jdbc.UcanaccessDriver"); Connection conn = DriverManager.getConnection(url);这个驱动是纯 Java 实现,不依赖 ODBC,因此支持 JDK 8、11、17 乃至更高版本,而且性能比桥驱动好。代价是需要引入三个 JAR 包到WEB-INF\lib目录下,配置步骤多一点,但长期维护角度看是值得的。如果你的项目不是必须用旧代码,我的建议是优先考虑 UCanAccess,把资源里的桥接代码当作理解原理的起点,而不是最终方案。
6.3 把连接参数抽到配置文件的习惯
从这套资源里延伸出来的一个好习惯是:不要硬编码数据库路径和连接字符串。把dbpath、user、pwd、连接 URL 模板放到webapps\ROOT\WEB-INF\classes\db.properties文件里,JSP 里用java.util.Properties读出来。这样换数据库文件或者换机器部署时只改配置文件,不用动 JSP 源码。
Properties props = new Properties(); String configPath = application.getRealPath("/WEB-INF/classes/db.properties"); props.load(new FileInputStream(configPath)); String dbpath = application.getRealPath(props.getProperty("db.path")); String url = "jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=" + dbpath;对应配置文件内容:
db.path=data/test.mdb db.user= db.password=这个习惯在项目变大后价值明显。当你有三五个 JSP 页面都要访问数据库时,改一处配置比逐个文件查字符串要省太多时间。我自己以前维护一个老课设项目时,就是吃了硬编码的亏,数据库文件换了个目录,结果十几个 JSP 页面里每个都要改路径,改完还有可能漏掉一两个。从那以后我每次写 JSP 连接数据库,都强制把连接参数抽到 properties 文件里,路径统一通过application.getRealPath解析,从来没有再为路径问题折腾过。希望帮到你。
本文还有配套的精品资源,点击获取