前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >spring boot 集成组件

spring boot 集成组件

原创
作者头像
二锅头一桶天下
修改2023-08-31 19:07:42
2840
修改2023-08-31 19:07:42
举报
文章被收录于专栏:二锅头一桶天下

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的配置,还需要详细梳理一下。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、集成redis
  • 2、集成mysql
  • 3、集成pgsql
  • 4、集成mongodb
相关产品与服务
数据库专家服务
数据库专家服务(Database Expert Service,DBexpert)为您提供专业化的数据库服务。仅需提交您的具体问题和需求,即可获得腾讯云数据库专家的专业支持,助您解决各类专业化问题。腾讯云数据库专家服务团队均有10年以上的 DBA 经验,拥有亿级用户产品的数据库管理经验,以及丰富的服务经验。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档