springboot(3) 数据源配置

该文假定您已经知道了如何搭建springboot项目,如果需要了解如何搭建springboot项目可以参考如下文章:

springboot(1) spring项目的搭建

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配置,那么需要注意以下几点。

  1. springboot运行代码中需初始化jndi值。
  2. 测试运行需要绑定jndi实体。
  3. 代码配置如果在打包后无法使用,打包后的程序获取的是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的方式进行开发和测试。

文章的项目源码:

springboot(3) 数据源配置

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值