предисловие
В этой статье в основном говорится оSpringBootИнтегрироватьMybatis,DruidиPageHelperИ внедрить несколько источников данных и пейджинг. Среди них SpringBoot интегрирует Mybatis, в предыдущемстатьяЭто уже было описано в , поэтому я не буду вдаваться в подробности. Основное внимание уделяется настройке и использованию Druid и PageHelper с несколькими источниками данных.
Введение и использование друидов
в настоящее время используетDruidПеред этим давайте кратко разберемся с Друидом.
Druid — это пул соединений с базой данных. Можно сказать, что на данный момент Druid является лучшим пулом соединений с базой данных! Разработчики предпочитают его за отличную функциональность, производительность и масштабируемость. Druid развернул более 600 приложений в Alibaba и более года подвергался тщательному тестированию крупномасштабного развертывания в производственных средах. Druid — это пул соединений с базой данных, разработанный Alibaba, который называется Monitoring!
При этом Druid — это не просто пул соединений с базой данных, ядро Druid в основном состоит из трех частей:
- Система плагинов, основанная на режиме Filter-Chain.
- DruidDataSource Эффективный и управляемый пул соединений с базой данных.
- SQLParser
Основные функции Друида следующие:
- Это эффективный, мощный и масштабируемый пул соединений с базой данных.
- Производительность доступа к базе данных можно контролировать.
- Шифрование пароля базы данных
- Получить журнал выполнения SQL
- Расширенный JDBC
Что касается введения, то я не буду больше говорить об этом, за подробностями обращайтесь к официальной документации. Затем начните рассказывать, как используется Друид.
Во-первых, это зависимость от Maven, просто добавьте банку друида.
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.8</version>
</dependency>
С точки зрения конфигурации, основной должен быть только вapplication.propertiesилиapplication.ymlПросто добавьте следующее.Описание: Поскольку здесь я использую два источника данных, они немного отличаются. Описание конфигурации Друида было подробно описано ниже, поэтому я не буду его здесь объяснять.
## 默认的数据源
master.datasource.url=jdbc:mysql://localhost:3306/springBoot?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true
master.datasource.username=root
master.datasource.password=123456
master.datasource.driverClassName=com.mysql.jdbc.Driver
## 另一个的数据源
cluster.datasource.url=jdbc:mysql://localhost:3306/springBoot_test?useUnicode=true&characterEncoding=utf8
cluster.datasource.username=root
cluster.datasource.password=123456
cluster.datasource.driverClassName=com.mysql.jdbc.Driver
# 连接池的配置信息
# 初始化大小,最小,最大
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
# 配置获取连接等待超时的时间
spring.datasource.maxWait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource.timeBetweenEvictionRunsMillis=60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECT 1 FROM DUAL
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
# 打开PSCache,并且指定每个连接上PSCache的大小
spring.datasource.poolPreparedStatements=true
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
spring.datasource.filters=stat,wall,log4j
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
После успешного добавления файла конфигурации давайте напишем классы, связанные с Друидом. прежде всегоMasterDataSourceConfig.javaЭтот класс, это класс конфигурации источника данных по умолчанию.
@Configuration
@MapperScan(basePackages = MasterDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "masterSqlSessionFactory")
public class MasterDataSourceConfig {
static final String PACKAGE = "com.pancm.dao.master";
static final String MAPPER_LOCATION = "classpath:mapper/master/*.xml";
@Value("${master.datasource.url}")
private String url;
@Value("${master.datasource.username}")
private String username;
@Value("${master.datasource.password}")
private String password;
@Value("${master.datasource.driverClassName}")
private String driverClassName;
@Value("${spring.datasource.initialSize}")
private int initialSize;
@Value("${spring.datasource.minIdle}")
private int minIdle;
@Value("${spring.datasource.maxActive}")
private int maxActive;
@Value("${spring.datasource.maxWait}")
private int maxWait;
@Value("${spring.datasource.timeBetweenEvictionRunsMillis}")
private int timeBetweenEvictionRunsMillis;
@Value("${spring.datasource.minEvictableIdleTimeMillis}")
private int minEvictableIdleTimeMillis;
@Value("${spring.datasource.validationQuery}")
private String validationQuery;
@Value("${spring.datasource.testWhileIdle}")
private boolean testWhileIdle;
@Value("${spring.datasource.testOnBorrow}")
private boolean testOnBorrow;
@Value("${spring.datasource.testOnReturn}")
private boolean testOnReturn;
@Value("${spring.datasource.poolPreparedStatements}")
private boolean poolPreparedStatements;
@Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}")
private int maxPoolPreparedStatementPerConnectionSize;
@Value("${spring.datasource.filters}")
private String filters;
@Value("{spring.datasource.connectionProperties}")
private String connectionProperties;
@Bean(name = "masterDataSource")
@Primary
public DataSource masterDataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setDriverClassName(driverClassName);
//具体配置
dataSource.setInitialSize(initialSize);
dataSource.setMinIdle(minIdle);
dataSource.setMaxActive(maxActive);
dataSource.setMaxWait(maxWait);
dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
dataSource.setValidationQuery(validationQuery);
dataSource.setTestWhileIdle(testWhileIdle);
dataSource.setTestOnBorrow(testOnBorrow);
dataSource.setTestOnReturn(testOnReturn);
dataSource.setPoolPreparedStatements(poolPreparedStatements);
dataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
try {
dataSource.setFilters(filters);
} catch (SQLException e) {
e.printStackTrace();
}
dataSource.setConnectionProperties(connectionProperties);
return dataSource;
}
@Bean(name = "masterTransactionManager")
@Primary
public DataSourceTransactionManager masterTransactionManager() {
return new DataSourceTransactionManager(masterDataSource());
}
@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));
return sessionFactory.getObject();
}
}
Эти две аннотации описывают:
-
@Primary: Отметьте этот Бин, если есть несколько кандидатов одного и того же типа Бин, Бин считается приоритетным. При настройке нескольких источников данных обратите внимание, что должен быть первичный источник данных, и пометьте компонент @Primary.
-
@MapperScan: Интерфейс Scan Mapper и управление контейнерами.
должен быть в курсеsqlSessionFactoryRefозначает определение уникальногоSqlSessionFactoryпример.
После того, как описанная выше конфигурация завершена, Druid можно использовать в качестве пула соединений. Но Druid — это не просто пул соединений, его также можно назвать приложением для мониторинга, он поставляется с веб-интерфейсом для мониторинга, вы можете четко видеть информацию, связанную с SQL. существуетSpringBootиспользовать вDruidфункция мониторинга, нужно только написатьStatViewServletиWebStatFilterКласс, реализующий службы регистрации и правила фильтрации. Здесь мы можем написать эти два вместе, используя **@Configurationи@Бин**. Для удобства понимания соответствующие инструкции по настройке также прописаны в коде, поэтому я не буду их здесь повторять. код показывает, как показано ниже:
@Configuration
public class DruidConfiguration {
@Bean
public ServletRegistrationBean druidStatViewServle() {
//注册服务
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(
new StatViewServlet(), "/druid/*");
// 白名单(为空表示,所有的都可以访问,多个IP的时候用逗号隔开)
servletRegistrationBean.addInitParameter("allow", "127.0.0.1");
// IP黑名单 (存在共同时,deny优先于allow)
servletRegistrationBean.addInitParameter("deny", "127.0.0.2");
// 设置登录的用户名和密码
servletRegistrationBean.addInitParameter("loginUsername", "pancm");
servletRegistrationBean.addInitParameter("loginPassword", "123456");
// 是否能够重置数据.
servletRegistrationBean.addInitParameter("resetEnable", "false");
return servletRegistrationBean;
}
@Bean
public FilterRegistrationBean druidStatFilter() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(
new WebStatFilter());
// 添加过滤规则
filterRegistrationBean.addUrlPatterns("/*");
// 添加不需要忽略的格式信息
filterRegistrationBean.addInitParameter("exclusions",
"*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
System.out.println("druid初始化成功!");
return filterRegistrationBean;
}
}
После записи запустите программу, введите в браузере: http://127.0.0.1:8084/druid/index.html, а затем введите установленные имя пользователя и пароль для доступа к веб-интерфейсу.
Конфигурация нескольких источников данных
Перед настройкой нескольких источников данныхspringBootиspringBoot_testизmysqlВыполните следующий сценарий в базе данных.
-- springBoot库的脚本
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`name` varchar(10) DEFAULT NULL COMMENT '姓名',
`age` int(2) DEFAULT NULL COMMENT '年龄',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8
-- springBoot_test库的脚本
CREATE TABLE `t_student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(16) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
Примечание: Чтобы не было лени, структуры двух таблиц сделаны одинаковыми! Но на тест это не влияет!
существуетapplication.propertiesИнформация об этих двух источниках данных была настроена выше, и конфигурация была опубликована один раз, поэтому она не будет опубликована здесь. Здесь мы сосредоточимся на настройке второго источника данных. и вышеMasterDataSourceConfig.javaРазница почти в том, что аннотация и имя **@Primary** не используются. должен быть в курсеMasterDataSourceConfig.javaСканирование пакетов и картографов выполняется с точностью до каталога, как и второй источник данных здесь. Тогда код следующий:
@Configuration
@MapperScan(basePackages = ClusterDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "clusterSqlSessionFactory")
public class ClusterDataSourceConfig {
static final String PACKAGE = "com.pancm.dao.cluster";
static final String MAPPER_LOCATION = "classpath:mapper/cluster/*.xml";
@Value("${cluster.datasource.url}")
private String url;
@Value("${cluster.datasource.username}")
private String username;
@Value("${cluster.datasource.password}")
private String password;
@Value("${cluster.datasource.driverClassName}")
private String driverClass;
// 和MasterDataSourceConfig一样,这里略
@Bean(name = "clusterDataSource")
public DataSource clusterDataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setDriverClassName(driverClass);
// 和MasterDataSourceConfig一样,这里略 ...
return dataSource;
}
@Bean(name = "clusterTransactionManager")
public DataSourceTransactionManager clusterTransactionManager() {
return new DataSourceTransactionManager(clusterDataSource());
}
@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));
return sessionFactory.getObject();
}
}
После успешного написания конфигурации запустите программу и протестируйте ее. СоответственноspringBootиspringBoot_testБиблиотека использует интерфейс для добавления данных.
t_user
POST http://localhost:8084/api/user
{"name":"张三","age":25}
{"name":"李四","age":25}
{"name":"王五","age":25}
t_student
POST http://localhost:8084/api/student
{"name":"学生A","age":16}
{"name":"学生B","age":17}
{"name":"学生C","age":18}
После успешного добавления данных вызовите разные интерфейсы для запроса.
просить:
GET http://localhost:8084/api/user?name=李四
возвращение:
{
"id": 2,
"name": "李四",
"age": 25
}
просить:
GET http://localhost:8084/api/student?name=学生C
возвращение:
{
"id": 1,
"name": "学生C",
"age": 16
}
Из данных видно, что несколько источников данных были успешно настроены.
Реализация подкачки PageHelper
PageHelper — это плагин пейджинга для Mybatis, очень простой в использовании! Очень рекомендуется здесь! ! !
Использовать PageHelper очень просто, просто добавьте зависимость pagehelper в Maven. Зависимости Maven следующие:
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.3</version>
</dependency>
Примечание. Здесь я использую версию SpringBoot! Можно использовать и другие версии.
После добавления зависимостей вам нужно только добавить следующую конфигурацию или код. Первый, вapplication.propertiesилиapplication.ymlДобавить к
pagehelper:
helperDialect: mysql
offsetAsPageNum: true
rowBoundsWithCount: true
reasonable: false
Второй, добавить в конфигурацию mybatis.xml
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 扫描mapping.xml文件 -->
<property name="mapperLocations" value="classpath:mapper/*.xml"></property>
<!-- 配置分页插件 -->
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageHelper">
<property name="properties">
<value>
helperDialect=mysql
offsetAsPageNum=true
rowBoundsWithCount=true
reasonable=false
</value>
</property>
</bean>
</array>
</property>
</bean>
Третий — добавить его в код и использовать аннотацию **@Bean** для инициализации при запуске программы.
@Bean
public PageHelper pageHelper(){
PageHelper pageHelper = new PageHelper();
Properties properties = new Properties();
//数据库
properties.setProperty("helperDialect", "mysql");
//是否将参数offset作为PageNum使用
properties.setProperty("offsetAsPageNum", "true");
//是否进行count查询
properties.setProperty("rowBoundsWithCount", "true");
//是否分页合理化
properties.setProperty("reasonable", "false");
pageHelper.setProperties(properties);
}
Поскольку здесь мы используем несколько источников данных, конфигурация здесь немного отличается. нам надоsessionFactoryнастроить здесь. Прямо здесьMasterDataSourceConfig.javaВнесите соответствующие изменения. существуетmasterSqlSessionFactoryметод, добавьте следующий код.
@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));
//分页插件
Interceptor interceptor = new PageInterceptor();
Properties properties = new Properties();
//数据库
properties.setProperty("helperDialect", "mysql");
//是否将参数offset作为PageNum使用
properties.setProperty("offsetAsPageNum", "true");
//是否进行count查询
properties.setProperty("rowBoundsWithCount", "true");
//是否分页合理化
properties.setProperty("reasonable", "false");
interceptor.setProperties(properties);
sessionFactory.setPlugins(new Interceptor[] {interceptor});
return sessionFactory.getObject();
}
Примечание. Если другие источники данных также хотят выполнить разбиение по страницам, обратитесь к приведенному выше коду.
Здесь следует отметить, чтоreasonableПараметр, указывающий на рационализацию пейджинга, по умолчанию имеет значение false. Если для этого параметра установлено значение true, первая страница будет запрашиваться, когда pageNumpages (больше, чем общее количество). Когда значение по умолчанию равно false, запрос выполняется непосредственно в соответствии с параметрами.
После установки PageHelper, если вы хотите его использовать, вам нужно только добавить его перед sql запросаPageHelper.startPage(pageNum,pageSize);, если вы хотите узнать общее число, просто добавьте **page.getTotal()** после инструкции sql запроса. Пример кода:
public List<T> findByListEntity(T entity) {
List<T> list = null;
try {
Page<?> page =PageHelper.startPage(1,2);
System.out.println(getClassName(entity)+"设置第一页两条数据!");
list = getMapper().findByListEntity(entity);
System.out.println("总共有:"+page.getTotal()+"条数据,实际返回:"+list.size()+"两条数据!");
} catch (Exception e) {
logger.error("查询"+getClassName(entity)+"失败!原因是:",e);
}
return list;
}
После того, как код написан, начинается финальное тестирование.
Запросt_userВсе данные в таблице разбиты на страницы.
просить:
GET http://localhost:8084/api/user
возвращение:
[
{
"id": 1,
"name": "张三",
"age": 25
},
{
"id": 2,
"name": "李四",
"age": 25
}
]
консольная печать:
开始查询...
User设置第一页两条数据!
2018-04-27 19:55:50.769 DEBUG 6152 --- [io-8084-exec-10] c.p.d.m.UserDao.findByListEntity_COUNT : ==> Preparing: SELECT count(0) FROM t_user WHERE 1 = 1
2018-04-27 19:55:50.770 DEBUG 6152 --- [io-8084-exec-10] c.p.d.m.UserDao.findByListEntity_COUNT : ==> Parameters:
2018-04-27 19:55:50.771 DEBUG 6152 --- [io-8084-exec-10] c.p.d.m.UserDao.findByListEntity_COUNT : <== Total: 1
2018-04-27 19:55:50.772 DEBUG 6152 --- [io-8084-exec-10] c.p.dao.master.UserDao.findByListEntity : ==> Preparing: select id, name, age from t_user where 1=1 LIMIT ?
2018-04-27 19:55:50.773 DEBUG 6152 --- [io-8084-exec-10] c.p.dao.master.UserDao.findByListEntity : ==> Parameters: 2(Integer)
2018-04-27 19:55:50.774 DEBUG 6152 --- [io-8084-exec-10] c.p.dao.master.UserDao.findByListEntity : <== Total: 2
总共有:3条数据,实际返回:2两条数据!
Запросt_studentВсе данные в таблице разбиты на страницы.
просить:
GET http://localhost:8084/api/student
возвращение:
[
{
"id": 1,
"name": "学生A",
"age": 16
},
{
"id": 2,
"name": "学生B",
"age": 17
}
]
консольная печать:
开始查询...
Studnet设置第一页两条数据!
2018-04-27 19:54:56.155 DEBUG 6152 --- [nio-8084-exec-8] c.p.d.c.S.findByListEntity_COUNT : ==> Preparing: SELECT count(0) FROM t_student WHERE 1 = 1
2018-04-27 19:54:56.155 DEBUG 6152 --- [nio-8084-exec-8] c.p.d.c.S.findByListEntity_COUNT : ==> Parameters:
2018-04-27 19:54:56.156 DEBUG 6152 --- [nio-8084-exec-8] c.p.d.c.S.findByListEntity_COUNT : <== Total: 1
2018-04-27 19:54:56.157 DEBUG 6152 --- [nio-8084-exec-8] c.p.d.c.StudentDao.findByListEntity : ==> Preparing: select id, name, age from t_student where 1=1 LIMIT ?
2018-04-27 19:54:56.157 DEBUG 6152 --- [nio-8084-exec-8] c.p.d.c.StudentDao.findByListEntity : ==> Parameters: 2(Integer)
2018-04-27 19:54:56.157 DEBUG 6152 --- [nio-8084-exec-8] c.p.d.c.StudentDao.findByListEntity : <== Total: 2
总共有:3条数据,实际返回:2两条数据!
После завершения запроса давайте посмотрим на интерфейс мониторинга Druid. Введите в браузере: http://127.0.0.1:8084/druid/index.html
Вы можете четко видеть записи операций! Если вы хотите узнать больше о Druid, вы можете проверить официальную документацию!
Эпилог
Эта статья, наконец, закончена.При написании кода я столкнулся со многими проблемами, а затем потихоньку пробовал и находил информацию для их решения. В этой статье только кратко представлены эти связанные области применения, а фактическое применение может быть более сложным. Если у вас есть лучшие идеи и предложения, пожалуйста, оставьте сообщение для обсуждения!
Справочная статья: https://www.bysocket.com/?p=1712
Официальный адрес Дурида: https://github.com/alibaba/druid
Официальный адрес PageHelper: https://github.com/pagehelper/Mybatis-PageHelper
Выкладываю проект на гитхаб: https://github.com/xuwujing/springBoot
Если он чувствует себя хорошо, я надеюсь дать звезду, кстати. Это конец этой статьи, спасибо за прочтение.
Уведомление об авторских правах: Автор: ничтожество Источник блога сада: http://www.cnblogs.com/xuwujing Источник CSDN: http://blog.csdn.net/qazwsxpcm Источник личного блога: http://www.panchengming.com Оригинальность непростая, пожалуйста, указывайте источник при перепечатке, спасибо!