Spring 中使用Nacos服务发现

引入依赖

<dependency>
    <groupId>com.alibaba.nacos</groupId>
    <artifactId>nacos-spring-context</artifactId>
    <version>${latest.version}</version>
</dependency>

本文使用的版本为:1.1.1(与Spring 中使用Nacos配置管理一章引用的依赖一样)

示例

package com.yyoo.nacos.spring.discovery;

import com.alibaba.nacos.api.annotation.NacosProperties;
import com.alibaba.nacos.spring.context.annotation.discovery.EnableNacosDiscovery;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableNacosDiscovery(globalProperties = @NacosProperties(serverAddr = "127.0.0.1:8848"))
public class DiscoveryConfiguration {
}
package com.yyoo.nacos.spring.discovery;

import com.alibaba.nacos.api.annotation.NacosInjected;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

@Controller
@RequestMapping("discovery")
public class DiscoveryController {

    @NacosInjected
    private NamingService namingService;

    @RequestMapping(value = "/register", method = RequestMethod.GET)
    @ResponseBody
    public void register(@RequestParam String serviceName) throws NacosException {
        namingService.registerInstance(serviceName,"111.111.1.1",8888);
    }


    @RequestMapping(value = "/get", method = RequestMethod.GET)
    @ResponseBody
    public List<Instance> get(@RequestParam String serviceName) throws NacosException {
        return namingService.getAllInstances(serviceName);
    }
}
    @Test
    public void testSpring3() throws NacosException {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.scan("com.yyoo");
        context.refresh();

        String serviceName = "testDiscovery";
        DiscoveryController controller = context.getBean(DiscoveryController.class);
        controller.register(serviceName);
        System.out.println(controller.get(serviceName));

    }

注:此处是为了方便,模拟请求Controller,其实效果是一样的。

目前还未注册服务,所以打印结果为:

