SpringBoot整合Nacos實現動態配置數據源


1. Nacos介紹

  是不是還有好多小伙伴不知道 nacos 是啥?nacos 是阿里巴巴的一個開源項目,官網給它的定義是:

一個更易於構建雲原生應用的動態服務發現、配置管理和服務管理平台。

  SpringBoot/SpringCloud項目部署運行后,如果使用硬編碼方式定義數據源,那么如果需要更換數據庫,就只能通過更改源碼並重啟的方式來達成目的,而 nacos 配置中心這一組件,我們可以將數據源連接

屬性編寫在配置中心中,需要修改連接屬性就可以從配置中心中修改並發布,這樣就可以熱修改數據源位置無需重啟服務。

  其實,目前 nacos 這個組件應用很廣泛,很多項目都用它來做配置中心和注冊中心,今天分享的內容就是 nacos 作為配置中心使用的。

  在做之前,我查了好多示例和博客,但是都沒有找到符合我需求的,所以走了好多彎路,才讓這個項目完整的跑起來,現在我們就來看下如何實現 SpringBoot + Nacos + Druid 動態獲取數據庫配置信息。

  今天的內容比較多,如果你恰好在學習 nacos,認真看完,肯定會有收獲。

  官網地址:官網地址

  官網文檔地址:官網文檔地址

  Gitee地址:Springboot-nacos

1.1 Nacos特性

  Nacos 致力於幫助您發現、配置和管理微服務。Nacos 提供了一組簡單易用的特性集,幫助您快速實現動態服務發現、服務配置、服務元數據及流量管理。

  Nacos 幫助您更敏捷和容易地構建、交付和管理微服務平台。 Nacos 是構建以“服務”為中心的現代應用架構 (例如微服務范式、雲原生范式) 的服務基礎設施。

  1、服務發現和服務健康監測

  2、動態配置服務

  3、動態 DNS 服務

  4、服務及其元數據管理

  等等。。。。

1.2 Nacos相關頁面展示(登錄賬號密碼:nacos nacos)

2. 下載安裝並啟動Nacos服務

2.1 下載Nacos

進入官網,點擊版本前往 github,你需要去 nacos 的 GitHub 發布列表中下載,不清楚的小伙伴直接訪問下面的網址進入下載頁選擇適合的版本:GitHub下載地址

最新版本是 2.0.4,目前最新的穩定版本是1.4.3

點擊Assets,選擇 zip 文件,然后應該就開始下載了,下載可能比較慢

如果 GitHub 打不開,可以從下面地址下載

  鏈接: https://pan.baidu.com/s/1bFLQ-2jnDg8Mm_bmMpePqw

2.2 Windows啟動關閉Nacos服務

2.2.1 zip 文件結構是這樣的,直接解壓就行,也不需要配置環境變量

2.2.2 啟動Nacos服務,進入 bin 目錄下直接雙擊 startup.cmd,窗口不要關閉,關閉服務也就停止了

 

2.2.3 關閉Nacos服務,雙擊 shutdown.cmd 或者 直接關閉啟動的 cmd 窗口

2.3 修改 Nacos 服務端配置信息(可不修改)

2.4 訪問Nacos服務

如果沒有修改 nacos 的配置,直接瀏覽器打開如下地址即可,如果修改了端口,需要把端口改成你修改的端口:http://127.0.0.1:8848/nacos

http://127.0.0.1:8848/nacos

 

默認用戶名和密碼都是 nacos,登陸成功之后就可以發布你的配置信息了。

2.5 啟動后是沒有配置的,點擊 + 號發布配置信息

輸入Data ID,必須唯一,類似於主鍵,不能重復;選擇配置格式,這里我選擇YAML(內容如下);然后點擊發布,一個配置信息就發布成功了

