继承PropertyPlaceholderConfigurer实现自定义解析占位符策略

spring提供的PropertyPlaceholderConfigurer都是根据指定的配置文件解析占位符,

在实际生产环境中,更常见的需求是从数据库中加载配置信息,根据加载的配置信息解析占位符。

本文将讨论如何继承PropertyPlaceholderConfigurer,实现自定义解析占位符的策略

继承Spring的PropertyPlaceholderConfigurer,重写方法,实现从数据库加载配置信息,目前就我所了解到的,有2种方法:

1、重写mergeProperties()方法

2、重写resolvePlaceHolder()方法

mergeProperties()方法的介绍-来自官网API

protected java.util.Properties mergeProperties()  throws java.io.IOException
Return a merged Properties instance containing both the loaded properties and properties set on this FactoryBean.

该方法扩充了获取properties的渠道。

resolvePlaceHolder()方法的介绍

protected java.lang.String resolvePlaceholder(java.lang.String placeholder,
                                                        java.util.Properties props)
Resolve the given placeholder using the given properties. The default implementation simply checks for a corresponding property key.
Subclasses can override this for customized placeholder-to-key mappings or custom resolution strategies, possibly just using the given properties as fallback.


Note that system properties will still be checked before respectively after this method is invoked, according to the system properties mode.


Parameters:
placeholder - the placeholder to resolve
props - the merged properties of this configurer
Returns:

the resolved value, of null if none

该方法扩充了解析占位符的方式。重写逻辑一般为,如果在merged properties中没有相应的属性供解析占位符,则使用自定义的从占位符到属性值的映射。

原英文译文为:使用给定的属性解析给定的占位符。 默认实现只是检查相应的属性键。
子类可以覆盖此自定义占位符到键映射或自定义解析策略,可能只是使用给定属性作为后备。

请注意,根据系统属性模式,在调用此方法之后,系统属性仍将分别进行检查。


两种方式大同小异,第一种方法是先将自定义的从占位符到属性值的映射加入merged properties

第二种方法是在解析占位符时,再使用自定义的从占位符到属性值的映射

第一种方法实现转载自以下博文:

重写Spring的PropertyPlaceholderConfigurer,从数据库加载配置数据    

1,applicationContext.xml

用自定义扩展类DataBasePropertyPlaceholderConfigurer替换Spring的PropertyPlaceholderConfigurer

<!-- 从数据库配置表加载系统配置属性 -->
<bean id="dataBasePropertyConfigurer" class="com.crc.util.DataBasePropertyPlaceholderConfigurer">
</bean>

2,DataBasePropertyPlaceholderConfigurer.java

[java]  view plain  copy
  1. package com.crc.util;  
  2.   
  3. import java.util.Properties;  
  4. import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;  
  5.   
  6. public class DataBasePropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer  
  7. {  
  8.     @Override  
  9.     public Properties mergeProperties()   
  10.     {  
  11.         return ConfigPropertiesUtil.getProperties();  
  12.     }  
  13.       
  14. }  

3,ConfigPropertiesUtil.java,从数据库读取配置数据的工具类

