Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Objects;
Expand All @@ -42,7 +43,6 @@
@Slf4j
@ToString
public class Profile {
/** key */
String key;

Map<String, Object> map = new ConcurrentHashMap<>();
Expand Down Expand Up @@ -149,18 +149,20 @@ public void load(Properties properties) {
*/
public void load(List<URL> urls) {
// 需要加载的配置文件
urls.forEach(url -> {

try (InputStream inputStream = url.openStream()) {
Properties properties = new Properties();
properties.load(inputStream);

this.load(properties);

} catch (IOException e) {
log.error(e.getMessage(), e);
}
});
urls.forEach(this::load);
}

public void load(URL url) {
if (url == null) {
log.warn("加载配置失败:URL 为空");
return;
}
try (InputStreamReader reader = new InputStreamReader(url.openStream(), StandardCharsets.UTF_8)) {
Properties properties = new Properties();
properties.load(reader);
this.load(properties);
} catch (IOException e) {
log.error("读取配置文件异常 [{}]: {}", url, e.getMessage(), e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.core.convert.support.DefaultConversionService;

import java.net.URL;
import java.util.*;
Expand Down Expand Up @@ -48,7 +49,6 @@ public final class ProfileManager {
*/
private final Map<String, Profile> profileMap = new ConcurrentHashMap<>();


public Profile profile() {
return profile(MAIN_CONFIG);
}
Expand Down Expand Up @@ -115,5 +115,36 @@ public void loadMainProfile(String profileConfigName) {

}

/**
* 加载特定环境的配置文件
*
* @param env 环境名称
* @param fileName 配置文件名 (不需要带 .props 后缀)
*/
public Profile loadEnvFile(String env, String fileName) {
if (StringUtils.isEmpty(env) || StringUtils.isEmpty(fileName)) {
log.warn("环境或文件名为空,跳过加载");
return null;
}
URL fileURL = ResourcePatternResolverProfile.getFileURL(env, fileName);
Profile profile = profile(fileName);
profile.load(fileURL);
log.debug("配置内容 - size:{} - {}", profile.map.size(), profile.map);
return profile;
}

public void loadEnvFileFillStaticClass(String env, String fileName, Class<?> staticClass) {
if (StringUtils.isEmpty(env) || StringUtils.isEmpty(fileName)) {
log.warn("环境或文件名为空,跳过加载");
return;
}
Profile profile = loadEnvFile(env, fileName);
if (Objects.isNull(profile)) {
log.warn("加载配置文件失败,跳过加载");
return;
}
ProfileStaticBinder.bind(staticClass, profile.map);
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.iohao.game.widget.light.profile;

import org.springframework.core.convert.support.DefaultConversionService;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Map;

/**
* @Author: caochaojie
* @Date: 2026-01-2215:29
*/
public class ProfileStaticBinder {

// Spring 标准类型转换器:支持 String -> int/long/boolean/Enum/Array 等
private static final DefaultConversionService CONVERTER = new DefaultConversionService();

public static void bind(Class<?> targetClass, Map<?, ?> configMap) {
if (configMap == null || configMap.isEmpty()) {
return;
}

// 获取类中定义的全部字段
Field[] fields = targetClass.getDeclaredFields();

configMap.forEach((key, value) -> {
if (key == null || value == null) return;

String configKey = key.toString();
// 归一化处理:去掉下划线并转为小写
String normalizedConfigKey = normalize(configKey);

for (Field field : fields) {
int mod = field.getModifiers();

// 仅处理 public static 字段
if (Modifier.isPublic(mod) && Modifier.isStatic(mod)) {
String fieldName = field.getName();

// 匹配规则:原始名一致 OR 归一化后一致
if (fieldName.equalsIgnoreCase(configKey) || normalize(fieldName).equals(normalizedConfigKey)) {
try {
Object convertedValue = CONVERTER.convert(value, field.getType());
field.set(null, convertedValue);
} catch (Exception e) {
System.err.printf("[Config] 字段 [%s] 赋值失败: %s%n", fieldName, e.getMessage());
}
break; // 匹配到一个字段后跳出内层循环
}
}
}
});
}

/**
* 归一化处理:移除所有下划线并转为小写
* 例如: SERVER_ID -> serverid, serverId -> serverid, server_id -> serverid
*/
private static String normalize(String name) {
return name.replace("_", "").toLowerCase();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,25 @@
*/
@Slf4j
class ResourcePatternResolverProfile {
/** 默认主目录 */
/**
* 默认主目录
*/
@Setter
private static String rootDir = "conf";
/** 默认加载主目录-子目录 */
/**
* 默认加载主目录-子目录
*/
@Setter
private static String defaultDir = "common";
/** 默认加载指定后缀文件 */
/**
* 默认加载指定后缀文件
*/
@Setter
private static String suffix = ".props";

/** 需要加载的目录列表 */
/**
* 需要加载的目录列表
*/
private final LinkedList<String> dirNameList = new LinkedList<>();

/**
Expand All @@ -68,15 +76,11 @@ public List<URL> toUrls() {

List<URL> files = new LinkedList<>();

String locationPatternTemplate = "classpath*:%s/%s/*%s";
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

try {
for (String dir : dirNameList) {
String locationPattern = String.format(locationPatternTemplate, rootDir, dir, suffix);

Resource[] resources = resolver.getResources(locationPattern);
log.debug("locationPattern: {}", locationPattern);
Resource[] resources = getResourcesForDirectory(resolver, dir);
for (Resource resource : resources) {
URL url = resource.getURL();
files.add(url);
Expand All @@ -89,4 +93,42 @@ public List<URL> toUrls() {
return files;
}

public static URL getFileURL(String env, String fileName) {
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources;
try {
resources = getResourcesForDirectory(resolver, env);
} catch (IOException e) {
log.error("Error getting resources for directory: " + env, e);
return null;
}

for (Resource resource : resources) {
try {
URL url = resource.getURL();
if (url.getFile().contains(fileName)) {
return url;
}
} catch (IOException e) {
log.warn("Error getting URL for resource: " + resource.getDescription(), e);
// Continue to next resource
}
}
return null;
}

/**
* 获取指定目录下的资源
*
* @param resolver 资源解析器
* @param directory 目录名
* @return 资源数组
*/
private static Resource[] getResourcesForDirectory(PathMatchingResourcePatternResolver resolver, String directory) throws IOException {
String locationPatternTemplate = "classpath*:%s/%s/*%s";
String locationPattern = String.format(locationPatternTemplate, rootDir, directory, suffix);
log.debug("locationPattern: {}", locationPattern);
return resolver.getResources(locationPattern);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
package com.iohao.game.widget.light.profile;

import com.iohao.game.widget.light.profile.bean.DbProps;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

Expand All @@ -38,7 +39,17 @@ public void loadLocal() {

List<URL> urls = config.toUrls();
log.info("local profile {}", urls.size());
}

@Test
public void loadEnvFile() {
ProfileManager.loadEnvFile("local", "db.props");
}

@Test
public void loadEnvFileStaticBinder() {
ProfileManager.loadEnvFileFillStaticClass("local", "db.props", DbProps.class);
log.info("DbProps.jdbcUser = {}", DbProps.JDBC_USER);
log.info("DbProps.jdbcPwd = {}", DbProps.JDBC_PWD);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.iohao.game.widget.light.profile.bean;

/**
* @Author: caochaojie
* @Date: 2026-01-2215:31
*/
public class DbProps {
public static String JDBC_USER;
public static String JDBC_PWD;
}
Loading