该文假定您已经知道了如何搭建springboot项目,如果需要了解如何搭建springboot项目可以参考如下文章:
springboot(2) springMVC(web)项目的搭建
对于spring/springboot数据源配置,常见的有直接配置数据库连接信息和通过jndi进行配置。
首先,需要添加驱动依赖(这里我们使用的是sqlite数据库):
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
</dependency>
其次,我们需要添加相关的依赖(如果是使用了hibernate或者mybatis,那么该配置不需要):
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
在springboot中配置数据源我们只需新建配置新建一个数据源即可:
package com.test.db.conf;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
@Configuration
public class DataSourceConfig {
@Bean
public DataSource dataSource() {
DriverManagerDataSource ds = new DriverManagerDataSource("jdbc:sqlite:dev.db");
ds.setDriverClassName("org.sqlite.JDBC");
return ds;
}
}
配置完成后测试代码:
package com.test.service.ds;
import javax.sql.DataSource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.test.App;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = App.class)
public class DataSourceTest {
@Autowired
private DataSource dataSource;
@Test
public void testDataSource() {
LoggerFactory.getLogger(getClass()).info(dataSource.toString());
}
}
运行结果如下:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.3.RELEASE)
2019-08-28 13:30:17.435 INFO 5412 --- [ main] com.test.service.ds.DataSourceTest : Starting DataSourceTest on DEVPNLN15YF127 with PID 5412 (started by c_yinjicheng-002 in E:\Users\c_yinjicheng-002\bqpt_boot\springboot-db)
2019-08-28 13:30:17.436 INFO 5412 --- [ main] com.test.service.ds.DataSourceTest : No active profile set, falling back to default profiles: default
2019-08-28 13:30:19.860 INFO 5412 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2019-08-28 13:30:20.388 INFO 5412 --- [ main] com.test.service.ds.DataSourceTest : Started DataSourceTest in 3.724 seconds (JVM running for 4.635)
2019-08-28 13:30:20.574 INFO 5412 --- [ main] com.test.service.ds.DataSourceTest : org.springframework.jdbc.datasource.DriverManagerDataSource@2d2acd89
2019-08-28 13:30:20.703 INFO 5412 --- [ Thread-2] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'
证明数据源配置为成功的。
数据源配置完成后,spring默认会配置JdbcTemplate。具体使用如下:
@Autowired
private JdbcTemplate jdbcTemplate;
@Test
public void testJdbcTemplate() {
LoggerFactory.getLogger(getClass()).info(jdbcTemplate.toString());
}
运行结果如下:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.3.RELEASE)
2019-08-28 13:36:34.934 INFO 832 --- [ main] com.test.service.ds.DataSourceTest : Starting DataSourceTest on DEVPNLN15YF127 with PID 832 (started by c_yinjicheng-002 in E:\Users\c_yinjicheng-002\bqpt_boot\springboot-db)
2019-08-28 13:36:34.936 INFO 832 --- [ main] com.test.service.ds.DataSourceTest : No active profile set, falling back to default profiles: default
2019-08-28 13:36:37.214 INFO 832 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2019-08-28 13:36:37.727 INFO 832 --- [ main] com.test.service.ds.DataSourceTest : Started DataSourceTest in 3.653 seconds (JVM running for 4.61)
2019-08-28 13:36:37.921 INFO 832 --- [ main] com.test.service.ds.DataSourceTest : org.springframework.jdbc.core.JdbcTemplate@22bb5646
2019-08-28 13:36:38.132 INFO 832 --- [ Thread-2] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'
当然如果是多数据源,则无法默认JdbcTemplate,这是如果我们需要使用,则需要制定初始化JdbcTemplate,具体的初始化代码如下:
@Bean
public JdbcTemplate jdbcTemplate(@Qualifier("dataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
测试结果同上。
除了使用直接配置外,我们也可以使用jndi进行配置,如果是使用jndi配置,那么需要注意以下几点。
- springboot运行代码中需初始化jndi值。
- 测试运行需要绑定jndi实体。
- 代码配置如果在打包后无法使用,打包后的程序获取的是tomcat的jndi配置。
接下来我们就看下jndi是如何配置的:
首先,是程序中的配置:
@Bean
public ServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
@Override
protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
tomcat.enableNaming();
return super.getTomcatWebServer(tomcat);
}
@Override
protected void postProcessContext(Context context) {
ContextResource resource2 = new ContextResource();
resource2.setName("ds2");
resource2.setType(DataSource.class.getName());
resource2.setProperty("driverClassName", "org.sqlite.JDBC");
resource2.setProperty("url", "jdbc:sqlite:dev2.db");
context.getNamingResources().addResource(resource2);
super.postProcessContext(context);
}
};
return tomcat;
}
@Bean
public DataSource dataSource2() {
JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
dataSourceLookup.setResourceRef(true);
return dataSourceLookup.getDataSource("java:comp/env/ds2");
}
@Bean
public JdbcTemplate jdbcTemplate2(@Qualifier("dataSource2") DataSource dataSource2) {
return new JdbcTemplate(dataSource2);
}
测试程序中需要初始化绑定:
@BeforeClass
public static void bindJndi() throws IllegalStateException, NamingException {
SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
DriverManagerDataSource dataSource2 = new DriverManagerDataSource();
dataSource2.setDriverClassName("org.sqlite.JDBC");
dataSource2.setUrl("jdbc:sqlite:dev2.db");
builder.bind("java:comp/env/ds2", dataSource2);
builder.activate();
}
测试代码如下:
@Autowired
private DataSource dataSource2;
@Autowired
private JdbcTemplate jdbcTemplate2;
@Test
public void testJndi() {
LoggerFactory.getLogger(getClass()).info(dataSource.toString());
LoggerFactory.getLogger(getClass()).info(jdbcTemplate.toString());
LoggerFactory.getLogger(getClass()).info(dataSource2.toString());
LoggerFactory.getLogger(getClass()).info(jdbcTemplate2.toString());
}
测试运行结果:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.3.RELEASE)
2019-08-28 14:27:44.096 INFO 2928 --- [ main] com.test.service.ds.DataSourceTest : Starting DataSourceTest on DEVPNLN15YF127 with PID 2928 (started by c_yinjicheng-002 in E:\Users\c_yinjicheng-002\bqpt_boot\springboot-db)
2019-08-28 14:27:44.115 INFO 2928 --- [ main] com.test.service.ds.DataSourceTest : No active profile set, falling back to default profiles: default
2019-08-28 14:27:46.716 INFO 2928 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2019-08-28 14:27:47.144 INFO 2928 --- [ main] com.test.service.ds.DataSourceTest : Started DataSourceTest in 3.734 seconds (JVM running for 4.786)
2019-08-28 14:27:47.344 INFO 2928 --- [ main] com.test.service.ds.DataSourceTest : org.springframework.jdbc.datasource.DriverManagerDataSource@1949309d
2019-08-28 14:27:47.345 INFO 2928 --- [ main] com.test.service.ds.DataSourceTest : org.springframework.jdbc.core.JdbcTemplate@5af97169
2019-08-28 14:27:47.345 INFO 2928 --- [ main] com.test.service.ds.DataSourceTest : org.springframework.jdbc.datasource.DriverManagerDataSource@2f112965
2019-08-28 14:27:47.345 INFO 2928 --- [ main] com.test.service.ds.DataSourceTest : org.springframework.jdbc.core.JdbcTemplate@99a78d7
2019-08-28 14:27:47.364 INFO 2928 --- [ Thread-2] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'
这里需要注意的是,如果是App.main中启动项目,需添加配置:application.properties,内容如下:
spring.jmx.enabled=false
同时需要添加依赖(该依赖只是运行时需要,打包时不需要该依赖):
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-dbcp</artifactId>
<version>8.5.28</version>
<scope>runtime</scope>
</dependency>
具体原因请参考:
同一个tomcat下部署2个springboot的war包出现InstanceAlreadyExistsException
另外,如果是在springboot2.x之前的版本,那么绑定jndi的代码如下:
import javax.naming.NamingException;
import javax.sql.DataSource;
import org.apache.catalina.Context;
import org.apache.catalina.startup.Tomcat;
import org.apache.tomcat.util.descriptor.web.ContextResource;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jndi.JndiObjectFactoryBean;
@Configuration
public class TomcatConfigs {
@Bean
public TomcatEmbeddedServletContainerFactory tomcatFactory() {
return new TomcatEmbeddedServletContainerFactory() {
@Override
protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(Tomcat tomcat) {
tomcat.enableNaming();
return super.getTomcatEmbeddedServletContainer(tomcat);
}
@Override
protected void postProcessContext(Context context) {
ContextResource resource = new ContextResource();
resource.setType(DataSource.class.getName());
resource.setName("j4s");
resource.setProperty("factory", "org.apache.tomcat.jdbc.pool.DataSourceFactory");
resource.setProperty("driverClassName", "com.mysql.jdbc.Driver");
resource.setProperty("url", "jdbc:mysql://localhost/test");
resource.setProperty("username", "java4s");
resource.setProperty("password", "java4s");
context.getNamingResources().addResource(resource);
}
};
}
@Bean
public DataSource jndiDataSource() throws IllegalArgumentException, NamingException {
JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
bean.setJndiName("java:/comp/env/j4s");
bean.setProxyInterface(DataSource.class);
bean.setLookupOnStartup(false);
bean.afterPropertiesSet();
return (DataSource) bean.getObject();
}
}
具体请参考:Spring Boot中怎么玩JNDI
上面的例子中可以看出,其实项目中可以同时使用直接配置和jndi两种配置的,但实际项目中,一般都是用jndi的方式进行开发和测试。
文章的项目源码: