JNDI查找数据源核心是容器管理连接池、代码仅按名查找,关键在名称匹配配置与环境就绪;必须在context.xml定义Resource、web.xml声明resource-ref,并用java:comp/env/前缀lookup,驱动需置于$CATALINA_HOME/lib。

Java JDBC 通过 JNDI 查找数据源,核心是让应用服务器(如 Tomcat、WildFly)管理连接池,代码只负责按名称查找 DataSource 对象,不硬编码数据库地址、用户名等敏感信息。关键不在“怎么写 lookup 语句”,而在于“名字是否匹配容器配置”和“环境是否就绪”。
必须配置好服务器端资源绑定
JNDI 不是内存 Map,它依赖容器启动时完成的绑定。没配置,lookup 必然失败。
- 在 Tomcat 中,通常在
META-INF/context.xml(应用级)或conf/server.xml(全局)里定义<Resource>,例如:
type="javax.sql.DataSource"
driverClassName="com.mysql.cj.jdbc.Driver"
url="jdbc:mysql://localhost:3306/mydb?useSSL=false"
username="root" password="1234"
maxTotal="20" maxIdle="10" minIdle="5" />
注意:name 属性值就是后续 lookup 的路径后半段。
- 同时需在
WEB-INF/web.xml中声明引用,告诉容器“我这个应用要用这个资源”:
<res-ref-name>jdbc/myapp</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
这一步不是可选的,否则 Tomcat 不会把该资源注入到当前应用的私有命名上下文。
立即学习“Java免费学习笔记(深入)”;
代码中使用标准 JNDI 查找路径
lookup 字符串必须带前缀,不能只写 "jdbc/myapp"。
- Web 应用中,绝大多数情况应使用组件私有上下文:java:comp/env/jdbc/myapp
- 直接写
"jdbc/myapp"或"java:jdbc/myapp"都会抛NamingException - 完整查找示例:
DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/myapp");
Connection conn = ds.getConnection();
不需要手动设置 INITIAL_CONTEXT_FACTORY —— Web 容器已内置适配,显式设置反而可能破坏默认行为。
驱动和类路径要放对位置
Tomcat 管理数据源,意味着驱动加载由容器完成,不是你的应用类加载器负责。
- JDBC 驱动 JAR(如
mysql-connector-java-8.0.33.jar)必须放在$CATALINA_HOME/lib目录下,不能只丢在WEB-INF/lib - 如果放错位置,会出现
ClassNotFoundException或连接时提示 “No suitable driver” - Tomcat 9+ 推荐使用
com.mysql.cj.jdbc.Driver;旧版用com.mysql.jdbc.Driver(已弃用)
常见失败原因和验证方法
lookup 失败,90% 是配置路径或部署问题,不是代码逻辑错。
-
查不到名字:确认
context.xml的name和web.xml的res-ref-name完全一致(含大小写、空格) - java:comp/env 无效:确保代码运行在容器管理的 Servlet/Filter/Listener 中;在普通 Java main 方法里调用会失败
-
想验证是否绑定成功:启动 Tomcat 后访问
http://localhost:8080/manager/html(需配置 manager 角色),查看 JNDI Resources 页面 - 日志提示 NamingException: Name jdbc/myapp is not bound:说明绑定未生效,检查 context.xml 是否被正确加载(看 Tomcat 启动日志是否有 Resource 配置信息)


















