spring boot 实现nacos监听自定义内容

2,860 阅读2分钟

这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战

前言

不知道大家平常有没有遇到一个nacos的麻烦点, spring boot、cloud集成nacos的时候是只能properties\yml格式的,此时如果想要监听一个很大的json文件时没有办法的,所以只能自己动手写

昨天写了一篇nacos配置读取、监听的源码笔记,基于这个修改

思路

自定义监听

nacos配置读取、监听核心的类其实就是 NacosContextRefresher

// 注册监听器
private void registerNacosListener(final String group, final String dataId) {

   Listener listener = listenerMap.computeIfAbsent(dataId, i -> new Listener() {
      @Override
      public void receiveConfigInfo(String configInfo) {
         refreshCountIncrement();
         String md5 = "";
         if (!StringUtils.isEmpty(configInfo)) {
            try {
               MessageDigest md = MessageDigest.getInstance("MD5");
               md5 = new BigInteger(1, md.digest(configInfo.getBytes("UTF-8")))
                     .toString(16);
            }
            catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
               log.warn("[Nacos] unable to get md5 for dataId: " + dataId, e);
            }
         }
         refreshHistory.add(dataId, md5);
         applicationContext.publishEvent(
               new RefreshEvent(this, null, "Refresh Nacos config"));
         if (log.isDebugEnabled()) {
            log.debug("Refresh Nacos config group " + group + ",dataId" + dataId);
         }
      }

      @Override
      public Executor getExecutor() {
         return null;
      }
   });

   try {
      configService.addListener(dataId, group, listener);
   }
   catch (NacosException e) {
      e.printStackTrace();
   }
}

但是呢这个方法是private的,所以我们只能自己重写一个类,不能继承

另外RefreshEvent这个事件不适合我们场景,所以也得自定义一个

同理事件接收器也是

代码

配置修改事件类

public class ConfigChangeEvent extends ApplicationEvent {
    String dataId;

    String content;

    public ConfigChangeEvent(Object source, String dataId, String content) {
        super(source);
        this.dataId = dataId;
        this.content = content;
    }
}

配置修改事件监听


@Slf4j
@Component
public class ConfigEventListener implements ApplicationListener<ConfigChangeEvent> {

    JSONObject jsonObject;
    
    @Override
    public void onApplicationEvent(ConfigChangeEvent event) {
        Object source = event.getSource();
        jsonObject = JSON.parseObject(event.content);
        log.info("收到事件推送 ===> {}", source.toString());
    }
}

注册监听器类

@Slf4j
@Component
public class CusNacosConfigRef implements ApplicationListener<ApplicationReadyEvent>, ApplicationContextAware {

    private static final AtomicLong REFRESH_COUNT = new AtomicLong(0);

    private final NacosRefreshHistory refreshHistory;

    private final ConfigService configService;

    private ApplicationContext applicationContext;

    private AtomicBoolean ready = new AtomicBoolean(false);

    private Map<String, Listener> listenerMap = new ConcurrentHashMap<>(16);

    public CusNacosConfigRef(NacosConfigProperties nacosConfigProperties) {
        this.refreshHistory = new NacosRefreshHistory();
        this.configService = nacosConfigProperties.configServiceInstance();

    }

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        // many Spring context
        if (this.ready.compareAndSet(false, true)) {
            this.registerNacosListenersForApplications();
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    private void registerNacosListenersForApplications() {
        // 这个地方需要优化,改成配置形式,
        String dataId = "boot-demo.json";
        registerNacosListener("DEFAULT_GROUP", dataId);
    }

    private void registerNacosListener(final String group, final String dataId) {

        Listener listener = listenerMap.computeIfAbsent(dataId, i -> new Listener() {
            @Override
            public void receiveConfigInfo(String configInfo) {
                refreshCountIncrement();
                String md5 = "";
                if (!StringUtils.isEmpty(configInfo)) {
                    try {
                        MessageDigest md = MessageDigest.getInstance("MD5");
                        md5 = new BigInteger(1, md.digest(configInfo.getBytes("UTF-8")))
                                .toString(16);
                    }
                    catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
                        log.warn("[Nacos] unable to get md5 for dataId: " + dataId, e);
                    }
                }
                refreshHistory.add(dataId, md5);
                // 推送配置修改事件
                applicationContext.publishEvent(new ConfigChangeEvent(this, dataId, configInfo));
                if (log.isDebugEnabled()) {
                    log.debug("Refresh Nacos config group " + group + ",dataId" + dataId);
                }
            }

            @Override
            public Executor getExecutor() {
                return null;
            }
        });

        try {
            configService.addListener(dataId, group, listener);
        }
        catch (NacosException e) {
            e.printStackTrace();
        }
    }

    public static long getRefreshCount() {
        return REFRESH_COUNT.get();
    }

    public static void refreshCountIncrement() {
        REFRESH_COUNT.incrementAndGet();
    }

}