springboot在spring的基础上进行了提升,主要是减少了spring里面一成不变的xml配置。
使用约定大于配置大于代码的思想,只需要引用响应的包,进行对应的值配置即可。
下面是集成各个组件的例子。
1、集成redis
包引用
代码语言:javascript复制 <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.5.12</version>
<!-- 这里频繁的报Caused by: java.lang.ClassNotFoundException: com.fasterxml.jackson.core.Versioned
也就是jackon相关的包找不到,是因为在spring-boot-starter-web中排除了,不排除即可-->
</dependency>
配置内容
代码语言:javascript复制spring:
redis:
database: 0
host: 9.0.0.43
port: 6379
password: password
jedis:
pool:
max-active: 1024
max-wait: 10000
max-idle: 200
min-idle: 0
timeout: 10000
block-when-exhausted: true
这个配置是标准的配置格式,不能乱动。按照这个配置整好之后,
启动项目,@SpringBootApplication -> @EnableAutoConfiguration -> @Import({AutoConfigurationImportSelector.class})将会自动进行bean的配置,前提是有按照spring约定的格式进行配置。有哪些bean可以自动配置的呢,可参见包org.springframework.boot:spring-boot-autoconfigure/Meta-inf/spring-autoconfigure-metadata.properties。
在使用的时候,直接使用springboot的redisTemplate即可,spring中有很多template的对象,使用的是模板方法模式,即里面设计好了逻辑,只需要对应的实现或者实现自己的逻辑即可。
代码语言:javascript复制 @Autowired
RedisTemplate redisTemplate;
redisTemplate.opsForValue().get("aa");
如果是用spring框架的话,则需要有很多配置,可参考如https://developer.aliyun.com/article/319845(没验证)至少需要xml进行bean配置以及Configurate代码配置等。
但是标准配置也不是万能的,比如,有多个mysql库,这里就区分不了了。所以该有的还是避免不了。
2、集成mysql
包引用
代码语言:javascript复制<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
配置内容
代码语言:javascript复制spring:
datasource:
mysql:
# fatp,数据源的地址
fatp:
username: admin
password: password
jdbc-url: jdbc:mysql://9.0.0.7:3306/fatp?useUnicode=true&characterEncoding=utf8&serverTimezone=Hongkong&useAffectedRows=true&autoReconnect=true&useSSL=false
driver-class-name: com.mysql.jdbc.Driver
pool-name: mysqlHikariCP
register-mbeans: true
maximum-pool-size: 10
connection-test-query: select 1
这里可见与redis的配置数据结构不一样,是因为考虑到会有多个mysql的db配置
代码语言:javascript复制package com.xx.fatp.dw.conf;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import com.zaxxer.hikari.HikariPoolMXBean;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.concurrent.TimeUnit;
@Slf4j
@Configuration
@MapperScan(basePackages = {"com.xx.dao.mysql.mapper"},
sqlSessionTemplateRef = "mysqlSqlSessionTemplate", lazyInitialization = "true")
public class MysqlDataSourceConfig {
private static final int MONITOR_INTERVAL_SECONDS = 5;
/**
* 获取数据源信息
*/
@Bean
public HikariConfig mysqlDataSourceProperties() {
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setUsername(
PropertiesUtils.getString("spring.datasource.mysql.fatp.username"));
hikariConfig.setPassword(
PropertiesUtils.getString("spring.datasource.mysql.fatp.password"));
hikariConfig.setJdbcUrl(
PropertiesUtils.getString("spring.datasource.mysql.fatp.jdbc-url"));
hikariConfig.setDriverClassName(
PropertiesUtils.getString("spring.datasource.mysql.fatp.driver-class-name"));
hikariConfig.setPoolName(
PropertiesUtils.getString("spring.datasource.mysql.fatp.pool-name"));
hikariConfig.setRegisterMbeans(Boolean.parseBoolean(
PropertiesUtils.getString("spring.datasource.mysql.fatp.register-mbeans")));
hikariConfig.setMaximumPoolSize(
PropertiesUtils.getInt("spring.datasource.mysql.fatp.maximum-pool-size"));
return hikariConfig;
}
/**
* 创建datasource
*/
@Bean(name = "mysqlDataSource")
@Lazy
public DataSource mysqlDataSource() {
HikariDataSource ds = new HikariDataSource(mysqlDataSourceProperties());
log.info("database url : {}, pool size : {}", ds.getJdbcUrl(), ds.getMaximumPoolSize());
try {
HikariPoolMXBean poolProxy = ds.getHikariPoolMXBean();
//连接池监控进程
startConnectionPoolMonitor(poolProxy);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return ds;
}
private void startConnectionPoolMonitor(HikariPoolMXBean poolProxy) {
new Thread(() -> {
while (true) {
try {
if (poolProxy.getThreadsAwaitingConnection() > 0) {
log.info("MySQLHikariConnectionPoolState = "
"Active=[" poolProxy.getActiveConnections() "] "
"Idle=[" poolProxy.getIdleConnections() "] "
"Wait=[" poolProxy.getThreadsAwaitingConnection() "] "
"Total=[" poolProxy.getTotalConnections() "]");
}
} catch (Exception e) {
log.error(e.getMessage(), e);
} finally {
try {
TimeUnit.SECONDS.sleep(MONITOR_INTERVAL_SECONDS);
} catch (Exception e) {
//do nothing
}
}
}
}).start();
}
/**
* 配置事务.
*/
@Bean
@Resource
public PlatformTransactionManager mysqlManager(
@Qualifier("mysqlDataSource") DataSource mysqlDataSource) {
return new DataSourceTransactionManager(mysqlDataSource);
}
/**
* 创建factory
*/
@Bean
public SqlSessionFactory mysqlSqlSessionFactory(
@Qualifier("mysqlDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
try {
return bean.getObject();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* 创建template
*/
@Bean
public SqlSessionTemplate mysqlSqlSessionTemplate(
@Qualifier("mysqlSqlSessionFactory") SqlSessionFactory sqlSessionFactory)
throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
3、集成pgsql
依赖包
代码语言:javascript复制<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.25</version>
</dependency>
配置
代码语言:javascript复制spring:
datasource:
pgsql:
dw:
username: admin
password: password
jdbc-url: jdbc:postgresql://9.0.0.1:5432/postgres?charSet=utf-8
driver-class-name: org.postgresql.Driver
initialSize: 10
maximum-pool-size: 2000
pool-name: pgsqlHikariCP
connection-test-query: select 1
代码语言:javascript复制package com.xx.fatp.dw.conf;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
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 javax.sql.DataSource;
@Configuration
@MapperScan(
basePackages = "com.xx.dao.pgsql.mapper",
sqlSessionTemplateRef = "pgsqlSqlSessionTemplate")
public class PgsqlDataSourceConfig {
/**
* 创建datasource
*/
@Bean(name = "pgsqlDataSource")
@ConfigurationProperties(prefix = "spring.datasource.pgsql.dw")
@Primary
public DataSource pgsqlDataSource() {
return DataSourceBuilder.create().build();
}
/**
* 创建factory
*/
@Bean(name = "pgsqlSqlSessionFactory")
@Primary
public SqlSessionFactory pgsqlSqlSessionFactory(@Qualifier("pgsqlDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
return bean.getObject();
}
@Bean(name = "pgsqlTransactionManager")
@Primary
public DataSourceTransactionManager pgsqlTransactionManager(@Qualifier("pgsqlDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
/**
* 创建template
*/
@Bean(name = "pgsqlSqlSessionTemplate")
@Primary
public SqlSessionTemplate pgsqlSqlSessionTemplate(@Qualifier("pgsqlSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
4、集成mongodb
依赖包
代码语言:javascript复制<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<version>2.5.12</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
<exclusion>
<artifactId>spring-beans</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-context</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-core</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-expression</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>
配置
代码语言:javascript复制spring:
datasource:
mongodb:
dw:
# dw,数仓的地址
# 需要在databse库创建对应的用户,详见fatp_rw1用户信息。
# 角色的权限要对dbAdmin角色就不行。
username: root
password: password
address: 9.0.0.121:27017
database: fatp_dw
下面这些暂时没有配置上,可以继续配置
# 客户端连接池参数
#客户端的标识,用于定位请求来源等,一般用程序名
clientName: ${spring.application.name}
#TCP(socket)连接超时时间,毫秒
connectionTimeoutMs: 5000
#TCP(socket)连接闲置时间,毫秒
maxConnectionIdleTimeMs: 60000
#TCP(socket)连接最多可以使用多久,毫秒
maxConnectionLifeTimeMs: 300000
#TCP(socket)读取超时时间,毫秒
readTimeoutMs: 15000
#当连接池无可用连接时客户端阻塞等待的最大时长,毫秒
maxWaitTimeMs: 5000
#心跳检测发送频率,毫秒
heartbeatFrequencyMs: 20000
#最小的心跳检测发送频率,毫秒
minHeartbeatFrequencyMs: 8000
#心跳检测连接超时时间,毫秒
heartbeatConnectionTimeoutMs: 10000
#心跳检测读取超时时间,毫秒
heartbeatReadTimeoutMs: 15000
#线程池允许的最大连接数
connectionsPerHost: 100
#线程池空闲时保持的最小连接数
minConnectionsPerHost: 20
#计算允许多少个线程阻塞等待时的乘数,算法:threadsAllowedToBlockForConnectionMultiplier*maxConnectionsPerHost
threadsAllowedToBlockForConnectionMultiplier: 10
代码语言:javascript复制package com.xx.fatp.dw.conf;
import com.mongodb.*;
import com.mongodb.client.*;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
import org.springframework.data.mongodb.core.convert.*;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import java.util.ArrayList;
import java.util.List;
@Configuration
@EnableConfigurationProperties(MongodbDataSourceConfig.MongoClientOptionProperties.class)
public class MongodbDataSourceConfig {
/**
* 此Bean也是可以不显示定义的,如果我们没有显示定义生成MongoTemplate实例,
* SpringBoot利用我们配置好的MongoDbFactory在配置类中生成一个MongoTemplate,
* 之后我们就可以在项目代码中直接@Autowired了。因为用于生成MongoTemplate
* 的MongoDbFactory是我们自己在MongoConfig配置类中生成的,所以我们自定义的连接池参数也就生效了。
*
* @param mongoDbFactory mongo工厂
* @param converter 转换器
* @return MongoTemplate实例
*/
@Bean(name = "mongoTemplateMZ")
public MongoTemplate mongoTemplate(MongoDatabaseFactory mongoDbFactory, MappingMongoConverter converter) {
MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory, converter);
// 设置读从库优先
mongoTemplate.setReadPreference(ReadPreference.secondaryPreferred());
System.out.println("use this fuck shit");
return mongoTemplate;
}
/**
* 转换器
* MappingMongoConverter可以自定义mongo转换器,主要自定义存取mongo数据时的一些操作,例如 mappingConverter.setTypeMapper(new
* DefaultMongoTypeMapper(null)) 方法会将mongo数据中的_class字段去掉。
*
* @param factory mongo工厂
* @param context 上下文
* @param conversions 自定义转换器
* @return 转换器对象
*/
@Bean
public MappingMongoConverter mappingMongoConverter(MongoDatabaseFactory factory, MongoMappingContext context,
MongoCustomConversions conversions) {
DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context);
mappingConverter.setCustomConversions(conversions);
// remove _class field
mappingConverter.setTypeMapper(new DefaultMongoTypeMapper(null));
return mappingConverter;
}
/**
* 自定义mongo连接池
*
* @param properties 属性配置类
* @return MongoDbFactory对象
*/
@Bean
public MongoDatabaseFactory mongoDbFactory(MongoClientOptionProperties properties) {
// 解析获取mongo服务地址
List<ServerAddress> serverAddressList = getServerAddress(properties.getAddress());
// 创建认证
MongoCredential mongoCredential = getCredential(properties);
MongoClientSettings settings = MongoClientSettings.builder()
.applyToClusterSettings(builder -> builder.hosts(serverAddressList))
.credential(mongoCredential)
.build();
MongoClient mongoClient = MongoClients.create(settings);
return new SimpleMongoClientDatabaseFactory(mongoClient, properties.getDatabase());
}
/**
* 创建认证
*
* @param properties 属性配置类
* @return 认证对象
*/
private MongoCredential getCredential(MongoClientOptionProperties properties) {
if (!StringUtils.isEmpty(properties.getUsername()) && !StringUtils.isEmpty(properties.getPassword())) {
// 没有专用认证数据库则取当前数据库
String database = StringUtils.isEmpty(properties.getAuthenticationDatabase()) ?
properties.getDatabase() : properties.getAuthenticationDatabase();
return MongoCredential.createCredential(properties.getUsername(), database,
properties.getPassword().toCharArray());
}
return null;
}
/**
* 获取数据库服务地址
*
* @param mongoAddress 地址字符串
* @return 服务地址数组
*/
private List<ServerAddress> getServerAddress(String mongoAddress) {
String[] mongoAddressArray = mongoAddress.trim().split(",");
List<ServerAddress> serverAddressList = new ArrayList<>(4);
for (String address : mongoAddressArray) {
String[] hostAndPort = address.split(":");
serverAddressList.add(new ServerAddress(hostAndPort[0], Integer.parseInt(hostAndPort[1])));
}
return serverAddressList;
}
@Data
@ConfigurationProperties(prefix = "spring.datasource.mongodb.dw")
public static class MongoClientOptionProperties {
/**
* 基础连接参数
*/
private String database; // 要连接的数据库
private String username; // 用户名
private String password; // 密码
private String address; // IP和端口(host:port),例如127.0.0.1:27017。集群模式用,分隔开,例如host1:port1,host2:port2
private String authenticationDatabase; // 设置认证数据库,如果有的话
/**
* 客户端连接池参数
*/
private String clientName; // 客户端的标识,用于定位请求来源等,一般用程序名
private int connectionTimeoutMs; // TCP(socket)连接超时时间,毫秒
private int maxConnectionIdleTimeMs; // TCP(socket)连接闲置时间,毫秒
private int maxConnectionLifeTimeMs; // TCP(socket)连接最多可以使用多久,毫秒
private int readTimeoutMs; // TCP(socket)读取超时时间,毫秒
private int maxWaitTimeMs; // 当连接池无可用连接时客户端阻塞等待的最大时长,毫秒
private int heartbeatFrequencyMs; // 心跳检测发送频率,毫秒
private int minHeartbeatFrequencyMs; // 最小的心跳检测发送频率,毫秒
private int heartbeatConnectionTimeoutMs; // 心跳检测连接超时时间,毫秒
private int heartbeatReadTimeoutMs; // 心跳检测读取超时时间,毫秒
private int connectionsPerHost; // 线程池允许的最大连接数
private int minConnectionsPerHost; // 线程池空闲时保持的最小连接数
// 计算允许多少个线程阻塞等待时的乘数,算法:threadsAllowedToBlockForConnectionMultiplier*maxConnectionsPerHost
private int threadsAllowedToBlockForConnectionMultiplier;
}
}
集成mongo有账号的限制
todo,可见各个db的配置,无非就是datasource - factory - template的配置,还需要详细梳理一下。