栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Springmvc+Nacos+自定义Scope+自定义PropertyPlaceholderConfigurer,实现自动刷新配置文件

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Springmvc+Nacos+自定义Scope+自定义PropertyPlaceholderConfigurer,实现自动刷新配置文件

目录

背景

实现

Nacos环境搭建

Springmvc项目

pom引入nacos依赖

自定义scope

静态资源类

自定义PropertyPlaceholderConfigurer

spring-application.xml配置

config.properties


背景

springmvc项目自定义PropertyPlaceholderConfigurer,

在mergeProperties()中对接nacos配置中心,

需要自动刷新配置文件的类添加@RefreshScope注解,

监听配置中心文件更新,清理包含@RefreshScope注解的bean

实现自动刷新配置文件

实现

Nacos环境搭建

官网:什么是 Nacos

Spring集成文档:Nacos Spring 快速开始

参考之前写的博文:Springcloud+Druid+Mybatis+Seata+Nacos动态切换多数据源,分布式事务的实现

使用的nacos版本1.4.1 

Springmvc项目

pom引入nacos依赖

    com.alibaba.nacos
    nacos-spring-context
    1.1.1

自定义scope

RefreshScope注解

package com.luck.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Scope(BeanRefreshScope.SCOPE_REFRESH)
@Documented
public @interface RefreshScope {
	ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;
}

BeanRefreshScope用来维护添加了@RefreshScope的bean对象 

package com.luck.annotation;

import java.util.concurrent.ConcurrentHashMap;

import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;

public class BeanRefreshScope implements Scope {

	public static final String SCOPE_REFRESH = "refresh";

	private static final BeanRefreshScope INSTANCE = new BeanRefreshScope();

	private static ConcurrentHashMap beanMap = new ConcurrentHashMap<>();

	public BeanRefreshScope() {
	}

	public static BeanRefreshScope getInstance() {
		return INSTANCE;
	}

	
	public static void clean() {
		beanMap.clear();
	}

	@Override
	public Object get(String name, ObjectFactory objectFactory) {
		Object bean = beanMap.get(name);
		if (bean == null) {
			bean = objectFactory.getObject();
			beanMap.put(name, bean);
		}
		return bean;
	}

	@Override
	public Object remove(String name) {
		return beanMap.remove(name);
	}

	@Override
	public void registerDestructionCallback(String name, Runnable callback) {

	}

	@Override
	public Object resolveContextualObject(String key) {
		return null;
	}

	@Override
	public String getConversationId() {
		return null;
	}

}

使用示例

package com.luck.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.luck.annotation.RefreshScope;
import com.luck.utils.Constant;

@RestController
@RefreshScope
public class TestController {

	@Value("${test:123456}")
	private String test;

	@GetMapping("esbapi/test")
	public void print() {
		System.out.println(test);

		System.out.println(Constant.NACOS_SERVER_ADDRESS);

		System.out.println(Constant.getProperty("abc", ""));
	}
}

静态资源类
package com.luck.utils;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;


@Component
public class Constant {

	
	public static String NACOS_SERVER_ADDRESS;

	
	private static Properties p;

	
	private static Environment environment;

	@Autowired
	public void setEnvironment(Environment environment) {
		Constant.environment = environment;
	}

	@Value("${nacos.config.server-addr:}")
	public void setNACOS_SERVER_ADDRESS(String nACOS_SERVER_ADDRESS) {
		NACOS_SERVER_ADDRESS = nACOS_SERVER_ADDRESS;
	}

	
	protected static void init(String propertyFileName) {
		InputStream in = null;
		p = new Properties();
		try {
			in = Constant.class.getResourceAsStream(propertyFileName);
			p.clear();
			if (in != null) {
				p.load(in);
			}
		} catch (IOException e) {
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
				}
			}
		}
	}

	
	public static String getProperty(String key, String defaultValue) {
		String value = null;
		if (null != environment) {
			value = environment.getProperty(key);
		}
		if (StringUtils.isBlank(value)) {
			if (null == p) {
				init("/config.properties");
			}
			value = p.getProperty(key, defaultValue);
		}
		return value;
	}
}

自定义PropertyPlaceholderConfigurer
package com.luck.config;

import java.io.IOException;
import java.io.StringReader;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.util.CollectionUtils;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;

import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;

import com.luck.annotation.BeanRefreshScope;
import com.luck.utils.Constant;