[java]  view plain  copy
  1. package com.crc.util;  
  2. import java.sql.Connection;  
  3. import java.sql.PreparedStatement;  
  4. import java.sql.ResultSet;  
  5. import java.sql.SQLException;  
  6. import java.util.Properties;  
  7. import java.util.concurrent.locks.ReentrantReadWriteLock;  
  8. import javax.naming.Context;  
  9. import javax.naming.InitialContext;  
  10. import javax.naming.NamingException;  
  11. import javax.sql.DataSource;  
  12. import org.slf4j.Logger;  
  13. import org.slf4j.LoggerFactory;  
  14.   
  15.   
  16. public class ConfigPropertiesUtil  
  17. {  
  18.     private static final String JNDI_PREFIX = "java:comp/env/";  
  19.     private static final String JNDI_NAME = "jdbc/reimburse";  
  20.       
  21.     private static Properties properties = null;  
  22.       
  23.     private static final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();  
  24.   
  25.     private static final String queryString = "select t.property_key, t.property_value from appmgr.t_config_properties t";  
  26.   
  27.     private static final Logger logger = LoggerFactory.getLogger(ConfigPropertiesUtil.class);  
  28.       
  29.       
  30.     private ConfigPropertiesUtil() {  
  31.           
  32.     }  
  33.       
  34.       
  35.     public static String getValueByKey(String key)  
  36.     {  
  37.         if(key == null || "".equals(key.trim()))  
  38.         {  
  39.             return "";  
  40.         }  
  41.           
  42.         loadProperties();  
  43.           
  44.         return properties.get(key) == null ? "" : properties.get(key).toString();  
  45.     }  
  46.       
  47.       
  48.     public static Properties getProperties()  
  49.     {  
  50.         loadProperties();  
  51.         return properties;  
  52.     }  
  53.       
  54.       
  55.     private static void loadProperties()  
  56.     {  
  57.         readWriteLock.readLock().lock();  
  58.           
  59.         if(properties == null)  
  60.         {  
  61.             readWriteLock.readLock().unlock();  
  62.             readWriteLock.writeLock().lock();  
  63.               
  64.             if(properties == null)  
  65.             {  
  66.                 properties = new Properties();  
  67.                   
  68.                 DataSource dataSource = null;  
  69.                 Connection connection = null;  
  70.                 PreparedStatement statement = null;  
  71.                 ResultSet resultSet = null;  
  72.                   
  73.                 Context context = null;  
  74.                 try  
  75.                 {  
  76.                     context = new InitialContext();  
  77.                 }  
  78.                 catch(NamingException e3)  
  79.                 {  
  80.                     logger.error("初始化JNDI上下文出错(加载系统配置数据):", e3);  
  81.                     readWriteLock.writeLock().unlock();  
  82.                     return;  
  83.                 }  
  84.                   
  85.                 try  
  86.                 {  
  87.                     dataSource = (DataSource)(context.lookup(JNDI_NAME));  
  88.                 }  
  89.                 catch(NamingException e1)  
  90.                 {  
  91.                     try  
  92.                     {  
  93.                         dataSource = (DataSource)(context.lookup(JNDI_PREFIX + JNDI_NAME));  
  94.                     }  
  95.                     catch(NamingException e2)  
  96.                     {  
  97.                         logger.error("获取JNDI数据源出错(加载系统配置数据):", e2);  
  98.                         readWriteLock.writeLock().unlock();  
  99.                         return;  
  100.                     }  
  101.                 }  
  102.                   
  103.                 try  
  104.                 {  
  105.                     connection = dataSource.getConnection();  
  106.                     statement = connection.prepareStatement(queryString);  
  107.                     resultSet = statement.executeQuery();  
  108.                       
  109.                     while(resultSet.next())  
  110.                     {  
  111.                         properties.setProperty(resultSet.getString(1), resultSet.getString(2) == null ? "" : resultSet.getString(2).trim());  
  112.                     }  
  113.                       
  114.                     logger.info("==========================加载配置数据开始============================");  
  115.                     logger.info(properties.toString());  
  116.                     logger.info("==========================加载配置数据结束============================");  
  117.                 }  
  118.                 catch(Exception e)  
  119.                 {  
  120.                     logger.error("加载系统配置数据出错:", e);  
  121.                 }  
  122.                 finally  
  123.                 {  
  124.                     if(resultSet != null)  
  125.                     {  
  126.                         try  
  127.                         {  
  128.                             resultSet.close();  
  129.                         }  
  130.                         catch(SQLException e)  
  131.                         {  
  132.                             e.printStackTrace();  
  133.                         }  
  134.                     }  
  135.                     if(statement != null)  
  136.                     {  
  137.                         try  
  138.                         {  
  139.                             statement.close();  
  140.                         }  
  141.                         catch(SQLException e)  
  142.                         {  
  143.                             e.printStackTrace();  
  144.                         }  
  145.                     }  
  146.                     if(connection != null)  
  147.                     {  
  148.                         try  
  149.                         {  
  150.                             connection.close();  
  151.                         }  
  152.                         catch(SQLException e)  
  153.                         {  
  154.                             e.printStackTrace();  
  155.                         }  
  156.                     }  
  157.                 }  
  158.             }  
  159.               
  160.             readWriteLock.readLock().lock();  
  161.             readWriteLock.writeLock().unlock();  
  162.         }  
  163.           
  164.         readWriteLock.readLock().unlock();  
  165.     }  
  166.   
  167. }  

第二种方法实现:

import java.util.ArrayList;
import java.util.List;

/**
 * 
 */

import java.util.Map;
import java.util.Properties;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;

import com.service.configuration.ConfigListenerSvc;
import com.service.configuration.constants.ConfigurationConstants;
import com.service.configuration.utils.DecryptUtil;
import com.service.configuration.utils.HttpClientConnectionManager;

import lombok.extern.slf4j.Slf4j;

