【Java】Spring Boot 2 集成 nacos
官方文档:https://nacos.io/zh-cn/docs/quick-start-spring-boot.html
项目地址:https://gitee.com/codingce/codingce-leetcode/tree/master/%E9%9D%A2%E7%BB%8F/Java/Nacos
pom
本次Spring Boot版本 2.2.6.RELEASE
,nacos-config 版本 0.2.7
,nacos-discovery版本 0.2.7
parent
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.6.RELEASE</version><relativePath/> <!-- lookup parent from repository -->
</parent>
dependencies
<!-- nacos-config-->
<dependency><groupId>com.alibaba.boot</groupId><artifactId>nacos-config-spring-boot-starter</artifactId><version>0.2.7</version>
</dependency>
<!-- nacos-discovery-->
<dependency><groupId>com.alibaba.boot</groupId><artifactId>nacos-discovery-spring-boot-starter</artifactId><version>0.2.7</version>
</dependency>
Nacos
Nacos版本 nacos-server-2.1.0
MySQL
数据持久化 D:\dev\nacos-server-2.1.0\nacos\conf\application.properties
文件修改
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=root
db.password.0=1234567890
创建数据库 nacos_config
,导入数据 nacos-mysql.sql
(配置文件文件夹下)
启动方式 ./startup.cmd -m standalone
单机方式.
登录地址 http://localhost:8848/nacos/#/login
默认账号密码 nacos
nacos
实现配置的动态变更
注解方式
示例使用默认的空间
my.http_url=aaaaa
server.port=8092
.................
package cn.com.codingce.demo;import com.alibaba.nacos.spring.context.annotation.config.NacosPropertySource;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@NacosPropertySource(dataId = "test", autoRefreshed = true)
@SpringBootApplication
public class CodingceDemoApplication {public static void main(String[] args) {SpringApplication.run(CodingceDemoApplication.class, args);}}
启动项目
2023-02-26 10:39:28.055 INFO 9544 --- [ main] c.a.b.n.c.u.NacosConfigPropertiesUtils : nacosConfigProperties : NacosConfigProperties{serverAddr='127.0.0.1:8848', contextPath='null', encode='null', endpoint='null', namespace='null', accessKey='null', secretKey='null', ramRoleName='null', autoRefresh=false, dataId='null', dataIds='null', group='DEFAULT_GROUP', type=null, maxRetry='null', configLongPollTimeout='null', configRetryTime='null', enableRemoteSyncConfig=false, extConfig=[], bootstrap=Bootstrap{enable=false, logEnable=false}}
测试
package cn.com.codingce.demo.conrtoller;import cn.com.codingce.demo.utils.ResT;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("test")
public class Test {/*** 通过NacosValue读取配置,* autoRefreshed 表示是否自动更新*/@NacosValue(value = "${my.http_url}", autoRefreshed = true)private String httpUrl;/*** 信息*/@RequestMapping(value = "/a", method = RequestMethod.GET)public ResT info() {return ResT.ok().put("nacos", httpUrl);}}
http://localhost:8092/test/a
测试可以实现动态的配置变更.
配置文件方式
采用自定义的命名空间进行测试,新建命名空间
新建test配置
这里我们已经创建完了,就截一张编辑图片.
配置文件 application.properties
# nacos
# nacos.config.bootstrap.enable 是否开启 Nacos 配置预加载功能.默认为 false, 这个配置必须设置, 否则不会读取 properties 配置文件
nacos.config.bootstrap.enable=true
# bootstrap.log-enable 是否开启 Nacos 支持日志级别的加载时机. 默认为 false.
nacos.config.bootstrap.log-enable=true
# server-addr 本机启动, 远端写远端的ip:端口
nacos.config.server-addr=127.0.0.1:8848
# nacos.config.type=properties 这个配置必须设置, 未设置会报空指针, 支持的类型 properties xml json text html yaml
nacos.config.type=properties
# Data Id
nacos.config.dataId=test
# 使用的 Nacos 的命名空间, 默认为 null.
nacos.config.namespace=7746f477-222d-4c88-8244-3fae3ae5bdfa
# Group
nacos.config.group=dev
# 自动刷新
nacos.config.auto-refresh=true
nacos.config.bootstrap.enable=true
nacos.config.type=properties
这两个配置有点坑了,也怪自己不仔细,大家用的时候注意是否缺少这两个配置~
2023-02-26 10:57:13.579 INFO 7856 --- [ main] c.a.b.n.c.u.NacosConfigPropertiesUtils : nacosConfigProperties : NacosConfigProperties{serverAddr='127.0.0.1:8848', contextPath='null', encode='null', endpoint='null', namespace='7746f477-222d-4c88-8244-3fae3ae5bdfa', accessKey='null', secretKey='null', ramRoleName='null', autoRefresh=true, dataId='test', dataIds='null', group='dev', type=PROPERTIES, maxRetry='null', configLongPollTimeout='null', configRetryTime='null', enableRemoteSyncConfig=false, extConfig=[], bootstrap=Bootstrap{enable=true, logEnable=true}}
测试可以实现动态的配置变更.
整合Nacos多环境
Data Id 方式
本次展示以 Data Id
方式实现多环境 dev、prod
项目配置文件
application.yml
spring:profiles:active: dev
application-dev.yml
spring:application:name: codingce-demo
nacos:config:auto-refresh: truebootstrap:enable: truelog-enable: truedata-ids: nacos-dev.propertiesgroup: devnamespace: 4f1d4fa1-7df7-47dd-8274-1e0cc53ebbb7server-addr: 127.0.0.1:8848type: properties# data-id:
management:endpoint:health:show-details: alwaysendpoints:web:exposure:include: '*'
application-prod.yml
spring:application:name: codingce-demo
nacos:config:auto-refresh: truebootstrap:enable: truelog-enable: truedata-ids: nacos-dev.propertiesgroup: devnamespace: 4f1d4fa1-7df7-47dd-8274-1e0cc53ebbb7server-addr: 127.0.0.1:8848type: properties# data-id:
management:endpoint:health:show-details: alwaysendpoints:web:exposure:include: '*'
实现服务的注册与发现
NacosRegisterConfiguration
配置文件
package cn.com.codingce.demo.config;import com.alibaba.nacos.api.annotation.NacosInjected;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;import javax.annotation.PostConstruct;/*** @author 24607*/
@Configuration
public class NacosRegisterConfiguration {@Value("${server.port}")private int serverPort;@Value("${spring.application.name}")private String applicationName;@NacosInjectedprivate NamingService namingService;@PostConstructpublic void registerInstance() throws NacosException {namingService.registerInstance(applicationName, "127.0.0.1", serverPort, "DEFAULT");}
}
application-dev.yml
nacos:discovery:server-addr: 127.0.0.1:8848username: nacospassword: nacos
服务生产者
代码:
package cn.com.codingce.demo.conrtoller;import cn.com.codingce.demo.utils.ResT;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import static org.springframework.web.bind.annotation.RequestMethod.GET;@RestController
@RequestMapping("test")
public class Test {/*** 通过NacosValue读取配置,* autoRefreshed 表示是否自动更新*/@NacosValue(value = "${my.http_url}", autoRefreshed = true)private String httpUrl;/*** 信息*/@RequestMapping(value = "/a", method = GET)public ResT info() {return ResT.ok().put("nacos", httpUrl);}/*** name*/@RequestMapping(value = "/name", method = GET, produces = "application/json;charset=UTF-8")public String name() {return httpUrl;}}
服务消费者
代码
package cn.com.codingce.customer.controller;import com.alibaba.nacos.api.annotation.NacosInjected;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;import java.util.HashMap;
import java.util.Map;@RestController
@RequestMapping("test")
public class OrderController {private static final Logger logger = LoggerFactory.getLogger(OrderController.class);@NacosInjectedprivate NamingService namingService;private RestTemplate restTemplate = new RestTemplate();@RequestMapping(value = "/getOrder")public Map<String, Object> getOrder() {Map<String, Object> order = new HashMap<>();order.put("username", queryUserName());order.put("money", 100.00);return order;}private String queryUserName() {try {if (namingService != null) {// 选择 codingce-demo 服务的一个健康的实例(可配置负载均衡策略)Instance instance = namingService.selectOneHealthyInstance("codingce-demo");// 拼接请求接口url并请求选取的实例String url = "http://" + instance.getIp() + ":" + instance.getPort() + "/test/name";ResponseEntity<String> entity = restTemplate.getForEntity(url, String.class);return entity.getBody();}} catch (Exception e) {logger.error("query user error", e);}return null;}}
测试
如有问题欢迎讨论,踩了很多坑…