[Instance{instanceId=‘111.111.1.1#8888#DEFAULT#DEFAULT_GROUP@@testDiscovery’, ip=‘111.111.1.1’, port=8888, weight=1.0, healthy=true, enabled=true, ephemeral=true, clusterName=‘DEFAULT’, serviceName=‘DEFAULT_GROUP@@testDiscovery’, metadata={}}]

此时可以查看Nacos服务管理界面
在这里插入图片描述

@NacosInjected注解详解

@NacosInjected 是一个核心注解,用于在Spring Beans 中注入 ConfigService 或 NamingService 实例,并使这些实例可缓存

package com.yyoo.nacos.spring.discovery;

import com.alibaba.nacos.api.annotation.NacosInjected;
import com.alibaba.nacos.api.annotation.NacosProperties;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.naming.NamingService;
import org.springframework.stereotype.Component;

@Component
public class InjectedBean {

    @NacosInjected
    private ConfigService configService;

    @NacosInjected(properties = @NacosProperties(encode = "UTF-8"))
    private ConfigService configService2;

    @NacosInjected(properties = @NacosProperties(encode = "GBK"))
    private ConfigService configService3;

    @NacosInjected
    private NamingService namingService;

    @NacosInjected(properties = @NacosProperties(encode = "UTF-8"))
    private NamingService namingService2;

    @NacosInjected(properties = @NacosProperties(encode = "GBK"))
    private NamingService namingService3;


    public void testInjection() {

        System.out.println("configService == configService2:" + (configService == configService2));
        System.out.println("configService2 == configService3:" + (configService2 == configService3));

        System.out.println("namingService == namingService2:" + (namingService == namingService2));
        System.out.println("namingService2 == namingService3:" + (namingService2 == namingService3));
    }

}

结果:
configService == configService2:true
configService2 == configService3:false
namingService == namingService2:true
namingService2 == namingService3:false

结论: @NacosProperties 相等,则实例将是相同的,无论属性是来自全局还是自定义的 Nacos 属性。反之,如果@NacosProperties不相等,实例不是相同的,建议在同一个应用内使用相同的配置。

配置监听注解

package com.yyoo.nacos.spring.bean;

import com.alibaba.nacos.api.annotation.NacosInjected;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.annotation.NacosConfigListener;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ConfigBean {

    @NacosInjected
    private ConfigService configService;

    @NacosConfigListener(dataId = "com.yyoo.nacos.sdk.CofingServiceTest",groupId = "Nacos:Test")
    public void onMessage(String config) {
        System.out.println("listener:"+config);
    }

}
    @NacosConfigListener(dataId = "com.yyoo.nacos.sdk.CofingServiceTest",groupId = "Nacos:Test")
    public void onMessage(String config) {
        System.out.println("listener:"+config);
    }

以上代码等价于:

configService.addListener("com.yyoo.nacos.sdk.CofingServiceTest", "Nacos:Test", new AbstractListener() {
    @Override
    public void receiveConfigInfo(String config) {
        System.out.println("listener:"+config);
    }
});

为监听添加类型转换器

@NacosConfigListener 的类型转换包括内置和自定义实现。 默认情况下,内置类型转换基于 Spring DefaultFormattingConversionService来实现。常见的基本类型都可以自动转换。
比如我们上面示例的DataId:“com.yyoo.nacos.sdk.CofingServiceTest”,groupId:“Nacos:Test”

在这里插入图片描述

其是一个Json类型,我们监听示例中使用String类型是可以的。如果我们需要将其在监听中解析成对象呢?这个时候就需要类型转换器了,自定义实现NacosConfigConverter接口即可自己实现类型转换器,比如我们自定义实现上面JSON配置内容的类型转换器

package com.yyoo.nacos.spring.bean;

import com.alibaba.nacos.api.config.convert.NacosConfigConverter;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;


public class TestNacosConfigConverter implements NacosConfigConverter<TestNacosConfig> {

    @Override
    public boolean canConvert(Class<TestNacosConfig> targetType) {
        return true;
    }

    @Override
    public TestNacosConfig convert(String config) {
        ObjectMapper mapper = new ObjectMapper();
        TestNacosConfig obj = null;
        try {
            obj =  mapper.readValue(config,TestNacosConfig.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return obj;
    }
}

编写自定义对象

package com.yyoo.nacos.spring.bean;

public class TestNacosConfig {
    private String conf1;
    private String conf2;

    public String getConf1() {
        return conf1;
    }

    public void setConf1(String conf1) {
        this.conf1 = conf1;
    }

    public String getConf2() {
        return conf2;
    }

    public void setConf2(String conf2) {
        this.conf2 = conf2;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("TestNacosConfig{");
        sb.append("conf1='").append(conf1).append('\'');
        sb.append(", conf2='").append(conf2).append('\'');
        sb.append('}');
        return sb.toString();
    }
}

修改添加监听的程序

    @NacosConfigListener(dataId = "com.yyoo.nacos.sdk.CofingServiceTest",groupId = "Nacos:Test",converter = TestNacosConfigConverter.class)
    public void onMessage(TestNacosConfig config) {
        System.out.println("bean listener:"+config);
    }

测试代码:

    @Test
    public void testSpring5() throws NacosException, InterruptedException {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.scan("com.yyoo");
        context.refresh();

        Thread.sleep(60000); // 休眠60秒,保证主程序不关闭

    }

测试代码主程序没有停止前,在Nacos配置界面修改对应的配置conf2=‘test2’,监听程序打印结果:

bean listener:TestNacosConfig{conf1=‘test1’, conf2=‘test2’}

监听超时时间设置

由于运行自定义的 NacosConfigConverter 可能需要一些时间,因此您可以在 @NacosConfigListener.timeout() 属性中设置最大执行时间,以防止它阻塞其他侦听器。只需在@NacosConfigListener注解上加上timeout属性配置即可,timeout默认为1000L

    @NacosConfigListener(dataId = "com.yyoo.nacos.sdk.CofingServiceTest",groupId = "Nacos:Test"
            ,converter = TestNacosConfigConverter.class,timeout = 1000L)
    public void onMessage(TestNacosConfig config) {
        System.out.println("bean listener:"+config);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值