Tomcat-Oracle JNDI连接疑问:仅WEB-INF/lib有ojdbc.jar为何可运行?
遗留Web应用Oracle JNDI连接问题解答
问题场景
我正在搭建一个遗留Web应用,遇到了一些问题:
- 应用的
WEB-INF/lib目录下打包了ojdbc.jar,Tomcat的context.xml中配置了JNDI数据源,采用Oracle OCI连接方式(Windows系统),配置代码如下:
<Resource name="jdbc/MainSource" auth="Container" type="javax.sql.DataSource" driverClassName="oracle.jdbc.driver.OracleDriver" url="jdbc:oracle:oci:@username/password@tnsinstance" validationQuery="SELECT sysdate from DUAL;" jdbcInterceptors="ConectionState" />
- 发现Tomcat的
$CATALINA_HOME/lib目录下没有ojdbc.jar,存在两个疑问:- 仅
WEB-INF/lib目录下存在ojdbc.jar时,应用为何能通过JNDI正常运行? - OCI连接是否能让JNDI无需提供
ojdbc.jar?(我的理解是不行,因为Tomcat仍需查找driverClassName的实现)
- 仅
补充说明:服务器已安装Oracle客户端,其安装目录下有ojdbc.jar,且ORACLE_HOME已注册,该JAR应处于$PATH中,但根据Tomcat JNDI文档,我认为即使是Oracle OCI连接,Tomcat也不会从操作系统的$PATH中获取ojdbc.jar。
问题解答
1. 仅WEB-INF/lib存在ojdbc.jar时JNDI正常运行的原因
这是由Tomcat的类加载机制决定的:
- Tomcat为每个Web应用分配独立的应用类加载器,该加载器会优先加载应用自身
WEB-INF/lib和WEB-INF/classes目录下的类与资源。 - 如果你的JNDI数据源是应用级配置(比如配置在应用的
META-INF/context.xml中,或者在Tomcat全局server.xml的Host节点下关联了当前应用的Context配置),Tomcat会使用该应用的类加载器去加载driverClassName指定的OracleDriver类,自然能找到WEB-INF/lib下的ojdbc.jar。 - 只有全局级别的JNDI数据源(配置在Tomcat全局
context.xml中,供所有应用共享)才需要将ojdbc.jar放在$CATALINA_HOME/lib目录下,因为全局数据源由Tomcat的系统类加载器加载。
2. OCI连接不能替代ojdbc.jar的作用
你的理解是正确的,OCI连接并不能让JNDI无需ojdbc.jar:
- OCI只是JDBC连接Oracle的一种方式,它通过调用本地Oracle客户端的OCI原生库来建立数据库连接,但JDBC驱动的核心类(比如
oracle.jdbc.driver.OracleDriver)依然存在于ojdbc.jar中,Tomcat必须加载这个类才能完成数据源的初始化。 - Oracle客户端目录下的
ojdbc.jar不会被Tomcat自动识别,因为Tomcat的类加载器只会从预设的目录(如CATALINA_HOME/lib、应用WEB-INF/lib)加载JAR包,不会扫描操作系统的$PATH环境变量中的JAR文件。
内容的提问来源于stack exchange,提问作者Dreamer
相关产品推荐
相关产品推荐

