1. 1 不可撤销
  2. 2 小年兽 程嘉敏
  3. 3 手放开 李圣杰
  4. 4 迷人的危险3(翻自 dance flow) FAFA
  5. 5 山楂树之恋 程佳佳
  6. 6 summertime cinnamons / evening cinema
  7. 7 不谓侠(Cover 萧忆情Alex) CRITTY
  8. 8 神武醉相思(翻自 优我女团) 双笙
  9. 9 空山新雨后 音阙诗听 / 锦零
  10. 10 Wonderful U (Demo Version) AGA
  11. 11 广寒宫 丸子呦
  12. 12 陪我看日出 回音哥
  13. 13 春夏秋冬的你 王宇良
  14. 14 世界が终わるまでは… WANDS
  15. 15 多想在平庸的生活拥抱你 隔壁老樊
  16. 16 千禧 徐秉龙
  17. 17 我的一个道姑朋友 双笙
  18. 18 大鱼  (Cover 周深) 双笙
  19. 19 霜雪千年(Cover 洛天依 / 乐正绫) 双笙 / 封茗囧菌
  20. 20 云烟成雨(翻自 房东的猫) 周玥
  21. 21 情深深雨濛濛 杨胖雨
  22. 22 Five Hundred Miles Justin Timberlake / Carey Mulligan / Stark Sands
  23. 23 斑马斑马 房东的猫
  24. 24 See You Again Wiz Khalifa / Charlie Puth
  25. 25 Faded Alan Walker / Iselin Solheim
  26. 26 Natural J.Fla
  27. 27 New Soul Vox Angeli
  28. 28 ハレハレヤ(朗朗晴天)(翻自 v flower) 猫瑾
  29. 29 像鱼 王贰浪
  30. 30 Bye Bye Bye Lovestoned
  31. 31 Blame You 眠 / Lopu$
  32. 32 Believer J.Fla
  33. 33 书信 戴羽彤
  34. 34 柴 鱼 の c a l l i n g【已售】 幸子小姐拜托了
  35. 35 夜空中最亮的星(翻自 逃跑计划) 戴羽彤
  36. 36 慢慢喜欢你 LIve版(翻自 莫文蔚) 戴羽彤
  37. 37 病变(翻自 cubi) 戴羽彤
  38. 38 那女孩对我说 (完整版) Uu
  39. 39 绿色 陈雪凝
  40. 40 月牙湾 LIve版(翻自 F.I.R.) 戴羽彤
夜空中最亮的星(翻自 逃跑计划) - 戴羽彤
00:00 / 04:10

夜空中最亮的星 能否听清

那仰望的人 心底的孤独和叹息

夜空中最亮的星 能否记起

那曾与我同行 消失在风里的身影

我祈祷拥有一颗透明的心灵

和会流泪的眼睛

给我再去相信的勇气

越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请指引我靠近你

夜空中最亮的星 是否知道

那曾与我同行的身影 如今在哪里

夜空中最亮的星 是否在意

是等太阳先升起 还是意外先来临

我宁愿所有痛苦都留在心底

也不愿忘记你的眼睛

哦 给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行 哒~

我祈祷拥有一颗透明的心灵

和会流泪的眼睛 哦

给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行

springboot整合nacos动态获取druid配置

前言

是不是还有好多小伙伴不知道nacos是啥?其实,我也是从上一次nacos爆出漏洞,才知道还有nacos这个组件,而且目前这个组件应用很广泛,很多项目都用它来做配置中心和注册中心,今天我们分享的内容就是nacos作为配置中心使用的一个小demo

在完成这个小demo之前,我查了好多示例和博客,但是都没有找到符合我需求的,所以走了好多弯路,才让这个demo完整的跑起来,现在我们就来看下如何实现springboot+nacos+druid动态获取数据库配置信息。

今天的demo内容比较多,如果你恰好在学习nacos,认真看完,肯定会有收获。