/**
 * @project configuration
 * @description 重写PropertyPlaceholderConfigurer的resolvePlaceholder方法,
 *              当从指定的Properties文件中读取不到配置项时,尝试从配置中心读取所有配置信息。
 * @copyright Copyright (c) 2016 foresee
 * @company foresee
 * @author Tim
 * @version 1.0
 * @history 修订历史(历次修订内容、修订人、修订时间等)
 *
 */
@Slf4j
public class DatabasePropertyPlaceholder extends PropertyPlaceholderConfigurer {
	
	private static Map<String, String> dbPropertyValues = null;

	public DatabasePropertyPlaceholder() {
		String delay = getDbProperty("conf.refresh.delay");
		int de = 60;
		if (delay == null) {
			log.info("配置中心没有设置conf.refresh.delay参数,使用默认值:60。");
		} else {
			de = Integer.parseInt(delay);
		}
		// 每分钟执行一次刷新配置缓存
		Timer timer = new Timer();
		timer.schedule(new MyTask(), de * 1000, de * 1000);
	}

	/**
	 * 从配置中心获取配置项
	 * 
	 * @param placeholder
	 * @return
	 */
	public static String getDbProperty(String placeholder) {
		String value = null;
		if (dbPropertyValues == null) {
			dbPropertyValues = getDbPropertyValuesFromConfCenter();
		}
		if (dbPropertyValues != null) {
			value = dbPropertyValues.get(placeholder);
		}
		return value;
	}

	public static List<String> getDbPropertyLst(String placeholder) {
		List<String> valuelst = new ArrayList<String>();
		if (dbPropertyValues == null) {
			dbPropertyValues = getDbPropertyValuesFromConfCenter();
		}
		if (dbPropertyValues != null) {
			for (Map.Entry<String, String> entry : dbPropertyValues.entrySet()) {
				// dbPropertyValues.set(entry.getKey(), entry.getValue());
				if (entry.getKey().startsWith(placeholder)) {
					valuelst.add(entry.getValue());
				}
			}
			// value = dbPropertyValues.get(placeholder);
		}
		return valuelst;

	}

	@Override
	protected String resolvePlaceholder(String placeholder, Properties props) {
		String value = props.getProperty(placeholder);
		if (value == null) {
			value = getDbProperty (placeholder);
		}
		return value;
	}

	/**
	 * 从配置中心读取配置表
	 * 
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private static Map<String, String> getDbPropertyValuesFromConfCenter() {
		String confCenterAddr = System.getProperty("confCenterAddr");
		if (confCenterAddr == null) {
			confCenterAddr = "http://localhost:6789/confCenter/conf";
		}
		String confTable = System.getProperty("confTable");
		// 请求配置中心获取配置表信息,然后载入dbPropertyValues中
		String url = confCenterAddr + (confTable == null ? "" : "?confTable=" + confTable);
		HttpGet get = HttpClientConnectionManager.getGetMethod(url);
		HttpResponse response = null;
		try {
			log.info("准备请求配置中心获取配置文件,配置表为:"
					+ (confTable == null ? ConfigurationConstants.DEFAULT_CONFIGURATION_TABLENAME : confTable));
			response = HttpClientConnectionManager.createHttpClient().execute(get);
			String jsonStr = EntityUtils.toString(response.getEntity(), "utf-8");
			Map<String, String> values = new ObjectMapper().readValue(jsonStr, Map.class);
			// 开始解密
			log.info("对配置表"+(confTable == null ? ConfigurationConstants.DEFAULT_CONFIGURATION_TABLENAME : confTable)+"进行解密...");
			
			values =DecryptUtil.doDecryptMap(values);
			log.info("读取配置表" + (confTable == null ? ConfigurationConstants.DEFAULT_CONFIGURATION_TABLENAME : confTable)
					+ "成功!");
			return values;
		} catch (Exception e) {
			e.printStackTrace();
			log.debug("请求配置中心获取配置信息失败!", e);
		}
		return null;
	}

	/**
	 * 刷新配置中心缓存
	 * 
	 * @project configuration
	 * @copyright Copyright (c) 2016 foresee
	 * @company foresee
	 * @author Tim
	 * @version 1.0
	 * @history 修订历史(历次修订内容、修订人、修订时间等)
	 */
	class MyTask extends TimerTask {
		public void run() {
			Map<String, String> values = getDbPropertyValuesFromConfCenter();
			if (values != null) {
				dbPropertyValues = values;
			}
			// 执行监听配置中心
			ConfigListenerSvc.getInstance().excute();
		}
	}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值