Spring Boot配置WebLogic 12c JNDI数据源时Maven编译失败求助
你遇到的NoInitialContextException核心原因是:JNDI数据源依赖应用服务器(如Tomcat、JBoss)提供的上下文环境才能访问,而当前你的运行/编译环境没有提供这个JNDI上下文。
直接配置spring.datasource.url这类参数时,Spring Boot会自行创建DataSource Bean,完全不依赖外部容器;但切换到JNDI配置后,程序需要从容器的JNDI注册表中查找数据源,一旦没有容器提供这个环境,就会抛出找不到初始上下文的错误。
再看你的pom.xml,你排除了spring-boot-starter-tomcat,如果是打算打包成WAR部署到外部Tomcat,那本地用mvn spring-boot:run运行时,因为没有内嵌容器提供JNDI支持,自然会编译/运行失败。
根据你的使用场景,分两种情况处理:
场景1:打包成WAR部署到外部应用服务器(生产环境常用)
1. 调整pom.xml配置
首先确保项目是WAR打包方式,并将Tomcat依赖设为provided(避免打包时包含内嵌Tomcat):
<packaging>war</packaging> <!-- 恢复Tomcat依赖并设置为provided --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency>
2. 在外部服务器配置JNDI数据源
以Tomcat为例,需要在服务器端配置数据源:
- 编辑Tomcat的
conf/context.xml,添加数据源定义:
<Resource name="jdbc/Conn" auth="Container" type="javax.sql.DataSource" driverClassName="oracle.jdbc.driver.OracleDriver" url="jdbc:oracle:thin:@dbhost:1521/SERVICE" username="user" password="pass" maxTotal="20" maxIdle="10" maxWaitMillis="-1" />
- 编辑Tomcat的
conf/web.xml,添加资源引用:
<resource-ref> <description>Oracle Database Connection</description> <res-ref-name>jdbc/Conn</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref>
3. 修改Spring Boot启动类
让启动类继承SpringBootServletInitializer,适配外部容器部署:
@SpringBootApplication public class YourAppApplication extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(YourAppApplication.class); } public static void main(String[] args) { SpringApplication.run(YourAppApplication.class, args); } }
完成以上配置后,打包WAR部署到外部Tomcat,就能正常获取JNDI数据源了。
场景2:本地开发时用内嵌容器模拟JNDI(方便编译运行)
如果想在本地用mvn spring-boot:run测试JNDI配置,可以给内嵌Tomcat添加JNDI支持:
1. 恢复内嵌Tomcat依赖
如果之前排除了spring-boot-starter-tomcat,先取消排除(或者用Maven Profile区分开发/生产环境):
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <!-- 移除tomcat的exclusion --> </dependency>
2. 创建JNDI配置类
添加一个配置类,让内嵌Tomcat注册JNDI数据源:
@Configuration public class EmbeddedTomcatJndiConfig { @Bean public TomcatEmbeddedServletContainerFactory tomcatFactory() { return new TomcatEmbeddedServletContainerFactory() { @Override protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(Tomcat tomcat) { // 启用内嵌Tomcat的JNDI支持 tomcat.enableNaming(); return super.getTomcatEmbeddedServletContainer(tomcat); } @Override protected void postProcessContext(Context context) { // 注册JNDI数据源 ContextResource resource = new ContextResource(); resource.setName("jdbc/Conn"); resource.setType(DataSource.class.getName()); resource.setProperty("driverClassName", "oracle.jdbc.driver.OracleDriver"); resource.setProperty("url", "jdbc:oracle:thin:@dbhost:1521/SERVICE"); resource.setProperty("username", "user"); resource.setProperty("password", "pass"); context.getNamingResources().addResource(resource); } }; } }
这样本地启动时,内嵌Tomcat会自动创建JNDI上下文,mvn spring-boot:run就能正常编译运行了。
内容的提问来源于stack exchange,提问作者Gaspar Teixeira