正文

nacos是什么

在开始讲解这个demo之前,我们先看下什么是naconsnacos是阿里巴巴的一个开源项目,官网给它的定义是:

一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。

也就是说,它可以实现动态的服务发现,能够实现配置管理,可以作为服务管理平台,简介就到这里,更多信息直接去看官方文档:

https://nacos.io/zh-cn/docs/what-is-nacos.html

如何使用nacos

了解它的目的,主要还是为了在我们的项目中使用它,所以我们直接来看如何使用它。

下载nacos

进入官网,点击前往github,你需要去nacosGitHub发布列表中下载,不清楚的小伙伴直接访问下面的网址进入下载页:

https://github.com/alibaba/nacos/releases

最新版本是2.0.0-BETA,是个测试版本,目前最新的稳定版本是1.4.0,本次示例也是这个版本

点击Assets,选择.zip文件,然后应该就开始下载了,下载可能比较慢

解压zip文件

zip文件结构是这样的,直接解压就行,也不需要配置环境变量

运行启动nacos服务

进入nacosbin目录,打开cmd窗口,linux打开sh窗口,执行如下命令:

windos环境:

cmd startup.cmd -m standalone

linux环境:

sh startup.sh -m standalone

如果您使用的是ubuntu系统,或者运行脚本报错提示[[符号找不到,可尝试如下运行:

bash startup.sh -m standalone

其中,standalone表示单机模式,如果不加这个参数,默认是以集群模式运行的(cluster

关闭nacos服务

Linux/Unix/Mac
sh shutdown.sh
Windows
cmd shutdown.cmd

或者双击shutdown.cmd运行文件。

服务注册&发现和配置管理

这里的内容,我直接copy的官网文档,大概看一下就可以了,和示例关系不大。下面的命令就是通过http接口的方式,注册服务、发现服务、发布配置和获取配置。

服务注册
curl -X POST 'http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=nacos.naming.serviceName&ip=20.18.7.10&port=8080'
服务发现
curl -X GET 'http://127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=nacos.naming.serviceName'
发布配置
curl -X POST "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test&content=HelloWorld"
获取配置
curl -X GET "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test"

修改nacos服务端配置信息

这个配置文件里面还可以设置nacos的数据存储,默认的数据存储是derby,这是个完全用java编写的数据库,非常小巧,核心部分derby.jar只有2M,所以既可以做为单独的数据库服务器使用,也可以内嵌在应用程序中使用。如果要启用mysql,可以修改相关配置文件,进行启用:

访问nacos服务

如果没有修改nacos的配置,直接浏览器打开如下地址即可,如果修改了端口,需要把端口改成你修改的端口:

http://127.0.0.1:8848/nacos

默认用户名和密码都是nacos,登陆成功之后就可以发布你的配置信息了。

发布配置信息

因为我已经加过配置信息了,如果是第一次访问,应该是没有配置信息的。点击右边的+号进行创建

输入data-id,必须唯一,类似于主键,不能重复;选择配置格式,这里我选择properties;然后点击发布,一个配置信息就发布成功了

我们现在来测试下,我们用如下命令:

curl -X GET "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos-test-demo&group=DEFAULT_GROUP"

返回结果:

springboot整合nacos和druid

这里才是今天的重点,但是我还是想直接上代码,需要解释的地方,我会补充说明的。

创建springboot项目

引入如下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jdbc</artifactId>
    <exclusions>
        <exclusion>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.21</version>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

除了spring-boot-start-web外,我们引入了spring-cloud-starter-alibaba-nacos-config,这个是nacos的依赖,剩下的就是数据库哈数据源相关的依赖了。

增加nacos配置文件

spring:
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        prefix: springboot-nacos-demo
        file-extension: yaml
        username: nacos
        password: nacos

  profiles:
    active: dev

其中,server-addrnacos的服务地址,如果要修改服务端口的话,可以进入conf找到application.properties进行修改,详细修改过程看前面的内容;

prefixnacos服务中配置的data-id的前缀,和file-extensionprofiles.active最终组合成data-id

file-extension表示文件扩展名,目前支持propetiesYAML,因为springboot目前只支持这两种配置文件,当然nacos本身支持多种配置文件:TEXTJSONXMLYAMLHTMLProperties

usernamenacos服务端的登陆用户名;passwordnacso服务端的登陆密码。profilesspringboot的配置,这里不讲。

发布数据源配置

我这里的数据源密码是加密的,如果你不想加密,删除connection-properties配置,password改成明文密码就可以了,如果你也想加密,可以参考我之前发过的文章:spring boot基于DRUID数据源密码加密及数据源监控实现

spring:
  #阿里巴巴druid数据源配置
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    sql-script-encoding: utf-8
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      username: root
      url: jdbc:mysql://127.0.0.1:3307/userlogin?characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&serverTimezone=Asia/Shanghai
      password: Y2YOft/vPjw/JFPkevqZZKi8pCHu5ambR2ivSxgipTbL76pOoxNw3Un5Hcarbe9AqUImr+wS7YI6TjJZOVYjzA==
      connection-properties: config.decrypt=true;config.decrypt.key=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJI/xqbyvpVttxfAKulKeSTIb7tZAGaFcPyTnE2r7AHTQ8kOnqKXDda4u59umt9XBFxi7db28KxeVooB138zuRUCAwEAAQ==
      filter:
        config:
          enabled: true
      # 连接池的配置信息
      # 初始化时建立物理连接的个数
      initial-size: 3
      # 连接池最小连接数
      min-idle: 3
      # 连接池最大连接数
      max-active: 20
      # 获取连接时最大等待时间,单位毫秒
      max-wait: 60000
      # 申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
      test-while-idle: true
      # 既作为检测的间隔时间又作为testWhileIdel执行的依据
      time-between-connect-error-millis: 60000
      # 销毁线程时检测当前连接的最后活动时间和当前时间差大于该值时,关闭当前连接
      min-evictable-idle-time-millis: 30000
      # 用来检测连接是否有效的sql 必须是一个查询语句
      # mysql中为 select 'x'
      # oracle中为 select 1 from dual
      validationQuery: select 'x'
      # 申请连接时会执行validationQuery检测连接是否有效,开启会降低性能,默认为true
      test-on-borrow: false
      # 归还连接时会执行validationQuery检测连接是否有效,开启会降低性能,默认为true
      test-on-return: false
      # 是否缓存preparedStatement,mysql5.5+建议开启
      pool-prepared-statements: true
      # 当值大于0时poolPreparedStatements会自动修改为true
      max-pool-prepared-statement-per-connection-size: 20
      # 合并多个DruidDataSource的监控数据
      use-global-data-source-stat: false
      # 配置扩展插件
      #监控统计拦截的filters
      filters: stat,wall,slf4j
      # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
      connect-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
      # 定时输出统计信息到日志中,并每次输出日志会导致清零(reset)连接池相关的计数器。
      time-between-log-stats-millis: 300000
      # 配置DruidStatFilter
      web-stat-filter:
        enabled: true
        url-pattern: '/*'
        exclusions: '*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*'
      # 配置DruidStatViewServlet
      stat-view-servlet:
        # 是否启用StatViewServlet(监控页面)默认值为false(考虑到安全问题默认并未启动,如需启用建议设置密码或白名单以保障安全)
        enabled: true
        url-pattern: '/druid/*'
        # IP白名单(没有配置或者为空,则允许所有访问)
        allow: 127.0.0.1,192.168.0.1
        # IP黑名单 (存在共同时,deny优先于allow)
        deny: 192.168.0.128
        # 禁用HTML页面上的“Reset All”功能
        reset-enable: false
        # 登录名
        login-username: admin
        # 登录密码
        login-password: admin

这些配置文件发布到nacos中:

data-id我前面说了,已经很清楚了。

自定义DruidDatasouceWrapper

DruidDatasouceWrapper要继承DruidDataSource

RefreshScope的作用是实现配置、实例热加载,也就是我们重写修改配置信息后,spring会销毁当前类的实例,然后重新创建一个新的实例放到容器中,也是实现数据源配置实时更新的关键

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;

/**
 * @program: springboot-nacos-demo
 * @description:
 * @author: syske
 * @create: 2021-02-28 11:33
 */
@Configuration
@RefreshScope
public class DruidDataSourceWrapper extends DruidDataSource implements InitializingBean {
    @Value("${spring.datasource.druid.url}")
    private String url;
    @Value("${spring.datasource.druid.username}")
    private String username;
    @Value("${spring.datasource.druid.password}")
    private String password;
    @Value("${spring.datasource.druid.driver-class-name}")
    private String driverClassName;
    @Value("${spring.datasource.druid.connection-properties}")
    private String connectionProperties;

    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 setConnectionProperties(String connectionProperties) {
        this.connectionProperties = connectionProperties;
    }

    @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.setConnectionProperties(connectionProperties);
        super.setDbType(dbType);
        super.setPasswordCallbackClassName(passwordCallbackClassName);
    }
}

配置nacos

这里关键的配置就一个,EnableAutoConfiguration启动springboot的自动自动配置,下面的方法是在初始化的时候,创建数据源实例,同样也启用了热加载

import com.alibaba.druid.pool.DruidDataSource;
import io.github.syske.springbootnacosdemo.druidconfig.DruidDataSourceWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;

/**
 * Nacos配置
 */
@EnableAutoConfiguration
@Configuration
public class NacosConfigConfiguration {
    private final Logger LOGGER = LoggerFactory.getLogger(NacosConfigConfiguration.class);

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

测试

到这里,核心代码就全部完了,我们启动demo测试下:

如上日志信息,我们可以看到springboot启动的时候加载了nacos发布的配置信息,然后还会有数据源初始成功的提示信息:

然后我们写一个controller测试下:

@RestController
public class TestController {

    @Autowired
    private DruidDataSourceWrapper dataSourceWrapper;

    @RequestMapping("/test")
    public String testDruid() throws SQLException {
        DruidPooledConnection connection = dataSourceWrapper.getConnection();
        Statement statement = connection.createStatement();
        ResultSet  resultSet = statement.executeQuery("SELECT * from user;");
        System.out.println(resultSet);
        while(resultSet.next()){
            System.out.println(resultSet.getString("username"));
        }
        return "hello druid";
    }
}

我这里有两个数据库,都有user表,我现在的数据库地址配的是userlogin这个库,我先访问下,后台打印信息如下:

然后我们将数据库改成my_db_test,然后发布配置,再次访问:

配置发布完成后,springboot后台已经打印了配置更新的日志,说明配置已经被刷新:

然后我们再访问:

从日志记录来看,我们再次访问的时候,数据源重新初始化,当然最后打印的结果也和我们预期的一样,打印了我们刚加的配置对应的数据表里面的用户信息。当然再改回,也是可以的:

再次访问:

而且后台也有数据库url修改的提示信息

结语

好了,今天的内容就到这里吧,本次实例比较完整的介绍了springboo + nacos + druid实现动态获取数据库配置的构建过程,同时也比较详细的说明了nacos的相关配置,我觉得很完美,至少我很满意。关于这个demo,我上周就在弄,但是项目一直跑不起来,也没有参考的样例,所以就搁置着,今天总算搞定了,很奈斯哦。下面是demo的完整代码获取地址:

https://github.com/Syske/learning-dome-code/tree/dev/springboot-nacos-demo
posted @ 2021-02-28 17:11  云中志  阅读(723)  评论(0编辑  收藏  举报