public class LuckPreferencesPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
	protected Logger logger = LoggerFactory.getLogger(getClass());

	private static String NACOS_DATA_ID = Constant.getProperty("nacos.config.dataid", "config.properties");
	private static String NACOS_GROUP = Constant.getProperty("nacos.config.group", "DEFAULT_GROUP");
	private static String NACOS_NAMESPACE = Constant.getProperty("nacos.config.namespace", "");
	private static String NACOS_SERVERADDR = Constant.getProperty("nacos.config.server-addr", null);

	
	private static ConfigService configService;

	
	private static Properties nacosProps;

	
	private static Properties allProps;

	@Override
	protected Properties mergeProperties() throws IOException {
		Properties allProperties = super.mergeProperties();
		if (null == configService) {
			configNacos(allProperties);
		}
		if (null != nacosProps) {

			logger.info("设置Spring环境配置信息");

			WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
			if (null != context) {
				Map props = new LinkedHashMap<>(nacosProps.size());
				nacosProps.stringPropertyNames().stream().forEach(key -> props.put(key, nacosProps.getProperty(key)));
				Environment environment = context.getEnvironment();
				MutablePropertySources propertySources = ((ConfigurableEnvironment) environment).getPropertySources();
				String name = "first";
				PropertySource propertySource = propertySources.get(name);
				if (null != propertySource) {
					propertySources.remove(name);
				}
				propertySources.addFirst(new MapPropertySource(name, props));
			}

			CollectionUtils.mergePropertiesIntoMap(nacosProps, allProperties);
		}
		allProps = allProperties;
		return allProperties;
	}

	
	private void configNacos(Properties allProperties) {
		if (StringUtils.isBlank(NACOS_SERVERADDR)) {
			return;
		}
		try {
			Properties properties = new Properties();
			properties.put(PropertyKeyConst.SERVER_ADDR, NACOS_SERVERADDR);
			properties.put(PropertyKeyConst.NAMESPACE, NACOS_NAMESPACE);
			configService = NacosFactory.createConfigService(properties);
			if (null == configService) {
				return;
			}
			String config = configService.getConfig(NACOS_DATA_ID, NACOS_GROUP, 5000);
			if (StringUtils.isBlank(config)) {
				return;
			}
			try {
				loadNacosProps(config);
			} catch (IOException e) {
				if (logger.isDebugEnabled()) {
					logger.error("加载nacos配置文件失败:{}", e.getMessage());
				}
			}
			// 添加监听
			configService.addListener(NACOS_DATA_ID, NACOS_GROUP, new Listener() {

				@Override
				public void receiveConfigInfo(String config) {

					logger.info("onReceived(String) : {}", config);
					try {
						loadNacosProps(config);
						mergeProperties();
					} catch (IOException e) {
						if (logger.isDebugEnabled()) {
							logger.error("已监听到最新nacos配置文件,但是加载失败:{}", e.getMessage());
						}
					}
					// 刷新下静态资源类
					AutowireCapableBeanFactory autowireCapableBeanFactory = ContextLoader.getCurrentWebApplicationContext().getAutowireCapableBeanFactory();
					Constant bean = autowireCapableBeanFactory.getBean(Constant.class);
					autowireCapableBeanFactory.autowireBean(bean);

					//清空BeanRefreshScope中所有bean的缓存
					BeanRefreshScope.clean();

				}

				@Override
				public Executor getExecutor() {
					return null;
				}
			});
		} catch (NacosException e) {
			e.printStackTrace();
		}
	}

	
	private void loadNacosProps(String config) throws IOException {
		if (null == nacosProps) {
			nacosProps = new Properties();
		}
		nacosProps.load(new StringReader(config));
	}

	
	protected String resolvePlaceholder(String placeholder, Properties props, int systemPropertiesMode) {
		String propVal = null;
		if (systemPropertiesMode == SYSTEM_PROPERTIES_MODE_OVERRIDE) {
			propVal = resolveSystemProperty(placeholder);
		}
		if (propVal == null) {
			propVal = resolvePlaceholder(placeholder, allProps);
		}
		if (propVal == null && systemPropertiesMode == SYSTEM_PROPERTIES_MODE_FALLBACK) {
			propVal = resolveSystemProperty(placeholder);
		}
		return propVal;
	}
}

spring-application.xml配置

	
		
			classpath:config.properties
		
	


    
        
            
        
    

config.properties
nacos.config.dataid=config.properties
nacos.config.group=DEFAULT_GROUP
nacos.config.namespace=
nacos.config.server-addr=127.0.0.1:8848

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1007925.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号