# 數據源配置
spring:
    datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driverClassName: com.mysql.cj.jdbc.Driver
        druid:
            # 主庫數據源
            master:
                url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                username: root
                password: root
            # 從庫數據源
            slave:
                # 從數據源開關/默認關閉
                enabled: false
                url:
                username:
                password:
            # 初始連接數
            initialSize: 5
            # 最小連接池數量
            minIdle: 10
            # 最大連接池數量
            maxActive: 20
            # 配置獲取連接等待超時的時間
            maxWait: 60000
            # 配置間隔多久才進行一次檢測,檢測需要關閉的空閑連接,單位是毫秒
            timeBetweenEvictionRunsMillis: 60000
            # 配置一個連接在池中最小生存的時間,單位是毫秒
            minEvictableIdleTimeMillis: 300000
            # 配置一個連接在池中最大生存的時間,單位是毫秒
            maxEvictableIdleTimeMillis: 900000
            # 配置檢測連接是否有效
            validationQuery: SELECT 1 FROM DUAL
            testWhileIdle: true
            testOnBorrow: false
            testOnReturn: false
            webStatFilter:
                enabled: true
            statViewServlet:
                enabled: true
                # 設置白名單,不填則允許所有訪問
                allow:
                url-pattern: /druid/*
                # 控制台管理用戶名和密碼
                login-username: admin
                login-password: admin123
            filter:
                stat:
                    enabled: true
                    # 慢SQL記錄
                    log-slow-sql: true
                    slow-sql-millis: 1000
                    merge-sql: true
                wall:
                    config:
                        multi-statement-allow: true

3. 創建Springboot-nacos項目

按下圖步驟,我是創建了一個父子工程,創建了普通的maven項目,在項目下創建不同的springboot項目,也可以直接創建spring boot項目。

項目結構:

3.1 創建springboot項目

3.2 導入需要的依賴(spring-boot-start-parent版本過高可能會導致啟動失敗)

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.8.RELEASE</version>
</parent>
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--nacos配置-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>
        <!--mysql驅動-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--jdbc 數據庫連接-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!-- 引入阿里數據庫連接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.6</version>
        </dependency>
</dependencies>

3.3 resources目錄下的application.yml內容注釋掉

注意:需要把 application.yml 中的內容注釋掉或者刪除就可以

#server:
#  port: 8091
## 數據源配置
#spring:
#  datasource:
#    type: com.alibaba.druid.pool.DruidDataSource
#    driverClassName: com.mysql.cj.jdbc.Driver
#    druid:
#      # 主庫數據源
#      master:
#        url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
#        username: root
#        password: root
#      # 從庫數據源
#      slave:
#        # 從數據源開關/默認關閉
#        enabled: false
#        url:
#        username:
#        password:
#   。。。。。。。
#      filter:
#        stat:
#          enabled: true
#          # 慢SQL記錄
#          log-slow-sql: true
#          slow-sql-millis: 1000
#          merge-sql: true
#        wall:
#          config:
#            multi-statement-allow: true

3.4 在resources目錄下創建bootstrap.yml文件

spring:
  application:
    name: springboot-nacos
  profiles:
    active: dev
  cloud:
    nacos:
      config:
        # 配置中心的地址
        server-addr: 127.0.0.1:8848
        # 配置文件prefix
        prefix: ${spring.application.name}
        # 配置文件的格式
        file-extension: yaml
        # 配置文件的環境
        group: DEFAULT_GROUP
        # 命名空間
        namespace:
server:
  port: 8090

注意:
  只能是 bootstrap.yml 文件,application 文件是整合不上的。 bootstrap.yml 先於 application.yml 加載

bootstrap.yml(bootstrap.properties)用來在程序引導時執行,應用於更加早期配置信息讀取,如可以使用來配置application.yml中使用到參數等

application.yml(application.properties) 應用程序特有配置信息,可以用來配置后續各個模塊中需使用的公共參數等。

配置文件 prefix 是 nacos 服務器中 Data-ID 的前綴,若無此項配置,默認{spring.application.name}。項目啟動時根據此配置文件拼接 nacos 配置中心的 Data-ID 的名稱來查找配置文件

1. 拼接規則標准:${prefix}-${spring.profile.active}.${file-extension}

2. 如果 spring.cloud.nacos.config.prefix 省略的拼接規則:

{spring.application.name}-${spring.profile.active}.${file-extension}

建議: 以上配置配完整,不要省略,符合規范

3.5 自定義DruidDatasouceWrapper

DruidDataSourceWrapper 要繼承 DruidDataSource

RefreshScope 的作用是實現配置、實例熱加載,也就是我們重寫修改配置信息后,Spring 會銷毀當前類的實例,然后重新創建一個新的實例放到容器中,也是實現數據源配置實時更新的關鍵

注意:@Value代碼根據自己在 nacos 配置修改

package com.liyh.druid;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;

@Configuration
@RefreshScope
public class DruidDataSourceWrapper extends DruidDataSource implements InitializingBean {
    @Value("${spring.datasource.druid.master.url}")
    private String url;
    @Value("${spring.datasource.druid.master.username}")
    private String username;
    @Value("${spring.datasource.druid.master.password}")
    private String password;
    @Value("${spring.datasource.driver-class-name}")
    private String driverClassName;

    private String passwordCallbackClassName;

    public void setMaxWait(int maxWait) {
        this.maxWait = maxWait;
    }

    public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
        this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
    }

    public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
        this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
    }

    @Override
    public void setUrl(String url) {
        this.url = url;
    }

    @Override
    public void setDriverClassName(String driverClassName) {
        this.driverClassName = driverClassName;
    }

    @Override
    public void setPasswordCallbackClassName(String passwordCallbackClassName) {
        this.passwordCallbackClassName = passwordCallbackClassName;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        // 如果未找到前綴“spring.datasource.druid”JDBC屬性,將使用“Spring.DataSource”前綴JDBC屬性。
        super.setUrl(url);
        super.setUsername(username);
        super.setPassword(password);
        super.setDriverClassName(driverClassName);
        super.setInitialSize(initialSize);
        super.setMinIdle(minIdle);
        super.setMaxActive(maxActive);
        super.setMaxWait(maxWait);
        super.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
        super.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
        super.setValidationQuery(validationQuery);
        super.setTestWhileIdle(testWhileIdle);
        super.setTestOnBorrow(testOnBorrow);
        super.setTestOnReturn(testOnReturn);
        super.setPoolPreparedStatements(poolPreparedStatements);
        super.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
        super.setDbType(dbType);
        super.setPasswordCallbackClassName(passwordCallbackClassName);
    }
}

3.6 創建配置文件

這里關鍵的配置就一個,EnableAutoConfiguration 啟動 SpringBoot 的自動自動配置,下面的方法是在初始化的時候,創建數據源實例,同樣也啟用了熱加載

package com.liyh.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.liyh.druid.DruidDataSourceWrapper;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@EnableAutoConfiguration
@Configuration
public class NacosConfigConfiguration {

    @Bean(initMethod = "init")
    @ConditionalOnMissingBean
    @RefreshScope
    public DruidDataSource dataSource() {
        return new DruidDataSourceWrapper();
    }
}

3.7 創建測試數據庫和用戶表

創建兩個MySQL 數據庫 test 和 test2,並導入用戶表,不同的用戶名方便測試

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for sys_user
-- ----------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user`  (
  `user_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用戶ID',
  `user_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用戶賬號',
  `nick_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用戶昵稱',
  PRIMARY KEY (`user_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用戶信息表' ROW_FORMAT = DYNAMIC;

-- ----------------------------
-- Records of sys_user
-- ----------------------------
INSERT INTO `sys_user` VALUES (1, 'admin', '超級管理員');

SET FOREIGN_KEY_CHECKS = 1;
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for sys_user
-- ----------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user`  (
  `user_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用戶ID',
  `user_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用戶賬號',
  `nick_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用戶昵稱',
  PRIMARY KEY (`user_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用戶信息表' ROW_FORMAT = DYNAMIC;

-- ----------------------------
-- Records of sys_user
-- ----------------------------
INSERT INTO `sys_user` VALUES (1, 'nacos', '嘻嘻哈哈');

SET FOREIGN_KEY_CHECKS = 1;

 

3.8 啟動項目

如上日志信息,我們可以看到 SpringBoot 項目啟動成功,成功讀取到了 nacos 中的配置文件

4. 創建測試接口

4.1 創建 TestController 接口

package com.liyh.controller;

import com.liyh.druid.DruidDataSourceWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("nacos")
@RefreshScope
public class TestController {
    @Autowired
    private DruidDataSourceWrapper dataSourceWrapper;

    @Value(value = "${spring.datasource.druid.master.url}")
    private String useLocalCache;

}

4.2 在TestController種添加測試接口讀取數據源配置信息

@GetMapping("/get")
@ResponseBody
public String get() {
    System.out.println("url: " + useLocalCache);
    return useLocalCache;
}

4.2.1 重啟項目測試接口

http://localhost:8090/nacos/get

4.2.2 修改Nacos配置文件,修改數據庫

 發布成功后,無需重啟項目會讀取最新配置

4.2.3 重新調取接口,可以獲取信息數據庫信息

http://localhost:8090/nacos/get

 

4.3 創建測試接口讀取數據庫用戶信息

@GetMapping("/query")
public String testDruid() throws SQLException {
    DruidPooledConnection connection = dataSourceWrapper.getConnection();
    Statement statement = connection.createStatement();
    ResultSet resultSet = statement.executeQuery("SELECT * from sys_user where user_id = 1;");
    String result = "沒有此用戶!!!";
    while (resultSet.next()) {
        result =  resultSet.getString("user_name") + " : " + resultSet.getString("nick_name");
        System.out.println(result);
        return result;
    }
    return result;
}

4.3.1 重啟項目測試接口

http://localhost:8090/nacos/query

 

4.3.2 修改Nacos配置文件,修改數據庫

 

4.3.3 重新調取接口,可以獲取信息數據庫信息

http://localhost:8090/nacos/query

4.4 完整的測試接口代碼

package com.liyh.controller;

import com.alibaba.druid.pool.DruidPooledConnection;
import com.liyh.druid.DruidDataSourceWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

@RestController
@RequestMapping("nacos")
@RefreshScope
public class TestController {

    @Autowired
    private DruidDataSourceWrapper dataSourceWrapper;

    @Value(value = "${spring.datasource.druid.master.url}")
    private String useLocalCache;

    @GetMapping("/get")
    @ResponseBody
    public String get() {
        System.out.println("url: " + useLocalCache);
        return useLocalCache;
    }

    @GetMapping("/query")
    public String testDruid() throws SQLException {
        DruidPooledConnection connection = dataSourceWrapper.getConnection();
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery("SELECT * from sys_user where user_id = 1;");
        String result = "沒有此用戶!!!";
        while (resultSet.next()) {
            result =  resultSet.getString("user_name") + " : " + resultSet.getString("nick_name");
            System.out.println(result);
            return result;
        }
        return result;
    }
}

5. 項目地址:springboot-nacos

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM