使用SpringBoot的主要思想是习惯大于配置。使用Java配置代替XML配置。
在实际应用开发过程中也会存在不得不添加配置文件的情况,例如集成其他框架或者需要配置一些中间件等,在这种情况下,就需要引入自定义的xml配置文件。
@SpringBootApplication会自动扫描当前包以及子包中的bean
模拟创建一个不和启动类在同一个包中的bean,编写spring配置文件由容器负责实例化。
package other;
public class OtherBean {
public OtherBean(){
System.out.println("我是有外部xml实例化的");
}
}
编写spring配置文件
在启动类上添加注解:
@ImportResource(locations= {“classpath:application-bean.xml”})
测试启动时,控制台会打印构造方法中输出的内容。
7.SpringBoot多数据源支持
实际项目中,可能不仅会面临单一数据源的状况,甚至还会遇到多数据源的状况。
使用DBCP、和Druid 数据源,连接MySql中不同的Database
创建2个Database
create database master; -- 主库 使用DBCP数据源
create database cluster; -- 从库 使用Druid数据源
添加依赖
org.springframework.boot
spring-boot-starter-parent
1.5.4.RELEASE
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-jdbc
commons-dbcp
commons-dbcp
mysql
mysql-connector-java
runtime
application.properties
spring.datasource.master.url=jdbc:mysql://localhost:3306/master
spring.datasource.master.username=root
spring.datasource.master.password=root
spring.datasource.master.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.master.type=org.apache.commons.dbcp.BasicDataSource
spring.datasource.cluster.url=jdbc:mysql://localhost:3306/cluster
spring.datasource.cluster.username=root
spring.datasource.cluster.password=root
spring.datasource.cluster.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.cluster.type=com.alibaba.druid.pool.DruidDataSource
创建一个类,设置数据源
@Configuration
public class DataSourceConfig {
@Bean(name ="masterDataSource")
@Primary
@ConfigurationProperties(prefix = "spring.datasource.master")
public DataSource masterDataSource() {
DataSource dataSource = new BasicDataSource();
return dataSource;
}
@Bean(name = "clusterDataSource")
@ConfigurationProperties(prefix = "spring.datasource.cluster")
public DataSource clusterDataSource() {
DataSource dataSource = new DruidDataSource();
return dataSource;
}
}
@Configuration
@Bean
@Primary众多相同的bean中,优先使用用@Primary注解的bean。同一个类型有多个实例,但我们需要注入一个的时候,我们必须采取措施,不然spring容器
会报错:…required a single bean, but 2 were found:…
有时候我们能保证同一个类型在spring容器中只有一个实例,有时候我们保证不了。这个时候@Primary注解就非常重要了
@ConfigurationProperties prefix 指定前缀和application.properties内容一致。读取内容,绑定到BasicDataSource 和 DruidDataSource的属性上。
测试
@SpringBootApplication
public class SpringBootDataSourceApplication {
public static void main(String[] args) throws SQLException {
ConfigurableApplicationContext context = SpringApplication.run(SpringBootDataSourceApplication.class,args);
DataSource master = context.getBean("masterDataSource",DataSource.class);
System.out.println(master.getClass().getName());
DataSource ds = context.getBean(DataSource.class);
System.out.println(ds.getClass().getName()); //会获取有@Primary设置的对象
DataSource cluster = context.getBean("clusterDataSource",DataSource.class);
System.out.println(cluster.getClass().getName());
}
}
如果持久层使用JDBC设计实现,需要在DataSourceConfig 类中添加获取JdbcTemplete的方法。需要指定JdbcTemplete是由哪个数据源提供的。
//创建由主库 主数据源提供的JdbcTemplete
@Bean(name = "masterJdbcTemplate")
public JdbcTemplate primaryJdbcTemplate(
@Qualifier("masterDataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
//创建由从库 从数据源提供的JdbcTemplete
@Bean(name = "clusterJdbcTemplate")
public JdbcTemplate secondaryJdbcTemplate(
@Qualifier("clusterDataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
在主库中创建表
create table master_user (id int primary key auto_increment,name varchar(200))
在从库中创建表
create table cluster_user (id int primary key auto_increment,name varchar(200))
分别建立MasterUser 和 ClusterUser 对应表
public class MasterUser {
private Integer id;
private String name;
}
public class ClusterUser {
private Integer id;
private String name;
}
建立MasterUserDao 和 ClusterUserDao 接口和实现类
public interface MasterUserDao {
MasterUser getUserById(Integer id);
}
public interface ClusterUserDao {
MasterUser getUserById(Integer id);
}
@Repository
public class MasterUserDaoImpl implements MasterUserDao {
@Autowired
@Qualifier("masterJdbcTemplate")//自动装配主库提供的JdbcTemplete
private JdbcTemplate jdbcTemplate;
@Override
public MasterUser getUserById(Integer id) {
List list = jdbcTemplate.query(
"select * from master_user where id = ?", new Object[] { id },
new BeanPropertyRowMapper(MasterUser.class));
if (list.size() > 0) {
return list.get(0);
}
return null;
}
}
@Repository
public class ClusterUserDaoImpl implements ClusterUserDao {
@Autowired
@Qualifier("clusterJdbcTemplate")//自动装配从库提供的JdbcTemplete
private JdbcTemplate jdbcTemplate;
@Override
public ClusterUser getUserById(Integer id) {
List list = jdbcTemplate.query(
"select * from cluster_user where id = ?", new Object[] { id },
new BeanPropertyRowMapper(ClusterUser.class));
if (list.size() > 0) {
return list.get(0);
}
return null;
}
}
启动类中添加测试代代码:
MasterUserDao mud = context.getBean(MasterUserDao.class);
System.out.println(mud.getUserById(1));
ClusterUserDao cud = context.getBean(ClusterUserDao.class);
System.out.println(cud.getUserById(1));
事务管理,使用单独的数据源的事务管理
在DataSourceConfig类中添加方法
@Bean(name="masterTransactionManager")
public PlatformTransactionManager masterTransactionManager(
@Qualifier("masterDataSource") DataSource masterDataSource) {
return new DataSourceTransactionManager(masterDataSource);
}
@Bean(name="clusterTransactionManager")
public PlatformTransactionManager clusterTransactionManager(
@Qualifier("clusterDataSource") DataSource clusterDataSource) {
return new DataSourceTransactionManager(clusterDataSource);
}
在需要事务绑定的方法上添加注解
@Transactional(value = “masterTransactionManager”)使用主库数据源的事务管理器
@Transactional(value = “clusterTransactionManager”)使用从库数据源的事务管理器
如果持久层使用MyBatis实现,需要由不同的数据源创建不同的SqlSessionFactory
添加mybatis-spring-boot-starter依赖
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.1.1
项目结构:
application.properties
同上
POJO设计Mapper接口设计同上
映射文件,注意Mapper代理开发时namespace的取值
主库对应数据源设置 MasterDataSourceConfig
//集成MyBatis
@Configuration
// 扫描 Mapper 接口并容器管理
@MapperScan(basePackages = MasterDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "masterSqlSessionFactory")
public class MasterDataSourceConfig {
// 精确到 master目录,以便跟其他数据源隔离
// 主库对应的mapper接口所在包
static final String PACKAGE = "com.hf.master.mapper";
// 主库对应的POJO所在包
static final String TYPEALIASES = "com.hf.master.pojo";
// 主库对应的mapper映射文件对应的位置
static final String MAPPER_LOCATION = "classpath:mybatis/master/mapper/*.xml";
// 设置主库,主数据源
@Bean(name = "masterDataSource")
@Primary
@ConfigurationProperties(prefix = "spring.datasource.master")
public DataSource
masterDataSource() {
DataSource dataSource = new BasicDataSource();
return dataSource;
}
@Bean(name = "masterSqlSessionFactory")
@Primary
public SqlSessionFactory masterSqlSessionFactory(
@Qualifier("masterDataSource") DataSource masterDataSource)
throws Exception {
final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(masterDataSource);
sessionFactory
.setMapperLocations(new PathMatchingResourcePatternResolver()
.getResources(MasterDataSourceConfig.MAPPER_LOCATION));
sessionFactory.setTypeAliasesPackage(TYPEALIASES);
return sessionFactory.getObject();
}
@Bean(name = "masterSqlSessionTemplate")
@Primary
public SqlSessionTemplate testSqlSessionTemplate(
@Qualifier("masterSqlSessionFactory") SqlSessionFactory masterSqlSessionFactory)
throws Exception {
return new SqlSessionTemplate(masterSqlSessionFactory);
}
// 事务管理器
@Bean(name = "masterTransactionManager")
public PlatformTransactionManager masterTransactionManager(
@Qualifier("masterDataSource") DataSource masterDataSource) {
return new DataSourceTransactionManager(masterDataSource);
}
}
从库对应数据源设置 ClusterDataSourceConfig
//集成MyBatis
@Configuration
// 扫描 Mapper 接口并容器管理
@MapperScan(basePackages = ClusterDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "clusterSqlSessionFactory")
public class ClusterDataSourceConfig {
// 精确到 cluster目录,以便跟其他数据源隔离
// 从库对应的mapper接口所在包
static final String PACKAGE = "com.hf.cluster.mapper";
// 从库对应的POJO所在包
static final String TYPEALIASES = "com.hf.cluster.pojo";
// 从库对应的mapper映射文件对应的位置
static final String MAPPER_LOCATION = "classpath:mybatis/cluster/mapper/*.xml";
// 设置主库,从数据源
@Bean(name = "clusterDataSource")
@ConfigurationProperties(prefix = "spring.datasource.cluster")
public DataSource clusterDataSource() {
DataSource dataSource = new DruidDataSource();
return dataSource;
}
@Bean(name = "clusterSqlSessionFactory")
public SqlSessionFactory clusterSqlSessionFactory(
@Qualifier("clusterDataSource") DataSource clusterDataSource)
throws Exception {
final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(clusterDataSource);
sessionFactory
.setMapperLocations(new PathMatchingResourcePatternResolver()
.getResources(ClusterDataSourceConfig.MAPPER_LOCATION));
sessionFactory.setTypeAliasesPackage(TYPEALIASES);
return sessionFactory.getObject();
}
@Bean(name = "clusterSqlSessionTemplate")
public SqlSessionTemplate testSqlSessionTemplate(
@Qualifier("clusterSqlSessionFactory") SqlSessionFactory clusterSqlSessionFactory)
throws Exception {
return new SqlSessionTemplate(clusterSqlSessionFactory);
}
// 事务管理器
@Bean(name = "clusterTransactionManager")
public PlatformTransactionManager clusterTransactionManager(
@Qualifier("clusterDataSource") DataSource clusterDataSource) {
return new DataSourceTransactionManager(clusterDataSource);
}
}
启动类
@SpringBootApplication
public class SpringBootDataSourceApplication {
public static void main(String[] args) throws SQLException {
ConfigurableApplicationContext context = SpringApplication.run(SpringBootDataSourceApplication.class,args);
MasterUserMapper mum = context.getBean(MasterUserMapper.class);
System.out.println(mum.getUserById(1));
ClusterUserMapper cum = context.getBean(ClusterUserMapper.class);
System.out.println(cum.getUserById(1));
}
}