package com.creditcore.services.common.dataSource;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
/**
* springboot集成mybatis的基本入口
* 1)创建数据源(如果采用的是默认的tomcat-jdbc数据源,则不需要)
* 2)创建SqlSessionFactory
* 3)配置事务管理器,除非需要使用事务,否则不用配置
*/
@Configuration // 该注解类似于spring配置文件
// @MapperScan(basePackages = "com.xxx.firstboot.mapper")
@EnableConfigurationProperties(DataSourceConfiguration.class)
public class MyBatisConfig {
private static final Logger logger = LoggerFactory.getLogger(MyBatisConfig.class);
// @Autowired
// private Environment env;
// @Value("${info.build.name:Hello default}")
// private String projectName;
@Autowired
private DataSourceConfiguration dataSourceConfiguration;
// mybaits mapper xml搜索路径
private static final String MAPPER_LOCATION = "classpath:mapper/*.xml";
// 从cloud config上读取配置信息,生成数据源Map 定义bean :dataSources
@Bean
@Primary
@ConditionalOnMissingBean(name="dataSources")
public Map<String, DataSource> dataSources() {
//System.out.println(projectName);
List<Map<String, String>> configList = dataSourceConfiguration.getConfiglist();
Map<String, DataSource> dsMap = new HashMap<String, DataSource>();
// 配置数据源的相关信息
for (Map<String, String> configMap : configList) {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(configMap.get("driverClassName"));
dataSource.setUrl(configMap.get("url"));
dataSource.setUsername(configMap.get("username"));
dataSource.setPassword(configMap.get("password"));
// 配置初始化大小、最小、最大
dataSource.setInitialSize(Integer.parseInt(configMap.get("initialSize")));
dataSource.setMinIdle(Integer.parseInt(configMap.get("minIdle")));
dataSource.setMaxActive(Integer.parseInt(configMap.get("maxActive")));
// 配置获取连接等待超时的时间
dataSource.setMaxWait(Integer.parseInt(configMap.get("maxWait")));
// 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
dataSource.setTimeBetweenEvictionRunsMillis(Integer.parseInt(configMap.get("timeBetweenEvictionRunsMillis")));
// 配置一个连接在池中最小生存的时间,单位是毫秒
dataSource.setMinEvictableIdleTimeMillis(Integer.parseInt(configMap.get("minEvictableIdleTimeMillis")));
dataSource.setValidationQuery(configMap.get("validationQuery"));
dataSource.setTestWhileIdle(Boolean.parseBoolean(configMap.get("testWhileIdle")));
dataSource.setTestOnBorrow(Boolean.parseBoolean(configMap.get("testOnBorrow")));
dataSource.setTestOnReturn(Boolean.parseBoolean(configMap.get("testOnReturn")));
// 打开PSCache
dataSource.setPoolPreparedStatements(Boolean.parseBoolean(configMap.get("poolPreparedStatements")));
// 指定每个连接上PSCache的大小
dataSource.setMaxPoolPreparedStatementPerConnectionSize(Integer.parseInt(configMap.get("maxPoolPreparedStatementPerConnectionSize")));
try {
// 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
dataSource.setFilters(configMap.get("filters"));
} catch (SQLException e) {
logger.error("druid configuration initialization filter", e);
}
// 通过connectProperties属性来打开mergeSql功能;慢SQL记录
dataSource.setConnectionProperties(configMap.get("connectionProperties"));
// 合并多个DruidDataSource的监控数据
dataSource.setUseGlobalDataSourceStat(true);
dsMap.put(configMap.get("key"), dataSource);
}
return dsMap;
}
/**
* @Primary 该注解表示在同一个接口有多个实现类可以注入的时候,默认选择哪一个,而不是让@autowire注解报错
* @Qualifier 根据名称进行注入,通常是在具有相同的多个类型的实例的一个注入(例如有多个DataSource类型的实例)
*/
// 定义bean:dataSource
// dataSources的值来源于上面定义的dataSources
@Bean
@Primary
public DynamicDataSource dataSource(@Qualifier("dataSources")Map<String, DataSource> dataSources) {
Map<Object, Object> targetDataSources = new HashMap<>();
for (String key : dataSources.keySet()) {
targetDataSources.put(key, dataSources.get(key));
}
DynamicDataSource dataSource = new DynamicDataSource();
dataSource.setTargetDataSources(targetDataSources);// 该方法是AbstractRoutingDataSource的方法
dataSource.setDefaultTargetDataSource(targetDataSources.get("default"));// 默认的datasource设置为myTestDbDataSource
return dataSource;
}
/**
* 根据数据源创建SqlSessionFactory
*/
// 定义bean:sqlSessionFactory
// dataSource的值来源于上面定义的dataSource
@Bean
public SqlSessionFactory sqlSessionFactory(DynamicDataSource dataSource) throws Exception {
SqlSessionFactoryBean fb = new SqlSessionFactoryBean();
fb.setDataSource(dataSource);// 指定数据源(这个必须有,否则报错)
// 下边两句仅仅用于*.xml文件,如果整个持久层操作不需要使用到xml文件的话(只用注解就可以搞定),则不加
// fb.setTypeAliasesPackage(env.getProperty("mybatis.typeAliasesPackage"));//
// 指定基包
try {
fb.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPER_LOCATION));//
} catch (Exception e) {
// 有的工程不需要操作DB的没有MAPPER文件,防止启动报错
e.printStackTrace();
}
return fb.getObject();
}
/**
* 配置事务管理器
*/
@Bean
public DataSourceTransactionManager transactionManager(DynamicDataSource dataSource) throws Exception {
return new DataSourceTransactionManager(dataSource);
}
@Bean
public ServletRegistrationBean druidServlet() {
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
//白名单:
servletRegistrationBean.addInitParameter("allow", "");
//IP黑名单 (存在共同时,deny优先于allow) : 如果满足deny的话提示:Sorry, you are not permitted to view this page.
servletRegistrationBean.addInitParameter("deny", "192.168.1.73");
//登录查看信息的账号密码.
servletRegistrationBean.addInitParameter("loginUsername", "admin");
servletRegistrationBean.addInitParameter("loginPassword", "123456");
//是否能够重置数据.
servletRegistrationBean.addInitParameter("resetEnable", "false");
return servletRegistrationBean;
}
@Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new WebStatFilter());
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
return filterRegistrationBean;
}
}