最近一个新项目准备使用SpringBoot,因为SpringBoot开发配置简单些。但由于公司部署流程的原因,测试和生产环境需要将代码打成WAR包部署到Tomcat下,并且数据库连接使用JNDI数据源方式配置Tomcat里面。
这种部署方式本没有问题,但是在本地环境我们用main方式启动的SpringBoot时就遇到问题,由于Tomcat是以内核的方式嵌入在SpringBoot里面的,那怎样配置JNDI数据源呢?
SpringBoot里使用JNDI数据源很简单,只需在application.properties文件中配置一下就可以了,如:
# JNDI数据源。开发环境在代码中配置,测试、生产在容器中配置。
spring.datasource.jndi-name=java:comp/env/jdbc/timcore/DefaultDS
测试和生成环境,以WAR包方式部署在Tomcat里的情况,需要在Tomcat的conf/context.xml文件添加配置,如:
<Resource
name="jdbc/timcore/DefaultDS"
url="jdbc:postgresql://30.31.0.14:7523/timc"
username="timcopr"
password="123456"
type="javax.sql.DataSource"
auth="Container"
driverClassName="org.postgresql.Driver"
maxIdle="30"
maxWait="10000"
maxActive="100"
/>
本地以main方式启动的需要修改Tomcat内核,打开JNDI数据源,并配置。比如我们项目是dev环境才是Main方式启动,则需要:
1,新增application-dev.properties文件:
# DEV环境才会加载
DataSource.jndiName=jdbc/timcore/DefaultDS
DataSource.auth=Container
DataSource.driverClassName=org.postgresql.Driver
DataSource.url=jdbc:postgresql://30.31.0.14:7523/timc
DataSource.username=timcopr
DataSource.pwd=123456
DataSource.maxActive=100
DataSource.maxIdle=30
DataSource.maxWait=10000
2,创建一个PropConfig类,接收配置:
@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "DataSource")
public class DataSourcePropConfig {
private String jndiName;
private String auth;
private String driverClassName;
private String url;
private String username;
private String pwd;
private String maxActive;
private String maxIdle;
private String maxWait;
}
3,代码的方式修改配置,加入数据源:
@Configuration
public class MyWebMvcConfigurerAdapter extends WebMvcConfigurerAdapter {
@Resource
private DataSourcePropConfig dataSourcePropConfig;
// 开发环境手工添加数据源。测试、生产环境部署在容器中,在容器中配置数据源。
@ConditionalOnProperty(name = "spring.profiles.active", havingValue = "dev")
@Bean
public TomcatEmbeddedServletContainerFactory servletContainerFactory() {
return new TomcatEmbeddedServletContainerFactory() {
@Override
protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(Tomcat tomcat) {
tomcat.enableNaming(); // 打开JNDI数据源
return super.getTomcatEmbeddedServletContainer(tomcat);
}
@Override
protected void postProcessContext(Context context) {
ContextResource resource = new ContextResource();
resource.setType(DataSource.class.getName());
resource.setName(dataSourcePropConfig.getJndiName());
resource.setAuth(dataSourcePropConfig.getAuth());
resource.setProperty("driverClassName", dataSourcePropConfig.getDriverClassName());
resource.setProperty("url", dataSourcePropConfig.getUrl());
resource.setProperty("username", dataSourcePropConfig.getUsername());
resource.setProperty("password", dataSourcePropConfig.getPwd());
// 连接池配置,和测试、生产配置一致。
resource.setProperty("maxActive", dataSourcePropConfig.getMaxActive()); // 最大连接数
resource.setProperty("maxIdle", dataSourcePropConfig.getMaxIdle()); // 空闲连接数
resource.setProperty("maxWait", dataSourcePropConfig.getMaxWait()); // 最大等待时间
context.getNamingResources().addResource(resource);
}
};
}
}
这样同一份代码就可以兼容两种方式了。